【总结】计算几何模板

【总结】计算几何模板计算几何模板 1 几何公式 1 1 角 1 正弦定理 a sinA b sinB c sinC 2R2 余弦定理 a b c 2bc cosAb a c 2ac cosBc a b 2ab cosC3 倍角公

大家好,欢迎来到IT知识分享网。

 
 
   

 

计算几何模板

 

1.   几何公式

 

1.1 角:

1.正弦定理:

a/sinA = b/sinB = c/sinC = 2R

2.余弦定理:

a² = b²+c²-2bc*cosA

b² = a²+c²-2ac*cosB

c² = a²+b²-2ab*cosC

3.倍角公式:

sin(2α)=2sinαcosα

cos(2α)=(cosα)²-1=1-2(sinα)²

tan(2α)=2tanα/[1-(tanα)²]

sin(3α)=3sinα-4(sinα)^3

cos(3α)=4(cosα)^3-3cosα

 

1.2 三角形:

在△ABC中,设AB=c,AC=b,CB=a, r为内切圆半径, R为外接圆半径

1.半周长 P = a+b+c;

2.面积 S =a*b*sin(C)/2;

      S = sqrt(P(P-a)(P-b)(P-c))

3.a边中线长 Ma =(1/2)*sqrt(2b²+2c²-a²)

           Ma = (1/2)*sqrt(b²+c²+2bc*cosA)

4.a边高长 ha =c*sinB=b*sinC

         ha = sqrt(b²-(a²+b²-c²)²/(2a)²)

5.A角平分线长 la =2bc*cos(A/2)/(b+c)

              la = sqrt{bc[(b+c)²-a²]}/(b+c)

6.内切圆半径 r = S/P;

            r = 4R*sin(A/2)sin(B/2)sin(C/2);

            r = P*tan(A/2)tan(B/2)tan(C/2)

7.外接圆半径 R =a/(2sinA)

            R = abc/(4P)

            R = abc/[2r(a+b+c)]

 

1.3 四边形:

D1,D2为对角线,M对角线中点连线,A为对角线夹角,P为四边形半周长

1. a^2+b^2+c^2+d^2 = D1^2+D2^2+4M^2

2. 面积 S=D1D2sin(A)/2

(以下对于圆的内接四边形)

3. ac+bd=D1D2

4. S=sqrt((P-a)(P-b)(P-c)(P-d))

 

1.4 正n边形:

R为外接圆半径,r为内切圆半径

1. 中心角 A=2PI/n

2. 内角 C=(n-2)PI/n

3. 边长a=2sqrt(R^2-r^2)=2Rsin(A/2)=2rtan(A/2)

4. 面积S=nar/2=nr^2tan(A/2)=nR^2sin(A)/2=na^2/(4tan(A/2))

 

1.5 圆:

A为所求的角度

1. 弧长 l=rA

2. 弦长 a=2sqrt(2hr-h^2)=2rsin(A/2)

3. 弓形高h=r-sqrt(r^2-a^2/4)=r(1-cos(A/2))=atan(A/4)/2

4. 扇形面积S1=rl/2=r^2A/2

5. 弓形面积S2=(rl-a(r-h))/2=r^2(A-sin(A))/2

 

1.6 棱柱:

1. 体积 V=Ah,A为底面积,h为高

2. 侧面积 S=lp,l为棱长,p为直截面周长

3. 全面积 T=S+2A

 

1.7 棱锥:

1. 体积 V=Ah/3,A为底面积,h为高

(以下对正棱锥)

2. 侧面积 S=lp/2,l为斜高,p为底面周长

3. 全面积 T=S+A

 

1.8 棱台:

1. 体积V=(A1+A2+sqrt(A1A2))h/3,A1.A2为上下底面积,h为高

(以下为正棱台)

2. 侧面积S=(p1+p2)l/2,p1.p2为上下底面周长,l为斜高

3. 全面积 T=S+A1+A2

 

1.9 圆柱:

1. 侧面积 S=2PIrh

2. 全面积 T=2PIr(h+r)

3. 体积 V=PIr^2h

 

 

 

1.10圆锥:

1. 母线l=sqrt(h^2+r^2)

2. 侧面积 S=PIrl

3. 全面积 T=PIr(l+r)

4. 体积 V=PIr^2h/3

 

1.11 圆台:

1. 母线l=sqrt(h^2+(r1-r2)^2)

2. 侧面积 S=PI(r1+r2)l

3. 全面积T=PIr1(l+r1)+PIr2(l+r2)

4. 体积V=PI(r1^2+r2^2+r1r2)h/3

 

1.12 球:

1. 全面积 T=4PIr^2

2. 体积 V=4PIr^3/3

 

1.13 球台:

1. 侧面积 S=2PIrh

2. 全面积T=PI(2rh+r1^2+r2^2)

3. 体积V=PIh(3(r1^2+r2^2)+h^2)/6

 

1.14 球扇形:

1. 全面积T=PIr(2h+r0),h为球冠高,r0为球冠底面半径

2. 体积 V=2PIr^2h/3

 

2.   几何向量表示

 

2.1:定义

struct Point{ double x,y; };    //点坐标

struct V{ Point start,endd; };  //两点式

struct V2{ double A,B,C; };   //一般式 ax+by+c = 0

 

2.2:转化

//两点式化一般式

V2 V2toV1(V Line)      // y=kx+c  k=y/x

{

  V2temp;

 temp.A = Line.endd.y – Line.start.y;

 temp.B = Line.start.x – Line.endd.x;

 temp.C = Line.endd.x * Line.start.y – Line.start.x * Line.endd.y;

 return temp;

}

//两点式起点化为 0,0

V change(V a)

