From 771770af220f8c09c16d9a53513e6397c457aafc Mon Sep 17 00:00:00 2001 From: Arndt Brenschede Date: Sat, 15 Jan 2022 10:05:06 +0100 Subject: [PATCH] added bad-TRs analysis to pre-processor --- .../java/btools/mapcreator/OsmCutter.java | 57 ++++----- .../main/java/btools/mapcreator/OsmNodeP.java | 4 +- .../btools/mapcreator/RestrictionData.java | 113 +++++++++++++++++- .../java/btools/mapcreator/WayLinker.java | 28 ++++- misc/pbfparser/OsmParser.java | 7 +- 5 files changed, 163 insertions(+), 46 deletions(-) diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/OsmCutter.java b/brouter-map-creator/src/main/java/btools/mapcreator/OsmCutter.java index 749950c..ab5b050 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/OsmCutter.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/OsmCutter.java @@ -260,30 +260,11 @@ public class OsmCutter extends MapCreatorBase @Override public void nextRestriction( RelationData r, long fromWid, long toWid, long viaNid ) throws Exception { - if ( fromWid == 0 || toWid == 0 || viaNid == 0 ) - { - return; - } String type = r.getTag( "type" ); if ( type == null || !"restriction".equals( type ) ) { return; } - String restriction = r.getTag( "restriction" ); - if ( restriction == null ) - { - return; - } - boolean isPositive = true; - if ( restriction.startsWith( "no_" ) ) - { - isPositive = false; - } - else if ( !restriction.startsWith( "only_" ) ) - { - return; - } - short exceptions = 0; String except = r.getTag( "except" ); if ( except != null ) @@ -296,23 +277,31 @@ public class OsmCutter extends MapCreatorBase exceptions |= toBit( "hgv" , 4, except ); } - // System.out.println( "restriction id = " + r.rid + " isPositive=" + isPositive + " fromWid = " + fromWid + " toWid = " + toWid+ " viaNid = " + viaNid ); - RestrictionData res = new RestrictionData(); - res.isPositive = isPositive; - res.exceptions = exceptions; - res.fromWid = fromWid; - res.toWid = toWid; - res.viaNid = viaNid; - - if ( restrictionsDos != null ) + for( String restrictionKey : r.getTagsOrNull().keySet() ) { - res.writeTo( restrictionsDos ); - } - if ( restrictionCutter != null ) - { - restrictionCutter.nextRestriction( res ); - } + if ( !( restrictionKey.equals( "restriction" ) || restrictionKey.startsWith( "restriction:" ) ) ) + { + continue; + } + String restriction = r.getTag( restrictionKey ); + + RestrictionData res = new RestrictionData(); + res.restrictionKey = restrictionKey; + res.restriction = restriction; + res.exceptions = exceptions; + res.fromWid = fromWid; + res.toWid = toWid; + res.viaNid = viaNid; + if ( restrictionsDos != null ) + { + res.writeTo( restrictionsDos ); + } + if ( restrictionCutter != null ) + { + restrictionCutter.nextRestriction( res ); + } + } } private static short toBit( String tag, int bitpos, String s ) diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java b/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java index 936072f..92b1b54 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java @@ -175,11 +175,11 @@ public class OsmNodeP extends OsmLinkP RestrictionData r = getFirstRestriction(); while( r != null ) { - if ( r.fromLon != 0 && r.toLon != 0 ) + if ( r.isValid() && r.fromLon != 0 && r.toLon != 0 ) { mc.writeBoolean( true ); // restriction follows mc.writeShort( r.exceptions ); - mc.writeBoolean( r.isPositive ); + mc.writeBoolean( r.isPositive() ); mc.writeInt( r.fromLon ); mc.writeInt( r.fromLat ); mc.writeInt( r.toLon ); diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/RestrictionData.java b/brouter-map-creator/src/main/java/btools/mapcreator/RestrictionData.java index 72ac0d4..50f3130 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/RestrictionData.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/RestrictionData.java @@ -1,9 +1,14 @@ package btools.mapcreator; +import java.io.BufferedWriter; import java.io.DataInputStream; import java.io.DataOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.util.HashMap; +import java.util.TreeSet; -import btools.util.LongList; +import btools.util.CheapAngleMeter; /** * Container for a turn restriction @@ -12,26 +17,125 @@ import btools.util.LongList; */ public class RestrictionData extends MapCreatorBase { - public boolean isPositive; + public String restrictionKey; + public String restriction; public short exceptions; public long fromWid; public long toWid; public long viaNid; public RestrictionData next; + public int viaLon; + public int viaLat; + public int fromLon; public int fromLat; public int toLon; public int toLat; + + public boolean badWayMatch; + + private static HashMap names = new HashMap<>(); + private static TreeSet badTRs = new TreeSet<>(); public RestrictionData() { } + + public boolean isPositive() + { + return restriction.startsWith( "only_" ); + } + + public boolean isValid() + { + boolean valid = fromLon != 0 && toLon != 0 && ( restriction.startsWith( "only_" ) || restriction.startsWith( "no_" ) ); + if ( (!valid) || badWayMatch || !(checkGeometry()) ) + { + synchronized( badTRs ) + { + badTRs.add( ( (long) viaLon ) << 32 | viaLat ); + } + } + return valid && "restriction".equals( restrictionKey ); + } + + private boolean checkGeometry() + { + double a = (new CheapAngleMeter()).calcAngle( fromLon, fromLat, viaLon, viaLat, toLon, toLat ); + String t; + if ( restriction.startsWith( "only_" ) ) + { + t = restriction.substring( "only_".length() ); + } + else if ( restriction.startsWith( "no_" ) ) + { + t = restriction.substring( "no_".length() ); + } + else throw new RuntimeException( "ups" ); + + if ( restrictionKey.endsWith( ":conditional" ) ) + { + int idx = t.indexOf( '@' ); + if ( idx >= 0 ) + { + t = t.substring(0, idx ).trim(); + } + } + + if ( "left_turn".equals( t ) ) + { + return a < -5. && a > -175.; + } + if ( "right_turn".equals( t ) ) + { + return a > 5. && a < 175.; + } + if ( "straight_on".equals( t ) ) + { + return a > -85. && a < 85.; + } + if ( "u_turn".equals( t ) ) + { + return a < - 95. || a > 95.; + } + return "entry".equals( t ) || "exit".equals( t ); + } + + private static String unifyName( String name ) + { + synchronized( names ) + { + String n = names.get(name); + if ( n == null ) + { + names.put( name, name ); + n = name; + } + return n; + } + } + + public static void dumpBadTRs() + { + try( BufferedWriter bw = new BufferedWriter( new FileWriter( "badtrs.txt" ) ) ) + { + for( Long id : badTRs ) + { + bw.write( "" + id + " 26\n" ); + } + } + catch( IOException ioe ) + { + throw new RuntimeException( ioe ); + } + } public RestrictionData( DataInputStream di ) throws Exception { - isPositive = di.readBoolean(); + restrictionKey = unifyName( di.readUTF() ); + restriction = unifyName( di.readUTF() ); exceptions = di.readShort(); fromWid = readId( di ); toWid = readId( di ); @@ -40,7 +144,8 @@ public class RestrictionData extends MapCreatorBase public void writeTo( DataOutputStream dos ) throws Exception { - dos.writeBoolean( isPositive ); + dos.writeUTF( restrictionKey ); + dos.writeUTF( restriction ); dos.writeShort( exceptions ); writeId( dos, fromWid ); writeId( dos, toWid ); diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java b/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java index 99e127c..ffb491d 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/WayLinker.java @@ -138,6 +138,9 @@ public class WayLinker extends MapCreatorBase implements Runnable new WayLinker().process( new File( args[0] ), new File( args[1] ), new File( args[2] ), new File( args[3] ), new File( args[4] ), new File( args[5] ), new File( args[6] ), args[7] ); + + System.out.println( "dumping bad TRs" ); + RestrictionData.dumpBadTRs(); } public void process( File nodeTilesIn, File wayTilesIn, File borderFileIn, File restrictionsFileIn, File lookupFile, File profileFile, File dataTilesOut, @@ -287,6 +290,8 @@ public class WayLinker extends MapCreatorBase implements Runnable nodesMap.put( res.viaNid, n ); } OsmNodePT nt = (OsmNodePT) n; + res.viaLon = nt.ilon; + res.viaLat = nt.ilat; res.next = nt.firstRestriction; nt.firstRestriction = res; ntr++; @@ -351,36 +356,49 @@ public class WayLinker extends MapCreatorBase implements Runnable // the leg according to the mapped direction private void checkRestriction( OsmNodeP n1, OsmNodeP n2, WayData w ) { - checkRestriction( n1, n2, w.wid, true ); - checkRestriction( n2, n1, w.wid, false ); + checkRestriction( n1, n2, w, true ); + checkRestriction( n2, n1, w, false ); } - private void checkRestriction( OsmNodeP n1, OsmNodeP n2, long wid, boolean checkFrom ) + private void checkRestriction( OsmNodeP n1, OsmNodeP n2, WayData w, boolean checkFrom ) { RestrictionData r = n2.getFirstRestriction(); while ( r != null ) { - if ( r.fromWid == wid ) + if ( r.fromWid == w.wid ) { if ( r.fromLon == 0 || checkFrom ) { r.fromLon = n1.ilon; r.fromLat = n1.ilat; n1.bits |= OsmNodeP.DP_SURVIVOR_BIT; + if ( !isEndNode( n2, w ) ) + { + r.badWayMatch = true; + } } } - if ( r.toWid == wid ) + if ( r.toWid == w.wid ) { if ( r.toLon == 0 || !checkFrom ) { r.toLon = n1.ilon; r.toLat = n1.ilat; n1.bits |= OsmNodeP.DP_SURVIVOR_BIT; + if ( !isEndNode( n2, w ) ) + { + r.badWayMatch = true; + } } } r = r.next; } } + + private boolean isEndNode( OsmNodeP n, WayData w ) + { + return n == nodesMap.get( w.nodes.get( 0 ) ) || n == nodesMap.get( w.nodes.get( w.nodes.size() - 1 ) ); + } @Override public void nextWay( WayData way ) throws Exception diff --git a/misc/pbfparser/OsmParser.java b/misc/pbfparser/OsmParser.java index 58039b8..9c5ee42 100644 --- a/misc/pbfparser/OsmParser.java +++ b/misc/pbfparser/OsmParser.java @@ -140,6 +140,11 @@ public class OsmParser extends MapCreatorBase rListener.nextRelation( r ); if ( fromWid == null || toWid == null || viaNid == null || viaNid.size() != 1 ) { + // dummy-TR for each viaNid + for( int vi = 0; vi < ( viaNid == null ? 0 : viaNid.size() ); vi++ ) + { + rListener.nextRestriction( r, 0L, 0L, viaNid.get( vi ) ); + } return; } for( int fi = 0; fi < fromWid.size(); fi++ ) @@ -152,7 +157,7 @@ public class OsmParser extends MapCreatorBase } catch( Exception e ) { - throw new RuntimeException( "error writing relation: " + e ); + throw new RuntimeException( "error writing relation", e ); } }