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 / _rat_segment.c < prev    next >
C/C++ Source or Header  |  1996-09-03  |  18KB  |  590 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA 3.4
  4. +
  5. +  _rat_segment.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.  
  18. //------------------------------------------------------------------------------// rat_segment : segments with rational coordinates
  19. //
  20. // by S. Naeher (1995,1996)
  21. //------------------------------------------------------------------------------
  22.  
  23. #include <LEDA/rat_segment.h>
  24. #include <math.h>
  25. #include <ctype.h>
  26.  
  27.  
  28.  
  29. #if defined(sparc)
  30. #define FABS(x) (*(unsigned long*)&x) &= 0x7FFFFFFF
  31. #else
  32. #define FABS(x) x=fabs(x)
  33. #endif
  34.  
  35.  
  36. mutex rat_segment_rep::mutex_id_counter;
  37.  
  38. unsigned long rat_segment_rep::id_counter = 0;
  39.  
  40.  
  41. rat_segment_rep::rat_segment_rep(const rat_point& p, const rat_point& q) : start(p),end(q)
  42. { dx = q.X()*p.W() - p.X()*q.W();
  43.   dy = q.Y()*p.W() - p.Y()*q.W();
  44.   dxd = dx.todouble();
  45.   dyd = dy.todouble();
  46.   mutex_id_counter.lock();
  47.   id  = id_counter++; 
  48.   mutex_id_counter.unlock();
  49.  }
  50.  
  51. rat_segment_rep::rat_segment_rep() : start(0,0,1), end(0,0,1)
  52. { dx  = 0;
  53.   dy  = 0;
  54.   dxd = 0;
  55.   dyd = 0;
  56.   mutex_id_counter.lock();
  57.   id  = id_counter++; 
  58.   mutex_id_counter.unlock();
  59.  }
  60.  
  61. rat_segment::rat_segment(const rat_point& x, const rat_vector& v) 
  62. { PTR = new rat_segment_rep(x,x+v); }
  63.   
  64.  
  65. // MOVED TO _pglobal.c
  66. /*
  67.  * int rat_segment::use_filter = true;
  68.  */
  69.  
  70.  
  71. segment rat_segment::to_segment() const
  72. { return segment(ptr()->start.to_point(),ptr()->end.to_point()); }
  73.  
  74.  
  75. rat_segment rat_segment::reversal() const
  76. { return rat_segment(ptr()->end,ptr()->start); }
  77.  
  78.  
  79. rat_segment rat_segment::translate(const integer& dx, const integer& dy, const integer& dw) const
  80. { rat_point p = ptr()->start.translate(dx,dy,dw);
  81.   rat_point q = ptr()->end.translate(dx,dy,dw);
  82.   return rat_segment(p,q);
  83.  }
  84.  
  85. rat_segment rat_segment::translate(const rational& dx, const rational& dy) const
  86. { rat_point p = ptr()->start.translate(dx,dy);
  87.   rat_point q = ptr()->end.translate(dx,dy);
  88.   return rat_segment(p,q);
  89. }
  90.  
  91. rat_segment rat_segment::translate(const rat_vector& v) const
  92. { rat_point p = ptr()->start.translate(v);
  93.   rat_point q = ptr()->end.translate(v);
  94.   return rat_segment(p,q);
  95.  }
  96.  
  97.  
  98. rat_segment rat_segment::rotate90() const
  99. { return rat_segment(start(),end().rotate90(start())); }
  100.  
  101. rat_segment rat_segment::rotate90(const rat_point& q) const
  102. {  return rat_segment(start().rotate90(q),end().rotate90(q)); }
  103.  
  104.  
  105. rat_segment rat_segment::reflect(const rat_point& p, const rat_point& q) const
  106. { return rat_segment(start().reflect(p,q),end().reflect(p,q)); }
  107.  
  108. rat_segment rat_segment::reflect(const rat_point& p) const
  109. { return rat_segment(start().reflect(p),end().reflect(p)); }
  110.  
  111.  
  112.  
  113. rational rat_segment::sqr_length() const
  114. { integer x = dx();
  115.   integer y = dy();
  116.   integer w = W1()*W2();
  117.   return rational(x*x+y*y,w*w);
  118.  }
  119.  
  120.  
  121. ostream& operator<<(ostream& out, const rat_segment& s) 
  122. { out << "[" << s.start() << "===" << s.end() << "]"; 
  123.   return out;
  124.  } 
  125.  
  126. istream& operator>>(istream& in, rat_segment& s) 
  127. { // syntax: {[} p {===} q {]}
  128.  
  129.   rat_point p,q; 
  130.   char c;
  131.  
  132.   do in.get(c); while (isspace(c));
  133.   if (c != '[') in.putback(c);
  134.  
  135.   in >> p;
  136.  
  137.   do in.get(c); while (isspace(c));
  138.   while (c== '=') in.get(c);
  139.   while (isspace(c)) in.get(c);
  140.   in.putback(c);
  141.  
  142.   in >> q; 
  143.  
  144.   do in.get(c); while (c == ' ');
  145.   if (c != ']') in.putback(c);
  146.  
  147.   s = rat_segment(p,q); 
  148.   return in; 
  149.  
  150.  } 
  151.  
  152.  
  153. bool rat_segment::contains(const rat_point& p) const
  154. { rat_point a = source();
  155.   rat_point b = target();
  156.   if (orientation(a,b,p) == 0)
  157.   { if ( a == b) return ( a == p? true: false);
  158.     rat_point c = b.rotate90(a);
  159.     rat_point d = a.rotate90(b);
  160.     return (orientation(a,c,p) <= 0)  && (orientation(b,d,p) <= 0);
  161.    }
  162.   return false;
  163.  }
  164.  
  165.  
  166. bool rat_segment::intersection(const rat_segment& t)
  167. { // decides whether this and |t| intersect
  168.   if (   is_trivial() ) return t.contains(  source());
  169.   if ( t.is_trivial() ) return   contains(t.source());
  170.    
  171.   int o1 = orientation(*this,t.start()); 
  172.   int o2 = orientation(*this,t.end());
  173.   int o3 = orientation(t,start());
  174.   int o4 = orientation(t,end());
  175.  
  176.   if ( o1 == 0 && o2 == 0 )
  177.      // same slope
  178.      return ( t.contains(  source()) || t.contains(  target()) ||
  179.                 contains(t.source()) ||   contains(t.target())    );
  180.   else 
  181.      return o1 != o2 && o3 != o4;
  182. }
  183.  
  184.  
  185.  
  186. bool rat_segment::intersection(const rat_segment& t, rat_point& I) const
  187. { if (   is_trivial() )
  188.   { if ( t.contains(  source()) )
  189.        { I = source(); return true; }
  190.     else
  191.        return false;
  192.   }
  193.   if ( t.is_trivial() ) 
  194.   { if ( contains(t.source()) )
  195.        { I = t.source(); return true; }
  196.     else 
  197.        return false;
  198.   }
  199.    
  200.   int o1 = orientation(*this,t.start()); 
  201.   int o2 = orientation(*this,t.end());
  202.   int o3 = orientation(t,start());
  203.   int o4 = orientation(t,end());
  204.  
  205.   if ( o1 == 0 && o2 == 0 )
  206.   { // same slope
  207.     if ( t.contains(  source()) )
  208.        {  I = source(); return true; }
  209.     if ( t.contains(  target()) )
  210.        { I = target(); return true;  }
  211.     if ( contains(t.source()) )
  212.        {  I = t.source(); return true; }
  213.     if ( contains(t.target()) )
  214.        { I = t.target(); return true; }
  215.     return false;
  216.   }
  217.   
  218.   if ( o1 != o2 && o3 != o4 )
  219.   { integer w  =   dy()*t.dx() - t.dy()*dx();
  220.     integer c1 =   X2()*  Y1() -   X1()*  Y2();
  221.     integer c2 = t.X2()*t.Y1() - t.X1()*t.Y2();
  222.  
  223.     I = rat_point(c2*dx()-c1*t.dx(), c2*dy()-c1*t.dy(), w);
  224.     return true;
  225.   }
  226.   return false;
  227. }
  228.  
  229. bool rat_segment::intersection(const rat_segment& t, rat_segment& I) const
  230. { if (   is_trivial() )
  231.   { if ( t.contains(  source()) )
  232.        { I = rat_segment(source(),source()); return true; }
  233.     else
  234.        return false;
  235.   }
  236.   if ( t.is_trivial() ) 
  237.   { if ( contains(t.source()) )
  238.        { I = rat_segment(t.source(),t.source()); return true; }
  239.     else 
  240.        return false;
  241.   }
  242.    
  243.   int o1 = orientation(*this,t.start()); 
  244.   int o2 = orientation(*this,t.end());
  245.   int o3 = orientation(t,start());
  246.   int o4 = orientation(t,end());
  247.  
  248.   if ( o1 == 0 && o2 == 0 )
  249.   { rat_point sa = source(); 
  250.     rat_point sb = target();
  251.     if ( compare (sa,sb) > 0 )
  252.        { rat_point h = sa; sa = sb; sb = sa; }
  253.  
  254.     rat_point ta = t.source(); rat_point tb = t.target();
  255.  
  256.     if ( compare (ta,tb) > 0 )
  257.        { rat_point h = ta; ta = tb; tb = ta; }
  258.  
  259.     rat_point a = ta;
  260.     rat_point b = tb; 
  261.  
  262.     if (compare(sa,a) < 0) a = sa;
  263.     if (compare(sb,b) < 0) b = sb;
  264.  
  265.     if ( compare(a,b) <= 0 )
  266.     { I = rat_segment(a,b);
  267.       return true;
  268.     }
  269.     return false;
  270.   }
  271.   
  272.   if ( o1 != o2 && o3 != o4 )
  273.   { integer w  =   dy()*t.dx() - t.dy()*dx();
  274.     integer c1 =   X2()*  Y1() -   X1()*  Y2();
  275.     integer c2 = t.X2()*t.Y1() - t.X1()*t.Y2();
  276.  
  277.     rat_point p(c2*dx()-c1*t.dx(), c2*dy()-c1*t.dy(), w);
  278.     I = rat_segment(p,p);
  279.     return true;
  280.   }
  281.   return false;
  282. }
  283.  
  284. bool rat_segment::intersection_of_lines(const rat_segment& t, rat_point& inter) const
  285.   /* decides whether the lines induced by |s| and |this| segment 
  286.      intersect and, if so, returns the intersection in |inter|. 
  287.      It is assumed that both segments have non-zero length
  288.    */
  289.  
  290.   integer w = dy()*t.dx() - dx()*t.dy();
  291.  
  292.   if (w == 0) //same slope
  293.   { inter = source();
  294.     return true;
  295.   }
  296.  
  297.   integer c1 =   X2()*  Y1() -   X1()*  Y2();
  298.   integer c2 = t.X2()*t.Y1() - t.X1()*t.Y2();
  299.  
  300.   inter = rat_point(c2*dx()-c1*t.dx(), c2*dy()-c1*t.dy(), w);
  301.  
  302.   return true;
  303. }
  304.  
  305.  
  306. const double eps0 = ldexp(1.0,-53);
  307. const double eps2 = ldexp(1.0,-47); // 64 * eps0
  308.  
  309. int cmp_slopes(const rat_segment& s1, const rat_segment& s2)
  310.   if (rat_segment::use_filter)
  311.   { if ( s2.dxD() == 0 || s1.dxD() == 0 )
  312.     { // one of the lines is vertical
  313.       if ( s2.dxD() == 0 && s1.dxD() == 0 ) return 0;
  314.       if ( s2.dxD() == 0) return -1;  // s1 has smaller slope
  315.       return +1;  // s2 has smaller slope
  316.     }
  317.  
  318.     double dy1dx2 = s1.dyD()*s2.dxD();
  319.     double dy2dx1 = s2.dyD()*s1.dxD();
  320.     double E = dy1dx2 - dy2dx1; 
  321.     if ( s1.dxD() * s2.dxD() < 0 ) E = -E;
  322.  
  323.     //-----------------------------------------------------------------------
  324.     //  ERROR BOUNDS
  325.     //-----------------------------------------------------------------------
  326.     // mes(E) = 2 * (mes(dy1*dx2) + mes(dy2*dx2))
  327.     //        = 2 * (mes(dy1)*mes(dx2) + mes(dy2)*mes(dx2))
  328.     //        = 2 * (4*fabs(dy1dx2) + 4*fabs(dy2dx2))
  329.     //        = 8 * (fabs(dy1dx2) + fabs(dy2dx2))
  330.     //
  331.     // ind(E) = (ind(dy1*dx2) + ind(dy2*dx2) + 1)/2
  332.     //        = (ind(dy1) + ind(dx2) + 0.5 + ind(dy2) + ind(dx2) + 0.5 + 1)/2
  333.     //        = (0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 1)/2
  334.     //        = 2
  335.     //
  336.     // eps(E) = ind(E) * mes(E) * eps0
  337.     //        = 16 * (fabs(dy1dx2) + fabs(dy2dx2)) * eps0
  338.     //-----------------------------------------------------------------------
  339.   
  340.     FABS(dy1dx2);
  341.     FABS(dy2dx1);
  342.     double eps = 16 * (dy1dx2+dy2dx1) * eps0;
  343.   
  344.     if (E >  eps) return  1;
  345.     if (E < -eps) return -1;
  346.     if (eps < 1)  return 0;
  347.   }
  348.   
  349.   // use big integers
  350.   if ( s2.dx() == 0 || s1.dx() == 0 )
  351.   { // one of the lines is vertical
  352.     if ( s2.dx() == 0 && s1.dx() == 0 ) return 0;
  353.     if ( s2.dx() == 0) return -1;  // s1 has smaller slope
  354.     return +1;  // s2 has smaller slope
  355.   }
  356.   integer E = s1.dy() * s2.dx() - s2.dy() * s1.dx();
  357.   int s = sign(E);
  358.   return ( sign(s1.dx()) * sign(s2.dx()) < 0 ) ? -s : s;
  359. }
  360.  
  361. int rat_segment::cmp_slope(const rat_segment& s1) const
  362. { return cmp_slopes(*this,s1); }
  363.  
  364.  
  365. int orientation(const rat_segment& s, const rat_point& p)
  366.   rat_point a = s.start();
  367.  
  368.   if (rat_segment::use_filter)
  369.   { 
  370.     double dx = s.dxD();
  371.     double dy = s.dyD();
  372.     double axpw = a.XD() * p.WD();
  373.     double aypw = a.YD() * p.WD();
  374.     double pxaw = p.XD() * a.WD();
  375.     double pyaw = p.YD() * a.WD();
  376.   
  377.     double E =  dy * (axpw - pxaw) - dx * (aypw - pyaw); 
  378.  
  379.     //-----------------------------------------------------------------------
  380.     //  ERROR BOUNDS
  381.     //-----------------------------------------------------------------------
  382.     //
  383.     // mes(E) = 2 * (mes(dx) * 2*(mes(aypw)+mes(pyaw)) +
  384.     //               mes(dy) * 2*(mes(axpw)+mes(pxaw)))
  385.     //        = 4 * (mes(dx) * (mes(aypw)+mes(pyaw)) +
  386.     //               mes(dy) * (mes(axpw)+mes(pxaw)))
  387.     //        = 8 * (fabs(dx) * (2*fabs(aypw)+2*fabs(pyaw)) +
  388.     //               fabs(dy) * (2*fabs(axpw)+2*fabs(pxaw)))
  389.     //        =16 * (fabs(dx) * (fabs(aypw)+fabs(pyaw)) +
  390.     //               fabs(dy) * (fabs(axpw)+fabs(pxaw)))
  391.     //
  392.     // ind(E) =  (ind(dx) + ind(aypw - pyaw) + 0.5 +
  393.     //            ind(dy) + ind(axpw - pxaw) + 0.5 + 1)/2
  394.     //        =  (ind(dx) + (ind(aypw) + ind(pyaw) + 1)/2 + 0.5 +
  395.     //            ind(dy) + (ind(axpw) + ind(pxaw) + 1)/2 + 0.5 + 1)/2
  396.     //        =  (0.5 + (1.5 + 1.5 + 1)/2 + 0.5
  397.     //            0.5 + (1.5 + 1.5 + 1)/2 + 0.5 + 1)/2
  398.     //        =  (0.5 + 2 + 0.5 + 0.5 + 2 + 0.5 + 1)/2
  399.     //        =  3.5 
  400.     //
  401.     // mes(E) = ind(E) * mes(E) * eps0
  402.     //        = 56 * (fabs(dx) * (fabs(aypw)+fabs(pyaw)) +
  403.     //                fabs(dy) * (fabs(axpw)+fabs(pxaw))) * eps0
  404.     //-----------------------------------------------------------------------
  405.   
  406.     FABS(aypw);
  407.     FABS(pyaw);
  408.     FABS(axpw);
  409.     FABS(pxaw);
  410.     FABS(dx);
  411.     FABS(dy);
  412.   
  413.     double eps = 56 * ((aypw+pyaw)*dx + (axpw+pxaw)*dy) * eps0;
  414.   
  415.     if (E >  eps) return  1;
  416.     if (E < -eps) return -1;
  417.     if (eps < 1)  return 0;
  418.    }
  419.  
  420.   // big integers
  421.  
  422.   return sign( s.dy() * (a.X()*p.W() - p.X()*a.W()) -
  423.                s.dx() * (a.Y()*p.W() - p.Y()*a.W()) );
  424.  
  425.  }
  426.  
  427.  
  428.  
  429. int cmp_segments_at_xcoord(const rat_segment& s1, const rat_segment& s2, 
  430.                            const rat_point& r)
  431.   if (rat_segment::use_filter)
  432.     {
  433.       double s1x = s1.XD1();
  434.       double s1y = s1.YD1();
  435.       double s1w = s1.WD1();
  436.       
  437.       double s2x = s2.XD1();
  438.       double s2y = s2.YD1();
  439.       double s2w = s2.WD1();
  440.       
  441.       double rx = r.XD();
  442.       double ry = r.YD();
  443.       double rw = r.WD();
  444.       
  445.       double d1x = s1.dxD();
  446.       double d1y = s1.dyD();
  447.       
  448.       double d2x = s2.dxD();
  449.       double d2y = s2.dyD();
  450.       
  451.       double E = d2x * s2w * (s1y * d1x * rw + d1y * (rx * s1w - s1x * rw))
  452.           - d1x * s1w * (s2y * d2x * rw + d2y * (rx * s2w - s2x * rw));
  453.  
  454.  
  455.       /* ----------------------------------------------------------------------
  456.        *                             ERROR BOUNDS
  457.        * ----------------------------------------------------------------------
  458.        *
  459.        * mes(E) = mes(d2x*s2w *(s1y*d1x*rw+d1y*(rx*s1w-s1x*rw))
  460.        *              -d1x*s1w*(s2y*d2x*rw+d2y*(rx*s2w-s2x*rw)))
  461.        *
  462.        *        = 2*(mes(d2x)*mes(s2w)*mes(s1y*d1x*rw+d1y*(rx*s1w-s1x*rw))
  463.        *             + mes(d1x)*mes(s1w)*mes(s2y*d2x*rw+d2y*(rx*s2w-s2x*rw)))
  464.        *
  465.        *        = 4*(mes(d2x)*mes(s2w)*
  466.        *               (mes(s1y)*mes(d1x)*mes(rw)+
  467.        *                  mes(d1y)*2(mes(rx)*mes(s1w)+mes(s1x)*mes(rw)))
  468.        *           +mes(d1x)*mes(s1w)*
  469.        *              (mes(s2y)*mes(d2x)*mes(rw)+
  470.        *                  mes(d2y)*2(mes(rx)*mes(s2w)+mes(s2x)*mes(rw))))
  471.        *
  472.        *        = 4*(fabs(d2x)*fabs(s2w)*
  473.        *               (fabs(s1y)*2*fabs(d1x)*fabs(rw)+
  474.        *                  fabs(d1y)*2*(fabs(rx)*fabs(s1w)+fabs(s1x)*fabs(rw)))
  475.        *            +fabs(d1x)*fabs(s1w)*
  476.        *               (fabs(s2y)*2*fabs(d2x)*fabs(rw)+
  477.        *                  fabs(d2y)*2*(fabs(rx)*fabs(s1w)+fabs(s2x)*fabs(rw))))
  478.        *
  479.        * ----------------------------------------------------------------------
  480.        *
  481.        * ind(E) = ind(d2x*s2w *(s1y*d1x*rw+d1y*(rx*s1w-s1x*rw))
  482.        *              -d1x*s1w*(s2y*d2x*rw+d2y*(rx*s2w-s2x*rw)))
  483.        * 
  484.        *        = (ind(d2x*s2w *(s1y*d1x*rw+d1y*(rx*s1w-s1x*rw)))
  485.        *          +ind(d1x*s1w*(s2y*d2x*rw+d2y*(rx*s2w-s2x*rw))) + 1)/2
  486.        *
  487.        *        = (ind(d2x)+ind(s2w *(s1y*d1x*rw+d1y*(rx*s1w-s1x*rw)))+0.5
  488.        *          +ind(d1x)+ind(s1w*(s2y*d2x*rw+d2y*(rx*s2w-s2x*rw)))+0.5+1)/2
  489.        *
  490.        *        = (1 + ind(s1y*d1x*rw+d1y*(rx*s1w-s1x*rw)) + 1
  491.        *           + 1 ind(s2y*d2x*rw+d2y*(rx*s2w-s2x*rw)) + 1 + 1)/2
  492.        *
  493.        *        = (5 + (ind(s1y*d1x*rw) + ind(d1y*(rx*s1w-s1x*rw)) + 1)/2
  494.        *          + (ind(s2y*d2x*rw) + ind(d2y*(rx*s2w-s2x*rw)) + 1)/2 )/2
  495.        *
  496.        *        = (5 + (ind(s1y)+ind(d1x)+ind(rw) + 1 + 
  497.        *                ind(d1y*(rx*s1w-s1x*rw)) + 1)/2
  498.        *          + (ind(s2y)+ind(d2x)+ind(rw) + 1 +
  499.        *             ind(d2y*(rx*s2w-s2x*rw))+ 1)/2)/2
  500.        *
  501.        *        = (5 + (0.5 + 0.5 + 0.5 + 1 + ind(d1y*(rx*s1w-s1x*rw)) + 1)/2
  502.        *          + (0.5 + 0.5 + 0.5 + 1 + ind(d2y*(rx*s2w-s2x*rw)) + 1)/2 )/2
  503.        *
  504.        *        = (5 + (3.5 + ind(d1y) + ind(rx*s1w-s1x*rw) + 0.5)/2
  505.        *          + (3.5 + ind(d2y) + ind(rx*s2w-s2x*rw) + 0.5)/2 )/2
  506.        *
  507.        *        = (5 + (3.5 + 0.5 +(ind(rx*s1w) + ind(s1x*rw) + 1)/2 + 0.5)/2
  508.        *          + (3.5 + 0.5 +(ind(rx*s2w) + ind(s2x*rw) + 1)/2 + 0.5)/2 )/2 
  509.        *
  510.        *        = (5 + (3.5 + 0.5 + (1.5 + 1.5 + 1 )/2 + 0.5 )/2
  511.        *             + (3.5 + 0.5 + (1.5 + 1.5 + 1 )/2 + 0.5 )/2)/2
  512.        *
  513.        *        = (5 + (4 + 2 + 0.5)/2 + (4 + 2 + 0.5)/2)/2 
  514.        *
  515.        *        = (5 + 13/2)/2 = 23/4
  516.        *
  517.        * ----------------------------------------------------------------------
  518.        *
  519.        * eps(E) = ind(E) * mes(E) * eps0
  520.        *
  521.        * eps    = 23*(fabs(d2x)*fabs(s2w)*
  522.        *               (fabs(s1y)*fabs(d1x)*fabs(rw)+
  523.        *                  fabs(d1y)*2*(fabs(rx)*fabs(s1w)+fabs(s1x)*fabs(rw)))
  524.        *            +fabs(d1x)*fabs(s1w)*
  525.        *               (fabs(s2y)*fabs(d2x)*fabs(rw)+
  526.        *                  fabs(d2y)*2*(fabs(rx)*fabs(s1w)+fabs(s2x)*fabs(rw))))
  527.        *            *eps0
  528.        *
  529.        *
  530.        * ------------------------------------------------------------------- */
  531.  
  532.       FABS(s1x);
  533.       FABS(s1y);
  534.       FABS(s1w);
  535.       
  536.       FABS(s2x);
  537.       FABS(s2y);
  538.       FABS(s2w);
  539.       
  540.       FABS(rx);
  541.       FABS(ry);
  542.       FABS(rw);
  543.       
  544.       FABS(d1x);
  545.       FABS(d1y);
  546.       
  547.       FABS(d2x);
  548.       FABS(d2y);
  549.       
  550.       double eps = 23 * 
  551.                    (d2x * s2w * (s1y * d1x * rw + 2*d1y * 
  552.                                  (rx * s1w + s1x * rw))
  553.                    + d1x * s1w * (s2y * d2x * rw + 2*d2y * 
  554.                                   (rx * s2w + s2x * rw)))
  555.                    * eps0; 
  556.  
  557.       if(E > eps)  return  1;
  558.       if(E < -eps) return -1;
  559.       if (eps < 1) return 0;
  560.  
  561.     }
  562.   
  563.   return sign( s2.dx() * s2.W1() *
  564.                  ( s1.Y1() * s1.dx() * r.W() + 
  565.                    s1.dy() * (r.X() * s1.W1() - s1.X1() * r.W()))
  566.                -
  567.                s1.dx() * s1.W1() * 
  568.                  ( s2.Y1() * s2.dx() * r.W() + 
  569.                    s2.dy() * ( r.X() * s2.W1() - s2.X1() * r.W()))); 
  570. }
  571.  
  572.  
  573. rat_segment rat_segment::perpendicular(const rat_point& q) const
  574. { if ( is_trivial() )
  575.      error_handler(1,"rat_segment::perpendicular: this must be nontrivial");
  576.   rat_point p = source();
  577.   integer  dx = q.X()*p.W() - p.X()*q.W();
  578.   integer  dy = q.Y()*p.W() - p.Y()*q.W();
  579.   integer  dw = p.W()*q.W();
  580.   rat_point r;
  581.   intersection_of_lines(translate(dx,dy,dw).rotate90(), r);
  582.   return rat_segment(q,r);
  583.  }
  584.  
  585.