home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / yacl-012.zip / ui / arc.cxx < prev    next >
C/C++ Source or Header  |  1995-04-05  |  7KB  |  246 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/applic.h"
  37. #include "ui/cntroler.h"
  38. #include "ui/dwgsurf.h"
  39. #include "ui/ellipse.h"
  40. #include "ui/arc.h"
  41. #include "ui/grutils.h"
  42.  
  43. #include <math.h>
  44. #include <stdlib.h>
  45.  
  46. #ifndef M_PI
  47. #define M_PI 3.1415926535897932
  48. #endif
  49.  
  50. #define TO_RAD64(p) ((p/64)*M_PI/180)
  51. #define TO_DEG64(p) (((p*180)/M_PI)*64)
  52.  
  53.  
  54. UI_Arc::UI_Arc (const UI_Rectangle &boundingRect, long startAngleDeg64,
  55.                 long subtendedDeg64)
  56. {
  57.     _boundingEllipse = boundingRect;
  58.     _startAngle      = startAngleDeg64;
  59.     _subtAngle       = subtendedDeg64;
  60. }
  61.  
  62.  
  63.  
  64. UI_Arc::UI_Arc (const UI_Point &p1, const UI_Point &p2, const UI_Point &origin)
  65. {
  66.     float xdiff  = p1.XCoord()     - origin.XCoord();
  67.     float ydiff  = origin.YCoord() - p1.YCoord();
  68.     float angle = 0;
  69.     long startangle = 0, subtangle = 0;
  70.  
  71.     if (xdiff == 0) return;
  72.     angle = atan2 (ydiff, xdiff);
  73.     if (angle < 0) {
  74.         angle = M_PI + (M_PI + angle);
  75.     }
  76.     startangle = (long) TO_DEG64 (angle);
  77.     _startAngle = startangle;
  78.     xdiff       = p2.XCoord()     - origin.XCoord();
  79.     ydiff       = origin.YCoord() - p2.YCoord();
  80.     if (xdiff == 0) return;
  81.     angle = atan2 (ydiff, xdiff);
  82.     if (angle < 0) {
  83.         angle = M_PI + (M_PI + angle);
  84.     }
  85.     if (_startAngle > (long) TO_DEG64 (angle)) 
  86.         angle  = 2*M_PI + angle; 
  87.     subtangle  = (long) TO_DEG64 (angle) - _startAngle;
  88.     _subtAngle = subtangle;
  89.  
  90.     float p = cos (TO_RAD64(startangle));
  91.     float q = sin (TO_RAD64(startangle));
  92.     float major = 0, minor = 0;
  93.  
  94.     if (p == 0) major = 0;
  95.     else
  96.         major       = (p1.XCoord() - origin.XCoord())/p;
  97.     if (q == 0) minor = 0;
  98.     else 
  99.         minor       = (origin.YCoord() - p1.YCoord())/q;
  100.     
  101.     UI_Point start ((long) origin.XCoord() - (long) major/2, 
  102.                     (long) origin.YCoord() - (long) minor/2);
  103.     
  104.     _boundingEllipse = UI_Rectangle (start, (long)major, (long)minor);
  105. }
  106.  
  107.  
  108.  
  109.  
  110. bool UI_Arc::DrawOn (UI_DrawingSurface& sfc, const UI_Point &p) const
  111. {
  112.     if (p != UI_Point (0, 0)) {
  113.         UI_Arc a (_boundingEllipse + p, _startAngle, _subtAngle);
  114.         sfc.DrawArc (a);
  115.     }
  116.     else sfc.DrawArc (*this);
  117.  
  118.     return TRUE;
  119. }
  120.  
  121.  
  122.  
  123.  
  124. bool UI_Arc::ReshapeTo (const UI_Point &p1, const UI_Point &p2)
  125. {
  126.     if (p1.XCoord () > p2.XCoord())
  127.         _boundingEllipse = UI_Rectangle (p2.XCoord(), p1.YCoord(),
  128.                                          p1.XCoord() - p2.XCoord(),
  129.                                          p2.YCoord() - p1.YCoord());
  130.     else
  131.         _boundingEllipse = UI_Rectangle (p1.XCoord(), p1.YCoord(),
  132.                                          p2.XCoord() - p1.XCoord(),
  133.                                          p2.YCoord() - p1.YCoord());
  134.     return TRUE;
  135. }
  136.  
  137.  
  138.  
  139. void UI_Arc::StartAngle (long startAngle64)
  140. {
  141.     _startAngle = startAngle64;
  142. }
  143.  
  144.  
  145.  
  146. void UI_Arc::SubtendedAngle (long subtAngle64)
  147. {
  148.     _subtAngle   = subtAngle64;
  149. }
  150.  
  151.  
  152.  
  153. void UI_Arc::Origin (const UI_Point &origin)
  154. {
  155.     _boundingEllipse.Origin (origin);
  156. }
  157.  
  158.  
  159.  
  160. UI_Ellipse UI_Arc::Ellipse() const
  161. {
  162.     return UI_Ellipse (_boundingEllipse);
  163. }
  164.  
  165.  
  166.  
  167. UI_Rectangle UI_Arc::BoundingRectangle () const
  168. {
  169.     return Ellipse().BoundingRectangle();
  170. }
  171.  
  172.  
  173.  
  174. UI_PointPair UI_Arc::EndPoints() const
  175. {
  176.     long r1 = _boundingEllipse.Width()/2;
  177.     long r2 = _boundingEllipse.Height()/2;
  178.     short centerx    = _boundingEllipse.Width()/2 + _boundingEllipse.Left();
  179.     short centery    = _boundingEllipse.Height()/2 + _boundingEllipse.Top();
  180.     long startangle = 0, ssangle = 0;
  181.  
  182.     startangle = _startAngle;
  183.     ssangle    = _startAngle + _subtAngle;
  184.  
  185.     double x1 = r1 *  cos (TO_RAD64(startangle));
  186.     double y1 = r2 *  sin (TO_RAD64(startangle));
  187.     double x2 = r1 *  cos (TO_RAD64((ssangle)));
  188.     double y2 = r2 *  sin (TO_RAD64((ssangle)));
  189.  
  190.     x2 += centerx;
  191.     x1 += centerx;
  192.     if (y2 >= 0)  y2 -= centery;
  193.     else          y2  = abs ((long) y2) + centery;
  194.     if (y1 >= 0)  y1 -= centery;
  195.     else          y1  = abs ((long) y1) + centery;
  196.  
  197.     return UI_PointPair (UI_Point ((long) x1, (long) abs ((long) y1)),
  198.                          UI_Point ((long) x2, (long) abs ((long) y2)));
  199. }
  200.  
  201.  
  202.  
  203. bool UI_Arc::IntersectsBoundary (const UI_Rectangle& r) const
  204. {
  205.     long topx    = r.Left();
  206.     long topy    = r.Top();
  207.     long a       = _boundingEllipse.Width();
  208.     long b       = _boundingEllipse.Height();
  209.     long centerx = a/2 + _boundingEllipse.Left();
  210.     long centery = b/2 + _boundingEllipse.Top();
  211.     topx = centerx - topx;
  212.     topy = centery - topy;
  213.  
  214.     float lhs = (topx*topx)/(a*a) + (topy*topy)/(b*b);
  215.     if (abs ((long)(lhs - 1.00)) <= 1) return TRUE;
  216.     else return FALSE;
  217. }
  218.  
  219.  
  220.  
  221. UI_HitTest UI_Arc::HitTest (const UI_Point& p) const
  222. {
  223.     UI_Ellipse e = Ellipse();
  224.     UI_Point center = e.Center();
  225.     double x = p.XCoord() - center.XCoord();
  226.     double y = p.YCoord() - center.YCoord();
  227.     // Borland is buggy. The following conditional does not compute the
  228.     // correct result.
  229.     //     double angle = (x == 0) ? (y > 0 ? M_PI/2 : 1.5 * M_PI)
  230.     //         : atan2 (y, x);
  231.     // So we say:
  232.     double angle;
  233.     if (x == 0) {
  234.         if (y > 0)
  235.             angle = M_PI/2;
  236.         else
  237.             angle = 1.5 * M_PI;
  238.     }
  239.     else angle = atan2 (y, x);
  240.     if (angle < 0)
  241.         angle += 2 * M_PI;
  242.     return angle >= DegToRad (_startAngle / 64.0) &&
  243.         angle <= DegToRad ((_startAngle + _subtAngle) / 64.0) &&
  244.         e.HitTest (p) == UIHit_Boundary ? UIHit_Boundary : UIHit_Outside;
  245. }
  246.