Implement search by name. Refactor some binary file readers
This commit is contained in:
parent
54c3487c48
commit
5f95151338
12 changed files with 638 additions and 206 deletions
132
DataExtractionOSM/src/net/osmand/CollatorStringMatcher.java
Normal file
132
DataExtractionOSM/src/net/osmand/CollatorStringMatcher.java
Normal file
|
@ -0,0 +1,132 @@
|
|||
package net.osmand;
|
||||
|
||||
|
||||
import java.text.Collator;
|
||||
|
||||
import net.osmand.StringMatcher;
|
||||
|
||||
/**
|
||||
* Abstract collator matcher that basically supports subclasses with some collator
|
||||
* matching.
|
||||
*
|
||||
* @author pavol.zibrita
|
||||
*/
|
||||
public class CollatorStringMatcher implements StringMatcher {
|
||||
|
||||
private final Collator collator;
|
||||
private final StringMatcherMode mode;
|
||||
private final String part;
|
||||
|
||||
public enum StringMatcherMode {
|
||||
CHECK_ONLY_STARTS_WITH,
|
||||
CHECK_STARTS_FROM_SPACE,
|
||||
CHECK_STARTS_FROM_SPACE_NOT_BEGINNING,
|
||||
CHECK_CONTAINS
|
||||
}
|
||||
|
||||
public CollatorStringMatcher(Collator collator, String part, StringMatcherMode mode) {
|
||||
this.collator = collator;
|
||||
this.part = part;
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public Collator getCollator() {
|
||||
return collator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(String name) {
|
||||
return cmatches(collator, name, part, mode);
|
||||
}
|
||||
|
||||
|
||||
public static boolean cmatches(Collator collator, String base, String part, StringMatcherMode mode){
|
||||
switch (mode) {
|
||||
case CHECK_CONTAINS:
|
||||
return ccontains(collator, base, part);
|
||||
case CHECK_STARTS_FROM_SPACE:
|
||||
return cstartsWith(collator, base, part, true, true);
|
||||
case CHECK_STARTS_FROM_SPACE_NOT_BEGINNING:
|
||||
return cstartsWith(collator, base, part, false, true);
|
||||
case CHECK_ONLY_STARTS_WITH:
|
||||
return cstartsWith(collator, base, part, true, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if part contains in base
|
||||
*
|
||||
* @param collator Collator to use
|
||||
* @param part String to search
|
||||
* @param base String where to search
|
||||
* @return true if part is contained in base
|
||||
*/
|
||||
public static boolean ccontains(Collator collator, String base, String part) {
|
||||
int pos = 0;
|
||||
if (part.length() > 3) {
|
||||
// improve searching by searching first 3 characters
|
||||
pos = cindexOf(collator, pos, part.substring(0, 3), base);
|
||||
if (pos == -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
pos = cindexOf(collator, pos, part, base);
|
||||
if (pos == -1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int cindexOf(Collator collator, int start, String part, String base) {
|
||||
for (int pos = start; pos <= base.length() - part.length(); pos++) {
|
||||
if (collator.equals(base.substring(pos, pos + part.length()), part)) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if string starts with another string.
|
||||
* Special check try to find as well in the middle of name
|
||||
*
|
||||
* @param collator
|
||||
* @param searchIn
|
||||
* @param theStart
|
||||
* @return true if searchIn starts with token
|
||||
*/
|
||||
public static boolean cstartsWith(Collator collator, String searchIn, String theStart,
|
||||
boolean checkBeginning, boolean checkSpaces) {
|
||||
int startLength = theStart.length();
|
||||
int searchInLength = searchIn.length();
|
||||
if (startLength == 0) {
|
||||
return true;
|
||||
}
|
||||
if (startLength > searchInLength) {
|
||||
return false;
|
||||
}
|
||||
// simulate starts with for collator
|
||||
if (checkBeginning) {
|
||||
boolean starts = collator.equals(searchIn.substring(0, startLength), theStart);
|
||||
if (starts) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (checkSpaces) {
|
||||
for (int i = 1; i <= searchInLength - startLength; i++) {
|
||||
if (isSpace(searchIn.charAt(i - 1)) && !isSpace(searchIn.charAt(i))) {
|
||||
if (collator.equals(searchIn.substring(i, i + startLength), theStart)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isSpace(char c){
|
||||
return !Character.isLetter(c) && !Character.isDigit(c);
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import java.util.List;
|
|||
|
||||
import net.osmand.ResultMatcher;
|
||||
import net.osmand.StringMatcher;
|
||||
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
||||
import net.osmand.data.Building;
|
||||
import net.osmand.data.City;
|
||||
import net.osmand.data.MapObject;
|
||||
|
@ -85,7 +86,7 @@ public class BinaryMapAddressReaderAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
protected void readCities(List<City> cities, ResultMatcher<MapObject> resultMatcher, StringMatcher matcher, boolean useEn) throws IOException {
|
||||
protected void readCities(List<City> cities, SearchRequest<MapObject> resultMatcher, StringMatcher matcher, boolean useEn) throws IOException {
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
|
@ -116,7 +117,7 @@ public class BinaryMapAddressReaderAdapter {
|
|||
}
|
||||
|
||||
|
||||
protected PostCode readPostcode(PostCode p, int fileOffset, ResultMatcher<Street> resultMatcher, boolean loadStreets, String postcodeFilter) throws IOException{
|
||||
protected PostCode readPostcode(PostCode p, int fileOffset, SearchRequest<Street> resultMatcher, boolean loadStreets, String postcodeFilter) throws IOException{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
while(true){
|
||||
|
@ -173,7 +174,7 @@ public class BinaryMapAddressReaderAdapter {
|
|||
}
|
||||
|
||||
|
||||
protected City readCity(City c, int fileOffset, boolean loadStreets, ResultMatcher<Street> resultMatcher,
|
||||
protected City readCity(City c, int fileOffset, boolean loadStreets, SearchRequest<Street> resultMatcher,
|
||||
StringMatcher nameMatcher, boolean useEn) throws IOException{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
@ -269,7 +270,7 @@ public class BinaryMapAddressReaderAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
protected Street readStreet(Street s, ResultMatcher<Building> resultMatcher, boolean loadBuildings, int city24X, int city24Y, String postcodeFilter) throws IOException{
|
||||
protected Street readStreet(Street s, SearchRequest<Building> resultMatcher, boolean loadBuildings, int city24X, int city24Y, String postcodeFilter) throws IOException{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
boolean loadLocation = city24X != 0 || city24Y != 0;
|
||||
|
@ -477,7 +478,7 @@ public class BinaryMapAddressReaderAdapter {
|
|||
|
||||
|
||||
|
||||
protected void readPostcodes(List<PostCode> postcodes, ResultMatcher<MapObject> resultMatcher, StringMatcher nameMatcher) throws IOException{
|
||||
protected void readPostcodes(List<PostCode> postcodes, SearchRequest<MapObject> resultMatcher, StringMatcher nameMatcher) throws IOException{
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.io.RandomAccessFile;
|
|||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import net.osmand.Algoritms;
|
||||
|
@ -375,7 +376,7 @@ public class BinaryMapIndexReader {
|
|||
throw new IllegalArgumentException(name);
|
||||
}
|
||||
|
||||
public List<PostCode> getPostcodes(String region, ResultMatcher<MapObject> resultMatcher, StringMatcher nameMatcher) throws IOException {
|
||||
public List<PostCode> getPostcodes(String region, SearchRequest<MapObject> resultMatcher, StringMatcher nameMatcher) throws IOException {
|
||||
List<PostCode> postcodes = new ArrayList<PostCode>();
|
||||
AddressRegion r = getRegionByName(region);
|
||||
if(r.postcodesOffset != -1){
|
||||
|
@ -403,7 +404,7 @@ public class BinaryMapIndexReader {
|
|||
return null;
|
||||
}
|
||||
|
||||
public List<City> getCities(String region, ResultMatcher<MapObject> resultMatcher) throws IOException {
|
||||
public List<City> getCities(String region, SearchRequest<MapObject> resultMatcher) throws IOException {
|
||||
List<City> cities = new ArrayList<City>();
|
||||
AddressRegion r = getRegionByName(region);
|
||||
if(r.citiesOffset != -1){
|
||||
|
@ -416,7 +417,7 @@ public class BinaryMapIndexReader {
|
|||
return cities;
|
||||
}
|
||||
|
||||
public List<City> getVillages(String region, ResultMatcher<MapObject> resultMatcher, StringMatcher nameMatcher, boolean useEn) throws IOException {
|
||||
public List<City> getVillages(String region, SearchRequest<MapObject> resultMatcher, StringMatcher nameMatcher, boolean useEn) throws IOException {
|
||||
List<City> cities = new ArrayList<City>();
|
||||
AddressRegion r = getRegionByName(region);
|
||||
if(r.villagesOffset != -1){
|
||||
|
@ -430,7 +431,7 @@ public class BinaryMapIndexReader {
|
|||
}
|
||||
|
||||
|
||||
public void preloadStreets(City c, ResultMatcher<Street> resultMatcher) throws IOException {
|
||||
public void preloadStreets(City c, SearchRequest<Street> resultMatcher) throws IOException {
|
||||
checkAddressIndex(c.getFileOffset());
|
||||
codedIS.seek(c.getFileOffset());
|
||||
int size = codedIS.readRawVarint32();
|
||||
|
@ -451,7 +452,7 @@ public class BinaryMapIndexReader {
|
|||
}
|
||||
|
||||
|
||||
public void preloadStreets(PostCode p, ResultMatcher<Street> resultMatcher) throws IOException {
|
||||
public void preloadStreets(PostCode p, SearchRequest<Street> resultMatcher) throws IOException {
|
||||
checkAddressIndex(p.getFileOffset());
|
||||
|
||||
codedIS.seek(p.getFileOffset());
|
||||
|
@ -474,7 +475,7 @@ public class BinaryMapIndexReader {
|
|||
}
|
||||
}
|
||||
|
||||
public void preloadBuildings(Street s, ResultMatcher<Building> resultMatcher) throws IOException {
|
||||
public void preloadBuildings(Street s, SearchRequest<Building> resultMatcher) throws IOException {
|
||||
checkAddressIndex(s.getFileOffset());
|
||||
codedIS.seek(s.getFileOffset());
|
||||
int size = codedIS.readRawVarint32();
|
||||
|
@ -712,7 +713,7 @@ public class BinaryMapIndexReader {
|
|||
int cbottom = 0;
|
||||
req.numberOfReadSubtrees++;
|
||||
while(true){
|
||||
if(req.isInterrupted()){
|
||||
if(req.isCancelled()){
|
||||
return;
|
||||
}
|
||||
int t = codedIS.readTag();
|
||||
|
@ -918,6 +919,18 @@ public class BinaryMapIndexReader {
|
|||
|
||||
}
|
||||
|
||||
public void searchPoiByName(SearchRequest<Amenity> req) throws IOException {
|
||||
if (req.nameQuery == null || req.nameQuery.length() == 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
for (PoiRegion poiIndex : poiIndexes) {
|
||||
codedIS.seek(poiIndex.filePointer);
|
||||
int old = codedIS.pushLimit(poiIndex.length);
|
||||
poiAdapter.searchPoiByName(poiIndex, req);
|
||||
codedIS.popLimit(old);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Amenity> searchPoi(SearchRequest<Amenity> req) throws IOException {
|
||||
req.numberOfVisitedObjects = 0;
|
||||
req.numberOfAcceptedObjects = 0;
|
||||
|
@ -963,25 +976,42 @@ public class BinaryMapIndexReader {
|
|||
}
|
||||
|
||||
|
||||
public static SearchRequest<BinaryMapDataObject> buildSearchRequest(int sleft, int sright, int stop, int sbottom, int zoom){
|
||||
public static SearchRequest<BinaryMapDataObject> buildSearchRequest(int sleft, int sright, int stop, int sbottom, int zoom, SearchFilter searchFilter){
|
||||
SearchRequest<BinaryMapDataObject> request = new SearchRequest<BinaryMapDataObject>();
|
||||
request.left = sleft;
|
||||
request.right = sright;
|
||||
request.top = stop;
|
||||
request.bottom = sbottom;
|
||||
request.zoom = zoom;
|
||||
request.searchFilter = searchFilter;
|
||||
return request;
|
||||
}
|
||||
|
||||
public static <T> SearchRequest<T> buildAddressRequest(ResultMatcher<T> resultMatcher){
|
||||
SearchRequest<T> request = new SearchRequest<T>();
|
||||
request.resultMatcher = resultMatcher;
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
public static SearchRequest<Amenity> buildSearchPoiRequest(int sleft, int sright, int stop, int sbottom, int zoom, int limit){
|
||||
public static SearchRequest<Amenity> buildSearchPoiRequest(int sleft, int sright, int stop, int sbottom, int zoom, SearchPoiTypeFilter poiTypeFilter){
|
||||
SearchRequest<Amenity> request = new SearchRequest<Amenity>();
|
||||
request.left = sleft;
|
||||
request.right = sright;
|
||||
request.top = stop;
|
||||
request.bottom = sbottom;
|
||||
request.zoom = zoom;
|
||||
request.limit = limit;
|
||||
request.poiTypeFilter = poiTypeFilter;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
public static SearchRequest<Amenity> buildSearchPoiRequest(int x, int y, String nameFilter, SearchPoiTypeFilter poiTypeFilter){
|
||||
SearchRequest<Amenity> request = new SearchRequest<Amenity>();
|
||||
request.x = x;
|
||||
request.y = y;
|
||||
request.poiTypeFilter = poiTypeFilter;
|
||||
request.nameQuery = nameFilter;
|
||||
return request;
|
||||
}
|
||||
|
||||
|
@ -1022,18 +1052,31 @@ public class BinaryMapIndexReader {
|
|||
}
|
||||
|
||||
public static class SearchRequest<T> {
|
||||
private List<T> searchResults = new ArrayList<T>();
|
||||
private ResultMatcher<T> resultMatcher;
|
||||
|
||||
// 31 zoom tiles
|
||||
// common variables
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int left = 0;
|
||||
int right = 0;
|
||||
int top = 0;
|
||||
int bottom = 0;
|
||||
|
||||
int zoom = 15;
|
||||
int limit = -1;
|
||||
List<T> searchResults = new ArrayList<T>();
|
||||
|
||||
|
||||
String nameQuery = null;
|
||||
|
||||
SearchFilter searchFilter = null;
|
||||
|
||||
SearchPoiTypeFilter poiTypeFilter = null;
|
||||
|
||||
// cache information
|
||||
TIntArrayList cacheCoordinates = new TIntArrayList();
|
||||
TIntArrayList cacheTypes = new TIntArrayList();
|
||||
SearchFilter searchFilter = null;
|
||||
SearchPoiTypeFilter poiTypeFilter = null;
|
||||
|
||||
// TRACE INFO
|
||||
int numberOfVisitedObjects = 0;
|
||||
|
@ -1045,19 +1088,13 @@ public class BinaryMapIndexReader {
|
|||
protected SearchRequest(){
|
||||
}
|
||||
|
||||
public SearchFilter getSearchFilter() {
|
||||
return searchFilter;
|
||||
}
|
||||
public void setSearchFilter(SearchFilter searchFilter) {
|
||||
this.searchFilter = searchFilter;
|
||||
}
|
||||
|
||||
public void setPoiTypeFilter(SearchPoiTypeFilter poiTypeFilter) {
|
||||
this.poiTypeFilter = poiTypeFilter;
|
||||
protected boolean publish(T obj){
|
||||
if(resultMatcher == null || resultMatcher.publish(obj)){
|
||||
searchResults.add(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
public SearchPoiTypeFilter getPoiTypeFilter() {
|
||||
return poiTypeFilter;
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<T> getSearchResults() {
|
||||
|
@ -1068,13 +1105,25 @@ public class BinaryMapIndexReader {
|
|||
this.interrupted = interrupted;
|
||||
}
|
||||
|
||||
public boolean isInterrupted() {
|
||||
public boolean isCancelled() {
|
||||
if(this.interrupted){
|
||||
return interrupted;
|
||||
}
|
||||
if(resultMatcher != null){
|
||||
return resultMatcher.isCancelled();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void clearSearchResults(){
|
||||
// recreate whole list to allow GC collect old data
|
||||
searchResults = new ArrayList<T>();
|
||||
cacheCoordinates.clear();
|
||||
cacheTypes.clear();
|
||||
numberOfVisitedObjects = 0;
|
||||
numberOfAcceptedObjects = 0;
|
||||
numberOfReadSubtrees = 0;
|
||||
numberOfAcceptedSubtrees = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1206,28 +1255,42 @@ public class BinaryMapIndexReader {
|
|||
}
|
||||
|
||||
|
||||
private static boolean testMapSearch = false;
|
||||
private static boolean testAddressSearch = false;
|
||||
private static boolean testPoiSearch = true;
|
||||
private static boolean testTransportSearch = false;
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
RandomAccessFile raf = new RandomAccessFile(new File("/home/victor/projects/OsmAnd/data/osm-gen/POI/Test-Ru.poi.obf"), "r");
|
||||
RandomAccessFile raf = new RandomAccessFile(new File("/home/victor/projects/OsmAnd/data/osm-gen/POI/Ru-mow.poi.obf"), "r");
|
||||
BinaryMapIndexReader reader = new BinaryMapIndexReader(raf);
|
||||
System.out.println("VERSION " + reader.getVersion()); //$NON-NLS-1$
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
if (testMapSearch) {
|
||||
testMapSearch(reader);
|
||||
}
|
||||
if(testAddressSearch) {
|
||||
testAddressSearch(reader);
|
||||
}
|
||||
if(testTransportSearch) {
|
||||
testTransportSearch(reader);
|
||||
}
|
||||
|
||||
Locale.setDefault(new Locale("RU"));
|
||||
if (testPoiSearch) {
|
||||
PoiRegion poiRegion = reader.getPoiIndexes().get(0);
|
||||
System.out.println(poiRegion.leftLongitude + " " + poiRegion.rightLongitude + " " + poiRegion.bottomLatitude + " " + poiRegion.topLatitude);
|
||||
// for (int i = 0; i < poiRegion.categories.size(); i++) {
|
||||
// System.out.println(poiRegion.categories.get(i));
|
||||
// System.out.println(" " + poiRegion.subcategories.get(i));
|
||||
// }
|
||||
System.out.println(poiRegion.leftLongitude + " " + poiRegion.rightLongitude + " " + poiRegion.bottomLatitude + " "
|
||||
+ poiRegion.topLatitude);
|
||||
for (int i = 0; i < poiRegion.categories.size(); i++) {
|
||||
System.out.println(poiRegion.categories.get(i));
|
||||
System.out.println(" " + poiRegion.subcategories.get(i));
|
||||
}
|
||||
|
||||
int sleft = MapUtils.get31TileNumberX(37.5);
|
||||
int sright = MapUtils.get31TileNumberX(37.9);
|
||||
int stop = MapUtils.get31TileNumberY(55.814);
|
||||
int sbottom = MapUtils.get31TileNumberY(55.81);
|
||||
SearchRequest<Amenity> req = buildSearchPoiRequest(sleft, sright, stop, sbottom, -1, 200);
|
||||
req.setPoiTypeFilter(new SearchPoiTypeFilter() {
|
||||
SearchRequest<Amenity> req = buildSearchPoiRequest(sleft, sright, stop, sbottom, -1, new SearchPoiTypeFilter() {
|
||||
@Override
|
||||
public boolean accept(AmenityType type, String subcategory) {
|
||||
return type == AmenityType.TRANSPORTATION && "fuel".equals(subcategory);
|
||||
|
@ -1238,89 +1301,97 @@ public class BinaryMapIndexReader {
|
|||
System.out.println(a.getType() + " " + a.getSubType() + " " + a.getName() + " " + a.getLocation());
|
||||
}
|
||||
|
||||
System.out.println("Searching by name...");
|
||||
req = buildSearchPoiRequest(sleft, sright, "kolie", null);
|
||||
reader.searchPoiByName(req);
|
||||
for (Amenity a : req.getSearchResults()) {
|
||||
System.out.println(a.getType() + " " + a.getSubType() + " " + a.getName() + " " + a.getLocation());
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("MEMORY " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())); //$NON-NLS-1$
|
||||
System.out.println("Time " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private static void testTransportSearch(BinaryMapIndexReader reader) {
|
||||
private static void testTransportSearch(BinaryMapIndexReader reader) throws IOException {
|
||||
// test transport
|
||||
// for(TransportIndex i : reader.transportIndexes){
|
||||
// System.out.println(i.left + " " + i.right + " " + i.top + " " + i.bottom);
|
||||
// System.out.println(i.stringTable.cacheOfStrings);
|
||||
// System.out.println(i.stringTable.offsets);
|
||||
// System.out.println(i.stringTable.window);
|
||||
// }
|
||||
// {
|
||||
// int sleft = MapUtils.get31TileNumberX(27.573);
|
||||
// int sright = MapUtils.get31TileNumberX(27.581);
|
||||
// int stop = MapUtils.get31TileNumberY(53.912);
|
||||
// int sbottom = MapUtils.get31TileNumberY(53.908);
|
||||
// for (TransportStop s : reader.searchTransportIndex(buildSearchTransportRequest(sleft, sright, stop, sbottom, 15, null))) {
|
||||
// System.out.println(s.getName());
|
||||
// for (int i : s.getReferencesToRoutes()) {
|
||||
// TransportRoute route = reader.getTransportRoute(i);
|
||||
// System.out.println(" " + route.getRef() + " " + route.getName() + " " + route.getDistance() + " "
|
||||
// + route.getAvgBothDistance());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// {
|
||||
// int sleft = MapUtils.get31TileNumberX(27.473);
|
||||
// int sright = MapUtils.get31TileNumberX(27.681);
|
||||
// int stop = MapUtils.get31TileNumberY(53.912);
|
||||
// int sbottom = MapUtils.get31TileNumberY(53.708);
|
||||
// for (TransportStop s : reader.searchTransportIndex(buildSearchTransportRequest(sleft, sright, stop, sbottom, 16, null))) {
|
||||
// System.out.println(s.getName());
|
||||
// for (int i : s.getReferencesToRoutes()) {
|
||||
// TransportRoute route = reader.getTransportRoute(i);
|
||||
// System.out.println(" " + route.getRef() + " " + route.getName() + " " + route.getDistance() + " "
|
||||
// + route.getAvgBothDistance());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
for (TransportIndex i : reader.transportIndexes) {
|
||||
System.out.println(i.left + " " + i.right + " " + i.top + " " + i.bottom);
|
||||
System.out.println(i.stringTable.cacheOfStrings);
|
||||
System.out.println(i.stringTable.offsets);
|
||||
System.out.println(i.stringTable.window);
|
||||
}
|
||||
{
|
||||
int sleft = MapUtils.get31TileNumberX(27.573);
|
||||
int sright = MapUtils.get31TileNumberX(27.581);
|
||||
int stop = MapUtils.get31TileNumberY(53.912);
|
||||
int sbottom = MapUtils.get31TileNumberY(53.908);
|
||||
for (TransportStop s : reader.searchTransportIndex(buildSearchTransportRequest(sleft, sright, stop, sbottom, 15, null))) {
|
||||
System.out.println(s.getName());
|
||||
for (int i : s.getReferencesToRoutes()) {
|
||||
net.osmand.data.TransportRoute route = reader.getTransportRoute(i);
|
||||
System.out.println(" " + route.getRef() + " " + route.getName() + " " + route.getDistance() + " "
|
||||
+ route.getAvgBothDistance());
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
int sleft = MapUtils.get31TileNumberX(27.473);
|
||||
int sright = MapUtils.get31TileNumberX(27.681);
|
||||
int stop = MapUtils.get31TileNumberY(53.912);
|
||||
int sbottom = MapUtils.get31TileNumberY(53.708);
|
||||
for (TransportStop s : reader.searchTransportIndex(buildSearchTransportRequest(sleft, sright, stop, sbottom, 16, null))) {
|
||||
System.out.println(s.getName());
|
||||
for (int i : s.getReferencesToRoutes()) {
|
||||
net.osmand.data.TransportRoute route = reader.getTransportRoute(i);
|
||||
System.out.println(" " + route.getRef() + " " + route.getName() + " " + route.getDistance() + " "
|
||||
+ route.getAvgBothDistance());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testAddressSearch(BinaryMapIndexReader reader) throws IOException {
|
||||
// test address index search
|
||||
// String reg = reader.getRegionNames().get(0);
|
||||
// List<City> cs = reader.getCities(reg, null);
|
||||
// for(City c : cs){
|
||||
// int buildings = 0;
|
||||
// reader.preloadStreets(c, null);
|
||||
// for(Street s : c.getStreets()){
|
||||
// reader.preloadBuildings(s);
|
||||
// buildings += s.getBuildings().size();
|
||||
// }
|
||||
// System.out.println(c.getName() + " " + c.getLocation() + " " + c.getStreets().size() + " " + buildings + " " + c.getEnName());
|
||||
// }
|
||||
// List<PostCode> postcodes = reader.getPostcodes(reg);
|
||||
// for(PostCode c : postcodes){
|
||||
// reader.preloadStreets(c);
|
||||
// System.out.println(c.getName());
|
||||
// }
|
||||
// List<City> villages = reader.getVillages(reg, new StringMatcher() {
|
||||
//
|
||||
// @Override
|
||||
// public boolean matches(String name) {
|
||||
// return false;
|
||||
// }
|
||||
// }, true);
|
||||
// System.out.println("Villages " + villages.size());
|
||||
String reg = reader.getRegionNames().get(0);
|
||||
List<City> cs = reader.getCities(reg, null);
|
||||
for(City c : cs){
|
||||
int buildings = 0;
|
||||
reader.preloadStreets(c, null);
|
||||
for(Street s : c.getStreets()){
|
||||
reader.preloadBuildings(s, buildAddressRequest((ResultMatcher<Building>) null));
|
||||
buildings += s.getBuildings().size();
|
||||
}
|
||||
System.out.println(c.getName() + " " + c.getLocation() + " " + c.getStreets().size() + " " + buildings + " " + c.getEnName());
|
||||
}
|
||||
List<PostCode> postcodes = reader.getPostcodes(reg, buildAddressRequest((ResultMatcher<MapObject>) null), null);
|
||||
for(PostCode c : postcodes){
|
||||
reader.preloadStreets(c, buildAddressRequest((ResultMatcher<Street>) null));
|
||||
System.out.println(c.getName());
|
||||
}
|
||||
List<City> villages = reader.getVillages(reg, buildAddressRequest((ResultMatcher<MapObject>) null), new StringMatcher() {
|
||||
|
||||
@Override
|
||||
public boolean matches(String name) {
|
||||
return false;
|
||||
}
|
||||
}, true);
|
||||
System.out.println("Villages " + villages.size());
|
||||
}
|
||||
|
||||
private static void testMapSearch(BinaryMapIndexReader reader) throws IOException {
|
||||
// System.out.println(reader.mapIndexes.get(0).encodingRules);
|
||||
// int sleft = MapUtils.get31TileNumberX(27.596);
|
||||
// int sright = MapUtils.get31TileNumberX(27.599);
|
||||
// int stop = MapUtils.get31TileNumberY(53.921);
|
||||
// int sbottom = MapUtils.get31TileNumberY(53.919);
|
||||
// System.out.println("SEARCH " + sleft + " " + sright + " " + stop + " " + sbottom);
|
||||
//
|
||||
// for (BinaryMapDataObject obj : reader.searchMapIndex(buildSearchRequest(sleft, sright, stop, sbottom, 8))) {
|
||||
// if (obj.getName() != null) {
|
||||
// System.out.println(" " + obj.getName());
|
||||
// }
|
||||
// }
|
||||
System.out.println(reader.mapIndexes.get(0).encodingRules);
|
||||
int sleft = MapUtils.get31TileNumberX(27.596);
|
||||
int sright = MapUtils.get31TileNumberX(27.599);
|
||||
int stop = MapUtils.get31TileNumberY(53.921);
|
||||
int sbottom = MapUtils.get31TileNumberY(53.919);
|
||||
System.out.println("SEARCH " + sleft + " " + sright + " " + stop + " " + sbottom);
|
||||
|
||||
for (BinaryMapDataObject obj : reader.searchMapIndex(buildSearchRequest(sleft, sright, stop, sbottom, 8, null))) {
|
||||
if (obj.getName() != null) {
|
||||
System.out.println(" " + obj.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -7,6 +7,7 @@ import gnu.trove.list.array.TLongArrayList;
|
|||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
|
@ -812,7 +813,7 @@ public class BinaryMapIndexWriter {
|
|||
codedOutStream.writeMessage(OsmandOdb.OsmAndPoiBox.CATEGORIES_FIELD_NUMBER, builder.build());
|
||||
}
|
||||
|
||||
public Map<PoiTileBox, TLongList> writePoiNameIndex(Map<String, List<PoiTileBox>> namesIndex, long fpPoiIndex) throws IOException {
|
||||
public Map<PoiTileBox, TLongList> writePoiNameIndex(Map<String, Set<PoiTileBox>> namesIndex) throws IOException {
|
||||
checkPeekState(POI_INDEX_INIT);
|
||||
codedOutStream.writeTag(OsmandOdb.OsmAndPoiIndex.NAMEINDEX_FIELD_NUMBER, WireFormat.WIRETYPE_FIXED32_LENGTH_DELIMITED);
|
||||
preserveInt32Size();
|
||||
|
@ -821,9 +822,9 @@ public class BinaryMapIndexWriter {
|
|||
Map<String, Integer> indexedTable = new LinkedHashMap<String, Integer>();
|
||||
Map<PoiTileBox, TLongList> fpToWriteSeeks = new LinkedHashMap<PoiTileBox, TLongList>();
|
||||
int previousSize = 0;
|
||||
for(Map.Entry<String, List<PoiTileBox>> e : namesIndex.entrySet()) {
|
||||
for(Map.Entry<String, Set<PoiTileBox>> e : namesIndex.entrySet()) {
|
||||
OsmandOdb.OsmAndPoiNameIndexData.Builder builder = OsmandOdb.OsmAndPoiNameIndexData.newBuilder();
|
||||
List<PoiTileBox> tileBoxes = e.getValue();
|
||||
List<PoiTileBox> tileBoxes = new ArrayList<PoiTileBox>(e.getValue());
|
||||
for(PoiTileBox box : tileBoxes) {
|
||||
OsmandOdb.OsmAndPoiNameIndexDataAtom.Builder bs = OsmandOdb.OsmAndPoiNameIndexDataAtom.newBuilder();
|
||||
bs.setX(box.getX());
|
||||
|
@ -852,10 +853,10 @@ public class BinaryMapIndexWriter {
|
|||
}
|
||||
writeIndexedTable(OsmandOdb.OsmAndPoiNameIndex.TABLE_FIELD_NUMBER, indexedTable);
|
||||
codedOutStream.flush();
|
||||
int diff = (int) (raf.getFilePointer() - fpPoiIndex);
|
||||
long l = raf.getFilePointer();
|
||||
for (TLongList es : fpToWriteSeeks.values()) {
|
||||
for (int i = 0; i < es.size(); i++) {
|
||||
es.set(i, es.get(i) + diff);
|
||||
es.set(i, es.get(i) + l);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package net.osmand.binary;
|
||||
|
||||
import gnu.trove.list.array.TIntArrayList;
|
||||
import gnu.trove.map.hash.TIntLongHashMap;
|
||||
import gnu.trove.set.hash.TLongHashSet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
@ -11,7 +13,9 @@ import java.util.List;
|
|||
import org.apache.commons.logging.Log;
|
||||
|
||||
import net.osmand.Algoritms;
|
||||
import net.osmand.CollatorStringMatcher;
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.CollatorStringMatcher.StringMatcherMode;
|
||||
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
||||
import net.osmand.data.Amenity;
|
||||
import net.osmand.data.AmenityType;
|
||||
|
@ -156,6 +160,184 @@ public class BinaryMapPoiReaderAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
protected void searchPoiByName( PoiRegion region, SearchRequest<Amenity> req) throws IOException {
|
||||
TIntArrayList offsets = new TIntArrayList();
|
||||
Collator instance = Collator.getInstance();
|
||||
instance.setStrength(Collator.PRIMARY);
|
||||
CollatorStringMatcher matcher = new CollatorStringMatcher(instance, req.nameQuery,
|
||||
StringMatcherMode.CHECK_STARTS_FROM_SPACE);
|
||||
long time = System.currentTimeMillis();
|
||||
int indexOffset = codedIS.getTotalBytesRead();
|
||||
while(true){
|
||||
if(req.isCancelled()){
|
||||
return;
|
||||
}
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
return;
|
||||
case OsmandOdb.OsmAndPoiIndex.NAMEINDEX_FIELD_NUMBER :
|
||||
int length = readInt();
|
||||
int oldLimit = codedIS.pushLimit(length);
|
||||
offsets = readPoiNameIndex(instance, req.nameQuery, req);
|
||||
codedIS.popLimit(oldLimit);
|
||||
break;
|
||||
case OsmandOdb.OsmAndPoiIndex.POIDATA_FIELD_NUMBER :
|
||||
// also offsets can be randomly skipped by limit
|
||||
offsets.sort();
|
||||
LOG.info("Searched poi structure in "+(System.currentTimeMillis() - time) +
|
||||
"ms. Found " + offsets.size() +" subtress");
|
||||
for (int j = 0; j < offsets.size(); j++) {
|
||||
codedIS.seek(offsets.get(j) + indexOffset);
|
||||
int len = readInt();
|
||||
int oldLim = codedIS.pushLimit(len);
|
||||
readPoiData(matcher, req, region);
|
||||
codedIS.popLimit(oldLim);
|
||||
if(req.isCancelled()){
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOG.info("Whole poi by name search is done in "+(System.currentTimeMillis() - time) +
|
||||
"ms. Found " + req.getSearchResults().size());
|
||||
codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
|
||||
return;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TIntArrayList readPoiNameIndex(Collator instance, String query, SearchRequest<Amenity> req) throws IOException {
|
||||
TIntArrayList offsets = new TIntArrayList();
|
||||
TIntArrayList dataOffsets = null;
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
return offsets;
|
||||
case OsmandOdb.OsmAndPoiNameIndex.TABLE_FIELD_NUMBER : {
|
||||
int length = readInt();
|
||||
int oldLimit = codedIS.pushLimit(length);
|
||||
dataOffsets = readIndexedStringTable(instance, query);
|
||||
codedIS.popLimit(oldLimit);
|
||||
break; }
|
||||
case OsmandOdb.OsmAndPoiNameIndex.DATA_FIELD_NUMBER : {
|
||||
if(dataOffsets != null){
|
||||
dataOffsets.sort();
|
||||
int offset = codedIS.getTotalBytesRead();
|
||||
for (int i = 0; i < dataOffsets.size(); i++) {
|
||||
codedIS.seek(dataOffsets.get(i) + offset);
|
||||
int len = codedIS.readRawVarint32();
|
||||
int oldLim = codedIS.pushLimit(len);
|
||||
readPoiNameIndexData(offsets);
|
||||
codedIS.popLimit(oldLim);
|
||||
if (req.isCancelled()) {
|
||||
codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
|
||||
return offsets;
|
||||
}
|
||||
}
|
||||
}
|
||||
codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
|
||||
return offsets; }
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void readPoiNameIndexData(TIntArrayList offsets) throws IOException {
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
return;
|
||||
case OsmandOdb.OsmAndPoiNameIndexData.ATOMS_FIELD_NUMBER :
|
||||
int len = codedIS.readRawVarint32();
|
||||
int oldLim = codedIS.pushLimit(len);
|
||||
readPoiNameIndexDataAtom(offsets);
|
||||
codedIS.popLimit(oldLim);
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void readPoiNameIndexDataAtom(TIntArrayList offsets) throws IOException {
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
return;
|
||||
case OsmandOdb.OsmAndPoiNameIndexDataAtom.X_FIELD_NUMBER :
|
||||
/*int x = */codedIS.readUInt32();
|
||||
break;
|
||||
case OsmandOdb.OsmAndPoiNameIndexDataAtom.Y_FIELD_NUMBER :
|
||||
/*int y = */codedIS.readUInt32();
|
||||
break;
|
||||
case OsmandOdb.OsmAndPoiNameIndexDataAtom.ZOOM_FIELD_NUMBER :
|
||||
/*int zoom = */codedIS.readUInt32();
|
||||
break;
|
||||
case OsmandOdb.OsmAndPoiNameIndexDataAtom.SHIFTTO_FIELD_NUMBER :
|
||||
offsets.add(readInt());
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TIntArrayList readIndexedStringTable(Collator instance, String query) throws IOException {
|
||||
// TODO support fully functional indexed string table
|
||||
TIntArrayList list = new TIntArrayList();
|
||||
int charMatches = 0;
|
||||
boolean keyMatches = false;
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
return list;
|
||||
case OsmandOdb.IndexedStringTable.KEY_FIELD_NUMBER :
|
||||
String key = codedIS.readString();
|
||||
keyMatches = false;
|
||||
int i=0;
|
||||
for(; i<query.length(); i++){
|
||||
if (i >= key.length() || instance.compare(key.substring(i, i + 1), query.substring(i, i + 1)) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i >= charMatches && i > 0){
|
||||
if(i > charMatches){
|
||||
list.clear();
|
||||
charMatches = i;
|
||||
}
|
||||
keyMatches = true;
|
||||
}
|
||||
break;
|
||||
case OsmandOdb.IndexedStringTable.VAL_FIELD_NUMBER :
|
||||
int val = codedIS.readUInt32();
|
||||
if (keyMatches) {
|
||||
list.add(val);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void searchPoiIndex(int left31, int right31, int top31, int bottom31,
|
||||
SearchRequest<Amenity> req, PoiRegion region) throws IOException {
|
||||
int indexOffset = codedIS.getTotalBytesRead();
|
||||
|
@ -168,7 +350,7 @@ public class BinaryMapPoiReaderAdapter {
|
|||
}
|
||||
TIntLongHashMap offsetsMap = new TIntLongHashMap();
|
||||
while(true){
|
||||
if(req.isInterrupted()){
|
||||
if(req.isCancelled()){
|
||||
return;
|
||||
}
|
||||
int t = codedIS.readTag();
|
||||
|
@ -199,7 +381,7 @@ public class BinaryMapPoiReaderAdapter {
|
|||
int oldLim = codedIS.pushLimit(len);
|
||||
readPoiData(left31, right31, top31, bottom31, req, req.getSearchResults(), region, skipTiles, zoomToSkip);
|
||||
codedIS.popLimit(oldLim);
|
||||
if(req.isInterrupted()){
|
||||
if(req.isCancelled()){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -212,13 +394,12 @@ public class BinaryMapPoiReaderAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
private void readPoiData(int left31, int right31, int top31, int bottom31,
|
||||
SearchRequest<Amenity> req, List<Amenity> result, PoiRegion region, TLongHashSet toSkip, int zSkip) throws IOException {
|
||||
private void readPoiData(CollatorStringMatcher matcher, SearchRequest<Amenity> req, PoiRegion region) throws IOException {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int zoom = 0;
|
||||
while(true){
|
||||
if(req.isInterrupted()){
|
||||
if(req.isCancelled()){
|
||||
return;
|
||||
}
|
||||
int t = codedIS.readTag();
|
||||
|
@ -238,7 +419,48 @@ public class BinaryMapPoiReaderAdapter {
|
|||
case OsmandOdb.OsmAndPoiBoxData.POIDATA_FIELD_NUMBER:
|
||||
int len = codedIS.readRawVarint32();
|
||||
int oldLim = codedIS.pushLimit(len);
|
||||
Amenity am = readPoiPoint(left31, right31, top31, bottom31, x, y, zoom, req, region);
|
||||
Amenity am = readPoiPoint(0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, x, y, zoom, req, region, false);
|
||||
codedIS.popLimit(oldLim);
|
||||
if (am != null) {
|
||||
if(matcher.matches(am.getName(false)) || matcher.matches(am.getName(true))) {
|
||||
req.publish(am);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
skipUnknownField(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readPoiData(int left31, int right31, int top31, int bottom31,
|
||||
SearchRequest<Amenity> req, List<Amenity> result, PoiRegion region, TLongHashSet toSkip, int zSkip) throws IOException {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int zoom = 0;
|
||||
while(true){
|
||||
if(req.isCancelled()){
|
||||
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);
|
||||
Amenity am = readPoiPoint(left31, right31, top31, bottom31, x, y, zoom, req, region, true);
|
||||
codedIS.popLimit(oldLim);
|
||||
if (am != null) {
|
||||
if (toSkip != null) {
|
||||
|
@ -266,7 +488,7 @@ public class BinaryMapPoiReaderAdapter {
|
|||
}
|
||||
|
||||
private Amenity readPoiPoint(int left31, int right31, int top31, int bottom31,
|
||||
int px, int py, int zoom, SearchRequest<Amenity> req, PoiRegion region) throws IOException {
|
||||
int px, int py, int zoom, SearchRequest<Amenity> req, PoiRegion region, boolean checkBounds) throws IOException {
|
||||
Amenity am = null;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
@ -291,10 +513,12 @@ public class BinaryMapPoiReaderAdapter {
|
|||
case OsmandOdb.OsmAndPoiBoxDataAtom.DY_FIELD_NUMBER :
|
||||
y = (codedIS.readSInt32() + (py << (24 - zoom))) << 7;
|
||||
req.numberOfVisitedObjects++;
|
||||
if (checkBounds) {
|
||||
if (left31 > x || right31 < x || top31 > y || bottom31 < y) {
|
||||
codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
am = new Amenity();
|
||||
am.setLocation(MapUtils.get31LatitudeY(y), MapUtils.get31LongitudeX(x));
|
||||
break;
|
||||
|
@ -392,7 +616,7 @@ public class BinaryMapPoiReaderAdapter {
|
|||
int dy = py;
|
||||
int dx = px;
|
||||
while(true){
|
||||
if(req.isInterrupted()){
|
||||
if(req.isCancelled()){
|
||||
return false;
|
||||
}
|
||||
int t = codedIS.readTag();
|
||||
|
|
|
@ -63,7 +63,7 @@ public class BinaryMapTransportReaderAdapter {
|
|||
IndexStringTable stringTable = null;
|
||||
}
|
||||
|
||||
private static class IndexStringTable {
|
||||
protected static class IndexStringTable {
|
||||
private static final int SIZE_OFFSET_ARRAY = 100;
|
||||
private static final int WINDOW_SIZE = 25;
|
||||
int fileOffset = 0;
|
||||
|
@ -262,7 +262,7 @@ public class BinaryMapTransportReaderAdapter {
|
|||
int cbottom = 0;
|
||||
req.numberOfReadSubtrees++;
|
||||
while(true){
|
||||
if(req.isInterrupted()){
|
||||
if(req.isCancelled()){
|
||||
return;
|
||||
}
|
||||
int t = codedIS.readTag();
|
||||
|
@ -300,13 +300,12 @@ public class BinaryMapTransportReaderAdapter {
|
|||
int length = codedIS.readRawVarint32();
|
||||
int oldLimit = codedIS.pushLimit(length);
|
||||
if(lastIndexResult == -1){
|
||||
lastIndexResult = req.searchResults.size();
|
||||
lastIndexResult = req.getSearchResults().size();
|
||||
}
|
||||
req.numberOfVisitedObjects++;
|
||||
TransportStop transportStop = readTransportStop(stopOffset, cleft, cright, ctop, cbottom, req);
|
||||
if(transportStop != null){
|
||||
req.searchResults.add(transportStop);
|
||||
|
||||
req.publish(transportStop);
|
||||
}
|
||||
codedIS.popLimit(oldLimit);
|
||||
break;
|
||||
|
@ -314,7 +313,7 @@ public class BinaryMapTransportReaderAdapter {
|
|||
// left, ... already initialized
|
||||
length = readInt();
|
||||
int filePointer = codedIS.getTotalBytesRead();
|
||||
if (req.limit == -1 || req.limit >= req.searchResults.size()) {
|
||||
if (req.limit == -1 || req.limit >= req.getSearchResults().size()) {
|
||||
oldLimit = codedIS.pushLimit(length);
|
||||
searchTransportTreeBounds(cleft, cright, ctop, cbottom, req);
|
||||
codedIS.popLimit(oldLimit);
|
||||
|
@ -328,8 +327,8 @@ public class BinaryMapTransportReaderAdapter {
|
|||
case OsmandOdb.TransportStopsTree.BASEID_FIELD_NUMBER :
|
||||
long baseId = codedIS.readUInt64();
|
||||
if (lastIndexResult != -1) {
|
||||
for (int i = lastIndexResult; i < req.searchResults.size(); i++) {
|
||||
TransportStop rs = req.searchResults.get(i);
|
||||
for (int i = lastIndexResult; i < req.getSearchResults().size(); i++) {
|
||||
TransportStop rs = req.getSearchResults().get(i);
|
||||
rs.setId(rs.getId() + baseId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,10 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import net.osmand.Algoritms;
|
||||
|
@ -49,6 +51,7 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
|
|||
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_END = 16;
|
||||
private static final int CHARACTERS_TO_BUILD = 4;
|
||||
private boolean useInMemoryCreator = true;
|
||||
|
||||
|
||||
|
@ -193,7 +196,7 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
|
|||
Collator collator = Collator.getInstance();
|
||||
collator.setStrength(Collator.PRIMARY);
|
||||
|
||||
Map<String, List<PoiTileBox>> namesIndex = new LinkedHashMap<String, List<PoiTileBox>>();
|
||||
Map<String, Set<PoiTileBox>> namesIndex = new TreeMap<String, Set<PoiTileBox>>();
|
||||
|
||||
// 0. process all entities
|
||||
ResultSet rs;
|
||||
|
@ -289,7 +292,8 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
|
|||
Map<String, Integer> catIndexes = writer.writePOICategoriesTable(categories);
|
||||
|
||||
// 2.5 write names table
|
||||
Map<PoiTileBox, TLongList> fpToWriteSeeks = writer.writePoiNameIndex(namesIndex, startFpPoiIndex);
|
||||
//Map<PoiTileBox, TLongList> fpToWriteSeeks = new LinkedHashMap<PoiTileBox, TLongList>();
|
||||
Map<PoiTileBox, TLongList> fpToWriteSeeks = writer.writePoiNameIndex(namesIndex);
|
||||
|
||||
// 3. write boxes
|
||||
log.info("Poi box processing finishied");
|
||||
|
@ -375,7 +379,7 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
|
|||
|
||||
}
|
||||
|
||||
public void addNamePrefix(String name, String nameEn, PoiTileBox data, Map<String, List<PoiTileBox>> poiData) {
|
||||
public void addNamePrefix(String name, String nameEn, PoiTileBox data, Map<String, Set<PoiTileBox>> poiData) {
|
||||
if(Algoritms.isEmpty(nameEn)){
|
||||
nameEn = Junidecode.unidecode(name);
|
||||
}
|
||||
|
@ -383,19 +387,19 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
|
|||
parsePrefix(nameEn, data, poiData);
|
||||
}
|
||||
|
||||
private void parsePrefix(String name, PoiTileBox data, Map<String, List<PoiTileBox>> poiData) {
|
||||
private void parsePrefix(String name, PoiTileBox data, Map<String, Set<PoiTileBox>> poiData) {
|
||||
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);
|
||||
if (substr.length() > CHARACTERS_TO_BUILD) {
|
||||
substr = substr.substring(0, CHARACTERS_TO_BUILD);
|
||||
}
|
||||
String val = substr.toLowerCase();
|
||||
if(!poiData.containsKey(val)){
|
||||
poiData.put(val, new ArrayList<PoiTileBox>());
|
||||
poiData.put(val, new LinkedHashSet<PoiTileBox>());
|
||||
}
|
||||
poiData.get(val).add(data);
|
||||
prev = -1;
|
||||
|
@ -554,13 +558,14 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
|
|||
// TODO support multiple reading amenity types! +/-
|
||||
// TODO support proper POI editing
|
||||
// TODO support string trigramms
|
||||
// TODO support cancelling poi search request! Do it in another thread
|
||||
// TODO support cancelling poi search request! Do it in another thread (Check is cancelled()!!!)
|
||||
// TODO support fully functional indexed string table and pass name matcher
|
||||
long time = System.currentTimeMillis();
|
||||
IndexPoiCreator poiCreator = new IndexPoiCreator();
|
||||
String fileSqlte = "/home/victor/projects/OsmAnd/data/osm-gen/POI/Ru-mow.poi.odb";
|
||||
String outFile = "/home/victor/projects/OsmAnd/data/osm-gen/POI/Ru-mow.poi.obf";
|
||||
// String fileSqlte = "/home/victor/projects/OsmAnd/data/osm-gen/POI/Netherlands_europe.poi.odb";
|
||||
// String outFile = "/home/victor/projects/OsmAnd/data/osm-gen/POI/Netherlands.poi.obf";
|
||||
// String fileSqlte = "/home/victor/projects/OsmAnd/data/osm-gen/POI/Ru-mow.poi.odb";
|
||||
// String outFile = "/home/victor/projects/OsmAnd/data/osm-gen/POI/Ru-mow.poi.obf";
|
||||
String fileSqlte = "/home/victor/projects/OsmAnd/data/osm-gen/POI/Netherlands_europe.poi.odb";
|
||||
String outFile = "/home/victor/projects/OsmAnd/data/osm-gen/POI/Netherlands.poi.obf";
|
||||
|
||||
poiCreator.poiConnection = (Connection) DBDialect.SQLITE.getDatabaseConnection(
|
||||
fileSqlte, log);
|
||||
|
|
|
@ -15,6 +15,7 @@ import net.osmand.LogUtil;
|
|||
import net.osmand.binary.BinaryMapDataObject;
|
||||
import net.osmand.binary.BinaryMapIndexReader;
|
||||
import net.osmand.binary.BinaryMapIndexReader.MapIndex;
|
||||
import net.osmand.binary.BinaryMapIndexReader.SearchFilter;
|
||||
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
||||
import net.osmand.binary.BinaryMapIndexReader.TagValuePair;
|
||||
import net.osmand.osm.LatLon;
|
||||
|
@ -66,10 +67,7 @@ public class BinaryRoutePlanner {
|
|||
long now = System.nanoTime();
|
||||
|
||||
int zoomToLoad = 31 - ctx.getZoomToLoadTileWithRoads();
|
||||
SearchRequest<BinaryMapDataObject> request = BinaryMapIndexReader.buildSearchRequest(tileX << zoomToLoad,
|
||||
(tileX + 1) << zoomToLoad, tileY << zoomToLoad,
|
||||
(tileY + 1) << zoomToLoad, 15);
|
||||
request.setSearchFilter(new BinaryMapIndexReader.SearchFilter(){
|
||||
SearchFilter searchFilter = new BinaryMapIndexReader.SearchFilter(){
|
||||
@Override
|
||||
public boolean accept(TIntArrayList types, MapIndex index) {
|
||||
for (int j = 0; j < types.size(); j++) {
|
||||
|
@ -90,7 +88,10 @@ public class BinaryRoutePlanner {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
SearchRequest<BinaryMapDataObject> request = BinaryMapIndexReader.buildSearchRequest(tileX << zoomToLoad,
|
||||
(tileX + 1) << zoomToLoad, tileY << zoomToLoad,
|
||||
(tileY + 1) << zoomToLoad, 15, searchFilter);
|
||||
for (BinaryMapIndexReader r : map) {
|
||||
r.searchMapIndex(request);
|
||||
for (BinaryMapDataObject o : request.getSearchResults()) {
|
||||
|
|
|
@ -50,9 +50,8 @@ public class AmenityIndexRepositoryBinary implements AmenityIndexRepository {
|
|||
public List<Amenity> searchAmenities(int stop, int sleft, int sbottom, int sright, int zoom,
|
||||
final PoiFilter filter, final List<Amenity> amenities) {
|
||||
long now = System.currentTimeMillis();
|
||||
int limit = zoom > 0 ? 200 : -1;
|
||||
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(sleft, sright, stop, sbottom, zoom, limit);
|
||||
req.setPoiTypeFilter(new SearchPoiTypeFilter(){
|
||||
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(sleft, sright, stop, sbottom, zoom,
|
||||
new SearchPoiTypeFilter(){
|
||||
@Override
|
||||
public boolean accept(AmenityType type, String subcategory) {
|
||||
return filter.acceptTypeSubtype(type, subcategory);
|
||||
|
|
|
@ -116,7 +116,7 @@ public class CollatorStringMatcher implements StringMatcher {
|
|||
}
|
||||
if (checkSpaces) {
|
||||
for (int i = 1; i <= searchInLength - startLength; i++) {
|
||||
if (Character.isSpace(searchIn.charAt(i - 1)) && !Character.isSpace(searchIn.charAt(i))) {
|
||||
if (considerAsSpace(searchIn.charAt(i - 1)) && !considerAsSpace(searchIn.charAt(i))) {
|
||||
if (collator.equals(searchIn.substring(i, i + startLength), theStart)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -125,4 +125,8 @@ public class CollatorStringMatcher implements StringMatcher {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean considerAsSpace(char c){
|
||||
return !Character.isLetter(c) && !Character.isDigit(c);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ public class RegionAddressRepositoryBinary implements RegionAddressRepository {
|
|||
public synchronized void preloadCities(ResultMatcher<MapObject> resultMatcher) {
|
||||
if (cities.isEmpty()) {
|
||||
try {
|
||||
List<City> cs = file.getCities(region, resultMatcher);
|
||||
List<City> cs = file.getCities(region, BinaryMapIndexReader.buildAddressRequest(resultMatcher));
|
||||
for (City c : cs) {
|
||||
cities.put(c.getId(), c);
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ public class RegionAddressRepositoryBinary implements RegionAddressRepository {
|
|||
public synchronized void preloadBuildings(Street street, ResultMatcher<Building> resultMatcher) {
|
||||
if(street.getBuildings().isEmpty()){
|
||||
try {
|
||||
file.preloadBuildings(street, resultMatcher);
|
||||
file.preloadBuildings(street, BinaryMapIndexReader.buildAddressRequest(resultMatcher));
|
||||
street.sortBuildings();
|
||||
} catch (IOException e) {
|
||||
log.error("Disk operation failed" , e); //$NON-NLS-1$
|
||||
|
@ -92,9 +92,9 @@ public class RegionAddressRepositoryBinary implements RegionAddressRepository {
|
|||
}
|
||||
try {
|
||||
if(o instanceof PostCode){
|
||||
file.preloadStreets((PostCode) o, resultMatcher);
|
||||
file.preloadStreets((PostCode) o, BinaryMapIndexReader.buildAddressRequest(resultMatcher));
|
||||
} else {
|
||||
file.preloadStreets((City) o, resultMatcher);
|
||||
file.preloadStreets((City) o, BinaryMapIndexReader.buildAddressRequest(resultMatcher));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Disk operation failed" , e); //$NON-NLS-1$
|
||||
|
@ -162,8 +162,8 @@ public class RegionAddressRepositoryBinary implements RegionAddressRepository {
|
|||
if (name.length() >= 2 && Algoritms.containsDigit(name)) {
|
||||
// also try to identify postcodes
|
||||
String uName = name.toUpperCase();
|
||||
for (PostCode code : file.getPostcodes(region, resultMatcher, new CollatorStringMatcher(collator, uName,
|
||||
StringMatcherMode.CHECK_CONTAINS))) {
|
||||
for (PostCode code : file.getPostcodes(region, BinaryMapIndexReader.buildAddressRequest(resultMatcher),
|
||||
new CollatorStringMatcher(collator, uName, StringMatcherMode.CHECK_CONTAINS))) {
|
||||
citiesToFill.add(code);
|
||||
if (resultMatcher.isCancelled()) {
|
||||
return citiesToFill;
|
||||
|
@ -186,8 +186,8 @@ public class RegionAddressRepositoryBinary implements RegionAddressRepository {
|
|||
|
||||
int initialsize = citiesToFill.size();
|
||||
if (name.length() >= 3) {
|
||||
for (City c : file.getVillages(region, resultMatcher, new CollatorStringMatcher(collator, name,
|
||||
StringMatcherMode.CHECK_STARTS_FROM_SPACE), useEnglishNames)) {
|
||||
for (City c : file.getVillages(region, BinaryMapIndexReader.buildAddressRequest(resultMatcher),
|
||||
new CollatorStringMatcher(collator, name,StringMatcherMode.CHECK_STARTS_FROM_SPACE), useEnglishNames)) {
|
||||
citiesToFill.add(c);
|
||||
if (resultMatcher.isCancelled()) {
|
||||
return citiesToFill;
|
||||
|
@ -267,7 +267,7 @@ public class RegionAddressRepositoryBinary implements RegionAddressRepository {
|
|||
preloadCities(null);
|
||||
if (!cities.containsKey(id)) {
|
||||
try {
|
||||
file.getVillages(region, new ResultMatcher<MapObject>() {
|
||||
file.getVillages(region, BinaryMapIndexReader.buildAddressRequest(new ResultMatcher<MapObject>() {
|
||||
boolean canceled = false;
|
||||
|
||||
@Override
|
||||
|
@ -282,7 +282,7 @@ public class RegionAddressRepositoryBinary implements RegionAddressRepository {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
}, null, useEnglishNames);
|
||||
}), null, useEnglishNames);
|
||||
} catch (IOException e) {
|
||||
log.error("Disk operation failed", e); //$NON-NLS-1$
|
||||
}
|
||||
|
|
|
@ -239,9 +239,7 @@ public class MapRenderRepositories {
|
|||
int rightX = MapUtils.get31TileNumberX(cRightLongitude);
|
||||
int bottomY = MapUtils.get31TileNumberY(cBottomLatitude);
|
||||
int topY = MapUtils.get31TileNumberY(cTopLatitude);
|
||||
searchRequest = BinaryMapIndexReader.buildSearchRequest(leftX, rightX, topY, bottomY, zoom);
|
||||
if (zoom < 17) {
|
||||
searchRequest.setSearchFilter(new BinaryMapIndexReader.SearchFilter() {
|
||||
BinaryMapIndexReader.SearchFilter searchFilter = new BinaryMapIndexReader.SearchFilter() {
|
||||
|
||||
@Override
|
||||
public boolean accept(TIntArrayList types, BinaryMapIndexReader.MapIndex root) {
|
||||
|
@ -260,7 +258,9 @@ public class MapRenderRepositories {
|
|||
return false;
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
if (zoom > 17) {
|
||||
searchFilter = null;
|
||||
}
|
||||
// search lower level zooms only in basemap for now :) before it was intersection of maps on zooms 5-7
|
||||
boolean basemapSearch = false;
|
||||
|
@ -278,10 +278,8 @@ public class MapRenderRepositories {
|
|||
continue;
|
||||
}
|
||||
BinaryMapIndexReader c = files.get(mapName);
|
||||
searchRequest = BinaryMapIndexReader.buildSearchRequest(leftX, rightX, topY, bottomY, zoom, null);
|
||||
List<BinaryMapDataObject> res = c.searchMapIndex(searchRequest);
|
||||
if (checkWhetherInterrupted()) {
|
||||
return false;
|
||||
}
|
||||
for (BinaryMapDataObject r : res) {
|
||||
if (PerformanceFlags.checkForDuplicateObjectIds) {
|
||||
if (ids.contains(r.getId())) {
|
||||
|
@ -306,14 +304,11 @@ public class MapRenderRepositories {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (checkWhetherInterrupted()) {
|
||||
return false;
|
||||
}
|
||||
tempList.add(r);
|
||||
}
|
||||
searchRequest.clearSearchResults();
|
||||
}
|
||||
|
||||
List<MultyPolygon> pMulti = proccessMultiPolygons(multiPolygons, leftX, rightX, bottomY, topY, zoom);
|
||||
|
|
Loading…
Reference in a new issue