home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / leda / src / plane / _circle.c next >
Encoding:
C/C++ Source or Header  |  1991-11-15  |  4.3 KB  |  178 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  2.1.1                                                 11-15-1991
  4. +
  5. +
  6. +  _circle.c
  7. +
  8. +
  9. +  Copyright (c) 1991  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. #include <LEDA/plane.h>
  17. #include <math.h>
  18.  
  19. static const double eps = 1e-10;
  20.  
  21. //------------------------------------------------------------------------------
  22. // circles
  23. //------------------------------------------------------------------------------
  24.  
  25.  
  26. circle_rep::circle_rep(point p, double r)  
  27. { center = p;
  28.   radius = r;
  29.   count = 1; 
  30.  }
  31.  
  32. circle_rep::circle_rep()                { count = 1; }
  33.  
  34. circle::circle()                        { ptr = new circle_rep; }
  35. circle::circle(int)                     { ptr = new circle_rep; }
  36. circle::circle(ent x)                   { ptr= (circle_rep*)x; ptr->count++; }
  37. circle::circle(circle& l)               { ptr = l.ptr; ptr->count++; }
  38. circle::circle(point c, double r)         { ptr = new circle_rep(c,r); }
  39. circle::circle(double x, double y, double r)  { ptr = new circle_rep(point(x,y),r); }
  40. void circle::clear()                    { if (--(ptr->count)==0) delete ptr; }
  41.   
  42.  
  43. int circle::operator==(const circle& c) 
  44. { double dr =  fabs(ptr->radius - c.ptr->radius);
  45.   return (ptr->center == c.ptr->center && dr < eps);
  46.  }
  47.  
  48.  
  49. double circle::distance(point p)
  50. { double d = p.distance(ptr->center);
  51.   return (d - ptr->radius);
  52.  }
  53.  
  54. double circle::distance(line l)
  55. { double d = l.distance(ptr->center);
  56.   return (d - ptr->radius);
  57.  }
  58.  
  59. double circle::distance(circle c)
  60. { double d = ptr->center.distance(c.ptr->center);
  61.   return (d - ptr->radius - c.ptr->radius);
  62.  }
  63.  
  64. bool circle::inside(point p) { return distance(p)<=0; }
  65.  
  66.  
  67. circle circle::translate(double alpha, double d)
  68. { point p = ptr->center.translate(alpha,d);
  69.   return circle(p,ptr->radius);
  70.  }
  71.  
  72. circle circle::translate(const vector& v)
  73. { point p = ptr->center.translate(v);
  74.   return circle(p,ptr->radius);
  75.  }
  76.  
  77. circle  circle::rotate(point o, double alpha)
  78. { return circle(ptr->center.rotate(o,alpha),ptr->radius); 
  79.  }
  80.  
  81. circle  circle::rotate(double alpha)         
  82. { return rotate(point(0,0),alpha);
  83.  }
  84.  
  85. segment circle::left_tangent(point p)
  86. { if (inside(p)) error_handler(1,"left_tangent:: point inside circle");
  87.   segment s(p,ptr->center);
  88.   double d = s.length();
  89.   double alpha = asin(ptr->radius/d) + s.angle();
  90.   point touch = p.translate(alpha,sqrt(d*d - ptr->radius*ptr->radius));
  91.   return segment(p,touch);
  92. }
  93.  
  94. segment circle::right_tangent(point p)
  95. { if (inside(p)) error_handler(1,"right_tangent:: point inside circle");
  96.   segment s(p,ptr->center);
  97.   double d = s.length();
  98.   double alpha = s.angle() - asin(ptr->radius/d);
  99.   point touch = p.translate(alpha,sqrt(d*d - ptr->radius*ptr->radius));
  100.   return segment(p,touch);
  101. }
  102.  
  103.  
  104. list(point) circle::intersection(line l)
  105. { list(point) result;
  106.   segment s = l.perpendicular(ptr->center);
  107.   double  d = s.length();
  108.   double  r = ptr->radius;
  109.   point   F = s.end();
  110.  
  111.   if (d==r) result.append(F);
  112.   
  113.   if (d < r)
  114.   { double alpha = l.angle();
  115.     double x = sqrt(r*r - d*d);
  116.     point  p = F.translate(alpha,x);
  117.     point  q = F.translate(alpha,-x);
  118.     result.append(q);
  119.     result.append(p);
  120.   }
  121.  
  122.   return result;
  123. }
  124.  
  125.  
  126. list(point) circle::intersection(segment s)
  127. { list(point) result,L;
  128.  
  129.   line l(s);
  130.   L = intersection(l);
  131.  
  132.   point p;
  133.   double  d  = s.length();
  134.  
  135.   forall(p,L)
  136.   { double d1 = s.ptr->start.distance(p);
  137.     double d2 = s.ptr->end.distance(p);
  138.     if (d1 <= d && d2 <= d) result.append(p);
  139.    }
  140.  
  141.   return result;
  142. }
  143.  
  144. list(point) circle::intersection(circle c)
  145. { list(point) result;
  146.   segment s(ptr->center, c.ptr->center);
  147.   double d  = s.length();
  148.   double r1 = ptr->radius;
  149.   double r2 = c.ptr->radius;
  150.  
  151.   if (d > (r1+r2) || (d+r2) < r1 || (d+r1) < r2) return result;
  152.  
  153.  
  154.   double x = (d*d + r1*r1 - r2*r2)/(2*d);
  155.   double alpha = acos(x/r1);
  156.   double beta  = s.angle() + alpha;
  157.   double gamma = s.angle() - alpha;
  158.  
  159.   result.append(ptr->center.translate(beta,r1));
  160.   if (alpha!=0) result.append(ptr->center.translate(gamma,r1));
  161.  
  162.   return result;
  163.  }
  164.  
  165.  
  166. ostream& operator<<(ostream& out, const circle& c) 
  167. { out << "(" << c.center() << "*"<< c.radius() <<")"; 
  168.   return out;
  169.  } 
  170.  
  171. istream& operator>>(istream& in,  circle& c) 
  172. { in >> c.ptr->center >> c.ptr->radius;
  173.   return in;
  174. }
  175.  
  176.  
  177.