_segment.c
上传用户:gzelex
上传日期:2007-01-07
资源大小:707k
文件大小:6k
开发平台:

MultiPlatform

  1. /*******************************************************************************
  2. +
  3. +  LEDA-R  3.2.3
  4. +
  5. +  _segment.c
  6. +
  7. +  Copyright (c) 1995  by  Max-Planck-Institut fuer Informatik
  8. +  Im Stadtwald, 66123 Saarbruecken, Germany     
  9. +  All rights reserved.
  10. *******************************************************************************/
  11. #include <LEDA/line.h>
  12. #include <math.h>
  13. #include <ctype.h>
  14. unsigned long segment_rep::id_counter = 0;
  15. //------------------------------------------------------------------------------
  16. // segments 
  17. //------------------------------------------------------------------------------
  18. segment_rep::segment_rep()  { count = 1; id  = id_counter++; }
  19. segment_rep::segment_rep(const point& p, const point& q) 
  20.   count = 1; 
  21.   start = p;
  22.   end   = q;
  23.   dx    = q.xcoord() - p.xcoord(); 
  24.   dy    = q.ycoord() - p.ycoord(); 
  25.   if (dx==0)
  26.     { slope = MAXDOUBLE;
  27.       y_abs = -MAXDOUBLE;
  28.      }
  29.   else
  30.     { slope = dy/dx;
  31.       y_abs =  p.ycoord() - slope * p.xcoord();
  32.      }
  33.   if (dx != 0 || dy != 0)
  34.       angle = atan2(dy,dx); 
  35.   else
  36.       angle = 0;
  37.   id  = id_counter++; 
  38. }
  39.   
  40. segment::segment() { PTR = new segment_rep; }
  41. segment::segment(const point& x, const point& y) 
  42. { PTR = new segment_rep(x,y); }
  43. segment::segment(const point& x, const vector& v) 
  44. { PTR = new segment_rep(x,x+v); }
  45. segment::segment(double x1, double y1, double x2, double y2) 
  46. { PTR = new segment_rep(point(x1,y1), point(x2,y2)); }
  47. segment::segment(const point& p, double alpha, double length)
  48. { point q = p.translate(alpha,length);
  49.   PTR  = new segment_rep(p,q); 
  50.  }
  51.   
  52. segment segment::translate(double alpha, double d) const
  53. { point p = ptr()->start.translate(alpha,d);
  54.   point q = ptr()->end.translate(alpha,d);
  55.   return segment(p,q);
  56.  }
  57. segment segment::translate(const vector& v) const
  58. { point p = ptr()->start.translate(v);
  59.   point q = ptr()->end.translate(v);
  60.   return segment(p,q);
  61.  }
  62. ostream& operator<<(ostream& out, const segment& s) 
  63. { out << "[" << s.start() << "===" << s.end() << "]"; 
  64.   return out;
  65.  } 
  66. istream& operator>>(istream& in, segment& s) 
  67. { // syntax: {[} p {===} q {]}
  68.   point p,q; 
  69.   char c;
  70.   do in.get(c); while (isspace(c));
  71.   if (c != '[') in.putback(c);
  72.   in >> p;
  73.   do in.get(c); while (isspace(c));
  74.   while (c== '=') in.get(c);
  75.   while (isspace(c)) in.get(c);
  76.   in.putback(c);
  77.   in >> q; 
  78.   do in.get(c); while (c == ' ');
  79.   if (c != ']') in.putback(c);
  80.   s = segment(p,q); 
  81.   return in; 
  82.  } 
  83. double segment::angle(const segment& s) const
  84. {
  85.   double cosfi,fi,norm;
  86.   
  87.   double dx  = ptr()->end.ptr()->x - ptr()->start.ptr()->x; 
  88.   double dy  = ptr()->end.ptr()->y - ptr()->start.ptr()->y; 
  89.   double dxs = s.ptr()->end.ptr()->x - s.ptr()->start.ptr()->x; 
  90.   double dys = s.ptr()->end.ptr()->y - s.ptr()->start.ptr()->y; 
  91.   
  92.   cosfi=dx*dxs+dy*dys;
  93.   
  94.   norm=(dx*dx+dy*dy)*(dxs*dxs+dys*dys);
  95.   if (norm == 0) return 0;
  96.   cosfi /= sqrt( norm );
  97.   if (cosfi >=  1.0 ) return 0;
  98.   if (cosfi <= -1.0 ) return LEDA_PI;
  99.   
  100.   fi=acos(cosfi);
  101.   if (dx*dys-dy*dxs>0) return fi;
  102.   return -fi;
  103. }
  104. double segment::distance(const segment& s) const
  105. { if (angle(s)!=0) return 0;
  106.   return distance(s.ptr()->start);
  107.  }
  108. double  segment::distance() const
  109. { return distance(point(0,0)); }
  110. double segment::distance(const point& p) const
  111. { segment s(ptr()->start,p);
  112.   double l = s.length();
  113.   if (l==0) return 0;
  114.   else return l*sin(angle(s));
  115.  }
  116. double  segment::y_proj(double x)  const
  117. { return  ptr()->start.ptr()->y - ptr()->slope * (ptr()->start.ptr()->x - x); }
  118. double  segment::x_proj(double y)  const
  119. { if (vertical())  return  ptr()->start.ptr()->x;
  120.   return  ptr()->start.ptr()->x - (ptr()->start.ptr()->y - y)/ptr()->slope; }
  121. bool segment::intersection(const segment& s, point& inter) const
  122. { double cx,cy;
  123.   if (slope() == s.slope()) return false;
  124.   if (start() == s.start() || start() == s.end())
  125.   { inter = start();
  126.     return true;
  127.    }
  128.   if (end() == s.start() || end() == s.end())
  129.   { inter = end();
  130.     return true;
  131.    }
  132.   if (vertical())
  133.      cx = xcoord1();
  134.   else
  135.      if (s.vertical())
  136.         cx = s.xcoord1();
  137.      else
  138.         cx = (s.y_abs()-y_abs())/(slope()-s.slope());
  139.   // test whether cx lies in the x-ranges of both segments
  140.  
  141.   if ( xcoord1()   < cx && xcoord2()   < cx ||
  142.        xcoord1()   > cx && xcoord2()   > cx ||
  143.        s.xcoord1() < cx && s.xcoord2() < cx ||
  144.        s.xcoord1() > cx && s.xcoord2() > cx   ) return false;
  145.   if (vertical())
  146.      cy = s.slope() * cx + s.y_abs();
  147.   else
  148.      cy = slope() * cx + y_abs();
  149.   // if vertical test y-ranges too
  150.   if (vertical() && (ycoord1() < cy && ycoord2() < cy
  151.                      || ycoord1() > cy && ycoord2() > cy) ) return false;
  152.   if (s.vertical() && (s.ycoord1() < cy && s.ycoord2() < cy
  153.                        || s.ycoord1() > cy && s.ycoord2() > cy) ) return false;
  154.   inter = point(cx,cy);
  155.   return true;
  156. }
  157. bool segment::intersection_of_lines(const segment& s, point& inter) const
  158. { double cx,cy;
  159.   if (slope() == s.slope()) return false;
  160.   if (start() == s.start() || start() == s.end())
  161.   { inter = start();
  162.     return true;
  163.    }
  164.   if (end() == s.start() || end() == s.end())
  165.   { inter = end();
  166.     return true;
  167.    }
  168.   if (vertical())
  169.      cx = xcoord1();
  170.   else
  171.      if (s.vertical())
  172.         cx = s.xcoord1();
  173.      else
  174.         cx = (s.y_abs()-y_abs())/(slope()-s.slope());
  175.   if (vertical())
  176.      cy = s.slope() * cx + s.y_abs();
  177.   else
  178.      cy = slope() * cx + y_abs();
  179.   inter = point(cx,cy);
  180.   return true;
  181. }
  182. segment segment::rotate(double alpha) const
  183. { point p = start();
  184.   point q = end();
  185.   return segment(p,q.rotate(p,alpha));
  186. }
  187. segment segment::rotate(const point& origin, double alpha) const
  188. {  point p = start().rotate(origin,alpha);
  189.    point q = end().rotate(origin,alpha);
  190.    return segment(p,q);
  191. }
  192. segment segment::rotate90() const
  193. { return segment(start(),point(xcoord1()-dy(),ycoord1()+dx())); }
  194. segment segment::rotate90(const point& origin) const
  195. {  return segment(start().rotate90(origin),end().rotate90(origin)); }