diff options
-rw-r--r-- | tksao/frame/baseellipse.C | 260 | ||||
-rw-r--r-- | tksao/frame/baseellipse.h | 10 | ||||
-rw-r--r-- | tksao/frame/basefill.C | 10 | ||||
-rw-r--r-- | tksao/frame/basefill.h | 1 | ||||
-rw-r--r-- | tksao/frame/circle.C | 17 | ||||
-rw-r--r-- | tksao/frame/circle.h | 1 | ||||
-rw-r--r-- | tksao/frame/ellipse.C | 17 | ||||
-rw-r--r-- | tksao/frame/ellipse.h | 1 |
8 files changed, 211 insertions, 106 deletions
diff --git a/tksao/frame/baseellipse.C b/tksao/frame/baseellipse.C index 6b84669..cb0c63f 100644 --- a/tksao/frame/baseellipse.C +++ b/tksao/frame/baseellipse.C @@ -2,14 +2,17 @@ // 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" +#define XPOINT_BLOCK 1024 + BaseEllipse::BaseEllipse(Base* p, const Vector& ctr, double ang) : BaseMarker(p, ctr, ang) { + xpoint_ =NULL; + xpointSize_ =0; + xpointNum_ =0; } BaseEllipse::BaseEllipse(Base* p, const Vector& ctr, @@ -20,14 +23,26 @@ BaseEllipse::BaseEllipse(Base* p, const Vector& ctr, const List<Tag>& tag, const List<CallBack>& cb) : BaseMarker(p, ctr, ang, clr, dsh, w, f, t, prop, c, tag, cb) { + xpoint_ =NULL; + xpointSize_ =0; + xpointNum_ =0; } -BaseEllipse::BaseEllipse(const BaseEllipse& a) : BaseMarker(a) {} +BaseEllipse::BaseEllipse(const BaseEllipse& a) : BaseMarker(a) +{ + xpoint_ =NULL; + xpointSize_ =0; + xpointNum_ =0; +} BaseEllipse::~BaseEllipse() { + if (xpoint_) + free(xpoint_); } +// renderX + void BaseEllipse::renderX(Drawable drawable, Coord::InternalSystem sys, RenderMode mode) { @@ -99,6 +114,10 @@ void BaseEllipse::renderXEllipse(Drawable drawable, Coord::InternalSystem sys, for (int i=0; i<numAnnuli_; i++) { Vector r = annuli_[i]; + xpointSize_ = XPOINT_BLOCK*sizeof(XPoint); + xpoint_ = (XPoint*)malloc(xpointSize_); + xpointNum_ =0; + int s1 =0; int s2 =0; for (int i=0; i<8; i++) { @@ -115,6 +134,60 @@ void BaseEllipse::renderXEllipse(Drawable drawable, Coord::InternalSystem sys, if (s1&&s2) s1=s2=0; } + + // close the loop + xpointNum_++; + if (xpointNum_*sizeof(XPoint) >= xpointSize_) { + xpointSize_ += XPOINT_BLOCK*sizeof(XPoint); + xpoint_ = (XPoint*)realloc(xpoint_, xpointSize_); + } + XPoint* ptr = xpoint_+xpointNum_; + (*ptr).x = (*xpoint_).x; + (*ptr).y = (*xpoint_).y; + + // 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; + } + } + + renderXEllipseDraw(drawable, lgc, xpoint_, xpointNum_); + + if (xpoint_) + free(xpoint_); + xpoint_ =NULL; + xpointSize_ =0; + xpointNum_ =0; + } +} + +void BaseEllipse::renderXEllipseDraw(Drawable drawable, GC lgc, + XPoint* pts, int cnt) +{ + if ((properties & SOURCE) && !(properties & DASH)) + XDrawLines(display, drawable, lgc, pts, cnt, CoordModeOrigin); + else { + // crude attempt to clip unwanted drawlines + // only works for SRC + for (int ii=0; ii<xpointNum_; ii+=2) { + XPoint* ptr1 = xpoint_+ii; + XPoint* ptr2 = xpoint_+ii+1; + XDrawLine(display, drawable, lgc, + (*ptr1).x, (*ptr1).y, (*ptr2).x, (*ptr2).y); + } } } @@ -169,9 +242,82 @@ void BaseEllipse::renderXEllipseArc(Drawable drawable, Vector xx2 = fwdMap(x2*FlipY(),sys); Vector tt1 = fwdMap(t1*FlipY(),sys); + if (xpointNum_ == 0) { + (*xpoint_).x = tt0[0]; + (*xpoint_).y = tt0[1]; + } + XDrawCurve(drawable, mode, tt0, xx1, xx2, tt1); } +void BaseEllipse::XDrawCurve(Drawable drawable, RenderMode mode, + Vector& t1, Vector& x1, + Vector& x2, Vector& t2) +{ + 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]; + + 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); + + 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; + + xpointNum_++; + if (xpointNum_*sizeof(XPoint) >= xpointSize_) { + xpointSize_ += XPOINT_BLOCK*sizeof(XPoint); + xpoint_ = (XPoint*)realloc(xpoint_, xpointSize_); + } + XPoint* ptr = xpoint_+xpointNum_; + (*ptr).x = xx; + (*ptr).y = 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; +} + void BaseEllipse::renderXInclude(Drawable drawable, Coord::InternalSystem sys, RenderMode mode) @@ -180,12 +326,8 @@ void BaseEllipse::renderXInclude(Drawable drawable, // 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); + 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) @@ -195,6 +337,8 @@ void BaseEllipse::renderXInclude(Drawable drawable, } } +// renderPS + void BaseEllipse::renderPS(int mode) { Vector r = annuli_[numAnnuli_-1]; Vector z = parent->zoom(); @@ -207,7 +351,7 @@ void BaseEllipse::renderPS(int mode) { if (isRound && isScale && isOrient && parent->isAzElZero()) renderPSCircle(mode); else - renderPSEllipseCurve(mode); + renderPSEllipse(mode); } void BaseEllipse::renderPSCircle(int mode) @@ -251,7 +395,7 @@ void BaseEllipse::renderPSCircleDraw(Vector& cc, double l, float a1, float a2) Tcl_AppendResult(parent->interp, str.str().c_str(), NULL); } -void BaseEllipse::renderPSEllipseCurve(int mode) +void BaseEllipse::renderPSEllipse(int mode) { renderPSGC(mode); @@ -691,97 +835,3 @@ Vector BaseEllipse::intersect(Vector rr, double aa) 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; -} diff --git a/tksao/frame/baseellipse.h b/tksao/frame/baseellipse.h index 834b584..117ad8a 100644 --- a/tksao/frame/baseellipse.h +++ b/tksao/frame/baseellipse.h @@ -5,9 +5,16 @@ #ifndef __baseellipse_h__ #define __baseellipse_h__ +#include <tk.h> + #include "basemarker.h" class BaseEllipse : public BaseMarker { + protected: + XPoint* xpoint_; + int xpointSize_; + int xpointNum_; + private: double xyz(Vector rr, double ang); void XDrawCurve(Drawable, RenderMode, Vector&, Vector&, Vector&, Vector&); @@ -21,7 +28,7 @@ class BaseEllipse : public BaseMarker { void renderXInclude(Drawable, Coord::InternalSystem, RenderMode); void renderPSCircle(int); - void renderPSEllipseCurve(int); + void renderPSEllipse(int); void renderPSEllipsePrep(double, double, double, double, Vector&); void renderPSEllipseArc(double, double, Vector&); void renderPSInclude(int); @@ -45,6 +52,7 @@ class BaseEllipse : public BaseMarker { protected: void renderX(Drawable, Coord::InternalSystem, RenderMode); virtual void renderXCircleDraw(Drawable, GC, Vector&, Vector&, int, int); + virtual void renderXEllipseDraw(Drawable, GC, XPoint*, int); void renderPS(int); virtual void renderPSCircleDraw(Vector& cc, double l, float a1, float a2); virtual void renderPSEllipseArcDraw(Vector&, Vector&, Vector&, Vector&); diff --git a/tksao/frame/basefill.C b/tksao/frame/basefill.C index 4da1ae5..91e5171 100644 --- a/tksao/frame/basefill.C +++ b/tksao/frame/basefill.C @@ -42,6 +42,16 @@ void BaseFillEllipse::renderXCircleDraw(Display* display, Drawable drawable, XDrawArc(display, drawable, lgc, st[0], st[1], size[0], size[1], a1, aa); } +void BaseFillEllipse::renderXEllipseDraw(Display* display, Drawable drawable, + GC lgc, + XPoint* pts, int cnt) +{ + if (fill_) + XFillPolygon(display, drawable, lgc, pts, cnt, Convex, CoordModeOrigin); + else + XDrawLines(display, drawable, lgc, pts, cnt, CoordModeOrigin); +} + void BaseFillEllipse::renderPSCircleDraw(Base* parent, Vector& cc, double l, float a1, float a2) diff --git a/tksao/frame/basefill.h b/tksao/frame/basefill.h index f50adcf..5e2dd2c 100644 --- a/tksao/frame/basefill.h +++ b/tksao/frame/basefill.h @@ -27,6 +27,7 @@ class BaseFill { class BaseFillEllipse : public BaseFill { protected: void renderXCircleDraw(Display*, Drawable, GC, Vector&, Vector&, int, int); + void renderXEllipseDraw(Display*, Drawable, GC, XPoint*, int); void renderPSCircleDraw(Base*, Vector&, double, float, float); void renderPSEllipseArcDraw(Base*, Vector&, Vector&, Vector&, Vector&, Vector&); diff --git a/tksao/frame/circle.C b/tksao/frame/circle.C index 3015d07..87d29cb 100644 --- a/tksao/frame/circle.C +++ b/tksao/frame/circle.C @@ -61,6 +61,23 @@ void Circle::renderXCircleDraw(Drawable drawable, GC lgc, BaseFillEllipse::renderXCircleDraw(display, drawable, lgc, st, size, a1, aa); } +void Circle::renderXEllipseDraw(Drawable drawable, GC lgc, + XPoint* pts, int cnt) +{ + if (fill_ || ((properties & SOURCE) && !(properties & DASH))) + BaseFillEllipse::renderXEllipseDraw(display, drawable, lgc, pts, cnt); + else { + // crude attempt to clip unwanted drawlines + // only works for SRC + for (int ii=0; ii<xpointNum_; ii+=2) { + XPoint* ptr1 = xpoint_+ii; + XPoint* ptr2 = xpoint_+ii+1; + XDrawLine(display, drawable, lgc, + (*ptr1).x, (*ptr1).y, (*ptr2).x, (*ptr2).y); + } + } +} + void Circle::renderPSCircleDraw(Vector& cc, double l, float a1, float a2) { BaseFillEllipse::renderPSCircleDraw(parent, cc, l, a1, a2); diff --git a/tksao/frame/circle.h b/tksao/frame/circle.h index 1d7ff77..ed26b7b 100644 --- a/tksao/frame/circle.h +++ b/tksao/frame/circle.h @@ -11,6 +11,7 @@ class Circle : public BaseEllipse, public BaseFillEllipse { protected: void renderXCircleDraw(Drawable, GC, Vector&, Vector&, int, int); + void renderXEllipseDraw(Drawable, GC, XPoint*, int); void renderPSCircleDraw(Vector& cc, double l, float a1, float a2); void renderPSEllipseArcDraw(Vector&, Vector&, Vector&, Vector&); diff --git a/tksao/frame/ellipse.C b/tksao/frame/ellipse.C index 7992090..0a53023 100644 --- a/tksao/frame/ellipse.C +++ b/tksao/frame/ellipse.C @@ -49,6 +49,23 @@ void Ellipse::renderXCircleDraw(Drawable drawable, GC lgc, BaseFillEllipse::renderXCircleDraw(display, drawable, lgc, st, size, a1, aa); } +void Ellipse::renderXEllipseDraw(Drawable drawable, GC lgc, + XPoint* pts, int cnt) +{ + if (fill_ || ((properties & SOURCE) && !(properties & DASH))) + BaseFillEllipse::renderXEllipseDraw(display, drawable, lgc, pts, cnt); + else { + // crude attempt to clip unwanted drawlines + // only works for SRC + for (int ii=0; ii<xpointNum_; ii+=2) { + XPoint* ptr1 = xpoint_+ii; + XPoint* ptr2 = xpoint_+ii+1; + XDrawLine(display, drawable, lgc, + (*ptr1).x, (*ptr1).y, (*ptr2).x, (*ptr2).y); + } + } +} + void Ellipse::renderPSCircleDraw(Vector& cc, double l, float a1, float a2) { BaseFillEllipse::renderPSCircleDraw(parent, cc, l, a1, a2); diff --git a/tksao/frame/ellipse.h b/tksao/frame/ellipse.h index 25bf115..5b95a7a 100644 --- a/tksao/frame/ellipse.h +++ b/tksao/frame/ellipse.h @@ -11,6 +11,7 @@ class Ellipse : public BaseEllipse, public BaseFillEllipse { protected: void renderXCircleDraw(Drawable, GC, Vector&, Vector&, int, int); + void renderXEllipseDraw(Drawable, GC, XPoint*, int); void renderPSCircleDraw(Vector& cc, double l, float a1, float a2); void renderPSEllipseArcDraw(Vector&, Vector&, Vector&, Vector&); |