Hi Gerd

Thinking about this a bit more, there are still some cases where
adjacent shapes are next to cut-lines to get to holes (ie 3 or more
lines at same cut-point) that might not be ordered correctly. I think
it is possible to fix these by adding another sort structure.

Starting on this, I didn't like some of my new awkward shape handling
code and it has is a bug in the handling of the last element in the
list - fixed in the tidy-up

I've attached low-res-opt patch

Ticker

On Wed, 2021-06-02 at 14:58 +0000, Gerd Petermann wrote:
> Hi Ticker,
> 
> That seems to work better. I still see some error messages but those
> are probably really invalid shapes produced by ShapeMerger. At least
> I see that one point is visited more than twice and that should not
> happen.
> 
> Maybe you can add unit tests to test the error cases?
> 
> Gerd
> 
> ________________________________________
> Von: mkgmap-dev <mkgmap-dev-boun...@lists.mkgmap.org.uk> im Auftrag
> von Ticker Berkin <rwb-mkg...@jagit.co.uk>
> Gesendet: Mittwoch, 2. Juni 2021 16:06
> An: Development list for mkgmap
> Betreff: Re: [mkgmap-dev] special case where splitting fails without
> a log message
> 
> Hi Gerd
> 
> I've found and fixed some stupid mistakes - sorry for wasting your
> time.
> 
> Patch attached - works with your test case.
> 
> Ticker
> 
> _______________________________________________
> mkgmap-dev mailing list
> mkgmap-dev@lists.mkgmap.org.uk
> https://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev
Index: src/uk/me/parabola/util/ShapeSplitter.java
===================================================================
--- src/uk/me/parabola/util/ShapeSplitter.java	(revision 4755)
+++ src/uk/me/parabola/util/ShapeSplitter.java	(working copy)
@@ -287,6 +287,10 @@
 
 	private boolean multSameLow; // lineInfo.sort(comparator) might set this
 