{

    Vb;

    b.start.x= b.start.y = 0;

   b.endd.x = a.endd.x – a.start.x;

   b.endd.y = a.endd.y – a.start.y;

   return b;

}

向量运算需要先把两点式起点化为 0,0

2.3 向量相加:

V add(V a,V b)

{

    Vaa = change(a);

    Vbb = change(b);

    Vc;

   c.start.x = c.start.y = 0;

   c.endd.x = aa.endd.x+bb.endd.x;

   c.endd.y = aa.endd.y+bb.endd.y;

   return c;

}

 

2.4 向量相减:

V dec(V a,V b)

 {

    Vaa = change(a);

    Vbb = change(b);

    Vc;

   c.start.x = 0;

   c.start.y = 0;

   c.endd.x = aa.endd.x-bb.endd.x;

   c.endd.y = aa.endd.y-bb.endd.y;

   return c;

}

 

 

 

 

2.5 向量点积:

double dmult(V a,V b)

{

   double result;

    Vaa = change(a);

    Vbb = change(b);

   result = aa.endd.x*bb.endd.x + aa.endd.y*bb.endd.y;

   return result;

}

double dmult(Point a,Point b,Point c) //(ca)•(cb)

{

   return (a.x-c.x)*(b.x-c.x)+(a.y-c.y)*(b.y-c.y);

}

 

可以通过向量点积计算向量夹角

a•b = |a|*|b|*cos(∠)

a•b = x1*x2 + y1*y2;

 

2.6 向量叉积:

double xmult(V a,V b)

{

   double result;

    Vaa = change(a);

    Vbb = change(b);

   result = aa.endd.x*bb.endd.y – aa.endd.y*bb.endd.x;

   return result;

}

 

double xmult(Point a,Point b,Point c)   //(ca)×(cb)

{

   return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);

}

 

叉积可以计算三角形面积(取绝对值)

可以通过向量叉积的符号判断向量的顺逆时针关系

a×b > 0 , a 在 b的顺时针方向

a×b < 0 , a 在 b的逆时针方向

a×b = 0 , a 在 b同方向或反方向

a×b = x1*y2 – x2*y1;

 

 

3.   点线关系

 

3.1  点与点问题:

//两点距离

double dist(Point a,Point b) {

   return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));

}

 

//判断三点共线

bool dot_line(Point a,Point b,Point c)

{

   double temp = xmult(b,c,a);

   if(fabs(temp) < eps)    //满足向量 AC×AB == 0

       return true;

   return false;

}

 

3.2  点与线问题:

//判断点C是否在线段A,B上(包括端点)

bool dot_seg(Point a,Point b,Point c)

{

   //满足三点共线,并且满足C在AB构成的矩形内

   if(dot_line(a,b,c) && c.x >= min(a.x,b.x) && c.x<= max(a.x,b.x) && c.y >= min(a.y,b.y) && c.y <=max(a.y,b.y))

       return true;

   return false;

}

//判断两点在线的同侧,点在线上或异侧返回false

bool same_side(Point a,Point b,V line) {

   return xmult(line.start,a,line.endd)*xmult(line.start,b,line.endd) >eps;

}

//判断两点在线的异侧,点在线上或同侧返回false

bool opp_side(Point a,Point b,V line) {

   return xmult(line.start,a,line.endd)*xmult(line.start,b,line.endd) <-eps;

}

 

//获得某点对于线垂线的另个点

Point get_cLine(Point a, V Line)

{

   Point t = a;

   t.x += Line.start.y-Line.endd.y;

   t.y += Line.endd.x-Line.start.x;

   return t;

}

 

//点在直线上的最近点(垂点)

Point ptoline(Point a,V Line)

{

   Point t = get_cLine(a, Line);   //得到垂线的另个点

    VLine2;    //垂线

   Line2.start = a;

   Line2.endd = t;

   return intersection(Line2,Line);   //两直线相交的交点

}

 

//点到直线的距离(点到垂点的距离)

double dist_ptoline(Point a,V Line) {

   returnfabs(xmult(a,Line.start,Line.endd)/dist(Line.start,Line.endd));  //叉积求面积/底长

}

 

//点到线段上的最近点

Point ptoseg(Point a,V Line)

{

   Point t = get_cLine(a, Line);   //得到垂线的另个点

    VLine2;

   Line2.start = a;

   Line2.endd = t;

   if(!seg_Line_intersect(Line,Line2)) //如果直线Line2与线段Line不相交

       return dist(a,Line.start)<dist(a,Line.endd)?Line.start:Line.endd;

   return ptoline(a,Line); //点在直线上的垂点

}

 

//点到线段距离

double dist_ptoseg(Point a,V Line) {

   Point t = get_cLine(a, Line);   //得到垂线的另个点

    VLine2;

   Line2.start = a;

   Line2.endd = t;

   if(!seg_Line_intersect(Line,Line2)) //如果直线Line2与线段Line不相交

       returndist(a,Line.start)<dist(a,Line.endd)?dist(a,Line.start):dist(a,Line.endd);

   return dist_ptoline(a,Line);    //点到直线的距离(点到垂点的距离)

}

//矢量V以P为顶点逆时针旋转angle并放大scale倍

Point rotat(Point v,Point p,doubleangle,double scale)

{

   Point ret=p;

   v.x-=p.x,v.y-=p.y;

   p.x=scale*cos(angle);

   p.y=scale*sin(angle);

   ret.x+=v.x*p.x-v.y*p.y;

   ret.y+=v.x*p.y+v.y*p.x;

   return ret;

}

 

//p点关于直线L的对称点(用一般式,未验证)

Point symmetricalPointofLine(Point p, V2Line)

{

   Point p2;

   double d;

    d= Line.a * Line.a + Line.b * Line.b;

   p2.x = (Line.b * Line.b * p.x – Line.a * Line.a * p.x –

           2 * Line.a * Line.b * p.y – 2 * Line.a * Line.c) / d;

   p2.y = (Line.a * Line.a * p.y – Line.b * Line.b * p.y –

           2 * Line.a * Line.b * p.x – 2 * Line.b * Line.c) / d;

   return p2;

}

 

3.3 线与线问题:

//两直线平行

bool parallel(V Line1,V Line2) {

   return fabs((Line1.start.x-Line1.endd.x)*(Line2.start.y-Line2.endd.y) -(Line2.start.x-Line2.endd.x)*(Line1.start.y-Line1.endd.y)) < eps;

}

//两直线垂直

bool perpendicular(V Line1,V Line2) {

   return fabs((Line1.start.x-Line1.endd.x)*(Line2.start.x-Line2.endd.x) +(Line1.start.y-Line1.endd.y)*(Line2.start.y-Line2.endd.y)) < eps;

}

 

//判断直线Line2与线段Line1相交,包括端点,不包括平行

bool seg_Line_intersect(V Line1,V Line2)

{

   return !same_side(Line1.start,Line1.endd,Line2);

}

 

//判断两线段相交,包括端点和部分重合

bool intersect_in(V Line1,V Line2)

{

   if(!dot_line(Line1.start,Line1.endd,Line2.start) ||!dot_line(Line1.start,Line1.endd,Line2.endd))

       return !same_side(Line1.start,Line1.endd,Line2) &&!same_side(Line2.start,Line2.endd,Line1);

   returndot_seg(Line1.start,Line1.endd,Line2.start)||dot_seg(Line1.start,Line1.endd,Line2.endd)||dot_seg(Line2.start,Line2.endd,Line1.start)||dot_seg(Line2.start,Line2.endd,Line1.endd);

}

 

//判两线段相交,不包括端点和部分重合

bool intersect_ex(V Line1,V Line2)

{

   return opp_side(Line1.start,Line1.endd,Line2) &&opp_side(Line2.start,Line2.endd,Line1);

}

 

//计算两直线交点,注意事先判断直线是否平行!

//线段交点请另外判线段相交(同时还是要判断是否平行!)

Point intersection(V u,V v)

{

   Point ret=u.start;

   doublet=((u.start.x-v.start.x)*(v.start.y-v.endd.y)-(u.start.y-v.start.y)*(v.start.x-v.endd.x))

            /((u.start.x-u.endd.x)*(v.start.y-v.endd.y)-(u.start.y-u.endd.y)*(v.start.x-v.endd.x));

   ret.x+=(u.endd.x-u.start.x)*t;

   ret.y+=(u.endd.y-u.start.y)*t;

   return ret;

}

 

4三角形

4.1 面积:

//计算三角形面积,输入三顶点

double area_triangle(Point p1,Pointp2,Point p3) {

   return fabs(xmult(p1,p2,p3))/2;

}

//计算三角形面积,输入三边长

double area_triangle(double a,doubleb,double c) {

   double s=(a+b+c)/2;

   return sqrt(s*(s-a)*(s-b)*(s-c));

}

 

4.2 三角形与点:

//判断点p是否在三角形内或上

//点在平面内与三角形三个点构成的三个三角形的面积和与原三角形的面积比较,如果相等,即可判断在三角形内或上(若需要区分,先判断点与三条边)

bool dot_triangle(Point p,Point a,Pointb,Point c)

{

   double abx = fabs(xmult(a,b,p));

   double acx = fabs(xmult(a,c,p));

   double bcx = fabs(xmult(b,c,p));

   double abc = fabs(xmult(a,b,c));

   if(fabs(abx+acx+bcx – abc) < eps)

       return true;

   return false;

}

 

4.3 五个重要点:

//外心 三角形三边垂直平分线的交点

Point circumcenter(Point a,Point b,Point c){

    Vu,v;      //垂直平分线

   u.start.x=(a.x+b.x)/2;

   u.start.y=(a.y+b.y)/2;

   u.endd.x=u.start.x-a.y+b.y;

   u.endd.y=u.start.y+a.x-b.x;

 

   v.start.x=(a.x+c.x)/2;

   v.start.y=(a.y+c.y)/2;

   v.endd.x=v.start.x-a.y+c.y;

   v.endd.y=v.start.y+a.x-c.x;

   return intersection(u,v);

}

 

//内心 三个内角的三条角平分线的交点

Point incenter(Point a,Point b,Point c) {

    Vu,v;  //角平分线

   double n,m; //角度

   u.start = a;

   m=atan2(b.y-a.y,b.x-a.x);

   n=atan2(c.y-a.y,c.x-a.x);

   u.endd.x=u.start.x+cos((m+n)/2);

   u.endd.y=u.start.y+sin((m+n)/2);

 

   v.start=b;

   m=atan2(a.y-b.y,a.x-b.x);

   n=atan2(c.y-b.y,c.x-b.x);

   v.endd.x=v.start.x+cos((m+n)/2);

   v.endd.y=v.start.y+sin((m+n)/2);

   return intersection(u,v);

}

 

//垂心  三角形的三条高或其延长线相交于一点

Point perpencenter(Point a,Point b,Point c){

    Vu,v;  //高

   u.start=c;

   u.endd.x=u.start.x-a.y+b.y;

   u.endd.y=u.start.y+a.x-b.x;

 

   v.start=b;

   v.endd.x=v.start.x-a.y+c.y;

   v.endd.y=v.start.y+a.x-c.x;

   return intersection(u,v);

}

 

//重心  是三角形三边中线的交点

//到三角形三顶点距离的平方和最小的点

//三角形内到三边距离之积最大的点

Point barycenter(Point a,Point b,Point c)

{

    Vu,v;  //中线

   u.start.x=(a.x+b.x)/2;

   u.start.y=(a.y+b.y)/2;

   u.endd=c;

   v.start.x=(a.x+c.x)/2;

   v.start.y=(a.y+c.y)/2;

   v.endd=b;

   return intersection(u,v);

}

 

//费马点

//到三角形三顶点距离之和最小的点

Point fermentpoint(Point a,Point b,Point c)

{

   Point u,v;

   double step=fabs(a.x)+fabs(a.y)+fabs(b.x)+fabs(b.y)+fabs(c.x)+fabs(c.y);

   int i,j,k;

    u.x=(a.x+b.x+c.x)/3;

   u.y=(a.y+b.y+c.y)/3;

   while (step>1e-10)

       for (k=0; k<10; step/=2,k++)

           for (i=-1; i<=1; i++)

                for (j=-1; j<=1; j++)

                {

                    v.x=u.x+step*i;

                    v.y=u.y+step*j;

                    if(dist(u,a)+dist(u,b)+dist(u,c)>dist(v,a)+dist(v,b)+dist(v,c))

                        u=v;

                }

   return u;

}

 

5多边形

 

5.1 简单多边形面积:

// p[]为顶点集并是顺序存储的(不是的话,无法计算吧),n为多边形顶点数

//存储是从0开始         (未验证)

double area_poly(Point* p,int n)

{

   double ans = 0;

   for(int i = 1; i < n-1; i++)

       ans += xmult(p[i],p[i+1],p[0]);

   return fabs(ans)/2;

}

 

5.2 判定多边形:

int _sign(double temp)

{

   if(temp < -eps) return 2;

   else if(temp > eps) return 1;

   else return 0;

}

//判定凸多边形,顶点按顺时针或逆时针给出,允许相邻边共线

int is_convex(Point* p,int n)

{

   int i,s[3]= {1,1,1};

   for (i=0; i<n&&s[1]|s[2]; i++)

       s[_sign(xmult(p[(i+1)%n],p[(i+2)%n],p[i]))]=0;

   return s[1]|s[2];

}

//判定凸多边形,顶点按顺时针或逆时针给出,不允许相邻边共线

int is_convex2(Point* p,int n)

{

   int i,s[3]= {1,1,1};

   for (i=0; i<n&&s[1]|s[2]; i++)

       s[_sign(xmult(p[(i+1)%n],p[(i+2)%n],p[i]))]=0;

   return s[0]&&s[1]|s[2];

}

 

5.3 点与多边形:

//判点在凸多边形内或多边形边上,顶点按顺时针或逆时针给出

int inside_convex(Point q,int n,Point* p)

{

   int i,s[3]= {1,1,1};

   for (i=0; i<n&&s[1]|s[2]; i++)

       s[_sign(xmult(p[(i+1)%n],q,p[i]))]=0;

   return s[1]|s[2];

}

 

//判点在凸多边形内,顶点按顺时针或逆时针给出,在多边形边上返回0

int inside_convex_v2(Point q,int n,Point*p)

{

   int i,s[3]= {1,1,1};

   for (i=0; i<n&&s[0]&&s[1]|s[2]; i++)

       s[_sign(xmult(p[(i+1)%n],q,p[i]))]=0;

   return s[0]&&s[1]|s[2];

}

//判点在任意多边形内,顶点按顺时针或逆时针给出

//on_edge表示点在多边形边上时的返回值,offset为多边形坐标上限  (不是很懂这个)

int inside_polygon(Point q,int n,Point* p,inton_edge=1)

{

   Point q2;

   int i=0,coun;

   while (i<n)

       for (coun=i=0,q2.x=rand()/*+offset*/,q2.y=rand()/*+offset*/; i<n;i++)

           if(fabs(xmult(q,p[i],p[(i+1)%n]))<eps&&(p[i].x-q.x)*(p[(i+1)%n].x-q.x)<eps&&(p[i].y-q.y)*(p[(i+1)%n].y-q.y)<eps)

                return on_edge;

           else if (fabs(xmult(q,q2,p[i])) < eps)

                break;

           else if(xmult(q,p[i],q2)*xmult(q,p[(i+1)%n],q2)<-eps&&xmult(p[i],q,p[(i+1)%n])*xmult(p[i],q2,p[(i+1)%n])<-eps)

               coun++;

   return coun&1;

}

 

5.4 多边形重心:

//多边形重心

Point barycenter(Point* p,int n) {

   Point ret,t;

   double t1=0,t2;

   int i;

   ret.x=ret.y=0;

   for (i=1;i<n-1;i++)

       if (fabs(t2=xmult(p[0],p[i],p[i+1]))>eps)

       {

           t=barycenter(p[0],p[i],p[i+1]); //三角形重心

           ret.x+=t.x*t2;

           ret.y+=t.y*t2;

           t1+=t2;

       }

   if (fabs(t1)>eps)

       ret.x/=t1,ret.y/=t1;

   return ret;

}

 

5.5 多边形与网格:

struct PPoint{ int x,y; };

//多边形上的网格点个数(PPoint中 x,y 是int行)

int grid_onedge(int n,PPoint* p) {

   int i,ret=0;

   for (i=0; i<n; i++)

       ret+=__gcd(abs(p[i].x-p[(i+1)%n].x),abs(p[i].y-p[(i+1)%n].y));

   return ret;

}

 

//多边形内的网格点个数

int grid_inside(int n,PPoint* p) {

   int i,ret=0;

   for (i=0; i<n; i++)

       ret+=p[(i+1)%n].y*(p[i].x-p[(i+2)%n].x);

   return (abs(ret)-grid_onedge(n,p))/2+1;

}

6圆

 

//判直线和圆相交,包括相切

int intersect_line_circle(Point c,doubler,Point p1,Point p2)

{

    VLine;

   Line.start = p1;

   Line.endd = p2;

   return dist_ptoline(c,Line)<r+eps;  //点到直线的最近距离

}

 

//判线段和圆相交,包括端点和相切

int intersect_seg_circle(Point c,doubler,Point p1,Point p2)

{

   double t1=dist(c,p1)-r,t2=dist(c,p2)-r;

   Point t=c;

   if (t1<eps||t2<eps)

       return t1>-eps||t2>-eps;

    t.x+=p1.y-p2.y;

   t.y+=p2.x-p1.x;

    VLine;

   Line.start = p1;

   Line.endd = p2;

   returnxmult(p1,c,t)*xmult(p2,c,t)<eps&&dist_ptoline(c,Line)-r<eps;

}

 

//判圆和圆相交,包括相切

int intersect_circle_circle(Point c1,doubler1,Point c2,double r2) {

   return dist(c1,c2)<r1+r2+eps&&dist(c1,c2)>fabs(r1-r2)-eps;

}

 

//计算圆上到点p最近点,如p与圆心重合,返回p本身

Point dot_to_circle(Point c,double r,Pointp) {

   Point u,v;

   if (dist(p,c)<eps)

       return p;

   u.x=c.x+r*fabs(c.x-p.x)/dist(c,p);

   u.y=c.y+r*fabs(c.y-p.y)/dist(c,p)*((c.x-p.x)*(c.y-p.y)<0?-1:1);

   v.x=c.x-r*fabs(c.x-p.x)/dist(c,p);

   v.y=c.y-r*fabs(c.y-p.y)/dist(c,p)*((c.x-p.x)*(c.y-p.y)<0?-1:1);

   return dist(u,p)<dist(v,p)?u:v;

}

 

//计算直线与圆的交点,保证直线与圆有交点

//计算线段与圆的交点可用这个函数后判点是否在线段上

void intersection_line_circle(Pointc,double r,V Line,Point& p1,Point& p2) {

   Point p=c;

   double t;

   p.x+=Line.start.y-Line.endd.y;

   p.y+=Line.endd.x-Line.start.x;

    VLine2;

   Line2.start = p;

   Line2.endd = c;

   p=intersection(Line2,Line);

   t=sqrt(r*r-dist(p,c)*dist(p,c))/dist(Line.start,Line.endd);

   p1.x=p.x+(Line.endd.x-Line.start.x)*t;

   p1.y=p.y+(Line.endd.y-Line.start.y)*t;

   p2.x=p.x-(Line.endd.x-Line.start.x)*t;

   p2.y=p.y-(Line.endd.y-Line.start.y)*t;

}

 

//计算圆与圆的交点,保证圆与圆有交点,圆心不重合

void intersection_circle_circle(Pointc1,double r1,Point c2,double r2,Point& p1,Point& p2) {

   Point u,v;

   double t;

   t=(1+(r1*r1-r2*r2)/dist(c1,c2)/dist(c1,c2))/2;

   u.x=c1.x+(c2.x-c1.x)*t;

   u.y=c1.y+(c2.y-c1.y)*t;

   v.x=u.x+c1.y-c2.y;

   v.y=u.y-c1.x+c2.x;

    VLine;

   Line.start = u;

   Line.endd = v;

   intersection_line_circle(c1,r1,Line,p1,p2);

}

 

//将向量p逆时针旋转angle角度

Point Rotate(Point p,double angle) {

   Point res;

   res.x=p.x*cos(angle)-p.y*sin(angle);

   res.y=p.x*sin(angle)+p.y*cos(angle);

   return res;

}

 

//求圆外一点对圆(o,r)的两个切点result1和result2

void TangentPoint_PC(Point poi,Pointo,double r,Point &result1,Point &result2) {

   double line=sqrt((poi.x-o.x)*(poi.x-o.x)+(poi.y-o.y)*(poi.y-o.y));

   double angle=acos(r/line);

   Point unitvector,lin;

   lin.x=poi.x-o.x;

   lin.y=poi.y-o.y;

   unitvector.x=lin.x/sqrt(lin.x*lin.x+lin.y*lin.y)*r;

   unitvector.y=lin.y/sqrt(lin.x*lin.x+lin.y*lin.y)*r;

   result1=Rotate(unitvector,-angle);

   result2=Rotate(unitvector,angle);

   result1.x+=o.x;

   result1.y+=o.y;

   result2.x+=o.x;

   result2.y+=o.y;

   return ;

}

 

7三维几何(未)

 

//三维几何函数库

#define zero(x)(((x)>0?(x):-(x))<eps)

struct point3 {

   double x,y,z;

};

struct line3 {

   point3 a,b;

};

struct plane3 {

   point3 a,b,c;

};

 

//计算dot product U .V

double dmult(point3 u,point3 v) {

   return u.x*v.x+u.y*v.y+u.z*v.z;

}

//计算cross product Ux V

point3 xmult(point3 u,point3 v) {

   point3 ret;

   ret.x=u.y*v.z-v.y*u.z;

   ret.y=u.z*v.x-u.x*v.z;

   ret.z=u.x*v.y-u.y*v.x;

   return ret;

}

//矢量差 U – V

point3 subt(point3 u,point3 v) {

   point3 ret;

   ret.x=u.x-v.x;

   ret.y=u.y-v.y;

   ret.z=u.z-v.z;

   return ret;

}

 

//取平面法向量

point3 pvec(plane3 s) {

   return xmult(subt(s.a,s.b),subt(s.b,s.c));

}

point3 pvec(point3 s1,point3 s2,point3 s3) {

   return xmult(subt(s1,s2),subt(s2,s3));

}

 

//两点距离,单参数取向量大小

double dist(point3 p1,point3 p2) {

   return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)+(p1.z-p2.z)*(p1.z-p2.z));

}

 

//向量大小

double vlen(point3 p) {

   return sqrt(p.x*p.x+p.y*p.y+p.z*p.z);

}

 

//判三点共线

int dots_inline(point3 p1,point3 p2,point3p3) {

   return vlen(xmult(subt(p1,p2),subt(p2,p3)))<eps;

}

//判四点共面

int dots_onplane(point3 a,point3 b,point3c,point3 d) {

   return zero(dmult(pvec(a,b,c),subt(d,a)));

}

 

//判点是否在线段上,包括端点和共线

int dot_online_in(point3 p,line3 l) {

   returnzero(vlen(xmult(subt(p,l.a),subt(p,l.b))))&&(l.a.x-p.x)*(l.b.x-p.x)<eps&&

          (l.a.y-p.y)*(l.b.y-p.y)<eps&&(l.a.z-p.z)*(l.b.z-p.z)<eps;

}

int dot_online_in(point3 p,point3 l1,point3l2) {

   returnzero(vlen(xmult(subt(p,l1),subt(p,l2))))&&(l1.x-p.x)*(l2.x-p.x)<eps&&

          (l1.y-p.y)*(l2.y-p.y)<eps&&(l1.z-p.z)*(l2.z-p.z)<eps;

}

 

//判点是否在线段上,不包括端点

int dot_online_ex(point3 p,line3 l) {

   returndot_online_in(p,l)&&(!zero(p.x-l.a.x)||!zero(p.y-l.a.y)||!zero(p.z-l.a.z))&&

          (!zero(p.x-l.b.x)||!zero(p.y-l.b.y)||!zero(p.z-l.b.z));

}

int dot_online_ex(point3 p,point3 l1,point3l2) {

   returndot_online_in(p,l1,l2)&&(!zero(p.x-l1.x)||!zero(p.y-l1.y)||!zero(p.z-l1.z))&&

          (!zero(p.x-l2.x)||!zero(p.y-l2.y)||!zero(p.z-l2.z));

}

 

//判点是否在空间三角形上,包括边界,三点共线无意义

int dot_inplane_in(point3 p,plane3 s) {

   return zero(vlen(xmult(subt(s.a,s.b),subt(s.a,s.c)))-vlen(xmult(subt(p,s.a),subt(p,s.b)))-

               vlen(xmult(subt(p,s.b),subt(p,s.c)))-vlen(xmult(subt(p,s.c),subt(p,s.a))));

}

int dot_inplane_in(point3 p,point3s1,point3 s2,point3 s3) {

   return zero(vlen(xmult(subt(s1,s2),subt(s1,s3)))-vlen(xmult(subt(p,s1),subt(p,s2)))-

               vlen(xmult(subt(p,s2),subt(p,s3)))-vlen(xmult(subt(p,s3),subt(p,s1))));

}

 

//判点是否在空间三角形上,不包括边界,三点共线无意义

int dot_inplane_ex(point3 p,plane3 s) {

   returndot_inplane_in(p,s)&&vlen(xmult(subt(p,s.a),subt(p,s.b)))>eps&&

          vlen(xmult(subt(p,s.b),subt(p,s.c)))>eps&&vlen(xmult(subt(p,s.c),subt(p,s.a)))>eps;

}

int dot_inplane_ex(point3 p,point3s1,point3 s2,point3 s3) {

   return dot_inplane_in(p,s1,s2,s3)&&vlen(xmult(subt(p,s1),subt(p,s2)))>eps&&

          vlen(xmult(subt(p,s2),subt(p,s3)))>eps&&vlen(xmult(subt(p,s3),subt(p,s1)))>eps;

}

 

//判两点在线段同侧,点在线段上返回0,不共面无意义

int same_side(point3 p1,point3 p2,line3 l) {

   return dmult(xmult(subt(l.a,l.b),subt(p1,l.b)),xmult(subt(l.a,l.b),subt(p2,l.b)))>eps;

}

 

int same_side(point3 p1,point3 p2,point3l1,point3 l2) {

   returndmult(xmult(subt(l1,l2),subt(p1,l2)),xmult(subt(l1,l2),subt(p2,l2)))>eps;

}

 

//判两点在线段异侧,点在线段上返回0,不共面无意义

int opposite_side(point3 p1,point3 p2,line3l) {

   returndmult(xmult(subt(l.a,l.b),subt(p1,l.b)),xmult(subt(l.a,l.b),subt(p2,l.b)))<-eps;

}

int opposite_side(point3 p1,point3p2,point3 l1,point3 l2) {

   returndmult(xmult(subt(l1,l2),subt(p1,l2)),xmult(subt(l1,l2),subt(p2,l2)))<-eps;

}

 

//判两点在平面同侧,点在平面上返回0

int same_side(point3 p1,point3 p2,plane3 s){

   return dmult(pvec(s),subt(p1,s.a))*dmult(pvec(s),subt(p2,s.a))>eps;

}

int same_side(point3 p1,point3 p2,point3s1,point3 s2,point3 s3) {

   returndmult(pvec(s1,s2,s3),subt(p1,s1))*dmult(pvec(s1,s2,s3),subt(p2,s1))>eps;

}

 

//判两点在平面异侧,点在平面上返回0

int opposite_side(point3 p1,point3p2,plane3 s) {

   return dmult(pvec(s),subt(p1,s.a))*dmult(pvec(s),subt(p2,s.a))<-eps;

}

