package btools.codec; import java.util.BitSet; import java.util.HashMap; import btools.util.ByteArrayUnifier; import btools.util.ByteDataReader; /** * MicroCache2 is the new format that uses statistical encoding and * is able to do access filtering and waypoint matching during encoding */ public final class MicroCache2 extends MicroCache { private int lonBase; private int latBase; private int cellsize; public MicroCache2( int size, byte[] databuffer, int lonIdx, int latIdx, int divisor ) throws Exception { super( databuffer ); // sets ab=databuffer, aboffset=0 faid = new int[size]; fapos = new int[size]; this.size = 0; cellsize = 1000000 / divisor; lonBase = lonIdx*cellsize; latBase = latIdx*cellsize; } public byte[] readUnified( int len, ByteArrayUnifier u ) { byte[] b = u.unify( ab, aboffset, len ); aboffset += len; return b; } public MicroCache2( DataBuffers dataBuffers, int lonIdx, int latIdx, int divisor, TagValueValidator wayValidator, WaypointMatcher waypointMatcher ) throws Exception { super( null ); cellsize = 1000000 / divisor; lonBase = lonIdx*cellsize; latBase = latIdx*cellsize; StatCoderContext bc = new StatCoderContext( dataBuffers.iobuffer ); TagValueCoder wayTagCoder = new TagValueCoder( bc, dataBuffers.tagbuf1, wayValidator ); TagValueCoder nodeTagCoder = new TagValueCoder( bc, dataBuffers.tagbuf1, null ); NoisyDiffCoder nodeIdxDiff = new NoisyDiffCoder( bc ); NoisyDiffCoder nodeEleDiff = new NoisyDiffCoder( bc ); NoisyDiffCoder extLonDiff = new NoisyDiffCoder(bc); NoisyDiffCoder extLatDiff = new NoisyDiffCoder(bc); NoisyDiffCoder transEleDiff = new NoisyDiffCoder( bc ); size = bc.decodeNoisyNumber( 5 ); faid = size > dataBuffers.ibuf2.length ? new int[size] : dataBuffers.ibuf2; fapos = size > dataBuffers.ibuf3.length ? new int[size] : dataBuffers.ibuf3; int[] alon = size > dataBuffers.alon.length ? new int[size] : dataBuffers.alon; int[] alat = size > dataBuffers.alat.length ? new int[size] : dataBuffers.alat; if ( debug ) System.out.println( "*** decoding cache of size=" + size ); bc.decodeSortedArray( faid, 0, size, 0x20000000, 0 ); for( int n = 0; n> 32); alat[n] = (int)(id64 & 0xffffffff); } int netdatasize = bc.decodeNoisyNumber( 10 ); ab = netdatasize > dataBuffers.bbuf1.length ? new byte[netdatasize] : dataBuffers.bbuf1; aboffset = 0; BitSet validNodes = new BitSet( size ); int finaldatasize = 0; LinkedListContainer reverseLinks = new LinkedListContainer( size, dataBuffers.ibuf1 ); int selev = 0; for( int n=0; n>= 2; } int lon32 = lonBase + dlon; int lat32 = latBase + dlat; return ((long)lon32)<<32 | lat32; } @Override public int shrinkId( long id64 ) { int lon32 = (int)(id64 >> 32); int lat32 = (int)(id64 & 0xffffffff); int dlon = lon32 - lonBase; int dlat = lat32 - latBase; int id32 = 0; for( int bm = 0x4000; bm > 0; bm >>= 1 ) { id32 <<= 2; if ( ( dlon & bm ) != 0 ) id32 |= 1; if ( ( dlat & bm ) != 0 ) id32 |= 2; } return id32; } @Override public boolean isInternal( int ilon, int ilat ) { return ilon >= lonBase && ilon < lonBase + cellsize && ilat >= latBase && ilat < latBase + cellsize; } @Override public int encodeMicroCache( byte[] buffer ) { HashMap idMap = new HashMap(); for( int n=0; n> 32); int ilat = (int)(id64 & 0xffffffff); nlinks = 0; while( hasMoreData() ) // loop over links { // read link data int startPointer = aboffset; int endPointer = getEndPointer(); int ilonlink = ilon + readVarLengthSigned(); int ilatlink = ilat + readVarLengthSigned(); int sizecode = readVarLengthUnsigned(); boolean isReverse = ( sizecode & 1 ) != 0; int descSize = sizecode >> 1; byte[] description = null; if ( descSize > 0 ) { description = new byte[descSize]; readFully( description ); } boolean isInternal = isInternal( ilonlink, ilatlink ); if ( isReverse && isInternal ) { if ( dodebug ) System.out.println( "*** NOT encoding link reverse=" + isReverse + " internal=" + isInternal ); netdatasize -= aboffset-startPointer; continue; // do not encode internal reverse links } if ( dodebug ) System.out.println( "*** encoding link reverse=" + isReverse + " internal=" + isInternal ); nlinks++; if ( isInternal ) { long link64 = ((long)ilonlink)<<32 | ilatlink; Integer idx = idMap.get( Long.valueOf( link64 ) ); if ( idx == null ) throw new RuntimeException( "ups: internal not found?" ); int nodeIdx = idx.intValue(); if ( dodebug ) System.out.println( "*** target nodeIdx=" + nodeIdx ); if ( nodeIdx == n ) throw new RuntimeException( "ups: self ref?" ); nodeIdxDiff.encodeSignedValue( nodeIdx - n ); if ( dostats ) bc.assignBits( "nodeIdx" ); } else { nodeIdxDiff.encodeSignedValue( 0 ); bc.encodeBit( isReverse ); extLonDiff.encodeSignedValue( ilonlink - ilon ); extLatDiff.encodeSignedValue( ilatlink - ilat ); if ( dostats ) bc.assignBits( "externalNode" ); } wayTagCoder.encodeTagValueSet( description ); if ( dostats ) bc.assignBits( "wayDescIdx" ); if ( !isReverse ) { byte[] geometry = readDataUntil( endPointer ); // write transition nodes int count = transCounts.getNext(); if ( dodebug ) System.out.println( "*** encoding geometry with count=" + count ); bc.encodeVarBits( count++ ); if ( dostats ) bc.assignBits( "transcount" ); int transcount = 0; if ( geometry != null ) { int dlon_remaining = ilonlink - ilon; int dlat_remaining = ilatlink - ilat; ByteDataReader r = new ByteDataReader( geometry ); while ( r.hasMoreData() ) { transcount++; int dlon = r.readVarLengthSigned(); int dlat = r.readVarLengthSigned(); bc.encodePredictedValue( dlon, dlon_remaining/count ); bc.encodePredictedValue( dlat, dlat_remaining/count ); dlon_remaining -= dlon; dlat_remaining -= dlat; if ( count > 1 ) count--; if ( dostats ) bc.assignBits( "transpos" ); transEleDiff.encodeSignedValue( r.readVarLengthSigned() ); if ( dostats ) bc.assignBits( "transele" ); } } transCounts.add( transcount ); } } linkCounts.add( nlinks ); } if ( pass == 3 ) { return bc.getEncodedLength(); } } } }