From 3b4f0ec85fd73a1bc46fcdbc81fbfeb099dd709a Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Thu, 22 Sep 2011 22:12:15 +0200 Subject: [PATCH] Fix binary poi search --- .../osmand/binary/BinaryMapIndexReader.java | 1 + .../osmand/binary/BinaryMapIndexWriter.java | 2 +- .../binary/BinaryMapPoiReaderAdapter.java | 214 +++++++++++++++++- 3 files changed, 215 insertions(+), 2 deletions(-) diff --git a/DataExtractionOSM/src/net/osmand/binary/BinaryMapIndexReader.java b/DataExtractionOSM/src/net/osmand/binary/BinaryMapIndexReader.java index b463a66db9..2dd4e274e4 100644 --- a/DataExtractionOSM/src/net/osmand/binary/BinaryMapIndexReader.java +++ b/DataExtractionOSM/src/net/osmand/binary/BinaryMapIndexReader.java @@ -1150,6 +1150,7 @@ public class BinaryMapIndexReader { System.out.println(poiRegion.categories.get(i)); System.out.println(" " + poiRegion.subcategories.get(i)); } + http://www.openstreetmap.org/?lat=55.81111&lon=37.72368&zoom=16&layers=M System.out.println("MEMORY " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())); //$NON-NLS-1$ System.out.println("Time " + (System.currentTimeMillis() - time)); //$NON-NLS-1$ diff --git a/DataExtractionOSM/src/net/osmand/binary/BinaryMapIndexWriter.java b/DataExtractionOSM/src/net/osmand/binary/BinaryMapIndexWriter.java index c037636a5f..6c74fb8b4e 100644 --- a/DataExtractionOSM/src/net/osmand/binary/BinaryMapIndexWriter.java +++ b/DataExtractionOSM/src/net/osmand/binary/BinaryMapIndexWriter.java @@ -825,7 +825,7 @@ public class BinaryMapIndexWriter { // write shift to that data long filePointer = raf.getFilePointer(); raf.seek(fpPoiBox); - raf.writeInt((int) (startPoiData - fpPoiIndex)); + raf.writeInt((int) (startPoiData - fpPoiIndex - 4)); raf.seek(filePointer); codedOutStream.writeUInt32(OsmandOdb.OsmAndPoiBoxData.ZOOM_FIELD_NUMBER, zoom); diff --git a/DataExtractionOSM/src/net/osmand/binary/BinaryMapPoiReaderAdapter.java b/DataExtractionOSM/src/net/osmand/binary/BinaryMapPoiReaderAdapter.java index f84479fd8f..03dcc0f34b 100644 --- a/DataExtractionOSM/src/net/osmand/binary/BinaryMapPoiReaderAdapter.java +++ b/DataExtractionOSM/src/net/osmand/binary/BinaryMapPoiReaderAdapter.java @@ -1,18 +1,33 @@ package net.osmand.binary; +import gnu.trove.list.array.TIntArrayList; +import gnu.trove.map.hash.TLongObjectHashMap; +import gnu.trove.set.hash.TIntHashSet; + import java.io.IOException; import java.util.ArrayList; import java.util.List; +import net.osmand.Algoritms; +import net.osmand.binary.BinaryMapIndexReader.SearchRequest; +import net.osmand.data.Amenity; +import net.osmand.data.AmenityType; +import net.osmand.osm.MapUtils; +import net.sf.junidecode.Junidecode; + import com.google.protobuf.CodedInputStreamRAF; import com.google.protobuf.WireFormat; public class BinaryMapPoiReaderAdapter { + public static final int SHIFT_BITS_CATEGORY = 7; + private static final int CATEGORY_MASK = (1 << SHIFT_BITS_CATEGORY) - 1 ; + public static class PoiRegion extends BinaryIndexPart { List categories = new ArrayList(); + List categoriesType = new ArrayList(); List> subcategories = new ArrayList>(); } @@ -68,7 +83,9 @@ public class BinaryMapPoiReaderAdapter { case 0: return; case OsmandOdb.OsmAndCategoryTable.CATEGORY_FIELD_NUMBER : - region.categories.add(codedIS.readString()); + String cat = codedIS.readString(); + region.categories.add(cat); + region.categoriesType.add(AmenityType.fromString(cat)); region.subcategories.add(new ArrayList()); break; case OsmandOdb.OsmAndCategoryTable.SUBCATEGORIES_FIELD_NUMBER : @@ -81,5 +98,200 @@ public class BinaryMapPoiReaderAdapter { } } + protected void searchPoiIndex(int left31, int right31, int top31, int bottom31, + SearchRequest req, PoiRegion region) throws IOException { + int indexOffset = codedIS.getTotalBytesRead(); + TIntArrayList offsets = new TIntArrayList(); + while(true){ + if(req.isInterrupted()){ + return; + } + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case OsmandOdb.OsmAndPoiIndex.BOXES_FIELD_NUMBER : + int length = codedIS.readFixed32(); + int oldLimit = codedIS.pushLimit(length); + readBoxField(left31, right31, top31, bottom31, 0, 0, 0, offsets, req); + codedIS.popLimit(oldLimit); + break; + case OsmandOdb.OsmAndPoiIndex.POIDATA_FIELD_NUMBER : + offsets.sort(); + for (int j = 0; j < offsets.size(); j++) { + codedIS.seek(offsets.get(j) + indexOffset); + int len = codedIS.readFixed32(); + int oldLim = codedIS.pushLimit(len); + readPoiData(left31, right31, top31, bottom31, req, region); + codedIS.popLimit(oldLim); + if(req.isInterrupted()){ + return; + } + } + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return; + default: + skipUnknownField(t); + break; + } + } + } + + private void readPoiData(int left31, int right31, int top31, int bottom31, + SearchRequest req, PoiRegion region) throws IOException { + int x = 0; + int y = 0; + int zoom = 0; + while(true){ + if(req.isInterrupted()){ + return; + } + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case OsmandOdb.OsmAndPoiBoxData.X_FIELD_NUMBER : + x = codedIS.readUInt32(); + break; + case OsmandOdb.OsmAndPoiBoxData.ZOOM_FIELD_NUMBER : + zoom = codedIS.readUInt32(); + break; + case OsmandOdb.OsmAndPoiBoxData.Y_FIELD_NUMBER : + y= codedIS.readUInt32(); + break; + case OsmandOdb.OsmAndPoiBoxData.POIDATA_FIELD_NUMBER: + int len = codedIS.readRawVarint32(); + int oldLim = codedIS.pushLimit(len); + readPoiPoint(left31, right31, top31, bottom31, x, y, zoom, req, region); + codedIS.popLimit(oldLim); + return; + default: + skipUnknownField(t); + break; + } + } + } + + private void readPoiPoint(int left31, int right31, int top31, int bottom31, + int px, int py, int zoom, SearchRequest req, PoiRegion region) throws IOException { + Amenity am = null; + int x = 0; + int y = 0; + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + if(Algoritms.isEmpty(am.getEnName())){ + am.setEnName(Junidecode.unidecode(am.getName())); + } + req.getSearchResults().add(am); + return; + case OsmandOdb.OsmAndPoiBoxDataAtom.DX_FIELD_NUMBER : + x = (codedIS.readSInt32() + (px << (24 - zoom))) << 7; + break; + case OsmandOdb.OsmAndPoiBoxDataAtom.DY_FIELD_NUMBER : + y = (codedIS.readSInt32() + (py << (24 - zoom))) << 7; + if(left31 > x || right31 < x || top31 < y || bottom31 > y){ + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return; + } + am = new Amenity(); + am.setLocation(MapUtils.get31LatitudeY(y), MapUtils.get31LongitudeX(x)); + break; + case OsmandOdb.OsmAndPoiBoxDataAtom.CATEGORIES_FIELD_NUMBER : + // TODO add many amenities + int cat = codedIS.readUInt32(); + int subcatId = cat >> SHIFT_BITS_CATEGORY; + int catId = cat & CATEGORY_MASK; + if(catId < region.categoriesType.size()){ + am.setType(region.categoriesType.get(catId)); + List subcats = region.subcategories.get(catId); + if(subcatId < subcats.size()){ + am.setSubType(subcats.get(catId)); + } + } else { + am.setType(AmenityType.OTHER); + } + break; + case OsmandOdb.OsmAndPoiBoxDataAtom.ID_FIELD_NUMBER : + am.setId(codedIS.readUInt64()); + break; + case OsmandOdb.OsmAndPoiBoxDataAtom.NAME_FIELD_NUMBER : + am.setName(codedIS.readString()); + break; + case OsmandOdb.OsmAndPoiBoxDataAtom.NAMEEN_FIELD_NUMBER : + am.setEnName(codedIS.readString()); + break; + case OsmandOdb.OsmAndPoiBoxDataAtom.OPENINGHOURS_FIELD_NUMBER : + am.setOpeningHours(codedIS.readString()); + break; + case OsmandOdb.OsmAndPoiBoxDataAtom.SITE_FIELD_NUMBER : + am.setSite(codedIS.readString()); + break; + case OsmandOdb.OsmAndPoiBoxDataAtom.PHONE_FIELD_NUMBER: + am.setPhone(codedIS.readString()); + break; + default: + skipUnknownField(t); + break; + } + } + } + + private void readBoxField(int left31, int right31, int top31, int bottom31, + int px, int py, int pzoom, TIntArrayList offsets, SearchRequest req) throws IOException { + if(pzoom > 0){ + int x1 = px << (31 - pzoom); + int x2 = (px + 1) << (31 - pzoom); + int y1 = py << (31 - pzoom); + int y2 = (py + 1) << (31 - pzoom); + // check intersection + if(!(left31 <= x2 && x1 <= right31 && bottom31 <= y2 && y1 <= top31)){ + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + } + + } + int zoom = pzoom; + int y = py; + int x = px; + while(true){ + if(req.isInterrupted()){ + return; + } + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case OsmandOdb.OsmAndPoiBox.ZOOM_FIELD_NUMBER : + zoom = codedIS.readUInt32() + pzoom; + break; + case OsmandOdb.OsmAndPoiBox.LEFT_FIELD_NUMBER : + x = codedIS.readSInt32() + px; + break; + case OsmandOdb.OsmAndPoiBox.TOP_FIELD_NUMBER: + y = codedIS.readSInt32() + py; + break; + + case OsmandOdb.OsmAndPoiBox.SUBBOXES_FIELD_NUMBER: + int length = codedIS.readFixed32(); + int oldLimit = codedIS.pushLimit(length); + readBoxField(left31, right31, top31, bottom31, x, y, zoom, offsets, req); + codedIS.popLimit(oldLimit); + break; + + case OsmandOdb.OsmAndPoiBox.SHIFTTODATA_FIELD_NUMBER: + offsets.add(codedIS.readFixed32()); + break; + default: + skipUnknownField(t); + break; + } + } + } + }