home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
yacl-012.zip
/
ui
/
chord.cxx
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-05
|
6KB
|
238 lines
/*
*
* Copyright (C) 1994, M. A. Sridhar
*
*
* This software is Copyright M. A. Sridhar, 1994. You are free
* to copy, modify or distribute this software as you see fit,
* and to use it for any purpose, provided this copyright
* notice and the following disclaimer are included with all
* copies.
*
* DISCLAIMER
*
* The author makes no warranties, either expressed or implied,
* with respect to this software, its quality, performance,
* merchantability, or fitness for any particular purpose. This
* software is distributed AS IS. The user of this software
* assumes all risks as to its quality and performance. In no
* event shall the author be liable for any direct, indirect or
* consequential damages, even if the author has been advised
* as to the possibility of such damages.
*
*/
#if defined(__GNUC__)
#pragma implementation
#endif
#include "ui/rectangl.h"
#include "ui/arc.h"
#include "ui/applic.h"
#include "ui/cntroler.h"
#include "ui/dwgsurf.h"
#include "ui/lineseg.h"
#include "ui/ellipse.h"
#include "ui/chord.h"
#include "ui/grutils.h"
#include <math.h>
#include <stdlib.h>
#ifndef M_PI
#define M_PI 3.1415926535897932
#endif
#include <iostream.h> // DEBUG
UI_Chord::UI_Chord (const UI_Rectangle& boundingRect, long startAngleDeg64,
long subtendedDeg64)
: _startAngle (startAngleDeg64), _subtAngle (subtendedDeg64)
{
UI_Point p = boundingRect.Center();
_xOrigin = p.XCoord();
_yOrigin = p.YCoord();
_major = boundingRect.Width();
_minor = boundingRect.Height();
}
UI_Chord::UI_Chord (const UI_Point& p1, const UI_Point& p2,
const UI_Point& origin)
{
UI_Arc arc (p1, p2, origin);
_startAngle = arc.StartAngle();
_subtAngle = arc.SubtendedAngle();
_xOrigin = origin.XCoord();
_yOrigin = origin.YCoord();
UI_Rectangle r = arc.Ellipse().BoundingRectangle();
_major = r.Width ();
_major = r.Height ();
}
bool UI_Chord::DrawOn (UI_DrawingSurface& sfc, const UI_Point& p) const
{
if (p != UI_Point (0, 0)) {
UI_Chord a (Ellipse().BoundingRectangle() + p,
_startAngle, _subtAngle);
sfc.DrawChord (a, UID_Outline);
}
else
sfc.DrawChord (*this, UID_Outline);
return TRUE;
}
bool UI_Chord::Fill (UI_DrawingSurface& sfc) const
{
sfc.DrawChord (*this, UID_Fill);
return TRUE;
}
bool UI_Chord::ReshapeTo (const UI_Point& p1, const UI_Point& p2)
{
if (!PrepareToChange())
return FALSE;
UI_Arc arc (p1, p2, UI_Point (_xOrigin, _yOrigin));
_startAngle = arc.StartAngle();
_subtAngle = arc.SubtendedAngle();
Notify();
return TRUE;
}
void UI_Chord::StartAngle (long startAngle64)
{
if (PrepareToChange ()) {
_startAngle = startAngle64;
Notify ();
}
}
void UI_Chord::SubtendedAngle (long subtAngle64)
{
if (PrepareToChange()) {
_subtAngle = subtAngle64;
Notify ();
}
}
void UI_Chord::Origin (const UI_Point& origin)
{
if (PrepareToChange()) {
_xOrigin = origin.XCoord();
_yOrigin = origin.YCoord();
Notify ();
}
}
UI_Rectangle UI_Chord::BoundingRectangle () const
{
return Ellipse().BoundingRectangle();
}
UI_Ellipse UI_Chord::Ellipse() const
{
return UI_Ellipse (_major, _minor, UI_Point (_xOrigin, _yOrigin));
}
UI_PointPair UI_Chord::EndPoints () const
{
return Arc().EndPoints();
}
bool UI_Chord::IntersectsBoundary (const UI_Rectangle& r) const
{
return Arc().IntersectsBoundary (r) || Line().IntersectsBoundary (r);
}
UI_LineSegment UI_Chord::Line () const
{
UI_PointPair pair = EndPoints ();
return UI_LineSegment (pair.p1, pair.p2);
}
UI_Arc UI_Chord::Arc () const
{
UI_Rectangle r (_xOrigin - _major/2, _yOrigin - _minor/2, _major, _minor);
return UI_Arc (r, _startAngle, _subtAngle);
}
UI_Chord& UI_Chord::operator= (const UI_Chord& c)
{
if (PrepareToChange()) {
_startAngle = c._startAngle;
_subtAngle = c._subtAngle;
_xOrigin = c._xOrigin;
_yOrigin = c._yOrigin;
_major = c._major;
_minor = c._minor;
Notify();
}
return *this;
}
UI_HitTest UI_Chord::HitTest (const UI_Point& p) const
{
UI_Point center = Center ();
long x = p.XCoord() - center.XCoord(), y = center.YCoord() - p.YCoord();
double pAngle; // Can't use a conditional: Borland doesn't compile it right
if (x != 0)
pAngle = RadToDeg (atan2 (y, x));
else if (y > 0)
pAngle = 270;
else
pAngle = 90;
if (pAngle < _startAngle / 64.0 ||
pAngle > (_startAngle + _subtAngle) / 64.0)
return UIHit_Outside;
UI_HitTest tst = Ellipse().HitTest (p);
if (tst != UIHit_Inside)
return tst;
// So p is inside the ellipse.
UI_LineSegment chord = Line ();
if (chord.OnBoundary (p))
return UIHit_Boundary;
if (chord.OnBoundary (center))
return UIHit_Inside;
// Shoot a ray from the ellipse's center to p
UI_LineSegment ray (center, p);
if (ray.Intersects (chord))
return _subtAngle / 64.0 > 180 ? UIHit_Outside : UIHit_Inside;
return UIHit_Outside;
}