home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / yacl-012.zip / ui / chord.cxx < prev    next >
C/C++ Source or Header  |  1995-04-05  |  6KB  |  238 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6. /*
  7.  *
  8.  *          Copyright (C) 1994, M. A. Sridhar
  9.  *  
  10.  *
  11.  *     This software is Copyright M. A. Sridhar, 1994. You are free
  12.  *     to copy, modify or distribute this software  as you see fit,
  13.  *     and to use  it  for  any  purpose, provided   this copyright
  14.  *     notice and the following   disclaimer are included  with all
  15.  *     copies.
  16.  *
  17.  *                        DISCLAIMER
  18.  *
  19.  *     The author makes no warranties, either expressed or implied,
  20.  *     with respect  to  this  software, its  quality, performance,
  21.  *     merchantability, or fitness for any particular purpose. This
  22.  *     software is distributed  AS IS.  The  user of this  software
  23.  *     assumes all risks  as to its quality  and performance. In no
  24.  *     event shall the author be liable for any direct, indirect or
  25.  *     consequential damages, even if the  author has been  advised
  26.  *     as to the possibility of such damages.
  27.  *
  28.  */
  29.  
  30. #if defined(__GNUC__)
  31. #pragma implementation
  32. #endif
  33.  
  34.  
  35. #include "ui/rectangl.h"
  36. #include "ui/arc.h"
  37. #include "ui/applic.h"
  38. #include "ui/cntroler.h"
  39. #include "ui/dwgsurf.h"
  40. #include "ui/lineseg.h"
  41. #include "ui/ellipse.h"
  42. #include "ui/chord.h"
  43. #include "ui/grutils.h"
  44.  
  45. #include <math.h>
  46. #include <stdlib.h>
  47.  
  48.  
  49. #ifndef M_PI
  50. #define M_PI 3.1415926535897932
  51. #endif
  52.  
  53. #include <iostream.h> // DEBUG
  54.  
  55. UI_Chord::UI_Chord (const UI_Rectangle& boundingRect, long startAngleDeg64,
  56.                     long subtendedDeg64)
  57. : _startAngle (startAngleDeg64),  _subtAngle (subtendedDeg64)
  58. {
  59.     UI_Point p = boundingRect.Center();
  60.     _xOrigin   = p.XCoord();
  61.     _yOrigin   = p.YCoord();
  62.     _major     = boundingRect.Width();
  63.     _minor     = boundingRect.Height();
  64. }
  65.  
  66.  
  67.  
  68. UI_Chord::UI_Chord (const UI_Point& p1, const UI_Point& p2,
  69.                     const UI_Point& origin)
  70. {
  71.     UI_Arc arc (p1, p2, origin);
  72.     _startAngle = arc.StartAngle();
  73.     _subtAngle  = arc.SubtendedAngle();
  74.     _xOrigin    = origin.XCoord();
  75.     _yOrigin    = origin.YCoord();
  76.     UI_Rectangle r = arc.Ellipse().BoundingRectangle();
  77.     _major = r.Width ();
  78.     _major = r.Height ();
  79. }
  80.  
  81.  
  82.  
  83. bool UI_Chord::DrawOn (UI_DrawingSurface& sfc, const UI_Point& p) const
  84. {
  85.     if (p != UI_Point (0, 0)) {
  86.         UI_Chord a (Ellipse().BoundingRectangle() + p,
  87.                     _startAngle, _subtAngle);
  88.         sfc.DrawChord (a, UID_Outline);
  89.     }
  90.     else
  91.         sfc.DrawChord (*this, UID_Outline);
  92.     return TRUE;
  93. }
  94.  
  95.  
  96.  
  97. bool UI_Chord::Fill (UI_DrawingSurface& sfc) const
  98. {
  99.     sfc.DrawChord (*this, UID_Fill);
  100.     return TRUE;
  101. }
  102.  
  103.  
  104.  
  105. bool UI_Chord::ReshapeTo (const UI_Point& p1, const UI_Point& p2)
  106. {
  107.     if (!PrepareToChange())
  108.         return FALSE;
  109.     UI_Arc arc (p1, p2, UI_Point (_xOrigin, _yOrigin));
  110.     _startAngle = arc.StartAngle();
  111.     _subtAngle  = arc.SubtendedAngle();
  112.     Notify();
  113.     return TRUE;
  114. }
  115.  
  116.  
  117.  
  118. void UI_Chord::StartAngle (long startAngle64)
  119. {
  120.     if (PrepareToChange ()) {
  121.         _startAngle = startAngle64;
  122.         Notify ();
  123.     }
  124. }
  125.  
  126.  
  127.  
  128. void UI_Chord::SubtendedAngle (long subtAngle64)
  129. {
  130.     if (PrepareToChange()) {
  131.         _subtAngle   = subtAngle64;
  132.         Notify ();
  133.     }
  134. }
  135.  
  136.  
  137.  
  138. void UI_Chord::Origin (const UI_Point& origin)
  139. {
  140.     if (PrepareToChange()) {
  141.         _xOrigin = origin.XCoord();
  142.         _yOrigin = origin.YCoord();
  143.         Notify ();
  144.     }
  145. }
  146.  
  147.  
  148.  
  149.  
  150.  
  151.  
  152. UI_Rectangle UI_Chord::BoundingRectangle () const
  153. {
  154.     return Ellipse().BoundingRectangle();
  155. }
  156.  
  157.  
  158.  
  159. UI_Ellipse UI_Chord::Ellipse() const
  160. {
  161.     return UI_Ellipse (_major, _minor, UI_Point (_xOrigin, _yOrigin));
  162. }
  163.  
  164.  
  165.  
  166. UI_PointPair UI_Chord::EndPoints () const
  167. {
  168.     return Arc().EndPoints();
  169. }
  170.  
  171.  
  172. bool UI_Chord::IntersectsBoundary (const UI_Rectangle& r) const
  173. {
  174.     return Arc().IntersectsBoundary (r) || Line().IntersectsBoundary (r);
  175. }
  176.  
  177.  
  178. UI_LineSegment UI_Chord::Line () const
  179. {
  180.     UI_PointPair pair = EndPoints ();
  181.     return UI_LineSegment (pair.p1, pair.p2);
  182. }
  183.  
  184.  
  185. UI_Arc UI_Chord::Arc () const
  186. {
  187.     UI_Rectangle r (_xOrigin - _major/2, _yOrigin - _minor/2, _major, _minor);
  188.     return UI_Arc (r, _startAngle, _subtAngle);
  189. }
  190.  
  191.  
  192.  
  193. UI_Chord& UI_Chord::operator= (const UI_Chord& c)
  194. {
  195.     if (PrepareToChange()) {
  196.         _startAngle =  c._startAngle; 
  197.         _subtAngle  =  c._subtAngle;  
  198.         _xOrigin    =  c._xOrigin;    
  199.         _yOrigin    =  c._yOrigin;    
  200.         _major      =  c._major;      
  201.         _minor      =  c._minor;      
  202.         Notify();
  203.     }
  204.     return *this;
  205. }
  206.  
  207.  
  208. UI_HitTest UI_Chord::HitTest (const UI_Point& p) const
  209. {
  210.     UI_Point center = Center ();
  211.     long x = p.XCoord() - center.XCoord(), y = center.YCoord() - p.YCoord();
  212.     double pAngle; // Can't use a conditional: Borland doesn't compile it right
  213.     if (x != 0)
  214.         pAngle = RadToDeg (atan2 (y, x));
  215.     else if (y > 0)
  216.         pAngle = 270;
  217.     else
  218.         pAngle = 90;
  219.     if (pAngle < _startAngle / 64.0 ||
  220.         pAngle > (_startAngle + _subtAngle) / 64.0)
  221.         return UIHit_Outside;
  222.     UI_HitTest tst = Ellipse().HitTest (p);
  223.     if (tst != UIHit_Inside)
  224.         return tst;
  225.     // So p is inside the ellipse.
  226.     UI_LineSegment chord = Line ();
  227.     if (chord.OnBoundary (p))
  228.         return UIHit_Boundary;
  229.     if (chord.OnBoundary (center))
  230.         return UIHit_Inside;
  231.  
  232.     // Shoot a ray from the ellipse's center to p
  233.     UI_LineSegment ray (center, p);
  234.     if (ray.Intersects (chord))
  235.         return _subtAngle / 64.0 > 180 ? UIHit_Outside : UIHit_Inside;
  236.     return UIHit_Outside;
  237. }
  238.