home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
yacl-012.zip
/
ui
/
arc.cxx
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-05
|
7KB
|
246 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/applic.h"
#include "ui/cntroler.h"
#include "ui/dwgsurf.h"
#include "ui/ellipse.h"
#include "ui/arc.h"
#include "ui/grutils.h"
#include <math.h>
#include <stdlib.h>
#ifndef M_PI
#define M_PI 3.1415926535897932
#endif
#define TO_RAD64(p) ((p/64)*M_PI/180)
#define TO_DEG64(p) (((p*180)/M_PI)*64)
UI_Arc::UI_Arc (const UI_Rectangle &boundingRect, long startAngleDeg64,
long subtendedDeg64)
{
_boundingEllipse = boundingRect;
_startAngle = startAngleDeg64;
_subtAngle = subtendedDeg64;
}
UI_Arc::UI_Arc (const UI_Point &p1, const UI_Point &p2, const UI_Point &origin)
{
float xdiff = p1.XCoord() - origin.XCoord();
float ydiff = origin.YCoord() - p1.YCoord();
float angle = 0;
long startangle = 0, subtangle = 0;
if (xdiff == 0) return;
angle = atan2 (ydiff, xdiff);
if (angle < 0) {
angle = M_PI + (M_PI + angle);
}
startangle = (long) TO_DEG64 (angle);
_startAngle = startangle;
xdiff = p2.XCoord() - origin.XCoord();
ydiff = origin.YCoord() - p2.YCoord();
if (xdiff == 0) return;
angle = atan2 (ydiff, xdiff);
if (angle < 0) {
angle = M_PI + (M_PI + angle);
}
if (_startAngle > (long) TO_DEG64 (angle))
angle = 2*M_PI + angle;
subtangle = (long) TO_DEG64 (angle) - _startAngle;
_subtAngle = subtangle;
float p = cos (TO_RAD64(startangle));
float q = sin (TO_RAD64(startangle));
float major = 0, minor = 0;
if (p == 0) major = 0;
else
major = (p1.XCoord() - origin.XCoord())/p;
if (q == 0) minor = 0;
else
minor = (origin.YCoord() - p1.YCoord())/q;
UI_Point start ((long) origin.XCoord() - (long) major/2,
(long) origin.YCoord() - (long) minor/2);
_boundingEllipse = UI_Rectangle (start, (long)major, (long)minor);
}
bool UI_Arc::DrawOn (UI_DrawingSurface& sfc, const UI_Point &p) const
{
if (p != UI_Point (0, 0)) {
UI_Arc a (_boundingEllipse + p, _startAngle, _subtAngle);
sfc.DrawArc (a);
}
else sfc.DrawArc (*this);
return TRUE;
}
bool UI_Arc::ReshapeTo (const UI_Point &p1, const UI_Point &p2)
{
if (p1.XCoord () > p2.XCoord())
_boundingEllipse = UI_Rectangle (p2.XCoord(), p1.YCoord(),
p1.XCoord() - p2.XCoord(),
p2.YCoord() - p1.YCoord());
else
_boundingEllipse = UI_Rectangle (p1.XCoord(), p1.YCoord(),
p2.XCoord() - p1.XCoord(),
p2.YCoord() - p1.YCoord());
return TRUE;
}
void UI_Arc::StartAngle (long startAngle64)
{
_startAngle = startAngle64;
}
void UI_Arc::SubtendedAngle (long subtAngle64)
{
_subtAngle = subtAngle64;
}
void UI_Arc::Origin (const UI_Point &origin)
{
_boundingEllipse.Origin (origin);
}
UI_Ellipse UI_Arc::Ellipse() const
{
return UI_Ellipse (_boundingEllipse);
}
UI_Rectangle UI_Arc::BoundingRectangle () const
{
return Ellipse().BoundingRectangle();
}
UI_PointPair UI_Arc::EndPoints() const
{
long r1 = _boundingEllipse.Width()/2;
long r2 = _boundingEllipse.Height()/2;
short centerx = _boundingEllipse.Width()/2 + _boundingEllipse.Left();
short centery = _boundingEllipse.Height()/2 + _boundingEllipse.Top();
long startangle = 0, ssangle = 0;
startangle = _startAngle;
ssangle = _startAngle + _subtAngle;
double x1 = r1 * cos (TO_RAD64(startangle));
double y1 = r2 * sin (TO_RAD64(startangle));
double x2 = r1 * cos (TO_RAD64((ssangle)));
double y2 = r2 * sin (TO_RAD64((ssangle)));
x2 += centerx;
x1 += centerx;
if (y2 >= 0) y2 -= centery;
else y2 = abs ((long) y2) + centery;
if (y1 >= 0) y1 -= centery;
else y1 = abs ((long) y1) + centery;
return UI_PointPair (UI_Point ((long) x1, (long) abs ((long) y1)),
UI_Point ((long) x2, (long) abs ((long) y2)));
}
bool UI_Arc::IntersectsBoundary (const UI_Rectangle& r) const
{
long topx = r.Left();
long topy = r.Top();
long a = _boundingEllipse.Width();
long b = _boundingEllipse.Height();
long centerx = a/2 + _boundingEllipse.Left();
long centery = b/2 + _boundingEllipse.Top();
topx = centerx - topx;
topy = centery - topy;
float lhs = (topx*topx)/(a*a) + (topy*topy)/(b*b);
if (abs ((long)(lhs - 1.00)) <= 1) return TRUE;
else return FALSE;
}
UI_HitTest UI_Arc::HitTest (const UI_Point& p) const
{
UI_Ellipse e = Ellipse();
UI_Point center = e.Center();
double x = p.XCoord() - center.XCoord();
double y = p.YCoord() - center.YCoord();
// Borland is buggy. The following conditional does not compute the
// correct result.
// double angle = (x == 0) ? (y > 0 ? M_PI/2 : 1.5 * M_PI)
// : atan2 (y, x);
// So we say:
double angle;
if (x == 0) {
if (y > 0)
angle = M_PI/2;
else
angle = 1.5 * M_PI;
}
else angle = atan2 (y, x);
if (angle < 0)
angle += 2 * M_PI;
return angle >= DegToRad (_startAngle / 64.0) &&
angle <= DegToRad ((_startAngle + _subtAngle) / 64.0) &&
e.HitTest (p) == UIHit_Boundary ? UIHit_Boundary : UIHit_Outside;
}