int opposite_side(point3 p1,point3 p2,point3s1,point3 s2,point3 s3) {

   returndmult(pvec(s1,s2,s3),subt(p1,s1))*dmult(pvec(s1,s2,s3),subt(p2,s1))<-eps;

}

 

//判两直线平行

int parallel(line3 u,line3 v) {

   return vlen(xmult(subt(u.a,u.b),subt(v.a,v.b)))<eps;

}

int parallel(point3 u1,point3 u2,point3v1,point3 v2) {

   return vlen(xmult(subt(u1,u2),subt(v1,v2)))<eps;

}

 

//判两平面平行

int parallel(plane3 u,plane3 v) {

   return vlen(xmult(pvec(u),pvec(v)))<eps;

}

int parallel(point3 u1,point3 u2,point3 u3,point3v1,point3 v2,point3 v3) {

   return vlen(xmult(pvec(u1,u2,u3),pvec(v1,v2,v3)))<eps;

}

 

//判直线与平面平行

int parallel(line3 l,plane3 s) {

   return zero(dmult(subt(l.a,l.b),pvec(s)));

}

int parallel(point3 l1,point3 l2,point3s1,point3 s2,point3 s3) {

   return zero(dmult(subt(l1,l2),pvec(s1,s2,s3)));

}

 

 

//判两直线垂直

int perpendicular(line3 u,line3 v) {

   return zero(dmult(subt(u.a,u.b),subt(v.a,v.b)));

}

int perpendicular(point3 u1,point3u2,point3 v1,point3 v2) {

   return zero(dmult(subt(u1,u2),subt(v1,v2)));

}

 

//判两平面垂直

int perpendicular(plane3 u,plane3 v)

{

   return zero(dmult(pvec(u),pvec(v)));

}

int perpendicular(point3 u1,point3u2,point3 u3,point3 v1,point3 v2,point3 v3)

{

   return zero(dmult(pvec(u1,u2,u3),pvec(v1,v2,v3)));

}

 

//判直线与平面平行

int perpendicular(line3 l,plane3 s)

{

   return vlen(xmult(subt(l.a,l.b),pvec(s)))<eps;

}

int perpendicular(point3 l1,point3 l2,point3s1,point3 s2,point3 s3)

{

   return vlen(xmult(subt(l1,l2),pvec(s1,s2,s3)))<eps;

}

 

//判两线段相交,包括端点和部分重合

int intersect_in(line3 u,line3 v)

{

   if (!dots_onplane(u.a,u.b,v.a,v.b))

       return 0;

   if (!dots_inline(u.a,u.b,v.a)||!dots_inline(u.a,u.b,v.b))

       return !same_side(u.a,u.b,v)&&!same_side(v.a,v.b,u);

   return dot_online_in(u.a,v)||dot_online_in(u.b,v)||dot_online_in(v.a,u)||dot_online_in(v.b,u);

}

int intersect_in(point3 u1,point3 u2,point3v1,point3 v2)

{

   if (!dots_onplane(u1,u2,v1,v2))

       return 0;

   if (!dots_inline(u1,u2,v1)||!dots_inline(u1,u2,v2))

        return!same_side(u1,u2,v1,v2)&&!same_side(v1,v2,u1,u2);

   returndot_online_in(u1,v1,v2)||dot_online_in(u2,v1,v2)||dot_online_in(v1,u1,u2)||dot_online_in(v2,u1,u2);

}

 

 

//判两线段相交,不包括端点和部分重合

int intersect_ex(line3 u,line3 v) {

   returndots_onplane(u.a,u.b,v.a,v.b)&&opposite_side(u.a,u.b,v)&&opposite_side(v.a,v.b,u);

}

 

int intersect_ex(point3 u1,point3 u2,point3v1,point3 v2) {

   returndots_onplane(u1,u2,v1,v2)&&opposite_side(u1,u2,v1,v2)&&opposite_side(v1,v2,u1,u2);

}

 

//判线段与空间三角形相交,包括交于边界和(部分)包含

int intersect_in(line3 l,plane3 s)

{

   return!same_side(l.a,l.b,s)&&!same_side(s.a,s.b,l.a,l.b,s.c)&&

          !same_side(s.b,s.c,l.a,l.b,s.a)&&!same_side(s.c,s.a,l.a,l.b,s.b);

}

int intersect_in(point3 l1,point3 l2,point3s1,point3 s2,point3 s3)

{

   return!same_side(l1,l2,s1,s2,s3)&&!same_side(s1,s2,l1,l2,s3)&&

          !same_side(s2,s3,l1,l2,s1)&&!same_side(s3,s1,l1,l2,s2);

}

 

//判线段与空间三角形相交,不包括交于边界和(部分)包含

int intersect_ex(line3 l,plane3 s)

{

   return opposite_side(l.a,l.b,s)&&opposite_side(s.a,s.b,l.a,l.b,s.c)&&

          opposite_side(s.b,s.c,l.a,l.b,s.a)&&opposite_side(s.c,s.a,l.a,l.b,s.b);

}

int intersect_ex(point3 l1,point3 l2,point3s1,point3 s2,point3 s3)

{

   returnopposite_side(l1,l2,s1,s2,s3)&&opposite_side(s1,s2,l1,l2,s3)&&

          opposite_side(s2,s3,l1,l2,s1)&&opposite_side(s3,s1,l1,l2,s2);

}

 

//计算两直线交点,注意事先判断直线是否共面和平行!

//线段交点请另外判线段相交(同时还是要判断是否平行!)

point3 intersection(line3 u,line3 v)

