traffic simulation delta supression
This commit is contained in:
parent
e574045548
commit
010383e7e7
3 changed files with 135 additions and 28 deletions
|
@ -102,12 +102,12 @@ public class OsmNodeP extends OsmLinkP
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeNodeData( MicroCache mc ) throws IOException
|
public void writeNodeData( MicroCache mc, OsmTrafficMap trafficMap ) throws IOException
|
||||||
{
|
{
|
||||||
boolean valid = true;
|
boolean valid = true;
|
||||||
if ( mc instanceof MicroCache2 )
|
if ( mc instanceof MicroCache2 )
|
||||||
{
|
{
|
||||||
valid = writeNodeData2( (MicroCache2) mc );
|
valid = writeNodeData2( (MicroCache2) mc, trafficMap );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw new IllegalArgumentException( "unknown cache version: " + mc.getClass() );
|
throw new IllegalArgumentException( "unknown cache version: " + mc.getClass() );
|
||||||
|
@ -167,7 +167,7 @@ public class OsmNodeP extends OsmLinkP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean writeNodeData2( MicroCache2 mc ) throws IOException
|
public boolean writeNodeData2( MicroCache2 mc, OsmTrafficMap trafficMap ) throws IOException
|
||||||
{
|
{
|
||||||
boolean hasLinks = false;
|
boolean hasLinks = false;
|
||||||
|
|
||||||
|
@ -245,11 +245,18 @@ public class OsmNodeP extends OsmLinkP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add traffic simulation, if present
|
||||||
|
byte[] description = link0.descriptionBitmap;
|
||||||
|
if ( trafficMap != null )
|
||||||
|
{
|
||||||
|
description = trafficMap.addTrafficClass( linkNodes, description );
|
||||||
|
}
|
||||||
|
|
||||||
// write link data
|
// write link data
|
||||||
int sizeoffset = mc.writeSizePlaceHolder();
|
int sizeoffset = mc.writeSizePlaceHolder();
|
||||||
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, description );
|
||||||
if ( !isReverse && linkNodes.size() > 2 ) // write geometry for forward links only
|
if ( !isReverse && linkNodes.size() > 2 ) // write geometry for forward links only
|
||||||
{
|
{
|
||||||
DPFilter.doDPFilter( linkNodes );
|
DPFilter.doDPFilter( linkNodes );
|
||||||
|
|
|
@ -6,11 +6,18 @@
|
||||||
package btools.mapcreator;
|
package btools.mapcreator;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import btools.expressions.BExpressionContextWay;
|
||||||
|
import btools.util.CheapRuler;
|
||||||
import btools.util.CompactLongMap;
|
import btools.util.CompactLongMap;
|
||||||
import btools.util.FrozenLongMap;
|
import btools.util.FrozenLongMap;
|
||||||
|
|
||||||
|
@ -22,6 +29,21 @@ public class OsmTrafficMap
|
||||||
int maxLon;
|
int maxLon;
|
||||||
int maxLat;
|
int maxLat;
|
||||||
|
|
||||||
|
private BExpressionContextWay expctxWay;
|
||||||
|
|
||||||
|
private OsmTrafficMap oldTrafficClasses;
|
||||||
|
private DataOutputStream newTrafficDos;
|
||||||
|
private File oldTrafficFile;
|
||||||
|
private File newTrafficFile;
|
||||||
|
|
||||||
|
int totalChanges = 0;
|
||||||
|
int supressedChanges = 0;
|
||||||
|
|
||||||
|
public OsmTrafficMap( BExpressionContextWay expctxWay )
|
||||||
|
{
|
||||||
|
this.expctxWay = expctxWay;
|
||||||
|
}
|
||||||
|
|
||||||
public static class OsmTrafficElement
|
public static class OsmTrafficElement
|
||||||
{
|
{
|
||||||
public long node2;
|
public long node2;
|
||||||
|
@ -31,7 +53,36 @@ public class OsmTrafficMap
|
||||||
|
|
||||||
private CompactLongMap<OsmTrafficElement> map = new CompactLongMap<OsmTrafficElement>();
|
private CompactLongMap<OsmTrafficElement> map = new CompactLongMap<OsmTrafficElement>();
|
||||||
|
|
||||||
public long[] load( File file, int minLon, int minLat, int maxLon, int maxLat, boolean includeMotorways ) throws Exception
|
public void loadAll( File file, int minLon, int minLat, int maxLon, int maxLat, boolean includeMotorways ) throws Exception
|
||||||
|
{
|
||||||
|
load( file, minLon, minLat, maxLon, maxLat, includeMotorways );
|
||||||
|
|
||||||
|
// check for old traffic data
|
||||||
|
oldTrafficFile = new File( file.getParentFile(), file.getName() + "_old" );
|
||||||
|
if ( oldTrafficFile.exists() )
|
||||||
|
{
|
||||||
|
oldTrafficClasses = new OsmTrafficMap( null );
|
||||||
|
oldTrafficClasses.load( oldTrafficFile, minLon, minLat, maxLon, maxLat, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for old traffic data
|
||||||
|
newTrafficFile = new File( file.getParentFile(), file.getName() + "_new" );
|
||||||
|
newTrafficDos = new DataOutputStream( new BufferedOutputStream( new FileOutputStream( newTrafficFile ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finish() throws Exception
|
||||||
|
{
|
||||||
|
if ( newTrafficDos != null )
|
||||||
|
{
|
||||||
|
newTrafficDos.close();
|
||||||
|
newTrafficDos = null;
|
||||||
|
oldTrafficFile.delete();
|
||||||
|
newTrafficFile.renameTo( oldTrafficFile );
|
||||||
|
System.out.println( "TrafficMap: changes total=" + totalChanges + " supressed=" + supressedChanges );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load( File file, int minLon, int minLat, int maxLon, int maxLat, boolean includeMotorways ) throws Exception
|
||||||
{
|
{
|
||||||
this.minLon = minLon;
|
this.minLon = minLon;
|
||||||
this.minLat = minLat;
|
this.minLat = minLat;
|
||||||
|
@ -63,10 +114,8 @@ public class OsmTrafficMap
|
||||||
catch( EOFException eof ) {}
|
catch( EOFException eof ) {}
|
||||||
finally{ is.close(); }
|
finally{ is.close(); }
|
||||||
|
|
||||||
FrozenLongMap fmap = new FrozenLongMap<OsmTrafficElement>( map );
|
map = new FrozenLongMap<OsmTrafficElement>( map );
|
||||||
map = fmap;
|
|
||||||
System.out.println( "read traffic-elements: " + trafficElements );
|
System.out.println( "read traffic-elements: " + trafficElements );
|
||||||
return fmap.getKeyArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,17 +157,14 @@ public class OsmTrafficMap
|
||||||
|
|
||||||
public int getTrafficClass( long n1, long n2 )
|
public int getTrafficClass( long n1, long n2 )
|
||||||
{
|
{
|
||||||
int traffic1 = getTraffic( n1, n2 );
|
int traffic = getTraffic( n1, n2 );
|
||||||
int traffic2 = getTraffic( n2, n1 );
|
|
||||||
int traffic = traffic1 == -1 || traffic2 == -1 ? -1 : traffic1 > traffic2 ? traffic1 : traffic2;
|
|
||||||
return getTrafficClassForTraffic( traffic );
|
return getTrafficClassForTraffic( traffic );
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTrafficClassForTraffic( int traffic )
|
public int getTrafficClassForTraffic( int traffic )
|
||||||
{
|
{
|
||||||
if ( traffic < 0 ) return -1;
|
if ( traffic < 0 ) return -1;
|
||||||
if ( traffic < 20000 ) return 0;
|
if ( traffic < 40000 ) return 0;
|
||||||
if ( traffic < 40000 ) return 1;
|
|
||||||
if ( traffic < 80000 ) return 2;
|
if ( traffic < 80000 ) return 2;
|
||||||
if ( traffic < 160000 ) return 3;
|
if ( traffic < 160000 ) return 3;
|
||||||
if ( traffic < 320000 ) return 4;
|
if ( traffic < 320000 ) return 4;
|
||||||
|
@ -129,8 +175,11 @@ public class OsmTrafficMap
|
||||||
|
|
||||||
private int getTraffic( long n1, long n2 )
|
private int getTraffic( long n1, long n2 )
|
||||||
{
|
{
|
||||||
OsmTrafficElement e = getElement( n1, n2 );
|
OsmTrafficElement e1 = getElement( n1, n2 );
|
||||||
return e == null ? 0 : e.traffic;
|
int traffic1 = e1 == null ? 0 : e1.traffic;
|
||||||
|
OsmTrafficElement e2 = getElement( n2, n1 );
|
||||||
|
int traffic2 = e2 == null ? 0 : e2.traffic;
|
||||||
|
return traffic1 == -1 || traffic2 == -1 ? -1 : traffic1 > traffic2 ? traffic1 : traffic2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void freeze()
|
public void freeze()
|
||||||
|
@ -155,4 +204,61 @@ public class OsmTrafficMap
|
||||||
{
|
{
|
||||||
return map.get( n );
|
return map.get( n );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[] addTrafficClass( ArrayList<OsmNodeP> linkNodes, byte[] description ) throws IOException
|
||||||
|
{
|
||||||
|
double distance = 0.;
|
||||||
|
double sum = 0.;
|
||||||
|
|
||||||
|
for( int i=0; i<linkNodes.size()-1; i++ )
|
||||||
|
{
|
||||||
|
OsmNodeP n1 = linkNodes.get(i);
|
||||||
|
OsmNodeP n2 = linkNodes.get(i+1);
|
||||||
|
int traffic = getTraffic( n1.getIdFromPos(), n2.getIdFromPos() );
|
||||||
|
double dist = CheapRuler.distance( n1.ilon, n1.ilat, n2.ilon, n2.ilat );
|
||||||
|
distance += dist;
|
||||||
|
sum += dist*traffic;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( distance == 0. )
|
||||||
|
{
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
int traffic = (int)(sum/distance + 0.5);
|
||||||
|
|
||||||
|
long id0 = linkNodes.get(0).getIdFromPos();
|
||||||
|
long id1 = linkNodes.get(linkNodes.size()-1).getIdFromPos();
|
||||||
|
|
||||||
|
int trafficClass = getTrafficClassForTraffic( traffic );
|
||||||
|
|
||||||
|
// delta suppression: keep old traffic classes within some buffer range
|
||||||
|
if ( oldTrafficClasses != null )
|
||||||
|
{
|
||||||
|
int oldTrafficClass = oldTrafficClasses.getTraffic( id0, id1 );
|
||||||
|
if ( oldTrafficClass != trafficClass )
|
||||||
|
{
|
||||||
|
totalChanges++;
|
||||||
|
|
||||||
|
if ( oldTrafficClass == getTrafficClassForTraffic( (int)(traffic*1.3) )
|
||||||
|
|| oldTrafficClass == getTrafficClassForTraffic( (int)(traffic*0.77) ) )
|
||||||
|
{
|
||||||
|
trafficClass = oldTrafficClass;
|
||||||
|
supressedChanges++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( trafficClass > 0 )
|
||||||
|
{
|
||||||
|
newTrafficDos.writeLong( id0 );
|
||||||
|
newTrafficDos.writeLong( id1 );
|
||||||
|
newTrafficDos.writeInt( trafficClass );
|
||||||
|
|
||||||
|
expctxWay.decode( description );
|
||||||
|
expctxWay.addLookupValue( "estimated_traffic_class", trafficClass + 1 );
|
||||||
|
return expctxWay.encode();
|
||||||
|
}
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -306,7 +306,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
||||||
// read a traffic-file, if any
|
// read a traffic-file, if any
|
||||||
if ( trafficFile.exists() )
|
if ( trafficFile.exists() )
|
||||||
{
|
{
|
||||||
trafficMap = new OsmTrafficMap();
|
trafficMap = new OsmTrafficMap( expctxWay );
|
||||||
trafficMap.load( trafficFile, minLon, minLat, minLon + 5000000, minLat + 5000000, false );
|
trafficMap.load( trafficFile, minLon, minLat, minLon + 5000000, minLat + 5000000, false );
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -386,7 +386,6 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
||||||
public void nextWay( WayData way ) throws Exception
|
public void nextWay( WayData way ) throws Exception
|
||||||
{
|
{
|
||||||
byte[] description = abUnifier.unify( way.description );
|
byte[] description = abUnifier.unify( way.description );
|
||||||
int lastTraffic = 0;
|
|
||||||
|
|
||||||
// filter according to profile
|
// filter according to profile
|
||||||
expctxWay.evaluate( false, description );
|
expctxWay.evaluate( false, description );
|
||||||
|
@ -417,15 +416,6 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
||||||
|
|
||||||
OsmLinkP link = n2.createLink( n1 );
|
OsmLinkP link = n2.createLink( n1 );
|
||||||
|
|
||||||
int traffic = trafficMap == null ? 0 : trafficMap.getTrafficClass( n1.getIdFromPos(), n2.getIdFromPos() );
|
|
||||||
if ( traffic != lastTraffic )
|
|
||||||
{
|
|
||||||
expctxWay.decode( description );
|
|
||||||
expctxWay.addLookupValue( "estimated_traffic_class", traffic == 0 ? 0 : traffic + 1 );
|
|
||||||
description = abUnifier.unify( expctxWay.encode() );
|
|
||||||
lastTraffic = traffic;
|
|
||||||
n1.incWayCount(); // force network node due to description change
|
|
||||||
}
|
|
||||||
link.descriptionBitmap = description;
|
link.descriptionBitmap = description;
|
||||||
|
|
||||||
if ( n1.ilon / cellsize != n2.ilon / cellsize || n1.ilat / cellsize != n2.ilat / cellsize )
|
if ( n1.ilon / cellsize != n2.ilon / cellsize || n1.ilat / cellsize != n2.ilat / cellsize )
|
||||||
|
@ -450,7 +440,6 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
||||||
|
|
||||||
nodesMap = null;
|
nodesMap = null;
|
||||||
borderSet = null;
|
borderSet = null;
|
||||||
trafficMap = null;
|
|
||||||
|
|
||||||
byte[] abBuf1 = new byte[10 * 1024 * 1024];
|
byte[] abBuf1 = new byte[10 * 1024 * 1024];
|
||||||
byte[] abBuf2 = new byte[10 * 1024 * 1024];
|
byte[] abBuf2 = new byte[10 * 1024 * 1024];
|
||||||
|
@ -552,7 +541,7 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
||||||
|
|
||||||
for ( OsmNodeP n : sortedList.values() )
|
for ( OsmNodeP n : sortedList.values() )
|
||||||
{
|
{
|
||||||
n.writeNodeData( mc );
|
n.writeNodeData( mc, trafficMap );
|
||||||
}
|
}
|
||||||
if ( mc.getSize() > 0 )
|
if ( mc.getSize() > 0 )
|
||||||
{
|
{
|
||||||
|
@ -623,6 +612,11 @@ public class WayLinker extends MapCreatorBase implements Runnable
|
||||||
ra.write( abFileIndex, 0, abFileIndex.length );
|
ra.write( abFileIndex, 0, abFileIndex.length );
|
||||||
ra.close();
|
ra.close();
|
||||||
}
|
}
|
||||||
|
if ( trafficMap != null )
|
||||||
|
{
|
||||||
|
trafficMap.finish();
|
||||||
|
trafficMap = null;
|
||||||
|
}
|
||||||
System.out.println( "**** codec stats: *******\n" + StatCoderContext.getBitReport() );
|
System.out.println( "**** codec stats: *******\n" + StatCoderContext.getBitReport() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue