计算几何

?快速排斥实验&跨立实验

?点击打开链接

?点击打开链接

计算几何

基础

向量叉乘

A (x1,y1)  B(x2,y2)  A×B= x1y2-x2y1

叉乘判断向量位置,

P×Q < 0  P在 Q 左侧,

P×Q > 0  P在 Q 右侧,

P×Q > 0  P与 Q 共线,

向量点乘

A (x1,y1)  B(x2,y2)  A·B=x1x2+y1y2    a*b=|a||b|cos0

凸包

Jarvis步进法: O(nH)

(点少时,H是点个数) 建议 用Graham

思路:

纵坐标最小的那个点一定是凸包上的点,例如图上的 P0

P0 开始,按逆时针的方向,逐个找凸包上的点,每前进一步找到一个点,所以叫作步进法。

怎么找下一个点呢?利用夹角。假设现在已经找到 {P0P1P2} 了,要找下一个点:剩下的点分别和 P2 组成向量,设这个向量与向量P1P2的夹角为 β 。当 β 最小时就是所要求的下一个点了,此处为 P3

 

注意:

找第二个点 P1 时,因为已经找到的只有 P0 一个点,所以向量只能和水平线作夹角 α,当 α 最小时求得第二个点。

共线情况:如果直线 P2P3 上还有一个点 P4,即三个点共线,此时由向量P2P3 和向量P2P4 产生的两个 β 是相同的。我们应该把 P3P4 都当做凸包上的点,并且把距离 P2 最远的那个点(即图中的P4)作为最后搜索到的点,继续找它的下一个连接点。

 

Graham法: O(n㏒n) 

时间复杂度:O(nn) 
思路:Graham扫描的思想和Jarris步进法类似,也是先找到凸包上的一个点,然后从那个点开始按逆时针方向逐个找凸包上的点,但它不是利用夹角。 
 
步骤:

把所有点放在二维坐标系中,则纵坐标最小的点一定是凸包上的点,如图中的P0

把所有点的坐标平移一下,使 P0 作为原点,如上图。

计算各个点相对于 P0 的幅角 α ,按从小到大的顺序对各个点排序。当 α 相同时,距离 P0 比较近的排在前面。例如上图得到的结果为 P1P2P3P4P5P6P7P8。我们由几何知识可以知道,结果中第一个点 P1 和最后一个点 P8 一定是凸包上的点。 
(以上是准备步骤,以下开始求凸包) 
以上,我们已经知道了凸包上的第一个点 P0 和第二个点 P1,我们把它们放在栈里面。现在从步骤3求得的那个结果里,把 P1 后面的那个点拿出来做当前点,即 P2 。接下来开始找第三个点:

连接P0和栈顶的那个点,得到直线 L 。看当前点是在直线 L 的右边还是左边。如果在直线的右边就执行步骤5;如果在直线上,或者在直线的左边就执行步骤6

如果在右边,则栈顶的那个元素不是凸包上的点,把栈顶元素出栈。执行步骤4

当前点是凸包上的点,把它压入栈,执行步骤7

检查当前的点 P2 是不是步骤3那个结果的最后一个元素。是最后一个元素的话就结束。如果不是的话就把 P2 后面那个点做当前点,返回步骤4

最后,栈中的元素就是凸包上的点了。 
以下为用Graham扫描法动态求解的过程: 

 

 

应用

规则图形

判断点在线段上

点Q(x,y),线段P1P2 (x2-x1,y2-y1) 则向量共线   P1Q×P1P2 =0  (x(y2-y1)-(x2-x1)y)= 0

并且 min(x1,x2) <=x<=max(x1,x2)&&min(y1,y2)<=y<=max(y1,y2)// 在线段内部

判断两线段相交
快速排斥实验

§ 两个线段为对角线组成的矩形R和矩形T 若R,T不想交-->不想交,若相交进行跨立实验判断

§ 方法:  假设 P1 = (x1, y1), P2 = (x2, y2), Q1 = (x3, y3), Q2 = (x4, y4),设矩形 R x 坐标的最小边界为 RX1 = min(x1, x2)RX2=max(x1,x2) ,RY1=min(y1,y2)以此类推,将矩形表示为 R = (RX1, RY1, RX2, RY2) 的形式,若两矩形相交,则相交的部分构成了一个新的矩形 F,我们可以知道 F FX1 = max(RX1, TX1), FY2 = max(RY1, TY1),

§ FX2 = min(RX2, TX2), FY2 = min(RY2, TX2),得到 F 的各个值之后,只要判断矩形 F 是否成立就知道 R T 到底有没有相交了,若 FX1 > FX2 FY1 > Fy1 F 无法构成,RT不相交,否则 RT相交

§ 

跨立实验(互相跨立)

§ 

§      Q1P1×Q1P2 * Q1Q2×Q1Q1P2 >=0 && Q1P2×P1P2 * P1P2×Q2P2 >=0

线段与圆相交

 

三种情况, 第一种, 两个端点都在圆内,不相交,第二种,一个在圆外,一个圆内 一定相交;

第三种都在圆外,需要判断;

double x,y,r;

vector<pair<double,double> > V;

typedef pair<double,double> PAIR;

PAIR yuan;

bool judge(PAIR P)// 判断是否在圆内

{

    if( (P.first-x)*(P.first-x) + (P.second-y)*(P.second-y) -r*r <=0)

        return 1;

    return 0;

}

bool Judis(PAIR P1,PAIR P2,double R) //线段与圆的关系

{

 

    if(judge(P1)&&judge(P2))//都在圆内 不相交

        return false;

    if(!judge(P1)&&judge(P2)||judge(P1)&&!judge(P2))//一个圆内一个圆外 相交

        return true;

    double A,B,C,dist1,dist2,angle1,angle2;//Ax+By+C=0;//(y1-y2)x +(x2-x1)y +x1y2-y1x2=0

    if(P1.first==P2.first)

        A=1,B=0,C= -P1.first;

    else if(P1.second==P2.second)

        A=0,B=1,C= -P1.second;

    else

    {

        A = P1.second-P2.second;

        B = P2.first-P1.first;

        C = P1.first*P2.second - P1.second*P2.first;

    }

    dist1 = A * yuan.first + B * yuan.second + C;

    dist1 *= dist1;

    dist2 = (A * A + B * B) * R * R;

    if (dist1 > dist2) return false;//点到直线距离大于半径r  不相交

    angle1 = (yuan.first - P1.first) * (P2.first - P1.first) + (yuan.second - P1.second) * (P2.second - P1.second);

    angle2 = (yuan.first - P2.first) * (P1.first - P2.first) + (yuan.second - P2.second) * (P1.second - P2.second);

    if (angle1 > 0 && angle2 > 0) return true;//余弦都为正,则是锐角 相交

    return false;//不相交

}

 

判断线段和直线相交

化成线段相交

判断点在矩形内

点在矩形对角线坐标内

判断线段/折现/多边形在矩形内

转换为所有点在矩形内

判断矩形在矩形内

上下界问题

判断圆在矩形内

圆心在矩形内

圆的半径R小于min(圆心到四个边距离d)

不规则图形

判断点在多边形

多边形问题,射线法

 



 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值