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