home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / leda / prog / graphics / mulmuley.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-15  |  15.6 KB  |  716 lines

  1.  
  2. //------------------------------------------------------------------------------
  3. //
  4. // Mulmuley's randomized algorithm to compute the intersections of a set of 
  5. // line segments 
  6. //
  7. // implemented by Bettina Preis
  8. //
  9. //------------------------------------------------------------------------------
  10.  
  11.  
  12. /*       1.    read segments
  13.          2.    build frame
  14.          3.    draw vertical attachments through all endpoints
  15.          4.    randomly select segment
  16.          5.    start on a endpoint,
  17.                repeat
  18.                   FACE TRAVERSAL
  19.                and
  20.                   FACE TRANSITION,
  21.                until other endpoint reached
  22.          6.    repeat 4. and 5., until all segments are processed
  23. */
  24.  
  25.  
  26.  
  27. #include <LEDA/list.h>
  28. #include <LEDA/graph.h>
  29. #include <LEDA/plane.h>
  30. #include <LEDA/d_array.h>
  31. #include <LEDA/window.h>
  32.  
  33. #define eps 0.00001
  34.  
  35. window W;
  36.  
  37. double xmin, xmax, ymin, ymax;
  38.  
  39. edge frame_e_lower,frame_e_upper;
  40.  
  41.  
  42. int WAIT = 300;
  43.  
  44. void DRAW_EDGE(point a, point b, color c = black) { W.draw_edge(a,b,c); }
  45. void DRAW_EDGE(segment s, color c = black)        { W.draw_edge(s,c); }
  46.  
  47. /*****************************************************************************/
  48.  
  49. /* 
  50.     declared in plane.h:
  51.  
  52. int compare(point& p1,point& p2)
  53. {
  54.   int result = compare(p1.xcoord(),p2.xcoord());
  55.   if (result == 0)
  56.     return compare(p1.ycoord(),p2.ycoord());
  57.   else return result;
  58. }
  59. */
  60.  
  61. /*****************************************************************************/
  62.  
  63. int compare(segment& s1,segment& s2)
  64. {
  65.   int result = compare(s1.start(),s2.start());
  66.   return result;
  67. }
  68.  
  69. /*****************************************************************************/
  70.  
  71. int cmp_points(point& p1,point& p2)
  72. { return compare(p1.xcoord(),p2.xcoord()); }
  73.  
  74. /*****************************************************************************/
  75.  
  76. declare2(GRAPH,point,segment);
  77. GRAPH(point,segment) G;
  78.  
  79. declare2(d_array,point,node);
  80. d_array(point,node) node_of;
  81.  
  82. /*****************************************************************************/
  83.  
  84. struct frame 
  85. {
  86.   point a;              // left lower corner
  87.   point b;              // right upper corner
  88. };
  89.  
  90. frame Fr;
  91.  
  92. /*****************************************************************************/
  93.  
  94. node new_node(point p)
  95. {
  96.   node_of[p] = G.new_node(p);
  97.   return node_of[p];
  98. }
  99.  
  100. /*****************************************************************************/
  101.  
  102. void wait()
  103. {
  104.   for (int i=1;i<1000*WAIT;i++) {}
  105. }
  106.  
  107. /*****************************************************************************/
  108.  
  109. void frame_max(double wert,char ch)
  110.   // adapt frame frontiers to the read segments
  111.  
  112.   if (ch == 'x')
  113.   { 
  114.     if(wert<xmin)      xmin=wert;
  115.     else 
  116.       if(wert>xmax)    xmax=wert;
  117.   }
  118.   else
  119.   {
  120.     if(wert<ymin)      ymin=wert;
  121.     else 
  122.       if(wert>ymax)    ymax=wert;
  123.   }
  124. }
  125.  
  126. /*****************************************************************************/
  127.  
  128. void build_frame(double x1, double x2, double y1, double y2,frame& F)
  129. {
  130.   // build frame from frame frontiers 
  131.   edge edg;
  132.   point p1(x1,y1); 
  133.   point p2(x2,y1);
  134.   point p3(x2,y2);
  135.   point p4(x1,y2);
  136.   node kn1 = G.new_node(p1); W.draw_filled_node(x1,y1);
  137.   node kn2 = G.new_node(p2); W.draw_filled_node(x2,y1);
  138.   node kn3 = G.new_node(p3); W.draw_filled_node(x2,y2);
  139.   node kn4 = G.new_node(p4); W.draw_filled_node(x1,y2);
  140.   segment seg = segment(p1,p2);
  141.   frame_e_lower = G.new_edge(kn1, kn2, seg);
  142.   DRAW_EDGE(p1,p2);
  143.           seg = segment(p2,p3);
  144.           edg = G.new_edge(kn2, kn3, seg);
  145.   DRAW_EDGE(p2,p3);
  146.           seg = segment(p3,p4);
  147.   frame_e_upper = G.new_edge(kn3, kn4, seg);
  148.   DRAW_EDGE(p3,p4);
  149.           seg = segment(p4,p1);
  150.           edg = G.new_edge(kn4, kn1, seg);
  151.   DRAW_EDGE(p4,p1);
  152.   F.a = p1;
  153.   F.b = p3;
  154. }
  155.  
  156. /*****************************************************************************/
  157.  
  158. bool vertical(segment seg)
  159. {
  160.   /* true, if segment vertical
  161.      false, if not              */
  162.  
  163.   double diff = seg.xcoord1() - seg.xcoord2();
  164.  
  165.   return (fabs(diff) < eps);
  166. }
  167.  
  168. /*****************************************************************************/
  169.  
  170. void make_vertical_attachment(point pkt,edge e_lower,edge e_upper)
  171. {
  172.   /* adds the endpoint and the vertical edges from the endpoint to the frame 
  173.      and vice versa to the graph
  174.      furthermore, splits the upper and lower frame edges on the points of
  175.      attachment                                                             
  176.   */
  177.  
  178.   point p1,p2;
  179.   segment seg;
  180.   node kn,kn1,kn2;
  181.   edge edg;
  182.   
  183.   kn = new_node(pkt);
  184.   W.draw_filled_node(pkt);
  185.  
  186.   p1=point(pkt.xcoord(),Fr.b.ycoord());
  187.   kn1 = G.new_node(p1);              // upper node of attachment
  188.   W.draw_filled_node(p1);
  189.  
  190.   p2 = point(pkt.xcoord(),Fr.a.ycoord());
  191.   kn2 = G.new_node(p2);              // lower node of attachment
  192.   W.draw_filled_node(p2);
  193.  
  194.  
  195.   // new vertical edges
  196.  
  197.   seg = segment(p1,pkt);
  198.   edg = G.new_edge(kn1,kn,seg);
  199.   DRAW_EDGE(p1,pkt);
  200.  
  201.   seg = segment(pkt,p2);
  202.   edg = G.new_edge(kn,kn2,seg);
  203.   DRAW_EDGE(pkt,p2);
  204.  
  205.   seg = segment(p2,pkt);
  206.   edg = G.new_edge(kn2,kn,seg);
  207.   DRAW_EDGE(p2,pkt);
  208.   
  209.   seg = segment(pkt,p1);
  210.   edg = G.new_edge(kn,kn1,seg);
  211.   DRAW_EDGE(pkt,p1);
  212.  
  213.   wait();
  214.  
  215.   // new upper frame edges :
  216.  
  217.   DRAW_EDGE(G[e_upper],white);
  218.   seg = segment(p1,G[e_upper].end());
  219.   edg = G.new_edge(kn1,G.target(e_upper),seg);
  220.   DRAW_EDGE(p1,G[G.target(e_upper)]);
  221.   seg = segment(G[e_upper].start(),p1);
  222.   edg = G.new_edge(G.source(e_upper),kn1,seg);
  223.   DRAW_EDGE(G[G.source(e_upper)],p1);
  224.   G.del_edge(e_upper);
  225.   frame_e_upper = edg;
  226.  
  227.   wait();
  228.  
  229.   // new lower frame edges :
  230.  
  231.   DRAW_EDGE(G[e_lower],white);
  232.   seg = segment(G[e_lower].start(),p2);
  233.   edg = G.new_edge(G.source(e_lower),kn2,seg);
  234.   DRAW_EDGE(G[G.source(e_lower)],p2);
  235.   seg = segment(p2,G[e_lower].end());
  236.   edg = G.new_edge(kn2,G.target(e_lower),seg);
  237.   DRAW_EDGE(p2,G[G.target(e_lower)]);
  238.   G.del_edge(e_lower);
  239.   frame_e_lower = edg;
  240.  
  241.   wait();
  242. }
  243.  
  244. /*****************************************************************************/
  245.  
  246. void insert_in_edge(node kn,edge edg,edge& f_edge,edge& s_edge)
  247. {
  248.   /* split edge edg on node kn into two edges f_edge (first edge) 
  249.      and s_edge (second edge)  
  250.   */
  251.  
  252.   segment f_seg,s_seg;
  253.  
  254.   f_seg = segment(G[G.source(edg)],G[kn]);
  255.   f_edge = G.new_edge(G.source(edg),kn,f_seg);
  256.   DRAW_EDGE(f_seg);
  257.   
  258.   wait();
  259.  
  260.   s_seg = segment(G[kn],G[G.target(edg)]);
  261.   s_edge = G.new_edge(kn,G.target(edg),s_seg);
  262.   DRAW_EDGE(s_seg);
  263.  
  264.   wait();
  265.  
  266.   G.del_edge(edg);
  267. }
  268.  
  269. /*****************************************************************************/
  270.  
  271. point face_traversal(segment seg, edge edg, edge& succ_e, edge& pred_e)
  272. {
  273.   /* travelling through a face until the intersection 
  274.      between the segment and a face border is found 
  275.      succ_e is the intersected face border
  276.      pred_e is the predecessor border of succ_edge
  277.   */
  278.  
  279.   point inter;
  280.   double angl;
  281.   double min_angle;
  282.   edge edg2;
  283.  
  284.  
  285.   do 
  286.   {
  287.     min_angle = M_PI;
  288.     forall_adj_edges(edg2,G.target(edg))
  289.     { 
  290.       // angle between edg2 and edg
  291.       segment s = G[edg2];
  292.       segment t = G[edg];
  293.  
  294.       angl = s.angle(t);
  295.  
  296. //      angl = G[edg2].angle(G[edg]);
  297.  
  298.       if ((angl > -M_PI) && (angl <= min_angle))
  299.       {
  300.         min_angle = angl;
  301.         succ_e = edg2;
  302.       }
  303.     }
  304.     pred_e = edg;
  305.     edg = succ_e;
  306.   } 
  307.   while (! seg.intersection(G[succ_e],inter)); 
  308.   return inter;
  309. }
  310.  
  311. /*****************************************************************************/
  312.  
  313. edge face_transition(segment seg, edge edg)
  314. {
  315.   /* find next face that must be traversed
  316.      return first border for next face_traversal   */
  317.   
  318.   double angl;
  319.   point inter;
  320.   edge succ_edge, edg2;
  321.   edge return_edge = nil;
  322.   edge corner_edge = nil;
  323.   edge act_edge = nil;
  324.   
  325.   do 
  326.   { 
  327.     succ_edge = nil;
  328.     edg2 = G.first_adj_edge(G.target(edg));
  329.  
  330.     for (;;)
  331.     {
  332.       angl = G[edg2].angle(G[edg]);
  333.       double diff = fabs(angl) - M_PI;
  334.       if (fabs(diff) < eps)
  335.       { 
  336.         return_edge = edg2;
  337.         break;
  338.       }
  339.       if (fabs(angl) < eps)
  340.         succ_edge = edg2; 
  341.       edg2 = G.adj_succ(edg2);
  342.     }
  343.     edg = succ_edge;
  344.  
  345.   } while (return_edge == nil);
  346.  
  347.   act_edge = return_edge;
  348.  
  349.   while(! seg.intersection(G[act_edge],inter))
  350.   {
  351.     edg2 = G.first_adj_edge(G.target(edg));
  352.     while (edg2 != nil)
  353.     { 
  354.       angl = G[edg2].angle(G[act_edge]);
  355.       if (fabs(angl) < eps )
  356.       {
  357.         act_edge = edg2;
  358.         break;
  359.       }
  360.       edg2 = G.adj_succ(edg2);
  361.     }
  362.   }
  363.  
  364.   return act_edge;
  365. }
  366.         
  367. /*****************************************************************************/
  368.  
  369. void delete_edges(list(edge)& e_list)
  370. {
  371.   // deletes upper vertical attachments
  372.  
  373.   list_item l_it;
  374.   edge edg;
  375.  
  376.   l_it = e_list.first();
  377.  
  378.   while (l_it != nil)
  379.   {
  380.     edg =  e_list.del(l_it);
  381.     G.del_edge(edg);
  382.     l_it = e_list.first();
  383.   }
  384. }
  385.  
  386. /*****************************************************************************/
  387. /*****************************************************************************/
  388.  
  389. list(point) fmul(list(segment)& L)
  390. {
  391.   /* for all segments : xcoord of first endpoint is smaller then
  392.                           xcoord of second endpoint                          */ 
  393.  
  394.   double angl;
  395.   point p,p_pred,p_succ,point_of_inter;
  396.   list_item l_it;
  397.   list(point) p_list,inter_p_list;
  398.   list(edge) edg_list;
  399.   segment seg,seg1,seg2;
  400.   node start_node,kn;
  401.   edge start_edge, succ_edge, pred_edge, first_edge, first2_edge, second_edge, second2_edge, edg1, edg2, edg4, edg8;
  402.  
  403.   /* initialisation of xmin, xmax, ymin, ymax (frame frontiers)
  404.        by the first segment                                                  */
  405.   
  406.   seg = L.head();
  407.  
  408.   xmin = seg.xcoord1();
  409.   xmax = seg.xcoord2();
  410.   
  411.   double r1 = seg.ycoord1();
  412.   double r2 = seg.ycoord2();
  413.  
  414.   if (r1 < r2)
  415.   {
  416.     ymin = r1;
  417.     ymax = r2;
  418.   }
  419.   else
  420.   {
  421.     ymin = r2;
  422.     ymax = r1;
  423.   }
  424.  
  425.   // expand frame frontiers
  426.   forall(seg,L)
  427.   {
  428.     if (seg.vertical()) error_handler(1,"vertical segment");
  429.     
  430.     frame_max(seg.xcoord1(),'x');
  431.     frame_max(seg.ycoord1(),'y');
  432.     frame_max(seg.xcoord2(),'x');
  433.     frame_max(seg.ycoord2(),'y');
  434.   }
  435.  
  436.  
  437.   // initialisation of the frame
  438.   build_frame(xmin-1,xmax+1,ymin-1,ymax+1,Fr);
  439.  
  440.   wait();
  441.  
  442.   /* make a list of all endpoints */
  443.  
  444.   forall(seg,L)
  445.   {
  446.     p = seg.start();
  447.     l_it = p_list.append(p);
  448.     p = seg.end();
  449.     l_it = p_list.append(p);
  450.   }
  451.  
  452.   // sort endpoints from left to right 
  453.   p_list.sort(cmp_points);
  454.  
  455.   // initialisation of the first ("stripped") partition
  456.   forall(p,p_list)
  457.   {
  458.     make_vertical_attachment(p,frame_e_lower,frame_e_upper);
  459.  
  460.   }
  461.  
  462.  
  463.   // algorithm begins
  464.  
  465.   forall(seg,L)
  466.   {
  467.     p = seg.end();                         // endpoint to be inserted
  468.  
  469.     start_node = node_of[p];
  470.     start_edge = nil;
  471.     edg8 = G.first_adj_edge(start_node);
  472.     while (edg8 != nil)
  473.     {
  474.       if (G[edg8].ycoord1() < G[edg8].ycoord2())
  475.       {
  476.         start_edge = edg8;
  477.         break;
  478.       }
  479.       else
  480.         edg8 = G.adj_succ(edg8);
  481.     } 
  482.  
  483.  
  484.     do
  485.     { 
  486.       point_of_inter = face_traversal(seg,start_edge,succ_edge,pred_edge);
  487.  
  488.       if (point_of_inter != seg.start())
  489.       { 
  490.  
  491.         kn = G.new_node(point_of_inter);
  492.         W.draw_filled_node(point_of_inter);
  493.         start_edge = nil;
  494.  
  495.         insert_in_edge(kn,succ_edge,first_edge,second_edge);
  496.    
  497.  
  498.         // new edges through face
  499.     
  500.         seg1 = segment(G[start_node],point_of_inter);
  501.         edg1 = G.new_edge(start_node,kn,seg1);
  502.         DRAW_EDGE(seg1);
  503.  
  504.         wait();
  505.     
  506.         seg2 = segment(point_of_inter,G[start_node]);
  507.         edg2 = G.new_edge(kn,start_node,seg2);
  508.         DRAW_EDGE(seg2);
  509.      
  510.         wait();
  511.       }
  512.  
  513.       else
  514.       {
  515.         kn = node_of[seg.start()];
  516.  
  517.         // new edges through face
  518.     
  519.         seg1 = segment(G[start_node],seg.start());
  520.         edg1 = G.new_edge(start_node,kn,seg1);
  521.         DRAW_EDGE(seg1);
  522.  
  523.         wait();
  524.     
  525.         seg2 = segment(point_of_inter,G[start_node]);
  526.         edg2 = G.new_edge(kn,start_node,seg2);
  527.         DRAW_EDGE(seg2);
  528.      
  529.         wait();
  530.         break;
  531.       }
  532.  
  533.       edg4 = face_transition(seg,second_edge);
  534.  
  535.  
  536.       insert_in_edge(kn,edg4,first2_edge,second2_edge);
  537.  
  538.       start_edge = second2_edge;
  539.  
  540.  
  541.       if (vertical(G[start_edge]))
  542.       { 
  543.         // cut vertical attachment 
  544.  
  545.         angl = G[first_edge].angle(G[pred_edge]);
  546.         if (fabs(angl) > eps)
  547.         {
  548.           if (! node_of.defined(G[G.target(pred_edge)]))
  549.           {
  550.             // delete upper vert_att
  551.  
  552.             edg_list.append(first_edge);
  553.             edg_list.append(second2_edge);
  554.             DRAW_EDGE(G[first_edge],white);
  555.             DRAW_EDGE(G[second2_edge],white);
  556.  
  557.             wait();
  558.           }
  559.           else
  560.           {
  561.             // delete lower vert_att
  562.           
  563.             DRAW_EDGE(G[second_edge],white);
  564.             DRAW_EDGE(G[first2_edge],white);
  565.             G.del_edge(second_edge);
  566.             G.del_edge(first2_edge);
  567.  
  568.             wait();
  569.           }
  570.         }
  571.         else
  572.         {
  573.           // delete lower vert_att
  574.           
  575.           DRAW_EDGE(G[second_edge],white);
  576.           DRAW_EDGE(G[first2_edge],white);
  577.           G.del_edge(second_edge);
  578.           G.del_edge(first2_edge);
  579.           wait();
  580.         }
  581.       }  
  582.       else
  583.  
  584.         inter_p_list.append(point_of_inter);
  585.  
  586.       start_node = kn;
  587.  
  588.     } while (start_edge != nil); 
  589.  
  590.     delete_edges(edg_list);
  591.     edg_list.clear();
  592.   }
  593.  
  594.  
  595.   G.print();
  596.  
  597.   return inter_p_list;
  598. }
  599.  
  600. /*****************************************************************************/
  601. /*****************************************************************************/
  602.  
  603. main()
  604. {
  605.   int    input = 0; 
  606.   int    grid_width = 0;;
  607.   int    N = 10;
  608.   string file_name;
  609.  
  610.   double x1,y1,x2,y2;
  611.   point p,q;
  612.   segment seg;
  613.   list(segment) seg_list;
  614.  
  615.   panel P("Line Segment Intersection (Mulmuley)");
  616.  
  617.   P.choice_item("INPUT", input, "mouse","random","file");
  618.  
  619.   P.int_item("GRID", grid_width, 0,100,20);
  620.   P.int_item("#segments",N);
  621.   P.int_item("WAIT",WAIT,0,300);
  622.  
  623.   P.string_item("FILE",file_name);
  624.  
  625.   P.open();
  626.  
  627.   W.init(-1000,1000,-1000,grid_width);
  628.  
  629.  
  630.   /* make a list of line_segments */
  631.  
  632.   switch(input) {
  633.  
  634.  
  635.   case 0: { // mouse
  636.             W.set_line_style(dashed);
  637.         
  638.             while(W >> seg)
  639.             { if (seg.xcoord1() > seg.xcoord2())
  640.                     seg=segment(seg.end(),seg.start());
  641.               W.draw_segment(seg);
  642.               seg_list.append(seg);
  643.             }
  644.             W.set_line_style(solid);
  645.             break;
  646.           }
  647.  
  648.  
  649.   case 1: { // random
  650.             W.set_line_style(dashed);
  651.             init_random();
  652.             for(int i=0;i<N;i++)
  653.             { x1 = random(-900,-100);
  654.               y1 = random(-900, 900);
  655.               x2 = random( 100, 900);
  656.               y2 = random(-900, 900);
  657.        
  658.               p = point(x1,y1);
  659.               q = point(x2,y2);
  660.               seg = segment(p,q);
  661.               seg_list.append(seg);
  662.       
  663.               W.draw_segment(seg);
  664.             }
  665.             W.set_line_style(solid);
  666.             break;
  667.            }
  668.  
  669.   case 2: { // file 
  670.             file_istream F(file_name);
  671.       
  672.             double x_min=0,x_max=0,y_min=0;
  673.       
  674.             while (F >> x1 >> y1 >> x2 >> y2)
  675.             {
  676.               x_min = Min(x_min,x1);
  677.               x_max = Max(x_max,x2);
  678.               y_min = Min(y_min,y1);
  679.       
  680.               p = point(x1,y1);
  681.               q = point(x2,y2);
  682.               seg = segment(p,q);
  683.               seg_list.append(seg);
  684.               break;
  685.             }
  686.       
  687.             W.init(x_min-1,x_max+1,y_min-1);
  688.           }
  689.  
  690. }//switch
  691.    
  692.  
  693.  
  694.   W.set_node_width(4);
  695.  
  696.  
  697.   list(point) point_list = fmul(seg_list);
  698.  
  699.   point_list.print("point_list = ");
  700.   W.read_mouse();
  701.   
  702.   W.clear();
  703.  
  704.   forall(seg,seg_list) W.draw_segment(seg);
  705.  
  706.   forall(p,point_list) W.draw_filled_node(p);
  707.  
  708.   W.read_mouse();
  709.  
  710. }
  711.  
  712. /*****************************************************************************/
  713. /*****************************************************************************/
  714. /*****************************************************************************/
  715.