Douglas-Peucker transfer-node elimination on pre-processor level
This commit is contained in:
parent
0a6ead24a1
commit
aa7bb37a99
2 changed files with 81 additions and 19 deletions
|
@ -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<OsmNodeP> 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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,6 +35,7 @@ public class OsmNodeP extends OsmLinkP
|
||||||
public final static int TRAFFIC_BIT = 8;
|
public final static int TRAFFIC_BIT = 8;
|
||||||
public final static int ANY_WAY_BIT = 16;
|
public final static int ANY_WAY_BIT = 16;
|
||||||
public final static int MULTI_WAY_BIT = 32;
|
public final static int MULTI_WAY_BIT = 32;
|
||||||
|
public final static int DP_SURVIVOR_BIT = 64;
|
||||||
|
|
||||||
public byte bits = 0;
|
public byte bits = 0;
|
||||||
|
|
||||||
|
@ -200,10 +201,15 @@ public class OsmNodeP extends OsmLinkP
|
||||||
OsmNodeP origin = this;
|
OsmNodeP origin = this;
|
||||||
OsmNodeP target = null;
|
OsmNodeP target = null;
|
||||||
|
|
||||||
|
ArrayList<OsmNodeP> linkNodes = new ArrayList<OsmNodeP>();
|
||||||
|
linkNodes.add( this );
|
||||||
|
|
||||||
// first pass just to see if that link is consistent
|
// first pass just to see if that link is consistent
|
||||||
while (link != null)
|
while (link != null)
|
||||||
{
|
{
|
||||||
target = link.getTarget( origin );
|
target = link.getTarget( origin );
|
||||||
|
linkNodes.add( target );
|
||||||
|
|
||||||
if ( !target.isTransferNode() )
|
if ( !target.isTransferNode() )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
@ -244,30 +250,20 @@ public class OsmNodeP extends OsmLinkP
|
||||||
mc.writeVarLengthSigned( target.ilon - ilon );
|
mc.writeVarLengthSigned( target.ilon - ilon );
|
||||||
mc.writeVarLengthSigned( target.ilat - ilat );
|
mc.writeVarLengthSigned( target.ilat - ilat );
|
||||||
mc.writeModeAndDesc( isReverse, link0.descriptionBitmap );
|
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;
|
origin = this;
|
||||||
while (link != null)
|
for( int i=1; i<linkNodes.size()-1; i++ )
|
||||||
{
|
{
|
||||||
OsmNodeP tranferNode = link.getTarget( origin );
|
OsmNodeP tranferNode = linkNodes.get(i);
|
||||||
if ( !tranferNode.isTransferNode() )
|
if ( ( tranferNode.bits & OsmNodeP.DP_SURVIVOR_BIT ) != 0 )
|
||||||
{
|
{
|
||||||
break;
|
mc.writeVarLengthSigned( tranferNode.ilon - origin.ilon );
|
||||||
|
mc.writeVarLengthSigned( tranferNode.ilat - origin.ilat );
|
||||||
|
mc.writeVarLengthSigned( tranferNode.getSElev() - origin.getSElev() );
|
||||||
|
origin = tranferNode;
|
||||||
}
|
}
|
||||||
mc.writeVarLengthSigned( tranferNode.ilon - origin.ilon );
|
|
||||||
mc.writeVarLengthSigned( tranferNode.ilat - origin.ilat );
|
|
||||||
mc.writeVarLengthSigned( tranferNode.getSElev() - origin.getSElev() );
|
|
||||||
|
|
||||||
// next link is the one (of two), does does'nt point back
|
|
||||||
for ( link = tranferNode.getFirstLink(); link != null; link = link.getNext( tranferNode ) )
|
|
||||||
{
|
|
||||||
if ( link.getTarget( tranferNode ) != origin )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ( link == null )
|
|
||||||
throw new RuntimeException( "follow-up link not found for transfer-node!" );
|
|
||||||
origin = tranferNode;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mc.injectSize( sizeoffset );
|
mc.injectSize( sizeoffset );
|
||||||
|
|
Loading…
Reference in a new issue