+	// following are for processAwkward...
+	private MergeCloseHelper forwardLine, backwardLine;
+	private int directionBalance;
+
 	private void logMsg(Object ... olist) {
 		detectedProblems = true;
 		log.warn(olist);
@@ -411,12 +415,14 @@
 		//  Multiple hole balloons from the same point
 		//  Balloon(s) that share the same point as dLoops
 		boolean haveBalloons = false;
-		
+
 		// Duplicate dLoops in same direction can be removed / opposite direction cancel each other out.
 		// Do this before Balloon processing as dLoop removal can make some problems go away.
 		List<MergeCloseHelper> newList = new ArrayList<>(lineInfo.size());
-		MergeCloseHelper forwardLine = null, backwardLine = null, lastLine = null;
-		int directionBalance = 0;
+		MergeCloseHelper lastLine = null;
+		forwardLine = null;
+		backwardLine = null;
+		directionBalance = 0;
 		boolean grouping = false;
 		for (MergeCloseHelper thisLine : lineInfo) {
 			if (lastLine != null) {
@@ -424,40 +430,14 @@
 					thisLine.lowPoint == lastLine.lowPoint &&
 					thisLine.highPoint == lastLine.highPoint &&
 					Math.abs(thisLine.areaToLine) == Math.abs(lastLine.areaToLine);
-				if (grouping || sameAsLast) {
-					grouping = true;
-					if (lastLine.direction > 0) {
-						forwardLine = lastLine;
-						++directionBalance;
-					} else {
-						backwardLine = lastLine;
-						--directionBalance;
-					}
-				}
-				if (!sameAsLast) { // flush previous
-					if (grouping) {
-						if (directionBalance > 0)
-							newList.add(forwardLine);
-						else if (directionBalance < 0)
-							newList.add(backwardLine);
-						directionBalance = 0;
-						grouping = false;
-					} else
-						newList.add(lastLine);
-				}
+				fixDups(newList, lastLine, sameAsLast, grouping);
+				grouping = sameAsLast;
 			}
 			lastLine = thisLine;
 			if (thisLine.lowPoint == thisLine.highPoint)
 				haveBalloons = true;
 		}
-		// flush last
-		if (grouping) {
-			if (directionBalance > 0)
-				newList.add(forwardLine);
-			else if (directionBalance < 0)
-				newList.add(backwardLine);
-		} else
-			newList.add(lastLine);
+		fixDups(newList, lastLine, false, grouping);
 
 		if (newList.size() < lineInfo.size()) {
 			lineInfo.clear();
@@ -466,7 +446,7 @@
 
 		if (!haveBalloons)
 			return;
-		
+
 		// Balloons will be sorted earlier than dLoops that share the same lowPoint,
 		// but those that form a shape must be within a hole and those that form a hole must be within
 		// a shape and so might need moving.
@@ -486,29 +466,12 @@
 		for (MergeCloseHelper thisLine : lineInfo) {
 			if (lastLine != null) {
 				boolean sameAsLast = thisLine.lowPoint == lastLine.lowPoint;
-				if (grouping || sameAsLast) {
-					grouping = true;
-					if (lastLine.lowPoint != lastLine.highPoint)
-						dLoops.add(lastLine);
-					else if (lastLine.areaOrHole == 1)
-						shapes.add(lastLine);
-					else
-						holes.add(lastLine);
-				}
-				if (!sameAsLast) {
-					if (grouping) {
-						reordered |= fixOrder(newList, dLoops, shapes, holes);
-						grouping = false;
-					} else
-						newList.add(lastLine);
-				}
+				reordered |= fixOrder(newList, lastLine, sameAsLast, grouping, dLoops, shapes, holes);
+				grouping = sameAsLast;
 			}
 			lastLine = thisLine;
 		}
-		if (grouping)
-			reordered |= fixOrder(newList, dLoops, shapes, holes);
-		else
-			newList.add(lastLine);
+		reordered |= fixOrder(newList, lastLine, false, grouping, dLoops, shapes, holes);
 
 		if (reordered) {
 			lineInfo.clear();
@@ -516,8 +479,48 @@
 		}
 	} // processAwkward
 
-	private boolean fixOrder(List<MergeCloseHelper> newList, List<MergeCloseHelper> dLoops,
-							 List<MergeCloseHelper> shapes, List<MergeCloseHelper> holes) {
+	private void fixDups(List<MergeCloseHelper> newList, MergeCloseHelper lastLine, boolean sameAsLast, boolean grouping) {
+		if (grouping || sameAsLast) {
+			if (lastLine.direction > 0) {
+				forwardLine = lastLine;
+				++directionBalance;
+			} else {
+				backwardLine = lastLine;
+				--directionBalance;
+			}
+		}
+		if (sameAsLast)
+			return;
+		// flush previous
+		if (!grouping) {
+			newList.add(lastLine);
+			return;
+		}
+		if (directionBalance > 0)
+			newList.add(forwardLine);
+		else if (directionBalance < 0)
+			newList.add(backwardLine);
+		directionBalance = 0;
+	} // fixDups
+
+	private boolean fixOrder(List<MergeCloseHelper> newList, MergeCloseHelper lastLine, boolean sameAsLast, boolean grouping,
+							 List<MergeCloseHelper> dLoops, List<MergeCloseHelper> shapes, List<MergeCloseHelper> holes) {
+		if (grouping || sameAsLast) {
+			if (lastLine.lowPoint != lastLine.highPoint)
+				dLoops.add(lastLine);
+			else if (lastLine.areaOrHole == 1)
+				shapes.add(lastLine);
+			else
+				holes.add(lastLine);
+		}
+		if (sameAsLast)
+			return false;
+		// flush previous
+		if (!grouping) {
+			newList.add(lastLine);
+			return false;
+		}
+
 		if (holes.size() > 1)
 			logMsg("Multiple holes at same point - shapeSplitter might cause self-intersection");
 			// logMsg triggers "split failed" and diags, but this is really a warning so maybe downgrade later
@@ -548,6 +551,7 @@
 			}
 		}
 
+		// there is still a flaw here, a highpoint could also be in this position. Need to have another structure to track this
 		if (dLoops.size() > 1)
 			logMsg("Possible ambiguous balloon allocation. Dloops:", dLoops.size(), "shapes:", shapes.size(), "holes:", holes.size());
 		// if 2 dividors hole>space | space>hole then, as only place for holes is middle, can avoid this warning
@@ -741,7 +745,7 @@
 					  "Possibly a self-intersecting polygon");
 		}
 	} // split
-		
+
 	private void formLoops(List<Coord> coords, int dividingLine, boolean isLongitude,
 						   boolean wantLess, boolean wantMore, Long2ObjectOpenHashMap<Coord> coordPool) {
 		List<Coord> lessPoly = null, morePoly = null;
_______________________________________________
mkgmap-dev mailing list
mkgmap-dev@lists.mkgmap.org.uk
https://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev

Reply via email to