Fix issue 406. Incorrect boundary algorithm and additional check of indexing multipolygon

This commit is contained in:
Victor Shcherb 2011-05-03 00:57:02 +02:00
parent c3f2194237
commit 2b6dd0e830
3 changed files with 44 additions and 29 deletions

View file

@ -15,7 +15,7 @@ public class Boundary {
private String adminLevel; private String adminLevel;
// ? ready rings // not necessary ready rings
private List<Way> outerWays = new ArrayList<Way>(); private List<Way> outerWays = new ArrayList<Way>();
private List<Way> innerWays = new ArrayList<Way>(); private List<Way> innerWays = new ArrayList<Way>();
@ -44,6 +44,7 @@ public class Boundary {
return intersections % 2 == 1; return intersections % 2 == 1;
} }
// Try to intersect with ray from left to right
private boolean ray_intersect(Node node, Node node2, double latitude, double longitude) { private boolean ray_intersect(Node node, Node node2, double latitude, double longitude) {
// a node below // a node below
Node a = node.getLatitude() < node2.getLatitude() ? node : node2; Node a = node.getLatitude() < node2.getLatitude() ? node : node2;
@ -60,19 +61,14 @@ public class Boundary {
} else if(longitude < Math.min(a.getLongitude(), b.getLongitude())){ } else if(longitude < Math.min(a.getLongitude(), b.getLongitude())){
return false; return false;
} else { } else {
double mR; if(a.getLongitude() == b.getLongitude()) {
if(a.getLongitude() != b.getLongitude()){ // the node on the boundary !!!
mR = (b.getLatitude() - a.getLatitude()) / (b.getLongitude() - a.getLongitude()); return true;
} else {
mR = Double.POSITIVE_INFINITY;
} }
double mB; // that tested on all cases (left/right)
if(a.getLongitude() != b.getLongitude()){ double mR = (b.getLatitude() - a.getLatitude()) / (b.getLongitude() - a.getLongitude());
mB = (latitude - a.getLatitude()) / (longitude - a.getLongitude()); double mB = (latitude - a.getLatitude()) / (longitude - a.getLongitude());
} else { if(mB <= mR){
mB = Double.POSITIVE_INFINITY;
}
if(mB >= mR){
return true; return true;
} else { } else {
return false; return false;
@ -81,19 +77,6 @@ public class Boundary {
} }
} }
public void initializeWay(Way w) {
for (int i = 0; i < outerWays.size(); i++) {
if (outerWays.get(i).getId() == w.getId()) {
outerWays.set(i, w);
}
}
for (int i = 0; i < innerWays.size(); i++) {
if (innerWays.get(i).getId() == w.getId()) {
innerWays.set(i, w);
}
}
}
public LatLon getCenterPoint(){ public LatLon getCenterPoint(){
List<Node> points = new ArrayList<Node>(); List<Node> points = new ArrayList<Node>();
for(Way w : outerWays){ for(Way w : outerWays){

View file

@ -596,10 +596,10 @@ public class IndexCreator {
creator.recreateOnlyBinaryFile = false; creator.recreateOnlyBinaryFile = false;
creator.deleteDatabaseIndexes = true; creator.deleteDatabaseIndexes = true;
// creator.generateIndexes(new File("/home/victor/projects/OsmAnd/download/384/spain.osm.pbf"), creator.generateIndexes(new File("/home/victor/projects/OsmAnd/download/406/map.osm"),
// new ConsoleProgressImplementation(1), null, MapZooms.getDefault(), null);
creator.generateIndexes(new File("/home/victor/projects/OsmAnd/data/osm-maps/minsk_around.osm"),
new ConsoleProgressImplementation(1), null, MapZooms.getDefault(), null); new ConsoleProgressImplementation(1), null, MapZooms.getDefault(), null);
// creator.generateIndexes(new File("/home/victor/projects/OsmAnd/data/osm-maps/minsk_around.osm"),
// new ConsoleProgressImplementation(1), null, MapZooms.getDefault(), null);

View file

@ -12,6 +12,7 @@ import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
@ -21,6 +22,7 @@ import java.util.Set;
import net.osmand.Algoritms; import net.osmand.Algoritms;
import net.osmand.IProgress; import net.osmand.IProgress;
import net.osmand.binary.BinaryMapIndexWriter; import net.osmand.binary.BinaryMapIndexWriter;
import net.osmand.data.Boundary;
import net.osmand.data.MapAlgorithms; import net.osmand.data.MapAlgorithms;
import net.osmand.osm.Entity; import net.osmand.osm.Entity;
import net.osmand.osm.LatLon; import net.osmand.osm.LatLon;
@ -131,6 +133,13 @@ public class IndexVectorMapCreator extends AbstractIndexPartCreator {
} }
} }
Node nodeOut = checkOuterWaysEncloseInnerWays(completedRings, entities);
if(nodeOut != null){
log.warn("Map bug: Multipoligon contains 'inner' way point outside of 'outer' border.\n" + //$NON-NLS-1$
"Multipolygon id : " + e.getId() + ", inner node out id : " + nodeOut.getId()); //$NON-NLS-1$
return;
}
for (List<Way> l : completedRings) { for (List<Way> l : completedRings) {
boolean innerType = "inner".equals(entities.get(l.get(0))); //$NON-NLS-1$ boolean innerType = "inner".equals(entities.get(l.get(0))); //$NON-NLS-1$
boolean clockwise = MapSwingAlgorithms.isClockwiseWay(l); boolean clockwise = MapSwingAlgorithms.isClockwiseWay(l);
@ -157,6 +166,29 @@ public class IndexVectorMapCreator extends AbstractIndexPartCreator {
private Node checkOuterWaysEncloseInnerWays(List<List<Way>> completedRings, Map<Entity, String> entities) {
List<Way> innerWays = new ArrayList<Way>();
Boundary outerBoundary = new Boundary();
for(List<Way> ring : completedRings){
boolean innerType = "inner".equals(entities.get(ring.get(0))); //$NON-NLS-1$
if(!innerType){
outerBoundary.getOuterWays().addAll(ring);
} else {
innerWays.addAll(ring);
}
}
for(Way innerWay : innerWays){
for(Node node : innerWay.getNodes()){
if(!outerBoundary.containsPoint(node.getLatitude(), node.getLongitude())){
return node;
}
}
}
return null;
}
private void indexHighwayRestrictions(Entity e, OsmDbAccessorContext ctx) throws SQLException { private void indexHighwayRestrictions(Entity e, OsmDbAccessorContext ctx) throws SQLException {
if (e instanceof Relation && "restriction".equals(e.getTag(OSMTagKey.TYPE))) { //$NON-NLS-1$ if (e instanceof Relation && "restriction".equals(e.getTag(OSMTagKey.TYPE))) { //$NON-NLS-1$
String val = e.getTag("restriction"); //$NON-NLS-1$ String val = e.getTag("restriction"); //$NON-NLS-1$