POI Name index

This commit is contained in:
Victor Shcherb 2011-09-27 01:22:07 +02:00
parent 068a15d7cc
commit 54c3487c48
6 changed files with 1848 additions and 648 deletions

View file

@ -42,6 +42,7 @@ import com.google.protobuf.WireFormat;
public class BinaryMapIndexReader { public class BinaryMapIndexReader {
public final static int TRANSPORT_STOP_ZOOM = 24; public final static int TRANSPORT_STOP_ZOOM = 24;
protected static final int SHIFT_COORDINATES = 5;
private final static Log log = LogUtil.getLog(BinaryMapIndexReader.class); private final static Log log = LogUtil.getLog(BinaryMapIndexReader.class);
private final RandomAccessFile raf; private final RandomAccessFile raf;
@ -807,7 +808,7 @@ public class BinaryMapIndexReader {
} }
} }
private int MASK_TO_READ = ~((1 << BinaryMapIndexWriter.SHIFT_COORDINATES) - 1); private int MASK_TO_READ = ~((1 << SHIFT_COORDINATES) - 1);
private BinaryMapDataObject readMapDataObject(int left, int right, int top, int bottom, SearchRequest<BinaryMapDataObject> req, private BinaryMapDataObject readMapDataObject(int left, int right, int top, int bottom, SearchRequest<BinaryMapDataObject> req,
MapIndex root) throws IOException { MapIndex root) throws IOException {
int tag = WireFormat.getTagFieldNumber(codedIS.readTag()); int tag = WireFormat.getTagFieldNumber(codedIS.readTag());
@ -826,8 +827,8 @@ public class BinaryMapIndexReader {
int maxY = 0; int maxY = 0;
req.numberOfVisitedObjects++; req.numberOfVisitedObjects++;
while(codedIS.getBytesUntilLimit() > 0){ while(codedIS.getBytesUntilLimit() > 0){
int x = (codedIS.readSInt32() << BinaryMapIndexWriter.SHIFT_COORDINATES) + px; int x = (codedIS.readSInt32() << SHIFT_COORDINATES) + px;
int y = (codedIS.readSInt32() << BinaryMapIndexWriter.SHIFT_COORDINATES) + py; int y = (codedIS.readSInt32() << SHIFT_COORDINATES) + py;
req.cacheCoordinates.add(x); req.cacheCoordinates.add(x);
req.cacheCoordinates.add(y); req.cacheCoordinates.add(y);
px = x; px = x;

View file

@ -1,6 +1,8 @@
package net.osmand.binary; package net.osmand.binary;
import gnu.trove.list.TLongList;
import gnu.trove.list.array.TIntArrayList; import gnu.trove.list.array.TIntArrayList;
import gnu.trove.list.array.TLongArrayList;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
@ -18,6 +20,8 @@ import net.osmand.binary.OsmandOdb.CityIndex;
import net.osmand.binary.OsmandOdb.InteresectedStreets; import net.osmand.binary.OsmandOdb.InteresectedStreets;
import net.osmand.binary.OsmandOdb.MapEncodingRule; import net.osmand.binary.OsmandOdb.MapEncodingRule;
import net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom; import net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom;
import net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexData;
import net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom;
import net.osmand.binary.OsmandOdb.OsmAndTransportIndex; import net.osmand.binary.OsmandOdb.OsmAndTransportIndex;
import net.osmand.binary.OsmandOdb.PostcodeIndex; import net.osmand.binary.OsmandOdb.PostcodeIndex;
import net.osmand.binary.OsmandOdb.StreetIndex; import net.osmand.binary.OsmandOdb.StreetIndex;
@ -31,6 +35,7 @@ import net.osmand.data.IndexConstants;
import net.osmand.data.MapObject; import net.osmand.data.MapObject;
import net.osmand.data.Street; import net.osmand.data.Street;
import net.osmand.data.TransportStop; import net.osmand.data.TransportStop;
import net.osmand.data.preparation.IndexPoiCreator.PoiTileBox;
import net.osmand.osm.LatLon; import net.osmand.osm.LatLon;
import net.osmand.osm.MapUtils; import net.osmand.osm.MapUtils;
import net.osmand.osm.Node; import net.osmand.osm.Node;
@ -38,6 +43,7 @@ import net.osmand.osm.MapRenderingTypes.MapRulType;
import net.sf.junidecode.Junidecode; import net.sf.junidecode.Junidecode;
import com.google.protobuf.CodedOutputStream; import com.google.protobuf.CodedOutputStream;
import com.google.protobuf.MessageLite;
import com.google.protobuf.WireFormat; import com.google.protobuf.WireFormat;
import com.google.protobuf.WireFormat.FieldType; import com.google.protobuf.WireFormat.FieldType;
@ -45,7 +51,7 @@ public class BinaryMapIndexWriter {
private RandomAccessFile raf; private RandomAccessFile raf;
private CodedOutputStream codedOutStream; private CodedOutputStream codedOutStream;
protected static final int SHIFT_COORDINATES = 5; protected static final int SHIFT_COORDINATES = BinaryMapIndexReader.SHIFT_COORDINATES;
private static class Bounds { private static class Bounds {
public Bounds(int leftX, int rightX, int topY, int bottomY) { public Bounds(int leftX, int rightX, int topY, int bottomY) {
@ -806,27 +812,75 @@ public class BinaryMapIndexWriter {
codedOutStream.writeMessage(OsmandOdb.OsmAndPoiBox.CATEGORIES_FIELD_NUMBER, builder.build()); codedOutStream.writeMessage(OsmandOdb.OsmAndPoiBox.CATEGORIES_FIELD_NUMBER, builder.build());
} }
public void writePoiIncludedStrings(Set<String> includes) throws IOException { public Map<PoiTileBox, TLongList> writePoiNameIndex(Map<String, List<PoiTileBox>> namesIndex, long fpPoiIndex) throws IOException {
checkPeekState(POI_BOX); checkPeekState(POI_INDEX_INIT);
OsmandOdb.IndexedStringTable.Builder builder = OsmandOdb.IndexedStringTable.newBuilder(); codedOutStream.writeTag(OsmandOdb.OsmAndPoiIndex.NAMEINDEX_FIELD_NUMBER, WireFormat.WIRETYPE_FIXED32_LENGTH_DELIMITED);
for(String s : includes){ preserveInt32Size();
builder.addKey(s);
} Map<String, MessageLite> message = new LinkedHashMap<String, MessageLite>();
codedOutStream.writeMessage(OsmandOdb.OsmAndPoiBox.INCLUDENAMESLIST_FIELD_NUMBER, builder.build()); Map<String, Integer> indexedTable = new LinkedHashMap<String, Integer>();
} Map<PoiTileBox, TLongList> fpToWriteSeeks = new LinkedHashMap<PoiTileBox, TLongList>();
int previousSize = 0;
public void writePoiExcludedStrings(Set<String> parentNames, Set<String> includes) throws IOException { for(Map.Entry<String, List<PoiTileBox>> e : namesIndex.entrySet()) {
checkPeekState(POI_BOX); OsmandOdb.OsmAndPoiNameIndexData.Builder builder = OsmandOdb.OsmAndPoiNameIndexData.newBuilder();
OsmandOdb.IndexedStringTable.Builder builder = OsmandOdb.IndexedStringTable.newBuilder(); List<PoiTileBox> tileBoxes = e.getValue();
for(String s : parentNames){ for(PoiTileBox box : tileBoxes) {
if(!includes.contains(s)){ OsmandOdb.OsmAndPoiNameIndexDataAtom.Builder bs = OsmandOdb.OsmAndPoiNameIndexDataAtom.newBuilder();
builder.addKey(s); bs.setX(box.getX());
bs.setY(box.getY());
bs.setZoom(box.getZoom());
bs.setShiftTo(0);
OsmAndPoiNameIndexDataAtom atom = bs.build();
builder.addAtoms(atom);
}
OsmAndPoiNameIndexData msg = builder.build();
message.put(e.getKey(), msg);
indexedTable.put(e.getKey(), previousSize);
previousSize += CodedOutputStream.computeMessageSize(OsmandOdb.OsmAndPoiNameIndex.DATA_FIELD_NUMBER, msg);
int accumulateSize = 4;
for (int i = tileBoxes.size() - 1; i >= 0; i--) {
PoiTileBox box = tileBoxes.get(i);
if (!fpToWriteSeeks.containsKey(box)) {
fpToWriteSeeks.put(box, new TLongArrayList());
}
fpToWriteSeeks.get(box).add(previousSize - accumulateSize);
accumulateSize += CodedOutputStream.computeMessageSize(
OsmandOdb.OsmAndPoiNameIndexData.ATOMS_FIELD_NUMBER, msg.getAtoms(i));
}
}
writeIndexedTable(OsmandOdb.OsmAndPoiNameIndex.TABLE_FIELD_NUMBER, indexedTable);
codedOutStream.flush();
int diff = (int) (raf.getFilePointer() - fpPoiIndex);
for (TLongList es : fpToWriteSeeks.values()) {
for (int i = 0; i < es.size(); i++) {
es.set(i, es.get(i) + diff);
} }
} }
codedOutStream.writeMessage(OsmandOdb.OsmAndPoiBox.EXCLUDENAMESLIST_FIELD_NUMBER, builder.build());
for(Map.Entry<String, MessageLite> s : message.entrySet()) {
codedOutStream.writeMessage(OsmandOdb.OsmAndPoiNameIndex.DATA_FIELD_NUMBER, s.getValue());
}
writeInt32Size();
return fpToWriteSeeks;
} }
private void writeIndexedTable(int tag, Map<String, Integer> indexedTable) throws IOException {
codedOutStream.writeTag(tag, WireFormat.WIRETYPE_FIXED32_LENGTH_DELIMITED);
preserveInt32Size();
for(Map.Entry<String, Integer> e : indexedTable.entrySet()){
codedOutStream.writeString(OsmandOdb.IndexedStringTable.KEY_FIELD_NUMBER, e.getKey());
codedOutStream.writeUInt32(OsmandOdb.IndexedStringTable.VAL_FIELD_NUMBER, e.getValue());
}
writeInt32Size();
}
public void writePoiDataAtom(long id, int x24shift, int y24shift, String nameEn, String name, TIntArrayList types, String openingHours, public void writePoiDataAtom(long id, int x24shift, int y24shift, String nameEn, String name, TIntArrayList types, String openingHours,
String site, String phone) throws IOException { String site, String phone) throws IOException {
checkPeekState(POI_DATA); checkPeekState(POI_DATA);
@ -860,14 +914,16 @@ public class BinaryMapIndexWriter {
} }
public void startWritePoiData(int zoom, int x, int y, long fpPoiIndex, long fpPoiBox) throws IOException { public void startWritePoiData(int zoom, int x, int y, long fpPoiIndex, TLongList fpPoiBox) throws IOException {
pushState(POI_DATA, POI_INDEX_INIT); pushState(POI_DATA, POI_INDEX_INIT);
codedOutStream.writeTag(OsmandOdb.OsmAndPoiIndex.POIDATA_FIELD_NUMBER, WireFormat.WIRETYPE_FIXED32_LENGTH_DELIMITED); codedOutStream.writeTag(OsmandOdb.OsmAndPoiIndex.POIDATA_FIELD_NUMBER, WireFormat.WIRETYPE_FIXED32_LENGTH_DELIMITED);
long startPoiData = preserveInt32Size(); long startPoiData = preserveInt32Size();
// write shift to that data // write shift to that data
long filePointer = raf.getFilePointer(); long filePointer = raf.getFilePointer();
raf.seek(fpPoiBox); for (int i = 0; i < fpPoiBox.size(); i++) {
raf.writeInt((int) (startPoiData - fpPoiIndex - 4)); raf.seek(fpPoiBox.get(i));
raf.writeInt((int) (startPoiData - fpPoiIndex - 4));
}
raf.seek(filePointer); raf.seek(filePointer);
codedOutStream.writeUInt32(OsmandOdb.OsmAndPoiBoxData.ZOOM_FIELD_NUMBER, zoom); codedOutStream.writeUInt32(OsmandOdb.OsmAndPoiBoxData.ZOOM_FIELD_NUMBER, zoom);

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,8 @@
package net.osmand.data.preparation; package net.osmand.data.preparation;
import gnu.trove.list.TLongList;
import gnu.trove.list.array.TIntArrayList; import gnu.trove.list.array.TIntArrayList;
import gnu.trove.list.array.TLongArrayList;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -18,9 +20,7 @@ import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.TreeSet;
import net.osmand.Algoritms; import net.osmand.Algoritms;
import net.osmand.IProgress; import net.osmand.IProgress;
@ -49,8 +49,6 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
private static final int ZOOM_TO_SAVE_START = 6; private static final int ZOOM_TO_SAVE_START = 6;
private static final int ZOOM_TO_WRITE_CATEGORIES_START = 12; private static final int ZOOM_TO_WRITE_CATEGORIES_START = 12;
private static final int ZOOM_TO_WRITE_CATEGORIES_END = 16; private static final int ZOOM_TO_WRITE_CATEGORIES_END = 16;
private static final int ZOOM_TO_WRITE_NAME_START = 9;
private static final int ZOOM_TO_WRITE_NAME_END = 11;
private boolean useInMemoryCreator = true; private boolean useInMemoryCreator = true;
@ -195,6 +193,8 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
Collator collator = Collator.getInstance(); Collator collator = Collator.getInstance();
collator.setStrength(Collator.PRIMARY); collator.setStrength(Collator.PRIMARY);
Map<String, List<PoiTileBox>> namesIndex = new LinkedHashMap<String, List<PoiTileBox>>();
// 0. process all entities // 0. process all entities
ResultSet rs; ResultSet rs;
if(useInMemoryCreator) { if(useInMemoryCreator) {
@ -203,8 +203,8 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
rs = poiConnection.createStatement().executeQuery("SELECT x,y,name,name_en,type,subtype from poi"); rs = poiConnection.createStatement().executeQuery("SELECT x,y,name,name_en,type,subtype from poi");
} }
int zoomToStart = ZOOM_TO_SAVE_START; int zoomToStart = ZOOM_TO_SAVE_START;
Tree<PoiBox> rootZoomsTree = new Tree<PoiBox>(); Tree<PoiTileBox> rootZoomsTree = new Tree<PoiTileBox>();
rootZoomsTree.setNode(new PoiBox()); rootZoomsTree.setNode(new PoiTileBox());
int minX = Integer.MAX_VALUE; int minX = Integer.MAX_VALUE;
int maxX = 0; int maxX = 0;
int minY = Integer.MAX_VALUE; int minY = Integer.MAX_VALUE;
@ -227,22 +227,21 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
String type = rs.getString(5); String type = rs.getString(5);
String subtype = rs.getString(6); String subtype = rs.getString(6);
Tree<PoiBox> prevTree = rootZoomsTree; Tree<PoiTileBox> prevTree = rootZoomsTree;
rootZoomsTree.getNode().addCategory(type, subtype); rootZoomsTree.getNode().addCategory(type, subtype);
rootZoomsTree.getNode().addNamePrefix(name, nameEn);
for (int i = zoomToStart; i <= ZOOM_TO_SAVE_END; i++) { for (int i = zoomToStart; i <= ZOOM_TO_SAVE_END; i++) {
int xs = x >> (31 - i); int xs = x >> (31 - i);
int ys = y >> (31 - i); int ys = y >> (31 - i);
Tree<PoiBox> subtree = null; Tree<PoiTileBox> subtree = null;
for (Tree<PoiBox> sub : prevTree.getSubtrees()) { for (Tree<PoiTileBox> sub : prevTree.getSubtrees()) {
if (sub.getNode().x == xs && sub.getNode().y == ys && sub.getNode().zoom == i) { if (sub.getNode().x == xs && sub.getNode().y == ys && sub.getNode().zoom == i) {
subtree = sub; subtree = sub;
break; break;
} }
} }
if (subtree == null) { if (subtree == null) {
subtree = new Tree<PoiBox>(); subtree = new Tree<PoiTileBox>();
PoiBox poiBox = new PoiBox(); PoiTileBox poiBox = new PoiTileBox();
subtree.setNode(poiBox); subtree.setNode(poiBox);
poiBox.x = xs; poiBox.x = xs;
poiBox.y = ys; poiBox.y = ys;
@ -251,10 +250,11 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
prevTree.addSubTree(subtree); prevTree.addSubTree(subtree);
} }
subtree.getNode().addCategory(type, subtype); subtree.getNode().addCategory(type, subtype);
subtree.getNode().addNamePrefix(name, nameEn);
prevTree = subtree; prevTree = subtree;
} }
addNamePrefix(name, nameEn, prevTree.getNode(), namesIndex);
if (useInMemoryCreator) { if (useInMemoryCreator) {
if (prevTree.getNode().poiData == null) { if (prevTree.getNode().poiData == null) {
prevTree.getNode().poiData = new ArrayList<PoiData>(); prevTree.getNode().poiData = new ArrayList<PoiData>();
@ -287,6 +287,9 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
// 2. write categories table // 2. write categories table
Map<String, Map<String, Integer>> categories = rootZoomsTree.node.categories; Map<String, Map<String, Integer>> categories = rootZoomsTree.node.categories;
Map<String, Integer> catIndexes = writer.writePOICategoriesTable(categories); Map<String, Integer> catIndexes = writer.writePOICategoriesTable(categories);
// 2.5 write names table
Map<PoiTileBox, TLongList> fpToWriteSeeks = writer.writePoiNameIndex(namesIndex, startFpPoiIndex);
// 3. write boxes // 3. write boxes
log.info("Poi box processing finishied"); log.info("Poi box processing finishied");
@ -304,9 +307,8 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
} }
// 3.2 write tree using stack // 3.2 write tree using stack
Map<PoiBox, Long> fpToWriteSeeks = new LinkedHashMap<PoiBox, Long>(); for (Tree<PoiTileBox> subs : rootZoomsTree.getSubtrees()) {
for (Tree<PoiBox> subs : rootZoomsTree.getSubtrees()) { writePoiBoxes(writer, subs, fpToWriteSeeks, categories, catIndexes);
writePoiBoxes(writer, subs, fpToWriteSeeks, categories, catIndexes, rootZoomsTree.getNode().startsName);
} }
// 4. write poi data // 4. write poi data
@ -315,7 +317,7 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
.prepareStatement("SELECT id, x, y, name_en, name, type, subtype, opening_hours, site, phone from poi " .prepareStatement("SELECT id, x, y, name_en, name, type, subtype, opening_hours, site, phone from poi "
+ "where x >= ? AND x < ? AND y >= ? AND y < ?"); + "where x >= ? AND x < ? AND y >= ? AND y < ?");
TIntArrayList types = new TIntArrayList(); TIntArrayList types = new TIntArrayList();
for (Map.Entry<PoiBox, Long> entry : fpToWriteSeeks.entrySet()) { for (Map.Entry<PoiTileBox, TLongList> entry : fpToWriteSeeks.entrySet()) {
int z = entry.getKey().zoom; int z = entry.getKey().zoom;
int x = entry.getKey().x; int x = entry.getKey().x;
int y = entry.getKey().y; int y = entry.getKey().y;
@ -372,10 +374,43 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
writer.endWritePOIIndex(); writer.endWritePOIIndex();
} }
public void addNamePrefix(String name, String nameEn, PoiTileBox data, Map<String, List<PoiTileBox>> poiData) {
if(Algoritms.isEmpty(nameEn)){
nameEn = Junidecode.unidecode(name);
}
parsePrefix(name, data, poiData);
parsePrefix(nameEn, data, poiData);
}
private void writePoiBoxes(BinaryMapIndexWriter writer, Tree<PoiBox> tree, Map<PoiBox, Long> fpToWriteSeeks, private void parsePrefix(String name, PoiTileBox data, Map<String, List<PoiTileBox>> poiData) {
Map<String, Map<String, Integer>> categories, Map<String, Integer> catIndexes, int prev = -1;
Set<String> parentNames) throws IOException, SQLException { for (int i = 0; i <= name.length(); i++) {
if (i == name.length() || (!Character.isLetter(name.charAt(i)) &&
!Character.isDigit(name.charAt(i)))) {
if (prev != -1) {
String substr = name.substring(prev, i);
if (substr.length() > 3) {
substr = substr.substring(0, 3);
}
String val = substr.toLowerCase();
if(!poiData.containsKey(val)){
poiData.put(val, new ArrayList<PoiTileBox>());
}
poiData.get(val).add(data);
prev = -1;
}
} else {
if(prev == -1){
prev = i;
}
}
}
}
private void writePoiBoxes(BinaryMapIndexWriter writer, Tree<PoiTileBox> tree, Map<PoiTileBox, TLongList> fpToWriteSeeks,
Map<String, Map<String, Integer>> categories, Map<String, Integer> catIndexes) throws IOException, SQLException {
int x = tree.getNode().x; int x = tree.getNode().x;
int y = tree.getNode().y; int y = tree.getNode().y;
int zoom = tree.getNode().zoom; int zoom = tree.getNode().zoom;
@ -391,25 +426,16 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
} }
writer.writePOICategories(types); writer.writePOICategories(types);
} }
if(zoom >= ZOOM_TO_WRITE_NAME_START && zoom <= ZOOM_TO_WRITE_NAME_END){
Set<String> names = tree.getNode().startsName;
if (names.size() > 0) {
if (zoom == ZOOM_TO_WRITE_NAME_START || parentNames.size() - names.size() > names.size()) {
System.out.println("I" + names.size() + " " + zoom);
writer.writePoiIncludedStrings(names);
} else {
System.out.println("E" + (parentNames.size() - names.size()) + " " + zoom);
writer.writePoiExcludedStrings(parentNames, names);
}
}
}
if (!end) { if (!end) {
for (Tree<PoiBox> subTree : tree.getSubtrees()) { for (Tree<PoiTileBox> subTree : tree.getSubtrees()) {
writePoiBoxes(writer, subTree, fpToWriteSeeks, categories, catIndexes, tree.getNode().startsName); writePoiBoxes(writer, subTree, fpToWriteSeeks, categories, catIndexes);
} }
} else { } else {
fpToWriteSeeks.put(tree.getNode(), fp); if(!fpToWriteSeeks.containsKey(tree.getNode())) {
fpToWriteSeeks.put(tree.getNode(), new TLongArrayList());
}
fpToWriteSeeks.get(tree.getNode()).add(fp);
} }
writer.endWritePoiBox(); writer.endWritePoiBox();
} }
@ -427,14 +453,24 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
String site; String site;
} }
private static class PoiBox { public static class PoiTileBox {
int x; int x;
int y; int y;
int zoom; int zoom;
Map<String, Map<String, Integer>> categories = new LinkedHashMap<String, Map<String, Integer>>(); Map<String, Map<String, Integer>> categories = new LinkedHashMap<String, Map<String, Integer>>();
Set<String> startsName = new TreeSet<String>();
List<PoiData> poiData = null; List<PoiData> poiData = null;
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getZoom() {
return zoom;
}
private void addCategory(String cat, String subCat){ private void addCategory(String cat, String subCat){
if(!categories.containsKey(cat)){ if(!categories.containsKey(cat)){
categories.put(cat, new TreeMap<String, Integer>()); categories.put(cat, new TreeMap<String, Integer>());
@ -450,35 +486,6 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
categories.get(cat).put(subCat, 0); categories.get(cat).put(subCat, 0);
} }
public void addNamePrefix(String name, String nameEn) {
if(Algoritms.isEmpty(nameEn)){
nameEn = Junidecode.unidecode(name);
}
parsePrefix(name);
parsePrefix(nameEn);
}
private void parsePrefix(String name) {
int prev = -1;
for (int i = 0; i <= name.length(); i++) {
if (i == name.length() || (!Character.isLetter(name.charAt(i)) &&
!Character.isDigit(name.charAt(i)))) {
if (prev != -1) {
String substr = name.substring(prev, i);
if (substr.length() > 3) {
substr = substr.substring(0, 3);
}
startsName.add(substr.toLowerCase());
prev = -1;
}
} else {
if(prev == -1){
prev = i;
}
}
}
}
} }
private static class Tree<T> { private static class Tree<T> {

View file

@ -1,7 +1,6 @@
option java_package = "net.osmand.binary"; option java_package = "net.osmand.binary";
//protoc --java_out=../.. osmand_odb.proto //protoc --java_out=../.. osmand_odb.proto
// //
// STORAGE LAYER: Storing primitives. // STORAGE LAYER: Storing primitives.
// //
@ -30,6 +29,20 @@ message StringTable {
repeated string s = 1; repeated string s = 1;
} }
message IndexedStringTable {
// common prefix for all strings inside
optional string prefix = 1;
// key, val and subtables are mixed and order is preserved by key (ascending)
// so that's example of data : key1,val1,subtables1,key2,val2,key3,val3,subtables3,subtables3
repeated string key = 3;
// the shift to the data or one uint data itself
repeated uint32 val = 4;
// subtables are supposed to make search faster instead of searching through all strings
// it's enought to read prefix in the header
repeated IndexedStringTable subtables = 5;
}
message OsmAndMapIndex { message OsmAndMapIndex {
// encoded as fixed32 length delimited // encoded as fixed32 length delimited
repeated MapRootLevel levels = 1; repeated MapRootLevel levels = 1;
@ -82,8 +95,6 @@ message MapTree {
} }
/// Simple messages /// Simple messages
message MapData { message MapData {
required bytes coordinates = 1; // array of delta x,y sint32 (CodedIinputStream) >> 5 required bytes coordinates = 1; // array of delta x,y sint32 (CodedIinputStream) >> 5
@ -275,6 +286,8 @@ message OsmAndPoiIndex {
repeated OsmAndCategoryTable categoriesTable = 3; repeated OsmAndCategoryTable categoriesTable = 3;
// leave space for other indexes // leave space for other indexes
// encoded as fixed32 length delimited
optional OsmAndPoiNameIndex nameIndex = 4;
// encoded as fixed32 length delimited // encoded as fixed32 length delimited
repeated OsmAndPoiBox boxes = 6; // children repeated OsmAndPoiBox boxes = 6; // children
@ -284,19 +297,34 @@ message OsmAndPoiIndex {
} }
message IndexedStringTable { message OsmAndPoiNameIndex {
// common prefix for all strings inside
optional string prefix = 1; // shift to data starting from first OsmAndPoiNameIndexData message
// encoded as fixed32 length delimited
required IndexedStringTable table = 2;
// key, val and subtables are mixed and order is preserved by key (ascending) repeated OsmAndPoiNameIndexData data = 5;
// so that's example of data : key1,val1,subtables1,key2,val2,key3,val3,subtables3,subtables3 }
repeated string key = 3;
// the shift to the data or one uint data itself message OsmAndPoiNameIndexData {
repeated uint32 val = 4;
// subtables are supposed to make search faster instead of searching through all strings // can contain multiple data offsets
// it's enought to read prefix in the header repeated OsmAndPoiNameIndexDataAtom atoms = 4;
repeated IndexedStringTable subtables = 5; }
}
message OsmAndPoiNameIndexDataAtom {
// fields do not preserve order define, they are repeating
optional uint32 zoom = 2;
optional uint32 x = 3;
optional uint32 y = 4;
// Must be the last
// shift to OsmAndPoiBoxData message from OsmAndPoiIndex.start
// message is started when body is started
optional fixed32 shiftTo = 14;
}
message OsmAndCategoryTable { message OsmAndCategoryTable {
required string category = 1; required string category = 1;
@ -310,14 +338,11 @@ message OsmAndPoiBox {
required sint32 top = 3; // delta encoded (zoom) required sint32 top = 3; // delta encoded (zoom)
optional OsmAndPoiCategories categories = 4; optional OsmAndPoiCategories categories = 4;
optional IndexedStringTable includeNamesList = 5;
optional IndexedStringTable excludeNamesList = 6;
// encoded as fixed32 length delimited // encoded as fixed32 length delimited
repeated OsmAndPoiBox subBoxes = 10; repeated OsmAndPoiBox subBoxes = 10;
// must be the last
optional fixed32 shiftToData = 14; // shift to OsmAndPoiBoxData message from OsmAndPoiIndex.start optional fixed32 shiftToData = 14; // shift to OsmAndPoiBoxData message from OsmAndPoiIndex.start
// message is started when body is started // message is started when body is started
} }

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry kind="src" path="src"/> <classpathentry kind="src" path="src"/>
<classpathentry excluding="net/osmand/LogUtil.java|net/osmand/swing/|net/osmand/data/preparation/|net/osmand/osm/util/|net/osmand/data/index/|net/osmand/osm/io/OsmStorageWriter.java" kind="src" path="use"/> <classpathentry excluding="net/osmand/LogUtil.java|net/osmand/swing/|net/osmand/data/preparation/|net/osmand/osm/util/|net/osmand/data/index/|net/osmand/osm/io/OsmStorageWriter.java|net/osmand/binary/BinaryMapIndexWriter.java" kind="src" path="use"/>
<classpathentry kind="src" path="gen"/> <classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="lib" path="lib/bzip2-20090327.jar"/> <classpathentry kind="lib" path="lib/bzip2-20090327.jar"/>