summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2018-10-08 18:57:07 (GMT)
committerGitHub <noreply@github.com>2018-10-08 18:57:07 (GMT)
commit11d2be66bad300683f2a71ec5c1a716a501dde66 (patch)
treece44434092eca69d96b95e38f8e2ae601b3a4a97
parent243ab6b1c0e547e66a6fafe5795e80bb0761264f (diff)
parentdbddfe871076e4a9c10438a8af9c1dfea3b917f6 (diff)
downloadblt-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
-rw-r--r--generic/tkbltGrAxis.C4
-rw-r--r--generic/tkbltGrElemLine.C86
-rw-r--r--generic/tkbltGrMisc.C80
-rw-r--r--generic/tkbltGrMisc.h22
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);
};