Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix rendering of cross-hatched areas #2102

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

lpechacek
Copy link
Member

See issue #2101 for details.

@dl3sdo
Copy link
Member

dl3sdo commented Oct 22, 2022

The fix looks fine to me. I just tested it and it provides the expected results.

@dg0yt
Copy link
Member

dg0yt commented Oct 22, 2022

Thanks to both of you for picking up this issue.

setTopLeft was really wrong because it "may change the size". I think it should have been moveTopLeft.
IMO includeRect does too much to the extent which is an initial, invalid QRectF at this point.
(There is also safeIncludeRect, just for cases where the rect maybe initially invalid. So many helpers which even aren't pure functions...)

@lpechacek lpechacek force-pushed the issue-2101-cross-hatch-pattern branch from afbc16d to 72836d3 Compare November 28, 2022 08:52
The assumption that the first point lies in the top left corner of the
bounding box is not valid. As a result, the rendering of cross-hatched
area patterns was broken when the area extended beyond the viewport.

Amends commit 3590c35 (LineRenderable: Fix extent calculation in
simple constructor).

Closes OpenOrienteeringGH-2101 (Incorrect rendering of area cross-hatch pattern).
@lpechacek lpechacek force-pushed the issue-2101-cross-hatch-pattern branch from 72836d3 to 36e68aa Compare November 28, 2022 09:13
@lpechacek
Copy link
Member Author

lpechacek commented Nov 28, 2022

Answering out of order...

IMO includeRect does too much to the extent which is an initial, invalid QRectF at this point. (There is also safeIncludeRect, just for cases where the rect maybe initially invalid. So many helpers which even aren't pure functions...)

Thanks, Kai, for the review. includeRect is plain wrong in my patch as it causes too large extents for the lines. includeRectSafe does the right job in the freshly constructed extent.

setTopLeft was really wrong because it "may change the size". I think it should have been moveTopLeft.

The use of moveTopLeft would be a solution. Anyway, we would have to determine the minimum on the x and y coordinates, including the line width, or blindly set the rectangle origin and then call includeRect:

	extent.moveTopLeft(first);
	rectInclude(extent, first - right);
	rectInclude(extent, first + right);
	rectInclude(extent, second - right);
	rectInclude(extent, second + right);

My approach would be completely different, however. We've got a straightforward calculation here - two line endpoints, determine the bounding rectangle. My choice would be a complete rewrite here for the sake of comprehension and efficiency. The only disadvantage I can see is that we are working with individual coordinates rather than with vectors which is error prone. I don't see a vector-based solution at the moment though.

diff --git a/src/core/renderables/renderable_implementation.cpp b/src/core/renderables/renderable_implementation.cpp
index 32f6f78d9201..ab849f4fc977 100644
--- a/src/core/renderables/renderable_implementation.cpp
+++ b/src/core/renderables/renderable_implementation.cpp
@@ -281,17 +281,15 @@ LineRenderable::LineRenderable(const LineSymbol* symbol, QPointF first, QPointF
  , cap_style(Qt::FlatCap)
  , join_style(Qt::MiterJoin)
 {
-	qreal half_line_width = (color_priority < 0) ? 0 : line_width/2;
-	
 	auto right = MapCoordF(second - first).perpRight();
 	right.normalize();
-	right *= half_line_width;
-	
-	extent.setTopLeft(first + right);
-	rectInclude(extent, first - right);
-	rectInclude(extent, second - right);
-	rectInclude(extent, second + right);
-	
+	right *= (color_priority < 0) ? 0 : line_width;
+	auto const origin = QPointF { std::min(first.x(), second.x()) - right.x()/2,
+	                              std::min(first.y(), second.y()) - right.y()/2 };
+	auto const size = QSizeF { std::abs(first.x() - second.x()) + right.x()/2,
+	                           std::abs(first.y() - second.y()) + right.y()/2 };
+
+	extent = QRectF { origin, size };
 	path.moveTo(first);
 	path.lineTo(second);
 }

@lpechacek
Copy link
Member Author

My choice would be a complete rewrite here for the sake of comprehension and efficiency.

LibreMapper/mapper@c3f86a7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants