diff --git a/OsmAndCore-sample/res/values/styles.xml b/OsmAndCore-sample/res/values/styles.xml index bdae789d20..e165c50d21 100644 --- a/OsmAndCore-sample/res/values/styles.xml +++ b/OsmAndCore-sample/res/values/styles.xml @@ -28,9 +28,8 @@ @color/list_item_light @color/osmo_header_light @color/dashboard_subheader_text_light - - @color/dashboard_general_button_text_light - + @color/dashboard_general_button_text_light + @drawable/expandable_list_item_background_light @color/color_black @color/color_black @color/spinner_list_background_light diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/MainActivity.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/MainActivity.java index 497c83d838..1e51e47256 100644 --- a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/MainActivity.java +++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/MainActivity.java @@ -25,8 +25,8 @@ import android.view.View; import android.widget.ImageButton; import android.widget.TextView; +import net.osmand.binary.BinaryMapIndexReader; import net.osmand.core.android.AtlasMapRendererView; -import net.osmand.core.jni.Amenity; import net.osmand.core.jni.AmenitySymbolsProvider.AmenitySymbolsGroup; import net.osmand.core.jni.AreaI; import net.osmand.core.jni.IBillboardMapSymbol; @@ -59,14 +59,19 @@ import net.osmand.core.jni.Utilities; import net.osmand.core.samples.android.sample1.MultiTouchSupport.MultiTouchZoomListener; import net.osmand.core.samples.android.sample1.data.PointDescription; import net.osmand.core.samples.android.sample1.mapcontextmenu.MapContextMenu; -import net.osmand.core.samples.android.sample1.mapcontextmenu.MapMultiSelectionMenu; +import net.osmand.core.samples.android.sample1.mapcontextmenu.MenuController; import net.osmand.core.samples.android.sample1.search.QuickSearchDialogFragment; +import net.osmand.data.Amenity; import net.osmand.data.LatLon; +import net.osmand.data.QuadRect; import net.osmand.data.RotatedTileBox; +import net.osmand.osm.PoiCategory; import net.osmand.util.MapUtils; import java.io.File; import java.io.FilenameFilter; +import java.util.ArrayList; +import java.util.List; public class MainActivity extends AppCompatActivity { private static final String TAG = "OsmAndCoreSample"; @@ -98,7 +103,6 @@ public class MainActivity extends AppCompatActivity { private MultiTouchSupport multiTouchSupport; private MapContextMenu menu; - private MapMultiSelectionMenu multiMenu; // Context pin marker private MapMarkersCollection contextPinMarkersCollection; @@ -259,7 +263,6 @@ public class MainActivity extends AppCompatActivity { menu = new MapContextMenu(); menu.setMainActivity(this); - multiMenu = new MapMultiSelectionMenu(this); if (!InstallOsmandAppDialog.show(getSupportFragmentManager(), this) && externalStoragePermissionGranted) { @@ -377,8 +380,8 @@ public class MainActivity extends AppCompatActivity { public boolean showContextMenu(@NonNull LatLon latLon, @Nullable PointDescription pointDescription, @Nullable Object object) { - if (multiMenu.isVisible()) { - multiMenu.hide(); + if (menu.getMultiSelectionMenu().isVisible()) { + menu.getMultiSelectionMenu().hide(); } if (!getBox().containsLatLon(latLon)) { menu.setMapCenter(latLon); @@ -388,6 +391,16 @@ public class MainActivity extends AppCompatActivity { return true; } + private void showContextMenuForSelectedObjects(final LatLon latLon, final List selectedObjects) { + menu.getMultiSelectionMenu().show(latLon, selectedObjects); + } + + private void hideMultiContextMenu() { + if (menu.getMultiSelectionMenu().isVisible()) { + menu.getMultiSelectionMenu().hide(); + } + } + public RotatedTileBox getBox() { RotatedTileBox.RotatedTileBoxBuilder boxBuilder = new RotatedTileBox.RotatedTileBoxBuilder(); LatLon screenCenter = getScreenCenter(); @@ -501,6 +514,8 @@ public class MainActivity extends AppCompatActivity { AreaI area = new AreaI(new PointI(touchPoint.getX() - delta, touchPoint.getY() - delta), new PointI(touchPoint.getX() + delta, touchPoint.getY() + delta)); + List selectedObjects = new ArrayList<>(); + MapSymbolInformationList symbolInfos = mapView.getSymbolsIn(area, false); for (int i = 0; i < symbolInfos.size(); i++) { MapSymbolInformation symbolInfo = symbolInfos.get(i); @@ -529,57 +544,124 @@ public class MainActivity extends AppCompatActivity { } } - Log.e("111", i + ". lat=" + lat + " lon=" + lon); + String name = null; MapMarker mapMarker; try { SymbolsGroup markerSymbolsGroup = SymbolsGroup.dynamic_cast(symbolInfo.getMapSymbol().getGroupPtr()); mapMarker = markerSymbolsGroup.getMapMarker(); - Log.e("111", "marker=" + mapMarker.getMarkerId()); } catch (Exception eMapMarker) { mapMarker = null; } if (mapMarker != null && mapMarker.getMarkerId() == CONTEXT_MARKER_ID) { - // todo + hideMultiContextMenu(); + menu.show(); + return true; } else { - Amenity amenity; + net.osmand.core.jni.Amenity amenity; try { - AmenitySymbolsGroup amenitySymbolGroup = AmenitySymbolsGroup.dynamic_cast(symbolInfo.getMapSymbol().getGroupPtr()); + AmenitySymbolsGroup amenitySymbolGroup = + AmenitySymbolsGroup.dynamic_cast(symbolInfo.getMapSymbol().getGroupPtr()); amenity = amenitySymbolGroup.getAmenity(); } catch (Exception eAmenity) { amenity = null; } if (amenity != null) { - amenity.getId(); // todo - Log.e("111", "amenity=" + amenity.getNativeName()); + name = amenity.getNativeName(); + net.osmand.core.jni.LatLon aLatLon = Utilities.convert31ToLatLon(amenity.getPosition31()); + Amenity osmandAmenity = findAmenity(amenity.getId().getId().longValue() >> 7, + aLatLon.getLatitude(), aLatLon.getLongitude()); + if (osmandAmenity != null) { + if (!selectedObjects.contains(osmandAmenity)) { + selectedObjects.add(osmandAmenity); + } + continue; + } } else { MapObject mapObject; try { - MapObjectSymbolsGroup objSymbolGroup = MapObjectSymbolsGroup.dynamic_cast(symbolInfo.getMapSymbol().getGroupPtr()); + MapObjectSymbolsGroup objSymbolGroup = + MapObjectSymbolsGroup.dynamic_cast(symbolInfo.getMapSymbol().getGroupPtr()); mapObject = objSymbolGroup.getMapObject(); } catch (Exception eMapObject) { mapObject = null; } ObfMapObject obfMapObject; if (mapObject != null) { - Log.e("111", "mapObject=" + mapObject.getCaptionInNativeLanguage()); + name = mapObject.getCaptionInNativeLanguage(); try { obfMapObject = ObfMapObject.dynamic_pointer_cast(mapObject); } catch (Exception eObfMapObject) { obfMapObject = null; } if (obfMapObject != null) { - Log.e("111", "obfMapObject=" + obfMapObject.getId().getOsmId()); - obfMapObject.getId(); // todo + name = obfMapObject.getCaptionInNativeLanguage(); + Amenity osmandAmenity = findAmenity( + obfMapObject.getId().getId().longValue() >> 7, lat, lon); + if (osmandAmenity != null) { + if (!selectedObjects.contains(osmandAmenity)) { + selectedObjects.add(osmandAmenity); + } + continue; + } } } } + if (name != null && name.trim().length() > 0) { + selectedObjects.add(new PointDescription("", name)); + } else { + selectedObjects.add(new PointDescription(lat, lon)); + } } } } + if (selectedObjects.size() == 1) { + Object selectedObj = selectedObjects.get(0); + LatLon latLon = new LatLon(lat, lon); //MenuController.getObjectLocation(selectedObj); + PointDescription pointDescription = MenuController.getObjectName(selectedObj); + //if (latLon == null) { + // latLon = new LatLon(lat, lon); + //} + showContextMenu(latLon, pointDescription, selectedObj); + return true; + + } else if (selectedObjects.size() > 1) { + showContextMenuForSelectedObjects(new LatLon(lat, lon), selectedObjects); + return true; + } + + hideMultiContextMenu(); + hideContextMenu(); + return true; } + private Amenity findAmenity(long id, double lat, double lon) { + QuadRect rect = MapUtils.calculateLatLonBbox(lat, lon, 50); + List amenities = getMyApplication().getResourceManager().searchAmenities( + new BinaryMapIndexReader.SearchPoiTypeFilter() { + @Override + public boolean accept(PoiCategory type, String subcategory) { + return true; + } + + @Override + public boolean isEmpty() { + return false; + } + }, rect.top, rect.left, rect.bottom, rect.right, -1, null); + + Amenity res = null; + for (Amenity amenity : amenities) { + Long amenityId = amenity.getId() >> 1; + if (amenityId == id) { + res = amenity; + break; + } + } + return res; + } + @Override public void onLongPress(MotionEvent e) { if (!multiTouchSupport.isInMultiTouch()) { diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleApplication.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleApplication.java index 88f5e371cb..371d92aa2a 100644 --- a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleApplication.java +++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleApplication.java @@ -17,6 +17,7 @@ import net.osmand.core.jni.LogSeverityLevel; import net.osmand.core.jni.Logger; import net.osmand.core.samples.android.sample1.SampleFormatter.MetricsConstants; import net.osmand.core.samples.android.sample1.SampleFormatter.SpeedConstants; +import net.osmand.core.samples.android.sample1.resources.ResourceManager; import net.osmand.core.samples.android.sample1.search.QuickSearchHelper; import net.osmand.map.OsmandRegions; import net.osmand.map.WorldRegion; @@ -48,6 +49,7 @@ public class SampleApplication extends Application { private QuickSearchHelper searchUICore; private GeocodingLookupService geocodingLookupService; private OsmandRegions regions; + private ResourceManager resourceManager; public static String LANGUAGE; public static boolean TRANSLITERATE = false; @@ -67,6 +69,7 @@ public class SampleApplication extends Application { locationProvider = new SampleLocationProvider(this); searchUICore = new QuickSearchHelper(this); geocodingLookupService = new GeocodingLookupService(this); + resourceManager = new ResourceManager(this); regions = new OsmandRegions(); updateRegionVars(); indexRegionsBoundaries(); @@ -136,6 +139,10 @@ public class SampleApplication extends Application { } } + public ResourceManager getResourceManager() { + return resourceManager; + } + public OsmandRegions getRegions() { return regions; } diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/resources/AmenityIndexRepository.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/resources/AmenityIndexRepository.java new file mode 100644 index 0000000000..4945276d06 --- /dev/null +++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/resources/AmenityIndexRepository.java @@ -0,0 +1,28 @@ +package net.osmand.core.samples.android.sample1.resources; + +import net.osmand.Location; +import net.osmand.ResultMatcher; +import net.osmand.binary.BinaryMapIndexReader.SearchPoiTypeFilter; +import net.osmand.data.Amenity; + +import java.util.List; + +public interface AmenityIndexRepository { + + public void close(); + + public boolean checkContains(double latitude, double longitude); + + public boolean checkContainsInt(int top31, int left31, int bottom31, int right31); + + /** + * Search amenities in the specified box doesn't cache results + */ + List searchAmenities(int stop, int sleft, int sbottom, int sright, int zoom, SearchPoiTypeFilter filter, + ResultMatcher matcher); + + List searchAmenitiesOnThePath(List locations, double radius, SearchPoiTypeFilter filter, + ResultMatcher matcher); + + +} diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/resources/AmenityIndexRepositoryBinary.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/resources/AmenityIndexRepositoryBinary.java new file mode 100644 index 0000000000..a2daf3bc11 --- /dev/null +++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/resources/AmenityIndexRepositoryBinary.java @@ -0,0 +1,123 @@ +package net.osmand.core.samples.android.sample1.resources; + + +import net.osmand.Location; +import net.osmand.PlatformUtil; +import net.osmand.ResultMatcher; +import net.osmand.binary.BinaryMapIndexReader; +import net.osmand.binary.BinaryMapIndexReader.MapIndex; +import net.osmand.binary.BinaryMapIndexReader.SearchPoiTypeFilter; +import net.osmand.binary.BinaryMapIndexReader.SearchRequest; +import net.osmand.data.Amenity; +import net.osmand.osm.PoiCategory; +import net.osmand.util.MapUtils; + +import org.apache.commons.logging.Log; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class AmenityIndexRepositoryBinary implements AmenityIndexRepository { + + private final static Log log = PlatformUtil.getLog(AmenityIndexRepositoryBinary.class); + private final BinaryMapIndexReader index; + + public AmenityIndexRepositoryBinary(BinaryMapIndexReader index) { + this.index = index; + } + + @Override + public void close() { + try { + index.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public boolean checkContains(double latitude, double longitude) { + int x31 = MapUtils.get31TileNumberX(longitude); + int y31 = MapUtils.get31TileNumberY(latitude); + return index.containsPoiData(x31, y31, x31, y31); + } + + @Override + public boolean checkContainsInt(int top31, int left31, int bottom31, int right31) { + return index.containsPoiData(left31, top31, right31, bottom31); + } + + + public synchronized Map> searchAmenityCategoriesByName(String query, Map> map) { + try { + return index.searchPoiCategoriesByName(query, map); + } catch (IOException e) { + log.error("Error searching amenities", e); //$NON-NLS-1$ + } + return map; + } + + + public synchronized List searchAmenitiesByName(int x, int y, int l, int t, int r, int b, String query, ResultMatcher resulMatcher) { + long now = System.currentTimeMillis(); + List amenities = Collections.emptyList(); + SearchRequest req = BinaryMapIndexReader.buildSearchPoiRequest(x, y, query, l, r, t, b,resulMatcher); + try { + amenities = index.searchPoiByName(req); + if (log.isDebugEnabled()) { + String nm = ""; + List mi = index.getMapIndexes(); + if(mi.size() > 0) { + nm = mi.get(0).getName(); + } + log.debug(String.format("Search for %s done in %s ms found %s (%s) %s.", //$NON-NLS-1$ + query, System.currentTimeMillis() - now, amenities.size(), nm, index.getFile().getName())); //$NON-NLS-1$ + } + } catch (IOException e) { + log.error("Error searching amenities", e); //$NON-NLS-1$ + } + + return amenities; + } + + @Override + public synchronized List searchAmenities(int stop, int sleft, int sbottom, int sright, int zoom, + final SearchPoiTypeFilter filter, ResultMatcher matcher) { + long now = System.currentTimeMillis(); + SearchRequest req = BinaryMapIndexReader.buildSearchPoiRequest(sleft, sright, stop, sbottom, zoom, + filter, matcher); + List result = null; + try { + result = index.searchPoi(req); + } catch (IOException e) { + log.error("Error searching amenities", e); //$NON-NLS-1$ + } + if (log.isDebugEnabled() && result != null) { + log.debug(String.format("Search for %s done in %s ms found %s.", //$NON-NLS-1$ + MapUtils.get31LatitudeY(stop) + " " + MapUtils.get31LongitudeX(sleft), System.currentTimeMillis() - now, result.size())); //$NON-NLS-1$ + } + return result; + } + + @Override + public synchronized List searchAmenitiesOnThePath(List locations, double radius, final SearchPoiTypeFilter filter, ResultMatcher matcher) { + long now = System.currentTimeMillis(); + List result = null; + SearchRequest req = BinaryMapIndexReader.buildSearchPoiRequest(locations, radius, + filter, matcher ); + try { + result = index.searchPoi(req); + } catch (IOException e) { + log.error("Error searching amenities", e); //$NON-NLS-1$ + return result; + } + if (log.isDebugEnabled() && result != null) { + log.debug(String.format("Search done in %s ms found %s.", (System.currentTimeMillis() - now), result.size())); //$NON-NLS-1$ + } + return result; + + } + +} diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/resources/ResourceManager.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/resources/ResourceManager.java new file mode 100644 index 0000000000..5ef96b3dad --- /dev/null +++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/resources/ResourceManager.java @@ -0,0 +1,76 @@ +package net.osmand.core.samples.android.sample1.resources; + + +import net.osmand.IndexConstants; +import net.osmand.ResultMatcher; +import net.osmand.binary.BinaryMapIndexReader; +import net.osmand.core.samples.android.sample1.SampleApplication; +import net.osmand.core.samples.android.sample1.SampleUtils; +import net.osmand.data.Amenity; +import net.osmand.util.MapUtils; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class ResourceManager { + + private final SampleApplication app; + private final Map amenityRepositories = new ConcurrentHashMap<>(); + + public ResourceManager(SampleApplication app) { + this.app = app; + setRepositories(); + } + + private void setRepositories() { + ArrayList files = new ArrayList<>(); + File appPath = app.getAppPath(null); + SampleUtils.collectFiles(appPath, IndexConstants.BINARY_MAP_INDEX_EXT, files); + SampleUtils.collectFiles(app.getAppPath(IndexConstants.WIKI_INDEX_DIR), IndexConstants.BINARY_MAP_INDEX_EXT, files); + + for (File f : files) { + try { + RandomAccessFile mf = new RandomAccessFile(f.getPath(), "r"); + BinaryMapIndexReader reader = new BinaryMapIndexReader(mf, f); + if (reader.containsPoiData()) { + amenityRepositories.put(f.getName(), new AmenityIndexRepositoryBinary(reader)); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public List searchAmenities(BinaryMapIndexReader.SearchPoiTypeFilter filter, + double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, final ResultMatcher matcher) { + final List amenities = new ArrayList<>(); + try { + if (!filter.isEmpty()) { + int top31 = MapUtils.get31TileNumberY(topLatitude); + int left31 = MapUtils.get31TileNumberX(leftLongitude); + int bottom31 = MapUtils.get31TileNumberY(bottomLatitude); + int right31 = MapUtils.get31TileNumberX(rightLongitude); + for (AmenityIndexRepository index : amenityRepositories.values()) { + if (matcher != null && matcher.isCancelled()) { + break; + } + if (index.checkContainsInt(top31, left31, bottom31, right31)) { + List r = index.searchAmenities(top31, + left31, bottom31, right31, zoom, filter, matcher); + if(r != null) { + amenities.addAll(r); + } + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return amenities; + } +}