计算几何之线段、直线、圆

计算几何之线段、直线、圆
  1 #include < stdio.h >
  2 #include < math.h >
  3
  4 const   double  eps = 1e - 6 ;
  5
  6 // 点(x,y) 
  7 typedef  struct
  8 {
  9    double x,y;
 10}
 Point;
 11
 12 // 直线方程ax+by+c=0 
 13 typedef  struct
 14 {
 15    double a,b,c;
 16}
 Line;
 17
 18 // 圆的标准方程(x-center.x)^2+(y-center.y)^2=r^2
 19 typedef  struct
 20 {
 21    Point center;
 22    double r;
 23}
 Circle; 
 24
 25 // 浮点数符号函数 
 26 int  DblCmp( double  d)
 27 {
 28    if(fabs(d)<eps) return 0;
 29    else return d>0?1:-1;
 30}

 31
 32 // 线段AB的中点C
 33 Point MidPoint(Point A,Point B)
 34 {
 35    Point C;
 36    C.x=(A.x+B.x)/2;
 37    C.y=(A.y+B.y)/2;
 38    return C;
 39}
 
 40
 41 // 点A到点B的距离 
 42 double  Dist(Point A,Point B)
 43 {
 44    return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
 45}

 46
 47 // ∠ACB的弧度值 
 48 double  Angle(Point A,Point B,Point C)
 49 {
 50    double a,b,c;
 51    a=Dist(B,C);
 52    b=Dist(A,C);
 53    c=Dist(A,B);
 54    return acos((a*a+b*b-c*c)/(2*a*b));
 55}

 56
 57 // 二维向量a=(x1,y1)与b=(x2,y2)的叉积的数值 
 58 double  Det( double  x1, double  y1, double  x2, double  y2)
 59 {
 60    return x1*y2-x2*y1;
 61}

 62
 63 // 二维向量的叉积AB*AC的数值 
 64 double  Cross(Point A,Point B,Point C)
 65 {
 66    return Det(B.x-A.x,B.y-A.y,C.x-A.x,C.y-A.y);
 67}

 68
 69 // 二维向量a=(x1,y1)与b=(x2,y2)的点积
 70 double  DotDet( double  x1, double  y1, double  x2, double  y2)
 71 {
 72    return x1*x2+y1*y2;
 73}

 74
 75 // 二维向量的点积AB·AC 
 76 double  Dot(Point A,Point B,Point C)
 77 {
 78    return DotDet(B.x-A.x,B.y-A.y,C.x-A.x,C.y-A.y);
 79}

 80
 81 // 点A与B或C重合时为0,点A在BC内部时为-1,点A在BC外部时为1
 82 int  BetweenCmp(Point A,Point B,Point C)
 83 {
 84    return DblCmp(Dot(A,B,C));
 85}
 
 86
 87 // 线段AB,CD规范相交则返回1,并求交点P;不规范相交则返回2;没有交点则返回0
 88 int  SegsCross(Point A,Point B,Point C,Point D,Point  & P)
 89 {
 90   double s1,s2,s3,s4;
 91   int d1,d2,d3,d4;
 92   d1=DblCmp(s1=Cross(A,B,C));
 93   d2=DblCmp(s2=Cross(A,B,D));
 94   d3=DblCmp(s3=Cross(C,D,A));
 95   d4=DblCmp(s4=Cross(C,D,B));
 96   if(((d1^d2)==-2)&&((d3^d4)==-2))
 97   {
 98      P.x=(C.x*s2-D.x*s1)/(s2-s1);
 99      P.y=(C.y*s2-D.y*s1)/(s2-s1);
100      return 1;
101   }

102   if(((d1==0)&&(BetweenCmp(C,A,B)<=0))||
103        ((d2==0)&&(BetweenCmp(D,A,B)<=0))|| 
104        ((d3==0)&&(BetweenCmp(A,C,D)<=0))||
105        ((d4==0)&&(BetweenCmp(B,C,D)<=0)))
106        return 2;
107    else return 0;
108}

109
110 // 直线L1,L2相交则返回1,并求交点P;重合则返回2,平行则返回0;
111 int  LinesCross(Line L1,Line L2,Point  & P)
112 {
113    double d1=Det(L1.a,L1.b,L2.a,L2.b),d2=Det(L1.b,L1.c,L2.b,L2.c),d3=Det(L1.a,L1.c,L2.a,L2.c);
114    int x=DblCmp(d1),y=DblCmp(d2);
115    if(x==0&&y==0return 2;
116    else if(x==0&&y!=0return 0;
117    else
118    {
119        P.x=d2/d1;
120        P.y=-d3/d1;
121        return 1;
122    }

123}

124
125 // 两点式:AB构造直线L 
126 Line LineFromSegs(Point A,Point B)
127 {
128    Line L;
129    L.a=B.y-A.y;
130    L.b=A.x-B.x;
131    L.c=B.x*A.y-A.x*B.y;
132    return L; 
133}

134
135 // 点斜式:A及方位向量dir构造直线L 
136 Line LineFromPointAndSlope(Point A,Point dir)
137 {
138    Line L;
139    if(dir.x==0)
140    {
141        L.a=1;
142        L.b=0;
143        L.c=-A.x;
144    }

145    else 
146    {
147        double k=dir.y/dir.x;
148        L.a=k;
149        L.b=-1;
150        L.c=A.y-k*A.x;  
151    }
    
152    return L; 
153}

154
155 // 两点A,B构造垂直平分线L
156 Line PerbisecFromSegs(Point A,Point B)
157 {
158    Line AB=LineFromSegs(A,B),L;
159    Point C=MidPoint(A,B),dir;
160    dir.x=B.y-A.y;dir.y=A.x-B.x;
161    L=LineFromPointAndSlope(C,dir);
162    return L;
163}

164
165 // 三点A,B,C构造圆O
166 Circle CirFromPoints(Point A,Point B,Point C)
167 {
168    Circle O;
169    double c=Dist(A,B),ACB=Angle(A,B,C);
170    O.r=c/(2*sin(ACB));
171    Line DO=PerbisecFromSegs(A,B),EO=PerbisecFromSegs(B,C);
172    Point P;
173    if(LinesCross(DO,EO,P)==1) O.center=P;
174    return O; 
175}

你可能感兴趣的:(计算几何之线段、直线、圆)