home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / leda / src / plane / _polygon.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-09  |  8.4 KB  |  406 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  2.1.1                                                 11-15-1991
  4. +
  5. +
  6. +  _polygon.c
  7. +
  8. +
  9. +  Copyright (c) 1991  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15. #include <LEDA/plane.h>
  16. #include <math.h>
  17.  
  18. /*
  19. #ifndef __TURBOC__
  20. #include <LEDA/plane_alg.h>
  21. declare(edge_array,bool)
  22. #endif
  23. */
  24.  
  25.  
  26. //------------------------------------------------------------------------------
  27. // polygons
  28. //------------------------------------------------------------------------------
  29.  
  30.  
  31. polygon_rep::polygon_rep(list(segment) L) 
  32.   seg_list = L;
  33.   count = 1; 
  34.  }
  35.  
  36. polygon_rep::polygon_rep()         { count = 1; }
  37.  
  38. polygon::polygon()                 { ptr = new polygon_rep; }
  39. polygon::polygon(int)              { ptr = new polygon_rep; }
  40. polygon::polygon(polygon& P)       { ptr = P.ptr; ptr->count++; }
  41. polygon::polygon(ent x)            { ptr=(polygon_rep*)x; ptr->count++; }
  42. void polygon::clear()              { if (--(ptr->count)==0) delete ptr; }
  43.  
  44.  
  45. ostream& operator<<(ostream& out, const polygon& p) 
  46. { p.vertices().print();
  47.   return out;
  48.  } 
  49.  
  50. istream& operator>>(istream& in,  polygon& p) 
  51. { list(point) L; 
  52.   L.read(); 
  53.   p = polygon(L); 
  54.   return in;
  55. }
  56.  
  57.  
  58. void polygon_check(list(segment)&);
  59.  
  60. polygon::polygon(list(point)& pl, bool check)
  61. { ptr = new polygon_rep;
  62.  
  63.   list_item it,it1;
  64.  
  65.   forall_list_items(it,pl)
  66.   { it1 = pl.cyclic_succ(it);
  67.     ptr->seg_list.append(segment(pl[it],pl[it1]));
  68.    }
  69.  
  70.   if (check) polygon_check(ptr->seg_list);
  71. }
  72.  
  73. list(point) polygon::vertices() const
  74. { list(point) result;
  75.   segment s;
  76.   forall(s,ptr->seg_list) result.append(s.start());
  77.   return result;
  78. }
  79.  
  80.  
  81.  
  82.  
  83. void polygon_check(list(segment)& seg_list)
  84. {  if (seg_list.length() < 3) 
  85.      error_handler(1,"polygon: must be simple");
  86.  
  87. /*
  88. #ifndef __TURBOC__
  89.    list(point) L;
  90.    SWEEP_SEGMENTS(seg_list,L);
  91.  
  92.   if (L.length() != seg_list.length())
  93.    error_handler(1,"polygon: must be simple");
  94. #endif
  95. */
  96.  
  97.   list_item it;
  98.  
  99.   double angle = 0;
  100.  
  101.   forall_list_items(it,seg_list)
  102.   { list_item succ = seg_list.cyclic_succ(it);
  103.     segment s1 = seg_list[it];
  104.     segment s2 = seg_list[succ];
  105.     angle += s1.angle(s2);
  106.    }
  107.  
  108.   if (angle > 0)
  109.    error_handler(1,"polygon: point list must be clockwise oriented.");
  110. }
  111.  
  112. polygon polygon::translate(double alpha, double d)
  113. { list(point) L;
  114.   segment s;
  115.   forall(s,ptr->seg_list) L.append(s.start().translate(alpha,d));
  116.   return polygon(L,false);
  117. }
  118.  
  119. polygon polygon::translate(const vector& v)
  120. { list(point) L;
  121.   segment s;
  122.   forall(s,ptr->seg_list) L.append(s.start().translate(v));
  123.   return polygon(L,false);
  124. }
  125.  
  126. polygon polygon::rotate(point origin, double alpha)
  127. { list(point) L;
  128.   segment s;
  129.   forall(s,ptr->seg_list) L.append(s.start().rotate(origin,alpha));
  130.   return polygon(L,false);
  131. }
  132.  
  133. polygon polygon::rotate(double alpha)
  134. { return rotate(point(0,0),alpha);
  135.  }
  136.  
  137.  
  138. /*
  139.  
  140. bool polygon::inside(point p)
  141. {
  142.   line l(p,M_PI_2);  // vertical line through p
  143.  
  144.   int count = 0;
  145.  
  146.   segment s;
  147.   forall(s,ptr->seg_list)
  148.   { point q;
  149.     if (!l.intersection(s,q)) continue;
  150.     if (q.ycoord() < p.ycoord()) continue;
  151.     if (q == s.start())  continue;
  152.     if (q == s.end())  continue;
  153.     count++ ;
  154.    }
  155.  
  156.   list(point) plist = vertices();
  157.  
  158.   list_item i = plist.first();;
  159.  
  160.   forall_items(i,plist)
  161.   { 
  162.     point q = plist[i];
  163.  
  164.     if (q==p) return true;
  165.  
  166.     if (q.xcoord() == p.xcoord() && q.ycoord() > p.ycoord())
  167.     { list_item i0 = plist.cyclic_pred(i);
  168.       list_item i1 = plist.cyclic_succ(i);
  169.       point q0 = plist[i0];
  170.       point q1 = plist[i1];
  171.  
  172.       if (q0.xcoord() < p.xcoord() && q1.xcoord() > p.xcoord()) count++;
  173.       if (q0.xcoord() > p.xcoord() && q1.xcoord() < p.xcoord()) count++;
  174.  
  175.      }
  176.  
  177.    }
  178.  
  179.    return count%2;
  180.  
  181. }
  182.  
  183. */
  184.  
  185.  
  186.  
  187. bool polygon::inside( point p)
  188. {
  189.   line l(p,M_PI_2);  // vertical line through p
  190.  
  191.   int count = 0;
  192.  
  193.   segment s;
  194.   forall(s,ptr->seg_list)
  195.   { point q;
  196.     if (!l.intersection(s,q)) continue;
  197.     if (q.ycoord() < p.ycoord()) continue;
  198.     if (q == s.start())  continue;
  199.     if (q == s.end())  continue;
  200.     count++ ;
  201.    }
  202.  
  203.   list(point) plist = vertices();
  204.  
  205.   list_item i0 = plist.first();
  206.  
  207.   while (plist[i0].xcoord() == p.xcoord())  i0 = plist.cyclic_pred(i0);
  208.  
  209.   list_item i = plist.cyclic_succ(i0);
  210.  
  211.   for(;;)
  212.   { 
  213.     while ( i != i0 && (plist[i].xcoord() != p.xcoord() || 
  214.                         plist[i].ycoord() < p.ycoord()    )  )
  215.        i = plist.cyclic_succ(i);
  216.  
  217.     if (i==i0) break;
  218.  
  219.     point q  = plist[i];
  220.     point q0 = plist[plist.cyclic_pred(i)];
  221.  
  222.     while ((plist[i].xcoord()==p.xcoord()) && (plist[i].ycoord() >= p.ycoord()))
  223.     { if (plist[i]==p) return true;
  224.       i = plist.cyclic_succ(i);
  225.      }
  226.  
  227.     point q1 = plist[i];
  228.  
  229.      if (q0.xcoord() < p.xcoord() && q1.xcoord() > p.xcoord()) count++;
  230.       if (q0.xcoord() > p.xcoord() && q1.xcoord() < p.xcoord()) count++;
  231.  
  232.    }
  233.  
  234.    return count%2;
  235.  
  236. }
  237.  
  238. bool polygon::outside(point p) { return !inside(p); }
  239.  
  240.  
  241. list(point) polygon::intersection(segment s)
  242. { list(point) result;
  243.   segment t;
  244.   point p;
  245.  
  246.   forall(t,ptr->seg_list) 
  247.     if (s.intersection(t,p))
  248.      if (result.empty()) result.append(p);
  249.      else if (p != result.tail() ) result.append(p);
  250.  
  251.   return result;
  252. }
  253.  
  254.  
  255. list(point) polygon::intersection(line l)
  256. { list(point) result;
  257.   segment t;
  258.   point p;
  259.  
  260.   forall(t,ptr->seg_list) 
  261.     if (l.intersection(t,p))
  262.      if (result.empty()) result.append(p);
  263.      else if (p != result.tail() ) result.append(p);
  264.  
  265.   return result;
  266. }
  267.  
  268.  
  269. // intersection with polygon
  270. /*
  271. #ifndef __TURBOC__
  272.  
  273. static bool polygon_test_edge(GRAPH(point,int)& G,edge& i1)
  274. { node v = G.target(i1);
  275.  
  276.   edge e,i2=nil,o1=nil,o2=nil;
  277.  
  278.   forall_adj_edges(e,v)
  279.     if (e != i1)
  280.     { if (v==target(e)) i2 = e;
  281.       else if (G[e]== G[i1]) o1 = e;
  282.            else o2 = e;
  283.      }
  284.  
  285.   if (i2==nil) return false;
  286.  
  287.   segment si1(G[source(i1)],G[v]);
  288.   segment si2(G[v],G[source(i2)]);
  289.   segment so2(G[v],G[target(o2)]);
  290.  
  291.   double alpha = si1.angle(si2);
  292.   double beta  = si1.angle(so2);
  293.  
  294.   return (alpha > beta);
  295.  
  296. }
  297.  
  298.  
  299.  
  300. static edge polygon_switch_edge(GRAPH(point,int)& G,edge i1)
  301. { node v = G.target(i1);
  302.  
  303.   edge e,i2=nil,o1=nil,o2=nil;
  304.  
  305.   forall_adj_edges(e,v)
  306.     if (e != i1)
  307.     { if (v==target(e)) i2 = e;
  308.       else if (G[e]== G[i1]) o1 = e;
  309.            else o2 = e;
  310.      }
  311.  
  312.   if (i2==nil) return  o1;
  313.  
  314.   segment si1(G[source(i1)],G[v]);
  315.   segment si2(G[v],G[source(i2)]);
  316.   segment so1(G[v],G[target(o1)]);
  317.   segment so2(G[v],G[target(o2)]);
  318.  
  319.   double alpha = si1.angle(si2);
  320.   double beta  = si1.angle(so2);
  321.   double gamma = si1.angle(so1);
  322.  
  323.   if (alpha < beta) cout << "error: alpa < beta!!\n";
  324.  
  325.   if (gamma >= beta) return o2;
  326.   else return o1;
  327.  
  328. }
  329.  
  330. #endif
  331. */
  332.  
  333. list(polygon) polygon::intersection(polygon P)
  334. {
  335.  
  336.   list(polygon) result;
  337.  
  338. /*
  339. #ifndef __TURBOC__
  340.  
  341.   GRAPH(point,int) SUB;
  342.  
  343.   SWEEP_SEGMENTS(segments(),P.segments(),SUB);
  344.  
  345.   int N = SUB.number_of_nodes();
  346.  
  347.   if (N < size() + P.size())
  348.    error_handler(1,"polygon: sorry, internal error in intersection");
  349.  
  350.   if (N == size() + P.size())
  351.   { // no intersections between edges of (*this) and P
  352.     // check for inclusion
  353.  
  354.     segment s1 = ptr->seg_list.head();
  355.     segment s2 = P.ptr->seg_list.head();
  356.     point   p1 = s1.start();
  357.     point   p2 = s2.start();
  358.  
  359.     if (P.inside(p1))                     // (*this) is conained in P
  360.       result.append(*this);
  361.     else
  362.       if (inside(p2))                     // P is conained in (*this)
  363.         result.append(P);                   
  364.  
  365.  
  366.     return result;
  367.  
  368.    }
  369.  
  370.   SUB.make_undirected();
  371.  
  372.   edge e;
  373.  
  374.   list(point) PL;
  375.  
  376.   edge_array(bool) marked(SUB,false);
  377.  
  378.   forall_edges(e,SUB) 
  379.   { edge f;
  380.     if (!marked[e]  && SUB.outdeg(target(e))>1) 
  381.       if (polygon_test_edge(SUB,e))
  382.       { // new polygon found
  383.        marked[e] = true;
  384.        PL.append(SUB[source(e)]);
  385.        f = polygon_switch_edge(SUB,e);
  386.        while (f!=e)
  387.        { marked[f] = true;
  388.          PL.append(SUB[source(f)]);
  389.          f = polygon_switch_edge(SUB,f);
  390.         }
  391.        result.append(polygon(PL,false));
  392.        PL.clear();
  393.       }
  394.   }
  395.  
  396.  SUB.make_directed();
  397.  
  398. #endif
  399. */
  400.  
  401.  return result;
  402.  
  403. }
  404.