summaryrefslogtreecommitdiffstats
path: root/tksao/frame/baseellipse.C
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2016-10-27 18:59:29 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2016-10-27 18:59:29 (GMT)
commitd4d595fa7fb12903db9227d33d48b2b00120dbd1 (patch)
tree7d18365de0d6d1b29399b6a17c7eb01c2eb3ed49 /tksao/frame/baseellipse.C
parent949f96e29bfe0bd8710d775ce220e597064e2589 (diff)
downloadblt-d4d595fa7fb12903db9227d33d48b2b00120dbd1.zip
blt-d4d595fa7fb12903db9227d33d48b2b00120dbd1.tar.gz
blt-d4d595fa7fb12903db9227d33d48b2b00120dbd1.tar.bz2
Initial commit
Diffstat (limited to 'tksao/frame/baseellipse.C')
-rw-r--r--tksao/frame/baseellipse.C768
1 files changed, 768 insertions, 0 deletions
diff --git a/tksao/frame/baseellipse.C b/tksao/frame/baseellipse.C
new file mode 100644
index 0000000..290bf38
--- /dev/null
+++ b/tksao/frame/baseellipse.C
@@ -0,0 +1,768 @@
+// Copyright (C) 1999-2016
+// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+// For conditions of distribution and use, see copyright notice in "copyright"
+
+#include <tk.h>
+
+#include "baseellipse.h"
+#include "fitsimage.h"
+
+BaseEllipse::BaseEllipse(Base* p, const Vector& ctr, double ang)
+ : BaseMarker(p, ctr, ang)
+{
+}
+
+BaseEllipse::BaseEllipse(Base* p, const Vector& ctr,
+ double ang,
+ const char* clr, int* dsh,
+ int w, const char* f,
+ const char* t, unsigned short prop, const char* c,
+ const List<Tag>& tag, const List<CallBack>& cb)
+ : BaseMarker(p, ctr, ang, clr, dsh, w, f, t, prop, c, tag, cb)
+{
+}
+
+BaseEllipse::BaseEllipse(const BaseEllipse& a) : BaseMarker(a) {}
+
+BaseEllipse::~BaseEllipse()
+{
+}
+
+void BaseEllipse::renderX(Drawable drawable, Coord::InternalSystem sys,
+ RenderMode mode)
+{
+ double ang = calcAngle();
+ Vector r = annuli_[numAnnuli_-1];
+ Vector z = parent->zoom();
+
+ int isOrient = parent->getOrientation() == Coord::NORMAL &&
+ parent->getWCSOrientation() == Coord::NORMAL;
+ int isRound = r[0] == r[1];
+ int isScale = z[0] == z[1];
+ // int isAngle = teq(ang,0,FLT_EPSILON) || teq(ang,M_PI,FLT_EPSILON);
+
+ if (isRound && isScale && isOrient && parent->isAzElZero())
+ renderXCircle(drawable, sys, ang, mode);
+ else
+ renderXEllipseCurve(drawable, sys, mode);
+}
+
+void BaseEllipse::renderXCircle(Drawable drawable, Coord::InternalSystem sys,
+ double ang, RenderMode mode)
+{
+ GC lgc = renderXGC(mode);
+
+ // this routine is only valid for circles with equal zoom in x & y
+ Vector cc = parent->mapFromRef(center,sys);
+
+ for (int i=0; i<numAnnuli_; i++) {
+ Vector r = annuli_[i];
+
+ Vector ur = fwdMap(r,sys);
+ double l = (ur-cc).length() * cos(M_PI_4);
+
+ Vector rr(l,l);
+ Vector st = cc-rr;
+ Vector size = rr*2;
+
+ // Verify size is positive
+ // XDrawArc is sensative to bad data, and may hang the XServer
+ if (!size[0] || !size[1])
+ continue;
+
+ // Must be very sure that a1<a2
+ double aa1 = startAng_ + ang;
+ double aa2 = stopAng_ + ang;
+ int a1 = radToDeg(aa1)*64;
+ int a2 = radToDeg(aa2)*64;
+ if (a2<=a1)
+ a2 += 360*64;
+
+ XDrawArc(display, drawable, lgc, st[0], st[1], size[0], size[1],
+ a1, (a2-a1));
+ }
+}
+
+void BaseEllipse::renderXEllipseCurve(Drawable drawable, Coord::InternalSystem sys,
+ RenderMode mode)
+{
+ double a1 = startAng_;
+ double a2 = stopAng_;
+ if (a2<=a1)
+ a2 += M_TWOPI;
+
+ for (int i=0; i<numAnnuli_; i++) {
+ Vector r = annuli_[i];
+
+ int s1 =0;
+ int s2 =0;
+ for (int i=0; i<8; i++) {
+ double b1 = i*M_PI_2;
+ double b2 = (i+1)*M_PI_2;
+ if (!s1 && a1>=b1 && a1<b2)
+ s1 =1;
+ if (!s2 && a2>b1 && a2<=b2)
+ s2 =1;
+
+ if ((s1 && !s2) || (s1 && s2))
+ renderXEllipsePrep(drawable, sys, mode, a1,a2,b1,b2,r);
+
+ if (s1&&s2)
+ s1=s2=0;
+ }
+ }
+}
+
+void BaseEllipse::renderXEllipsePrep(Drawable drawable, Coord::InternalSystem sys,
+ RenderMode mode,
+ double a1, double a2,
+ double b1, double b2,
+ Vector& r)
+{
+ if (!(a1 >= b1 && a1 <= b2))
+ a1 = b1;
+ if (!(a2 >= b1 && a2 <= b2))
+ a2 = b2;
+
+ if (a1>a2) {
+ renderXEllipseArc(drawable, sys, mode, b1,a2,r);
+ renderXEllipseArc(drawable, sys, mode, a1,b2,r);
+ }
+ else
+ renderXEllipseArc(drawable, sys, mode, a1,a2,r);
+}
+
+void BaseEllipse::renderXEllipseArc(Drawable drawable, Coord::InternalSystem sys,
+ RenderMode mode,
+ double a1, double a2, Vector& rr)
+{
+ // don't render if zero angle
+ if (a1==a2)
+ return;
+
+ // don't render if zero length
+ if (rr[0]==0 || rr[1]==0)
+ return;
+
+ // bezier curve, valid for arcs of <M_PI_2
+ double aa1 = xyz(rr,a1);
+ double aa2 = xyz(rr,a2);
+ double bcp = 4.0/3*(1-cos((aa2-aa1)/2))/sin((aa2-aa1)/2);
+
+ Vector t0 = intersect(rr,a1);
+ Vector x1 = Vector(rr[0]*(cos(aa1)-bcp*sin(aa1)),
+ rr[1]*(sin(aa1)+bcp*cos(aa1)));
+ Vector x2 = Vector(rr[0]*(cos(aa2)+bcp*sin(aa2)),
+ rr[1]*(sin(aa2)-bcp*cos(aa2)));
+ Vector t1 = intersect(rr,a2);
+
+ Vector tt0 = fwdMap(t0*FlipY(),sys);
+ Vector xx1 = fwdMap(x1*FlipY(),sys);
+ Vector xx2 = fwdMap(x2*FlipY(),sys);
+ Vector tt1 = fwdMap(t1*FlipY(),sys);
+
+ XDrawCurve(drawable, mode, tt0, xx1, xx2, tt1);
+}
+
+void BaseEllipse::renderXInclude(Drawable drawable, Coord::InternalSystem sys,
+ RenderMode mode)
+{
+ if (!(properties & INCLUDE)) {
+ // Matrix mm = fwdMatrix();
+ double theta = degToRad(45);
+
+ Vector r1 = fwdMap(Vector(annuli_[numAnnuli_-1][0]*cos(theta),
+ annuli_[numAnnuli_-1][1]*sin(theta)),
+ sys);
+ Vector r2 = fwdMap(Vector(-annuli_[numAnnuli_-1][0]*cos(theta),
+ -annuli_[numAnnuli_-1][1]*sin(theta)),
+ sys);
+
+ GC lgc = renderXGC(mode);
+ if (mode == SRC)
+ XSetForeground(display, gc, parent->getColor("red"));
+
+ XDrawLine(display, drawable, lgc, r1[0], r1[1], r2[0], r2[1]);
+ }
+}
+
+void BaseEllipse::renderPS(int mode) {
+ Vector r = annuli_[numAnnuli_-1];
+ Vector z = parent->zoom();
+
+ int isOrient = parent->getOrientation() == Coord::NORMAL &&
+ parent->getWCSOrientation() == Coord::NORMAL;
+ int isRound = r[0] == r[1];
+ int isScale = z[0] == z[1];
+
+ if (isRound && isScale && isOrient && parent->isAzElZero())
+ renderPSCircle(mode);
+ else
+ renderPSEllipseCurve(mode);
+}
+
+void BaseEllipse::renderPSCircle(int mode)
+{
+ renderPSGC(mode);
+
+ Vector cc = parent->mapFromRef(center,Coord::CANVAS);
+ double ang = calcAngle();
+
+ for (int ii=0; ii<numAnnuli_; ii++) {
+ Vector r = annuli_[ii];
+
+ Vector ur = fwdMap(r,Coord::CANVAS);
+ double l = (ur-cc).length() * cos(M_PI_4);
+
+ // don't render zero length arcs
+ if (!l)
+ continue;
+
+ // Must be very sure that a1<a2
+ double aa1 = startAng_ + ang;
+ double aa2 = stopAng_ + ang;
+ float a1 = radToDeg(aa1);
+ float a2 = radToDeg(aa2);
+ if (a2<=a1)
+ a2 += 360;
+
+ ostringstream str;
+ str << "newpath "
+ << cc.TkCanvasPs(parent->canvas) << ' '
+ << l << ' '
+ << a1 << ' ' << a2 << ' '
+ << "arc stroke" << endl << ends;
+
+ Tcl_AppendResult(parent->interp, str.str().c_str(), NULL);
+ }
+}
+
+void BaseEllipse::renderPSEllipseCurve(int mode)
+{
+ renderPSGC(mode);
+
+ double a1 = startAng_;
+ double a2 = stopAng_;
+ if (a2<=a1)
+ a2 += M_TWOPI;
+
+ for (int ii=0; ii<numAnnuli_; ii++) {
+ Vector r = annuli_[ii];
+
+ int s1 =0;
+ int s2 =0;
+ for (int jj=0; jj<8; jj++) {
+ double b1 = jj*M_PI_2;
+ double b2 = (jj+1)*M_PI_2;
+ if (!s1 && a1>=b1 && a1<b2)
+ s1 =1;
+ if (!s2 && a2>b1 && a2<=b2)
+ s2 =1;
+
+ if ((s1 && !s2) || (s1 && s2))
+ renderPSEllipsePrep(a1,a2,b1,b2,r);
+
+ if (s1&&s2)
+ s1=s2=0;
+ }
+ }
+}
+
+void BaseEllipse::renderPSEllipsePrep(double a1, double a2,
+ double b1, double b2,
+ Vector& rr)
+{
+ if (!(a1 >= b1 && a1 <= b2))
+ a1 = b1;
+ if (!(a2 >= b1 && a2 <= b2))
+ a2 = b2;
+
+ if (a1>a2) {
+ renderPSEllipseArc(b1,a2,rr);
+ renderPSEllipseArc(a1,b2,rr);
+ }
+ else
+ renderPSEllipseArc(a1,a2,rr);
+}
+
+void BaseEllipse::renderPSEllipseArc(double a1, double a2, Vector& rr)
+
+{
+ // don't render zero length arcs
+ if (a1 == a2)
+ return;
+
+ if (!rr[0] || !rr[1])
+ return;
+
+ // bezier curve, valid for arcs of <M_PI_2
+ double aa1 = xyz(rr,a1);
+ double aa2 = xyz(rr,a2);
+ double bcp = 4.0/3*(1-cos((aa2-aa1)/2))/sin((aa2-aa1)/2);
+
+ Vector t0 = intersect(rr,a1);
+ Vector x1 = Vector(rr[0]*(cos(aa1)-bcp*sin(aa1)),
+ rr[1]*(sin(aa1)+bcp*cos(aa1)));
+ Vector x2 = Vector(rr[0]*(cos(aa2)+bcp*sin(aa2)),
+ rr[1]*(sin(aa2)-bcp*cos(aa2)));
+ Vector t1 = intersect(rr,a2);
+
+ Vector tt0 = fwdMap(t0*FlipY(),Coord::CANVAS);
+ Vector xx1 = fwdMap(x1*FlipY(),Coord::CANVAS);
+ Vector xx2 = fwdMap(x2*FlipY(),Coord::CANVAS);
+ Vector tt1 = fwdMap(t1*FlipY(),Coord::CANVAS);
+
+ ostringstream str;
+ str << "newpath "
+ << tt0.TkCanvasPs(parent->canvas) << ' '
+ << "moveto "
+ << xx1.TkCanvasPs(parent->canvas) << ' '
+ << xx2.TkCanvasPs(parent->canvas) << ' '
+ << tt1.TkCanvasPs(parent->canvas) << ' '
+ << "curveto stroke" << endl << ends;
+ Tcl_AppendResult(parent->interp, str.str().c_str(), NULL);
+}
+
+void BaseEllipse::renderPSInclude(int mode)
+{
+ if (!(properties & INCLUDE)) {
+ double theta = degToRad(45);
+ Vector r1 = fwdMap(Vector(annuli_[numAnnuli_-1][0]*cos(theta),
+ annuli_[numAnnuli_-1][1]*sin(theta)),
+ Coord::CANVAS);
+ Vector r2 = fwdMap(Vector(-annuli_[numAnnuli_-1][0]*cos(theta),
+ -annuli_[numAnnuli_-1][1]*sin(theta)),
+ Coord::CANVAS);
+
+ renderPSColor(mode, parent->getXColor("red"));
+
+ ostringstream str;
+ str << "newpath "
+ << r1.TkCanvasPs(parent->canvas) << ' '
+ << "moveto "
+ << r2.TkCanvasPs(parent->canvas) << ' '
+ << "lineto stroke" << endl << ends;
+ Tcl_AppendResult(parent->interp, str.str().c_str(), NULL);
+ }
+}
+
+#ifdef MAC_OSX_TK
+void BaseEllipse::renderMACOSX() {
+ Vector r = annuli_[numAnnuli_-1];
+ Vector z = parent->zoom();
+
+ int isOrient = parent->getOrientation() == Coord::NORMAL &&
+ parent->getWCSOrientation() == Coord::NORMAL;
+ int isRound = r[0] == r[1];
+ int isScale = z[0] == z[1];
+
+ if (isRound && isScale && isOrient & parent->isAzElZero())
+ renderMACOSXCircle();
+ else
+ renderMACOSXEllipseCurve();
+}
+
+void BaseEllipse::renderMACOSXCircle()
+{
+ renderMACOSXGC();
+
+ Vector cc = parent->mapFromRef(center,Coord::CANVAS);
+ double ang = calcAngle();
+
+ for (int ii=0; ii<numAnnuli_; ii++) {
+ Vector r = annuli_[ii];
+
+ Vector ur = fwdMap(r,Coord::CANVAS);
+ double l = (ur-cc).length() * cos(M_PI_4);
+
+ // don't render zero length arcs
+ if (!l)
+ continue;
+
+ double a1 = startAng_ + ang;
+ double a2 = stopAng_ + ang;
+ if (a2<=a1)
+ a2 += M_TWOPI;
+
+ macosxDrawArc(cc, l, a1, a2);
+ }
+}
+
+void BaseEllipse::renderMACOSXEllipseCurve()
+{
+ renderMACOSXGC();
+
+ double a1 = startAng_;
+ double a2 = stopAng_;
+ if (a2<=a1)
+ a2 += M_TWOPI;
+
+ for (int ii=0; ii<numAnnuli_; ii++) {
+ Vector r = annuli_[ii];
+
+ int s1 =0;
+ int s2 =0;
+ for (int jj=0; jj<8; jj++) {
+ double b1 = jj*M_PI_2;
+ double b2 = (jj+1)*M_PI_2;
+ if (!s1 && a1>=b1 && a1<b2)
+ s1 =1;
+ if (!s2 && a2>b1 && a2<=b2)
+ s2 =1;
+
+ if ((s1 && !s2) || (s1 && s2))
+ renderMACOSXEllipsePrep(a1,a2,b1,b2,r);
+
+ if (s1&&s2)
+ s1=s2=0;
+ }
+ }
+}
+
+void BaseEllipse::renderMACOSXEllipsePrep(double a1, double a2,
+ double b1, double b2,
+ Vector& rr)
+{
+ if (!(a1 >= b1 && a1 <= b2))
+ a1 = b1;
+ if (!(a2 >= b1 && a2 <= b2))
+ a2 = b2;
+
+ if (a1>a2) {
+ renderMACOSXEllipseArc(b1,a2,rr);
+ renderMACOSXEllipseArc(a1,b2,rr);
+ }
+ else
+ renderMACOSXEllipseArc(a1,a2,rr);
+}
+
+void BaseEllipse::renderMACOSXEllipseArc(double a1, double a2, Vector& rr)
+
+{
+ // don't render zero length arcs
+ if (a1 == a2)
+ return;
+
+ if (!rr[0] || !rr[1])
+ return;
+
+ // bezier curve, valid for arcs of <M_PI_2
+ double aa1 = xyz(rr,a1);
+ double aa2 = xyz(rr,a2);
+ double bcp = 4.0/3*(1-cos((aa2-aa1)/2))/sin((aa2-aa1)/2);
+
+ Vector t0 = intersect(rr,a1);
+ Vector x1 = Vector(rr[0]*(cos(aa1)-bcp*sin(aa1)),
+ rr[1]*(sin(aa1)+bcp*cos(aa1)));
+ Vector x2 = Vector(rr[0]*(cos(aa2)+bcp*sin(aa2)),
+ rr[1]*(sin(aa2)-bcp*cos(aa2)));
+ Vector t1 = intersect(rr,a2);
+
+ Vector tt0 = fwdMap(t0*FlipY(),Coord::CANVAS);
+ Vector xx1 = fwdMap(x1*FlipY(),Coord::CANVAS);
+ Vector xx2 = fwdMap(x2*FlipY(),Coord::CANVAS);
+ Vector tt1 = fwdMap(t1*FlipY(),Coord::CANVAS);
+
+ macosxDrawCurve(tt0, xx1, xx2, tt1);
+}
+
+void BaseEllipse::renderMACOSXInclude()
+{
+ if (!(properties & INCLUDE)) {
+ double theta = degToRad(45);
+ Vector r1 = fwdMap(Vector(annuli_[numAnnuli_-1][0]*cos(theta),
+ annuli_[numAnnuli_-1][1]*sin(theta)),
+ Coord::CANVAS);
+ Vector r2 = fwdMap(Vector(-annuli_[numAnnuli_-1][0]*cos(theta),
+ -annuli_[numAnnuli_-1][1]*sin(theta)),
+ Coord::CANVAS);
+
+ macosxColor(parent->getXColor("red"));
+ macosxDrawLine(r1,r2);
+ }
+}
+#endif
+
+#ifdef __WIN32
+void BaseEllipse::renderWIN32() {
+ Vector r = annuli_[numAnnuli_-1];
+ Vector z = parent->zoom();
+
+ int isOrient = parent->getOrientation() == Coord::NORMAL &&
+ parent->getWCSOrientation() == Coord::NORMAL;
+ int isRound = r[0] == r[1];
+ int isScale = z[0] == z[1];
+
+ if (isRound && isScale && isOrient && parent->isAzElZero())
+ renderWIN32Circle();
+ else
+ renderWIN32EllipseCurve();
+}
+
+void BaseEllipse::renderWIN32Circle()
+{
+ renderWIN32GC();
+
+ Vector cc = parent->mapFromRef(center,Coord::CANVAS);
+ double ang = calcAngle();
+
+ for (int i=0; i<numAnnuli_; i++) {
+ Vector r = annuli_[i];
+
+ Vector ur = fwdMap(r,Coord::CANVAS);
+ double l = (ur-cc).length() * cos(M_PI_4);
+
+ // don't render zero length arcs
+ if (!l)
+ continue;
+
+ double a1 = startAng_ + ang;
+ double a2 = stopAng_ + ang;
+ if (a2<=a1)
+ a2 += M_TWOPI;
+
+ win32DrawArc(cc, l, a1, a2);
+ }
+}
+
+void BaseEllipse::renderWIN32EllipseCurve()
+{
+ renderWIN32GC();
+
+ double a1 = startAng_;
+ double a2 = stopAng_;
+ if (a2<=a1)
+ a2 += M_TWOPI;
+
+ for (int ii=0; ii<numAnnuli_; ii++) {
+ Vector r = annuli_[ii];
+
+ int s1 =0;
+ int s2 =0;
+ for (int jj=0; jj<8; jj++) {
+ double b1 = jj*M_PI_2;
+ double b2 = (jj+1)*M_PI_2;
+ if (!s1 && a1>=b1 && a1<b2)
+ s1 =1;
+ if (!s2 && a2>b1 && a2<=b2)
+ s2 =1;
+
+ if ((s1 && !s2) || (s1 && s2))
+ renderWIN32EllipsePrep(a1,a2,b1,b2,r);
+
+ if (s1&&s2)
+ s1=s2=0;
+ }
+ }
+}
+
+void BaseEllipse::renderWIN32EllipsePrep(double a1, double a2,
+ double b1, double b2,
+ Vector& rr)
+{
+ if (!(a1 >= b1 && a1 <= b2))
+ a1 = b1;
+ if (!(a2 >= b1 && a2 <= b2))
+ a2 = b2;
+
+ if (a1>a2) {
+ renderWIN32EllipseArc(b1,a2,rr);
+ renderWIN32EllipseArc(a1,b2,rr);
+ }
+ else
+ renderWIN32EllipseArc(a1,a2,rr);
+}
+
+void BaseEllipse::renderWIN32EllipseArc(double a1, double a2, Vector& rr)
+
+{
+ // don't render zero length arcs
+ if (a1 == a2)
+ return;
+
+ if (!rr[0] || !rr[1])
+ return;
+
+ // bezier curve, valid for arcs of <M_PI_2
+ double aa1 = xyz(rr,a1);
+ double aa2 = xyz(rr,a2);
+ double bcp = 4.0/3*(1-cos((aa2-aa1)/2))/sin((aa2-aa1)/2);
+
+ Vector t0 = intersect(rr,a1);
+ Vector x1 = Vector(rr[0]*(cos(aa1)-bcp*sin(aa1)),
+ rr[1]*(sin(aa1)+bcp*cos(aa1)));
+ Vector x2 = Vector(rr[0]*(cos(aa2)+bcp*sin(aa2)),
+ rr[1]*(sin(aa2)-bcp*cos(aa2)));
+ Vector t1 = intersect(rr,a2);
+
+ Vector tt0 = fwdMap(t0*FlipY(),Coord::CANVAS);
+ Vector xx1 = fwdMap(x1*FlipY(),Coord::CANVAS);
+ Vector xx2 = fwdMap(x2*FlipY(),Coord::CANVAS);
+ Vector tt1 = fwdMap(t1*FlipY(),Coord::CANVAS);
+
+ win32DrawCurve(tt0, xx1, xx2, tt1);
+}
+
+void BaseEllipse::renderWIN32Include()
+{
+ if (!(properties & INCLUDE)) {
+ double theta = degToRad(45);
+ Vector r1 = fwdMap(Vector(annuli_[numAnnuli_-1][0]*cos(theta),
+ annuli_[numAnnuli_-1][1]*sin(theta)),
+ Coord::CANVAS);
+ Vector r2 = fwdMap(Vector(-annuli_[numAnnuli_-1][0]*cos(theta),
+ -annuli_[numAnnuli_-1][1]*sin(theta)),
+ Coord::CANVAS);
+
+ win32Color(parent->getXColor("red"));
+ win32DrawLine(r1,r2);
+ }
+}
+#endif
+
+// Support
+
+void BaseEllipse::updateHandles()
+{
+ // handles are in canvas coords
+ // we can't garantee that the annuli_ have been sorted yet
+ if (handle)
+ delete [] handle;
+ handle = new Vector[numHandle];
+
+ Vector max;
+ for(int ii=0; ii<numAnnuli_; ii++)
+ if (max[0]<annuli_[ii][0])
+ max = annuli_[ii];
+ Vector& r = max;
+
+ handle[0] = fwdMap(Vector(-r[0],-r[1]),Coord::CANVAS);
+ handle[1] = fwdMap(Vector( r[0],-r[1]),Coord::CANVAS);
+ handle[2] = fwdMap(Vector( r[0], r[1]),Coord::CANVAS);
+ handle[3] = fwdMap(Vector(-r[0], r[1]),Coord::CANVAS);
+
+ // annuli_
+ if (numAnnuli_>1)
+ for (int ii=0; ii<numAnnuli_; ii++)
+ handle[ii+4] = fwdMap(Vector(annuli_[ii][0],0),Coord::CANVAS);
+}
+
+int BaseEllipse::isInRef(const Vector& vv, int nn)
+{
+ Vector rr = annuli_[nn];
+
+ // zero radius
+ if (!rr[0] || !rr[1])
+ return 0;
+
+ Vector& pp = (Vector&)vv;
+ if ((pp[0]*pp[0])/(rr[0]*rr[0]) + (pp[1]*pp[1])/(rr[1]*rr[1]) <= 1)
+ return 1;
+ else
+ return 0;
+}
+
+Vector BaseEllipse::intersect(Vector rr, double aa)
+{
+ double tt = rr[1]*rr[1]*cos(aa)*cos(aa)+rr[0]*rr[0]*sin(aa)*sin(aa);
+ double ss =0;
+ if (tt>0)
+ ss = rr[0]*rr[1]/sqrt(tt);
+
+ return Vector(ss*cos(aa),ss*sin(aa));
+}
+
+void BaseEllipse::XDrawCurve(Drawable drawable, RenderMode mode,
+ Vector& t1, Vector& x1,
+ Vector& x2, Vector& t2)
+{
+ // if dashed, fake it
+ GC lgc;
+ if ((properties & SOURCE) && !(properties & DASH))
+ lgc = renderXGC(mode);
+ else {
+ // set width, color, dash
+ switch (mode) {
+ case SRC:
+ XSetForeground(display, gc, color);
+ renderXLineNoDash(gc);
+ lgc = gc;
+ break;
+ case XOR:
+ renderXLineNoDash(gcxor);
+ lgc = gcxor;
+ break;
+ }
+ }
+
+ float t1x = t1[0];
+ float t1y = t1[1];
+ float t2x = t2[0];
+ float t2y = t2[1];
+
+ float x1x = x1[0];
+ float x1y = x1[1];
+ float x2x = x2[0];
+ float x2y = x2[1];
+
+ float rx = t1x;
+ float ry = t1y;
+
+ Vector dd = (t2-t1).abs();
+ float max = dd[0]>dd[1] ? dd[0] : dd[1];
+
+ // calculate incr
+ // this is a crude attempt to limit the number of iterations
+ // we want a min for very small segments, but not that large for
+ // high zoom or elongated curves
+ float aa = int(log(max))*5;
+ float incr = 1./(aa > 2 ? aa : 2);
+
+ int dash=0;
+ float tt = incr;
+ while (tt<=1+FLT_EPSILON) {
+ float xx = pow(tt,3)*(t2x+3*(x1x-x2x)-t1x)
+ +3*pow(tt,2)*(t1x-2*x1x+x2x)
+ +3*tt*(x1x-t1x)+t1x;
+ float yy = pow(tt,3)*(t2y+3*(x1y-x2y)-t1y)
+ +3*pow(tt,2)*(t1y-2*x1y+x2y)
+ +3*tt*(x1y-t1y)+t1y;
+
+ // crude attempt to clip unwanted drawlines
+ // only works for SRC
+ if ((properties & SOURCE) && !(properties & DASH))
+ XDrawLine(display, drawable, lgc, rx, ry, xx, yy);
+ else {
+ if (dash)
+ XDrawLine(display, drawable, lgc, rx, ry, xx, yy);
+ dash = !dash;
+ }
+
+ rx = xx;
+ ry = yy;
+
+ tt += incr;
+ }
+}
+
+// this routine maps the desired angle to an angle to be used with XDrawArc
+double BaseEllipse::xyz(Vector rr, double aa)
+{
+ // just in case
+ if (!rr[0] || !rr[1])
+ return aa;
+
+ int flip=0;
+ while (aa>M_PI) {
+ aa -= M_PI;
+ flip++;
+ }
+
+ double tt = rr[1]*rr[1]*cos(aa)*cos(aa)+rr[0]*rr[0]*sin(aa)*sin(aa);
+ double ss =0;
+ if (tt>0)
+ ss = 1./sqrt(tt);
+
+ double bb = rr[1]*ss*cos(aa);
+ return acos(bb)+M_PI*flip;
+}