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

MultiPlatform

  1. /*******************************************************************************
  2. +
  3. +  LEDA-R  3.2.3
  4. +
  5. +  _circle.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/circle.h>
  12. #include <math.h>
  13. //------------------------------------------------------------------------------
  14. // circles
  15. //------------------------------------------------------------------------------
  16. circle::circle() 
  17. { PTR = new circle_rep; }
  18. circle::circle(const point& c, double r)       
  19. { PTR = new circle_rep(c,r); }
  20. circle::circle(double x, double y, double r)  
  21. { PTR = new circle_rep(point(x,y),r); }
  22. circle::circle(const point& a, const point& b, const point& c)
  23. { if (collinear(a,b,c)) 
  24.      error_handler(1,"circle::circle(a,b,c): points are collinear.");
  25.   line l1 = p_bisector(a,b);
  26.   line l2 = p_bisector(b,c);
  27.   point m;
  28.   l1.intersection(l2,m);
  29.   PTR = new circle_rep(m,m.distance(a));
  30.  }
  31.   
  32. bool circle::operator==(const circle& c)  const
  33. { return ptr()->center == c.ptr()->center && ptr()->radius == c.ptr()->radius; }
  34. double circle::distance(const point& p) const
  35. { double d = p.distance(ptr()->center);
  36.   return (d - ptr()->radius);
  37.  }
  38. double circle::distance(const line& l) const
  39. { double d = l.distance(ptr()->center);
  40.   return (d - ptr()->radius);
  41.  }
  42. double circle::distance(const circle& c) const
  43. { double d = ptr()->center.distance(c.ptr()->center);
  44.   return (d - ptr()->radius - c.ptr()->radius);
  45.  }
  46. bool circle::inside(const point& p) const 
  47. { return distance(p)<=0; }
  48. circle circle::translate(double alpha, double d) const
  49. { point p = ptr()->center.translate(alpha,d);
  50.   return circle(p,ptr()->radius);
  51.  }
  52. circle circle::translate(const vector& v) const
  53. { point p = ptr()->center.translate(v);
  54.   return circle(p,ptr()->radius);
  55.  }
  56. circle  circle::rotate(const point& o, double alpha) const
  57. { return circle(ptr()->center.rotate(o,alpha),ptr()->radius); 
  58.  }
  59. circle  circle::rotate(double alpha)          const
  60. { return rotate(point(0,0),alpha);
  61.  }
  62. list<point> circle::intersection(const line& l) const
  63. { list<point> result;
  64.   segment s = l.perpendicular(ptr()->center);
  65.   double  d = s.length();
  66.   double  r = ptr()->radius;
  67.   point   F = s.end();
  68.   if (d==r) result.append(F);
  69.   
  70.   if (d < r)
  71.   { double alpha = l.angle();
  72.     double x = sqrt(r*r - d*d);
  73.     point  p = F.translate(alpha,x);
  74.     point  q = F.translate(alpha,-x);
  75.     result.append(q);
  76.     result.append(p);
  77.   }
  78.   return result;
  79. }
  80. list<point> circle::intersection(const segment& s) const
  81. { list<point> result,L;
  82.   L = intersection(line(s));
  83.   point p;
  84.   double  d  = s.length();
  85.   forall(p,L)
  86.   { double d1 = s.ptr()->start.distance(p);
  87.     double d2 = s.ptr()->end.distance(p);
  88.     if (d1 <= d && d2 <= d) result.append(p);
  89.    }
  90.   return result;
  91. }
  92. list<point> circle::intersection(const circle& c) const
  93. { list<point> result;
  94.   segment s(ptr()->center, c.ptr()->center);
  95.   double d  = s.length();
  96.   double r1 = ptr()->radius;
  97.   double r2 = c.ptr()->radius;
  98.   if (d > (r1+r2) || (d+r2) < r1 || (d+r1) < r2) return result;
  99.   double x = (d*d + r1*r1 - r2*r2)/(2*d);
  100.   double alpha = acos(x/r1);
  101.   double beta  = s.angle() + alpha;
  102.   double gamma = s.angle() - alpha;
  103.   result.append(ptr()->center.translate(beta,r1));
  104.   if (alpha!=0) result.append(ptr()->center.translate(gamma,r1));
  105.   return result;
  106.  }
  107. segment circle::left_tangent(const point& p) const
  108. { if (inside(p)) error_handler(1,"left_tangent:: point inside circle");
  109.   segment s(p,ptr()->center);
  110.   double d = s.length();
  111.   double alpha = asin(ptr()->radius/d) + s.angle();
  112.   point touch = p.translate(alpha,sqrt(d*d - ptr()->radius*ptr()->radius));
  113.   return segment(p,touch);
  114. }
  115. segment circle::right_tangent(const point& p) const
  116. { if (inside(p)) error_handler(1,"right_tangent:: point inside circle");
  117.   segment s(p,ptr()->center);
  118.   double d = s.length();
  119.   double alpha = s.angle() - asin(ptr()->radius/d);
  120.   point touch = p.translate(alpha,sqrt(d*d - ptr()->radius*ptr()->radius));
  121.   return segment(p,touch);
  122. }
  123. ostream& operator<<(ostream& out, const circle& c) 
  124. { out << c.center() << " "<< c.radius(); 
  125.   return out;
  126.  } 
  127. istream& operator>>(istream& in,  circle& c) 
  128. { point cent;
  129.   double rad;
  130.   if (in) in >> cent;
  131.   if (in) in >> rad;
  132.   c = circle(cent,rad);
  133.   return in;
  134. }