OsmAnd/OsmAnd-java/src/net/osmand/binary/BinaryInspector.java

1288 lines
44 KiB
Java
Raw Normal View History

package net.osmand.binary;
import gnu.trove.iterator.TIntObjectIterator;
2013-09-23 19:42:48 +02:00
import gnu.trove.iterator.TLongIterator;
import gnu.trove.list.array.TIntArrayList;
2013-09-23 19:42:48 +02:00
import gnu.trove.list.array.TLongArrayList;
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;
import java.text.DecimalFormat;
import java.text.MessageFormat;
import java.util.ArrayList;
2016-08-23 22:53:12 +02:00
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
2016-08-23 22:53:12 +02:00
import java.util.Map.Entry;
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.MapObjectStat;
import net.osmand.binary.BinaryMapIndexReader.MapRoot;
import net.osmand.binary.BinaryMapIndexReader.SearchFilter;
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;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteSubregion;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule;
import net.osmand.binary.BinaryMapTransportReaderAdapter.TransportIndex;
import net.osmand.data.Amenity;
import net.osmand.data.Building;
import net.osmand.data.City;
import net.osmand.data.MapObject;
import net.osmand.data.Street;
2016-08-23 22:53:12 +02:00
import net.osmand.data.TransportRoute;
import net.osmand.data.TransportStop;
2016-07-28 01:28:22 +02:00
import net.osmand.osm.MapRenderingTypes;
import net.osmand.util.MapUtils;
import com.google.protobuf.CodedOutputStream;
import com.google.protobuf.WireFormat;
public class BinaryInspector {
2016-05-17 14:20:56 +02:00
public static final int BUFFER_SIZE = 1 << 20;
2016-04-26 22:59:47 +02:00
public static final int SHIFT_ID = 6;
2013-09-23 19:42:48 +02:00
private VerboseInfo vInfo;
public static void main(String[] args) throws IOException {
2013-09-23 19:42:48 +02:00
BinaryInspector in = new BinaryInspector();
2016-05-30 23:21:45 +02:00
if (args == null || args.length == 0) {
BinaryInspector.printUsage(null);
return;
}
// test cases show info
2016-05-07 18:01:34 +02:00
if ("test".equals(args[0])) {
2016-08-23 22:53:12 +02:00
in.inspector(new String[] {
// "-vpoi",
2016-11-04 12:19:34 +01:00
"-vmap", "-vmapobjects", // "-vmapcoordinates",
2016-08-23 22:53:12 +02:00
// "-vrouting",
2016-09-16 10:35:33 +02:00
// "-vtransport",
2016-11-04 12:19:34 +01:00
// "-vaddress", "-vcities","-vstreetgroups",
2016-07-28 01:09:45 +02:00
// "-vstreets", "-vbuildings", "-vintersections",
// "-lang=ru",
// "-bbox=4.8486,52.3084,4.8747,52.2970",
2016-07-31 15:16:10 +02:00
// "-osm="+System.getProperty("maps.dir")+"/map.obf.osm",
2016-09-16 10:35:33 +02:00
System.getProperty("maps.dir")+"/Map.obf"
2016-05-07 18:01:34 +02:00
});
2014-01-20 01:05:03 +01:00
} else {
in.inspector(args);
}
}
2013-09-23 19:42:48 +02:00
private void printToFile(String s) throws IOException {
2016-05-17 14:20:56 +02:00
if (vInfo.osmOut != null) {
2013-09-23 19:42:48 +02:00
vInfo.osmOut.write(s.getBytes());
} else {
System.out.println(s);
}
}
2016-05-17 14:20:56 +02:00
2013-09-23 19:42:48 +02:00
private void println(String s) {
2016-05-17 14:20:56 +02:00
if (vInfo != null && vInfo.osm && vInfo.osmOut == null) {
2013-09-23 19:42:48 +02:00
// ignore
} else {
System.out.println(s);
2013-09-23 19:42:48 +02:00
}
}
2013-09-23 19:42:48 +02:00
private void print(String s) {
2016-05-17 14:20:56 +02:00
if (vInfo != null && vInfo.osm && vInfo.osmOut == null) {
2013-09-23 19:42:48 +02:00
// ignore
} else {
System.out.print(s);
2013-09-23 19:42:48 +02:00
}
}
2016-05-17 14:20:56 +02:00
protected static class VerboseInfo {
boolean vaddress;
boolean vcities;
boolean vcitynames;
boolean vstreetgroups;
boolean vstreets;
boolean vbuildings;
boolean vintersections;
boolean vtransport;
boolean vpoi;
boolean vmap;
boolean vrouting;
boolean vmapObjects;
2015-07-28 01:36:53 +02:00
boolean vmapCoordinates;
boolean vstats;
2013-09-23 19:42:48 +02:00
boolean osm;
FileOutputStream osmOut = null;
double lattop = 85;
double latbottom = -85;
2016-11-04 12:19:34 +01:00
double lonleft = -179.9;
double lonright = 179.9;
2016-05-17 10:20:39 +02:00
String lang = null;
2016-11-04 12:19:34 +01:00
int zoom = 15;
2016-05-17 14:20:56 +02:00
public boolean isVaddress() {
return vaddress;
}
2016-05-17 14:20:56 +02:00
public int getZoom() {
return zoom;
}
2016-05-17 14:20:56 +02:00
public boolean isVmap() {
return vmap;
}
2016-05-17 14:20:56 +02:00
public boolean isVrouting() {
return vrouting;
}
2016-05-17 14:20:56 +02:00
public boolean isVpoi() {
return vpoi;
}
2016-05-17 14:20:56 +02:00
public boolean isVtransport() {
return vtransport;
}
2016-05-17 14:20:56 +02:00
public boolean isVStats() {
return vstats;
}
2016-05-17 14:20:56 +02:00
2013-09-23 19:42:48 +02:00
public VerboseInfo(String[] params) throws FileNotFoundException {
2016-05-17 14:20:56 +02:00
for (int i = 0; i < params.length; i++) {
if (params[i].equals("-vaddress")) {
vaddress = true;
2016-05-17 14:20:56 +02:00
} else if (params[i].equals("-vstreets")) {
vstreets = true;
2016-05-17 14:20:56 +02:00
} else if (params[i].equals("-vstreetgroups")) {
vstreetgroups = true;
2016-05-17 14:20:56 +02:00
} else if (params[i].equals("-vcities")) {
vcities = true;
} else if (params[i].equals("-vcitynames")) {
vcitynames = true;
2016-05-17 14:20:56 +02:00
} else if (params[i].equals("-vbuildings")) {
vbuildings = true;
2016-05-17 14:20:56 +02:00
} else if (params[i].equals("-vintersections")) {
vintersections = true;
2016-05-17 14:20:56 +02:00
} else if (params[i].equals("-vmap")) {
vmap = true;
2016-05-17 14:20:56 +02:00
} else if (params[i].equals("-vstats")) {
vstats = true;
2016-05-17 14:20:56 +02:00
} else if (params[i].equals("-vrouting")) {
vrouting = true;
2016-05-17 14:20:56 +02:00
} else if (params[i].equals("-vmapobjects")) {
vmapObjects = true;
2016-05-17 14:20:56 +02:00
} else if (params[i].equals("-vmapcoordinates")) {
2015-07-28 01:36:53 +02:00
vmapCoordinates = true;
2016-05-17 14:20:56 +02:00
} else if (params[i].equals("-vpoi")) {
vpoi = true;
2016-05-17 14:20:56 +02:00
} else if (params[i].startsWith("-osm")) {
2013-09-23 19:42:48 +02:00
osm = true;
2016-05-17 14:20:56 +02:00
if (params[i].startsWith("-osm=")) {
2013-09-23 19:42:48 +02:00
osmOut = new FileOutputStream(params[i].substring(5));
}
2016-05-17 14:20:56 +02:00
} else if (params[i].equals("-vtransport")) {
vtransport = true;
2016-05-17 10:20:39 +02:00
} else if (params[i].startsWith("-lang=")) {
lang = params[i].substring("-lang=".length());
2016-05-17 14:20:56 +02:00
} else if (params[i].startsWith("-zoom=")) {
zoom = Integer.parseInt(params[i].substring("-zoom=".length()));
2016-05-17 14:20:56 +02:00
} 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]);
}
}
}
2016-05-17 14:20:56 +02:00
public boolean contains(MapObject o) {
return lattop >= o.getLocation().getLatitude() && latbottom <= o.getLocation().getLatitude()
&& lonleft <= o.getLocation().getLongitude() && lonright >= o.getLocation().getLongitude();
2016-05-17 14:20:56 +02:00
}
2013-09-23 19:42:48 +02:00
public void close() throws IOException {
2016-05-17 14:20:56 +02:00
if (osmOut != null) {
osmOut.close();
2013-09-23 19:42:48 +02:00
osmOut = null;
}
}
}
2016-05-17 14:20:56 +02:00
public void inspector(String[] args) throws IOException {
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();
}
} else {
printUsage("Unknown command : " + f);
}
} else {
2013-09-23 19:42:48 +02:00
vInfo = null;
printFileInformation(f);
}
}
2016-05-17 14:20:56 +02:00
2015-08-02 21:44:46 +02:00
public static final void writeInt(CodedOutputStream ous, int v) throws IOException {
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);
//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 {
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");
2015-08-01 20:52:21 +02:00
indexes[c] = new BinaryMapIndexReader(rafs[c], f);
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);
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);
}
}
}
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);
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",
new Object[]{part.getName(), part.getLength(), map}));
}
}
ous.writeInt32(OsmandOdb.OsmAndStructure.VERSIONCONFIRM_FIELD_NUMBER, version);
ous.flush();
fout.close();
return list;
}
2015-08-02 21:44:46 +02:00
public static void copyBinaryPart(CodedOutputStream ous, byte[] BUFFER, RandomAccessFile raf, long fp, int length)
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;
}
}
2016-05-17 14:20:56 +02:00
protected String formatBounds(int left, int right, int top, int bottom) {
double l = MapUtils.get31LongitudeX(left);
double r = MapUtils.get31LongitudeX(right);
double t = MapUtils.get31LatitudeY(top);
double b = MapUtils.get31LatitudeY(bottom);
2016-05-17 14:20:56 +02:00
return formatLatBounds(l, r, t, b);
}
2016-05-17 14:20:56 +02:00
protected String formatLatBounds(double l, double r, double t, double b) {
MessageFormat format = new MessageFormat("(left top - right bottom) : {0,number,#.####}, {1,number,#.####} NE - {2,number,#.####}, {3,number,#.####} NE", new Locale("EN", "US"));
2016-05-17 14:20:56 +02:00
return format.format(new Object[]{l, t, r, b});
}
2016-05-17 14:20:56 +02:00
public void printFileInformation(String fileName) throws IOException {
File file = new File(fileName);
2016-05-17 14:20:56 +02:00
if (!file.exists()) {
println("Binary OsmAnd index " + fileName + " was not found.");
return;
}
2013-09-23 19:42:48 +02:00
printFileInformation(file);
}
2016-05-17 14:20:56 +02:00
2014-03-06 01:57:31 +01:00
public void printFileInformation(File file) throws IOException {
RandomAccessFile r = new RandomAccessFile(file.getAbsolutePath(), "r");
2015-08-01 20:52:21 +02:00
printFileInformation(r, file);
2014-03-06 01:57:31 +01:00
}
2016-05-17 14:20:56 +02:00
public void printFileInformation(RandomAccessFile r, File file) throws IOException {
2015-08-01 20:52:21 +02:00
String filename = file.getName();
try {
2015-08-01 20:52:21 +02:00
BinaryMapIndexReader index = new BinaryMapIndexReader(r, file);
int i = 1;
2016-05-17 14:20:56 +02:00
println("Binary index " + filename + " version = " + index.getVersion() + " edition = " + new Date(index.getDateCreated()));
for (BinaryIndexPart p : index.getIndexes()) {
String partname = "";
2016-05-17 14:20:56 +02:00
if (p instanceof MapIndex) {
partname = "Map";
2016-05-17 14:20:56 +02:00
} else if (p instanceof TransportIndex) {
2016-05-17 14:24:37 +02:00
partname = "Transport";
2016-05-17 14:20:56 +02:00
} else if (p instanceof RouteRegion) {
partname = "Routing";
2016-05-17 14:20:56 +02:00
} else if (p instanceof PoiRegion) {
partname = "Poi";
2016-05-17 14:20:56 +02:00
} else if (p instanceof AddressRegion) {
partname = "Address";
}
2016-05-17 14:20:56 +02:00
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}));
if(p instanceof TransportIndex){
TransportIndex ti = ((TransportIndex) p);
int sh = (31 - BinaryMapIndexReader.TRANSPORT_STOP_ZOOM);
2016-05-17 14:20:56 +02:00
println("\tBounds " + formatBounds(ti.getLeft() << sh, ti.getRight() << sh,
ti.getTop() << sh, ti.getBottom() << sh));
2016-08-23 22:53:12 +02:00
if ((vInfo != null && vInfo.isVtransport())) {
printTransportDetailInfo(vInfo, index, (TransportIndex) p);
}
2016-05-17 14:20:56 +02:00
} else if (p instanceof RouteRegion) {
RouteRegion ri = ((RouteRegion) p);
2016-05-17 14:20:56 +02:00
println("\tBounds " + formatLatBounds(ri.getLeftLongitude(), ri.getRightLongitude(),
ri.getTopLatitude(), ri.getBottomLatitude()));
2016-05-17 14:20:56 +02:00
if ((vInfo != null && vInfo.isVrouting())) {
printRouteDetailInfo(index, (RouteRegion) p);
}
2016-05-17 14:20:56 +02:00
} else if (p instanceof MapIndex) {
MapIndex m = ((MapIndex) p);
int j = 1;
2016-05-17 14:20:56 +02:00
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++}));
}
2016-05-17 14:20:56 +02:00
if ((vInfo != null && vInfo.isVmap())) {
2013-09-23 19:42:48 +02:00
printMapDetailInfo(index, m);
}
2016-05-17 14:20:56 +02:00
} else if (p instanceof PoiRegion && (vInfo != null && vInfo.isVpoi())) {
2013-09-23 19:42:48 +02:00
printPOIDetailInfo(vInfo, index, (PoiRegion) p);
2016-08-23 22:53:12 +02:00
} else if (p instanceof TransportIndex && (vInfo != null && vInfo.isVtransport())) {
} 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);
}
}
i++;
}
2016-05-17 14:20:56 +02:00
} catch (IOException e) {
2016-05-17 14:20:56 +02:00
System.err.println("File doesn't have valid structure : " + filename + " " + e.getMessage());
throw e;
}
2016-05-17 14:20:56 +02:00
}
private void printRouteDetailInfo(BinaryMapIndexReader index, RouteRegion p) throws IOException {
final DamnCounter mapObjectsCounter = new DamnCounter();
final StringBuilder b = new StringBuilder();
List<RouteSubregion> regions = index.searchRouteIndexTree(
BinaryMapIndexReader.buildSearchRequest(MapUtils.get31TileNumberX(vInfo.lonleft),
MapUtils.get31TileNumberX(vInfo.lonright), MapUtils.get31TileNumberY(vInfo.lattop),
MapUtils.get31TileNumberY(vInfo.latbottom), vInfo.getZoom(), null),
p.getSubregions());
2016-07-28 01:09:45 +02:00
if (vInfo.osm) {
printToFile("<?xml version='1.0' encoding='UTF-8'?>\n" +
"<osm version='0.6'>\n");
}
index.loadRouteIndexData(regions, new ResultMatcher<RouteDataObject>() {
@Override
public boolean publish(RouteDataObject obj) {
mapObjectsCounter.value++;
2016-07-28 01:09:45 +02:00
if (vInfo.osm) {
b.setLength(0);
2016-07-28 01:28:22 +02:00
printOsmRouteDetails(obj, b);
2016-07-28 01:09:45 +02:00
try {
printToFile(b.toString());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
b.setLength(0);
b.append("Road ");
b.append(obj.id);
2016-04-26 22:59:47 +02:00
b.append(" osmid ").append(obj.getId() >> (SHIFT_ID));
2016-07-28 01:09:45 +02:00
for (int i = 0; i < obj.getTypes().length; i++) {
RouteTypeRule rr = obj.region.quickGetEncodingRule(obj.getTypes()[i]);
b.append(" ").append(rr.getTag()).append("='").append(rr.getValue()).append("'");
}
int[] nameIds = obj.getNameIds();
if (nameIds != null) {
for (int key : nameIds) {
RouteTypeRule rr = obj.region.quickGetEncodingRule(key);
b.append(" ").append(rr.getTag()).append("='").append(obj.getNames().get(key)).append("'");
}
}
2016-04-26 20:08:37 +02:00
int pointsLength = obj.getPointsLength();
if(obj.hasPointNames() || obj.hasPointTypes()) {
b.append(" pointtypes [");
for (int i = 0; i < pointsLength; i++) {
String[] names = obj.getPointNames(i);
int[] nametypes = obj.getPointNameTypes(i);
int[] types = obj.getPointTypes(i);
2016-04-26 22:07:57 +02:00
if (types != null || names != null) {
2016-07-28 01:09:45 +02:00
b.append("[" + (i + 1) + ". ");
2016-04-26 22:07:57 +02:00
if (names != null) {
for (int k = 0; k < names.length; k++) {
RouteTypeRule rr = obj.region.quickGetEncodingRule(nametypes[k]);
b.append(rr.getTag()).append("='").append(names[k]).append("' ");
}
2016-04-26 20:08:37 +02:00
}
2016-04-26 22:07:57 +02:00
if (types != null) {
for (int k = 0; k < types.length; k++) {
RouteTypeRule rr = obj.region.quickGetEncodingRule(types[k]);
b.append(rr.getTag()).append("='").append(rr.getValue()).append("' ");
}
}
if (vInfo.vmapCoordinates) {
float x = (float) MapUtils.get31LongitudeX(obj.getPoint31XTile(i));
float y = (float) MapUtils.get31LatitudeY(obj.getPoint31YTile(i));
b.append(y).append(" / ").append(x).append(" ");
2016-04-26 20:08:37 +02:00
}
2016-07-28 01:09:45 +02:00
b.append("]");
2016-04-26 20:08:37 +02:00
}
}
2016-07-28 01:09:45 +02:00
b.append("]");
2016-04-26 20:08:37 +02:00
}
if (obj.restrictions != null) {
2016-04-26 20:08:37 +02:00
b.append(" restrictions [");
for (int i = 0; i < obj.restrictions.length; i++) {
2016-04-26 20:17:24 +02:00
if (i > 0) {
b.append(", ");
}
2016-07-28 01:28:22 +02:00
b.append(obj.getRestrictionId(i)).append(" (").append(
MapRenderingTypes.getRestrictionValue(
obj.getRestrictionType(i))).append(") ");
2016-04-26 20:17:24 +02:00
}
2016-04-26 20:08:37 +02:00
b.append("] ");
}
if (vInfo.vmapCoordinates) {
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(y).append(" / ").append(x).append(" , ");
}
}
println(b.toString());
return false;
}
@Override
public boolean isCancelled() {
return false;
}
});
println("\tTotal map objects: " + mapObjectsCounter.value);
2016-07-28 01:09:45 +02:00
if (vInfo.osm) {
printToFile("</osm >\n");
}
}
2016-05-17 16:29:31 +02:00
private void printAddressDetailedInfo(VerboseInfo verbose, BinaryMapIndexReader index, AddressRegion region) throws IOException {
String[] cityType_String = new String[]{
"Cities/Towns section",
"Postcodes section",
2016-05-21 13:47:44 +02:00
"Villages section",
};
2016-05-17 10:20:39 +02:00
for (int j = 0; j < BinaryMapAddressReaderAdapter.CITY_TYPES.length; j++) {
int type = BinaryMapAddressReaderAdapter.CITY_TYPES[j];
final List<City> cities = index.getCities(region, null, type);
2016-05-17 16:29:31 +02:00
print(MessageFormat.format("\t{0}, {1,number,#} group(s)", cityType_String[j], cities.size()));
if (BinaryMapAddressReaderAdapter.CITY_TOWN_TYPE == type) {
if (!verbose.vstreetgroups && !verbose.vcities) {
println("");
continue;
}
} else if (!verbose.vstreetgroups) {
println("");
continue;
}
println(":");
2016-05-17 14:20:56 +02:00
for (City c : cities) {
int size = index.preloadStreets(c, null);
List<Street> streets = new ArrayList<Street>(c.getStreets());
String name = c.getName(verbose.lang);
if (verbose.vcitynames) {
boolean includeEnName = verbose.lang == null || !verbose.lang.equals("en");
name += " " + c.getNamesMap(includeEnName).toString();
}
2016-05-25 10:22:40 +02:00
String cityDescription = (type == BinaryMapAddressReaderAdapter.POSTCODES_TYPE ?
MessageFormat.format("\t\t''{0}'' {1,number,#} street(s) size {2,number,#} bytes", name, streets.size(), size) :
MessageFormat.format("\t\t''{0}'' [{1,number,#}], {2,number,#} street(s) size {3,number,#} bytes", name, c.getId(), streets.size(), size));
print(cityDescription);
if (!verbose.vstreets) {
println("");
continue;
}
println(":");
if (!verbose.contains(c))
continue;
2016-05-17 14:20:56 +02:00
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();
2016-05-17 14:20:56 +02:00
println(MessageFormat.format("\t\t\t''{0}'' [{1,number,#}], {2,number,#} building(s), {3,number,#} intersections(s)",
2016-05-17 16:13:12 +02:00
new Object[]{t.getName(verbose.lang), t.getId(), buildings.size(), intersections.size()}));
if (buildings != null && !buildings.isEmpty() && verbose.vbuildings) {
println("\t\t\t\tBuildings:");
for (Building b : buildings) {
2016-06-23 00:41:09 +02:00
println(MessageFormat.format("\t\t\t\t{0} [{1,number,#} {2} ]",
new Object[]{b.getName(verbose.lang), b.getId(), b.getPostcode() == null ? "" : b.getPostcode()}));
}
}
2016-05-17 14:20:56 +02:00
if (intersections != null && !intersections.isEmpty() && verbose.vintersections) {
print("\t\t\t\tIntersects with:");
for (Street s : intersections) {
2016-05-17 10:20:39 +02:00
println("\t\t\t\t\t" + s.getName(verbose.lang));
}
}
}
}
}
}
private static class DamnCounter {
int value;
}
2016-05-17 14:20:56 +02:00
private static class MapStatKey {
String key = "";
long statCoordinates;
2015-03-09 23:09:16 +01:00
long statCoordinatesCount;
long statObjectSize;
int count;
int namesLength;
}
2016-05-17 14:20:56 +02:00
private class MapStats {
public int lastStringNamesSize;
public int lastObjectIdSize;
public int lastObjectHeaderInfo;
public int lastObjectAdditionalTypes;
public int lastObjectTypes;
public int lastObjectCoordinates;
public int lastObjectCoordinatesCount;
2016-05-17 14:20:56 +02:00
2015-03-09 23:09:16 +01:00
public int lastObjectSize;
2016-05-17 14:20:56 +02:00
private Map<String, MapStatKey> types = new LinkedHashMap<String, BinaryInspector.MapStatKey>();
private SearchRequest<BinaryMapDataObject> req;
2016-05-17 14:20:56 +02:00
2015-03-09 23:09:16 +01:00
public void processKey(String simpleString, MapObjectStat st, TIntObjectHashMap<String> objectNames,
2016-05-17 14:20:56 +02:00
int coordinates, boolean names) {
TIntObjectIterator<String> it = objectNames.iterator();
int nameLen = 0;
2016-05-17 14:20:56 +02:00
while (it.hasNext()) {
it.advance();
2016-05-17 14:20:56 +02:00
nameLen++;
nameLen += it.value().length();
}
2016-05-17 14:20:56 +02:00
if (!types.containsKey(simpleString)) {
MapStatKey stt = new MapStatKey();
stt.key = simpleString;
types.put(simpleString, stt);
}
MapStatKey key = types.get(simpleString);
2015-03-09 23:09:16 +01:00
if (names) {
key.namesLength += nameLen;
} else {
key.statCoordinates += st.lastObjectCoordinates;
key.statCoordinatesCount += coordinates;
key.statObjectSize += st.lastObjectSize;
key.count++;
}
}
public void process(BinaryMapDataObject obj) {
MapObjectStat st = req.stat;
2015-03-09 23:09:16 +01:00
int cnt = 0;
boolean names = st.lastObjectCoordinates == 0;
if (!names) {
2015-03-09 23:16:22 +01:00
this.lastStringNamesSize += st.lastStringNamesSize;
this.lastObjectIdSize += st.lastObjectIdSize;
this.lastObjectHeaderInfo += st.lastObjectHeaderInfo;
this.lastObjectAdditionalTypes += st.lastObjectAdditionalTypes;
this.lastObjectTypes += st.lastObjectTypes;
this.lastObjectCoordinates += st.lastObjectCoordinates;
2015-03-09 23:09:16 +01:00
cnt = obj.getPointsLength();
2015-03-09 23:16:22 +01:00
this.lastObjectSize += st.lastObjectSize;
2015-03-09 23:09:16 +01:00
if (obj.getPolygonInnerCoordinates() != null) {
for (int[] i : obj.getPolygonInnerCoordinates()) {
cnt += i.length;
}
}
2015-03-09 23:09:16 +01:00
this.lastObjectCoordinatesCount += cnt;
}
2015-03-09 23:09:16 +01:00
for (int i = 0; i < obj.getTypes().length; i++) {
int tp = obj.getTypes()[i];
TagValuePair pair = obj.mapIndex.decodeType(tp);
2016-05-17 14:20:56 +02:00
if (pair == null) {
2015-03-09 23:18:22 +01:00
continue;
}
2015-03-09 23:09:16 +01:00
processKey(pair.toSimpleString(), st, obj.getObjectNames(), cnt, names);
}
st.clearObjectStats();
2015-03-09 23:09:16 +01:00
st.lastObjectSize = 0;
}
public void print() {
MapObjectStat st = req.stat;
println("MAP BLOCK INFO:");
long b = 0;
b += out("Header", st.lastBlockHeaderInfo);
b += out("String table", st.lastBlockStringTableSize);
2015-03-09 23:16:22 +01:00
b += out("Map Objects", lastObjectSize);
out("TOTAL", b);
println("\nMAP OBJECTS INFO:");
b = 0;
b += out("Header", lastObjectHeaderInfo);
b += out("Coordinates", lastObjectCoordinates);
2015-03-09 23:16:22 +01:00
out("Coordinates Count(pair)", lastObjectCoordinatesCount);
b += out("Types", lastObjectTypes);
b += out("Additonal Types", lastObjectAdditionalTypes);
b += out("Ids", lastObjectIdSize);
b += out("String names", lastStringNamesSize);
out("TOTAL", b);
2016-05-17 14:20:56 +02:00
println("\n\nOBJECT BY TYPE STATS: ");
ArrayList<MapStatKey> stats = new ArrayList<MapStatKey>(types.values());
Collections.sort(stats, new Comparator<MapStatKey>() {
@Override
public int compare(MapStatKey o1, MapStatKey o2) {
2015-04-08 16:04:32 +02:00
return compare(o1.statObjectSize, o2.statObjectSize);
}
2016-05-17 14:20:56 +02:00
2015-04-08 16:04:32 +02:00
public int compare(long x, long y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
});
2016-05-17 14:20:56 +02:00
for (MapStatKey s : stats) {
println(s.key + " (" + s.count + ") \t " + s.statObjectSize + " bytes \t coord=" +
s.statCoordinatesCount +
" (" + s.statCoordinates + " bytes) " +
" names " + s.namesLength + " bytes");
}
2016-05-17 14:20:56 +02:00
}
private long out(String s, long i) {
2015-03-09 23:09:16 +01:00
while (s.length() < 25) {
s += " ";
}
DecimalFormat df = new DecimalFormat("0,000,000,000");
2016-05-17 14:20:56 +02:00
println(s + ": " + df.format(i));
return i;
}
public void setReq(SearchRequest<BinaryMapDataObject> req) {
this.req = req;
}
2016-05-17 14:20:56 +02:00
}
2016-05-17 14:20:56 +02:00
private void printMapDetailInfo(BinaryMapIndexReader index, MapIndex mapIndex) throws IOException {
final StringBuilder b = new StringBuilder();
final DamnCounter mapObjectsCounter = new DamnCounter();
final MapStats mapObjectStats = new MapStats();
2016-05-17 14:20:56 +02:00
if (vInfo.osm) {
2013-09-23 19:42:48 +02:00
printToFile("<?xml version='1.0' encoding='UTF-8'?>\n" +
2016-01-21 15:13:08 +01:00
"<osm version='0.6'>\n");
2013-09-23 19:42:48 +02:00
}
2016-05-17 14:20:56 +02:00
if (vInfo.isVStats()) {
BinaryMapIndexReader.READ_STATS = true;
}
final 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(),
new SearchFilter() {
@Override
public boolean accept(TIntArrayList types, MapIndex index) {
return true;
}
},
new ResultMatcher<BinaryMapDataObject>() {
@Override
public boolean publish(BinaryMapDataObject obj) {
mapObjectsCounter.value++;
2016-05-17 14:20:56 +02:00
if (vInfo.isVStats()) {
mapObjectStats.process(obj);
} else if (vInfo.vmapObjects) {
b.setLength(0);
if (vInfo.osm) {
2016-07-28 01:28:22 +02:00
printOsmMapDetails(obj, b);
2013-09-23 19:42:48 +02:00
try {
printToFile(b.toString());
} catch (IOException e) {
throw new RuntimeException(e);
}
2015-08-19 00:19:40 +02:00
// } else if(obj.getId() >> 1 == 205743436l) {
} else {
2015-07-28 01:36:53 +02:00
printMapDetails(obj, b, vInfo.vmapCoordinates);
2013-09-23 19:42:48 +02:00
println(b.toString());
}
}
return false;
}
2016-05-17 14:20:56 +02:00
@Override
public boolean isCancelled() {
return false;
}
});
2016-05-17 14:20:56 +02:00
if (vInfo.vstats) {
mapObjectStats.setReq(req);
}
index.searchMapIndex(req, mapIndex);
2016-05-17 14:20:56 +02:00
if (vInfo.osm) {
2013-09-23 19:42:48 +02:00
printToFile("</osm >\n");
2016-05-17 14:20:56 +02:00
}
if (vInfo.vstats) {
mapObjectStats.print();
2013-09-23 19:42:48 +02:00
}
println("\tTotal map objects: " + mapObjectsCounter.value);
}
2013-09-23 19:42:48 +02:00
2015-07-28 01:36:53 +02:00
private static void printMapDetails(BinaryMapDataObject obj, StringBuilder b, boolean vmapCoordinates) {
2013-09-23 19:42:48 +02:00
boolean multipolygon = obj.getPolygonInnerCoordinates() != null && obj.getPolygonInnerCoordinates().length > 0;
2016-05-17 14:20:56 +02:00
if (multipolygon) {
2013-09-23 19:42:48 +02:00
b.append("Multipolygon");
} else {
2016-05-17 14:20:56 +02:00
b.append(obj.area ? "Area" : (obj.getPointsLength() > 1 ? "Way" : "Point"));
2013-09-23 19:42:48 +02:00
}
int[] types = obj.getTypes();
b.append(" types [");
2016-05-17 14:20:56 +02:00
for (int j = 0; j < types.length; j++) {
if (j > 0) {
2013-09-23 19:42:48 +02:00
b.append(", ");
}
TagValuePair pair = obj.getMapIndex().decodeType(types[j]);
2016-05-17 14:20:56 +02:00
if (pair == null) {
2013-09-23 19:42:48 +02:00
System.err.println("Type " + types[j] + "was not found");
continue;
// throw new NullPointerException("Type " + obj.getAdditionalTypes()[j] + "was not found");
}
2016-05-17 14:20:56 +02:00
b.append(pair.toSimpleString() + " (" + types[j] + ")");
2013-09-23 19:42:48 +02:00
}
b.append("]");
2016-05-17 14:20:56 +02:00
if (obj.getAdditionalTypes() != null && obj.getAdditionalTypes().length > 0) {
2013-09-23 19:42:48 +02:00
b.append(" add_types [");
2016-05-17 14:20:56 +02:00
for (int j = 0; j < obj.getAdditionalTypes().length; j++) {
if (j > 0) {
2013-09-23 19:42:48 +02:00
b.append(", ");
}
TagValuePair pair = obj.getMapIndex().decodeType(obj.getAdditionalTypes()[j]);
2016-05-17 14:20:56 +02:00
if (pair == null) {
2013-09-23 19:42:48 +02:00
System.err.println("Type " + obj.getAdditionalTypes()[j] + "was not found");
continue;
// throw new NullPointerException("Type " + obj.getAdditionalTypes()[j] + "was not found");
}
2016-05-17 14:20:56 +02:00
b.append(pair.toSimpleString() + "(" + obj.getAdditionalTypes()[j] + ")");
2013-09-23 19:42:48 +02:00
}
b.append("]");
}
TIntObjectHashMap<String> names = obj.getObjectNames();
2014-06-26 01:14:30 +02:00
TIntArrayList order = obj.getNamesOrder();
if (names != null && !names.isEmpty()) {
2013-09-23 19:42:48 +02:00
b.append(" Names [");
2014-06-26 01:14:30 +02:00
// int[] keys = names.keys();
for (int j = 0; j < order.size(); j++) {
if (j > 0) {
2013-09-23 19:42:48 +02:00
b.append(", ");
}
2014-06-26 01:14:30 +02:00
TagValuePair pair = obj.getMapIndex().decodeType(order.get(j));
if (pair == null) {
throw new NullPointerException("Type " + order.get(j) + "was not found");
2013-09-23 19:42:48 +02:00
}
2014-06-26 01:14:30 +02:00
b.append(pair.toSimpleString() + "(" + order.get(j) + ")");
b.append(" - ").append(names.get(order.get(j)));
2013-09-23 19:42:48 +02:00
}
b.append("]");
}
2016-04-26 20:08:37 +02:00
b.append(" id ").append(obj.getId());
2016-04-26 22:59:47 +02:00
b.append(" osmid ").append((obj.getId() >> (SHIFT_ID + 1)));
2015-07-28 01:36:53 +02:00
if (vmapCoordinates) {
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(y).append(" / ").append(x).append(" , ");
}
2013-09-23 19:42:48 +02:00
}
}
private static int OSM_ID = 1;
2016-07-28 01:28:22 +02:00
private void printOsmRouteDetails(RouteDataObject obj, StringBuilder b) {
StringBuilder tags = new StringBuilder();
int[] types = obj.getTypes();
for (int j = 0; j < types.length; j++) {
RouteTypeRule rt = obj.region.quickGetEncodingRule(types[j]);
if (rt == null) {
throw new NullPointerException("Type " + types[j] + "was not found");
}
tags.append("\t<tag k='").append(rt.getTag()).append("' v='").append(rt.getValue()).append("' />\n");
}
TIntObjectHashMap<String> names = obj.getNames();
if (names != null && !names.isEmpty()) {
int[] keys = names.keys();
for (int j = 0; j < keys.length; j++) {
RouteTypeRule rt = obj.region.quickGetEncodingRule(keys[j]);
if (rt == null) {
throw new NullPointerException("Type " + keys[j] + "was not found");
}
String name = quoteName(names.get(keys[j]));
tags.append("\t<tag k='").append(rt.getTag()).append("' v='").append(name).append("' />\n");
}
}
tags.append("\t<tag k=\'").append("original_id").append("' v='").append(obj.getId() >> (SHIFT_ID))
.append("'/>\n");
tags.append("\t<tag k=\'").append("osmand_id").append("' v='").append(obj.getId()).append("'/>\n");
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 + "' version='1' lat='" + lat + "' lon='" + lon + "' >\n");
if (obj.getPointNames(i) != null) {
String[] vs = obj.getPointNames(i);
int[] keys = obj.getPointNameTypes(i);
for (int j = 0; j < keys.length; j++) {
RouteTypeRule rt = obj.region.quickGetEncodingRule(keys[j]);
String name = quoteName(vs[j]);
tags.append("\t\t<tag k='").append(rt.getTag()).append("' v='").append(name).append("' />\n");
}
}
if (obj.getPointTypes(i) != null) {
int[] keys = obj.getPointTypes(i);
for (int j = 0; j < keys.length; j++) {
RouteTypeRule rt = obj.region.quickGetEncodingRule(keys[j]);
tags.append("\t\t<tag k='").append(rt.getTag()).append("' v='").append(rt.getValue()).append("' />\n");
}
}
b.append("\t</node >\n");
ids.add(id);
}
long idway = printWay(ids, b, tags);
if(obj.getRestrictionLength() > 0) {
for(int i = 0; i < obj.getRestrictionLength(); i ++) {
long ld = obj.getRestrictionId(i);
String tp = MapRenderingTypes.getRestrictionValue(obj.getRestrictionType(i));
int id = OSM_ID++;
2016-07-28 01:32:59 +02:00
b.append("<relation id = '" + id + "' version='1'>\n");
2016-07-28 01:28:22 +02:00
b.append("\t<member ref='").append(idway).append("' role='from' type='way' />\n");
b.append("\t<tag k='").append("from_osmand_id").append("' v='").append(obj.getId()).append("' />\n");
b.append("\t<tag k='").append("from_id").append("' v='").append(obj.getId() >> SHIFT_ID).append("' />\n");
b.append("\t<tag k='").append("to_osmand_id").append("' v='").append(ld).append("' />\n");
b.append("\t<tag k='").append("to_id").append("' v='").append(ld >> SHIFT_ID).append("' />\n");
b.append("\t<tag k='").append("type").append("' v='").append("restriction").append("' />\n");
b.append("\t<tag k='").append("restriction").append("' v='").append(tp).append("' />\n");
2016-07-28 01:32:59 +02:00
b.append("</relation>\n");
2016-07-28 01:28:22 +02:00
}
}
}
private String quoteName(String name) {
name = name.replace("'", "&apos;");
name = name.replace("&", "&amp;");
return name;
}
private void printOsmMapDetails(BinaryMapDataObject obj, StringBuilder b) {
2013-09-23 19:42:48 +02:00
boolean multipolygon = obj.getPolygonInnerCoordinates() != null && obj.getPolygonInnerCoordinates().length > 0;
boolean point = obj.getPointsLength() == 1;
StringBuilder tags = new StringBuilder();
int[] types = obj.getTypes();
2016-05-17 14:20:56 +02:00
for (int j = 0; j < types.length; j++) {
2016-07-28 01:28:22 +02:00
TagValuePair pair = obj.getMapIndex().decodeType(types[j]);
2016-05-17 14:20:56 +02:00
if (pair == null) {
2013-09-23 19:42:48 +02:00
throw new NullPointerException("Type " + types[j] + "was not found");
}
tags.append("\t<tag k='").append(pair.tag).append("' v='").append(pair.value).append("' />\n");
}
2016-05-17 14:20:56 +02:00
if (obj.getAdditionalTypes() != null && obj.getAdditionalTypes().length > 0) {
for (int j = 0; j < obj.getAdditionalTypes().length; j++) {
2016-07-28 01:09:45 +02:00
int addtype = obj.getAdditionalTypes()[j];
2016-07-28 01:28:22 +02:00
TagValuePair pair = obj.getMapIndex().decodeType(addtype);
2016-05-17 14:20:56 +02:00
if (pair == null) {
2013-09-23 19:42:48 +02:00
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();
2016-05-17 14:20:56 +02:00
if (names != null && !names.isEmpty()) {
2013-09-23 19:42:48 +02:00
int[] keys = names.keys();
2016-05-17 14:20:56 +02:00
for (int j = 0; j < keys.length; j++) {
2016-07-28 01:28:22 +02:00
TagValuePair pair = obj.getMapIndex().decodeType(keys[j]);
2016-05-17 14:20:56 +02:00
if (pair == null) {
2013-09-23 19:42:48 +02:00
throw new NullPointerException("Type " + keys[j] + "was not found");
}
String name = names.get(keys[j]);
2016-07-28 01:28:22 +02:00
name = quoteName(name);
2013-09-23 19:42:48 +02:00
tags.append("\t<tag k='").append(pair.tag).append("' v='").append(name).append("' />\n");
}
}
2016-04-24 21:12:21 +02:00
tags.append("\t<tag k=\'").append("original_id").append("' v='").append(obj.getId() >> (SHIFT_ID + 1)).append("'/>\n");
2016-04-26 13:29:14 +02:00
tags.append("\t<tag k=\'").append("osmand_id").append("' v='").append(obj.getId()).append("'/>\n");
2013-09-23 19:42:48 +02:00
if(point) {
float lon= (float) MapUtils.get31LongitudeX(obj.getPoint31XTile(0));
float lat = (float) MapUtils.get31LatitudeY(obj.getPoint31YTile(0));
2016-05-17 14:20:56 +02:00
b.append("<node id = '" + OSM_ID++ + "' version='1' lat='" + lat + "' lon='" + lon + "' >\n");
2013-09-23 19:42:48 +02:00
b.append(tags);
b.append("</node>\n");
} else {
TLongArrayList innerIds = new TLongArrayList();
TLongArrayList ids = new TLongArrayList();
2016-05-17 14:20:56 +02:00
for (int i = 0; i < obj.getPointsLength(); i++) {
2013-09-23 19:42:48 +02:00
float lon = (float) MapUtils.get31LongitudeX(obj.getPoint31XTile(i));
float lat = (float) MapUtils.get31LatitudeY(obj.getPoint31YTile(i));
int id = OSM_ID++;
2016-05-17 14:20:56 +02:00
b.append("\t<node id = '" + id + "' version='1' lat='" + lat + "' lon='" + lon + "' />\n");
2013-09-23 19:42:48 +02:00
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++) {
2016-05-17 14:20:56 +02:00
ids.clear();
2013-09-23 19:42:48 +02:00
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++;
2016-01-21 15:22:00 +01:00
b.append("<node id = '" + id + "' version='1' lat='" + lat + "' lon='" + lon + "' />\n");
2013-09-23 19:42:48 +02:00
ids.add(id);
}
innerIds.add(printWay(ids, b, null));
}
int id = OSM_ID++;
2016-05-17 14:20:56 +02:00
b.append("<relation id = '" + id + "' version='1'>\n");
2013-09-23 19:42:48 +02:00
b.append(tags);
2016-05-17 14:20:56 +02:00
b.append("\t<member type='way' role='outer' ref= '" + outerId + "'/>\n");
2013-09-23 19:42:48 +02:00
TLongIterator it = innerIds.iterator();
2016-05-17 14:20:56 +02:00
while (it.hasNext()) {
2013-09-23 19:42:48 +02:00
long ref = it.next();
2016-05-17 14:20:56 +02:00
b.append("<member type='way' role='inner' ref= '" + ref + "'/>\n");
2013-09-23 19:42:48 +02:00
}
2016-05-17 14:20:56 +02:00
b.append("</relation>\n");
2013-09-23 19:42:48 +02:00
}
}
}
2016-07-28 01:09:45 +02:00
2016-05-17 14:20:56 +02:00
private long printWay(TLongArrayList ids, StringBuilder b, StringBuilder tags) {
2013-09-23 19:42:48 +02:00
int id = OSM_ID++;
2016-05-17 14:20:56 +02:00
b.append("<way id = '" + id + "' version='1'>\n");
if (tags != null) {
2013-09-23 19:42:48 +02:00
b.append(tags);
}
TLongIterator it = ids.iterator();
2016-05-17 14:20:56 +02:00
while (it.hasNext()) {
2013-09-23 19:42:48 +02:00
long ref = it.next();
2016-05-17 14:20:56 +02:00
b.append("\t<nd ref = '" + ref + "'/>\n");
2013-09-23 19:42:48 +02:00
}
2016-05-17 14:20:56 +02:00
b.append("</way>\n");
2013-09-23 19:42:48 +02:00
return id;
}
2016-08-23 22:53:12 +02:00
private void printTransportDetailInfo(VerboseInfo verbose, BinaryMapIndexReader index, TransportIndex p) throws IOException {
SearchRequest<TransportStop> sr = BinaryMapIndexReader.buildSearchTransportRequest(
MapUtils.get31TileNumberX(verbose.lonleft),
MapUtils.get31TileNumberX(verbose.lonright),
MapUtils.get31TileNumberY(verbose.lattop),
MapUtils.get31TileNumberY(verbose.latbottom),
-1, null);
List<TransportStop> stops = index.searchTransportIndex(sr);
Map<Long, TransportRoute> rs = new LinkedHashMap<>();
List<String> lrs = new ArrayList<>();
println("\nStops:");
for (TransportStop s : stops) {
lrs.clear();
for (int pnt : s.getReferencesToRoutes()) {
TransportRoute route;
if (!lrs.contains(pnt)) {
TIntObjectHashMap<TransportRoute> pts = index.getTransportRoutes(new int[] { pnt });
route = pts.valueCollection().iterator().next();
rs.put((long) pnt, route);
} else {
route = rs.get(pnt);
}
if (route != null) {
//lrs.add(route.getRef() + " " + route.getName(verbose.lang));
lrs.add(route.getRef() + " " + route.getType());
}
}
println(" " + s.getName(verbose.lang) + ": " + lrs + " " + s.getLocation());
}
println("\nRoutes:");
for(TransportRoute s : rs.values()) {
List<String> stopsString = new ArrayList<>();
for(TransportStop st : s.getForwardStops()) {
stopsString.add(st.getName(verbose.lang));
}
println(" " + s.getRef() + " " + s.getType() + " " + s.getName(verbose.lang) + ": " + stopsString);
}
}
2013-09-23 19:42:48 +02:00
2016-05-17 14:20:56 +02:00
private void printPOIDetailInfo(VerboseInfo verbose, BinaryMapIndexReader index, PoiRegion p) throws IOException {
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
MapUtils.get31TileNumberX(verbose.lonleft),
MapUtils.get31TileNumberX(verbose.lonright),
MapUtils.get31TileNumberY(verbose.lattop),
MapUtils.get31TileNumberY(verbose.latbottom),
verbose.getZoom(),
BinaryMapIndexReader.ACCEPT_ALL_POI_TYPE_FILTER,
new ResultMatcher<Amenity>() {
@Override
public boolean publish(Amenity object) {
2015-05-31 16:51:10 +02:00
Iterator<Entry<String, String>> it = object.getAdditionalInfo().entrySet().iterator();
String s = "";
2016-05-17 14:20:56 +02:00
while (it.hasNext()) {
2015-05-31 16:51:10 +02:00
Entry<String, String> e = it.next();
2016-05-17 14:20:56 +02:00
if (e.getValue().startsWith(" gz ")) {
s += " " + e.getKey() + "=...";
2015-05-31 16:51:10 +02:00
} else {
2016-05-17 14:20:56 +02:00
s += " " + e.getKey() + "=" + e.getValue();
2015-05-31 16:51:10 +02:00
}
}
2016-05-17 14:20:56 +02:00
2015-05-31 16:51:10 +02:00
println(object.getType().getKeyName() + " : " + object.getSubType() + " " + object.getName() + " " + object.getLocation() + " id=" + (object.getId() >> 1) + " " + s);
return false;
}
2016-05-17 14:20:56 +02:00
@Override
public boolean isCancelled() {
return false;
}
});
2016-05-17 14:20:56 +02:00
index.initCategories(p);
println("\tRegion: " + p.name);
2016-07-13 22:22:22 +02:00
println("\t\tBounds " + formatLatBounds(MapUtils.get31LongitudeX(p.left31),
MapUtils.get31LongitudeX(p.right31),
MapUtils.get31LatitudeY(p.top31),
MapUtils.get31LatitudeY(p.bottom31)));
println("\t\tCategories:");
2016-05-17 14:20:56 +02:00
for (int i = 0; i < p.categories.size(); i++) {
println("\t\t\t" + p.categories.get(i));
2016-05-17 14:20:56 +02:00
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:");
2016-05-17 14:20:56 +02:00
for (int i = 0; i < p.subTypes.size(); i++) {
2013-11-24 19:22:07 +01:00
PoiSubType st = p.subTypes.get(i);
2016-05-17 14:20:56 +02:00
println("\t\t\t" + st.name + " " + (st.text ? "text" : (" encoded " + st.possibleValues.size())));
2013-11-24 19:22:07 +01:00
}
2015-04-10 19:26:36 +02:00
// req.poiTypeFilter = null;//for test only
2013-11-30 20:14:46 +01:00
index.searchPoi(p, req);
2016-05-17 14:20:56 +02:00
}
2016-05-30 23:21:45 +02:00
public static void printUsage(String warning) {
2016-05-17 14:20:56 +02:00
if (warning != null) {
2016-05-30 23:21:45 +02:00
System.out.println(warning);
}
2016-05-30 23:21:45 +02:00
System.out.println("Inspector is console utility for working with binary indexes of OsmAnd.");
System.out.println("It allows print info about file, extract parts and merge indexes.");
System.out.println("\nUsage for print info : inspector [-vaddress] [-vcitynames] [-vstreetgroups] [-vstreets] [-vbuildings] [-vintersections] [-vmap] [-vmapobjects] [-vmapcoordinates] [-osm] [-vpoi] [-vrouting] [-vtransport] [-zoom=Zoom] [-bbox=LeftLon,TopLat,RightLon,BottomLat] [file]");
System.out.println(" Prints information about [file] binary index of OsmAnd.");
System.out.println(" -v.. more verbouse output (like all cities and their streets or all map objects with tags/values and coordinates)");
System.out.println("\nUsage for combining indexes : inspector -c file_to_create (file_from_extract ((+|-)parts_to_extract)? )*");
System.out.println("\tCreate new file of extracted parts from input file. [parts_to_extract] could be parts to include or exclude.");
System.out.println(" Example : inspector -c output_file input_file +1,2,3\n\tExtracts 1, 2, 3 parts (could be find in print info)");
System.out.println(" Example : inspector -c output_file input_file -2,3\n\tExtracts all parts excluding 2, 3");
System.out.println(" Example : inspector -c output_file input_file1 input_file2 input_file3\n\tSimply combine 3 files");
System.out.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");
}
}