diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2018-10-08 18:57:07 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-08 18:57:07 (GMT) |
commit | 11d2be66bad300683f2a71ec5c1a716a501dde66 (patch) | |
tree | ce44434092eca69d96b95e38f8e2ae601b3a4a97 /generic | |
parent | 243ab6b1c0e547e66a6fafe5795e80bb0761264f (diff) | |
parent | dbddfe871076e4a9c10438a8af9c1dfea3b917f6 (diff) | |
download | blt-11d2be66bad300683f2a71ec5c1a716a501dde66.zip blt-11d2be66bad300683f2a71ec5c1a716a501dde66.tar.gz blt-11d2be66bad300683f2a71ec5c1a716a501dde66.tar.bz2 |
Merge pull request #20 from prs-de/log-scale-zerov3.2.12
Correct display of zero values with -logscale 1
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tkbltGrAxis.C | 4 | ||||
-rw-r--r-- | generic/tkbltGrElemLine.C | 86 | ||||
-rw-r--r-- | generic/tkbltGrMisc.C | 80 | ||||
-rw-r--r-- | generic/tkbltGrMisc.h | 22 |
4 files changed, 105 insertions, 87 deletions
diff --git a/generic/tkbltGrAxis.C b/generic/tkbltGrAxis.C index 26560d0..738acc3 100644 --- a/generic/tkbltGrAxis.C +++ b/generic/tkbltGrAxis.C @@ -1129,7 +1129,7 @@ double Axis::invVMap(double y) double Axis::hMap(double x) { AxisOptions* ops = (AxisOptions*)ops_; - if ((ops->logScale) && (x != 0.0)) { + if (ops->logScale) { x = log10(fabs(x)); } /* Map graph coordinate to normalized coordinates [0..1] */ @@ -1143,7 +1143,7 @@ double Axis::hMap(double x) double Axis::vMap(double y) { AxisOptions* ops = (AxisOptions*)ops_; - if ((ops->logScale) && (y != 0.0)) { + if (ops->logScale) { y = log10(fabs(y)); } /* Map graph coordinate to normalized coordinates [0..1] */ diff --git a/generic/tkbltGrElemLine.C b/generic/tkbltGrElemLine.C index 9e3f39a..f8ec8f7 100644 --- a/generic/tkbltGrElemLine.C +++ b/generic/tkbltGrElemLine.C @@ -1427,71 +1427,6 @@ void LineElement::mergePens(LineStyle **styleMap) } } -#define CLIP_TOP (1<<0) -#define CLIP_BOTTOM (1<<1) -#define CLIP_RIGHT (1<<2) -#define CLIP_LEFT (1<<3) - -int LineElement::outCode(Region2d *extsPtr, Point2d *p) -{ - int code =0; - if (p->x > extsPtr->right) - code |= CLIP_RIGHT; - else if (p->x < extsPtr->left) - code |= CLIP_LEFT; - - if (p->y > extsPtr->bottom) - code |= CLIP_BOTTOM; - else if (p->y < extsPtr->top) - code |= CLIP_TOP; - - return code; -} - -int LineElement::clipSegment(Region2d *extsPtr, int code1, int code2, - Point2d *p, Point2d *q) -{ - int inside = ((code1 | code2) == 0); - int outside = ((code1 & code2) != 0); - - /* - * In the worst case, we'll clip the line segment against each of the four - * sides of the bounding rectangle. - */ - while ((!outside) && (!inside)) { - if (code1 == 0) { - Point2d *tmp; - int code; - - /* Swap pointers and out codes */ - tmp = p, p = q, q = tmp; - code = code1, code1 = code2, code2 = code; - } - if (code1 & CLIP_LEFT) { - p->y += (q->y - p->y) * - (extsPtr->left - p->x) / (q->x - p->x); - p->x = extsPtr->left; - } else if (code1 & CLIP_RIGHT) { - p->y += (q->y - p->y) * - (extsPtr->right - p->x) / (q->x - p->x); - p->x = extsPtr->right; - } else if (code1 & CLIP_BOTTOM) { - p->x += (q->x - p->x) * - (extsPtr->bottom - p->y) / (q->y - p->y); - p->y = extsPtr->bottom; - } else if (code1 & CLIP_TOP) { - p->x += (q->x - p->x) * - (extsPtr->top - p->y) / (q->y - p->y); - p->y = extsPtr->top; - } - code1 = outCode(extsPtr, p); - - inside = ((code1 | code2) == 0); - outside = ((code1 & code2) != 0); - } - return (!inside); -} - void LineElement::saveTrace(int start, int length, MapInfo* mapPtr) { bltTrace* tracePtr = new bltTrace; @@ -1544,24 +1479,18 @@ void LineElement::mapTraces(MapInfo *mapPtr) graphPtr_->extents(&exts); int count = 1; - int code1 = outCode(&exts, mapPtr->screenPts); Point2d* p = mapPtr->screenPts; Point2d* q = p + 1; int start; int ii; for (ii=1; ii<mapPtr->nScreenPts; ii++, p++, q++) { - Point2d s; - s.x = 0; - s.y = 0; - int code2 = outCode(&exts, q); - // Save the coordinates of the last point, before clipping - if (code2 != 0) - s = *q; - + // Save the coordinates of the last point before clipping. + Point2d originalq = *q; int broken = BROKEN_TRACE(ops->penDir, p->x, q->x); - int offscreen = clipSegment(&exts, code1, code2, p, q); - if (broken || offscreen) { + LineRectClipResult clipresult = lineRectClip(&exts, p, q); + + if (broken || clipresult == CLIP_OUTSIDE) { // The last line segment is either totally clipped by the plotting // area or the x-direction is wrong, breaking the trace. Either // way, save information about the last trace (if one exists), @@ -1579,14 +1508,13 @@ void LineElement::mapTraces(MapInfo *mapPtr) // If the last point is clipped, this means that the trace is // broken after this point. Restore the original coordinate // (before clipping) after saving the trace. - if (code2 != 0) { + if (clipresult & CLIP_Q) { start = ii - (count - 1); saveTrace(start, count, mapPtr); - mapPtr->screenPts[ii] = s; + mapPtr->screenPts[ii] = originalq; count = 1; } } - code1 = code2; } if (count > 1) { start = ii - count; diff --git a/generic/tkbltGrMisc.C b/generic/tkbltGrMisc.C index d951494..aaafcfd 100644 --- a/generic/tkbltGrMisc.C +++ b/generic/tkbltGrMisc.C @@ -39,6 +39,7 @@ #include "tkbltGraph.h" #include "tkbltGrMisc.h" +#include "tkbltInt.h" using namespace Blt; @@ -70,6 +71,63 @@ int Blt::pointInPolygon(Point2d *s, Point2d *points, int nPoints) return (count & 0x01); } +/* + *--------------------------------------------------------------------------- + * Clips a rectangle in one direction where some of the coordinates are + * infinite. + *--------------------------------------------------------------------------- + */ +static LineRectClipResult ClipInfinity (double *pa, double *pb, double *qa, double *qb, double region_min, double region_max) +{ + int finitepa = isfinite(*pa); + int finiteqa = isfinite(*qa); + + if (!finitepa) { + if (finiteqa) { + if (*pa > 0) { // +Inf + *pa = region_max; + } else if (*pa < 0) { // -Inf + *pa = region_min; + } else { // NaN + return CLIP_OUTSIDE; + } + // *qa is finite, simplify to zero slope at *pb. + *pb = *qb; + return CLIP_P; + } else { // Both infinite. + int positivepa = *pa > 0; + int positiveqa = *qa > 0; + + if (positivepa < positiveqa) { // (p,q) ~ (-Inf,Inf) + *pa = region_min; + *qa = region_max; + } else if (positivepa > positiveqa) { // (p,q) ~ (Inf,-Inf) + *pa = region_max; + *qa = region_min; + } else { // (Inf,Inf), (-Inf,-Inf) or NaN. + return CLIP_OUTSIDE; + } + // At opposite infinities; simplify to zero slope in the middle. + *pb = *qb = (*pb + *qb) / 2.0; + return CLIP_P | CLIP_Q; + } + } else if (!finiteqa) { + // *pa is finite. + if (*qa > 0) { // +Inf + *qa = region_max; + } else if (*qa < 0) { // -Inf + *qa = region_min; + } else { // NaN + return CLIP_OUTSIDE; + } + // *pa is finite, simplify to zero slope at *qb. + *qb = *pb; + return CLIP_Q; + } + return CLIP_OUTSIDE; +} + + static int ClipTest (double ds, double dr, double *t1, double *t2) { double t; @@ -77,7 +135,7 @@ static int ClipTest (double ds, double dr, double *t1, double *t2) if (ds < 0.0) { t = dr / ds; if (t > *t2) { - return 0; + return 0; /* Line is outside clipping edge */ } if (t > *t1) { *t1 = t; @@ -85,7 +143,7 @@ static int ClipTest (double ds, double dr, double *t1, double *t2) } else if (ds > 0.0) { t = dr / ds; if (t < *t1) { - return 0; + return 0; /* Line is outside clipping edge */ } if (t < *t2) { *t2 = t; @@ -105,35 +163,47 @@ static int ClipTest (double ds, double dr, double *t1, double *t2) * of the clipped line segment are returned. The original coordinates * are overwritten. * + * The return value indicates whether the line was completely outside of + * the region, returning CLIP_OUTSIDE; or at least partly inside, returning + * CLIP_INSIDE. In the latter case, the result might be or'ed with CLIP_P + * if p coordinates were clipped, or CLIP_Q if q coordinates were. + * * Reference: * Liang, Y-D., and B. Barsky, A new concept and method for * Line Clipping, ACM, TOG,3(1), 1984, pp.1-22. *--------------------------------------------------------------------------- */ -int Blt::lineRectClip(Region2d* regionPtr, Point2d *p, Point2d *q) +LineRectClipResult Blt::lineRectClip(Region2d* regionPtr, Point2d *p, Point2d *q) { double t1, t2; double dx, dy; + LineRectClipResult res = CLIP_OUTSIDE; + + res |= ClipInfinity(&p->x, &p->y, &q->x, &q->y, regionPtr->bottom, regionPtr->top); t1 = 0.0, t2 = 1.0; dx = q->x - p->x; if ((ClipTest (-dx, p->x - regionPtr->left, &t1, &t2)) && (ClipTest (dx, regionPtr->right - p->x, &t1, &t2))) { + res |= ClipInfinity(&p->y, &p->x, &q->y, &q->x, regionPtr->top, regionPtr->bottom); + dy = q->y - p->y; if ((ClipTest (-dy, p->y - regionPtr->top, &t1, &t2)) && (ClipTest (dy, regionPtr->bottom - p->y, &t1, &t2))) { if (t2 < 1.0) { q->x = p->x + t2 * dx; q->y = p->y + t2 * dy; + res |= CLIP_Q; } if (t1 > 0.0) { p->x += t1 * dx; p->y += t1 * dy; + res |= CLIP_P; } - return 1; + return res | CLIP_INSIDE; } } - return 0; + return CLIP_OUTSIDE; } /* diff --git a/generic/tkbltGrMisc.h b/generic/tkbltGrMisc.h index ba86b75..5c16dce 100644 --- a/generic/tkbltGrMisc.h +++ b/generic/tkbltGrMisc.h @@ -104,6 +104,26 @@ namespace Blt { int offset; } Dashes; + typedef enum { + CLIP_OUTSIDE = 0, + CLIP_INSIDE = 1 << 0, + CLIP_P = 1 << 1, + CLIP_Q = 1 << 2 + } LineRectClipResult; + + inline LineRectClipResult operator|(LineRectClipResult a, LineRectClipResult b) { + return static_cast<LineRectClipResult>(static_cast<int>(a) | static_cast<int>(b)); + } + + inline LineRectClipResult operator&(LineRectClipResult a, LineRectClipResult b) { + return static_cast<LineRectClipResult>(static_cast<int>(a) & static_cast<int>(b)); + } + + inline LineRectClipResult & operator|=(LineRectClipResult & rhs, LineRectClipResult v) { + rhs = rhs | v; + return rhs; + } + extern char* dupstr(const char*); extern Graph* getGraphFromWindowData(Tk_Window tkwin); @@ -111,7 +131,7 @@ namespace Blt { int nScreenPts); extern int polyRectClip(Region2d *extsPtr, Point2d *inputPts, int nInputPts, Point2d *outputPts); - extern int lineRectClip(Region2d *regionPtr, Point2d *p, Point2d *q); + extern LineRectClipResult lineRectClip(Region2d *regionPtr, Point2d *p, Point2d *q); extern Point2d getProjection (int x, int y, Point2d *p, Point2d *q); }; |