diff --git a/OsmAnd/res/layout/mapillary_static_image_view.xml b/OsmAnd/res/layout/mapillary_static_image_view.xml new file mode 100644 index 0000000000..b6ab505797 --- /dev/null +++ b/OsmAnd/res/layout/mapillary_static_image_view.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/mapillary/MapillaryImage.java b/OsmAnd/src/net/osmand/plus/mapillary/MapillaryImage.java index a539f61ab9..a7bd1c4579 100644 --- a/OsmAnd/src/net/osmand/plus/mapillary/MapillaryImage.java +++ b/OsmAnd/src/net/osmand/plus/mapillary/MapillaryImage.java @@ -1,7 +1,5 @@ package net.osmand.plus.mapillary; -import net.osmand.util.Algorithms; - import java.util.Map; public class MapillaryImage { @@ -41,10 +39,10 @@ public class MapillaryImage { public boolean setData(Map userData) { boolean res = true; try { - this.ca = (Double) userData.get("ca"); - this.capturedAt = (Long) userData.get("captured_at"); + this.ca = ((Number) userData.get("ca")).doubleValue(); + this.capturedAt = ((Number) userData.get("captured_at")).longValue(); this.key = (String) userData.get("key"); - this.pano = ((Long) userData.get("pano")) == 1; + this.pano = ((Number) userData.get("pano")).intValue() == 1; this.sKey = (String) userData.get("skey"); this.userKey = (String) userData.get("userkey"); @@ -78,7 +76,7 @@ public class MapillaryImage { return pano; } - public String getsKey() { + public String getSKey() { return sKey; } diff --git a/OsmAnd/src/net/osmand/plus/mapillary/MapillaryImageCard.java b/OsmAnd/src/net/osmand/plus/mapillary/MapillaryImageCard.java index 31cfef3536..b490d5f11a 100644 --- a/OsmAnd/src/net/osmand/plus/mapillary/MapillaryImageCard.java +++ b/OsmAnd/src/net/osmand/plus/mapillary/MapillaryImageCard.java @@ -8,6 +8,7 @@ import net.osmand.plus.activities.MapActivity; import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard; import net.osmand.util.Algorithms; +import org.json.JSONException; import org.json.JSONObject; public class MapillaryImageCard extends ImageCard { diff --git a/OsmAnd/src/net/osmand/plus/mapillary/MapillaryImageDialog.java b/OsmAnd/src/net/osmand/plus/mapillary/MapillaryImageDialog.java index 8024080f29..4f0658283d 100644 --- a/OsmAnd/src/net/osmand/plus/mapillary/MapillaryImageDialog.java +++ b/OsmAnd/src/net/osmand/plus/mapillary/MapillaryImageDialog.java @@ -7,7 +7,7 @@ import android.graphics.drawable.BitmapDrawable; import android.os.AsyncTask; import android.os.Bundle; import android.support.annotation.NonNull; -import android.view.Gravity; +import android.support.v4.util.Pair; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -16,24 +16,48 @@ import android.webkit.ConsoleMessage; import android.webkit.JavascriptInterface; import android.webkit.WebChromeClient; import android.webkit.WebView; +import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.Point; + import net.osmand.AndroidNetworkUtils; import net.osmand.AndroidUtils; +import net.osmand.data.GeometryTile; import net.osmand.data.LatLon; +import net.osmand.data.QuadPointDouble; +import net.osmand.data.QuadRect; +import net.osmand.data.RotatedTileBox; +import net.osmand.map.ITileSource; +import net.osmand.map.TileSourceManager; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.mapcontextmenu.MenuBuilder; import net.osmand.plus.mapcontextmenu.builders.cards.dialogs.ContextMenuCardDialog; import net.osmand.plus.mapcontextmenu.builders.cards.dialogs.ContextMenuCardDialogFragment; +import net.osmand.plus.resources.ResourceManager; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.util.Algorithms; +import net.osmand.util.MapUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +import static net.osmand.plus.mapillary.MapillaryVectorLayer.EXTENT; +import static net.osmand.plus.mapillary.MapillaryVectorLayer.TILE_ZOOM; public class MapillaryImageDialog extends ContextMenuCardDialog { private static final String KEY_MAPILLARY_DIALOG_IMAGE_KEY = "key_mapillary_dialog_image_key"; + private static final String KEY_MAPILLARY_DIALOG_IMAGE_SKEY = "key_mapillary_dialog_image_skey"; private static final String KEY_MAPILLARY_DIALOG_IMAGE_URL = "key_mapillary_dialog_image_url"; private static final String KEY_MAPILLARY_DIALOG_VIEWER_URL = "key_mapillary_dialog_viewer_url"; private static final String KEY_MAPILLARY_DIALOG_LATLON = "key_mapillary_dialog_latlon"; @@ -47,22 +71,31 @@ public class MapillaryImageDialog extends ContextMenuCardDialog { private static final String WEBGL_ERROR_MESSAGE = "Error creating WebGL context"; private String key; + private String sKey; private String imageUrl; private String viewerUrl; private LatLon latLon; private double ca = Double.NaN; + private View staticImageView; + private List> tiles = new ArrayList<>(); + private double fetchedTileLat = Double.NaN; + private double fetchedTileLon = Double.NaN; + private List sequenceImages = new ArrayList<>(); + private AtomicInteger downloadRequestNumber = new AtomicInteger(); + public MapillaryImageDialog(@NonNull MapActivity mapActivity, @NonNull Bundle bundle) { super(mapActivity, CardDialogType.MAPILLARY); restoreFields(bundle); } - public MapillaryImageDialog(MapActivity mapActivity, String key, String imageUrl, String viewerUrl, LatLon latLon, double ca, - String title, String description) { + public MapillaryImageDialog(MapActivity mapActivity, String key, String sKey, String imageUrl, + String viewerUrl, LatLon latLon, double ca, String title, String description) { super(mapActivity, CardDialogType.MAPILLARY); this.title = title; this.description = description; this.key = key; + this.sKey = sKey; this.imageUrl = imageUrl; this.viewerUrl = viewerUrl; this.latLon = latLon; @@ -88,6 +121,7 @@ public class MapillaryImageDialog extends ContextMenuCardDialog { public void saveMenu(Bundle bundle) { super.saveMenu(bundle); bundle.putSerializable(KEY_MAPILLARY_DIALOG_IMAGE_KEY, key); + bundle.putSerializable(KEY_MAPILLARY_DIALOG_IMAGE_SKEY, sKey); bundle.putSerializable(KEY_MAPILLARY_DIALOG_IMAGE_URL, imageUrl); bundle.putSerializable(KEY_MAPILLARY_DIALOG_VIEWER_URL, viewerUrl); bundle.putSerializable(KEY_MAPILLARY_DIALOG_LATLON, latLon); @@ -98,6 +132,7 @@ public class MapillaryImageDialog extends ContextMenuCardDialog { protected void restoreFields(Bundle bundle) { super.restoreFields(bundle); this.key = bundle.getString(KEY_MAPILLARY_DIALOG_IMAGE_KEY); + this.sKey = bundle.getString(KEY_MAPILLARY_DIALOG_IMAGE_SKEY); this.imageUrl = bundle.getString(KEY_MAPILLARY_DIALOG_IMAGE_URL); this.viewerUrl = bundle.getString(KEY_MAPILLARY_DIALOG_VIEWER_URL); Object latLonObj = bundle.getSerializable(KEY_MAPILLARY_DIALOG_LATLON); @@ -218,46 +253,221 @@ public class MapillaryImageDialog extends ContextMenuCardDialog { } private View getStaticImageView() { - LinearLayout ll = new LinearLayout(getMapActivity()); - ll.setClickable(true); - LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( + View view = getMapActivity().getLayoutInflater().inflate(R.layout.mapillary_static_image_view, null); + view.setClickable(true); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( isPortrait() ? ViewGroup.LayoutParams.MATCH_PARENT : AndroidUtils.dpToPx(getMapActivity(), 360f), isPortrait() ? AndroidUtils.dpToPx(getMapActivity(), 270f) : ViewGroup.LayoutParams.MATCH_PARENT); - ll.setGravity(Gravity.CENTER); - ll.setLayoutParams(lp); + view.setLayoutParams(lp); - ProgressBar progressBar = new ProgressBar(getMapActivity()); - progressBar.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT)); - ll.addView(progressBar); + view.findViewById(R.id.leftArrowButton).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + clickLeftArrowButton(v); + } + }); + view.findViewById(R.id.rightArrowButton).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + clickRightArrowButton(v); + } + }); - ImageView imageView = new ImageView(getMapActivity()); - imageView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); - ll.addView(imageView); + staticImageView = view; if (!Algorithms.isEmpty(imageUrl)) { - MenuBuilder.execute(new DownloadImageTask(progressBar, imageView)); + MenuBuilder.execute(new DownloadImageTask(staticImageView, downloadRequestNumber.incrementAndGet(), downloadRequestNumber)); + fetchSequence(); } - return ll; + updateArrowButtons(); + return staticImageView; } + private void fetchSequence() { + if (Algorithms.isEmpty(sKey)) { + acquireSequenceKey(); + } + if (!Algorithms.isEmpty(sKey)) { + acquireSequenceImages(); + } + } + + private void acquireSequenceKey() { + fetchTiles(); + for (Pair pt : tiles) { + GeometryTile tile = pt.second; + for (Geometry g : tile.getData()) { + if (g instanceof Point && !g.isEmpty() && g.getUserData() != null && g.getUserData() instanceof HashMap) { + HashMap userData = (HashMap) g.getUserData(); + String key = (String) userData.get("key"); + if (this.key.equals(key)) { + sKey = (String) userData.get("skey"); + return; + } + } + } + } + } + + private void acquireSequenceImages() { + fetchTiles(); + List sequenceImages = new ArrayList<>(); + if (!Algorithms.isEmpty(sKey)) { + double px, py; + for (Pair pt : tiles) { + QuadPointDouble point = pt.first; + GeometryTile tile = pt.second; + for (Geometry g : tile.getData()) { + if (g instanceof Point && !g.isEmpty() && g.getUserData() != null && g.getUserData() instanceof HashMap) { + HashMap userData = (HashMap) g.getUserData(); + String sKey = (String) userData.get("skey"); + if (this.sKey.equals(sKey)) { + Point p = (Point) g; + px = p.getCoordinate().x / EXTENT; + py = p.getCoordinate().y / EXTENT; + MapillaryImage image = new MapillaryImage( + MapUtils.getLatitudeFromTile(TILE_ZOOM, point.y + py), + MapUtils.getLongitudeFromTile(TILE_ZOOM, point.x + px)); + if (image.setData(userData)) { + sequenceImages.add(image); + } + } + } + } + } + } + Collections.sort(sequenceImages, new Comparator() { + @Override + public int compare(MapillaryImage img1, MapillaryImage img2) { + return img1.getCapturedAt() < img2.getCapturedAt() ? + -1 : (img1.getCapturedAt() == img2.getCapturedAt() ? 0 : 1); + } + }); + this.sequenceImages = sequenceImages; + } + + private void updateArrowButtons() { + if (staticImageView != null) { + boolean showLeftButton = false; + boolean showRightButton = false; + if (sequenceImages.size() > 1 && !Algorithms.isEmpty(key)) { + showLeftButton = !sequenceImages.get(0).getKey().equals(key); + showRightButton = !sequenceImages.get(sequenceImages.size() - 1).getKey().equals(key); + } + staticImageView.findViewById(R.id.leftArrowButton) + .setVisibility(showLeftButton ? View.VISIBLE : View.GONE); + staticImageView.findViewById(R.id.rightArrowButton) + .setVisibility(showRightButton ? View.VISIBLE : View.GONE); + } + } + + private int getImageIndex(String key) { + for (int i = 0; i < sequenceImages.size(); i++) { + if (sequenceImages.get(i).getKey().equals(key)) { + return i; + } + } + return -1; + } + + private void clickLeftArrowButton(View v) { + fetchSequence(); + if (sequenceImages != null) { + int index = getImageIndex(key); + if (index != -1 && index > 0) { + setImage(sequenceImages.get(index - 1)); + } + } + updateArrowButtons(); + } + + private void clickRightArrowButton(View v) { + fetchSequence(); + if (sequenceImages != null) { + int index = getImageIndex(key); + if (index != -1 && index < sequenceImages.size() - 1) { + setImage(sequenceImages.get(index + 1)); + } + } + updateArrowButtons(); + } + + private void setImage(MapillaryImage image) { + this.latLon = new LatLon(image.getLatitude(), image.getLongitude()); + this.ca = image.getCa(); + this.key = image.getKey(); + this.imageUrl = MAPILLARY_HIRES_IMAGE_URL_TEMPLATE + image.getKey(); + this.viewerUrl = MAPILLARY_VIEWER_URL_TEMPLATE + image.getKey(); + MenuBuilder.execute(new DownloadImageTask(staticImageView, downloadRequestNumber.incrementAndGet(), downloadRequestNumber)); + setImageLocation(latLon, ca, false); + } + + public void fetchTiles() { + RotatedTileBox tileBox = getMapActivity().getMapView().getCurrentRotatedTileBox().copy(); + if (fetchedTileLat == tileBox.getLatitude() && fetchedTileLon == tileBox.getLongitude()) { + return; + } + ITileSource map = TileSourceManager.getMapillaryVectorSource(); + int nzoom = tileBox.getZoom(); + if (nzoom < map.getMinimumZoomSupported()) { + return; + } + ResourceManager mgr = getMapActivity().getMyApplication().getResourceManager(); + final QuadRect tilesRect = tileBox.getTileBounds(); + + // recalculate for ellipsoid coordinates + float ellipticTileCorrection = 0; + if (map.isEllipticYTile()) { + ellipticTileCorrection = (float) (MapUtils.getTileEllipsoidNumberY(nzoom, tileBox.getLatitude()) - tileBox.getCenterTileY()); + } + + int left = (int) Math.floor(tilesRect.left); + int top = (int) Math.floor(tilesRect.top + ellipticTileCorrection); + int width = (int) Math.ceil(tilesRect.right - left); + int height = (int) Math.ceil(tilesRect.bottom + ellipticTileCorrection - top); + int dzoom = nzoom - TILE_ZOOM; + int div = (int) Math.pow(2.0, dzoom); + + Map> tiles = new HashMap<>(); + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + int tileX = (left + i) / div; + int tileY = (top + j) / div; + String tileId = mgr.calculateTileId(map, tileX, tileY, TILE_ZOOM); + Pair p = tiles.get(tileId); + if (p == null) { + GeometryTile tile = null; + // asking tile image async + boolean imgExist = mgr.tileExistOnFileSystem(tileId, map, tileX, tileY, TILE_ZOOM); + if (imgExist) { + tile = mgr.getGeometryTilesCache().getTileForMapAsync(tileId, map, tileX, tileY, TILE_ZOOM, false); + } + if (tile != null) { + tiles.put(tileId, new Pair<>(new QuadPointDouble(tileX, tileY), tile)); + } + } + } + } + fetchedTileLat = tileBox.getLatitude(); + fetchedTileLon = tileBox.getLongitude(); + this.tiles = new ArrayList<>(tiles.values()); + } public static MapillaryImageDialog show(MapActivity mapActivity, String key, String imageUrl, String viewerUrl, LatLon latLon, double ca, String title, String description) { - MapillaryImageDialog dialog = new MapillaryImageDialog(mapActivity, key, imageUrl, viewerUrl, - latLon, ca, title, description); + MapillaryImageDialog dialog = new MapillaryImageDialog(mapActivity, key, null, imageUrl, + viewerUrl, latLon, ca, title, description); ContextMenuCardDialogFragment.showInstance(dialog); return dialog; } public static MapillaryImageDialog show(MapActivity mapActivity, double latitude, double longitude, - String key, double ca, String title, String description) { + String key, String sKey, double ca, String title, String description) { String imageUrl = MAPILLARY_HIRES_IMAGE_URL_TEMPLATE + key; String viewerUrl = MAPILLARY_VIEWER_URL_TEMPLATE + key; LatLon latLon = new LatLon(latitude, longitude); - MapillaryImageDialog dialog = new MapillaryImageDialog(mapActivity, key, imageUrl, viewerUrl, + MapillaryImageDialog dialog = new MapillaryImageDialog(mapActivity, key, sKey, imageUrl, viewerUrl, latLon, ca, title, description); ContextMenuCardDialogFragment.showInstance(dialog); return dialog; @@ -265,30 +475,57 @@ public class MapillaryImageDialog extends ContextMenuCardDialog { private class DownloadImageTask extends AsyncTask { + private int request; + private AtomicInteger downloadRequestNumber; private ProgressBar progressBar; private ImageView imageView; - public DownloadImageTask(ProgressBar progressBar, ImageView imageView) { - this.progressBar = progressBar; - this.imageView = imageView; + public DownloadImageTask(View staticImageView, int request, AtomicInteger downloadRequestNumber) { + if (staticImageView != null) { + this.request = request; + this.downloadRequestNumber = downloadRequestNumber; + ProgressBar progressBar = (ProgressBar) staticImageView.findViewById(R.id.progressBar); + ImageView imageView = (ImageView) staticImageView.findViewById(R.id.imageView); + this.progressBar = progressBar; + this.imageView = imageView; + } } @Override protected void onPreExecute() { - progressBar.setVisibility(View.VISIBLE); + if (progressBar != null) { + progressBar.setVisibility(View.VISIBLE); + } } @Override protected Bitmap doInBackground(Void... params) { - return AndroidNetworkUtils.downloadImage(getMapActivity().getMyApplication(), imageUrl); + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // ignore + } + if (isValidRequest()) { + return AndroidNetworkUtils.downloadImage(getMapActivity().getMyApplication(), imageUrl); + } else { + return null; + } } @Override protected void onPostExecute(Bitmap bitmap) { - progressBar.setVisibility(View.GONE); - if (bitmap != null) { - imageView.setImageDrawable(new BitmapDrawable(getMapActivity().getResources(), bitmap)); + if (isValidRequest()) { + if (progressBar != null) { + progressBar.setVisibility(View.GONE); + } + if (bitmap != null && imageView != null) { + imageView.setImageDrawable(new BitmapDrawable(getMapActivity().getResources(), bitmap)); + } } } + + private boolean isValidRequest() { + return request == downloadRequestNumber.get(); + } } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/mapillary/MapillaryMenuController.java b/OsmAnd/src/net/osmand/plus/mapillary/MapillaryMenuController.java index 8c1d224846..9e5e919bf4 100644 --- a/OsmAnd/src/net/osmand/plus/mapillary/MapillaryMenuController.java +++ b/OsmAnd/src/net/osmand/plus/mapillary/MapillaryMenuController.java @@ -29,7 +29,7 @@ public class MapillaryMenuController extends MenuController { public boolean setActive(boolean active) { if (image != null && getMenuType() == MenuType.STANDARD) { MapillaryImageDialog.show(getMapActivity(), image.getLatitude(), image.getLongitude(), - image.getKey(), image.getCa(), getMapActivity().getMyApplication().getString(R.string.mapillary), null); + image.getKey(), image.getSKey(), image.getCa(), getMapActivity().getMyApplication().getString(R.string.mapillary), null); return false; } else { return super.setActive(active); diff --git a/OsmAnd/src/net/osmand/plus/mapillary/MapillaryVectorLayer.java b/OsmAnd/src/net/osmand/plus/mapillary/MapillaryVectorLayer.java index 6fcae266c2..7dda81194a 100644 --- a/OsmAnd/src/net/osmand/plus/mapillary/MapillaryVectorLayer.java +++ b/OsmAnd/src/net/osmand/plus/mapillary/MapillaryVectorLayer.java @@ -28,10 +28,8 @@ import net.osmand.plus.resources.ResourceManager; import net.osmand.plus.views.ContextMenuLayer.IContextMenuProvider; import net.osmand.plus.views.MapTileLayer; import net.osmand.plus.views.OsmandMapTileView; -import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -39,8 +37,8 @@ import java.util.Map.Entry; class MapillaryVectorLayer extends MapTileLayer implements MapillaryLayer, IContextMenuProvider { - private static final int TILE_ZOOM = 14; - private static final double EXTENT = 4096.0; + public static final int TILE_ZOOM = 14; + public static final double EXTENT = 4096.0; private LatLon selectedImageLocation; private Float selectedImageCameraAngle; @@ -70,7 +68,7 @@ class MapillaryVectorLayer extends MapTileLayer implements MapillaryLayer, ICont selectedImage = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_mapillary_location); headingImage = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_mapillary_location_view_angle); - point = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_note_small); + point = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_mapillary_photo_dot); } @Override @@ -123,6 +121,8 @@ class MapillaryVectorLayer extends MapTileLayer implements MapillaryLayer, ICont int top = (int) Math.floor(tilesRect.top + ellipticTileCorrection); int width = (int) Math.ceil(tilesRect.right - left); int height = (int) Math.ceil(tilesRect.bottom + ellipticTileCorrection - top); + int dzoom = nzoom - TILE_ZOOM; + int div = (int) Math.pow(2.0, dzoom); boolean useInternet = (OsmandPlugin.getEnabledPlugin(OsmandRasterMapsPlugin.class) != null || OsmandPlugin.getEnabledPlugin(MapillaryPlugin.class) != null) && settings.USE_INTERNET_TO_DOWNLOAD_TILES.get() && settings.isInternetConnectionAvailable() && map.couldBeDownloadedFromInternet(); @@ -131,23 +131,9 @@ class MapillaryVectorLayer extends MapTileLayer implements MapillaryLayer, ICont Map visiblePoints = new HashMap<>(); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { - int leftPlusI = left + i; - int topPlusJ = top + j; + int tileX = (left + i) / div; + int tileY = (top + j) / div; - int x1 = tileBox.getPixXFromTileXNoRot(leftPlusI); - int x2 = tileBox.getPixXFromTileXNoRot(leftPlusI + 1); - - int y1 = tileBox.getPixYFromTileYNoRot(topPlusJ - ellipticTileCorrection); - int y2 = tileBox.getPixYFromTileYNoRot(topPlusJ + 1 - ellipticTileCorrection); - bitmapToDraw.set(x1, y1, x2, y2); - - int tileX = leftPlusI; - int tileY = topPlusJ; - - int dzoom = nzoom - TILE_ZOOM; - int div = (int) Math.pow(2.0, dzoom); - tileX /= div; - tileY /= div; String tileId = mgr.calculateTileId(map, tileX, tileY, TILE_ZOOM); GeometryTile tile = tiles.get(tileId); if (tile == null) { @@ -173,22 +159,6 @@ class MapillaryVectorLayer extends MapTileLayer implements MapillaryLayer, ICont protected void drawPoints(Canvas canvas, RotatedTileBox tileBox, int tileX, int tileY, GeometryTile tile, Map visiblePoints) { - Map> seqMap = new HashMap<>(); - for (Geometry g : tile.getData()) { - if (g instanceof Point && !g.isEmpty() && g.getUserData() != null && g.getUserData() instanceof HashMap) { - HashMap userData = (HashMap) g.getUserData(); - String seq = (String) userData.get("skey"); - if (!Algorithms.isEmpty(seq)) { - List pointList = seqMap.get(seq); - if (pointList == null) { - pointList = new ArrayList<>(); - seqMap.put(seq, pointList); - } - pointList.add((Point) g); - } - } - } - int dzoom = tileBox.getZoom() - TILE_ZOOM; int mult = (int) Math.pow(2.0, dzoom); QuadRect tileBounds = tileBox.getTileBounds(); @@ -198,14 +168,11 @@ class MapillaryVectorLayer extends MapTileLayer implements MapillaryLayer, ICont float ph = point.getHeight(); float pwd = pw / 2; float phd = ph / 2; - //float lx = -1000f; - //float ly = -1000f; - //float pwm = pw * 2; - //float phm = ph * 2; canvas.rotate(-tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY()); - for (List points : seqMap.values()) { - for (int i = 0; i < points.size(); i++) { - Point p = points.get(i); + + for (Geometry g : tile.getData()) { + if (g instanceof Point && !g.isEmpty() && g.getUserData() != null && g.getUserData() instanceof HashMap) { + Point p = (Point) g; px = p.getCoordinate().x / EXTENT; py = p.getCoordinate().y / EXTENT; tx = (tileX + px) * mult; @@ -213,14 +180,8 @@ class MapillaryVectorLayer extends MapTileLayer implements MapillaryLayer, ICont if (tileBounds.contains(tx, ty, tx, ty)) { x = tileBox.getPixXFromTile(tileX + px, tileY + py, TILE_ZOOM); y = tileBox.getPixYFromTile(tileX + px, tileY + py, TILE_ZOOM); - //QuadRect rNow = calculateRect(x, y, pwm, phm); - //QuadRect rLast = calculateRect(lx, ly, pw, ph); - //if (!QuadRect.intersects(rLast, rNow) || i == points.size() - 1) { - canvas.drawBitmap(point, x - pwd, y - phd, paintPoint); - visiblePoints.put(new QuadPointDouble(tileX + px, tileY + py), (Map) p.getUserData()); - //lx = x; - //ly = y; - //} + canvas.drawBitmap(point, x - pwd, y - phd, paintPoint); + visiblePoints.put(new QuadPointDouble(tileX + px, tileY + py), (Map) p.getUserData()); } } } @@ -342,22 +303,32 @@ class MapillaryVectorLayer extends MapTileLayer implements MapillaryLayer, ICont private void getImagesFromPoint(RotatedTileBox tb, PointF point, List images) { Map points = this.visiblePoints; if (points != null) { - int ex = (int) point.x; - int ey = (int) point.y; + float ex = point.x; + float ey = point.y; final int rp = getRadius(tb); int radius = rp * 3 / 2; float x, y; + double minSqDist = Double.NaN; + double sqDist; + MapillaryImage img = null; for (Entry entry : points.entrySet()) { x = tb.getPixXFromTile(entry.getKey().x, entry.getKey().y, TILE_ZOOM); y = tb.getPixYFromTile(entry.getKey().x, entry.getKey().y, TILE_ZOOM); if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) { - MapillaryImage img = new MapillaryImage(MapUtils.getLatitudeFromTile(TILE_ZOOM, entry.getKey().y), - MapUtils.getLongitudeFromTile(TILE_ZOOM, entry.getKey().x)); - if (img.setData(entry.getValue())) { - images.add(img); + sqDist = (x - ex) * (x - ex) + (y - ey) * (y - ey); + if (img == null || minSqDist > sqDist) { + minSqDist = sqDist; + img = new MapillaryImage(MapUtils.getLatitudeFromTile(TILE_ZOOM, entry.getKey().y), + MapUtils.getLongitudeFromTile(TILE_ZOOM, entry.getKey().x)); + if (!img.setData(entry.getValue())) { + img = null; + } } } } + if (img != null) { + images.add(img); + } } }