diff --git a/OsmAnd-java/src/net/osmand/osm/edit/OsmMapUtils.java b/OsmAnd-java/src/net/osmand/osm/edit/OsmMapUtils.java index 103698823b..bd11e745d9 100644 --- a/OsmAnd-java/src/net/osmand/osm/edit/OsmMapUtils.java +++ b/OsmAnd-java/src/net/osmand/osm/edit/OsmMapUtils.java @@ -7,6 +7,7 @@ import java.util.Comparator; import java.util.List; import net.osmand.data.LatLon; +import net.osmand.util.MapAlgorithms; import net.osmand.util.MapUtils; public class OsmMapUtils { @@ -27,7 +28,7 @@ public class OsmMapUtils { if (e instanceof Node) { return ((Node) e).getLatLon(); } else if (e instanceof Way) { - return getWeightCenterForNodes(((Way) e).getNodes()); + return getWeightCenterForWay(((Way) e)); } else if (e instanceof Relation) { List list = new ArrayList(); for (Entity fe : ((Relation) e).getMembers(null)) { @@ -58,7 +59,7 @@ public class OsmMapUtils { return new LatLon(latitude / nodes.size(), longitude / nodes.size()); } - public static LatLon getWeightCenterForNodes(Collection nodes) { + public static LatLon getWeightCenterForNodes(Collection nodes ) { if (nodes.isEmpty()) { return null; } @@ -77,6 +78,36 @@ public class OsmMapUtils { } return new LatLon(latitude / count, longitude / count); } + + public static LatLon getWeightCenterForWay(Way w) { + Collection nodes = w.getNodes(); + boolean area = w.getFirstNodeId() == w.getLastNodeId(); + if (nodes.isEmpty()) { + return null; + } + LatLon ll = area ? getMathWeightCenterForNodes(nodes) : getWeightCenterForNodes(nodes); + if(ll == null) { + return null; + } + double flat = ll.getLatitude(); + double flon = ll.getLongitude(); + if(!area || !MapAlgorithms.containsPoint(nodes, ll.getLatitude(), ll.getLongitude())) { + double minDistance = Double.MAX_VALUE; + for (Node n : nodes) { + if (n != null) { + double d = MapUtils.getDistance(n.getLatitude(), n.getLongitude(), ll.getLatitude(), ll.getLongitude()); + if(d < minDistance) { + flon = n.getLongitude(); + flat = n.getLatitude(); + minDistance = d; + } + } + } + } + + return new LatLon(flat, flon); + } + public static LatLon getMathWeightCenterForNodes(Collection nodes) { if (nodes.isEmpty()) { diff --git a/OsmAnd-java/src/net/osmand/osm/edit/Way.java b/OsmAnd-java/src/net/osmand/osm/edit/Way.java index 982053a703..882b25cd2e 100644 --- a/OsmAnd-java/src/net/osmand/osm/edit/Way.java +++ b/OsmAnd-java/src/net/osmand/osm/edit/Way.java @@ -178,7 +178,7 @@ public class Way extends Entity { if(nodes == null){ return null; } - return OsmMapUtils.getWeightCenterForNodes(nodes); + return OsmMapUtils.getWeightCenterForWay(this); } diff --git a/OsmAnd-java/src/net/osmand/util/MapAlgorithms.java b/OsmAnd-java/src/net/osmand/util/MapAlgorithms.java index 4de1f17758..44c019b217 100644 --- a/OsmAnd-java/src/net/osmand/util/MapAlgorithms.java +++ b/OsmAnd-java/src/net/osmand/util/MapAlgorithms.java @@ -1,7 +1,12 @@ package net.osmand.util; +import java.util.Collection; +import java.util.List; + import gnu.trove.list.TLongList; import net.osmand.data.LatLon; +import net.osmand.osm.edit.Node; +import net.osmand.osm.edit.OsmMapUtils; public class MapAlgorithms { @@ -285,4 +290,44 @@ public class MapAlgorithms { } return true; } + + public static boolean containsPoint(Collection polyNodes, double latitude, double longitude){ + return countIntersections(polyNodes, latitude, longitude) % 2 == 1; + } + + /** + * count the intersections when going from lat, lon to outside the ring + * @param polyNodes2 + */ + private static int countIntersections(Collection polyNodes, double latitude, double longitude) { + int intersections = 0; + if (polyNodes.size() == 0) return 0; + Node prev = null; + Node first = null; + Node last = null; + for(Node n : polyNodes) { + if(prev == null) { + prev = n; + first = prev; + continue; + } + if(n == null) { + continue; + } + last = n; + if (OsmMapUtils.ray_intersect_lon(prev, + n, latitude, longitude) != -360.0d) { + intersections++; + } + prev = n; + } + // special handling, also count first and last, might not be closed, but + // we want this! + if (OsmMapUtils.ray_intersect_lon(first, + last, latitude, longitude) != -360.0d) { + intersections++; + } + return intersections; + } + } \ No newline at end of file