计算几何模板

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

}

【总结】计算几何模板相关推荐

  1. (转)计算几何模板 - kuangbin

    转自:https://kuangbin.github.io/2019/04/28/20190428/#more 二维几何 // `计算几何模板` const double eps = 1e-8; co ...

  2. 计算几何模板中的代码

    计算几何模板代码选自kuangbin 7 计算几何 7.1 二维几何 // `计算几何模板` const double eps = 1e-8; const double inf = 1e20; con ...

  3. 三维几何 --- 计算几何模板

    计算几何模板 全是纯干货,方法理解可查阅算法入门到进阶一书 ! #include <bits/stdc++.h>using namespace std; typedef long long ...

  4. 计算几何模板(大神整理)

    不知道出处,转载的转载... 计算几何模板 目录: 1.计算几何 2 1.1 注意 2 1.2几何公式 2 1.3 多边形 4 1.4多边形切割 7 1.5 浮点函数 8 1.6 面积 14 1.7球 ...

  5. 数论六之计算几何干货——计算几何模板解释全集 及 模板检验训练场

    文章目录 点和向量及运算 直线和线段 求解点到直线的距离/点在直线上 求解点到线段的距离/点在线段上 求解两条线段是否相交 求解两直线的交点 多边形 求解多边形面积 求解多边形重心 求解判断定点与多边 ...

  6. ZBT的计算几何模板

    Basic template 一个基础型模板包括一个向量的实现 DATE: 2015-06-01 #define op operator #define __ while #define _0 ret ...

  7. hdu 4667 Building Fence 计算几何模板

    1 //大白p263 2 #include <cmath> 3 #include <cstdio> 4 #include <cstring> 5 #include ...

  8. BNU校赛总决赛J 小白兔小灰兔 相交计算几何模板

    J 小白兔小灰兔 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K Special Judge, 64bit IO Format: %lld 题目描述 ...

  9. 二维几何基础大合集!《计算几何全家桶(一)》(基础运算、点、线、多边形、圆、网格)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的模板整合计划 目录 1.基本运算 1.1 判断正负函数(sgn) 1.2 点积(数量积.内积)(Dot) 1.3 向量积 ...

最新文章

  1. IOS开发基础知识--碎片39
  2. source tree常用功能
  3. leetcode201. 数字范围按位与
  4. 教程|YOLOX目标检测ncnn实现
  5. 【java】线程 ExecutorService 原理 源码 解释
  6. 把图标变成圆形的html_3组24个CSS3分享图标,可旋转和悬停
  7. 启动两个tomcat,两个端口,两个tomcat都启动时回显示端口被占用
  8. JavaScript 基本类型的装箱与拆箱
  9. PLIP--Linux 并口网络解决方法
  10. flash 实例教程
  11. 3.7V锂电池升压5V方案
  12. python三维方式显示灰度图像(已验证)
  13. Poi操作Excel,保留格式的情况下插入行
  14. Java由浅入深,考试or面试专用(自我整理)
  15. Linux上一键部署KMS
  16. Yocto新增一个hello程序
  17. 华为无线wifi设备连接到服务器,华为wifi路由器安装上网的方法
  18. Intellij IDEA 去除警告波浪线(Weak Warning)
  19. 从小学到高中,一个程序猿的独白
  20. (universal Image Loader)UIL 使用 (1)

热门文章

  1. Linux typeset用法
  2. 大数据分析案例-基于随机森林算法探究影响人类寿命的因素
  3. ubuntu中伪分布式hadoop搭建
  4. 你的企业有这样的网络安全盲点吗?
  5. 想做次世代三维建模师?先来提高自身美术基础
  6. 【TypeScript】从零开始玩转TypeScript - TypeScript中的接口
  7. delphi怎么获得文件服务器,delphi做web服务器
  8. Emscripten返回任意类型数据
  9. android布局置顶_[置顶] Android系统五大布局详解Layout
  10. Ubuntu系统安装后需要安装的软件包