简单的计算几何

 已解决问题:

  判断点是否在线段上

  判断两线段是否相交

  判断点是否在多边形内

  判断线段、折线、多边形是否在多变形内

  判断上述是否在圆内

  计算上述与线段及直线的交点

  凸包

待解决:

  半平面交

  1 #include<ctime>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<vector>
  8 #include<stack>
  9 #include<queue>
 10 
 11 using namespace std;
 12 //================================ struct =================================
 13 struct V{
 14     double px,py;
 15     V operator - (const V c){
 16         V a;
 17         a.px = px - c.px,a.py = py - c.py;
 18         return a;
 19     }
 20     V operator + (const V c){
 21         V a;
 22         a.px = px + c.px,a.py = py + c.py;
 23         return a;
 24     }
 25     V operator * (const double c){
 26         V a = *this;
 27         a.px *= c,a.py *= c;
 28         return a;
 29     }
 30     V operator / (const double c){
 31         V a = *this;
 32         a.px /= c,a.py /= c;
 33         return a;
 34     }
 35     bool operator <= (const V c){
 36         //return px <= c.px && py <= c.py;
 37         return px*px + py*py <= c.px*c.px + c.py*c.py;
 38     }
 39     bool operator == (const V c){
 40         return px == c.px && py == c.py;
 41     }
 42     double MO2(){
 43         return px * px + py * py;
 44     }
 45     double DIS(V p1,V p2,int pa){
 46         if(pa == 1){
 47             return abs(py - p1.py);
 48         }
 49         if(pa == 2){
 50             return abs(px - p1.px);
 51         }
 52         if(pa == 0){
 53             double k = (p2.py-p1.py)/(p2.px-p1.px),x0,y0;
 54             x0 = (k*k * p1.px + k * (py - p1.py) + px) / (k*k + 1);
 55             y0 = k * (px - p1.px) + p1.py;
 56             return sqrt((px-x0)*(px-x0) + (py-y0)*(py-y0));
 57         }
 58     }
 59     double CP(V c){
 60         return px*c.py - py*c.px;
 61     }//cross product
 62     double DP(V c){
 63         return px*c.px + py*c.py;
 64     }//dot product
 65     bool min(V a,V b){
 66         if(b <= a) swap(a,b);
 67         return a <= *this;
 68     }
 69     bool max(V a,V b){
 70         if(a <= b) swap(a,b);
 71         return *this <= a;
 72     }
 73 };//vector
 74 
 75 struct L{
 76     V p1,p2;
 77     int p0;
 78 /*
 79     switch(p0){
 80     case 1: beeline
 81     case 2: segment
 82     case 3: ray
 83     }
 84 */
 85     int pa;
 86 /*
 87     switch(pa){
 88     case 1: parallel-y;
 89     case 2: parallel-x;
 90     case 0: k < oo && k != 0;
 91     }
 92 */
 93     double k;
 94     void getk(){
 95         if(p1.px == p2.px) pa = 1;
 96         else if(p1.py == p2.py) pa = 2;
 97         else pa = 0,k = (p1.py-p2.py) / (p1.px-p2.px);
 98     }
 99     bool IP(V q){
100         return q.min(p1,p2) && q.max(p1,p2);
101     }//in the ploygon of the line
102     bool PA(L c){
103         if(pa != c.pa) return false;
104         if(pa) return true;
105         else if(k == c.k) return true;
106         else return false;
107     }
108     bool CR(L c){
109         if((*this).PA(c)) return false;
110         V v1 = p2 - p1,v2 = c.p1 - p1,v3 = c.p2 - p1;
111         double exp = v1.CP(v2) * v1.CP(v3);
112         //if(v1.CP(v2) * v1.CP(v3) < 0) return true;
113         switch(p0){
114         case 1://B_S
115             return exp <= 0;
116             break;
117         case 2://S_S
118             return exp < 0;
119             break;
120         case 3://R_S
121             if(exp > 0) return false;
122             else if(!exp){
123                 V v = v1.CP(v2)? c.p2:c.p1;
124                 if(p1-v <= p2-v) return false;
125                 else return true;
126             }
127             else{
128                 V v4 = c.p1 - p2,v5 = c.p2 - p2;
129                 double s1 = abs(v2.CP(v3)),s2 = abs(v4.CP(v5));
130                 return s1 > s2;
131             }
132             break;
133         }
134     }//line cross
135 };//line
136 
137 struct BL{
138     vector<L> E;
139 };//broken line
140 
141 struct PL{
142     vector<L> E;
143 };//ploygon
144 
145 struct O{
146     V o;
147     double r;
148 };//circle
149 
150 //================================ data ===================================
151 double CP(V a,V b){
152     return a.px*b.py - a.py*b.px;
153 }//cross product
154 
155 double DP(V a,V b){
156     return a.px*b.px + a.py*b.py;
157 }//dot product
158 
159 double P_P_DIST(V a,V b){
160     return sqrt((a.px-b.px)*(a.px-b.px) + (a.py-b.py)*(a.py-b.py));
161 }//disdance for points
162 
163 double P_L_DIST(V a,L b){
164     double ret = a.DIS(b.p1,b.p2,b.pa);
165     if(b.p0 != 1){
166         ret = min(ret,P_P_DIST(a,b.p1));
167     }
168     if(b.p0 == 2){
169         ret = min(ret,P_P_DIST(a,b.p2));
170     }
171     return ret;
172 }//least distance for point to line(segment/beeline/ray)
173 
174 double P_BL_DIST(V p,BL bl){
175     double ret = oo;
176     for(int i = 0;i < bl.E.size();++ i){
177         ret = min(ret,P_L_DIST(p,bl.E[i]));
178     }
179     return ret;
180 }//least distance for point to broken line
181 
182 double P_PL_DIST(V p,PL pl){
183     double ret = oo;
184     for(int i = 0;i < pl.E.size();++ i){
185         ret = min(ret,P_L_DIST(p,pl.E[i]));
186     }
187     return ret;
188 }//least distance for point to ploygon
189 
190 double P_O_DIST(V p,O o){
191     return o.r - P_P_DIST(p,o.o);
192 }//least distance for point to circle
193 
194 double AREA(PL pl){
195     V v0 = pl.E[0].p1;
196     double ret = 0;
197     for(int i = 0;i < pl.E.size();++ i){
198         ret += v0.CP(pl.E[i].p2-pl.E[i].p1);
199         v0 = v0 + (pl.E[i].p2-pl.E[i].p1);
200     }
201     return ret;
202 }//the measure of area
203 
204 //================================= judge =================================
205 bool P_L_ON(V q,L p){
206     /*double x1 = p.p1.px,x2 = p.p2.px,y1 = p.p1.py,y2 = p.p2.py,
207         x0 = q.px,y0 = q.py;
208     if((!p.p0) && (!(x0 <= max(x1,x2) && x0 >= min (x1,x2) && y0 <= max(y1,y2) && y0 >= min(y1,y2))))
209       return false;*/
210     //if((!p.p0) && (!(q.min(p.p1,p.p2) && q.max(p.p1,p.p2)))) return false;
211     if((p.p0 == 2) && (!p.IP(q))) return false;
212     int pd = CP(p.p1-q,p.p2-q);
213     if(pd != 0) return false;
214     pd = DP(p.p1-q,p.p2-q);
215     if(pd <= 0) return true;
216     else{
217         if(p.p0 == 1) return true;
218         if(p.p0 == 2) return false;
219         if(p.p0 == 3){
220             if(p.p1-q <= p.p2-q) return false;
221             else return true;
222         }
223     }
224        //if(!CP(q-p.p1,p.p2-p.p1)) return true;
225        //else return false;
226 }//wheather a point is on a line(beeline/segment/ray)
227 
228 bool S_S_CR(L a,L b){
229     return (a.CR(b) && b.CR(a)) || ((P_L_ON(a.p1,b) || P_L_ON(a.p2,b) || P_L_ON(b.p1,a) || P_L_ON(b.p2,a))/* && ((a.p2-a.p1).DP(b.p1-a.p1) * (a.p2-a.p1).DP(b.p2-a.p1) == 0)*/);
230 }//segments' cross
231 
232 bool S_L_CR(L a,L b){
233     return b.CR(a);
234 }//segment and beeline's cross
235 
236 bool S_R_CR(L a,L b){
237     return b.CR(a);
238 }//segment and ray's cross
239 
240 bool P_PL_IN(V p,PL pl){
241     L o;
242     o.p1 = p,o.p2.px = p.px-1,o.p2.py = p.py,o.p0 = 3;
243     int cnt = 0;
244     for(int i = 0;i < pl.E.size();++ i){
245         if(P_L_ON(p,pl.E[i])) return true;
246         if(pl.E[i].pa != 1){
247             if(P_L_ON(pl.E[i].p1,o) || (P_L_ON(pl.E[i].p2,o))){
248                 V v1 = P_L_ON(pl.E[i].p1,o)? pl.E[i].p1:pl.E[i].p2,
249                     v2 = P_L_ON(pl.E[i].p1,o)? pl.E[i].p2:pl.E[i].p1;
250                 if(v1.py > v2.py) cnt ++;
251             }
252         }
253         else if(S_R_CR(pl.E[i],o)) cnt ++;
254     }
255     return cnt & 1;
256 }//point in ploygon
257 
258 bool S_PL_IN(L p,PL pl){
259     if(!(P_PL_IN(p.p1,pl) && P_PL_IN(p.p2,pl))) return false;
260     vector<V> v;
261     for(int i = 0;i < pl.E.size();++ i){
262         if(P_L_ON(p.p1,pl.E[i]) || P_L_ON(p.p2,pl.E[i])){
263             if(P_L_ON(p.p1,pl.E[i])) v.push_back(p.p1);
264             if(P_L_ON(p.p2,pl.E[i])) v.push_back(p.p2);
265         }
266         else if(P_L_ON(pl.E[i].p1,p) || P_L_ON(pl.E[i].p2,p)){
267             if(P_L_ON(pl.E[i].p1,p)) v.push_back(pl.E[i].p1);
268             if(P_L_ON(pl.E[i].p2,p)) v.push_back(pl.E[i].p2);
269         }
270         else if(p.CR(pl.E[i])) return false;
271     }
272     for(int i = 0;i < v.size() - 1;++ i){
273         if(!P_PL_IN((v[i] + v[i+1])/2,pl)) return false;
274     }
275     return true;
276 }//segment in ploygon
277 
278 bool BL_PL_IN(BL bl,PL pl){
279     for(int i = 0;i < bl.E.size();++ i){
280         if(!S_PL_IN(bl.E[i],pl)) return false;
281     }
282     return true;
283 }//broken line in ploygon
284 
285 bool PL_PL_IN(PL pl1,PL pl2){
286     for(int i = 0;i < pl1.E.size();++ i){
287         if(!S_PL_IN(pl1.E[i],pl2)) return false;
288     }
289     return true;
290 }//ploygon in ploygon
291 
292 bool O_PL_IN(O o,PL pl){
293     double dis = oo;
294     for(int i = 0;i < pl.E.size();++ i){
295         dis = min(dis,P_L_DIST(o.o,pl.E[i]));
296     }
297     return o.r <= dis;
298 }//circle in ploygon
299 
300 bool P_O_IN(V p,O o){
301     return (p-o.o).MO2() <= o.r * o.r;
302 }//point in circle
303 
304 bool S_O_IN(L s,O o){
305     return P_O_IN(s.p1,o) && P_O_IN(s.p2,o);
306 }//segment in circle
307 
308 bool BL_O_IN(BL bl,O o){
309     for(int i = 0;i < bl.E.size();++ i){
310         if(!P_O_IN(bl.E[i].p1,o)) return false;
311     }
312     return P_O_IN(bl.E[bl.E.size()-1].p2,o);
313 }//broken line in circle
314 
315 bool PL_O_IN(PL pl,O o){
316     for(int i = 0;i < pl.E.size();++ i){
317         if(!P_O_IN(pl.E[i].p1,o)) return false;
318     }
319     return true;
320 }//ploygon in circle
321 
322 bool O_O_IN(O o1,O o2){
323     if(o1.r > o2.r) return false;
324     else return o2.r-o1.r <= P_P_DIST(o1.o,o2.o);
325 }//circle in circle
326 
327 //================================= node ==================================
328 void P_O_ND(V p,O o,double &x,double &y){
329     if(p == o.o){
330         x = y = oo;
331         return;
332     }
333     L a;
334     double lth = P_O_DIST(p,o);
335     a.p1 = o.o,a.p2 = p;
336     a.getk();
337     if(a.pa == 1){
338         if(p.py > o.o.py) x = p.px,y = o.o.py + o.r;
339         else x = p.px,y = o.o.py - o.r;
340     }
341     else if(a.pa == 2){
342         if(p.px > o.o.px) y = p.py,x = o.o.px + o.r;
343         else y = p.py,x = o.o.px - o.r;
344     }
345     else{
346         double xp = o.r / sqrt(a.k*a.k + 1),yp = abs(a.k * xp);
347         x = o.o.px,y = o.o.py;
348         if(p.px > o.o.px) x += xp;
349         else x -= xp;
350         if(p.py > o.o.py) y += yp;
351         else y -= yp;
352     }
353 }//closest node of point and circle
354 
355 void sameL_S_S_ND(L a,L b,double &x,double &y){
356     V h = a.p1,v1,v2,v3,v4;
357     if(a.pa == 1) h.px += 100;
358     else if(a.pa == 2) h.py += 100;
359     else a.getk(),h.px += 100,h.py += 100 * a.k;
360     if(a.p1.MO2() > a.p2.MO2()) swap(a.p1,a.p2);
361     if(b.p1.MO2() > b.p2.MO2()) swap(b.p1,b.p2);
362     if(a.p2.MO2() > b.p2.MO2()) swap(a,b);
363     v1 = a.p1 - h,v2 = a.p2 - h,v3 = b.p1 - h,v4 = b.p2 - h;
364     double s1 = abs(CP(v1,v2)),s2 = abs(CP(v3,v4)),s3 = abs(CP(v1,v4));
365     if(s1 + s2 < s3) x = y = - oo;//no node
366     else if(s1 + s2 > s3) x = y = oo;//oo nodes
367     else x = a.p2.px,y = a.p2.py;
368 }//node of segments which are on the same beeline
369 
370 void S_SorB_ND(L a,L b,double &x,double &y){
371     if(!((b.p0 == 1 && S_L_CR(a,b))||(b.p0 == 2 && S_S_CR(a,b)))){
372         x = y = - oo;//no node
373         return;
374     }
375     if(a.pa == 1){
376         if(b.pa == 1){
377             if(b.p0 == 1) x = y = oo;//oo nodes
378             else sameL_S_S_ND(a,b,x,y);
379         }
380         else{
381             x = a.p1.px;
382             b.getk();
383             y = b.k * (x - b.p1.px) + b.p1.py;
384         }
385     }
386     else if(b.pa == 1){
387         x = b.p1.px;
388         a.getk();
389         y = a.k * (x - a.p1.px) + a.p1.py;
390     }
391     else if(a.pa == 2){
392         if(b.pa == 2){
393             if(b.p0 == 1) x = y = oo;//oo nodes
394             else sameL_S_S_ND(a,b,x,y);
395         }
396         else{
397             y = a.p1.py;
398             b.getk();
399             x = 1.0/a.k * (y - b.p1.py) + b.p1.px;
400         }
401     }
402     else if(b.pa == 2){
403         y = b.p1.py;
404         a.getk();
405         x = 1.0/b.k * (y - a.p1.py) + a.p1.px;
406     }
407     else{
408         a.getk(),b.getk();
409         if(a.k == b.k) sameL_S_S_ND(a,b,x,y);
410         else{
411             x = (a.k*a.p1.px - b.k*b.p1.px + b.p1.py - a.p1.px) / (a.k - b.k);
412             y = a.k * (x - a.p1.px) + a.p1.py;
413         }
414     }
415 }//node of segment and segment(or beeline)
416 
417 void SorB_BL_ND(L l,BL bl,V v[]){
418     int j = 1;
419     for(int i = 0;i < bl.E.size();++ i){
420         S_SorB_ND(l,bl.E[i],v[j].px,v[j].py);
421         if(v[j].px != oo && v[j].px != -oo)
422             j ++;
423     }    
424 }//node(s) of segment(or beeline) and broken line
425 
426 void SorB_PL_ND(L l,PL pl,V v[]){
427     int j = 1;
428     for(int i = 0;i < pl.E.size();++ i){
429         S_SorB_ND(l,pl.E[i],v[j].px,v[j].py);
430         if(v[j].px != oo && v[j].px != -oo)
431             j ++;
432     }
433 }//node(s) of segment(or beeline) and ploygon
434 
435 void SorB_O_ND(L l,O o,V v[]){
436     if(l.pa == 2 && P_O_IN(l.p1,o) && P_O_IN(l.p2,o)) return;
437     //L l0 = l;l0.pa = 1;
438     double dis = P_L_DIST(o.o,l);
439     V v1,v2;
440     if(dis > o.r) return;
441     if(l.p0 == 1){
442         double h = sqrt(o.r * o.r - dis * dis);
443         if(h == 0){
444             v[1].px = l.p1.px,v[1].py = o.o.py;
445         }
446         else{
447             v1.px = v2.px = l.p1.px;
448             v1.py = v2.py = o.o.py;
449             v1.py += h,v2.py -= h;
450             if(l.pa == 1){
451                 v[1] = v1,v[2] = v2;
452             }
453             else{
454                 if((P_O_IN(l.p1,o) && P_O_IN(l.p2,o))||(!P_O_IN(l.p1,o) && !P_O_IN(l.p2,o))) return;
455                 if(P_L_ON(v1,l) && P_L_ON(v2,l)){
456                     v[1] = v1,v[2] = v2;
457                 }
458                 else if(P_L_ON(v1,l)){
459                     v[1] = v1;
460                 }
461                 else if(P_L_ON(v2,l)){
462                     v[1] = v2;
463                 }
464             }
465         }
466     }
467     else if(l.p0 == 2){
468         double w = sqrt(o.r * o.r - dis * dis);
469         if(w == 0){
470             v[1].py = l.p1.py,v[1].px = o.o.px;
471         }
472         else{
473             v1.py = v2.py = l.p1.py;
474             v1.px = v2.px = o.o.px;
475             v1.px += w,v2.px -= w;
476             if(l.pa == 1){
477                 v[1] = v1,v[2] = v2;
478             }
479             else{
480                 if((P_O_IN(l.p1,o) && P_O_IN(l.p2,o))||(!P_O_IN(l.p1,o) && !P_O_IN(l.p2,o))) return;
481                 if(P_L_ON(v1,l) && P_L_ON(v2,l)){
482                     v[1] = v1,v[2] = v2;
483                 }
484                 else if(P_L_ON(v1,l)){
485                     v[1] = v1;
486                 }
487                 else if(P_L_ON(v2,l)){
488                     v[1] = v2;
489                 }
490             }
491         }
492     }
493     else{
494         l.getk();
495         double A = l.k * l.k + 1,B = 2 * (-l.k * l.p1.px + l.p1.py - o.o.py - o.o.px),C = (-l.k * l.p1.px + l.p1.py - o.o.py) * (-l.k * l.p1.px + l.p1.py - o.o.py) - o.r * o.r,D;// = 4 * ((-l.k * l.p1.px + l.p1.py - o.o.py - o.o.px) * (-l.k * l.p1.px + l.p1.py - o.o.py - o.o.px) - (l.k * l.k + 1) * ((-l.k * l.p1.px + l.p1.py - o.o.py) * (-l.k * l.p1.px + l.p1.py - o.o.py) - o.r * o.r));
496         D = B * B - 4 * A * C;
497         v1.px = (-B + sqrt(D))/(2*A),v1.py = l.k * (v1.px - l.p1.px) + l.p1.py;
498         v2.px = (-B - sqrt(D))/(2*A),v2.py = l.k * (v2.px - l.p1.px) + l.p1.py;
499         if(D == 0){
500             v[1] = v1;
501         }
502         else{
503             if(l.pa == 1){
504                 v[1] = v1,v[2] = v2;
505             }
506             else{
507                 if((P_O_IN(l.p1,o) && P_O_IN(l.p2,o))||(!P_O_IN(l.p1,o) && !P_O_IN(l.p2,o))) return;
508                 if(P_L_ON(v1,l) && P_L_ON(v2,l)){
509                     v[1] = v1,v[2] = v2;
510                 }
511                 else if(P_L_ON(v1,l)){
512                     v[1] = v1;
513                 }
514                 else if(P_L_ON(v2,l)){
515                     v[1] = v2;
516                 }
517             }
518         }
519     }
520 }//node(s) of segment(or beeline) and circle
521 
522 //============================ convex closure =============================
523 bool cmp(V a,V b){
524     return CP(a,b) > 0;
525 }
526 
527 stack<V,vector<V> > GCC(V src[],int n){
528     V p0 = src[1];
529     int o0 = 1;
530     for(int i = 2;i <= n;++ i){
531         if(p0.py != src[i].py){
532             p0 = p0.py < src[i].py? p0:(o0 = i,src[i]);
533         }
534         else p0 = p0.px < src[i].py? p0:(o0 = i,src[i]);
535     }
536     V tmp[maxn];
537     int j = 0;
538     for(int i = 1;i <= n;++ i){
539         if(i != o0){
540             tmp[++j] = src[i];
541         }
542     }
543     sort(tmp+1,tmp+n,cmp);
544     stack<V,vector<V> > S;
545     S.push(p0),S.push(tmp[1]),S.push(tmp[2]);
546     V ut = tmp[1];//ut: undertop
547     for(int i = 3;i < n;++ i){
548         while(CP(S.top() - ut,tmp[i] - S.top()) <= 0){
549             S.pop(),S.pop();
550             V tp = ut;ut = S.top();
551             S.push(tp);
552         }
553         S.push(tmp[i]);
554     }
555     return S;
556 }//get convex closure
557 //================================= main ==================================
558 const double OO = 1e-8;
559 const double oo = 1e9;
560 const int maxn = 10000;
561 
562 
563 
564 void init(){
565 }
566 
567 void work(){
568 }
569 
570 int main(){
571     init();
572     work();
573     return 0;
574 }
posted @ 2015-12-28 11:17  woodenhead  阅读(228)  评论(0编辑  收藏  举报