home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / freedraft.tar.gz / freedraft.tar / FREEdraft-050298 / GEOMLIB2D / arc.cpp < prev    next >
C/C++ Source or Header  |  1998-05-01  |  6KB  |  202 lines

  1. // arc.cpp
  2.  
  3.  
  4. // Copyright (C) 1997  Cliff Johnson                                       //
  5. //                                                                         //
  6. // This program is free software; you can redistribute it and/or           //
  7. // modify it under the terms of the GNU  General Public                    //
  8. // License as published by the Free Software Foundation; either            //
  9. // version 2 of the License, or (at your option) any later version.        //
  10. //                                                                         //
  11. // This software is distributed in the hope that it will be useful,        //
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of          //
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       //
  14. // General Public License for more details.                                //
  15. //                                                                         //
  16. // You should have received a copy of the GNU General Public License       //
  17. // along with this software (see COPYING.LIB); if not, write to the        //
  18. // Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. //
  19.  
  20.  
  21. #include "arc.h"
  22. #include "geom_enum.h"
  23. #include <math.h>
  24.  
  25. #include "circle.h"
  26.  
  27. #include "geomexception.h"
  28.  
  29. //====================================================================================
  30. // unit arc  - default constructor
  31.  
  32. Arc::Arc():Geom(ARC)        // default is unit radius arc at origin in quadrant 1 
  33. {
  34.     center = Point();
  35.     origin = Point(1,0);
  36.     endpoint = Point(0,1);
  37.     arcAngle = M_PI/2.;
  38. }
  39.  
  40. //====================================================================================
  41. // Arc by center ,origin, endpoint
  42. // arcs are always interpreted right-handed from origin to endpoint
  43.  
  44. Arc::Arc(const Point& c, const Point& o, const Point& e)throw (GeomException)
  45.     :Geom(ARC),center(c), origin(o)
  46. {
  47.  
  48. // c == o - degenerate circles are not allowed
  49.     if( c == origin )
  50.         throw GeomException("Arc::Arc(c,o,e) : center and origin are coincident");
  51.  
  52. // origin and endpoint equal means full arc
  53.     if( c == e )
  54.     {
  55.         endpoint = o;
  56.         arcAngle = 2 * M_PI; // closed arc
  57.     }
  58. // regular case, are RH until intersection of arc with vector ce
  59.     else 
  60.     {
  61.         Vector dir= e - c; 
  62.         dir = dir.Normal();    // should never throw null vector
  63.                     // exception because we know c != e from above :)
  64.                     // gosh I hope that's true!
  65.  
  66.         endpoint = c + ( c.Distance(origin) * dir);
  67.         if(endpoint == origin)
  68.         {
  69.             arcAngle = 2 * M_PI; // closed arc
  70.         }
  71.         else 
  72.         {
  73.             Vector v = o - c; 
  74.             arcAngle = Angle(dir,v); // open arc
  75. // determine direction 
  76.             Vector vx = Cross(v,dir);
  77.             if(vx[2] < 0)arcAngle = (2 * M_PI) - arcAngle;
  78.         }
  79.     }
  80. }
  81.  
  82. //====================================================================================
  83. double Arc::Radius() const
  84. {
  85.     return center.Distance(origin);
  86. }
  87. //====================================================================================
  88.  
  89. Point Arc::U(double u) const
  90. {
  91.     Vector v = origin - center;
  92.  
  93.     double sine = sin(u * arcAngle);
  94.     double cosine = cos(u * arcAngle);
  95.  
  96.     return center + Point( v[0]*cosine - v[1]*sine, v[0]*sine + v[1]*cosine);
  97. }
  98.  
  99. //====================================================================================
  100. ostream& operator<<(ostream& os, const Arc& c)
  101. {
  102.     os << "Arc: center= " << c.center << " origin= " << c.origin << " endpoint= " << c.endpoint;
  103.     return os;
  104. }
  105.  
  106. //====================================================================================
  107. Point Arc::Project(const Point& p ) const throw (GeomException)
  108. {
  109. // return the point projected on the arc. Throw exception if projection is not within
  110. // arc domain or point is at arc center
  111.     if(p == center) throw GeomException("Arc::Project() : Point is at Arc center");
  112.  
  113.     Vector v1 = origin - center;
  114.  
  115.     // vector from center to point
  116.     Vector v2 = p - center;
  117.  
  118.     // determine the angle of the point with respect the v1
  119.     double ang = Angle(origin - center,v2);
  120.  
  121.     Point cross = Cross(v1,v2);
  122.     if(cross[2] < 0)ang = ang + M_PI; // quadrant III and IV 
  123.  
  124.     if(ang > arcAngle)throw GeomException("Arc::Project() : Point does not project onto arc");
  125.  
  126.     return center + ( v2.Normal() * Radius() ) ;
  127. }
  128.  
  129. //====================================================================================
  130.  
  131. double Arc::UProject(const Point& p ) const throw (GeomException)
  132. {
  133. // return the u value of a projected point
  134. // throw exception if point is not within the domain of the arc
  135. // or point is at center
  136.  
  137.     if(p == center) throw GeomException("Arc::UProject() : Point is at Arc center");
  138.  
  139.     Vector v1 = origin - center;
  140.  
  141.     // vector from center to point
  142.     Vector v2 = p - center;
  143.  
  144.     // determine the angle of the point with respect the v1
  145.     double ang = Angle(origin - center,v2);
  146.  
  147.     Point cross = Cross(v1,v2);
  148.     if(cross[2] < 0)ang = ang + M_PI; // quadrant III and IV 
  149.  
  150.     if(ang > arcAngle)throw GeomException("Arc::UProject() : Point does not project onto arc");
  151.  
  152.     return ang / arcAngle; // return ratio dude. 
  153. }
  154.  
  155. //====================================================================================
  156. Circle Arc::Support() const
  157. {
  158.     return Circle(center,origin);
  159. }
  160.  
  161. //====================================================================================
  162.  
  163. double Arc::Distance(const Point& p ) const
  164. {
  165. // you might think by the nature of selection, you should get the correct 
  166. // solution... but then consider arcs... oh oh. :(
  167.  
  168.     if(p == center) return Radius();
  169.  
  170.         // vector from center to point
  171.         Vector v = p - center;
  172.  
  173. // normalize v
  174.     v = v.Normal();        // should never throw null vector exception
  175.                 // because of above check :)
  176.  
  177. // find a valid solution - or none. 
  178.     Vector vco = origin - center;
  179.  
  180. // case 1 
  181.     double ang = Angle(vco,v);
  182.     Vector px = Cross(vco,v);
  183.         if(px[2]<0)ang = 2 * M_PI - ang;
  184.     if ( 0 < ang && ang < ArcAngle()) return  p.Distance(center + Radius() * v);
  185.  
  186. // case 2 
  187.     double d0;
  188.     ang = ang + M_PI;
  189.     if(ang > (2*M_PI))ang = ang - 2 * M_PI;
  190.     if ( 0 < ang && ang < ArcAngle())d0 = p.Distance(center - Radius() * v);
  191.     else d0 = 1e+99;
  192.  
  193. // case 3,4
  194.  
  195.     double d1 = p.Distance(origin);
  196.     double d2 = p.Distance(endpoint);
  197.  
  198.     if(d0 < d1 && d0 < d2) return d0;
  199.     if(d1 < d2) return d1;
  200.     return d2;
  201. }
  202.