Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
5ea85a4d2b
7 changed files with 410 additions and 1 deletions
|
@ -2304,7 +2304,7 @@ public class BinaryMapIndexReader {
|
|||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
}, "Amstelvee", StringMatcherMode.CHECK_ONLY_STARTS_WITH);
|
||||
}, "Logger", StringMatcherMode.CHECK_ONLY_STARTS_WITH);
|
||||
reader.searchAddressDataByName(req);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
package net.osmand.search.example;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.ResultMatcher;
|
||||
import net.osmand.search.example.core.SearchPhrase;
|
||||
import net.osmand.search.example.core.SearchResult;
|
||||
|
||||
public class SearchUIAdapter {
|
||||
|
||||
SearchPhrase p;
|
||||
List<SearchResult> currentSearchResults = new ArrayList<>();
|
||||
|
||||
|
||||
public void updateSearchPhrase(SearchPhrase p) {
|
||||
boolean hasSameConstantWords = p.hasSameConstantWords(this.p);
|
||||
this.p = p;
|
||||
if(hasSameConstantWords) {
|
||||
filterCurrentResults(currentSearchResults);
|
||||
}
|
||||
boolean lastWordLooksLikeURLOrNumber = true;
|
||||
if(lastWordLooksLikeURLOrNumber) {
|
||||
// add search result location
|
||||
}
|
||||
|
||||
boolean poiTypeWasNotSelected = true;
|
||||
if(poiTypeWasNotSelected) {
|
||||
// add search result poi filters
|
||||
sortCurrentSearchResults();
|
||||
}
|
||||
|
||||
asyncCallToSearchCoreAPI(
|
||||
// final result
|
||||
new ResultMatcher<List<SearchResult<?>>>() {
|
||||
|
||||
@Override
|
||||
public boolean publish(List<SearchResult<?>> object) {
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}, // visitor
|
||||
new ResultMatcher<SearchResult<?>>() {
|
||||
|
||||
@Override
|
||||
public boolean publish(SearchResult<?> object) {
|
||||
if(filterOneResult(object)) {
|
||||
currentSearchResults.add(object);
|
||||
sortCurrentSearchResults();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void asyncCallToSearchCoreAPI(
|
||||
ResultMatcher<List<SearchResult<?>>> publisher,
|
||||
ResultMatcher<SearchResult<?>> visitor) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void filterCurrentResults(List<SearchResult> currentSearchResults2) {
|
||||
// Filter current results based on name filters from
|
||||
this.currentSearchResults = currentSearchResults;
|
||||
// use
|
||||
// filterOneResult(null);
|
||||
}
|
||||
|
||||
private boolean filterOneResult(SearchResult object) {
|
||||
// TODO Auto-generated method stub
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private void sortCurrentSearchResults() {
|
||||
// sort SearchResult by 1. searchDistance 2. Name
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package net.osmand.search.example.core;
|
||||
|
||||
public enum ObjectType {
|
||||
CITY, VILLAGE, POSTCODE, STREET, HOUSE, POI_TYPE, POI, LOCATION, NAME_FILTER
|
||||
}
|
172
OsmAnd-java/src/net/osmand/search/example/core/SearchCore.java
Normal file
172
OsmAnd-java/src/net/osmand/search/example/core/SearchCore.java
Normal file
|
@ -0,0 +1,172 @@
|
|||
package net.osmand.search.example.core;
|
||||
|
||||
import gnu.trove.map.hash.TLongObjectHashMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.Location;
|
||||
import net.osmand.ResultMatcher;
|
||||
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.util.MapUtils;
|
||||
|
||||
|
||||
public class SearchCore {
|
||||
List<SearchCoreAPI> apis = new ArrayList<>();
|
||||
|
||||
public static abstract class SearchBaseAPI implements SearchCoreAPI {
|
||||
@Override
|
||||
public List<SearchResult> search(SearchPhrase phrase, int radiusLevel, SearchCallback callback,
|
||||
List<SearchResult> existingSearchResults) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public QuadRect getBBoxToSearch(int radiusInMeters, int radiusLevel, LatLon loc) {
|
||||
float calcRadios = radiusLevel * radiusInMeters;
|
||||
float coeff = (float) (calcRadios / MapUtils.getTileDistanceWidth(SearchRequest.ZOOM_TO_SEARCH_POI));
|
||||
double tx = MapUtils.getTileNumberX(SearchRequest.ZOOM_TO_SEARCH_POI, loc.getLongitude());
|
||||
double ty = MapUtils.getTileNumberY(SearchRequest.ZOOM_TO_SEARCH_POI, loc.getLatitude());
|
||||
double topLeftX = tx - coeff;
|
||||
double topLeftY = ty - coeff;
|
||||
double bottomRightX = tx + coeff;
|
||||
double bottomRightY = ty + coeff;
|
||||
return new QuadRect(topLeftX, bottomRightY, bottomRightX, topLeftY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSearchPriority(SearchPhrase p) {
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SearchAmenityByNameAPI extends SearchBaseAPI {
|
||||
|
||||
}
|
||||
|
||||
public static class SearchAmenityByTypeAPI extends SearchBaseAPI {
|
||||
public boolean isLastWordPoi(SearchPhrase p ) {
|
||||
return p.isLastWord(ObjectType.POI_TYPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SearchResult> search(SearchPhrase phrase, int radiusLevel, SearchCallback callback,
|
||||
List<SearchResult> existingSearchResults) {
|
||||
if(isLastWordPoi(phrase)) {
|
||||
QuadRect bbox = getBBoxToSearch(10000, radiusLevel, phrase.getLastTokenLocation());
|
||||
// TODO NO LIMIT , BBOX - result priority 5, distPriority 1
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSearchPriority(SearchPhrase p) {
|
||||
if(isLastWordPoi(p)) {
|
||||
return 1;
|
||||
}
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SearchAddressByNameAPI extends SearchBaseAPI {
|
||||
|
||||
public boolean isLastWordPoi(SearchPhrase p ) {
|
||||
return p.isLastWord(ObjectType.POI);
|
||||
}
|
||||
|
||||
public boolean isNoSelectedType(SearchPhrase p ) {
|
||||
return p.isNoSelectedType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SearchResult> search(SearchPhrase phrase, int radiusLevel, SearchCallback callback,
|
||||
List<SearchResult> existingSearchResults) {
|
||||
if((isLastWordPoi(phrase) || isNoSelectedType(phrase)) && !(phrase.isEmpty())) {
|
||||
int typedLettersInStreet = 1;
|
||||
QuadRect bbox = getBBoxToSearch(30000 * typedLettersInStreet, radiusLevel, phrase.getLastTokenLocation());
|
||||
int priority = isNoSelectedType(phrase) ? 1 : 3;
|
||||
// priority
|
||||
// TODO LIMIT 100 * radiusLevel, BBOX - result priority 5, distPriority ${priority}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSearchPriority(SearchPhrase p) {
|
||||
if(isNoSelectedType(p)) {
|
||||
return 5;
|
||||
}
|
||||
if(isLastWordPoi(p)) {
|
||||
return 8;
|
||||
}
|
||||
return 10;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class SearchStreetByCityAPI extends SearchBaseAPI {
|
||||
@Override
|
||||
public List<SearchResult> search(SearchPhrase phrase, int radiusLevel, SearchCallback callback,
|
||||
List<SearchResult> existingSearchResults) {
|
||||
if(isLastWordCityGroup(phrase)) {
|
||||
// search all streets
|
||||
// TODO LIMIT 100 * radiusLevel - priority 1, distPriority 0 (alphabetic)
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public boolean isLastWordCityGroup(SearchPhrase p ) {
|
||||
return p.isLastWord(ObjectType.CITY) || p.isLastWord(ObjectType.POSTCODE) ||
|
||||
p.isLastWord(ObjectType.VILLAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSearchPriority(SearchPhrase p) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class SearchBuildingAndIntersectionsByStreetAPI extends SearchBaseAPI {
|
||||
|
||||
@Override
|
||||
public List<SearchResult> search(SearchPhrase phrase, int radiusLevel, SearchCallback callback,
|
||||
List<SearchResult> existingSearchResults) {
|
||||
if(isLastWordStreet(phrase)) {
|
||||
// search all buildings
|
||||
// TODO NO LIMIT - priority 1, distPriority 0 (alphabetic)
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public boolean isLastWordStreet(SearchPhrase p ) {
|
||||
return p.isLastWord(ObjectType.STREET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSearchPriority(SearchPhrase p) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void init() {
|
||||
apis.add(new SearchAmenityByNameAPI());
|
||||
apis.add(new SearchAmenityByTypeAPI());
|
||||
apis.add(new SearchAddressByNameAPI());
|
||||
apis.add(new SearchStreetByCityAPI());
|
||||
apis.add(new SearchBuildingAndIntersectionsByStreetAPI());
|
||||
}
|
||||
|
||||
private void callToSearchCoreAPI(
|
||||
SearchPhrase p,
|
||||
ResultMatcher<List<SearchResult<?>>> publisher,
|
||||
ResultMatcher<SearchResult<?>> visitor) {
|
||||
// sort apis by prioirity to search phrase
|
||||
// call apis in for loop
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package net.osmand.search.example.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SearchCoreAPI {
|
||||
|
||||
public int getSearchPriority(SearchPhrase p);
|
||||
|
||||
public interface SearchCallback {
|
||||
|
||||
public boolean accept(SearchResult r);
|
||||
}
|
||||
|
||||
public List<SearchResult> search(
|
||||
SearchPhrase phrase,
|
||||
int radiusLevel,
|
||||
SearchCallback callback,
|
||||
List<SearchResult> existingSearchResults);
|
||||
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package net.osmand.search.example.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.CollatorStringMatcher;
|
||||
import net.osmand.StringMatcher;
|
||||
import net.osmand.CollatorStringMatcher.StringMatcherMode;
|
||||
import net.osmand.data.LatLon;
|
||||
|
||||
public class SearchPhrase {
|
||||
|
||||
public static class SearchWord {
|
||||
public String word;
|
||||
public ObjectType type;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((type == null) ? 0 : type.hashCode());
|
||||
result = prime * result + ((word == null) ? 0 : word.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
SearchWord other = (SearchWord) obj;
|
||||
if (type != other.type)
|
||||
return false;
|
||||
if (word == null) {
|
||||
if (other.word != null)
|
||||
return false;
|
||||
} else if (!word.equals(other.word))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return word;
|
||||
}
|
||||
}
|
||||
|
||||
public List<SearchWord> words = new ArrayList<>();
|
||||
|
||||
public LatLon myLocationOrVisibleMap = new LatLon(0, 0);
|
||||
|
||||
public List<SearchWord> excludefilterWords() {
|
||||
List<SearchWord> w = new ArrayList<>();
|
||||
for(SearchWord s : words) {
|
||||
if(s.type != ObjectType.NAME_FILTER) {
|
||||
w.add(s);
|
||||
}
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
public boolean isLastWord(ObjectType p) {
|
||||
return true; // TODO
|
||||
}
|
||||
|
||||
public StringMatcher getNameStringMatcher() {
|
||||
return new CollatorStringMatcher("NameFitler", StringMatcherMode.CHECK_STARTS_FROM_SPACE);
|
||||
}
|
||||
|
||||
public boolean hasSameConstantWords(SearchPhrase p) {
|
||||
return excludefilterWords().equals(p.excludefilterWords());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String w = words.toString();
|
||||
return w.substring(1, w.length() - 1);
|
||||
}
|
||||
|
||||
public boolean isNoSelectedType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public LatLon getLastTokenLocation() {
|
||||
// last token or myLocationOrVisibleMap if not selected
|
||||
return myLocationOrVisibleMap;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package net.osmand.search.example.core;
|
||||
|
||||
import net.osmand.data.LatLon;
|
||||
|
||||
public class SearchResult<T> {
|
||||
|
||||
public T object;
|
||||
public ObjectType objectType;
|
||||
|
||||
// calculated by formula priority - 1 / (1 + priorityDistance * distance)
|
||||
public double searchDistance;
|
||||
|
||||
public LatLon location;
|
||||
public String mainName;
|
||||
// search phrase that makes search result valid
|
||||
public SearchPhrase requiredSearchPhrase;
|
||||
}
|
Loading…
Reference in a new issue