diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2016-10-27 18:59:29 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2016-10-27 18:59:29 (GMT) |
commit | d4d595fa7fb12903db9227d33d48b2b00120dbd1 (patch) | |
tree | 7d18365de0d6d1b29399b6a17c7eb01c2eb3ed49 /tksao/frame/baseellipse.C | |
parent | 949f96e29bfe0bd8710d775ce220e597064e2589 (diff) | |
download | blt-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.C | 768 |
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; +} |