计算几何--简单多边形与圆面积交

求解二维空间内一个简单多边形和一个长度为R的圆公共面积。

因为任意简单多边形都可以划分成若干三角形,我们可以把这个简单多边形划分成三角形后,求三角形与圆的面积交,然后在把所有三角形的解合并。

由于可能有凹多边形,我们计算三角形与圆面积交时采用向量叉乘,这样得到的是一个有向面积,刚好可以把凹多边形面积正负抵消掉,最后把总面积取绝对值就行了。

向量叉乘 A x B == 以向量A,B为2邻边,围城平行四边形的有向面积。  A在B顺时针方向值为正,逆时针为负。

AxB==

|A.x  ,  A.y |

|B.x  ,  B.y |

==A.x*B.y-A.y*B.x

 

计算一个圆与一个三角形的面积交(其中一个三角形顶点是圆心,如上图),我采用的方法是分4种情况。

 

1.

另外2个顶点在圆内(上),这个非常好算直接求三角形的有向面积即可。

2.

另外两个顶点有1个再圆内(上),另外1个再圆外,求得直线与圆一个交点后求一个三角形面积+上一个扇形面积。

3.

2个顶点在圆外,且2个顶点所在边与圆相交,先求圆外2顶点所在直线与圆交点,然后定比分点公式求另外2条直线与圆交点,然后求一个三角形+2个扇形面积即可。

 

4.

2个顶点都在圆外且2顶点所在边与圆不相交,这个情况求2个交点后算出那个扇形面积就行了。

 

下面是我写的圆与三角形有向面积交函数,注意三角形其中一个顶点在圆心,如果都不在圆心,可以把这个三角形在划分成3个其中一个顶点在圆心的三角形求解。

代码:

/*
* 多边形和圆面积并
* Complier: G++
* Create Time: 8:26 2015/10/1 星期四
*/
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;

const double pi=acos(-1.0);
const double e=exp(1.0);
const double eps=1e-8;
const int maxn=1005;
double R,k;
int n,m;
struct point          // 点或向量结构
{
    double x,y;
    point(double _x=0.0,double _y=0.0):x(_x),y(_y) {}
    point operator - (const point &p)
    {
        return point(x-p.x,y-p.y);
    }
    double sqrx()    //向量的模
    {
        return sqrt(x*x+y*y);
    }
} area[maxn];

int dcmp(double x)
{
    return (x>eps)-(x<-eps);
}

double xmult(point &p1,point &p2,point &p0)//叉积
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}

double distancex(point &p1,point &p2)
{
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}

