fix some problems

git-svn-id: https://osmand.googlecode.com/svn/trunk@600 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-10-28 15:55:09 +00:00
parent ce158272f3
commit ed5416f404
3 changed files with 230 additions and 15 deletions

View file

@ -6,6 +6,8 @@ import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
import net.osmand.osm.MapUtils;
import com.google.protobuf.CodedInputStreamRAF;
import com.google.protobuf.WireFormat;
@ -36,15 +38,26 @@ public class BinaryMapIndexReader {
int top = 0;
int bottom = 0;
long baseId = 0;
List<String> stringTable = null;
List<MapTree> subTrees = null;
List<MapObject> children = null;
}
public class MapObject {
public class MapDataObject {
int[] coordinates = null;
int[] types = null;
int stringId = -1;
long id = 0;
long[] restrictions = null;
int highwayAttributes = 0;
String name;
}
@ -169,6 +182,192 @@ public class BinaryMapIndexReader {
}
}
}
public List<MapDataObject> searchMapIndex(MapRoot index, int sleft, int sright, int stop, int sbottom,
List<MapDataObject> searchResults) throws IOException {
for(MapTree tree : index.trees){
codedIS.seek(tree.filePointer);
int oldLimit = codedIS.pushLimit(tree.length);
searchMapTreeBounds(tree, index.left, index.right, index.top, index.bottom,
sleft, sright, stop, sbottom, searchResults, " ");
codedIS.popLimit(oldLimit);
}
return searchResults;
}
private void searchMapTreeBounds(MapTree tree, int pleft, int pright, int ptop, int pbottom,
int sleft, int sright, int stop, int sbottom,
List<MapDataObject> searchResults, String indent) throws IOException {
int init = 0;
List<MapDataObject> results = null;
while(true){
int tag = WireFormat.getTagFieldNumber(codedIS.readTag());
if(init == 0xf){
init = 0;
// coordinates are init
if(tree.right < sleft || tree.left > sright || tree.top > sbottom || tree.bottom < stop){
return;
}
}
switch (tag) {
case 0:
return;
case OsmandOdb.MapTree.BOTTOM_FIELD_NUMBER :
tree.bottom = codedIS.readSInt32() + pbottom;
init |= 1;
break;
case OsmandOdb.MapTree.LEFT_FIELD_NUMBER :
tree.left = codedIS.readSInt32() + pleft;
init |= 2;
break;
case OsmandOdb.MapTree.RIGHT_FIELD_NUMBER :
tree.right = codedIS.readSInt32() + pright;
init |= 4;
break;
case OsmandOdb.MapTree.TOP_FIELD_NUMBER :
tree.top = codedIS.readSInt32() + ptop;
init |= 8;
break;
case OsmandOdb.MapTree.LEAFS_FIELD_NUMBER :
int length = codedIS.readRawVarint32();
int oldLimit = codedIS.pushLimit(length);
MapDataObject mapObject = readMapDataObject(tree.left, tree.right, tree.top, tree.bottom, sleft, sright, stop, sbottom);
if(mapObject != null){
if(results == null){
results = new ArrayList<MapDataObject>();
}
results.add(mapObject);
searchResults.add(mapObject);
}
codedIS.popLimit(oldLimit);
break;
case OsmandOdb.MapTree.SUBTREES_FIELD_NUMBER :
MapTree r = new MapTree();
// left, ... already initialized
r.length = readInt();
r.filePointer = codedIS.getTotalBytesRead();
oldLimit = codedIS.pushLimit(r.length);
searchMapTreeBounds(r, tree.left, tree.right, tree.top, tree.bottom, sleft, sright, stop, sbottom, searchResults, indent+" ");
codedIS.popLimit(oldLimit);
codedIS.seek(r.filePointer + r.length);
break;
case OsmandOdb.MapTree.BASEID_FIELD_NUMBER :
tree.baseId = codedIS.readUInt64();
if (results != null) {
for (MapDataObject rs : results) {
rs.id += tree.baseId;
if (rs.restrictions != null) {
for (int i = 0; i < rs.restrictions.length; i++) {
rs.restrictions[i] += tree.baseId;
}
}
}
}
break;
case OsmandOdb.MapTree.STRINGTABLE_FIELD_NUMBER :
length = codedIS.readRawVarint32();
oldLimit = codedIS.pushLimit(length);
tree.stringTable = readStringTable();
codedIS.popLimit(oldLimit);
if (results != null) {
for (MapDataObject rs : results) {
if (rs.stringId != -1) {
rs.name = tree.stringTable.get(rs.stringId);
}
}
}
break;
default:
// TODO skip unknown fields
return;
}
}
}
List<Integer> CACHE = new ArrayList<Integer>();
private MapDataObject readMapDataObject(int left, int right, int top, int bottom, int sleft, int sright, int stop, int sbottom) throws IOException {
int tag = WireFormat.getTagFieldNumber(codedIS.readTag());
if(OsmandOdb.MapData.COORDINATES_FIELD_NUMBER != tag) {
throw new IllegalArgumentException();
}
CACHE.clear();
int size = codedIS.readRawVarint32();
int old = codedIS.pushLimit(size);
int px = left;
int py = top;
boolean contains = false;
while(codedIS.getBytesUntilLimit() > 0){
int x = codedIS.readSInt32() + px;
int y = codedIS.readSInt32() + py;
CACHE.add(x);
CACHE.add(y);
px = x;
py = y;
if(!contains && sleft <= x && sright >= x && stop <= y && sbottom >= y){
contains = true;
}
}
codedIS.popLimit(old);
if(!contains){
codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
return null;
}
MapDataObject dataObject = new MapDataObject();
dataObject.coordinates = new int[CACHE.size()];
for(int i=0; i<CACHE.size(); i++){
dataObject.coordinates[i] = CACHE.get(i);
}
while(true){
tag = WireFormat.getTagFieldNumber(codedIS.readTag());
switch (tag) {
case 0:
return dataObject;
case OsmandOdb.MapData.TYPES_FIELD_NUMBER :
int sizeL = codedIS.readRawVarint32();
codedIS.skipRawBytes(sizeL);
// TODO read types
break;
case OsmandOdb.MapData.RESTRICTIONS_FIELD_NUMBER :
// TODO read restrictions
sizeL = codedIS.readRawVarint32();
codedIS.skipRawBytes(sizeL);
break;
case OsmandOdb.MapData.HIGHWAYMETA_FIELD_NUMBER :
dataObject.highwayAttributes = codedIS.readInt32();
break;
case OsmandOdb.MapData.ID_FIELD_NUMBER :
dataObject.id = codedIS.readSInt64();
break;
case OsmandOdb.MapData.STRINGID_FIELD_NUMBER :
dataObject.stringId = codedIS.readUInt32();
break;
default:
// TODO skip unknown fields
return dataObject;
}
}
}
private List<String> readStringTable() throws IOException{
List<String> list = new ArrayList<String>();
while(true){
int tag = WireFormat.getTagFieldNumber(codedIS.readTag());
switch (tag) {
case 0:
return list;
case OsmandOdb.StringTable.S_FIELD_NUMBER :
list.add(codedIS.readString());
break;
default:
// TODO skip unknown fields
return list;
}
}
}
public RandomAccessFile getRaf() {
return raf;
@ -203,9 +402,19 @@ public class BinaryMapIndexReader {
RandomAccessFile raf = new RandomAccessFile(new File("e:\\Information\\OSM maps\\osmand\\Minsk.map.pbf"), "r");
BinaryMapIndexReader reader = new BinaryMapIndexReader(raf);
System.out.println(reader.getVersion());
int sleft = MapUtils.get31TileNumberX(27.578);
int sright = MapUtils.get31TileNumberX(27.583);
int stop = MapUtils.get31TileNumberY(53.916);
int sbottom = MapUtils.get31TileNumberY(53.9138);
System.out.println("SEARCH " + sleft + " " + sright + " " + stop + " " + sbottom);
for(MapRoot b : reader.getMapIndexes()) {
System.out.println(b.minZoom + " " + b.maxZoom + " " +b.trees.size() + " "
+ b.left + " " + b.right + " " + b.top + " " + b.bottom);
for(MapDataObject obj : reader.searchMapIndex(b, sleft, sright, stop, sbottom, new ArrayList<MapDataObject>())){
if(obj.name != null){
System.out.println(" " + obj.name);
}
}
}
}

View file

@ -196,10 +196,10 @@ public class BinaryMapIndexWriter {
stackBaseIds.push(id);
}
// calculate size
int allSize = CodedOutputStream.computeTagSize(OsmandOdb.MapData.COORDINATES_FIELD_NUMBER);
int sizeCoordinates = 0;
int px = bounds.leftX / 2;
int py = bounds.topY / 2;
int allSize = 0;
int px = bounds.leftX;
int py = bounds.topY;
for(int i=0; i< nodes.length / 8; i++){
int x = Algoritms.parseIntFromBytes(nodes, i*8);
int y = Algoritms.parseIntFromBytes(nodes, i*8 + 4);
@ -208,21 +208,25 @@ public class BinaryMapIndexWriter {
px = x;
py = y;
}
allSize += sizeCoordinates;
allSize += CodedOutputStream.computeRawVarint32Size(sizeCoordinates) +
CodedOutputStream.computeTagSize(OsmandOdb.MapData.COORDINATES_FIELD_NUMBER) + sizeCoordinates;
// DEBUG
COORDINATES_SIZE += sizeCoordinates + CodedOutputStream.computeTagSize(OsmandOdb.MapData.COORDINATES_FIELD_NUMBER);
COORDINATES_SIZE += allSize;
allSize += CodedOutputStream.computeTagSize(OsmandOdb.MapData.TYPES_FIELD_NUMBER);
allSize += CodedOutputStream.computeRawVarint32Size(types.length);
allSize += types.length;
// DEBUG
TYPES_SIZE += CodedOutputStream.computeTagSize(OsmandOdb.MapData.TYPES_FIELD_NUMBER) +
CodedOutputStream.computeRawVarint32Size(types.length) + types.length;
System.out.println(id + " " + CodedOutputStream.computeSInt64Size(OsmandOdb.MapData.ID_FIELD_NUMBER, id - stackBaseIds.peek()));
allSize += CodedOutputStream.computeSInt64Size(OsmandOdb.MapData.ID_FIELD_NUMBER, id - stackBaseIds.peek());
// DEBUG
ID_SIZE += CodedOutputStream.computeSInt64Size(OsmandOdb.MapData.ID_FIELD_NUMBER, id - stackBaseIds.peek());
int nameId = 0;
if(name != null){
if(stackStringTable.peek() == null) {
@ -260,11 +264,12 @@ public class BinaryMapIndexWriter {
codedOutStream.writeTag(OsmandOdb.MapTree.LEAFS_FIELD_NUMBER, WireFormat.FieldType.MESSAGE.getWireType());
codedOutStream.writeRawVarint32(allSize);
codedOutStream.writeTag(OsmandOdb.MapData.COORDINATES_FIELD_NUMBER, WireFormat.FieldType.BYTES.getWireType());
codedOutStream.writeRawVarint32(sizeCoordinates);
px = bounds.leftX / 2;
py = bounds.topY / 2;
px = bounds.leftX;
py = bounds.topY;
for (int i = 0; i < nodes.length / 8; i++) {
int x = Algoritms.parseIntFromBytes(nodes, i*8);
int y = Algoritms.parseIntFromBytes(nodes, i*8 + 4);
@ -274,16 +279,17 @@ public class BinaryMapIndexWriter {
py = y;
}
codedOutStream.writeTag(OsmandOdb.MapData.TYPES_FIELD_NUMBER, WireFormat.FieldType.BYTES.getWireType());
codedOutStream.writeRawVarint32(types.length);
codedOutStream.writeRawBytes(types);
codedOutStream.writeSInt64(OsmandOdb.MapData.ID_FIELD_NUMBER, id - stackBaseIds.peek());
if(name != null){
codedOutStream.writeUInt32(OsmandOdb.MapData.STRINGID_FIELD_NUMBER, nameId);
}
}
if(restrictions.length > 0){
codedOutStream.writeTag(OsmandOdb.MapData.RESTRICTIONS_FIELD_NUMBER, WireFormat.FieldType.BYTES.getWireType());

View file

@ -785,7 +785,7 @@ public final class CodedInputStreamRAF {
} else {
// Skipping more bytes than are in the buffer. First skip what we have.
int pos = bufferSize - bufferPos;
totalBytesRetired += pos;
totalBytesRetired += bufferSize;
bufferPos = 0;
bufferSize = 0;
@ -802,8 +802,8 @@ public final class CodedInputStreamRAF {
}
public void seek(long pointer) throws IOException{
if(pointer - totalBytesRetired > 0 && pointer - totalBytesRetired < bufferSize){
skipRawBytes((int) (pointer - totalBytesRetired));
if(pointer - totalBytesRetired >= 0 && pointer - totalBytesRetired < bufferSize){
skipRawBytes((int) (pointer - getTotalBytesRead()));
} else {
totalBytesRetired = (int) pointer;
raf.seek(pointer);