Hi Thorsten and Gerd

I've looked at examples around my area where a higher class way terminates (at a
sharp angle) in the middle of a way or 2 straight ways and, in none that I
found, would it be a problem to adjust the angle of the higher class road.

I've re-done the patch to this effect, also adding in test for sameName arcs and
simplifying the logic slightly such that it is easier to change the testing
order.

@Thorsten: can you try this; it should fix your first example. It might fix the
second but, because the continuous way has quite an angle at the junction, even
moving the turn-off road away from it might not be enough to trigger the turn-
instruction.

@Gerd: The new logic doesn't attempt to handle roads crossing. For
straightEnough it just looks at the angle either side of the sharp angle. For
sameWay and sameRoad it just looks at the adjacent arcs either side of the sharp
angle. For 3 arc junctions this is correct but for 4 or more arcs it might help
but is not complete.

I'm going to use this for a while.

There are some diags that could be removed later.

Regards
Ticker

On Mon, 2024-08-12 at 09:34 +0000, Gerd Petermann wrote:
> Hi Ticker,
> 
> I also thought about sameWay as a criteria, but remember that this is likely
> to fail.
> I see quite often that tracks are drawn with 90° angles and another one is
> added which also
> has a 90° angle at the same crossing.  No idea why, but it isn't wrong.
> Same situation in residential areas where multiple ways are needed but all
> have the same name
> and type (e.g. a paved living_street).
> 
> ciao
> Gerd

Index: src/uk/me/parabola/imgfmt/app/net/AngleChecker.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/net/AngleChecker.java	(revision 4921)
+++ src/uk/me/parabola/imgfmt/app/net/AngleChecker.java	(working copy)
@@ -68,8 +68,9 @@
 	// If this is >= above, then compactDirs will be used unless other, non-vehicle access angles are sharp
 	private static final float SHARP_DEGREES = COMPACT_DIR_DEGREES;
 	// Experimentation found no benefit in increasing angle beyond 2 "sectors"
