2013-04-18 23:35:02 +02:00
package net.osmand.binary ;
2013-09-23 19:42:48 +02:00
import gnu.trove.iterator.TLongIterator ;
2013-04-18 23:35:02 +02:00
import gnu.trove.list.array.TIntArrayList ;
2013-09-23 19:42:48 +02:00
import gnu.trove.list.array.TLongArrayList ;
2013-04-18 23:35:02 +02:00
import gnu.trove.map.hash.TIntObjectHashMap ;
2013-11-06 13:51:54 +01:00
import java.io.File ;
import java.io.FileNotFoundException ;
import java.io.FileOutputStream ;
import java.io.IOException ;
import java.io.RandomAccessFile ;
2013-04-18 23:35:02 +02:00
import java.text.MessageFormat ;
import java.util.ArrayList ;
import java.util.HashMap ;
import java.util.Iterator ;
import java.util.LinkedHashSet ;
import java.util.List ;
import java.util.Locale ;
import java.util.Map ;
import java.util.Set ;
import net.osmand.ResultMatcher ;
import net.osmand.binary.BinaryMapAddressReaderAdapter.AddressRegion ;
import net.osmand.binary.BinaryMapAddressReaderAdapter.CitiesBlock ;
import net.osmand.binary.BinaryMapIndexReader.MapIndex ;
import net.osmand.binary.BinaryMapIndexReader.MapRoot ;
import net.osmand.binary.BinaryMapIndexReader.SearchFilter ;
import net.osmand.binary.BinaryMapIndexReader.SearchPoiTypeFilter ;
import net.osmand.binary.BinaryMapIndexReader.SearchRequest ;
import net.osmand.binary.BinaryMapIndexReader.TagValuePair ;
import net.osmand.binary.BinaryMapPoiReaderAdapter.PoiRegion ;
2013-11-24 19:22:07 +01:00
import net.osmand.binary.BinaryMapPoiReaderAdapter.PoiSubType ;
2013-04-18 23:35:02 +02:00
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion ;
import net.osmand.binary.BinaryMapTransportReaderAdapter.TransportIndex ;
import net.osmand.data.Amenity ;
import net.osmand.data.AmenityType ;
import net.osmand.data.Building ;
import net.osmand.data.City ;
import net.osmand.data.MapObject ;
import net.osmand.data.Street ;
import net.osmand.util.MapUtils ;
import com.google.protobuf.CodedOutputStream ;
import com.google.protobuf.WireFormat ;
public class BinaryInspector {
public static final int BUFFER_SIZE = 1 < < 20 ;
2013-09-23 19:42:48 +02:00
private VerboseInfo vInfo ;
2013-04-18 23:35:02 +02:00
public static void main ( String [ ] args ) throws IOException {
2013-09-23 19:42:48 +02:00
BinaryInspector in = new BinaryInspector ( ) ;
in . inspector ( args ) ;
2013-04-18 23:35:02 +02:00
// test cases show info
2013-11-24 21:29:50 +01:00
in . inspector ( new String [ ] {
2013-11-24 19:22:07 +01:00
" -vpoi " ,
//"-vmap", "-vmapobjects",
2013-11-24 17:36:38 +01:00
//"-vstreets", "-bbox=14.4,50.1,14.5,50.01",
2013-11-24 21:29:50 +01:00
" /home/victor/projects/osmand/osm-gen/Austria_europe.obf " } ) ;
2013-04-18 23:35:02 +02:00
}
2013-09-23 19:42:48 +02:00
private void printToFile ( String s ) throws IOException {
if ( vInfo . osmOut ! = null ) {
vInfo . osmOut . write ( s . getBytes ( ) ) ;
} else {
System . out . println ( s ) ;
}
}
2013-04-18 23:35:02 +02:00
2013-09-23 19:42:48 +02:00
private void println ( String s ) {
2013-09-24 18:53:48 +02:00
if ( vInfo ! = null & & vInfo . osm & & vInfo . osmOut = = null ) {
2013-09-23 19:42:48 +02:00
// ignore
} else {
2013-11-24 17:14:36 +01:00
System . out . println ( s ) ;
2013-09-23 19:42:48 +02:00
}
2013-04-18 23:35:02 +02:00
}
2013-09-24 18:53:48 +02:00
2013-09-23 19:42:48 +02:00
private void print ( String s ) {
2013-09-24 18:53:48 +02:00
if ( vInfo ! = null & & vInfo . osm & & vInfo . osmOut = = null ) {
2013-09-23 19:42:48 +02:00
// ignore
} else {
2013-11-24 17:14:36 +01:00
System . out . print ( s ) ;
2013-09-23 19:42:48 +02:00
}
2013-04-18 23:35:02 +02:00
}
protected static class VerboseInfo {
boolean vaddress ;
boolean vcities ;
boolean vstreetgroups ;
boolean vstreets ;
boolean vbuildings ;
boolean vintersections ;
boolean vtransport ;
boolean vpoi ;
boolean vmap ;
boolean vmapObjects ;
2013-09-23 19:42:48 +02:00
boolean osm ;
FileOutputStream osmOut = null ;
2013-04-18 23:35:02 +02:00
double lattop = 85 ;
double latbottom = - 85 ;
double lonleft = - 180 ;
double lonright = 180 ;
int zoom = - 1 ;
public boolean isVaddress ( ) {
return vaddress ;
}
public int getZoom ( ) {
return zoom ;
}
public boolean isVmap ( ) {
return vmap ;
}
public boolean isVpoi ( ) {
return vpoi ;
}
public boolean isVtransport ( ) {
return vtransport ;
}
2013-09-23 19:42:48 +02:00
public VerboseInfo ( String [ ] params ) throws FileNotFoundException {
2013-04-18 23:35:02 +02:00
for ( int i = 0 ; i < params . length ; i + + ) {
if ( params [ i ] . equals ( " -vaddress " ) ) {
vaddress = true ;
} else if ( params [ i ] . equals ( " -vstreets " ) ) {
vstreets = true ;
} else if ( params [ i ] . equals ( " -vstreetgroups " ) ) {
vstreetgroups = true ;
} else if ( params [ i ] . equals ( " -vcities " ) ) {
vcities = true ;
} else if ( params [ i ] . equals ( " -vbuildings " ) ) {
vbuildings = true ;
} else if ( params [ i ] . equals ( " -vintersections " ) ) {
vintersections = true ;
} else if ( params [ i ] . equals ( " -vmap " ) ) {
vmap = true ;
} else if ( params [ i ] . equals ( " -vmapobjects " ) ) {
vmapObjects = true ;
} else if ( params [ i ] . equals ( " -vpoi " ) ) {
vpoi = true ;
2013-09-23 19:42:48 +02:00
} else if ( params [ i ] . startsWith ( " -osm " ) ) {
osm = true ;
if ( params [ i ] . startsWith ( " -osm= " ) ) {
osmOut = new FileOutputStream ( params [ i ] . substring ( 5 ) ) ;
}
2013-04-18 23:35:02 +02:00
} else if ( params [ i ] . equals ( " -vtransport " ) ) {
vtransport = true ;
} else if ( params [ i ] . startsWith ( " -zoom= " ) ) {
zoom = Integer . parseInt ( params [ i ] . substring ( " -zoom= " . length ( ) ) ) ;
} else if ( params [ i ] . startsWith ( " -bbox= " ) ) {
String [ ] values = params [ i ] . substring ( " -bbox= " . length ( ) ) . split ( " , " ) ;
lonleft = Double . parseDouble ( values [ 0 ] ) ;
lattop = Double . parseDouble ( values [ 1 ] ) ;
lonright = Double . parseDouble ( values [ 2 ] ) ;
latbottom = Double . parseDouble ( values [ 3 ] ) ;
}
}
}
public boolean contains ( MapObject o ) {
return lattop > = o . getLocation ( ) . getLatitude ( ) & & latbottom < = o . getLocation ( ) . getLatitude ( )
& & lonleft < = o . getLocation ( ) . getLongitude ( ) & & lonright > = o . getLocation ( ) . getLongitude ( ) ;
}
2013-09-23 19:42:48 +02:00
public void close ( ) throws IOException {
if ( osmOut ! = null ) {
osmOut . close ( ) ; ;
osmOut = null ;
}
}
2013-04-18 23:35:02 +02:00
}
2013-09-23 19:42:48 +02:00
public void inspector ( String [ ] args ) throws IOException {
2013-04-18 23:35:02 +02:00
if ( args = = null | | args . length = = 0 ) {
printUsage ( null ) ;
return ;
}
String f = args [ 0 ] ;
if ( f . charAt ( 0 ) = = '-' ) {
// command
if ( f . equals ( " -c " ) | | f . equals ( " -combine " ) ) {
if ( args . length < 4 ) {
printUsage ( " Too few parameters to extract (require minimum 4) " ) ;
} else {
Map < File , String > parts = new HashMap < File , String > ( ) ;
for ( int i = 2 ; i < args . length ; i + + ) {
File file = new File ( args [ i ] ) ;
if ( ! file . exists ( ) ) {
System . err . println ( " File to extract from doesn't exist " + args [ i ] ) ;
return ;
}
parts . put ( file , null ) ;
if ( i < args . length - 1 ) {
if ( args [ i + 1 ] . startsWith ( " - " ) | | args [ i + 1 ] . startsWith ( " + " ) ) {
parts . put ( file , args [ i + 1 ] ) ;
i + + ;
}
}
}
List < Float > extracted = combineParts ( new File ( args [ 1 ] ) , parts ) ;
if ( extracted ! = null ) {
println ( " \ n " + extracted . size ( ) + " parts were successfully extracted to " + args [ 1 ] ) ;
}
}
} else if ( f . startsWith ( " -v " ) ) {
if ( args . length < 2 ) {
printUsage ( " Missing file parameter " ) ;
} else {
2013-09-23 19:42:48 +02:00
vInfo = new VerboseInfo ( args ) ;
printFileInformation ( args [ args . length - 1 ] ) ;
vInfo . close ( ) ;
2013-04-18 23:35:02 +02:00
}
} else {
printUsage ( " Unknown command : " + f ) ;
}
} else {
2013-09-23 19:42:48 +02:00
vInfo = null ;
printFileInformation ( f ) ;
2013-04-18 23:35:02 +02:00
}
}
2013-09-25 11:36:22 +02:00
public static final void writeInt ( CodedOutputStream ous , int v ) throws IOException {
2013-04-18 23:35:02 +02:00
ous . writeRawByte ( ( v > > > 24 ) & 0xFF ) ;
ous . writeRawByte ( ( v > > > 16 ) & 0xFF ) ;
ous . writeRawByte ( ( v > > > 8 ) & 0xFF ) ;
2013-07-31 20:39:50 +02:00
ous . writeRawByte ( v & 0xFF ) ;
2013-04-18 23:35:02 +02:00
//written += 4;
}
@SuppressWarnings ( " unchecked " )
2013-09-25 11:36:22 +02:00
public static List < Float > combineParts ( File fileToExtract , Map < File , String > partsToExtractFrom ) throws IOException {
2013-04-18 23:35:02 +02:00
BinaryMapIndexReader [ ] indexes = new BinaryMapIndexReader [ partsToExtractFrom . size ( ) ] ;
RandomAccessFile [ ] rafs = new RandomAccessFile [ partsToExtractFrom . size ( ) ] ;
LinkedHashSet < Float > [ ] partsSet = new LinkedHashSet [ partsToExtractFrom . size ( ) ] ;
int c = 0 ;
Set < String > addressNames = new LinkedHashSet < String > ( ) ;
int version = - 1 ;
// Go through all files and validate conistency
for ( File f : partsToExtractFrom . keySet ( ) ) {
if ( f . getAbsolutePath ( ) . equals ( fileToExtract . getAbsolutePath ( ) ) ) {
System . err . println ( " Error : Input file is equal to output file " + f . getAbsolutePath ( ) ) ;
return null ;
}
rafs [ c ] = new RandomAccessFile ( f . getAbsolutePath ( ) , " r " ) ;
indexes [ c ] = new BinaryMapIndexReader ( rafs [ c ] ) ;
partsSet [ c ] = new LinkedHashSet < Float > ( ) ;
if ( version = = - 1 ) {
version = indexes [ c ] . getVersion ( ) ;
} else {
if ( indexes [ c ] . getVersion ( ) ! = version ) {
System . err . println ( " Error : Different input files has different input versions " + indexes [ c ] . getVersion ( ) + " != " + version ) ;
return null ;
}
}
LinkedHashSet < Float > temp = new LinkedHashSet < Float > ( ) ;
String pattern = partsToExtractFrom . get ( f ) ;
boolean minus = true ;
for ( int i = 0 ; i < indexes [ c ] . getIndexes ( ) . size ( ) ; i + + ) {
2013-07-31 20:15:26 +02:00
partsSet [ c ] . add ( i + 1f ) ;
2013-04-18 23:35:02 +02:00
BinaryIndexPart part = indexes [ c ] . getIndexes ( ) . get ( i ) ;
if ( part instanceof MapIndex ) {
List < MapRoot > roots = ( ( MapIndex ) part ) . getRoots ( ) ;
int rsize = roots . size ( ) ;
for ( int j = 0 ; j < rsize ; j + + ) {
2013-07-31 20:15:26 +02:00
partsSet [ c ] . add ( ( i + 1f ) + ( j + 1 ) / 10f ) ;
2013-04-18 23:35:02 +02:00
}
}
}
if ( pattern ! = null ) {
minus = pattern . startsWith ( " - " ) ;
String [ ] split = pattern . substring ( 1 ) . split ( " , " ) ;
for ( String s : split ) {
temp . add ( Float . valueOf ( s ) ) ;
}
}
Iterator < Float > p = partsSet [ c ] . iterator ( ) ;
while ( p . hasNext ( ) ) {
Float part = p . next ( ) ;
if ( minus ) {
if ( temp . contains ( part ) ) {
p . remove ( ) ;
}
} else {
if ( ! temp . contains ( part ) ) {
p . remove ( ) ;
}
}
}
c + + ;
}
// write files
FileOutputStream fout = new FileOutputStream ( fileToExtract ) ;
CodedOutputStream ous = CodedOutputStream . newInstance ( fout , BUFFER_SIZE ) ;
List < Float > list = new ArrayList < Float > ( ) ;
byte [ ] BUFFER_TO_READ = new byte [ BUFFER_SIZE ] ;
ous . writeInt32 ( OsmandOdb . OsmAndStructure . VERSION_FIELD_NUMBER , version ) ;
ous . writeInt64 ( OsmandOdb . OsmAndStructure . DATECREATED_FIELD_NUMBER , System . currentTimeMillis ( ) ) ;
for ( int k = 0 ; k < indexes . length ; k + + ) {
LinkedHashSet < Float > partSet = partsSet [ k ] ;
BinaryMapIndexReader index = indexes [ k ] ;
RandomAccessFile raf = rafs [ k ] ;
for ( int i = 0 ; i < index . getIndexes ( ) . size ( ) ; i + + ) {
if ( ! partSet . contains ( Float . valueOf ( i + 1f ) ) ) {
continue ;
}
2013-07-31 20:15:26 +02:00
list . add ( i + 1f ) ;
2013-04-18 23:35:02 +02:00
BinaryIndexPart part = index . getIndexes ( ) . get ( i ) ;
String map ;
if ( part instanceof MapIndex ) {
ous . writeTag ( OsmandOdb . OsmAndStructure . MAPINDEX_FIELD_NUMBER , WireFormat . WIRETYPE_FIXED32_LENGTH_DELIMITED ) ;
map = " Map " ;
} else if ( part instanceof AddressRegion ) {
ous . writeTag ( OsmandOdb . OsmAndStructure . ADDRESSINDEX_FIELD_NUMBER , WireFormat . WIRETYPE_FIXED32_LENGTH_DELIMITED ) ;
map = " Address " ;
if ( addressNames . contains ( part . getName ( ) ) ) {
System . err . println ( " Error : going to merge 2 addresses with same names. Skip " + part . getName ( ) ) ;
continue ;
}
addressNames . add ( part . getName ( ) ) ;
} else if ( part instanceof TransportIndex ) {
ous . writeTag ( OsmandOdb . OsmAndStructure . TRANSPORTINDEX_FIELD_NUMBER , WireFormat . WIRETYPE_FIXED32_LENGTH_DELIMITED ) ;
map = " Transport " ;
} else if ( part instanceof PoiRegion ) {
ous . writeTag ( OsmandOdb . OsmAndStructure . POIINDEX_FIELD_NUMBER , WireFormat . WIRETYPE_FIXED32_LENGTH_DELIMITED ) ;
map = " POI " ;
} else if ( part instanceof RouteRegion ) {
ous . writeTag ( OsmandOdb . OsmAndStructure . ROUTINGINDEX_FIELD_NUMBER , WireFormat . WIRETYPE_FIXED32_LENGTH_DELIMITED ) ;
map = " Routing " ;
} else {
throw new UnsupportedOperationException ( ) ;
}
writeInt ( ous , part . getLength ( ) ) ;
copyBinaryPart ( ous , BUFFER_TO_READ , raf , part . getFilePointer ( ) , part . getLength ( ) ) ;
2013-09-25 11:36:22 +02:00
System . out . println ( MessageFormat . format ( " {2} part {0} is extracted {1} bytes " ,
2013-04-18 23:35:02 +02:00
new Object [ ] { part . getName ( ) , part . getLength ( ) , map } ) ) ;
}
}
ous . writeInt32 ( OsmandOdb . OsmAndStructure . VERSIONCONFIRM_FIELD_NUMBER , version ) ;
ous . flush ( ) ;
fout . close ( ) ;
return list ;
}
2013-09-25 11:36:22 +02:00
private static void copyBinaryPart ( CodedOutputStream ous , byte [ ] BUFFER , RandomAccessFile raf , long fp , int length )
2013-04-18 23:35:02 +02:00
throws IOException {
raf . seek ( fp ) ;
int toRead = length ;
while ( toRead > 0 ) {
int read = raf . read ( BUFFER ) ;
if ( read = = - 1 ) {
throw new IllegalArgumentException ( " Unexpected end of file " ) ;
}
if ( toRead < read ) {
read = toRead ;
}
ous . writeRawBytes ( BUFFER , 0 , read ) ;
toRead - = read ;
}
}
2013-09-23 19:42:48 +02:00
protected String formatBounds ( int left , int right , int top , int bottom ) {
2013-04-18 23:35:02 +02:00
double l = MapUtils . get31LongitudeX ( left ) ;
double r = MapUtils . get31LongitudeX ( right ) ;
double t = MapUtils . get31LatitudeY ( top ) ;
double b = MapUtils . get31LatitudeY ( bottom ) ;
return formatLatBounds ( l , r , t , b ) ;
}
2013-09-23 19:42:48 +02:00
protected String formatLatBounds ( double l , double r , double t , double b ) {
2013-04-18 23:35:02 +02:00
MessageFormat format = new MessageFormat ( " (left top - right bottom) : {0,number,#.####}, {1,number,#.####} NE - {2,number,#.####}, {3,number,#.####} NE " , new Locale ( " EN " , " US " ) ) ;
return format . format ( new Object [ ] { l , t , r , b } ) ;
}
2013-09-23 19:42:48 +02:00
public void printFileInformation ( String fileName ) throws IOException {
2013-04-18 23:35:02 +02:00
File file = new File ( fileName ) ;
if ( ! file . exists ( ) ) {
println ( " Binary OsmAnd index " + fileName + " was not found. " ) ;
return ;
}
2013-09-23 19:42:48 +02:00
printFileInformation ( file ) ;
2013-04-18 23:35:02 +02:00
}
2013-09-23 19:42:48 +02:00
public void printFileInformation ( File file ) throws IOException {
2013-04-18 23:35:02 +02:00
RandomAccessFile r = new RandomAccessFile ( file . getAbsolutePath ( ) , " r " ) ;
try {
BinaryMapIndexReader index = new BinaryMapIndexReader ( r ) ;
int i = 1 ;
println ( " Binary index " + file . getName ( ) + " version = " + index . getVersion ( ) ) ;
for ( BinaryIndexPart p : index . getIndexes ( ) ) {
String partname = " " ;
if ( p instanceof MapIndex ) {
partname = " Map " ;
} else if ( p instanceof TransportIndex ) {
partname = " Transport " ;
} else if ( p instanceof RouteRegion ) {
partname = " Routing " ;
} else if ( p instanceof PoiRegion ) {
partname = " Poi " ;
} else if ( p instanceof AddressRegion ) {
partname = " Address " ;
}
String name = p . getName ( ) = = null ? " " : p . getName ( ) ;
println ( MessageFormat . format ( " {0} {1} data {3} - {2,number,#} bytes " ,
2013-07-31 20:15:26 +02:00
new Object [ ] { i , partname , p . getLength ( ) , name } ) ) ;
2013-04-18 23:35:02 +02:00
if ( p instanceof TransportIndex ) {
TransportIndex ti = ( ( TransportIndex ) p ) ;
int sh = ( 31 - BinaryMapIndexReader . TRANSPORT_STOP_ZOOM ) ;
println ( " \ tBounds " + formatBounds ( ti . getLeft ( ) < < sh , ti . getRight ( ) < < sh ,
ti . getTop ( ) < < sh , ti . getBottom ( ) < < sh ) ) ;
} else if ( p instanceof RouteRegion ) {
RouteRegion ri = ( ( RouteRegion ) p ) ;
println ( " \ tBounds " + formatLatBounds ( ri . getLeftLongitude ( ) , ri . getRightLongitude ( ) ,
ri . getTopLatitude ( ) , ri . getBottomLatitude ( ) ) ) ;
} else if ( p instanceof MapIndex ) {
MapIndex m = ( ( MapIndex ) p ) ;
int j = 1 ;
for ( MapRoot mi : m . getRoots ( ) ) {
println ( MessageFormat . format ( " \ t{4}.{5} Map level minZoom = {0}, maxZoom = {1}, size = {2,number,#} bytes \ n \ t \ tBounds {3} " ,
new Object [ ] {
mi . getMinZoom ( ) , mi . getMaxZoom ( ) , mi . getLength ( ) ,
formatBounds ( mi . getLeft ( ) , mi . getRight ( ) , mi . getTop ( ) , mi . getBottom ( ) ) ,
i , j + + } ) ) ;
}
2013-09-23 19:42:48 +02:00
if ( ( vInfo ! = null & & vInfo . isVmap ( ) ) ) {
printMapDetailInfo ( index , m ) ;
2013-04-18 23:35:02 +02:00
}
2013-09-23 19:42:48 +02:00
} else if ( p instanceof PoiRegion & & ( vInfo ! = null & & vInfo . isVpoi ( ) ) ) {
printPOIDetailInfo ( vInfo , index , ( PoiRegion ) p ) ;
2013-04-18 23:35:02 +02:00
} else if ( p instanceof AddressRegion ) {
List < CitiesBlock > cities = ( ( AddressRegion ) p ) . cities ;
for ( CitiesBlock c : cities ) {
println ( " \ t " + i + " . " + c . type + " Address part size= " + c . length + " bytes " ) ;
}
2013-09-23 19:42:48 +02:00
if ( vInfo ! = null & & vInfo . isVaddress ( ) ) {
printAddressDetailedInfo ( vInfo , index , ( AddressRegion ) p ) ;
2013-04-18 23:35:02 +02:00
}
}
i + + ;
}
} catch ( IOException e ) {
System . err . println ( " File is not valid index : " + file . getAbsolutePath ( ) ) ;
throw e ;
}
}
2013-09-23 19:42:48 +02:00
private void printAddressDetailedInfo ( VerboseInfo verbose , BinaryMapIndexReader index , AddressRegion region ) throws IOException {
2013-04-18 23:35:02 +02:00
String [ ] cityType_String = new String [ ] {
" Cities/Towns section " ,
" Villages section " ,
" Postcodes section " ,
} ;
int [ ] cityType = new int [ ] {
BinaryMapAddressReaderAdapter . CITY_TOWN_TYPE ,
BinaryMapAddressReaderAdapter . VILLAGES_TYPE ,
BinaryMapAddressReaderAdapter . POSTCODES_TYPE
} ;
for ( int j = 0 ; j < cityType . length ; j + + ) {
int type = cityType [ j ] ;
final List < City > cities = index . getCities ( region , null , type ) ;
2013-07-31 20:15:26 +02:00
print ( MessageFormat . format ( " \ t{0}, {1,number,#} group(s) " , new Object [ ] { cityType_String [ j ] , cities . size ( ) } ) ) ;
2013-04-18 23:35:02 +02:00
if ( BinaryMapAddressReaderAdapter . CITY_TOWN_TYPE = = type ) {
if ( ! verbose . vstreetgroups & & ! verbose . vcities ) {
println ( " " ) ;
continue ;
}
} else if ( ! verbose . vstreetgroups ) {
println ( " " ) ;
continue ;
}
println ( " : " ) ;
for ( City c : cities ) {
int size = index . preloadStreets ( c , null ) ;
List < Street > streets = new ArrayList < Street > ( c . getStreets ( ) ) ;
print ( MessageFormat . format ( " \ t \ t''{0}'' [{1,number,#}], {2,number,#} street(s) size {3,number,#} bytes " ,
2013-08-03 05:52:24 +02:00
new Object [ ] { c . getEnName ( ) , c . getId ( ) , streets . size ( ) , size } ) ) ;
2013-04-18 23:35:02 +02:00
if ( ! verbose . vstreets )
{
println ( " " ) ;
continue ;
}
println ( " : " ) ;
if ( ! verbose . contains ( c ) )
continue ;
for ( Street t : streets ) {
if ( ! verbose . contains ( t ) )
continue ;
index . preloadBuildings ( t , null ) ;
final List < Building > buildings = t . getBuildings ( ) ;
final List < Street > intersections = t . getIntersectedStreets ( ) ;
println ( MessageFormat . format ( " \ t \ t \ t''{0}'' [{1,number,#}], {2,number,#} building(s), {3,number,#} intersections(s) " ,
2013-08-03 05:52:24 +02:00
new Object [ ] { t . getEnName ( ) , t . getId ( ) , buildings . size ( ) , intersections . size ( ) } ) ) ;
2013-04-18 23:35:02 +02:00
if ( buildings ! = null & & ! buildings . isEmpty ( ) & & verbose . vbuildings ) {
println ( " \ t \ t \ t \ tBuildings: " ) ;
for ( Building b : buildings ) {
println ( MessageFormat . format ( " \ t \ t \ t \ t{0} [{1,number,#}] " ,
2013-07-31 20:05:59 +02:00
new Object [ ] { b . getName ( true ) , b . getId ( ) } ) ) ;
2013-04-18 23:35:02 +02:00
}
}
if ( intersections ! = null & & ! intersections . isEmpty ( ) & & verbose . vintersections ) {
print ( " \ t \ t \ t \ tIntersects with: " ) ;
for ( Street s : intersections ) {
println ( " \ t \ t \ t \ t \ t " + s . getEnName ( ) ) ;
}
}
}
}
}
}
private static class DamnCounter
{
int value ;
}
2013-09-23 19:42:48 +02:00
private void printMapDetailInfo ( BinaryMapIndexReader index , MapIndex mapIndex ) throws IOException {
2013-04-18 23:35:02 +02:00
final StringBuilder b = new StringBuilder ( ) ;
final DamnCounter mapObjectsCounter = new DamnCounter ( ) ;
2013-09-23 19:42:48 +02:00
if ( vInfo . osm ) {
printToFile ( " <?xml version='1.0' encoding='UTF-8'?> \ n " +
" <osm version='0.5'> \ n " ) ;
}
2013-04-18 23:35:02 +02:00
SearchRequest < BinaryMapDataObject > req = BinaryMapIndexReader . buildSearchRequest (
2013-09-23 19:42:48 +02:00
MapUtils . get31TileNumberX ( vInfo . lonleft ) ,
MapUtils . get31TileNumberX ( vInfo . lonright ) ,
MapUtils . get31TileNumberY ( vInfo . lattop ) ,
MapUtils . get31TileNumberY ( vInfo . latbottom ) ,
vInfo . getZoom ( ) ,
2013-04-18 23:35:02 +02:00
new SearchFilter ( ) {
@Override
public boolean accept ( TIntArrayList types , MapIndex index ) {
return true ;
}
} ,
new ResultMatcher < BinaryMapDataObject > ( ) {
@Override
public boolean publish ( BinaryMapDataObject obj ) {
mapObjectsCounter . value + + ;
2013-09-23 19:42:48 +02:00
if ( vInfo . vmapObjects )
2013-04-18 23:35:02 +02:00
{
b . setLength ( 0 ) ;
2013-09-23 19:42:48 +02:00
if ( vInfo . osm ) {
printOsmMapDetails ( obj , b ) ;
try {
printToFile ( b . toString ( ) ) ;
} catch ( IOException e ) {
throw new RuntimeException ( e ) ;
2013-04-18 23:35:02 +02:00
}
2013-09-23 19:42:48 +02:00
} else {
printMapDetails ( obj , b ) ;
println ( b . toString ( ) ) ;
2013-04-18 23:35:02 +02:00
}
}
return false ;
}
@Override
public boolean isCancelled ( ) {
return false ;
}
} ) ;
index . searchMapIndex ( req , mapIndex ) ;
2013-09-23 19:42:48 +02:00
if ( vInfo . osm ) {
printToFile ( " </osm > \ n " ) ;
}
2013-04-18 23:35:02 +02:00
println ( " \ tTotal map objects: " + mapObjectsCounter . value ) ;
}
2013-09-23 19:42:48 +02:00
private static void printMapDetails ( BinaryMapDataObject obj , StringBuilder b ) {
boolean multipolygon = obj . getPolygonInnerCoordinates ( ) ! = null & & obj . getPolygonInnerCoordinates ( ) . length > 0 ;
if ( multipolygon ) {
b . append ( " Multipolygon " ) ;
} else {
b . append ( obj . area ? " Area " : ( obj . getPointsLength ( ) > 1 ? " Way " : " Point " ) ) ;
}
int [ ] types = obj . getTypes ( ) ;
b . append ( " types [ " ) ;
for ( int j = 0 ; j < types . length ; j + + ) {
if ( j > 0 ) {
b . append ( " , " ) ;
}
TagValuePair pair = obj . getMapIndex ( ) . decodeType ( types [ j ] ) ;
if ( pair = = null ) {
System . err . println ( " Type " + types [ j ] + " was not found " ) ;
continue ;
// throw new NullPointerException("Type " + obj.getAdditionalTypes()[j] + "was not found");
}
b . append ( pair . toSimpleString ( ) + " ( " + types [ j ] + " ) " ) ;
}
b . append ( " ] " ) ;
if ( obj . getAdditionalTypes ( ) ! = null & & obj . getAdditionalTypes ( ) . length > 0 ) {
b . append ( " add_types [ " ) ;
for ( int j = 0 ; j < obj . getAdditionalTypes ( ) . length ; j + + ) {
if ( j > 0 ) {
b . append ( " , " ) ;
}
TagValuePair pair = obj . getMapIndex ( ) . decodeType ( obj . getAdditionalTypes ( ) [ j ] ) ;
if ( pair = = null ) {
System . err . println ( " Type " + obj . getAdditionalTypes ( ) [ j ] + " was not found " ) ;
continue ;
// throw new NullPointerException("Type " + obj.getAdditionalTypes()[j] + "was not found");
}
b . append ( pair . toSimpleString ( ) + " ( " + obj . getAdditionalTypes ( ) [ j ] + " ) " ) ;
}
b . append ( " ] " ) ;
}
TIntObjectHashMap < String > names = obj . getObjectNames ( ) ;
if ( names ! = null & & ! names . isEmpty ( ) ) {
b . append ( " Names [ " ) ;
int [ ] keys = names . keys ( ) ;
for ( int j = 0 ; j < keys . length ; j + + ) {
if ( j > 0 ) {
b . append ( " , " ) ;
}
TagValuePair pair = obj . getMapIndex ( ) . decodeType ( keys [ j ] ) ;
if ( pair = = null ) {
throw new NullPointerException ( " Type " + keys [ j ] + " was not found " ) ;
}
b . append ( pair . toSimpleString ( ) + " ( " + keys [ j ] + " ) " ) ;
b . append ( " - " ) . append ( names . get ( keys [ j ] ) ) ;
}
b . append ( " ] " ) ;
}
b . append ( " id " ) . append ( ( obj . getId ( ) > > 1 ) ) ;
b . append ( " lat/lon : " ) ;
for ( int i = 0 ; i < obj . getPointsLength ( ) ; i + + ) {
float x = ( float ) MapUtils . get31LongitudeX ( obj . getPoint31XTile ( i ) ) ;
float y = ( float ) MapUtils . get31LatitudeY ( obj . getPoint31YTile ( i ) ) ;
b . append ( x ) . append ( " / " ) . append ( y ) . append ( " , " ) ;
}
}
private static int OSM_ID = 1 ;
private void printOsmMapDetails ( BinaryMapDataObject obj , StringBuilder b ) {
boolean multipolygon = obj . getPolygonInnerCoordinates ( ) ! = null & & obj . getPolygonInnerCoordinates ( ) . length > 0 ;
boolean point = obj . getPointsLength ( ) = = 1 ;
StringBuilder tags = new StringBuilder ( ) ;
int [ ] types = obj . getTypes ( ) ;
for ( int j = 0 ; j < types . length ; j + + ) {
TagValuePair pair = obj . getMapIndex ( ) . decodeType ( types [ j ] ) ;
if ( pair = = null ) {
throw new NullPointerException ( " Type " + types [ j ] + " was not found " ) ;
}
tags . append ( " \ t<tag k=' " ) . append ( pair . tag ) . append ( " ' v=' " ) . append ( pair . value ) . append ( " ' /> \ n " ) ;
}
if ( obj . getAdditionalTypes ( ) ! = null & & obj . getAdditionalTypes ( ) . length > 0 ) {
for ( int j = 0 ; j < obj . getAdditionalTypes ( ) . length ; j + + ) {
TagValuePair pair = obj . getMapIndex ( ) . decodeType ( obj . getAdditionalTypes ( ) [ j ] ) ;
if ( pair = = null ) {
throw new NullPointerException ( " Type " + obj . getAdditionalTypes ( ) [ j ] + " was not found " ) ;
}
tags . append ( " \ t<tag k=' " ) . append ( pair . tag ) . append ( " ' v=' " ) . append ( pair . value ) . append ( " ' /> \ n " ) ;
}
}
TIntObjectHashMap < String > names = obj . getObjectNames ( ) ;
if ( names ! = null & & ! names . isEmpty ( ) ) {
int [ ] keys = names . keys ( ) ;
for ( int j = 0 ; j < keys . length ; j + + ) {
TagValuePair pair = obj . getMapIndex ( ) . decodeType ( keys [ j ] ) ;
if ( pair = = null ) {
throw new NullPointerException ( " Type " + keys [ j ] + " was not found " ) ;
}
String name = names . get ( keys [ j ] ) ;
name = name . replace ( " ' " , " ' " ) ;
2013-09-24 18:53:48 +02:00
name = name . replace ( " & " , " & " ) ;
2013-09-23 19:42:48 +02:00
tags . append ( " \ t<tag k=' " ) . append ( pair . tag ) . append ( " ' v=' " ) . append ( name ) . append ( " ' /> \ n " ) ;
}
}
tags . append ( " \ t<tag k= \ ' " ) . append ( " original_id " ) . append ( " ' v=' " ) . append ( obj . getId ( ) > > 1 ) . append ( " '/> \ n " ) ;
if ( point ) {
float lon = ( float ) MapUtils . get31LongitudeX ( obj . getPoint31XTile ( 0 ) ) ;
float lat = ( float ) MapUtils . get31LatitudeY ( obj . getPoint31YTile ( 0 ) ) ;
b . append ( " <node id = ' " + OSM_ID + + + " ' lat=' " + lat + " ' lon=' " + lon + " ' > \ n " ) ;
b . append ( tags ) ;
b . append ( " </node> \ n " ) ;
} else {
TLongArrayList innerIds = new TLongArrayList ( ) ;
TLongArrayList ids = new TLongArrayList ( ) ;
for ( int i = 0 ; i < obj . getPointsLength ( ) ; i + + ) {
float lon = ( float ) MapUtils . get31LongitudeX ( obj . getPoint31XTile ( i ) ) ;
float lat = ( float ) MapUtils . get31LatitudeY ( obj . getPoint31YTile ( i ) ) ;
int id = OSM_ID + + ;
b . append ( " \ t<node id = ' " + id + " ' lat=' " + lat + " ' lon=' " + lon + " ' /> \ n " ) ;
ids . add ( id ) ;
}
long outerId = printWay ( ids , b , multipolygon ? null : tags ) ;
if ( multipolygon ) {
int [ ] [ ] polygonInnerCoordinates = obj . getPolygonInnerCoordinates ( ) ;
for ( int j = 0 ; j < polygonInnerCoordinates . length ; j + + ) {
ids . clear ( ) ; ;
for ( int i = 0 ; i < polygonInnerCoordinates [ j ] . length ; i + = 2 ) {
float lon = ( float ) MapUtils . get31LongitudeX ( polygonInnerCoordinates [ j ] [ i ] ) ;
float lat = ( float ) MapUtils . get31LatitudeY ( polygonInnerCoordinates [ j ] [ i + 1 ] ) ;
int id = OSM_ID + + ;
b . append ( " <node id = ' " + id + " ' lat=' " + lat + " ' lon=' " + lon + " ' /> \ n " ) ;
ids . add ( id ) ;
}
innerIds . add ( printWay ( ids , b , null ) ) ;
}
int id = OSM_ID + + ;
b . append ( " <relation id = ' " + id + " '> \ n " ) ;
b . append ( tags ) ;
b . append ( " \ t<member type='way' role='outer' ref= ' " + outerId + " '/> \ n " ) ;
TLongIterator it = innerIds . iterator ( ) ;
while ( it . hasNext ( ) ) {
long ref = it . next ( ) ;
b . append ( " <member type='way' role='inner' ref= ' " + ref + " '/> \ n " ) ;
}
b . append ( " </relation> \ n " ) ;
}
}
}
private long printWay ( TLongArrayList ids , StringBuilder b , StringBuilder tags ) {
int id = OSM_ID + + ;
b . append ( " <way id = ' " + id + " '> \ n " ) ;
if ( tags ! = null ) {
b . append ( tags ) ;
}
TLongIterator it = ids . iterator ( ) ;
while ( it . hasNext ( ) ) {
long ref = it . next ( ) ;
b . append ( " \ t<nd ref = ' " + ref + " '/> \ n " ) ;
}
b . append ( " </way> \ n " ) ;
return id ;
}
private void printPOIDetailInfo ( VerboseInfo verbose , BinaryMapIndexReader index , PoiRegion p ) throws IOException {
2013-04-18 23:35:02 +02:00
SearchRequest < Amenity > req = BinaryMapIndexReader . buildSearchPoiRequest (
MapUtils . get31TileNumberX ( verbose . lonleft ) ,
MapUtils . get31TileNumberX ( verbose . lonright ) ,
MapUtils . get31TileNumberY ( verbose . lattop ) ,
MapUtils . get31TileNumberY ( verbose . latbottom ) ,
verbose . getZoom ( ) ,
new SearchPoiTypeFilter ( ) {
@Override
public boolean accept ( AmenityType type , String subcategory ) {
return true ;
}
2013-11-24 19:22:07 +01:00
2013-04-18 23:35:02 +02:00
} ,
new ResultMatcher < Amenity > ( ) {
@Override
public boolean publish ( Amenity object ) {
2013-11-24 17:14:36 +01:00
println ( object . getType ( ) . toString ( ) + " : " + object . getSubType ( ) + " " + object . getName ( ) + " " + object . getLocation ( ) + " id= " + ( object . getId ( ) > > 1 ) + " " +
object . getAdditionalInfo ( ) ) ;
2013-04-18 23:35:02 +02:00
return false ;
}
@Override
public boolean isCancelled ( ) {
return false ;
}
} ) ;
index . initCategories ( p ) ;
println ( " \ tRegion: " + p . name ) ;
println ( " \ t \ tBounds " + formatLatBounds ( p . getLeftLongitude ( ) , p . getRightLongitude ( ) ,
p . getTopLatitude ( ) , p . getBottomLatitude ( ) ) ) ;
println ( " \ t \ tCategories: " ) ;
for ( int i = 0 ; i < p . categories . size ( ) ; i + + ) {
println ( " \ t \ t \ t " + p . categories . get ( i ) ) ;
for ( int j = 0 ; j < p . subcategories . get ( i ) . size ( ) ; j + + )
println ( " \ t \ t \ t \ t " + p . subcategories . get ( i ) . get ( j ) ) ;
}
2013-11-24 19:22:07 +01:00
println ( " \ t \ tSubtypes: " ) ;
for ( int i = 0 ; i < p . subTypes . size ( ) ; i + + ) {
PoiSubType st = p . subTypes . get ( i ) ;
println ( " \ t \ t \ t " + st . name + " " + ( st . text ? " text " : ( " encoded " + st . possibleValues . size ( ) ) ) ) ;
}
2013-04-18 23:35:02 +02:00
req . poiTypeFilter = null ; //TODO: for test only
2013-11-24 21:29:50 +01:00
// index.searchPoi(p, req);
2013-04-18 23:35:02 +02:00
}
2013-09-23 19:42:48 +02:00
public void printUsage ( String warning ) {
2013-04-18 23:35:02 +02:00
if ( warning ! = null ) {
println ( warning ) ;
}
println ( " Inspector is console utility for working with binary indexes of OsmAnd. " ) ;
println ( " It allows print info about file, extract parts and merge indexes. " ) ;
2013-09-23 19:42:48 +02:00
println ( " \ nUsage for print info : inspector [-vaddress] [-vstreetgroups] [-vstreets] [-vbuildings] [-vintersections] [-vmap] [-vmapobjects] [-osm] [-vpoi] [-vtransport] [-zoom=Zoom] [-bbox=LeftLon,TopLat,RightLon,BottomLan] [file] " ) ;
2013-04-18 23:35:02 +02:00
println ( " Prints information about [file] binary index of OsmAnd. " ) ;
println ( " -v.. more verbouse output (like all cities and their streets or all map objects with tags/values and coordinates) " ) ;
println ( " \ nUsage for combining indexes : inspector -c file_to_create (file_from_extract ((+|-)parts_to_extract)? )* " ) ;
println ( " \ tCreate new file of extracted parts from input file. [parts_to_extract] could be parts to include or exclude. " ) ;
println ( " Example : inspector -c output_file input_file +1,2,3 \ n \ tExtracts 1, 2, 3 parts (could be find in print info) " ) ;
println ( " Example : inspector -c output_file input_file -2,3 \ n \ tExtracts all parts excluding 2, 3 " ) ;
println ( " Example : inspector -c output_file input_file1 input_file2 input_file3 \ n \ tSimply combine 3 files " ) ;
println ( " Example : inspector -c output_file input_file1 input_file2 -4 \ n \ tCombine all parts of 1st file and all parts excluding 4th part of 2nd file " ) ;
}
}