Update search language

This commit is contained in:
Victor Shcherb 2016-07-12 16:47:34 +03:00
parent 5f70002d1e
commit 191d621f5f
4 changed files with 116 additions and 77 deletions

View file

@ -30,6 +30,7 @@ public abstract class MapObject implements Comparable<MapObject> {
protected LatLon location = null;
protected int fileOffset = 0;
protected Long id = null;
private Object referenceFile = null;
public void setId(Long id) {
@ -268,5 +269,13 @@ public abstract class MapObject implements Comparable<MapObject> {
}
}
}
public void setReferenceFile(Object referenceFile) {
this.referenceFile = referenceFile;
}
public Object getReferenceFile() {
return referenceFile;
}
}

View file

@ -93,10 +93,14 @@ public class SearchUICore {
apis.add(new SearchCoreFactory.SearchAmenityByNameAPI());
apis.add(new SearchCoreFactory.SearchStreetByCityAPI());
apis.add(new SearchCoreFactory.SearchBuildingAndIntersectionsByStreetAPI());
apis.add(new SearchCoreFactory.SearchRegionByNameAPI());
apis.add(new SearchCoreFactory.SearchAddressByNameAPI());
}
public void registerAPI(SearchCoreAPI api) {
apis.add(api);
}
public SearchResultCollection getCurrentSearchResult() {
return currentSearchResult;

View file

@ -42,23 +42,22 @@ import net.osmand.util.MapUtils;
public class SearchCoreFactory {
// TODO streets by city
// TODO amenity by name
// TODO ignore streets with <>
// TODO add location parse
// TODO add url parse (geo)
// TODO add location parse
// TODO show buildings if street is one or default ( <CITY>, CITY (den ilp), 1186RM)
// TODO exclude duplicate streets/cities...
// TODO add full text search with comma
// TODO add full text search with comma correct order
// TODO MED support poi additional select type and search
// TODO MED display results momentarily
// TODO MED add full text search without comma
// TODO MED add full text search without comma and different word order
// TODO LOW automatically increase radius if nothing found
// TODO LOW automatically increase radius if nothing found (log radius search)
public static abstract class SearchBaseAPI implements SearchCoreAPI {
@ -67,10 +66,6 @@ public class SearchCoreFactory {
return true;
}
public QuadRect getBBoxToSearch(SearchPhrase phrase, int radiusInMeters) {
return phrase.getBBoxToSearch(phrase.getRadiusLevel() * radiusInMeters);
}
@Override
public int getSearchPriority(SearchPhrase p) {
return 1;
@ -117,54 +112,86 @@ public class SearchCoreFactory {
private Map<BinaryMapIndexReader, List<City>> townCities = new LinkedHashMap<>();
private QuadTree<City> townCitiesQR = new QuadTree<City>(new QuadRect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE),
8, 0.55f);
private List<City> resArray = new ArrayList<>();
public boolean isLastWordPoi(SearchPhrase p) {
return p.isLastWord(ObjectType.POI);
}
public boolean isNoSelectedType(SearchPhrase p) {
return p.isNoSelectedType();
@Override
public int getSearchPriority(SearchPhrase p) {
if (p.isNoSelectedType()) {
return 5;
}
return 10;
}
@Override
public boolean search(final SearchPhrase phrase, final SearchResultMatcher resultMatcher) throws IOException {
// if (!phrase.hasObjectType(ObjectType.REGION)) {
// return false;
// }
if (phrase.getLastWord().isEmpty()) {
return false;
}
// (search streets in neighbor cities for radiusLevel > 2)
if (phrase.isNoSelectedType() ||
phrase.isLastWord(ObjectType.CITY, ObjectType.VILLAGE, ObjectType.POSTCODE) || // ?
phrase.isLastWord(ObjectType.REGION) || phrase.getRadiusLevel() >= 2) {
final boolean locSpecified = phrase.getLastTokenLocation() != null;
LatLon loc = phrase.getLastTokenLocation();
final QuadRect streetBbox = getBBoxToSearch(phrase, DEFAULT_ADDRESS_BBOX_RADIUS);
final QuadRect postcodeBbox = getBBoxToSearch(phrase, DEFAULT_ADDRESS_BBOX_RADIUS * 5);
final QuadRect villagesBbox = getBBoxToSearch(phrase, DEFAULT_ADDRESS_BBOX_RADIUS * 3);
final QuadRect cityBbox = getBBoxToSearch(phrase, DEFAULT_ADDRESS_BBOX_RADIUS * 10);
final int priority = isNoSelectedType(phrase) ? 1 : 3;
Iterator<BinaryMapIndexReader> offlineIndexes = phrase.getOfflineIndexes(DEFAULT_ADDRESS_BBOX_RADIUS * 10 *
phrase.getRadiusLevel(), SearchPhraseDataType.ADDRESS);
while(offlineIndexes.hasNext()) {
BinaryMapIndexReader r = offlineIndexes.next();
if(!townCities.containsKey(r)) {
BinaryMapIndexReader.buildAddressRequest(null);
List<City> l = r.getCities(null, BinaryMapAddressReaderAdapter.CITY_TOWN_TYPE);
townCities.put(r, l);
for(City c : l) {
LatLon cl = c.getLocation();
int y = MapUtils.get31TileNumberY(cl.getLatitude());
int x = MapUtils.get31TileNumberX(cl.getLongitude());
QuadRect qr = new QuadRect(x, y, x, y);
townCitiesQR.insert(c, qr);
}
// phrase.isLastWord(ObjectType.CITY, ObjectType.VILLAGE, ObjectType.POSTCODE) || phrase.isLastWord(ObjectType.REGION)
if (phrase.isNoSelectedType() || phrase.getRadiusLevel() >= 2) {
initAndSearchCities(phrase, resultMatcher);
searchByName(phrase, resultMatcher);
}
return true;
}
private void initAndSearchCities(final SearchPhrase phrase, final SearchResultMatcher resultMatcher) throws IOException {
QuadRect bbox = phrase.getBBoxToSearch(phrase.getRadiusSearch(DEFAULT_ADDRESS_BBOX_RADIUS * 10));
Iterator<BinaryMapIndexReader> offlineIndexes = phrase.getOfflineIndexes(bbox, SearchPhraseDataType.ADDRESS);
while(offlineIndexes.hasNext()) {
BinaryMapIndexReader r = offlineIndexes.next();
if(!townCities.containsKey(r)) {
BinaryMapIndexReader.buildAddressRequest(null);
List<City> l = r.getCities(null, BinaryMapAddressReaderAdapter.CITY_TOWN_TYPE);
townCities.put(r, l);
for(City c : l) {
LatLon cl = c.getLocation();
c.setReferenceFile(r);
int y = MapUtils.get31TileNumberY(cl.getLatitude());
int x = MapUtils.get31TileNumberX(cl.getLongitude());
QuadRect qr = new QuadRect(x, y, x, y);
townCitiesQR.insert(c, qr);
}
}
}
if (phrase.isNoSelectedType() && bbox != null && phrase.getLastWord().length() > 0) {
NameStringMatcher nm = phrase.getNameStringMatcher();
resArray.clear();
resArray = townCitiesQR.queryInBox(bbox, resArray);
int limit = 0;
for (City c : resArray) {
SearchResult sr = new SearchResult(phrase);
sr.object = c;
sr.file = (BinaryMapIndexReader) c.getReferenceFile();
sr.localeName = c.getName(phrase.getSettings().getLang(), true);
sr.otherNames = c.getAllNames(true);
sr.localeRelatedObjectName = sr.file.getRegionName();
sr.location = c.getLocation();
sr.priority = 1;
sr.priorityDistance = 0.1;
sr.objectType = ObjectType.CITY;
if(nm.matches(sr.localeName) || nm.matches(sr.otherNames)) {
resultMatcher.publish(sr);
}
if(limit++ > LIMIT * phrase.getRadiusLevel()) {
break;
}
}
}
}
private void searchByName(final SearchPhrase phrase, final SearchResultMatcher resultMatcher)
throws IOException {
if(phrase.getRadiusLevel() > 1 || phrase.getLastWord().length() > 3) {
final boolean locSpecified = phrase.getLastTokenLocation() != null;
LatLon loc = phrase.getLastTokenLocation();
final QuadRect streetBbox = phrase.getBBoxToSearch(phrase.getRadiusSearch(DEFAULT_ADDRESS_BBOX_RADIUS));
final QuadRect postcodeBbox = phrase.getBBoxToSearch(phrase.getRadiusSearch(DEFAULT_ADDRESS_BBOX_RADIUS * 5));
final QuadRect villagesBbox = phrase.getBBoxToSearch(phrase.getRadiusSearch(DEFAULT_ADDRESS_BBOX_RADIUS * 3));
final QuadRect cityBbox = phrase.getBBoxToSearch(phrase.getRadiusSearch(DEFAULT_ADDRESS_BBOX_RADIUS * 10));
final int priority = phrase.isNoSelectedType() ? 1 : 3;
final BinaryMapIndexReader[] currentFile = new BinaryMapIndexReader[1];
ResultMatcher<MapObject> rm = new ResultMatcher<MapObject>() {
int limit = 0;
@ -194,9 +221,14 @@ public class SearchCoreFactory {
} else if (object instanceof City) {
CityType type = ((City)object).getType();
if (type == CityType.CITY || type == CityType.TOWN) {
if(phrase.isNoSelectedType()) {
// ignore city/town
return false;
}
if (locSpecified && !cityBbox.contains(x, y, x, y)) {
return false;
}
sr.objectType = ObjectType.CITY;
sr.priorityDistance = 0.1;
} else if (((City)object).isPostcode()) {
@ -240,32 +272,21 @@ public class SearchCoreFactory {
resultMatcher.isCancelled();
}
};
if(phrase.getRadiusLevel() > 1 || phrase.getLastWord().length() > 2) {
Iterator<BinaryMapIndexReader> offlineIterator = phrase.getOfflineIndexes(DEFAULT_ADDRESS_BBOX_RADIUS * 10 *
phrase.getRadiusLevel(), SearchPhraseDataType.ADDRESS);
while (offlineIterator.hasNext()) {
BinaryMapIndexReader r = offlineIterator.next();
currentFile[0] = r;
SearchRequest<MapObject> req = BinaryMapIndexReader.buildAddressByNameRequest(rm, phrase
.getLastWord().toLowerCase(), StringMatcherMode.CHECK_STARTS_FROM_SPACE);
if (locSpecified) {
req.setBBoxRadius(loc.getLatitude(), loc.getLongitude(), DEFAULT_ADDRESS_BBOX_RADIUS * 10 * phrase.getRadiusLevel());
}
r.searchAddressDataByName(req);
Iterator<BinaryMapIndexReader> offlineIterator = phrase.getOfflineIndexes(phrase.getRadiusSearch(DEFAULT_ADDRESS_BBOX_RADIUS * 10),
SearchPhraseDataType.ADDRESS);
while (offlineIterator.hasNext()) {
BinaryMapIndexReader r = offlineIterator.next();
currentFile[0] = r;
SearchRequest<MapObject> req = BinaryMapIndexReader.buildAddressByNameRequest(rm, phrase
.getLastWord().toLowerCase(), StringMatcherMode.CHECK_STARTS_FROM_SPACE);
if (locSpecified) {
req.setBBoxRadius(loc.getLatitude(), loc.getLongitude(), phrase.getRadiusSearch(DEFAULT_ADDRESS_BBOX_RADIUS * 10));
}
r.searchAddressDataByName(req);
}
}
return true;
}
@Override
public int getSearchPriority(SearchPhrase p) {
if (p.isNoSelectedType()) {
return 5;
}
return 10;
}
}
@ -389,7 +410,7 @@ public class SearchCoreFactory {
poiAdditionals.clear();
updateTypesToAccept(pt);
QuadRect bbox = getBBoxToSearch(phrase, 10000);
QuadRect bbox = phrase.getBBoxToSearch(phrase.getRadiusSearch(10000));
List<BinaryMapIndexReader> oo = phrase.getOfflineIndexes();
final BinaryMapIndexReader[] selected = new BinaryMapIndexReader[1];
final NameStringMatcher ns = phrase.getNameStringMatcher();

View file

@ -6,11 +6,10 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.osmand.CollatorStringMatcher;
import net.osmand.StringMatcher;
import net.osmand.CollatorStringMatcher.StringMatcherMode;
import net.osmand.StringMatcher;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
import net.osmand.data.LatLon;
@ -66,13 +65,11 @@ public class SearchPhrase {
if(unknown) {
sp.words.add(new SearchWord(ws[i].trim()));
}
// sp.text += ws[i] + ", ";
}
}
sp.lastWord = ws[ws.length - 1];
}
sp.lastWordTrim = sp.lastWord.trim();
//sp.text = sp.text.trim();
return sp;
}
@ -122,9 +119,14 @@ public class SearchPhrase {
public Iterator<BinaryMapIndexReader> getOfflineIndexes(int meters, final SearchPhraseDataType dt) {
final QuadRect rect = meters > 0 ? getBBoxToSearch(meters) : null;
return getOfflineIndexes(rect, dt);
}
public Iterator<BinaryMapIndexReader> getOfflineIndexes(final QuadRect rect, final SearchPhraseDataType dt) {
List<BinaryMapIndexReader> list = indexes != null ? indexes : settings.getOfflineIndexes();
final Iterator<BinaryMapIndexReader> lit = list.iterator();
final QuadRect rect = meters > 0 ? getBBoxToSearch(meters) : null;
return new Iterator<BinaryMapIndexReader>() {
BinaryMapIndexReader next = null;
@Override
@ -167,7 +169,6 @@ public class SearchPhrase {
public void remove() {
}
};
}
public List<BinaryMapIndexReader> getOfflineIndexes() {
@ -371,4 +372,8 @@ public class SearchPhrase {
}
}
public int getRadiusSearch(int meters) {
return getRadiusLevel() * meters;
}
}