From 81c7a7de03a9b06218994ca2c9e2e4239247ed48 Mon Sep 17 00:00:00 2001 From: g_j_m Date: Tue, 22 Mar 2005 21:19:48 +0000 Subject: [PATCH] - Fix for x11 zoom bug now works for linestrings with more than one line segment. - Slight reduce CPU effort for intersection calculations git-svn-id: http://svn.osgeo.org/qgis/trunk@3006 c8812cc2-4d05-0410-92ff-de0c093fc19c --- src/qgsmaptopixel.cpp | 63 ++++++++++++++++++++++++------------------ src/qgsmaptopixel.h | 2 +- src/qgsvectorlayer.cpp | 20 +++++++------- 3 files changed, 47 insertions(+), 38 deletions(-) diff --git a/src/qgsmaptopixel.cpp b/src/qgsmaptopixel.cpp index 15d087099f0..47d150ae187 100644 --- a/src/qgsmaptopixel.cpp +++ b/src/qgsmaptopixel.cpp @@ -76,22 +76,18 @@ QString QgsMapToPixel::showParameters() } -void QgsMapToPixel::trimLine(const QgsPoint& from, const QgsPoint& to, +bool QgsMapToPixel::trimLine(const QgsPoint& from, const QgsPoint& to, QgsPoint& tFrom, QgsPoint& tTo) { // The limits for X11 screen coordinates. Actual value is 32767, but - // we allow a little bit if space of rounding errors in the + // we allow a little bit of space for rounding errors in the // calculations below. - static const int minX = -32760; - static const int maxX = 32760; - static const int minY = -32760; - static const int maxY = 32760; + static const double minX = -32760; + static const double maxX = 32760; + static const double minY = -32760; + static const double maxY = 32760; static const double SMALL_NUM = 1e-6; - // One thing in our favour is that if this function is called we - // already know that the line intersects the region that is visible - // on the screen, so there's no need to check for that intersection. - // To determine the intersection between a line given by the points // A and B, and the line given by the points C and D, calculate // @@ -122,6 +118,13 @@ void QgsMapToPixel::trimLine(const QgsPoint& from, const QgsPoint& to, // // P = A + r*(B-A) // + // Also do a check to see if the line segment is inside or outside + // the limits. If outside, return false to let the caller know that + // the shouldn't plot the line segment. + // + // This function has more than one exit point - as soon as the code + // determines that it has trimmed the lines appropriately, it exits, + // to reduce CPU effort. // Once we have adjusted both the to and from points, there is no // point in doing further checks, so return from the function @@ -136,13 +139,14 @@ void QgsMapToPixel::trimLine(const QgsPoint& from, const QgsPoint& to, tTo = to; // Check the top boundary - double r_n = (from.y() - minY) * (maxX - minX); - double d = - (to.y() - from.y()) * (maxX - minX); - double s_n = (from.y() - minY) * (to.x() - from.x()) - - (from.x() - minX) * (to.y() - from.y()); + double r_n = (from.y() - minY) * (maxX - minX); + double d = - (to.y() - from.y()) * (maxX - minX); + double s_n; - if (fabs(d) > SMALL_NUM && fabs(r_n) > SMALL_NUM != 0.0) + if (fabs(d) > SMALL_NUM && fabs(r_n) > SMALL_NUM) { + s_n = (from.y() - minY) * (to.x() - from.x()) + - (from.x() - minX) * (to.y() - from.y()); double r_nOverd = r_n / d; double s_nOverd = s_n / d; if (r_nOverd >= 0.0 && r_nOverd <= 1.0 && @@ -168,11 +172,11 @@ void QgsMapToPixel::trimLine(const QgsPoint& from, const QgsPoint& to, // the right border r_n = -(from.x() - maxX) * (maxY - minY); d = (to.x() - from.x()) * (maxY - minY); - s_n = (from.y() - minY) * (to.x() - from.x()) - - (from.x() - maxX) * (to.y() - from.y()); - if (fabs(d) > SMALL_NUM && fabs(r_n) > SMALL_NUM != 0.0) + if (fabs(d) > SMALL_NUM && fabs(r_n) > SMALL_NUM) { + s_n = (from.y() - minY) * (to.x() - from.x()) + - (from.x() - maxX) * (to.y() - from.y()); double r_nOverd = r_n / d; double s_nOverd = s_n / d; if (r_nOverd >= 0.0 && r_nOverd <= 1.0 && @@ -197,16 +201,16 @@ void QgsMapToPixel::trimLine(const QgsPoint& from, const QgsPoint& to, // Done both ends of the line, so leave. if (toDone && fromDone) - return; + return true; // the left border r_n = - (from.x() - minX) * (maxY - minY); d = (to.x() - from.x()) * (maxY - minY); - s_n = (from.y() - minY) * (to.x() - from.x()) - - (from.x() - minX) * (to.y() - from.y()); - if (fabs(d) > SMALL_NUM && fabs(r_n) > SMALL_NUM != 0.0) + if (fabs(d) > SMALL_NUM && fabs(r_n) > SMALL_NUM) { + s_n = (from.y() - minY) * (to.x() - from.x()) + - (from.x() - minX) * (to.y() - from.y()); double r_nOverd = r_n / d; double s_nOverd = s_n / d; if (r_nOverd >= 0.0 && r_nOverd <= 1.0 && @@ -231,16 +235,16 @@ void QgsMapToPixel::trimLine(const QgsPoint& from, const QgsPoint& to, // Done both ends of the line, so leave. if (toDone && fromDone) - return; + return true; // the bottom border r_n = (from.y() - maxY) * (maxX - minX); d = - (to.y() - from.y()) * (maxX - minX); - s_n = (from.y() - maxY) * (to.x() - from.x()) - - (from.x() - minX) * (to.y() - from.y()); - if (fabs(d) > SMALL_NUM && fabs(r_n) > SMALL_NUM != 0.0) + if (fabs(d) > SMALL_NUM && fabs(r_n) > SMALL_NUM) { + s_n = (from.y() - maxY) * (to.x() - from.x()) + - (from.x() - minX) * (to.y() - from.y()); double r_nOverd = r_n/d; double s_nOverd = s_n/d; if (r_nOverd >= 0.0 && r_nOverd <= 1.0 && @@ -262,6 +266,9 @@ void QgsMapToPixel::trimLine(const QgsPoint& from, const QgsPoint& to, } } } + // If the line hasn't been trimmed yet, it is entirely outside the + // boundary, so tell the calling code. + return false; } else { @@ -269,11 +276,13 @@ void QgsMapToPixel::trimLine(const QgsPoint& from, const QgsPoint& to, tFrom = from; tTo = to; } - /* + // Too verbose for QGISDEBUG, but handy sometimes. + /* std::cerr << "Point 1 trimmed from " << from.x() << ", " << from.y() << " to " << tFrom.x() << ", " << tFrom.y() << '\n' << "Point 2 trimmed from " << to.x() << ", " << to.y() << " to " << tTo.x() << ", " << tTo.y() << "\n\n"; */ + return true; } diff --git a/src/qgsmaptopixel.h b/src/qgsmaptopixel.h index 229835e2a44..dd2730d5ec2 100644 --- a/src/qgsmaptopixel.h +++ b/src/qgsmaptopixel.h @@ -85,7 +85,7 @@ class QgsMapToPixel{ //! String representation of the parameters used in the transform QString showParameters(); - static void trimLine(const QgsPoint& from, const QgsPoint& to, + static bool trimLine(const QgsPoint& from, const QgsPoint& to, QgsPoint& tFrom, QgsPoint& tTo); private: double mapUnitsPerPixel; diff --git a/src/qgsvectorlayer.cpp b/src/qgsvectorlayer.cpp index 111a1dc362b..4115ea1eaf5 100644 --- a/src/qgsvectorlayer.cpp +++ b/src/qgsvectorlayer.cpp @@ -2306,11 +2306,11 @@ void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsMapToPixel * t ptFrom = ptTo; else { - QgsMapToPixel::trimLine(ptFrom, ptTo, trimmedFrom, trimmedTo); - p->drawLine(static_cast(trimmedFrom.x()), - static_cast(trimmedFrom.y()), - static_cast(trimmedTo.x()), - static_cast(trimmedTo.y())); + if (QgsMapToPixel::trimLine(ptFrom, ptTo, trimmedFrom, trimmedTo)) + p->drawLine(static_cast(trimmedFrom.x()), + static_cast(trimmedFrom.y()), + static_cast(trimmedTo.x()), + static_cast(trimmedTo.y())); ptFrom = ptTo; } } @@ -2365,11 +2365,11 @@ void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsMapToPixel * t ptFrom = ptTo; else { - QgsMapToPixel::trimLine(ptFrom, ptTo, trimmedFrom, trimmedTo); - p->drawLine(static_cast(trimmedFrom.x()), - static_cast(trimmedFrom.y()), - static_cast(trimmedTo.x()), - static_cast(trimmedTo.y())); + if (QgsMapToPixel::trimLine(ptFrom, ptTo, trimmedFrom, trimmedTo)) + p->drawLine(static_cast(trimmedFrom.x()), + static_cast(trimmedFrom.y()), + static_cast(trimmedTo.x()), + static_cast(trimmedTo.y())); ptFrom = ptTo; } }