基础几何知识及公式

放这边便于查找

1.1  注意

1. 注意舍入方式(0.5的舍入方向);防止输出-0. 
2. 几何题注意多测试不对称数据. 
3. 整数几何注意xmult和dmult是否会出界; 
符点几何注意eps的使用. 
4. 避免使用斜率;注意除数是否会为0. 
5. 公式一定要化简后再代入. 
6. 判断同一个2*PI域内两角度差应该是
   abs(a1-a2)<beta||abs(a1-a2)>pi+pi-beta; 
相等应该是
   abs(a1-a2)<eps||abs(a1-a2)>pi+pi-eps; 
7. 需要的话尽量使用atan2,注意:atan2(0,0)=0, 
   atan2(1,0)=pi/2,atan2(-1,0)=-pi/2,atan2(0,1)=0,atan2(0,-1)=pi. 
8. cross product = |u|*|v|*sin(a) 
   dot product = |u|*|v|*cos(a) 
9. (P1-P0)x(P2-P0)结果的意义: 
正: <P0,P1>在<P0,P2>顺时针(0,pi)内
负: <P0,P1>在<P0,P2>逆时针(0,pi)内
   0 : <P0,P1>,<P0,P2>共线,夹角为0或pi 
10. 误差限缺省使用1e-8! 

1.2  几何公式

三角形: 
1. 半周长 P=(a+b+c)/2 
2. 面积 S=aHa/2=absin(C)/2=sqrt(P(P-a)(P-b)(P-c)) 
3. 中线 Ma=sqrt(2(b^2+c^2)-a^2)/2=sqrt(b^2+c^2+2bccos(A))/2 
4. 角平分线 Ta=sqrt(bc((b+c)^2-a^2))/(b+c)=2bccos(A/2)/(b+c) 
5. 高线 Ha=bsin(C)=csin(B)=sqrt(b^2-((a^2+b^2-c^2)/(2a))^2) 
26 
6. 内切圆半径 r=S/P=asin(B/2)sin(C/2)/sin((B+C)/2) 
               =4Rsin(A/2)sin(B/2)sin(C/2)=sqrt((P-a)(P-b)(P-c)/P) 
               =Ptan(A/2)tan(B/2)tan(C/2) 
7. 外接圆半径 R=abc/(4S)=a/(2sin(A))=b/(2sin(B))=c/(2sin(C)) 
四边形: 
D1,D2为对角线,M对角线中点连线,A为对角线夹角
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)),P为半周长
正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. 弧长 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. 体积 V=Ah,A为底面积,h为高
2. 侧面积 S=lp,l为棱长,p为直截面周长
3. 全面积 T=S+2A 
棱锥: 
1. 体积 V=Ah/3,A为底面积,h为高
(以下对正棱锥) 
2. 侧面积 S=lp/2,l为斜高,p为底面周长
3. 全面积 T=S+A 
棱台: 
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 
27 
圆柱: 
1. 侧面积 S=2PIrh 
2. 全面积 T=2PIr(h+r) 
3. 体积 V=PIr^2h 
圆锥: 
1. 母线 l=sqrt(h^2+r^2) 
2. 侧面积 S=PIrl 
3. 全面积 T=PIr(l+r) 
4. 体积 V=PIr^2h/3 
圆台: 
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. 全面积 T=4PIr^2 
2. 体积 V=4PIr^3/3 
球台: 
1. 侧面积 S=2PIrh 
2. 全面积 T=PI(2rh+r1^2+r2^2) 
3. 体积 V=PIh(3(r1^2+r2^2)+h^2)/6 
球扇形: 
1. 全面积 T=PIr(2h+r0),h为球冠高,r0为球冠底面半径
2. 体积 V=2PIr^2h/3 

1.3  多边形

#include <stdlib.h> 
#include <math.h> 
#define MAXN 1000 
#define offset 10000 
#define eps 1e-8 
#define zero(x) (((x)>0?(x):-(x))<eps) 
#define _sign(x) ((x)>eps?1:((x)<-eps?2:0)) 
struct point{double x,y;}; 
struct line{point a,b;}; 
double xmult(point p1,point p2,point p0){ 
 return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); 
28 
} 
//判定凸多边形,顶点按顺时针或逆时针给出,允许相邻边共线
int is_convex(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],p[(i+2)%n],p[i]))]=0; 
 return s[1]|s[2]; 
} 
//判定凸多边形,顶点按顺时针或逆时针给出,不允许相邻边共线
int is_convex_v2(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],p[(i+2)%n],p[i]))]=0; 
 return s[0]&&s[1]|s[2]; 
} 
//判点在凸多边形内或多边形边上,顶点按顺时针或逆时针给出
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,int on_edge=1){ 
 point q2; 
 int i=0,count; 
 while (i<n) 
  for (count=i=0,q2.x=rand()+offset,q2.y=rand()+offset;i<n;i++) 
   if 
(zero(xmult(q,p[i],p[(i+1)%n]))&&(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) 
29 
    return on_edge; 
   else if (zero(xmult(q,q2,p[i]))) 
    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) 
    count++; 
 return count&1; 
} 
inline int opposite_side(point p1,point p2,point l1,point l2){ 
 return xmult(l1,p1,l2)*xmult(l1,p2,l2)<-eps; 
} 
inline int dot_online_in(point p,point l1,point l2){ 
 return zero(xmult(p,l1,l2))&&(l1.x-p.x)*(l2.x-p.x)<eps&&(l1.y-p.y)*(l2.y-p.y)<eps; 
} 
//判线段在任意多边形内,顶点按顺时针或逆时针给出,与边界相交返回1 
int inside_polygon(point l1,point l2,int n,point* p){ 
 point t[MAXN],tt; 
 int i,j,k=0; 
 if (!inside_polygon(l1,n,p)||!inside_polygon(l2,n,p)) 
  return 0; 
 for (i=0;i<n;i++) 
  if (opposite_side(l1,l2,p[i],p[(i+1)%n])&&opposite_side(p[i],p[(i+1)%n],l1,l2)) 
   return 0; 
  else if (dot_online_in(l1,p[i],p[(i+1)%n])) 
   t[k++]=l1; 
  else if (dot_online_in(l2,p[i],p[(i+1)%n])) 
   t[k++]=l2; 
  else if (dot_online_in(p[i],l1,l2)) 
   t[k++]=p[i]; 
 for (i=0;i<k;i++) 
  for (j=i+1;j<k;j++){ 
   tt.x=(t[i].x+t[j].x)/2; 
   tt.y=(t[i].y+t[j].y)/2; 
   if (!inside_polygon(tt,n,p)) 
    return 0;    
  } 
 return 1; 
} 
point intersection(line u,line v){ 
30 
 point 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; 
 return ret; 
} 
point barycenter(point a,point b,point c){ 
 line u,v; 
 u.a.x=(a.x+b.x)/2; 
 u.a.y=(a.y+b.y)/2; 
 u.b=c; 
 v.a.x=(a.x+c.x)/2; 
 v.a.y=(a.y+c.y)/2; 
 v.b=b; 
 return intersection(u,v); 
} 
//多边形重心
point barycenter(int n,point* p){ 
 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; 
} 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值