home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ledar34.zip / leda-r-3_4_tar / LEDA-3.4 / src / plane_alg / balaban.c < prev    next >
C/C++ Source or Header  |  1996-09-03  |  14KB  |  557 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA 3.4
  4. +
  5. +  balaban.c
  6. +
  7. +  This file is part of the LEDA research version (LEDA-R) that can be 
  8. +  used free of charge in academic research and teaching. Any commercial
  9. +  use of this software requires a license which is distributed by the
  10. +  LEDA Software GmbH, Postfach 151101, 66041 Saarbruecken, FRG
  11. +  (fax +49 681 31104).
  12. +
  13. +  Copyright (c) 1991-1996  by  Max-Planck-Institut fuer Informatik
  14. +  Im Stadtwald, 66123 Saarbruecken, Germany     
  15. +  All rights reserved.
  16. *******************************************************************************/
  17. #include <LEDA/list.h>
  18. #include <LEDA/slist.h>
  19. #include <LEDA/sortseq.h>
  20. #include <LEDA/map.h>
  21.  
  22. // Problem :
  23. // Find all $K$ intersecting pairs in a set $S$ consisting of $n$ straight-line 
  24. // segments in the plane.
  25.  
  26. // Algorithm :
  27. // Literature : Ivan J. Balanban ???? S.211 - 219
  28.  
  29. // The following implementation should make no assumptions about the input :
  30. // -  segments may have length zero                              
  31. // -  segments may be vertical                                   
  32. // -  end  and intersection points may have the same abscissae   
  33. // -  end  and intersection points may have the same coordinates 
  34.  
  35. typedef void (*rep_int_func) (const SEGMENT&, const SEGMENT&);
  36.  
  37.  
  38.  
  39. // |stairs| : pointer to an array that implements the "staircase recursion
  40. //            stack"
  41. //            $O(n)$ space
  42.  
  43. static SEGMENT*  stairs = 0;
  44.  
  45. // |StairCount| : integer that stores the number of stairs that currently 
  46. // stored in |stairs|
  47.  
  48. static int      StairCount = 0;
  49.  
  50.  
  51.  
  52. // Classes :
  53.  
  54. class STAIRCASE
  55. {  
  56.   int   bcount;
  57.   int   ecount;
  58.   
  59.   public :
  60.   
  61.   int   b;   
  62.   int   e;
  63.  
  64.   STAIRCASE(int p1, int p2) : bcount(StairCount), ecount(0), b(p1), e(p2) {}
  65.   
  66.   int    Count() const { return ecount; }
  67.   bool   empty() const { return ecount == 0; }
  68.  
  69.   SEGMENT& operator[] (int i) const { return stairs[bcount+i]; }
  70.   
  71.   void append(SEGMENT& s)
  72.   { stairs[++StairCount] = s;
  73.     ecount++;
  74.    }
  75.  
  76. };
  77.  
  78.  
  79.  
  80.  
  81.  
  82. // function prototyps :
  83.  
  84. void TreeSearch_nloghoch2n(slist<SEGMENT>& L, slist<SEGMENT>& I, int b, int e,
  85.                slist<SEGMENT>& R);
  86. void SearchInStrip(slist<SEGMENT>& L, slist<SEGMENT>& R, int b, int e);
  87.  
  88. void InnerIntPoints(const STAIRCASE& D, const slist<SEGMENT>& I);
  89. int  Loc(const STAIRCASE& D, const SEGMENT s);
  90. void ReportIntersection(const SEGMENT& s1, const SEGMENT& s2);
  91.  
  92. void Split(slist<SEGMENT>& L, STAIRCASE& D);
  93. void Lrs_from_Rls(slist<SEGMENT>& Rls, slist<SEGMENT>& Lrs, int c);
  94. void Merge(STAIRCASE& D, slist<SEGMENT>& R);
  95.  
  96. // GlobalVar
  97.  
  98. // |report_func| : function to report intersecting pairs
  99. static rep_int_func              report_func = 0;
  100.  
  101. // |original| : pointer to a map that associates each input segment with an 
  102. //              internally used segment, which is directed from left to rigth 
  103. //              or upwards
  104. //              $O(n)$ space 
  105. static map<SEGMENT,SEGMENT>*     original    = 0; 
  106.  
  107. // |init_points| : pointer to an array that stores the different endpoints
  108. //                 of the input segments ordered lexicographically
  109. //                 $O(n)$ space
  110. static POINT*    init_points = 0;
  111.  
  112. // |seg_queue| : list of internal segment sorted, using the ordering defined  
  113. //               by the function |compare2(const SEGMENT&, const SEGMENT&)| 
  114. //               $O(n)$ space
  115. static list<SEGMENT>    seg_queue;
  116.  
  117. static int compare2(const SEGMENT& s1, const SEGMENT& s2)
  118. {
  119.   int c = compare(s1.start(), s2.start());
  120.   if (c) return c;
  121.   return cmp_slopes(s1, s2);
  122. }
  123.  
  124. void balaend(const list<SEGMENT>&)
  125. { // free used memory
  126.   
  127.   if(init_points) delete[] init_points; init_points = 0;
  128.   if(stairs)      delete[] stairs;      stairs = 0;
  129.   if(original)    delete original;      original = 0;
  130.   
  131.   seg_queue.clear();
  132. }
  133.  
  134. void BALABAN_SEGMENTS(const list<SEGMENT>& S, rep_int_func rif)
  135. {
  136.   report_func  = rif;
  137.  
  138.   if ( S.length() )   // no segments => no intersecting pairs
  139.     {
  140.       // allocate space for |original|
  141.       original    = new map<SEGMENT,SEGMENT>;
  142.       if( !original )  return;
  143.       
  144.       // sort the endpoints of the segments in $S$ lexico
  145.       sortseq <POINT, int> ps_queue;
  146.       SEGMENT s;
  147.       seq_item sit1, sit2;
  148.       
  149.       forall(s, S)
  150.     {
  151.       sit1 = ps_queue.insert(s.start(), 0);
  152.       sit2 = ps_queue.insert(s.end(), 0); 
  153.  
  154.       SEGMENT slex( ps_queue.key(sit1), ps_queue.key(sit2) );
  155.       
  156.       // adjust segments from left to rigth or upwards
  157.       if ( compare(slex.start(), slex.end()) > 0 ) 
  158.         slex = SEGMENT( slex.end(), slex.start() );
  159.  
  160.       (*original)[slex] = s;
  161.       seg_queue.append(slex);
  162.     }
  163.     
  164.       // sort |seg_queue| using the ordering defined by the 
  165.       // function |compare2(const SEGMENT&, const SEGMENT&)|
  166.       seg_queue.sort(compare2);
  167.  
  168.       int N = ps_queue.size();
  169.       StairCount = 0;
  170.  
  171.       // allocate space for |init_points| and |stairs|
  172.       init_points = new POINT[N+1];
  173.       stairs      = new SEGMENT[S.length()+1];
  174.  
  175.       if(!init_points || !stairs )  { balaend(S); return; }
  176.  
  177.       int n = 1;
  178.  
  179.       // initialize |init_points|
  180.       while (!ps_queue.empty())
  181.     {
  182.       sit1 = ps_queue.min();
  183.       init_points[n++]  = ps_queue.key(sit1);
  184.       ps_queue.del_item(sit1);
  185.     }
  186.       
  187.       slist<SEGMENT> L; 
  188.       slist<SEGMENT> I;
  189.       slist<SEGMENT> R;
  190.  
  191.       // initialize L 
  192.       Lrs_from_Rls(R, L, 1);
  193.       
  194.       // initialize I
  195.       forall( s, seg_queue )
  196.     if ( !identical(s.end(), init_points[N]) )
  197.       I.append(s);
  198.       
  199.       // start $TreeSearch$
  200.       if( N > 1 )
  201.     {
  202.       TreeSearch_nloghoch2n(L, I, 1, N, R);
  203.       Lrs_from_Rls(R, L, N);
  204.     }
  205.     }
  206.   
  207.   balaend(S);
  208. }
  209.  
  210. void TreeSearch_nloghoch2n(slist<SEGMENT>& Lv, slist<SEGMENT>& Iv,
  211.                int b, int e, slist<SEGMENT>& Rv)
  212. {   
  213.   // 1. if e-b = 1 then SearchInStripbe(Lv, Rv); exit;
  214.   
  215.   if( e-b == 1 )  { SearchInStrip(Lv, Rv, b, e); return; }
  216.   
  217.   // 2. Splitbe(Lv, Qv, Lls); Dv := (Qv, <b,e>);
  218.   //
  219.   //        and
  220.   // 
  221.   // 3. Find Int(Dv, Lls);
  222.   
  223.   STAIRCASE     Dv(b, e);
  224.   
  225.   Split(Lv, Dv);
  226.  
  227.   // 10. For s ele Iv do find Loc(Dv, s) endfor
  228.   // 11. Find Int(Dv, Iv)
  229.   
  230.   InnerIntPoints(Dv, Iv);
  231.  
  232.   // 4. c := (b+e)/2;
  233.   
  234.   int   c = (b+e)/2;  
  235.   POINT pc = init_points[c];
  236.   
  237.   // 5. Place segments of Iv
  238.   //     inner for <b,c> into Ils
  239.   //     inner for <c,e> into Irs
  240.  
  241.   slist<SEGMENT> Ils;
  242.   slist<SEGMENT> Irs;
  243.   
  244.   while (!Iv.empty())
  245.     {
  246.       if( compare( Iv.head().end(), pc) < 0 ) // inner <b,c>
  247.     Ils.append(Iv.pop());
  248.       else
  249.     if( compare(Iv.head().start(), pc) > 0 ) // inner <c, pe>
  250.       Irs.conc(Iv);
  251.     else 
  252.       Iv.pop();
  253.     }
  254.   
  255.   // 6. TreeSearch(Lls, Ils, b, c, Rls);
  256.  
  257.   TreeSearch_nloghoch2n( Lv, Ils, b, c, Rv);
  258.  
  259.   // 7. If pc is left endpoint of s(c) Lrs := insert s(c) into Rls
  260.   //                           else    Lrs := remove s(c) from Rls
  261.   
  262.   Lrs_from_Rls(Rv, Lv, c); 
  263.  
  264.   // 8. TreeSearch(Lrs, Irs, c, e, Rrs);
  265.  
  266.   TreeSearch_nloghoch2n( Lv, Irs, c, e, Rv);
  267.     
  268.   //  9. Find Int(Dv, Rrs)
  269.   // 12. Rv := Mergee(Qv, Rrs)
  270.   
  271.   Merge(Dv, Rv);
  272.  
  273.   StairCount -= Dv.Count();  // forget these stairs
  274. }
  275.  
  276. void SearchInStrip(slist<SEGMENT>& L, slist<SEGMENT>& R, int b, int e)
  277. {
  278.   STAIRCASE     D(b, e);
  279.   
  280.   Split(L, D);
  281.   
  282.   if( !L.empty() ) 
  283.     if( D.empty() ) { L.clear(); return; }
  284.     else SearchInStrip(L, R, b, e);
  285.   
  286.   Merge(D, R);
  287.  
  288.   StairCount -= D.Count();
  289. }
  290.  
  291. void InnerIntPoints(const STAIRCASE& D, const slist<SEGMENT>& I)
  292. { // Precondition : all segments in I are inner from <D.b, D.e>
  293.   // Find intersections between segments in D.Q and I (I is not ordered)
  294.   // O( |I|log|D.Q| + |Int(D,I)|)-time
  295.   
  296.   if ( D.empty() || I.empty() ) return;
  297.   
  298.   SEGMENT s(I.head());
  299.   
  300.   forall(s, I)
  301.     {
  302.       int i = Loc(D, s);   int j = i + 1;
  303.       
  304.       // intersections between s and stairs below s.start()
  305.       while( i > 0 && ( orientation(D[i], s.end()) <= 0 || 
  306.                   !orientation(D[i], s.start()) ) )
  307.           ReportIntersection(D[i--], s);
  308.       
  309.       // intersections between s and stairs above s.start()
  310.       while ( j<=D.Count() && ( orientation(D[j], s.end()) >= 0 ||
  311.                   !orientation(D[j], s.start()) ) )
  312.     ReportIntersection(D[j++], s);
  313.     }
  314. }
  315.  
  316. int  Loc(const STAIRCASE& D, const SEGMENT s)
  317. { // Precondition : s is inner from <D.b, D.e>
  318.   //                D is not empty
  319.    
  320.   if( orientation (D[1], s.start()) < 0 )          return 0;
  321.   if( orientation (D[D.Count()], s.start()) > 0 )  return D.Count();
  322.   
  323.   int locmin = 1;
  324.   int locmax = D.Count(); 
  325.   
  326.   while(locmax-locmin > 1)
  327.     {
  328.       int i = (locmin+locmax)/2;
  329.       SEGMENT sd(D[i]);
  330.       int o = orientation( sd, s.start() ); 
  331.       
  332.       if( o > 0 ) locmin = i;
  333.       else
  334.     if( o < 0 ) locmax = i;
  335.     else { locmin = i; locmax = i; }
  336.     }
  337.   
  338.   return locmin;
  339. }
  340.  
  341. void ReportIntersection(const SEGMENT& s1, const SEGMENT& s2)
  342. {
  343.   if ( report_func ) report_func( (*original)[s1],(*original)[s2] );
  344. }
  345.  
  346. void Split(slist<SEGMENT>& L, STAIRCASE& D)
  347.   slist_item lit = L.first();                 if(!lit) return;
  348.   slist_item lits_prev = nil;
  349.   SEGMENT    s(L.head());
  350.   POINT      pb(init_points[D.b]);
  351.   POINT      pe(init_points[D.e]);
  352.   slist<int> locs;
  353.   int        loc=0, i;
  354.  
  355.   while ( lit )
  356.     {
  357.       s = L.inf( lit );
  358.       if ( compare(s.end(), pe) >= 0 ) // s is spanning $(|pb|,|pe|)$ 
  359.     if ( D.empty() || cmp_at_x(D[D.Count()], s, pe) <= 0 )
  360.       {  
  361.         D.append(s); 
  362.         lit = L.succ(lit);
  363.         if ( lits_prev )
  364.           L.del_succ_item(lits_prev);
  365.         else L.pop();
  366.         loc++; 
  367.       }
  368.     else { locs.append(-loc); lits_prev = lit; lit = L.succ(lit); }
  369.       else   { locs.append(loc); lits_prev = lit; lit = L.succ(lit); }
  370.     }  
  371.  
  372.   if ( D.empty() || L.empty() ) return;
  373.  
  374.   lit = locs.first();
  375.   forall(s, L)
  376.     {
  377.       loc = locs.inf(lit); lit = locs.succ(lit);
  378.       if( loc < 0 )
  379.     {
  380.       i = -loc;
  381.       // intersections between s and stairs below s
  382.       ReportIntersection(D[i--], s); // s would be a stair if not      
  383.       while( i > 0 &&  cmp_at_x(D[i], s, pe) > 0  )
  384.         ReportIntersection(D[i--], s);
  385.     }
  386.       else
  387.     {
  388.       i = loc;
  389.       // intersections between s and stairs below s
  390.       while( i > 0 && orientation(D[i], s.end()) <= 0 )
  391.         ReportIntersection(D[i--], s);
  392.       i = loc+1;
  393.       // intersections between s and stairs above s
  394.       while ( i<=D.Count() && orientation(D[i], s.end()) >= 0 )
  395.         ReportIntersection(D[i++], s);
  396.     }
  397.     }
  398.   locs.clear();
  399. }
  400.  
  401. void Lrs_from_Rls(slist<SEGMENT>& R, slist<SEGMENT>& L, int c)
  402. {    
  403.   SEGMENT         s; 
  404.   POINT           pc(init_points[c]);
  405.  
  406.   // put all segments from R to L
  407.   L.conc(R);
  408.   slist_item      lits_prev = nil;
  409.   slist_item      lit = L.first();
  410.   
  411.   while ( lit && orientation(R.inf(lit), pc) > 0  ) 
  412.     { lits_prev = lit; lit = L.succ(lit); }
  413.   
  414.   slist<SEGMENT>   endings;
  415.   slist<SEGMENT>   pass_start;
  416.   slist<SEGMENT>   nuller;
  417.   SEGMENT          si;
  418.   
  419.   while ( lit && !orientation(R.inf(lit), pc) ) 
  420.     { 
  421.       s = R.inf(lit);
  422.       if( identical( s.end(), pc ) ) // segments ending at pc
  423.     {
  424.       forall(si, endings)    ReportIntersection(s, si);
  425.       forall(si, pass_start) ReportIntersection(s, si);
  426.       endings.append(s);
  427.       lit = L.succ(lit);
  428.       if ( lits_prev )  L.del_succ_item(lits_prev);
  429.       else L.pop();
  430.     }
  431.       else                          // segments passing pc
  432.     {  
  433.       forall(si, endings)    ReportIntersection(s, si);
  434.       forall(si, pass_start)
  435.         if( orientation(s, si.start()) ) ReportIntersection(s, si);
  436.       pass_start.push(s); 
  437.       lit = L.succ(lit);
  438.       if ( lits_prev )  L.del_succ_item(lits_prev);
  439.       else L.pop(); 
  440.     }
  441.     }
  442.  
  443.   while(!seg_queue.empty() && identical(seg_queue.head().start(), pc))
  444.     { 
  445.       s = seg_queue.pop();
  446.       if ( identical( s.end(), pc ) ) // zero length segments
  447.     {
  448.       forall(si, endings)    ReportIntersection(s, si);
  449.       forall(si, pass_start) ReportIntersection(s, si);
  450.       forall(si, nuller)     ReportIntersection(s, si);
  451.       nuller.append(s);
  452.     }
  453.       else                            // segments starting at pc
  454.     { 
  455.       forall(si, endings) ReportIntersection(s, si);
  456.       forall(si, nuller)  ReportIntersection(s, si);
  457.       slist_item lit1 = pass_start.first();
  458.       slist_item lit2 = 0;
  459.       while(lit1)
  460.         {
  461.           si = pass_start.inf(lit1);
  462.           int o = orientation(si, s.end());
  463.           if(o) ReportIntersection(s, si);
  464.           if( o > 0) lit2 = lit1; 
  465.           lit1 = pass_start.succ(lit1);
  466.         }
  467.       if (!lit2) pass_start.push(s);
  468.       else       pass_start.insert(s, lit2);
  469.     }
  470.     }
  471.  
  472.   forall(s, pass_start) 
  473.     {
  474.     if(lits_prev) 
  475.       { 
  476.         L.insert(s, lits_prev); 
  477.         lits_prev = L.succ(lits_prev); 
  478.       }
  479.     else  lits_prev = L.push(s);
  480.     }
  481. }
  482.  
  483. void Merge(STAIRCASE& D, slist<SEGMENT>& R)
  484. { // Merge the stairs in D and the segments in R and return result in R.
  485.   // Precondition : D.Q, and R are orderd by <(D.e.xcoord)
  486.   
  487.   int        loc = 1, i, j;
  488.   POINT      pb(init_points[D.b]);
  489.   POINT      pe(init_points[D.e]);
  490.   slist_item lit = R.first();
  491.   slist_item lits_prev = nil;
  492.   
  493.   if( D.Count() == 0 )  return;
  494.  
  495.   while( lit || loc <= D.Count() )
  496.     {
  497.       if( !lit )      
  498.     { 
  499.       for(; loc <= D.Count();) R.append(D[loc++]);
  500.       return; 
  501.     }
  502.       
  503.       SEGMENT s( R.inf(lit) );
  504.       
  505.       int c_x = loc > D.Count() ? 1 : cmp_at_x(s, D[loc], pe);
  506.       
  507.       if ( c_x < 0 )
  508.     {
  509.       if( compare( s.start(), pb ) > 0 )
  510.         {
  511.           i = loc-1; j = loc;
  512.           
  513.           while( i > 0 && orientation(D[i], s.start()) <= 0 )
  514.         ReportIntersection(D[i--], s);
  515.           
  516.           while( j<=D.Count() && orientation(D[j], s.start()) >= 0)
  517.         ReportIntersection(D[j++], s);
  518.         }
  519.       lits_prev = lit; lit = R.succ(lit);
  520.     }
  521.       else
  522.     if ( !c_x ) 
  523.       {
  524.         do
  525.           {
  526.         lits_prev = lit; lit = R.succ(lit);
  527.           } while( lit && !cmp_at_x(R.inf(lit), D[loc], pe) );
  528.         
  529.         while( loc<D.Count() && !cmp_at_x(D[loc+1],D[loc],pe))
  530.           { R.insert(D[loc++], lits_prev); lits_prev = R.succ(lits_prev); }
  531.       }
  532.     else 
  533.       {
  534.         if(loc > D.Count())
  535.           {
  536.         if( compare( s.start(), pb ) > 0 )
  537.           {
  538.             i = loc-1;
  539.             
  540.             while( i > 0 && orientation(D[i], s.start()) <= 0 )
  541.               ReportIntersection(D[i--], s);
  542.           }
  543.         lits_prev = lit; lit = R.succ(lit);
  544.           }
  545.         else
  546.           if(lits_prev)
  547.         { 
  548.           R.insert(D[loc++], lits_prev); lits_prev = R.succ(lits_prev);
  549.         }
  550.           else  lits_prev = R.push(D[loc++]);
  551.       }
  552.     }
  553. }
  554.  
  555.