Improve binary inspecctor to represent more information about binary maps in verbose mode
This commit is contained in:
parent
244123588e
commit
03f30de16c
2 changed files with 193 additions and 41 deletions
|
@ -1,5 +1,8 @@
|
||||||
package net.osmand.binary;
|
package net.osmand.binary;
|
||||||
|
|
||||||
|
|
||||||
|
import gnu.trove.list.array.TIntArrayList;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -13,14 +16,19 @@ import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.osmand.ResultMatcher;
|
||||||
import net.osmand.binary.BinaryMapAddressReaderAdapter.AddressRegion;
|
import net.osmand.binary.BinaryMapAddressReaderAdapter.AddressRegion;
|
||||||
import net.osmand.binary.BinaryMapIndexReader.MapIndex;
|
import net.osmand.binary.BinaryMapIndexReader.MapIndex;
|
||||||
import net.osmand.binary.BinaryMapIndexReader.MapRoot;
|
import net.osmand.binary.BinaryMapIndexReader.MapRoot;
|
||||||
|
import net.osmand.binary.BinaryMapIndexReader.SearchFilter;
|
||||||
|
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
||||||
import net.osmand.binary.BinaryMapPoiReaderAdapter.PoiRegion;
|
import net.osmand.binary.BinaryMapPoiReaderAdapter.PoiRegion;
|
||||||
import net.osmand.binary.BinaryMapTransportReaderAdapter.TransportIndex;
|
import net.osmand.binary.BinaryMapTransportReaderAdapter.TransportIndex;
|
||||||
import net.osmand.data.Building;
|
import net.osmand.data.Building;
|
||||||
import net.osmand.data.City;
|
import net.osmand.data.City;
|
||||||
|
import net.osmand.data.MapObject;
|
||||||
import net.osmand.data.Street;
|
import net.osmand.data.Street;
|
||||||
|
import net.osmand.osm.MapRenderingTypes;
|
||||||
import net.osmand.osm.MapUtils;
|
import net.osmand.osm.MapUtils;
|
||||||
|
|
||||||
import com.google.protobuf.CodedOutputStream;
|
import com.google.protobuf.CodedOutputStream;
|
||||||
|
@ -56,6 +64,65 @@ public class BinaryInspector {
|
||||||
private static void print(String s) {
|
private static void print(String s) {
|
||||||
System.out.print(s);
|
System.out.print(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static class VerboseInfo {
|
||||||
|
boolean vaddress;
|
||||||
|
boolean vtransport;
|
||||||
|
boolean vpoi;
|
||||||
|
boolean vmap;
|
||||||
|
double lattop = 85;
|
||||||
|
double latbottom = -85;
|
||||||
|
double lonleft = -180;
|
||||||
|
double lonright = 180;
|
||||||
|
int zoom = 15;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VerboseInfo(String[] params){
|
||||||
|
for(int i=0;i<params.length;i++){
|
||||||
|
if(params[i].equals("-vaddress")){
|
||||||
|
vaddress = true;
|
||||||
|
} else if(params[i].equals("-vmap")){
|
||||||
|
vmap = true;
|
||||||
|
} else if(params[i].equals("-vpoi")){
|
||||||
|
vpoi = true;
|
||||||
|
} 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();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void inspector(String[] args) throws IOException {
|
public static void inspector(String[] args) throws IOException {
|
||||||
if(args == null || args.length == 0){
|
if(args == null || args.length == 0){
|
||||||
|
@ -63,10 +130,10 @@ public class BinaryInspector {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String f = args[0];
|
String f = args[0];
|
||||||
if(f.charAt(0) == '-'){
|
if (f.charAt(0) == '-') {
|
||||||
// command
|
// command
|
||||||
if(f.equals("-c") || f.equals("-combine")) {
|
if (f.equals("-c") || f.equals("-combine")) {
|
||||||
if(args.length < 4){
|
if (args.length < 4) {
|
||||||
printUsage("Too few parameters to extract (require minimum 4)");
|
printUsage("Too few parameters to extract (require minimum 4)");
|
||||||
} else {
|
} else {
|
||||||
Map<File, String> parts = new LinkedHashMap<File, String>();
|
Map<File, String> parts = new LinkedHashMap<File, String>();
|
||||||
|
@ -77,29 +144,30 @@ public class BinaryInspector {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
parts.put(file, null);
|
parts.put(file, null);
|
||||||
if(i < args.length - 1){
|
if (i < args.length - 1) {
|
||||||
if(args[i+1].startsWith("-") || args[i+1].startsWith("+")){
|
if (args[i + 1].startsWith("-") || args[i + 1].startsWith("+")) {
|
||||||
parts.put(file, args[i+1]);
|
parts.put(file, args[i + 1]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<Float> extracted = combineParts(new File(args[1]), parts);
|
List<Float> extracted = combineParts(new File(args[1]), parts);
|
||||||
if(extracted != null){
|
if (extracted != null) {
|
||||||
println("\n"+extracted.size()+" parts were successfully extracted to " + args[1]);
|
println("\n" + extracted.size() + " parts were successfully extracted to " + args[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (f.equals("-v")) {
|
} else if (f.startsWith("-v")) {
|
||||||
if (args.length < 2) {
|
if (args.length < 2) {
|
||||||
printUsage("Missing file parameter");
|
printUsage("Missing file parameter");
|
||||||
} else {
|
} else {
|
||||||
printFileInformation(args[1],true);
|
VerboseInfo vinfo = new VerboseInfo(args);
|
||||||
|
printFileInformation(args[args.length - 1], vinfo);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printUsage("Unknown command : "+ f);
|
printUsage("Unknown command : " + f);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printFileInformation(f,false);
|
printFileInformation(f, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static final void writeInt(CodedOutputStream ous, int v) throws IOException {
|
public static final void writeInt(CodedOutputStream ous, int v) throws IOException {
|
||||||
|
@ -297,7 +365,7 @@ public class BinaryInspector {
|
||||||
return format.format(new Object[]{l, t, r, b});
|
return format.format(new Object[]{l, t, r, b});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void printFileInformation(String fileName,boolean verbose) throws IOException {
|
public static void printFileInformation(String fileName,VerboseInfo verbose) throws IOException {
|
||||||
File file = new File(fileName);
|
File file = new File(fileName);
|
||||||
if(!file.exists()){
|
if(!file.exists()){
|
||||||
println("Binary OsmAnd index " + fileName + " was not found.");
|
println("Binary OsmAnd index " + fileName + " was not found.");
|
||||||
|
@ -306,7 +374,25 @@ public class BinaryInspector {
|
||||||
printFileInformation(file,verbose);
|
printFileInformation(file,verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void printFileInformation(File file, boolean verbose) throws IOException {
|
private static void formatPoint(BinaryMapDataObject o, int ind, StringBuilder b){
|
||||||
|
b.append((float)MapUtils.get31LongitudeX(o.getPoint31XTile(ind))).append(",").append((float)MapUtils.get31LatitudeY(o.getPoint31YTile(ind)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void formatTags(BinaryMapDataObject o, StringBuilder b){
|
||||||
|
for (int i = 0; i < o.getTypes().length; i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
b.append(", ");
|
||||||
|
}
|
||||||
|
b.append(o.getTagValue(i).tag + "=" + o.getTagValue(i).value);
|
||||||
|
if ((o.getTypes()[i] & 3) == MapRenderingTypes.MULTY_POLYGON_TYPE) {
|
||||||
|
b.append("(multipolygon)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void printFileInformation(File file, VerboseInfo verbose) throws IOException {
|
||||||
RandomAccessFile r = new RandomAccessFile(file.getAbsolutePath(), "r");
|
RandomAccessFile r = new RandomAccessFile(file.getAbsolutePath(), "r");
|
||||||
try {
|
try {
|
||||||
BinaryMapIndexReader index = new BinaryMapIndexReader(r);
|
BinaryMapIndexReader index = new BinaryMapIndexReader(r);
|
||||||
|
@ -339,31 +425,73 @@ public class BinaryInspector {
|
||||||
formatBounds(mi.getLeft(), mi.getRight(), mi.getTop(), mi.getBottom()),
|
formatBounds(mi.getLeft(), mi.getRight(), mi.getTop(), mi.getBottom()),
|
||||||
i, j++));
|
i, j++));
|
||||||
}
|
}
|
||||||
} else if (p instanceof AddressRegion && verbose) {
|
if((verbose != null && verbose.isVmap())){
|
||||||
|
final StringBuilder b = new StringBuilder();
|
||||||
|
SearchRequest<BinaryMapDataObject> req = BinaryMapIndexReader.buildSearchRequest(MapUtils.get31TileNumberX(verbose.lonleft),
|
||||||
|
MapUtils.get31TileNumberX(verbose.lonright),
|
||||||
|
MapUtils.get31TileNumberY(verbose.lattop),
|
||||||
|
MapUtils.get31TileNumberY(verbose.latbottom), verbose.getZoom(),
|
||||||
|
new SearchFilter() {
|
||||||
|
@Override
|
||||||
|
public boolean accept(TIntArrayList types, MapIndex index) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new ResultMatcher<BinaryMapDataObject>() {
|
||||||
|
@Override
|
||||||
|
public boolean publish(BinaryMapDataObject object) {
|
||||||
|
boolean way = object.getPointsLength() > 1;
|
||||||
|
b.setLength(0);
|
||||||
|
b.append(way ? "Way " : "Point ");
|
||||||
|
if(object.getName() != null){
|
||||||
|
b.append(object.getName());
|
||||||
|
}
|
||||||
|
b.append(" ").append((object.getId() >> 1)).append(" ");
|
||||||
|
formatTags(object, b);
|
||||||
|
b.append(" ");
|
||||||
|
for (int i = 0; i < object.getPointsLength(); i++) {
|
||||||
|
b.append(" ");
|
||||||
|
formatPoint(object, i, b);
|
||||||
|
}
|
||||||
|
println(b.toString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
index.searchMapIndex(req);
|
||||||
|
}
|
||||||
|
} else if (p instanceof AddressRegion && (verbose != null && verbose.isVaddress())) {
|
||||||
for(String region : index.getRegionNames()){
|
for(String region : index.getRegionNames()){
|
||||||
println("\tRegion:" + region);
|
println("\tRegion:" + region);
|
||||||
for (City c : index.getCities(region, null)) {
|
for (City c : index.getCities(region, null)) {
|
||||||
index.preloadStreets(c, null);
|
index.preloadStreets(c, null);
|
||||||
println("\t\tCity:" + c.getName());
|
println("\t\tCity:" + c.getName() + getId(c));
|
||||||
for (Street t : c.getStreets()) {
|
for (Street t : c.getStreets()) {
|
||||||
print("\t\t\t" + t.getName());
|
if (verbose.contains(t)) {
|
||||||
index.preloadBuildings(t, null);
|
print("\t\t\t" + t.getName() + getId(t));
|
||||||
List<Building> buildings = t.getBuildings();
|
index.preloadBuildings(t, null);
|
||||||
if (buildings != null && !buildings.isEmpty()) {
|
List<Building> buildings = t.getBuildings();
|
||||||
print(" (");
|
if (buildings != null && !buildings.isEmpty()) {
|
||||||
for (Building b : buildings) {
|
print("\t\t\t\t (");
|
||||||
print(b.getName() + ",");
|
for (Building b : buildings) {
|
||||||
|
print(b.getName() + ",");
|
||||||
|
}
|
||||||
|
print(")");
|
||||||
}
|
}
|
||||||
print(")");
|
println("");
|
||||||
}
|
}
|
||||||
println("");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (City c : index.getVillages(region, null,null,false)) {
|
for (City c : index.getVillages(region, null,null,false)) {
|
||||||
index.preloadStreets(c, null);
|
if (verbose.contains(c)) {
|
||||||
println("\t\tVillage:" + c.getName());
|
index.preloadStreets(c, null);
|
||||||
for (Street t : c.getStreets()) {
|
println("\t\tVillage:" + c.getName() + getId(c));
|
||||||
println("\t\t\t" + t.getName());
|
for (Street t : c.getStreets()) {
|
||||||
|
println("\t\t\t" + t.getName() + getId(t));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -378,6 +506,10 @@ public class BinaryInspector {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String getId(MapObject o ){
|
||||||
|
return " " + (o.getId() >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
public static void printUsage(String warning) {
|
public static void printUsage(String warning) {
|
||||||
if(warning != null){
|
if(warning != null){
|
||||||
|
@ -385,9 +517,9 @@ public class BinaryInspector {
|
||||||
}
|
}
|
||||||
println("Inspector is console utility for working with binary indexes of OsmAnd.");
|
println("Inspector is console utility for working with binary indexes of OsmAnd.");
|
||||||
println("It allows print info about file, extract parts and merge indexes.");
|
println("It allows print info about file, extract parts and merge indexes.");
|
||||||
println("\nUsage for print info : inspector [-v] [file]");
|
println("\nUsage for print info : inspector [-vaddress] [-vmap] [-vpoi] [-vtransport] [-zoom=Zoom] [-bbox=LeftLon,TopLat,RightLon,BottomLan] [file]");
|
||||||
println(" Prints information about [file] binary index of OsmAnd.");
|
println(" Prints information about [file] binary index of OsmAnd.");
|
||||||
println(" -v more verbouse output (like all cities and their streets)");
|
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("\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("\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 +1,2,3\n\tExtracts 1, 2, 3 parts (could be find in print info)");
|
||||||
|
|
|
@ -789,6 +789,7 @@ public class BinaryMapIndexReader {
|
||||||
int ctop = 0;
|
int ctop = 0;
|
||||||
int cbottom = 0;
|
int cbottom = 0;
|
||||||
req.numberOfReadSubtrees++;
|
req.numberOfReadSubtrees++;
|
||||||
|
List<BinaryMapDataObject> tempResults = null;
|
||||||
while(true){
|
while(true){
|
||||||
if(req.isCancelled()){
|
if(req.isCancelled()){
|
||||||
return;
|
return;
|
||||||
|
@ -806,6 +807,11 @@ public class BinaryMapIndexReader {
|
||||||
}
|
}
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case 0:
|
case 0:
|
||||||
|
if (tempResults != null) {
|
||||||
|
for (int i = 0; i < tempResults.size(); i++) {
|
||||||
|
req.publish(tempResults.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
case OsmandOdb.MapTree.BOTTOM_FIELD_NUMBER :
|
case OsmandOdb.MapTree.BOTTOM_FIELD_NUMBER :
|
||||||
cbottom = codedIS.readSInt32() + pbottom;
|
cbottom = codedIS.readSInt32() + pbottom;
|
||||||
|
@ -831,8 +837,10 @@ public class BinaryMapIndexReader {
|
||||||
}
|
}
|
||||||
BinaryMapDataObject mapObject = readMapDataObject(cleft, cright, ctop, cbottom, req, root);
|
BinaryMapDataObject mapObject = readMapDataObject(cleft, cright, ctop, cbottom, req, root);
|
||||||
if(mapObject != null){
|
if(mapObject != null){
|
||||||
req.searchResults.add(mapObject);
|
if(tempResults == null){
|
||||||
|
tempResults = new ArrayList<BinaryMapDataObject>();
|
||||||
|
}
|
||||||
|
tempResults.add(mapObject);
|
||||||
}
|
}
|
||||||
codedIS.popLimit(oldLimit);
|
codedIS.popLimit(oldLimit);
|
||||||
break;
|
break;
|
||||||
|
@ -851,9 +859,9 @@ public class BinaryMapIndexReader {
|
||||||
case OsmandOdb.MapTree.BASEID_FIELD_NUMBER :
|
case OsmandOdb.MapTree.BASEID_FIELD_NUMBER :
|
||||||
case OsmandOdb.MapTree.OLDBASEID_FIELD_NUMBER :
|
case OsmandOdb.MapTree.OLDBASEID_FIELD_NUMBER :
|
||||||
long baseId = codedIS.readUInt64();
|
long baseId = codedIS.readUInt64();
|
||||||
if (lastIndexResult != -1) {
|
if (tempResults != null) {
|
||||||
for (int i = lastIndexResult; i < req.searchResults.size(); i++) {
|
for (int i = 0; i < tempResults.size(); i++) {
|
||||||
BinaryMapDataObject rs = req.searchResults.get(i);
|
BinaryMapDataObject rs = tempResults.get(i);
|
||||||
rs.id += baseId;
|
rs.id += baseId;
|
||||||
if (rs.restrictions != null) {
|
if (rs.restrictions != null) {
|
||||||
for (int j = 0; j < rs.restrictions.length; j++) {
|
for (int j = 0; j < rs.restrictions.length; j++) {
|
||||||
|
@ -870,9 +878,9 @@ public class BinaryMapIndexReader {
|
||||||
List<String> stringTable = readStringTable();
|
List<String> stringTable = readStringTable();
|
||||||
codedIS.popLimit(oldLimit);
|
codedIS.popLimit(oldLimit);
|
||||||
|
|
||||||
if (lastIndexResult != -1) {
|
if (tempResults != null) {
|
||||||
for (int i = lastIndexResult; i < req.searchResults.size(); i++) {
|
for (int i = 0; i < tempResults.size(); i++) {
|
||||||
BinaryMapDataObject rs = req.searchResults.get(i);
|
BinaryMapDataObject rs = tempResults.get(i);
|
||||||
if (rs.stringId != -1) {
|
if (rs.stringId != -1) {
|
||||||
rs.name = stringTable.get(rs.stringId);
|
rs.name = stringTable.get(rs.stringId);
|
||||||
}
|
}
|
||||||
|
@ -1085,6 +1093,18 @@ public class BinaryMapIndexReader {
|
||||||
return poiIndexes;
|
return poiIndexes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static SearchRequest<BinaryMapDataObject> buildSearchRequest(int sleft, int sright, int stop, int sbottom, int zoom,
|
||||||
|
SearchFilter searchFilter, ResultMatcher<BinaryMapDataObject> matcher) {
|
||||||
|
SearchRequest<BinaryMapDataObject> request = new SearchRequest<BinaryMapDataObject>();
|
||||||
|
request.left = sleft;
|
||||||
|
request.right = sright;
|
||||||
|
request.top = stop;
|
||||||
|
request.bottom = sbottom;
|
||||||
|
request.zoom = zoom;
|
||||||
|
request.resultMatcher = matcher;
|
||||||
|
request.searchFilter = searchFilter;
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
public static SearchRequest<BinaryMapDataObject> buildSearchRequest(int sleft, int sright, int stop, int sbottom, int zoom, SearchFilter searchFilter){
|
public static SearchRequest<BinaryMapDataObject> buildSearchRequest(int sleft, int sright, int stop, int sbottom, int zoom, SearchFilter searchFilter){
|
||||||
SearchRequest<BinaryMapDataObject> request = new SearchRequest<BinaryMapDataObject>();
|
SearchRequest<BinaryMapDataObject> request = new SearchRequest<BinaryMapDataObject>();
|
||||||
|
|
Loading…
Reference in a new issue