×ac就是 延伸出去的平行四边形的面积
S△abc=2ab×ac;判断大小关系的时候不用除以2 直接判断即可 且更加精确
线段相交
判断两线段是否相交
判断两个线段是否相交,要先想一下两条线段之间都有什么样的位置关系。
1.相离
2.相交
3.重合
4.平行
观察了上面4个图片 可以明显的观察到 相交与其他3种的不同
一条线段的两个端点分别在另一条线段的两边
了解了这些加上叉乘就可以进行计算了
Ps:如果不了解叉乘的话必须先了解下叉乘,但我相信能做到求线段相交的人一定对叉乘有了全方位的了解
首先我们知道如果两个点在在一条线段两侧 那么对于线段两端与这两个点分别做叉乘计算取得的积一定是小于0的
可以得到以下结论
(CD×DA)⋅(CD×DB)<0;
(AB×BD)⋅(AB×BC)<0;
其实想也很好想
如果两个线段不想交那么势必存在一条线段的两个端点在另一条线段同侧,上述式子就不能满足。
所以通过计算上述式子也就能知道两线段是不是相交了。
但是在实际计算中如果数据量非常大的话那么我们总是计算4遍叉乘的话会很麻烦
所以要考虑更简单的判断两条线不相交的办法来排除一些情况,当然也只能排除一些情况而已,但即使这样也能使整个程序运行的快一些。
我们可以通过判断这两条线段的四个点的关系来淘汰很多点:
(这部分证明并没有什么意义,大家想想即可明白,在此就不赘述了,支架以代码形式给出)
max(s1.x,e1.x) < min(s2.x,e2.x)
max(s2.x,e2.x) < min(s1.x,e1.x)
max(s1.y,e1.y) < min(s2.y,e2.y)
max(s2.y,e2.y) < min(s1.y,e1.y)
这4中情况都是不相交的
======
上述已经介绍了如何判断线段相交,该上代码了
1 2 3 4 5 6 7 8 9 10 11 12
| double multi(Point p1,Point p2,Point p0){ return ((p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x)); }
bool IsIntersected(Point s1,Point e1,Point s2,Point e2) { //两个线段相交 return(max(s1.x,e1.x)>=min(s2.x,e2.x))&& (max(s2.x,e2.x)>=min(s1.x,e1.x))&& (max(s1.y,e1.y)>=min(s2.y,e2.y))&& (max(s2.y,e2.y)>=min(s1.y,e1.y))&& (multi(s1,s2,e1)*multi(s1,e2,e1)<=0)&& (multi(s2,s1,e2)*multi(s2,e1,e2)<=0); }
|
求两圆相交面积
两个圆的位置一共有五种情况
1.内含 2.内切 3.相交 4.外切 5.外离
在计算几何中 内含与内切 可以当做同一种情况 外切与外离 可以当做同一种情况
Ps:如果有疑问可以自己画一画图 就会明白了
所以在计算几何中只要分成3种情况就行了
先定义 d为两圆圆心距离
1.外离
外离
这种情况下d>=r1+r2
两圆间没有相交的部分
所以相交面积是0
2.内含
内含
这种情况下 大圆把小圆全部覆盖
相交的面积就是校园的面积 PI * r1 * r1
此情况下 d<=r大-r小
写成代码就是d <= fabs(r1 - r2)
3.相交
相交
相交的部分可以分成 大小两个圆上弧ab与直线ab围成的图形
即可看作
S扇形abc1-S△abc1+S扇形abc2-S△abc2<=>
S扇形abc1+S扇形abc2-S□ac1bc2;
根据中学学的扇形的面积公式可以推到如下
ang1=acos(2.0∗r1∗dr1∗r1+d∗d−r2∗r2)
$ang2 = acos(\dfrac{r2 * r2 + d * d - r1 * r1}{2.0r2d})S扇形_{abc1}=ang1 * r1 * r1S扇形_{abc2}=ang2 * r2 * r2S□ac1bc2=d * r1 * sin(ang1)$
S=ang1∗r1∗r1+ang2∗r2∗r2−d∗r1∗sin(ang1);
======
上述已经介绍了如何计算两圆相交面积,该上代码了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| double solve(Round a, Round b) { double d = dis(a, b); if (d >= a.r + b.r) return 0; if (d <= fabs(a.r - b.r)) { double r = a.r < b.r ? a.r : b.r; return PI * r * r; } double ang1 = acos((a.r * a.r + d * d - b.r * b.r) / 2. / a.r / d); double ang2 = acos((b.r * b.r + d * d - a.r * a.r) / 2. / b.r / d); double ret = ang1 * a.r * a.r + ang2 * b.r * b.r - d * a.r * sin(ang1); return ret; }
|
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 tabris的博客! 赞助
wechat
alipay