-	private static final float MIN_ANGLE = 11.25f; // don't reduce angles to less than this (arbitrary)
-	
+	private static final float MIN_ANGLE = 23f; // don't reduce angles to less than this (1 sector + bit)
+	private static final float STRAIGHT_EPSILON = 3f; // for angle.straightAnough()
+
 	// helper class to collect multiple arcs with (nearly) the same initial headings
 	private class ArcGroup {
 		float initialHeading;
@@ -106,7 +107,27 @@
 		public boolean isForward() {
 			return isForwardTrueCount == arcs.size();
 		}
-		
+
+		public boolean sameWay(ArcGroup other) {
+			for (RoadDef thisRoad : roadDefs)
+				for (RoadDef otherRoad : other.roadDefs) {
+					if (thisRoad.getId() == otherRoad.getId())
+						return true;
+				}
+			return false;
+		}
+
+		public boolean sameName(ArcGroup other) {
+			for (RoadDef thisRoad : roadDefs)
+				for (RoadDef otherRoad : other.roadDefs) {
+					String thisName = thisRoad.getName();
+					if (thisName != null)
+						if (thisName.equals(otherRoad.getName()))
+							return true;
+				}
+			return false;
+		}
+
 		public void modInitialHeading(float modIH) {
 			initialHeading += modIH;
 			if (initialHeading >= 180)
@@ -116,6 +137,7 @@
 
 			for (RouteArc arc : arcs) {
 				arc.modInitialHeading(modIH);
+				log.info("modInitHead", arc, modIH, initialHeading);
 			}
 		}
 
@@ -152,12 +174,20 @@
 
 		// Combine arcs with nearly the same initial heading.
 
+		if (log.isInfoEnabled())
+			log.info("fixSharpAngles", node, sharpAnglesCheckMask, arcs.size());
+
 		// first get direct arcs leaving the node
 		List<RouteArc> directArcs = new ArrayList<>();
 		for (RouteArc arc : arcs) {
-			if (arc.isDirect())
+			if (arc.isDirect()) {
+				if (log.isInfoEnabled()) {
+					RoadDef rd = arc.getRoadDef();
+					log.info("directArc", /*arc,*/ arc.getInitialHeading(), rd.getId(), rd.getName(),
+							 rd.getRoadSpeed(), rd.getRoadClass(), rd.paved());
+				}
 				directArcs.add(arc);
-			else
+			} else
 				// AngleChecker runs before addArcsToMajorRoads so there shouldn't be any indirect arcs yet.
 				// If this changes, extra care needs to be taken check they are positioned correctly in the list
 				// of arcs or that their heading is kept consistent with changes to their direct base arc.
@@ -237,6 +267,11 @@
 		class AngleAttr {
 			float angle;
 			float minAngle;
+
+			private boolean straightAnough() {
+				return angle > 180-STRAIGHT_EPSILON && angle < 180+STRAIGHT_EPSILON;
+			}
+
 		}
 
 		AngleAttr[] angles = new AngleAttr[n];
@@ -249,6 +284,8 @@
 			if (i+1 >= n)
 				aa.angle += 360;
 			aa.minAngle = Math.min(MIN_ANGLE, aa.angle);
+			log.info("AngleCalc", node, ag1.getInitialHeading(), aa.angle, ag2.getInitialHeading(), aa.minAngle);
+
 			float saveMinAngle = aa.minAngle;
 
 			if (ag1.isOneway() && ag2.isOneway() && (ag1.isForward() == ag2.isForward()))
@@ -317,8 +354,10 @@
 			if (wantedIncrement <= 0)
 				continue;
 			float oldAngle = aa.angle;
+			ArcGroup ag0 = null;
 			ArcGroup ag1 = arcGroups.get(i);
 			ArcGroup ag2 = arcGroups.get(i+1 < n ? i+1 : 0);
+			ArcGroup ag3 = null;
 			if (log.isInfoEnabled()){
 				log.info("sharp angle", aa.angle, "° at", node.getCoord(),
 						 "headings", getCompassBearing(ag1.getInitialHeading()), getCompassBearing(ag2.getInitialHeading()),
@@ -336,13 +375,47 @@
 			float deltaNext = nextAA.angle - nextAA.minAngle;
 
 			if (deltaNext > 0 && deltaPred > 0) { // can take from both
-				if (ag1.maxRoadClass == ag2.maxRoadClass &&
-					ag1.maxRoadSpeed == ag2.maxRoadSpeed) { // take from both in ratio to available
+				int chooseWhich = 0; // -ve to prefer to take from prev, +ve take from next
+				// order of {road_class, sameWay, straightness, roadName, road_speed} adjusted for priority
+				// Hoping sameWay before road_class fixing more problems than it might cause
+				if (chooseWhich == 0)
+					chooseWhich = ag1.maxRoadClass - ag2.maxRoadClass;
+				if (chooseWhich == 0) {
+					// if the two arcs either side of the sharp angle belong to the same
+					// way then change the arc on the other side hoping to trigger
+					// the correct turn-instruction
+					ag0 = arcGroups.get(i > 0 ? i-1 : n-1);
+					ag3 = n == 3 ? ag0 : arcGroups.get(i+2 < n ? i+2 : i+2-n);
+					if (ag2.sameWay(ag3))
+						chooseWhich = -1;
+					else if (ag1.sameWay(ag0))
+						chooseWhich = +1;
+				}
+				if (chooseWhich == 0) {
+					// where there is a straight road with a sharp turn-off then just adjust
+					// the turn-off. This is treated as a special case because the general
+					// logic below will adjust the adjust the straight road slightly more
+					// than the turn-off and, in some cases, with compactDirs, turn-instructions
+					if (nextAA.straightAnough())
+						chooseWhich = -1;
+					else if (predAA.straightAnough())
+						chooseWhich = +1;
+				}
+				if (chooseWhich == 0) {
+					// NB set ag0 & 3 if move this before sameWay()
+					// Way might have changed but could still be the same road by name or ref
+					if (ag2.sameName(ag3))
+						chooseWhich = -1;
+					else if (ag1.sameName(ag0))
+						chooseWhich = +1;
+				}
+				if (chooseWhich == 0)
+					chooseWhich = ag1.maxRoadSpeed - ag2.maxRoadSpeed;
+
+				if (chooseWhich == 0 ) { // take from both in ratio to available
 					deltaNext = Math.min(deltaNext, wantedIncrement * deltaNext / (deltaNext + deltaPred));
 					deltaPred = Math.min(deltaPred, wantedIncrement - deltaNext);
-			    } else if (ag1.maxRoadClass > ag2.maxRoadClass ||
-						   (ag1.maxRoadClass == ag2.maxRoadClass &&
-							ag1.maxRoadSpeed > ag2.maxRoadSpeed)) { // take as much as poss from next
+				} else if (chooseWhich > 0) { // take as much as poss from next
 					if (deltaNext >= wantedIncrement) {
 						deltaNext = wantedIncrement;
 						deltaPred = 0;
@@ -349,7 +422,7 @@
 					} else {
 						deltaPred = Math.min(deltaPred, wantedIncrement - deltaNext);
 					}
-				} else  { // take as much as possible from pred
+				} else { // take as much as possible from pred
 					if (deltaPred >= wantedIncrement) {
 						deltaPred = wantedIncrement;
 						deltaNext = 0;
@@ -357,6 +430,7 @@
 						deltaNext = Math.min(deltaNext, wantedIncrement - deltaPred);
 					}
 				}
+
 			} else if (deltaNext > 0) {
 				if (deltaNext > wantedIncrement)
 					deltaNext = wantedIncrement;
Index: src/uk/me/parabola/imgfmt/app/net/RouteArc.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/net/RouteArc.java	(revision 4921)
+++ src/uk/me/parabola/imgfmt/app/net/RouteArc.java	(working copy)
@@ -418,7 +418,9 @@
 			int compactedRatio = lengthRatio / 2 - 8;
 			assert compactedRatio > 0 && compactedRatio < 8;
 			curveData = new int[1];
-			curveData[0] = (compactedRatio << 5) | ((dh >> 3) & 0x1f);
+			//curveData[0] = (compactedRatio << 5) | ((dh >> 3) & 0x1f);
+			//try rounding this as well
+			curveData[0] = (compactedRatio << 5) | (((dh+4) >> 3) & 0x1f);
 			
 			/* check math:
 			int dhx = curveData[0] & 0x1f;
_______________________________________________
mkgmap-dev mailing list
mkgmap-dev@lists.mkgmap.org.uk
https://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev

Reply via email to