计算几何摸黑(2)-点和直线

来源:互联网 发布:怎么才能看到淘宝直播 编辑:程序博客网 时间:2024/05/22 00:31

相等判断函数

有的时候我们会用到判断一个数是否大于0,小于0或等于0。大于小于还好办,等于的话可能会出现例如0.00000000001≠0的现象,但是实际计算的时候这两个数是应该按照相等来算的。所以,我们可以自己定义一个函数dcmp(),来判断是否和0极其近似相等。

int dcmp(const double x){    const double eps = 1e-10;    if (std::fabs(x) < eps)        return 0;    else        return x < 0 ? -1 : 1;}

直线的参数表示

参数式:

P=P0+tv

这个式子的意思就是直线上的所有点的坐标都可以表示成P0+tv的格式,其中v叫做直线的方向向量,P0可以用来表示这条直线的起点,t叫做参数。

直线的交点

如果可以确保直线P+tvQ+tw有唯一交点,且v⃗ w⃗ 非零时,如果用t1表示该点与P的距离,用t2表示该点与Q的距离,易证

t1=w⃗ ×u⃗ v⃗ ×w⃗ ,t2=v⃗ ×u⃗ v⃗ ×w⃗ 

实现如下:

// 这里是用了上述的t1的思路,用交点和P的交点距离求交点Point getLineInter(Point P, Vector v, Point Q, Vector w) // P + tv和Q + tw的……两点式……{    Vector u = P - Q;    double t = mulCross(w, u) / mulCross(v, w);    return P + v * t;}

点到直线的距离

点到直线的距离,很简单,就是叉乘乘出来的那个平行四边形的面积除以它的底。

double getDisPointToLine(Point p, Point a, Point b){    Vector v1 = b - a, v2 = p - a;    return std::fabs(mulCross(v1, v2) / v1.getNorm()); // 如果不加std::fabs,得到的将是有向长度}

点到线段的距离

点到线段的距离一共有三种情况,设投影点为Q,则有Q在线段AB上①,Q在线段AB的延长线上②,Q在线段AB的反向延长线上③。

对于①:所求的就是点 P到直线AB的距离。

对于②:所求的就是向量 PB的模。

对于③:所求的就是向量 PA的模。

至于Q的位置在哪里,可以用向量的点乘判断。

double getDisPointToSeg(Point P, Point a, Point b){    if (a == b)        return (P - a).getNorm();    Vector v1 = b - a, v2 = p - a, v3 = p - b;    if (dcmp(mulDot(v1, v2)) < 0)        return v2.getNorm();    else if (dcmp(mulDot(v1, v3)) > 0)        return v3.getNorm();    else        return std::fabs(mulCross(v1, v2) / v1.getNorm());}

点与线段的位置关系

一个点和一条线段无非就是两种关系,要么相交,要么相离。如果相交的话就相当于线段的两端点与该点所组成向量共线,且互相组成的两条向量方向相反。所以根据这两个性质,很容易想到需满足的性质为:点乘 < 0,且叉乘 == 0。为了避免精度错误,我这里用dcmp()来判断是否为0。

bool onSeg(Point P, Point hajimari, Point owari){    return         dcmp( mulCross(hajimari - P, owari - P) ) == 0 &&        dcmp( mulDot(hajimari - P, owari - P ) ) < 0;}

线段相交判定

这里的线段相交,是指“规范相交”,即不算在端点处相交的情况。两线段相交的条件很好理解:每条线段的两个端点都在另一条线段的两侧。也就是说,一条线段两侧的端点所组成的向量分别和另一条线段自己构成的向量的叉乘符号相反。

bool isSegInter(Point a1, Point a2, Point b1, Point b2){    double c1 = mulCross(a2 - a1, b1 - a1),           c2 = mulCross(a2 - a1, b2 - a1),           c3 = mulCross(b2 - b1, a1 - b1),           c4 = mulCross(b2 - b1, a2 - b1);    return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;}

点在直线上的投影

既然是点在直线上的投影,那么我们可以把直线AB通过参数式表示成A+tv的形式,如果设P的投影点在AB上为Q,并且设Q的坐标为A+t0v,那么根据PQAB,不难推出两个向量点乘 == 0。因此,v⃗ [P(A+t0v⃗ )]=0,根据分配率,可以推出:v⃗ (PA)t0×(v⃗ 2)=0,这样就可以解出t0,从而得到Q

Point getLineProj(Point P, Point a, Point b){    Vector v = B - A;    return A + v * (mulDot(v, P - a) / mulDot(v, v));}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 水管被水垢堵了怎么办 花洒喷头堵了怎么办 花洒分水器堵了怎么办 冲马桶水溅出来怎么办 吃了不熟的芋头怎么办 吃多了肚子胀气怎么办 吃多了胃胀气怎么办 红薯吃多了胀气怎么办 裙子贴在腿上怎么办 薄裤子静电吸腿怎么办 雪纺衬衫起静电怎么办 吃烤饼不松软是怎么办 1岁宝宝睡眠不好怎么办 3岁幼儿睡眠不好怎么办 2岁幼儿睡眠不好怎么办 2岁宝宝睡眠不好怎么办 9岁儿童睡眠不好怎么办 3岁宝宝老踢被子怎么办 4岁宝宝老踢被子怎么办 四线锁边机跳线怎么办 引流管伤口洞红怎么办 甘蔗卡在喉咙里怎么办 棉花被子生虫了怎么办 绗缝羽绒服钻毛怎么办 宝珠笔没墨水了怎么办 衣服上画的笔印怎么办 黑笔芯弄衣服上怎么办 圆珠笔油在皮上怎么办 不小心吞了水银怎么办 小孩吃了洗发露怎么办? 脸上被铅笔戳了怎么办 小孩吃了铅笔芯怎么办 小孩把橡皮吃了怎么办 用棉签掏耳朵里面疼怎么办 棉签头掉耳朵里怎么办 黑裤子老是粘毛怎么办 新买的裤子掉色怎么办 黑裤子容易粘毛怎么办 裤子粘了全部毛怎么办 纯棉裤子粘毛了怎么办 裤子粘毛怎么办怎么洗