point intersection(point u1,point u2,point v1,point v2)   //两直线交点
{
    point ret = u1;
    double t = ((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))/((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
    ret.x += (u2.x-u1.x)*t;
    ret.y += (u2.y-u1.y)*t;
    return ret;
}

void intersection_line_circle(point c, double r, point l1, point l2, point & p1, point & p2) //直线与圆相交
{
    point p = c;
    double t;
    p.x += l1.y-l2.y;
    p.y += l2.x-l1.x;
    p = intersection(p, c, l1, l2);
    t = sqrt(r*r-distancex(p, c)*distancex(p, c))/distancex(l1, l2);
    p1.x = p.x+(l2.x-l1.x)*t;
    p1.y = p.y+(l2.y-l1.y)*t;
    p2.x = p.x-(l2.x-l1.x)*t;
    p2.y = p.y-(l2.y-l1.y)*t;
}

point len_pot_seg(point p, point l1, point l2)//点到线段的最近距离
{
    point t = p;
    t.x += l1.y-l2.y;
    t.y += l2.x-l1.x;
    if (xmult(l1, t, p)*xmult(l2, t, p)>eps)
        return distancex(p, l1)<distancex(p, l2) ? l1 : l2;
    return intersection(p, t, l1, l2);
}

double distp(point & a, point & b)
{
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}

double Direct_Triangle_Circle_Area(point a, point b, point o, double r)
{
    double sign = 1.0;
    a = a-o;
    b = b-o;
    o = point(0.0, 0.0);
    if(fabs(xmult(a, b, o)) < eps) return 0.0;
    if(distp(a, o) > distp(b, o))
    {
        swap(a, b);
        sign = -1.0;
    }
    if (distp(a, o) < r*r+eps)
    {
        if (distp(b, o) < r*r+eps) return xmult(a, b, o)/2.0*sign;
        point p1, p2;
        intersection_line_circle(o, r, a, b, p1, p2);
        if (distancex(p1, b) > distancex(p2, b)) swap(p1, p2);
        double ret1 = fabs(xmult(a, p1, o));
        double ret2 = acos((p1.x*b.x+p1.y*b.y)/p1.sqrx()/b.sqrx())*r*r;
        double ret = (ret1+ret2)/2.0;
        if (xmult(a, b, o)<eps && sign>0.0 || xmult(a, b, o)>eps && sign<0.0) ret = -ret;
        return ret;
    }
    point ins = len_pot_seg(o, a, b);
    if(distp(o, ins)>r*r-eps)
    {
        double ret = acos((a.x*b.x+a.y*b.y)/a.sqrx()/b.sqrx())*r*r/2.0;
        if(xmult(a, b, o)<eps && sign>0.0 || xmult(a, b, o)>eps && sign<0.0) ret = -ret;
        return ret;
    }
    point p1, p2;
    intersection_line_circle(o, r, a, b, p1, p2);
    double cm = r/(distancex(o, a)-r);
    point m = point((o.x+cm*a.x)/(1+cm),(o.y+cm*a.y)/(1+cm));
    double cn = r/(distancex(o, b)-r);
    point n = point((o.x+cn*b.x)/(1+cn),(o.y+cn*b.y)/(1+cn));
    double ret1 = acos((m.x*n.x+m.y*n.y)/m.sqrx()/n.sqrx())*r*r;
    double ret2 = acos((p1.x*p2.x+p1.y*p2.y)/p1.sqrx()/p2.sqrx())*r*r-fabs(xmult(p1, p2, o));
    double ret = (ret1-ret2)/2.0;
    if(xmult(a, b, o)<eps && sign>0.0||xmult(a, b, o)>eps && sign<0.0) ret=-ret;
    return ret;
}


ACM 很全的计算几何模板 基础部分 1.几何公式 5 1.1三角形 5 1.2四边形 5 1.3正n边形 5 1.4 5 1.5棱柱 6 1.6棱锥 6 1.7棱台 6 1.8柱 6 1.9锥 6 1.10台 7 1.11球 7 1.12球台 7 1.13球扇形 7 2.直线与线段 7 2.0预备函数 7 2.1判三点是否共线 8 2.2判点是否在线段上 9 2.3判断两点在线段的同一侧 9 2.4判断两点是否在线段的异侧 9 2.5点关于直线的对称点 10 2.7判断两线段是否相 10 2.7.1常用版 10 2.7.2不常用版 11 2.8 两条直线的点 11 2.9点到直线的最近距离 12 2.10点到线段的最近距离 12 3.多边形 12 3.0 预备浮点函数 12 3.1判定是否是凸多边形 13 3.2判定点是否在多边形内 14 3.3 判定一条线段是否在一个任意多边形内 15 4. 三角形 16 4.0预备函数 16 4.1三角形的外心 17 4.2三角形内心 17 4.3三角形垂心 17 5. 18 5.0预备函数 18 5.1判定直线是否与 19 5.2判定线段与 19 5.3判 19 5.4计算上到点p最近点 19 5.5计算直线与点 20 5.6计算两个点 20 6. 球面 21 6.0给出地球经度纬度,计算心角 21 6.1已知经纬度,计算地球上两点直线距离 21 6.2已知经纬度,计算地球上两点球面距离 21 7. 三维几何的若干模板 22 7.0预备函数 22 7.1判定三点是否共线 23 7.2判定四点是否共面 23 7.1判定点是否在线段上 23 7.2判断点是否在空间三角形上 24 7.3判断两点是否在线段同侧 24 7.4判断两点是否在线段异侧 25 7.5判断两点是否在平面同侧 25 7.6判断两点是否在平面异侧 25 7.7判断两空间直线是否平行 25 7.8判断两平面是否平行 26 7.9判断直线是否与平面平行 26 7.10判断两直线是否垂直 26 7.11判断两平面是否垂直 26 7.12判断两条空间线段是否相 27 7.13判断线段是否与空间三角形相 27 7.14计算两条直线的点 28 7.15计算直线与平面的点 28 7.16计算两平面的线 29 7.17点到直线的距离 29 7.18 计算点到平面的距离 29 7.19计算直线到直线的距离 30 7.20空间两直线夹角的cos值 30 7.21两平面夹角的cos值 30 7.22直线与平面夹角sin值 31 1.最远曼哈顿距离 31 2. 最近点对 32 3. 最近点对 34 4. 最小包围 36 5. 两个点 39 6. 三角形外接心 40 7. 凸包 42 8.凸包卡壳旋转出所有对踵点、最远点对 44 9. 凸包+旋转卡壳平面面积最大三角 47 10. Pick定理 50 11. 多边形面积和重心 51 12. 判断一个简单多边形是否有核 52 13. 模拟退火 54 14. 六边形坐标系 56 15. 用一个给定半径的覆盖最多的点 60 16. 不等大的弧表示 62 17. 矩形面积并 62 18. 矩形的周长并 66 19. 最近对 70 20. 两个面积 74
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值