{

   point3 ret=u.a;

   double t=((u.a.x-v.a.x)*(v.a.y-v.b.y)-(u.a.y-v.a.y)*(v.a.x-v.b.x))

            /((u.a.x-u.b.x)*(v.a.y-v.b.y)-(u.a.y-u.b.y)*(v.a.x-v.b.x));

   ret.x+=(u.b.x-u.a.x)*t;

   ret.y+=(u.b.y-u.a.y)*t;

   ret.z+=(u.b.z-u.a.z)*t;

   return ret;

}

point3 intersection(point3 u1,point3u2,point3 v1,point3 v2)

{

   point3 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;

   ret.z+=(u2.z-u1.z)*t;

   return ret;

}

 

 

//计算直线与平面交点,注意事先判断是否平行,并保证三点不共线!

//线段和空间三角形交点请另外判断

point3 intersection(line3 l,plane3 s)

{

   point3 ret=pvec(s);

   double t=(ret.x*(s.a.x-l.a.x)+ret.y*(s.a.y-l.a.y)+ret.z*(s.a.z-l.a.z))/

            (ret.x*(l.b.x-l.a.x)+ret.y*(l.b.y-l.a.y)+ret.z*(l.b.z-l.a.z));

   ret.x=l.a.x+(l.b.x-l.a.x)*t;

   ret.y=l.a.y+(l.b.y-l.a.y)*t;

   ret.z=l.a.z+(l.b.z-l.a.z)*t;

   return ret;

}

point3 intersection(point3 l1,point3l2,point3 s1,point3 s2,point3 s3)

{

   point3 ret=pvec(s1,s2,s3);

   double t=(ret.x*(s1.x-l1.x)+ret.y*(s1.y-l1.y)+ret.z*(s1.z-l1.z))/

            (ret.x*(l2.x-l1.x)+ret.y*(l2.y-l1.y)+ret.z*(l2.z-l1.z));

   ret.x=l1.x+(l2.x-l1.x)*t;

   ret.y=l1.y+(l2.y-l1.y)*t;

   ret.z=l1.z+(l2.z-l1.z)*t;

   return ret;

}

 

 

//计算两平面交线,注意事先判断是否平行,并保证三点不共线!

line3 intersection(plane3 u,plane3 v)

{

   line3 ret;

   ret.a=parallel(v.a,v.b,u.a,u.b,u.c)?intersection(v.b,v.c,u.a,u.b,u.c):intersection(v.a,v.b,u.a,u.b,u.c);

   ret.b=parallel(v.c,v.a,u.a,u.b,u.c)?intersection(v.b,v.c,u.a,u.b,u.c):intersection(v.c,v.a,u.a,u.b,u.c);

   return ret;

}

line3 intersection(point3 u1,point3u2,point3 u3,point3 v1,point3 v2,point3 v3)

{

   line3 ret;

   ret.a=parallel(v1,v2,u1,u2,u3)?intersection(v2,v3,u1,u2,u3):intersection(v1,v2,u1,u2,u3);

   ret.b=parallel(v3,v1,u1,u2,u3)?intersection(v2,v3,u1,u2,u3):intersection(v3,v1,u1,u2,u3);

   return ret;

}

 

//点到直线距离

double ptoline(point3 p,line3 l) {

   return vlen(xmult(subt(p,l.a),subt(l.b,l.a)))/dist(l.a,l.b);

}

double ptoline(point3 p,point3 l1,point3l2) {

   return vlen(xmult(subt(p,l1),subt(l2,l1)))/dist(l1,l2);

}

 

//点到平面距离

double ptoplane(point3 p,plane3 s)

{

   return fabs(dmult(pvec(s),subt(p,s.a)))/vlen(pvec(s));

}

double ptoplane(point3 p,point3 s1,point3s2,point3 s3)

{

   return fabs(dmult(pvec(s1,s2,s3),subt(p,s1)))/vlen(pvec(s1,s2,s3));

}

 

//直线到直线距离

double linetoline(line3 u,line3 v)

{

   point3 n=xmult(subt(u.a,u.b),subt(v.a,v.b));

   return fabs(dmult(subt(u.a,v.a),n))/vlen(n);

}

double linetoline(point3 u1,point3u2,point3 v1,point3 v2)

{

   point3 n=xmult(subt(u1,u2),subt(v1,v2));

   return fabs(dmult(subt(u1,v1),n))/vlen(n);

}

 

 

//两直线夹角cos值

double angle_cos(line3 u,line3 v) {

   returndmult(subt(u.a,u.b),subt(v.a,v.b))/vlen(subt(u.a,u.b))/vlen(subt(v.a,v.b));

}

double angle_cos(point3 u1,point3 u2,point3v1,point3 v2) {

   returndmult(subt(u1,u2),subt(v1,v2))/vlen(subt(u1,u2))/vlen(subt(v1,v2));

}

 

//两平面夹角cos值

double angle_cos(plane3 u,plane3 v) {

   return dmult(pvec(u),pvec(v))/vlen(pvec(u))/vlen(pvec(v));

}

double angle_cos(point3 u1,point3 u2,point3u3,point3 v1,point3 v2,point3 v3) {

   returndmult(pvec(u1,u2,u3),pvec(v1,v2,v3))/vlen(pvec(u1,u2,u3))/vlen(pvec(v1,v2,v3));

}

 

//直线平面夹角sin值

double angle_sin(line3 l,plane3 s) {

   return dmult(subt(l.a,l.b),pvec(s))/vlen(subt(l.a,l.b))/vlen(pvec(s));

}

double angle_sin(point3 l1,point3 l2,point3s1,point3 s2,point3 s3) {

   returndmult(subt(l1,l2),pvec(s1,s2,s3))/vlen(subt(l1,l2))/vlen(pvec(s1,s2,s3));

}

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/152867.html

(0)
上一篇 2025-03-07 12:15
下一篇 2025-03-07 12:25

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信