计算几何学习笔记之基本运算

模板在网上很容易找到,这里我就讲一讲我对这些代码(lrj白皮书上的)的理解,包括添加证明,插图等。
定义向量及向量的四则运算,其中A,B都是一个向量。(貌似是高中数学课本上的内容)

struct poi
{
    double x,y;
    poi(double x=0,double y=0) :x(x),y(y){}
}
typedef poi vec;//定义一个poi的别名只是为了更方理解代码,一个表示点,一个表示向量
vec operator +(vec A,vec B) {return vec(A.x+B.x, A.y+B.y);}
vec operator -(vec A,vec B) {return vec(A.x-B.x, A.y-B.y);}
vec operator *(vec A,double p) {return vec(A.x*p, A.y*p);}
vec operator /(vec A,double p) {return vec(A.x/p, A.y/p);}

再来说说向量的比较函数
为什么要定义一个比较函数?就用==不好吗?由于在计算几何的计算中,参与运算的大多数都是浮点数,会产生误差,定义dcmp减少了精度问题

const double eps = 1e-9;
int dcmp(double x)
{if(fabs(x) < eps) return 0; else return x>0?1:-1;}
bool operator <(vec A,vec B) 
{if(A.x == B.x) return A.y < B.y; else return A.x < B.x;}
bool operator ==(vec A,vec B)
{return dcmp(A.x-B.x) == 0&&dcmp(A.y-B.y) == 0;}

基本运算包括求向量的点积(点乘),叉积(叉乘)和求向量的夹角,向量的模长。貌似在高中教材中没有提到叉积这一概念。
点积(dot): a⃗ b⃗ =|a⃗ ||b⃗ |cos<a⃗ ,b⃗ >|a⃗ |,|b⃗ |,cos<a⃗ ,b⃗ > 分别是向量的模长,夹角的余弦值。
叉积(cross): a⃗ b⃗ =|a⃗ ||b⃗ |sin<a⃗ ,b⃗ > 。几何意义为平移 a⃗ ,b⃗  得到的平行四边形面积,可由正弦公式推导而来。注意叉积有正负,不满足交换律,简单的判断方式:把向量a顺时针旋转到向量b,若角度小于 π 就为正,否则为负。
求夹角,其实就是把点积公式倒过来使用。 <a⃗ ,b⃗ >=arccos(a⃗ b⃗ |a⃗ ||b⃗ |) <script type="math/tex" id="MathJax-Element-5"><\vec a,\vec b> = arccos(\frac {\vec a \cdot \vec b}{|\vec a||\vec b|})</script>。

double dot(vec A,vec B) {return A.x*B.x + A.y*B.y;}
double cross(vec A,vec B) {return A.x*B.y - A.y*B.x;}
double length(vec A) {return sqrt(dot(A,A));}
double angle(vec A,vec B) {return acos(dot(A,B) /length(A) /length(B));}

强行解释一下cross那个公式怎么来的
这里写图片描述
直线OA: yAxxAy=0
那么由距离公式
d=|yAxBxAyB|x2A+y2Asinθ=|yAxBxAyB|x2A+y2Ax2B+y2BSabc=12|yAxBxAyB|
旋转任意角,求单位法向量(旋转90度)公式

vec rotate(vec A,double rad) {return vec(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));}
vec normal(vec A) {double L = length(A); return vec(-A.y/L,A.x/L);}

旋转公式推导
这里写图片描述
原来的向量设为 (x0,y0) ,倾斜角为 φ ,转角为 α ,那么有
x0=x20+y20cosφ,y0=x20+y20sinφ
旋转之后的向量 (x,y)
则有 x=x20+y20cos(α+φ),y=x20+y20sin(α+φ)
展开得到
x=x20+y20cosφcosαx20+y20sinφsinα=x0cosαy0sinα
y=x20+y20sinφcosα+x20+y20cosφsinα=y0cosα+x0sinα

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值