v1 suffered from the problem that ways were connected over the bbox
edge. Now connections with minimum distance are preferred no matter if a
way is closed to a polygon or if a way is joined to another unclosed way.
WanMil
The patch connects unclosed ways out of the bounding box. In some
situation this fixes a problem with multipolygons that are larger that
the tile.
WanMil
Index: src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java
(revision 1952)
+++ src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java
(working copy)
@@ -324,11 +324,8 @@
* a list of ways
*/
private void closeWays(ArrayList<JoinedWay> wayList) {
- // this is a VERY simple algorithm to close the ways
- // need to be improved
-
for (JoinedWay way : wayList) {
- if (way.isClosed() || way.getPoints().size() <= 3) {
+ if (way.isClosed() || way.getPoints().size() < 3) {
continue;
}
Coord p1 = way.getPoints().get(0);
@@ -356,38 +353,6 @@
"are both outside the
bbox. Closing it directly.");
continue;
}
-
-
- // Check if the way can be closed with one
additional point
- // outside the bounding box.
- // The additional point is combination of the
coords of both endpoints.
- // It works if the lines from the endpoints to
the additional point does
- // not cut the bounding box.
- // This can be removed when the splitter
guarantees to provide logical complete
- // multi-polygons.
- Coord edgePoint1 = new Coord(p1.getLatitude(),
p2
- .getLongitude());
- Coord edgePoint2 = new Coord(p2.getLatitude(),
p1
- .getLongitude());
-
- if (lineCutsBbox(p1, edgePoint1) == false
- && lineCutsBbox(edgePoint1, p2)
== false) {
- way.addPoint(edgePoint1);
- way.closeWayArtificially();
- log.info("Endpoints of way", way,
- "are both outside the
bbox. Add point", edgePoint1,
- "and close it.");
- continue;
- }
- if (lineCutsBbox(p1, edgePoint2) == false
- && lineCutsBbox(edgePoint2, p2)
== false) {
- way.addPoint(edgePoint2);
- way.closeWayArtificially();
- log.info("Endpoints of way", way,
- "are both outside the
bbox. Add point", edgePoint2,
- "and close it.");
- continue;
- }
}
Line2D closingLine = new
Line2D.Float(p1.getLongitude(), p1
@@ -424,6 +389,129 @@
}
}
}
+
+ private static class ConnectionData {
+ public Coord c1;
+ public Coord c2;
+ public JoinedWay w1;
+ public JoinedWay w2;
+ // sometimes the connection of both points cannot be done
directly but with an intermediate point
+ public Coord imC;
+ public double distance;
+ }
+
+ private boolean connectUnclosedWays(List<JoinedWay> allWays) {
+ List<JoinedWay> unclosed = new ArrayList<JoinedWay>();
+
+ for (JoinedWay w : allWays) {
+ if (w.isClosed() == false) {
+ unclosed.add(w);
+ }
+ }
+ // try to connect ways lying outside or on the bbox
+ if (unclosed.size() >= 2) {
+ log.debug("Checking",unclosed.size(),"unclosed ways for
connections outside the bbox");
+ Map<Coord, JoinedWay> outOfBboxPoints = new
HashMap<Coord, JoinedWay>();
+
+ // check all ways for endpoints outside or on the bbox
+ for (JoinedWay w : unclosed) {
+ Coord c1 = w.getPoints().get(0);
+ if (bbox.insideBoundary(c1)==false) {
+ log.debug("Point",c1,"of
way",w.getId(),"outside bbox");
+ outOfBboxPoints.put(c1, w);
+ }
+
+ Coord c2 =
w.getPoints().get(w.getPoints().size()-1);
+ if (bbox.insideBoundary(c2)==false) {
+ log.debug("Point",c2,"of
way",w.getId(),"outside bbox");
+ outOfBboxPoints.put(c2, w);
+ }
+ }
+
+ if (outOfBboxPoints.size() < 2) {
+ log.debug(outOfBboxPoints.size(),"point outside
the bbox. No connection possible.");
+ return false;
+ }
+
+ List<ConnectionData> coordPairs = new
ArrayList<ConnectionData>();
+ ArrayList<Coord> coords = new
ArrayList<Coord>(outOfBboxPoints.keySet());
+ for (int i = 0; i < coords.size(); i++) {
+ for (int j = i + 1; j < coords.size(); j++) {
+ ConnectionData cd = new
ConnectionData();
+ cd.c1 = coords.get(i);
+ cd.c2 = coords.get(j);
+ cd.w1 = outOfBboxPoints.get(cd.c1);
+ cd.w2 = outOfBboxPoints.get(cd.c2);
+
+ if (lineCutsBbox(cd.c1, cd.c2 )) {
+ // Check if the way can be
closed with one additional point
+ // outside the bounding box.
+ // The additional point is
combination of the coords of both endpoints.
+ // It works if the lines from
the endpoints to the additional point does
+ // not cut the bounding box.
+ // This can be removed when the
splitter guarantees to provide logical complete
+ // multi-polygons.
+ Coord edgePoint1 = new
Coord(cd.c1.getLatitude(), cd.c2
+
.getLongitude());
+ Coord edgePoint2 = new
Coord(cd.c2.getLatitude(), cd.c1
+
.getLongitude());
+
+ if (lineCutsBbox(cd.c1,
edgePoint1) == false
+ &&
lineCutsBbox(edgePoint1, cd.c2) == false) {
+ cd.imC = edgePoint1;
+ } else if (lineCutsBbox(cd.c1,
edgePoint2) == false
+ &&
lineCutsBbox(edgePoint2, cd.c2) == false) {
+ cd.imC = edgePoint1;
+ } else {
+ // both endpoints are
on opposite sides of the bounding box
+ // automatically
closing such points would create wrong polygons in most cases
+ continue;
+ }
+ cd.distance =
cd.c1.distance(cd.imC) + cd.imC.distance(cd.c2);
+ } else {
+ cd.distance =
cd.c1.distance(cd.c2);
+ }
+ coordPairs.add(cd);
+ }
+ }
+
+ if (coordPairs.isEmpty()) {
+ log.debug("All potential connections cross the
bbox. No connection possible.");
+ return false;
+ } else {
+ // retrieve the connection with the minimum
distance
+ ConnectionData minCon =
Collections.min(coordPairs,
+ new
Comparator<ConnectionData>() {
+ public int
compare(ConnectionData o1,
+
ConnectionData o2) {
+ return
Double.compare(o1.distance, o2.distance);
+ }
+ });
+
+ if (minCon.w1 == minCon.w2) {
+ log.debug("Close a gap in
way",minCon.w1);
+ if (minCon.imC != null)
+
minCon.w1.getPoints().add(minCon.imC);
+ minCon.w1.closeWayArtificially();
+ } else {
+ log.debug("Connect", minCon.w1, "with",
minCon.w2);
+
+ if
(minCon.w1.getPoints().get(0).equals(minCon.c1)) {
+
Collections.reverse(minCon.w1.getPoints());
+ }
+ if
(minCon.w2.getPoints().get(0).equals(minCon.c2) == false) {
+
Collections.reverse(minCon.w2.getPoints());
+ }
+
+
minCon.w1.getPoints().addAll(minCon.w2.getPoints());
+ minCon.w1.addWay(minCon.w2);
+ allWays.remove(minCon.w2);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
/**
* Removes all ways non closed ways from the given list (
@@ -619,6 +707,10 @@
outerTags = new HashMap<String,String>();
closeWays(polygons);
+
+ while (connectUnclosedWays(polygons)) {
+ closeWays(polygons);
+ }
removeUnclosedWays(polygons);
// now only closed ways are left => polygons only
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev