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.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
@ -32,6 +34,7 @@ public class BinaryMapPoiReaderAdapter {
|
|||
public static final int SHIFT_BITS_CATEGORY = 7;
|
||||
private static final int CATEGORY_MASK = (1 << SHIFT_BITS_CATEGORY) - 1 ;
|
||||
private static final int ZOOM_TO_SKIP_FILTER = 3;
|
||||
private static final int BUCKET_SEARCH_BY_NAME = 5;
|
||||
|
||||
public static class PoiRegion extends BinaryIndexPart {
|
||||
|
||||
|
@ -161,7 +164,7 @@ public class BinaryMapPoiReaderAdapter {
|
|||
}
|
||||
|
||||
protected void searchPoiByName( PoiRegion region, SearchRequest<Amenity> req) throws IOException {
|
||||
TIntArrayList offsets = new TIntArrayList();
|
||||
TIntLongHashMap offsets = new TIntLongHashMap();
|
||||
Collator instance = Collator.getInstance();
|
||||
instance.setStrength(Collator.PRIMARY);
|
||||
CollatorStringMatcher matcher = new CollatorStringMatcher(instance, req.nameQuery,
|
||||
|
@ -180,16 +183,42 @@ public class BinaryMapPoiReaderAdapter {
|
|||
case OsmandOdb.OsmAndPoiIndex.NAMEINDEX_FIELD_NUMBER :
|
||||
int length = readInt();
|
||||
int oldLimit = codedIS.pushLimit(length);
|
||||
// here offsets are sorted by distance
|
||||
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();
|
||||
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) +
|
||||
"ms. Found " + offsets.size() +" subtress");
|
||||
for (int j = 0; j < offsets.size(); j++) {
|
||||
codedIS.seek(offsets.get(j) + indexOffset);
|
||||
"ms. Found " + offKeys.length +" subtress");
|
||||
for (int j = 0; j < offKeys.length; j++) {
|
||||
codedIS.seek(offKeys[j] + indexOffset);
|
||||
int len = readInt();
|
||||
int oldLim = codedIS.pushLimit(len);
|
||||
readPoiData(matcher, req, region);
|
||||
|
@ -209,8 +238,8 @@ public class BinaryMapPoiReaderAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
private TIntArrayList readPoiNameIndex(Collator instance, String query, SearchRequest<Amenity> req) throws IOException {
|
||||
TIntArrayList offsets = new TIntArrayList();
|
||||
private TIntLongHashMap readPoiNameIndex(Collator instance, String query, SearchRequest<Amenity> req) throws IOException {
|
||||
TIntLongHashMap offsets = new TIntLongHashMap();
|
||||
TIntArrayList dataOffsets = null;
|
||||
while(true){
|
||||
int t = codedIS.readTag();
|
||||
|
@ -233,7 +262,7 @@ public class BinaryMapPoiReaderAdapter {
|
|||
codedIS.seek(dataOffsets.get(i) + offset);
|
||||
int len = codedIS.readRawVarint32();
|
||||
int oldLim = codedIS.pushLimit(len);
|
||||
readPoiNameIndexData(offsets);
|
||||
readPoiNameIndexData(offsets, req);
|
||||
codedIS.popLimit(oldLim);
|
||||
if (req.isCancelled()) {
|
||||
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){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
|
@ -261,7 +290,7 @@ public class BinaryMapPoiReaderAdapter {
|
|||
case OsmandOdb.OsmAndPoiNameIndexData.ATOMS_FIELD_NUMBER :
|
||||
int len = codedIS.readRawVarint32();
|
||||
int oldLim = codedIS.pushLimit(len);
|
||||
readPoiNameIndexDataAtom(offsets);
|
||||
readPoiNameIndexDataAtom(offsets, req);
|
||||
codedIS.popLimit(oldLim);
|
||||
break;
|
||||
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){
|
||||
int t = codedIS.readTag();
|
||||
int tag = WireFormat.getTagFieldNumber(t);
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int zoom = 15;
|
||||
switch (tag) {
|
||||
case 0:
|
||||
return;
|
||||
case OsmandOdb.OsmAndPoiNameIndexDataAtom.X_FIELD_NUMBER :
|
||||
/*int x = */codedIS.readUInt32();
|
||||
x = codedIS.readUInt32();
|
||||
break;
|
||||
case OsmandOdb.OsmAndPoiNameIndexDataAtom.Y_FIELD_NUMBER :
|
||||
/*int y = */codedIS.readUInt32();
|
||||
y = codedIS.readUInt32();
|
||||
break;
|
||||
case OsmandOdb.OsmAndPoiNameIndexDataAtom.ZOOM_FIELD_NUMBER :
|
||||
/*int zoom = */codedIS.readUInt32();
|
||||
zoom = codedIS.readUInt32();
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
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 make more discrete POI Filter
|
||||
// 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();
|
||||
IndexPoiCreator poiCreator = new IndexPoiCreator();
|
||||
// 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"?>
|
||||
<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="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>
|
||||
|
|
|
@ -604,6 +604,19 @@ public class ResourceManager {
|
|||
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,
|
||||
double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude,
|
||||
double lat, double lon, ResultMatcher<Amenity> matcher) {
|
||||
|
|
|
@ -7,10 +7,13 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import net.osmand.osm.LatLon;
|
||||
import net.osmand.plus.NameFinderPoiFilter;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.PoiFilter;
|
||||
import net.osmand.plus.PoiFiltersHelper;
|
||||
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.OsmandApplication;
|
||||
import android.app.ListActivity;
|
||||
|
@ -25,6 +28,7 @@ import android.widget.ArrayAdapter;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -109,6 +113,13 @@ public class SearchPoiFilterActivity extends ListActivity {
|
|||
showEditActivity(filter);
|
||||
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);
|
||||
newIntent.putExtra(SearchPOIActivity.AMENITY_FILTER, filter.getFilterId());
|
||||
updateIntentToLaunch(newIntent);
|
||||
|
|
Loading…
Reference in a new issue