From aa7bb37a99acf980de232fe5d6cbe70ee44a9cf2 Mon Sep 17 00:00:00 2001 From: Arndt Brenschede Date: Tue, 30 Jul 2019 11:36:45 +0200 Subject: [PATCH] Douglas-Peucker transfer-node elimination on pre-processor level --- .../main/java/btools/mapcreator/DPFilter.java | 66 +++++++++++++++++++ .../main/java/btools/mapcreator/OsmNodeP.java | 34 +++++----- 2 files changed, 81 insertions(+), 19 deletions(-) create mode 100644 brouter-map-creator/src/main/java/btools/mapcreator/DPFilter.java diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/DPFilter.java b/brouter-map-creator/src/main/java/btools/mapcreator/DPFilter.java new file mode 100644 index 0000000..b23d50b --- /dev/null +++ b/brouter-map-creator/src/main/java/btools/mapcreator/DPFilter.java @@ -0,0 +1,66 @@ +/** + * Filter to eliminate some transfer nodes (Douglas-Peucker algorithm) + * + * @author ab + */ +package btools.mapcreator; + +import java.util.ArrayList; + +import btools.util.CheapRuler; + +public class DPFilter +{ + private static double dp_sql_threshold = 0.4 * 0.4; + + /* + * for each node (except first+last), eventually set the DP_SURVIVOR_BIT + */ + public static void doDPFilter( ArrayList nodes, int first, int last ) + { + double maxSqDist = -1.; + int index = -1; + OsmNodeP p1 = nodes.get( first ); + OsmNodeP p2 = nodes.get( last ); + + double[] lonlat2m = CheapRuler.getLonLatToMeterScales( (p1.ilat+p2.ilat) >> 1 ); + double dlon2m = lonlat2m[0]; + double dlat2m = lonlat2m[1]; + double dx = (p2.ilon - p1.ilon) * dlon2m; + double dy = (p2.ilat - p1.ilat) * dlat2m; + double d2 = dx * dx + dy * dy; + for ( int i = first + 1; i < last; i++ ) + { + OsmNodeP p = nodes.get( i ); + double t = 0.; + if ( d2 != 0f ) + { + t = ( ( p.ilon - p1.ilon ) * dlon2m * dx + ( p.ilat - p1.ilat ) * dlat2m * dy ) / d2; + t = t > 1. ? 1. : ( t < 0. ? 0. : t ); + } + double dx2 = (p.ilon - ( p1.ilon + t*( p2.ilon - p1.ilon ) ) ) * dlon2m; + double dy2 = (p.ilat - ( p1.ilat + t*( p2.ilat - p1.ilat ) ) ) * dlat2m; + double sqDist = dx2 * dx2 + dy2 * dy2; + if ( sqDist > maxSqDist ) + { + index = i; + maxSqDist = sqDist; + } + } + if ( index >= 0 ) + { + if ( index - first > 1 ) + { + doDPFilter( nodes, first, index ); + } + if ( maxSqDist >= dp_sql_threshold ) + { + nodes.get( index ).bits |= OsmNodeP.DP_SURVIVOR_BIT; + } + if ( last - index > 1 ) + { + doDPFilter( nodes, index, last ); + } + } + } +} 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 dde2704..dd70c65 100644 --- a/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java +++ b/brouter-map-creator/src/main/java/btools/mapcreator/OsmNodeP.java @@ -35,6 +35,7 @@ public class OsmNodeP extends OsmLinkP public final static int TRAFFIC_BIT = 8; public final static int ANY_WAY_BIT = 16; public final static int MULTI_WAY_BIT = 32; + public final static int DP_SURVIVOR_BIT = 64; public byte bits = 0; @@ -200,10 +201,15 @@ public class OsmNodeP extends OsmLinkP OsmNodeP origin = this; OsmNodeP target = null; + ArrayList linkNodes = new ArrayList(); + linkNodes.add( this ); + // first pass just to see if that link is consistent while (link != null) { target = link.getTarget( origin ); + linkNodes.add( target ); + if ( !target.isTransferNode() ) { break; @@ -244,30 +250,20 @@ public class OsmNodeP extends OsmLinkP mc.writeVarLengthSigned( target.ilon - ilon ); mc.writeVarLengthSigned( target.ilat - ilat ); mc.writeModeAndDesc( isReverse, link0.descriptionBitmap ); - if ( !isReverse ) // write geometry for forward links only + if ( !isReverse && linkNodes.size() > 2 ) // write geometry for forward links only { - link = link0; + DPFilter.doDPFilter( linkNodes, 0, linkNodes.size()-1 ); origin = this; - while (link != null) + for( int i=1; i