Hi,

I remember that it is on my Todo-List :-)

So I performed a quick implementation following your suggestion. You can find in the attached patch so that you can play a little bit with it. (Attention: it is completely untested!!)
You can find a patched mkgmap.jar at http://files.mkgmap.org.uk/detail/215.

I think curviness should to be defined in a different way.
1. Calculate the distance of each point Dmiddle to the virtual line from first to the last point. 2. curviness()=standard mean(Dmiddle/(length to next point + length to previous point)

I think this gives a better indication how curviness a road is. But it need to be implemented and tested later on :-)

WanMil

Hi all,

Garmin offers "curvy roads" preferences for their zümo 390 and 590 devices.
https://buy.garmin.com/en-US/US/on-the-road/motorcycles/zumo-390lm/prod138275.html
I'm thinking about creating motorcycle maps for old 200 series.
Might it be useful to integrate a curviness() function so that mkgmap can 
optimize for curvy roads too? It might also help do determine a better default 
speed for curvy roads for use with car routing.

The curviness() value might be the overall absolute turning angle (in degrees) 
of a road segment divided by the segment's length.

What's your opinion?

Cheers
Manfred




Pseudo code might look like this:

function curviness()
{
oldpoint=points(0)
foreach (point of a way segment as newpoint)
   {
   d_x=(newpoint.x-oldpoint.x)/360*40000000*COS(newpoint.x*PI()/180) //in meters
   d_y=(newpoint.y-oldpoint.y)/360*40000000 //in meters
   length+=sqrt(d_x**2+d_y**2)
   angle=arctan(d_y/d_x)
   d_angle=abs(angle-old_angle)
   sgn_x=sgn(d_x)
   sgn_y=sgn(d_y)
   if ((sgn_x*sgn_y*old_sgn_x*old_sgn_y)=-1 && (sgn_x!=old_sgn_x))  
d_angle=pi-d_angle  // 180 degrees correction, otherwise north-south roads show strange 
results
   if (point>1) sum_angle+=d_angle
   old_angle=angle
   oldpoint=newpoint
   old_sgn_x=sgn_x
   old_sgn_y=sgn_y
   }
return sum_angle/length
}

// perhaps simple multiplication is faster than 4 times sgn() functions?
_______________________________________________
mkgmap-dev mailing list
mkgmap-dev@lists.mkgmap.org.uk
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev


Index: src/uk/me/parabola/mkgmap/osmstyle/function/FunctionFactory.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/function/FunctionFactory.java	(revision 3313)
+++ src/uk/me/parabola/mkgmap/osmstyle/function/FunctionFactory.java	(working copy)
@@ -28,27 +28,40 @@
 	 * @return the style function instance or {@code null} if there is no such function
 	 */
 	public static StyleFunction createFunction(String name) {
-		if ("length".equals(name))
+		if (name == null) {
+			return null;
+		}
+		
+		switch (name) {
+		case "length":
 			return new LengthFunction();
-		//} else if ("get_tag".equals(name))
-		//	return new GetTagFunction(tag);
-		if ("is_closed".equals(name)) {
+		case "curviness":
+			return new CurvinessFunction();
+			
+		case "is_closed":
 			return new IsClosedFunction();
-		}
-		if ("is_complete".equals(name)) {
+			
+		case "is_complete":
 			return new IsCompleteFunction();
-		}
-		if ("area_size".equals(name))
+		case "area_size":
 			return new AreaSizeFunction();
-		if ("maxspeedkmh".equals(name))
+			
+		case "maxspeedkmh":
 			return new MaxSpeedFunction(SpeedUnit.KMH);
-		if ("maxspeedmph".equals(name))
+		case "maxspeedmph":
 			return new MaxSpeedFunction(SpeedUnit.MPH);
-		if ("type".equals(name))
+			
+		case "type":
 			return new TypeFunction();
-		if ("osmid".equals(name))
+		case "osmid":
 			return new OsmIdFunction();
+			
+		default:
+			// function is not known
+			return null;
+		}
 		
-		return null;
+
+	
 	}
 }
Index: src/uk/me/parabola/mkgmap/osmstyle/function/CurvinessFunction.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/function/CurvinessFunction.java	(revision 0)
+++ src/uk/me/parabola/mkgmap/osmstyle/function/CurvinessFunction.java	(revision 0)
@@ -0,0 +1,67 @@
+package uk.me.parabola.mkgmap.osmstyle.function;
+
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.Locale;
+
+import uk.me.parabola.imgfmt.Utils;
+import uk.me.parabola.imgfmt.app.Coord;
+import uk.me.parabola.log.Logger;
+import uk.me.parabola.mkgmap.reader.osm.Element;
+import uk.me.parabola.mkgmap.reader.osm.Way;
+
+public class CurvinessFunction extends CachedFunction {
+	private static final Logger log = Logger.getLogger(LengthFunction.class);
+
+	private final DecimalFormat nf = new DecimalFormat("0.0#####################", DecimalFormatSymbols.getInstance(Locale.US));
+
+	private final LengthFunction length;
+	
+	public CurvinessFunction() {
+		super(null);
+		this.length = new LengthFunction();
+	}
+
+	protected String calcImpl(Element el) {
+		if (el instanceof Way) {
+			Way w = (Way)el;
+			String lengthStr = length.value(w);
+			if (lengthStr == null) {
+				// length cannot be calculated
+				return null;
+			}
+			double l = 0.0d;
+			try {
+				l = Double.valueOf(lengthStr);
+			} catch (Exception exp) {
+				// should not happen?
+				log.error("Cannot calculate length for way "+w.toBrowseURL(), exp);
+				return null;
+			}
+			if (l == 0) {
+				return null;
+			}
+			
+			// calc 
+			double angle = 0;
+			Coord c1 = null;
+			Coord c2 = null;
+			
+			for (Coord c3 : w.getPoints()) {
+				if (c1 != null && c2 != null) {
+					angle += Utils.getAngle(c1, c2, c3);
+				}
+				c1 = c2;
+				c2 = c3;
+			}
+			
+			return nf.format(angle/l);
+			
+		}
+		return null;
+	}
+
+	public boolean supportsWay() {
+		return true;
+	}
+}
_______________________________________________
mkgmap-dev mailing list
mkgmap-dev@lists.mkgmap.org.uk
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev

Reply via email to