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 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<OsmNodeP> linkNodes = new ArrayList<OsmNodeP>();
|
||||
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,32 +250,22 @@ 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<linkNodes.size()-1; i++ )
|
||||
{
|
||||
OsmNodeP tranferNode = link.getTarget( origin );
|
||||
if ( !tranferNode.isTransferNode() )
|
||||
OsmNodeP tranferNode = linkNodes.get(i);
|
||||
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() );
|
||||
|
||||
// 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 );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue