Search by name improvement
This commit is contained in:
parent
aaea8cb0de
commit
eb7abdd0b8
5 changed files with 73 additions and 17 deletions
|
@ -8,6 +8,8 @@ import java.io.IOException;
|
||||||
import java.text.Collator;
|
import java.text.Collator;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
@ -32,6 +34,7 @@ public class BinaryMapPoiReaderAdapter {
|
||||||
public static final int SHIFT_BITS_CATEGORY = 7;
|
public static final int SHIFT_BITS_CATEGORY = 7;
|
||||||
private static final int CATEGORY_MASK = (1 << SHIFT_BITS_CATEGORY) - 1 ;
|
private static final int CATEGORY_MASK = (1 << SHIFT_BITS_CATEGORY) - 1 ;
|
||||||
private static final int ZOOM_TO_SKIP_FILTER = 3;
|
private static final int ZOOM_TO_SKIP_FILTER = 3;
|
||||||
|
private static final int BUCKET_SEARCH_BY_NAME = 5;
|
||||||
|
|
||||||
public static class PoiRegion extends BinaryIndexPart {
|
public static class PoiRegion extends BinaryIndexPart {
|
||||||
|
|
||||||
|
@ -161,7 +164,7 @@ public class BinaryMapPoiReaderAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void searchPoiByName( PoiRegion region, SearchRequest<Amenity> req) throws IOException {
|
protected void searchPoiByName( PoiRegion region, SearchRequest<Amenity> req) throws IOException {
|
||||||
TIntArrayList offsets = new TIntArrayList();
|
TIntLongHashMap offsets = new TIntLongHashMap();
|
||||||
Collator instance = Collator.getInstance();
|
Collator instance = Collator.getInstance();
|
||||||
instance.setStrength(Collator.PRIMARY);
|
instance.setStrength(Collator.PRIMARY);
|
||||||
CollatorStringMatcher matcher = new CollatorStringMatcher(instance, req.nameQuery,
|
CollatorStringMatcher matcher = new CollatorStringMatcher(instance, req.nameQuery,
|
||||||
|
@ -180,16 +183,42 @@ public class BinaryMapPoiReaderAdapter {
|
||||||
case OsmandOdb.OsmAndPoiIndex.NAMEINDEX_FIELD_NUMBER :
|
case OsmandOdb.OsmAndPoiIndex.NAMEINDEX_FIELD_NUMBER :
|
||||||
int length = readInt();
|
int length = readInt();
|
||||||
int oldLimit = codedIS.pushLimit(length);
|
int oldLimit = codedIS.pushLimit(length);
|
||||||
|
// here offsets are sorted by distance
|
||||||
offsets = readPoiNameIndex(instance, req.nameQuery, req);
|
offsets = readPoiNameIndex(instance, req.nameQuery, req);
|
||||||
codedIS.popLimit(oldLimit);
|
codedIS.popLimit(oldLimit);
|
||||||
break;
|
break;
|
||||||
case OsmandOdb.OsmAndPoiIndex.POIDATA_FIELD_NUMBER :
|
case OsmandOdb.OsmAndPoiIndex.POIDATA_FIELD_NUMBER :
|
||||||
// also offsets can be randomly skipped by limit
|
// also offsets can be randomly skipped by limit
|
||||||
offsets.sort();
|
Integer[] offKeys = new Integer[offsets.size()];
|
||||||
|
if (offsets.size() > 0) {
|
||||||
|
int[] keys = offsets.keys();
|
||||||
|
for (int i = 0; i < keys.length; i++) {
|
||||||
|
offKeys[i] = keys[i];
|
||||||
|
}
|
||||||
|
final TIntLongHashMap foffsets = offsets;
|
||||||
|
Arrays.sort(offKeys, new Comparator<Integer>() {
|
||||||
|
@Override
|
||||||
|
public int compare(Integer object1, Integer object2) {
|
||||||
|
return Double.compare(foffsets.get(object1), foffsets.get(object2));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
int p = 0;
|
||||||
|
for (int i = BUCKET_SEARCH_BY_NAME;; i += BUCKET_SEARCH_BY_NAME) {
|
||||||
|
if (i > offKeys.length) {
|
||||||
|
Arrays.sort(offKeys, p, offKeys.length);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
Arrays.sort(offKeys, p, i);
|
||||||
|
}
|
||||||
|
p = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LOG.info("Searched poi structure in "+(System.currentTimeMillis() - time) +
|
LOG.info("Searched poi structure in "+(System.currentTimeMillis() - time) +
|
||||||
"ms. Found " + offsets.size() +" subtress");
|
"ms. Found " + offKeys.length +" subtress");
|
||||||
for (int j = 0; j < offsets.size(); j++) {
|
for (int j = 0; j < offKeys.length; j++) {
|
||||||
codedIS.seek(offsets.get(j) + indexOffset);
|
codedIS.seek(offKeys[j] + indexOffset);
|
||||||
int len = readInt();
|
int len = readInt();
|
||||||
int oldLim = codedIS.pushLimit(len);
|
int oldLim = codedIS.pushLimit(len);
|
||||||
readPoiData(matcher, req, region);
|
readPoiData(matcher, req, region);
|
||||||
|
@ -209,8 +238,8 @@ public class BinaryMapPoiReaderAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TIntArrayList readPoiNameIndex(Collator instance, String query, SearchRequest<Amenity> req) throws IOException {
|
private TIntLongHashMap readPoiNameIndex(Collator instance, String query, SearchRequest<Amenity> req) throws IOException {
|
||||||
TIntArrayList offsets = new TIntArrayList();
|
TIntLongHashMap offsets = new TIntLongHashMap();
|
||||||
TIntArrayList dataOffsets = null;
|
TIntArrayList dataOffsets = null;
|
||||||
while(true){
|
while(true){
|
||||||
int t = codedIS.readTag();
|
int t = codedIS.readTag();
|
||||||
|
@ -233,7 +262,7 @@ public class BinaryMapPoiReaderAdapter {
|
||||||
codedIS.seek(dataOffsets.get(i) + offset);
|
codedIS.seek(dataOffsets.get(i) + offset);
|
||||||
int len = codedIS.readRawVarint32();
|
int len = codedIS.readRawVarint32();
|
||||||
int oldLim = codedIS.pushLimit(len);
|
int oldLim = codedIS.pushLimit(len);
|
||||||
readPoiNameIndexData(offsets);
|
readPoiNameIndexData(offsets, req);
|
||||||
codedIS.popLimit(oldLim);
|
codedIS.popLimit(oldLim);
|
||||||
if (req.isCancelled()) {
|
if (req.isCancelled()) {
|
||||||
codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
|
codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
|
||||||
|
@ -251,7 +280,7 @@ public class BinaryMapPoiReaderAdapter {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readPoiNameIndexData(TIntArrayList offsets) throws IOException {
|
private void readPoiNameIndexData(TIntLongHashMap offsets, SearchRequest<Amenity> req) throws IOException {
|
||||||
while(true){
|
while(true){
|
||||||
int t = codedIS.readTag();
|
int t = codedIS.readTag();
|
||||||
int tag = WireFormat.getTagFieldNumber(t);
|
int tag = WireFormat.getTagFieldNumber(t);
|
||||||
|
@ -261,7 +290,7 @@ public class BinaryMapPoiReaderAdapter {
|
||||||
case OsmandOdb.OsmAndPoiNameIndexData.ATOMS_FIELD_NUMBER :
|
case OsmandOdb.OsmAndPoiNameIndexData.ATOMS_FIELD_NUMBER :
|
||||||
int len = codedIS.readRawVarint32();
|
int len = codedIS.readRawVarint32();
|
||||||
int oldLim = codedIS.pushLimit(len);
|
int oldLim = codedIS.pushLimit(len);
|
||||||
readPoiNameIndexDataAtom(offsets);
|
readPoiNameIndexDataAtom(offsets, req);
|
||||||
codedIS.popLimit(oldLim);
|
codedIS.popLimit(oldLim);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -272,24 +301,28 @@ public class BinaryMapPoiReaderAdapter {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readPoiNameIndexDataAtom(TIntArrayList offsets) throws IOException {
|
private void readPoiNameIndexDataAtom(TIntLongHashMap offsets, SearchRequest<Amenity> req) throws IOException {
|
||||||
while(true){
|
while(true){
|
||||||
int t = codedIS.readTag();
|
int t = codedIS.readTag();
|
||||||
int tag = WireFormat.getTagFieldNumber(t);
|
int tag = WireFormat.getTagFieldNumber(t);
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
int zoom = 15;
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case 0:
|
case 0:
|
||||||
return;
|
return;
|
||||||
case OsmandOdb.OsmAndPoiNameIndexDataAtom.X_FIELD_NUMBER :
|
case OsmandOdb.OsmAndPoiNameIndexDataAtom.X_FIELD_NUMBER :
|
||||||
/*int x = */codedIS.readUInt32();
|
x = codedIS.readUInt32();
|
||||||
break;
|
break;
|
||||||
case OsmandOdb.OsmAndPoiNameIndexDataAtom.Y_FIELD_NUMBER :
|
case OsmandOdb.OsmAndPoiNameIndexDataAtom.Y_FIELD_NUMBER :
|
||||||
/*int y = */codedIS.readUInt32();
|
y = codedIS.readUInt32();
|
||||||
break;
|
break;
|
||||||
case OsmandOdb.OsmAndPoiNameIndexDataAtom.ZOOM_FIELD_NUMBER :
|
case OsmandOdb.OsmAndPoiNameIndexDataAtom.ZOOM_FIELD_NUMBER :
|
||||||
/*int zoom = */codedIS.readUInt32();
|
zoom = codedIS.readUInt32();
|
||||||
break;
|
break;
|
||||||
case OsmandOdb.OsmAndPoiNameIndexDataAtom.SHIFTTO_FIELD_NUMBER :
|
case OsmandOdb.OsmAndPoiNameIndexDataAtom.SHIFTTO_FIELD_NUMBER :
|
||||||
offsets.add(readInt());
|
long d = Math.abs(req.x - (x << (31 - zoom))) + Math.abs(req.y - (y << (31 - zoom)));
|
||||||
|
offsets.put(readInt(), d);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipUnknownField(t);
|
skipUnknownField(t);
|
||||||
|
|
|
@ -558,8 +558,6 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
|
||||||
// TODO support cancelling poi search request! Do it in another thread (Check is cancelled()!!!)
|
// TODO support cancelling poi search request! Do it in another thread (Check is cancelled()!!!)
|
||||||
// TODO make more discrete POI Filter
|
// TODO make more discrete POI Filter
|
||||||
// TODO implement UI to show matching by name subcategories
|
// TODO implement UI to show matching by name subcategories
|
||||||
// TODO Warning if there is no poi files to search by name
|
|
||||||
// TODO sort blocks by distance in binary reader
|
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
IndexPoiCreator poiCreator = new IndexPoiCreator();
|
IndexPoiCreator poiCreator = new IndexPoiCreator();
|
||||||
// String fileSqlte = "/home/victor/projects/OsmAnd/data/osm-gen/POI/Ru-mow.poi.odb";
|
// String fileSqlte = "/home/victor/projects/OsmAnd/data/osm-gen/POI/Ru-mow.poi.odb";
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
<string name="data_to_search_poi_not_available">Local data to search POI is not present.</string>
|
||||||
<string name="poi_filter_by_name">Search by name</string>
|
<string name="poi_filter_by_name">Search by name</string>
|
||||||
<string name="old_poi_file_should_be_deleted">The poi data file \'%1$s\' is deprecated and can be deleted.</string>
|
<string name="old_poi_file_should_be_deleted">The poi data file \'%1$s\' is deprecated and can be deleted.</string>
|
||||||
<string name="update_poi_file_not_found">Local file to maintain poi changes not found and could not be created.</string>
|
<string name="update_poi_file_not_found">Local file to maintain poi changes not found and could not be created.</string>
|
||||||
|
|
|
@ -604,6 +604,19 @@ public class ResourceManager {
|
||||||
return amenities;
|
return amenities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean containsAmenityRepositoryToSearch(boolean searchByName){
|
||||||
|
for (AmenityIndexRepository index : amenityRepositories) {
|
||||||
|
if(searchByName){
|
||||||
|
if(index instanceof AmenityIndexRepositoryBinary){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public List<Amenity> searchAmenitiesByName(String searchQuery,
|
public List<Amenity> searchAmenitiesByName(String searchQuery,
|
||||||
double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude,
|
double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude,
|
||||||
double lat, double lon, ResultMatcher<Amenity> matcher) {
|
double lat, double lon, ResultMatcher<Amenity> matcher) {
|
||||||
|
|
|
@ -7,10 +7,13 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import net.osmand.osm.LatLon;
|
import net.osmand.osm.LatLon;
|
||||||
|
import net.osmand.plus.NameFinderPoiFilter;
|
||||||
import net.osmand.plus.OsmandSettings;
|
import net.osmand.plus.OsmandSettings;
|
||||||
import net.osmand.plus.PoiFilter;
|
import net.osmand.plus.PoiFilter;
|
||||||
import net.osmand.plus.PoiFiltersHelper;
|
import net.osmand.plus.PoiFiltersHelper;
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.ResourceManager;
|
||||||
|
import net.osmand.plus.SearchByNameFilter;
|
||||||
import net.osmand.plus.activities.EditPOIFilterActivity;
|
import net.osmand.plus.activities.EditPOIFilterActivity;
|
||||||
import net.osmand.plus.activities.OsmandApplication;
|
import net.osmand.plus.activities.OsmandApplication;
|
||||||
import android.app.ListActivity;
|
import android.app.ListActivity;
|
||||||
|
@ -25,6 +28,7 @@ import android.widget.ArrayAdapter;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -109,6 +113,13 @@ public class SearchPoiFilterActivity extends ListActivity {
|
||||||
showEditActivity(filter);
|
showEditActivity(filter);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(!(filter instanceof NameFinderPoiFilter)){
|
||||||
|
ResourceManager rm = ((OsmandApplication) getApplication()).getResourceManager();
|
||||||
|
if(!rm.containsAmenityRepositoryToSearch(filter instanceof SearchByNameFilter)){
|
||||||
|
Toast.makeText(this, R.string.data_to_search_poi_not_available, Toast.LENGTH_LONG);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
final Intent newIntent = new Intent(SearchPoiFilterActivity.this, SearchPOIActivity.class);
|
final Intent newIntent = new Intent(SearchPoiFilterActivity.this, SearchPOIActivity.class);
|
||||||
newIntent.putExtra(SearchPOIActivity.AMENITY_FILTER, filter.getFilterId());
|
newIntent.putExtra(SearchPOIActivity.AMENITY_FILTER, filter.getFilterId());
|
||||||
updateIntentToLaunch(newIntent);
|
updateIntentToLaunch(newIntent);
|
||||||
|
|
Loading…
Reference in a new issue