Added mapillary sequence browser for non webgl view

This commit is contained in:
Alexey Kulish 2017-05-20 14:12:12 +03:00
parent 42e15d2670
commit d2d967a40a
6 changed files with 349 additions and 95 deletions

View file

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"/>
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:background="@android:color/transparent">
<ImageButton
android:id="@+id/leftArrowButton"
android:layout_width="44dp"
android:layout_height="44dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_arrow_back"/>
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<ImageButton
android:id="@+id/rightArrowButton"
android:layout_width="44dp"
android:layout_height="44dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_arrow_forward"/>
</LinearLayout>
</FrameLayout>

View file

@ -1,7 +1,5 @@
package net.osmand.plus.mapillary; package net.osmand.plus.mapillary;
import net.osmand.util.Algorithms;
import java.util.Map; import java.util.Map;
public class MapillaryImage { public class MapillaryImage {
@ -41,10 +39,10 @@ public class MapillaryImage {
public boolean setData(Map userData) { public boolean setData(Map userData) {
boolean res = true; boolean res = true;
try { try {
this.ca = (Double) userData.get("ca"); this.ca = ((Number) userData.get("ca")).doubleValue();
this.capturedAt = (Long) userData.get("captured_at"); this.capturedAt = ((Number) userData.get("captured_at")).longValue();
this.key = (String) userData.get("key"); 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.sKey = (String) userData.get("skey");
this.userKey = (String) userData.get("userkey"); this.userKey = (String) userData.get("userkey");
@ -78,7 +76,7 @@ public class MapillaryImage {
return pano; return pano;
} }
public String getsKey() { public String getSKey() {
return sKey; return sKey;
} }

View file

@ -8,6 +8,7 @@ import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard; import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
public class MapillaryImageCard extends ImageCard { public class MapillaryImageCard extends ImageCard {

View file

@ -7,7 +7,7 @@ import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.view.Gravity; import android.support.v4.util.Pair;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
@ -16,24 +16,48 @@ import android.webkit.ConsoleMessage;
import android.webkit.JavascriptInterface; import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient; import android.webkit.WebChromeClient;
import android.webkit.WebView; import android.webkit.WebView;
import android.widget.FrameLayout;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
import net.osmand.AndroidNetworkUtils; import net.osmand.AndroidNetworkUtils;
import net.osmand.AndroidUtils; import net.osmand.AndroidUtils;
import net.osmand.data.GeometryTile;
import net.osmand.data.LatLon; 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.R;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.MenuBuilder; import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapcontextmenu.builders.cards.dialogs.ContextMenuCardDialog; import net.osmand.plus.mapcontextmenu.builders.cards.dialogs.ContextMenuCardDialog;
import net.osmand.plus.mapcontextmenu.builders.cards.dialogs.ContextMenuCardDialogFragment; import net.osmand.plus.mapcontextmenu.builders.cards.dialogs.ContextMenuCardDialogFragment;
import net.osmand.plus.resources.ResourceManager;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.util.Algorithms; 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 { 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_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_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_VIEWER_URL = "key_mapillary_dialog_viewer_url";
private static final String KEY_MAPILLARY_DIALOG_LATLON = "key_mapillary_dialog_latlon"; 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 static final String WEBGL_ERROR_MESSAGE = "Error creating WebGL context";
private String key; private String key;
private String sKey;
private String imageUrl; private String imageUrl;
private String viewerUrl; private String viewerUrl;
private LatLon latLon; private LatLon latLon;
private double ca = Double.NaN; private double ca = Double.NaN;
private View staticImageView;
private List<Pair<QuadPointDouble, GeometryTile>> tiles = new ArrayList<>();
private double fetchedTileLat = Double.NaN;
private double fetchedTileLon = Double.NaN;
private List<MapillaryImage> sequenceImages = new ArrayList<>();
private AtomicInteger downloadRequestNumber = new AtomicInteger();
public MapillaryImageDialog(@NonNull MapActivity mapActivity, @NonNull Bundle bundle) { public MapillaryImageDialog(@NonNull MapActivity mapActivity, @NonNull Bundle bundle) {
super(mapActivity, CardDialogType.MAPILLARY); super(mapActivity, CardDialogType.MAPILLARY);
restoreFields(bundle); restoreFields(bundle);
} }
public MapillaryImageDialog(MapActivity mapActivity, String key, String imageUrl, String viewerUrl, LatLon latLon, double ca, public MapillaryImageDialog(MapActivity mapActivity, String key, String sKey, String imageUrl,
String title, String description) { String viewerUrl, LatLon latLon, double ca, String title, String description) {
super(mapActivity, CardDialogType.MAPILLARY); super(mapActivity, CardDialogType.MAPILLARY);
this.title = title; this.title = title;
this.description = description; this.description = description;
this.key = key; this.key = key;
this.sKey = sKey;
this.imageUrl = imageUrl; this.imageUrl = imageUrl;
this.viewerUrl = viewerUrl; this.viewerUrl = viewerUrl;
this.latLon = latLon; this.latLon = latLon;
@ -88,6 +121,7 @@ public class MapillaryImageDialog extends ContextMenuCardDialog {
public void saveMenu(Bundle bundle) { public void saveMenu(Bundle bundle) {
super.saveMenu(bundle); super.saveMenu(bundle);
bundle.putSerializable(KEY_MAPILLARY_DIALOG_IMAGE_KEY, key); 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_IMAGE_URL, imageUrl);
bundle.putSerializable(KEY_MAPILLARY_DIALOG_VIEWER_URL, viewerUrl); bundle.putSerializable(KEY_MAPILLARY_DIALOG_VIEWER_URL, viewerUrl);
bundle.putSerializable(KEY_MAPILLARY_DIALOG_LATLON, latLon); bundle.putSerializable(KEY_MAPILLARY_DIALOG_LATLON, latLon);
@ -98,6 +132,7 @@ public class MapillaryImageDialog extends ContextMenuCardDialog {
protected void restoreFields(Bundle bundle) { protected void restoreFields(Bundle bundle) {
super.restoreFields(bundle); super.restoreFields(bundle);
this.key = bundle.getString(KEY_MAPILLARY_DIALOG_IMAGE_KEY); 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.imageUrl = bundle.getString(KEY_MAPILLARY_DIALOG_IMAGE_URL);
this.viewerUrl = bundle.getString(KEY_MAPILLARY_DIALOG_VIEWER_URL); this.viewerUrl = bundle.getString(KEY_MAPILLARY_DIALOG_VIEWER_URL);
Object latLonObj = bundle.getSerializable(KEY_MAPILLARY_DIALOG_LATLON); Object latLonObj = bundle.getSerializable(KEY_MAPILLARY_DIALOG_LATLON);
@ -218,46 +253,221 @@ public class MapillaryImageDialog extends ContextMenuCardDialog {
} }
private View getStaticImageView() { private View getStaticImageView() {
LinearLayout ll = new LinearLayout(getMapActivity()); View view = getMapActivity().getLayoutInflater().inflate(R.layout.mapillary_static_image_view, null);
ll.setClickable(true); view.setClickable(true);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
isPortrait() ? ViewGroup.LayoutParams.MATCH_PARENT : AndroidUtils.dpToPx(getMapActivity(), 360f), isPortrait() ? ViewGroup.LayoutParams.MATCH_PARENT : AndroidUtils.dpToPx(getMapActivity(), 360f),
isPortrait() ? AndroidUtils.dpToPx(getMapActivity(), 270f) : ViewGroup.LayoutParams.MATCH_PARENT); isPortrait() ? AndroidUtils.dpToPx(getMapActivity(), 270f) : ViewGroup.LayoutParams.MATCH_PARENT);
ll.setGravity(Gravity.CENTER); view.setLayoutParams(lp);
ll.setLayoutParams(lp);
ProgressBar progressBar = new ProgressBar(getMapActivity()); view.findViewById(R.id.leftArrowButton).setOnClickListener(new View.OnClickListener() {
progressBar.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, @Override
ViewGroup.LayoutParams.WRAP_CONTENT)); public void onClick(View v) {
ll.addView(progressBar); clickLeftArrowButton(v);
}
});
view.findViewById(R.id.rightArrowButton).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clickRightArrowButton(v);
}
});
ImageView imageView = new ImageView(getMapActivity()); staticImageView = view;
imageView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
ll.addView(imageView);
if (!Algorithms.isEmpty(imageUrl)) { 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<QuadPointDouble, GeometryTile> 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<MapillaryImage> sequenceImages = new ArrayList<>();
if (!Algorithms.isEmpty(sKey)) {
double px, py;
for (Pair<QuadPointDouble, GeometryTile> 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<MapillaryImage>() {
@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<String, Pair<QuadPointDouble, GeometryTile>> 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<QuadPointDouble, GeometryTile> 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, public static MapillaryImageDialog show(MapActivity mapActivity, String key, String imageUrl,
String viewerUrl, LatLon latLon, double ca, String viewerUrl, LatLon latLon, double ca,
String title, String description) { String title, String description) {
MapillaryImageDialog dialog = new MapillaryImageDialog(mapActivity, key, imageUrl, viewerUrl, MapillaryImageDialog dialog = new MapillaryImageDialog(mapActivity, key, null, imageUrl,
latLon, ca, title, description); viewerUrl, latLon, ca, title, description);
ContextMenuCardDialogFragment.showInstance(dialog); ContextMenuCardDialogFragment.showInstance(dialog);
return dialog; return dialog;
} }
public static MapillaryImageDialog show(MapActivity mapActivity, double latitude, double longitude, 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 imageUrl = MAPILLARY_HIRES_IMAGE_URL_TEMPLATE + key;
String viewerUrl = MAPILLARY_VIEWER_URL_TEMPLATE + key; String viewerUrl = MAPILLARY_VIEWER_URL_TEMPLATE + key;
LatLon latLon = new LatLon(latitude, longitude); 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); latLon, ca, title, description);
ContextMenuCardDialogFragment.showInstance(dialog); ContextMenuCardDialogFragment.showInstance(dialog);
return dialog; return dialog;
@ -265,30 +475,57 @@ public class MapillaryImageDialog extends ContextMenuCardDialog {
private class DownloadImageTask extends AsyncTask<Void, Void, Bitmap> { private class DownloadImageTask extends AsyncTask<Void, Void, Bitmap> {
private int request;
private AtomicInteger downloadRequestNumber;
private ProgressBar progressBar; private ProgressBar progressBar;
private ImageView imageView; private ImageView imageView;
public DownloadImageTask(ProgressBar progressBar, ImageView imageView) { public DownloadImageTask(View staticImageView, int request, AtomicInteger downloadRequestNumber) {
this.progressBar = progressBar; if (staticImageView != null) {
this.imageView = imageView; 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 @Override
protected void onPreExecute() { protected void onPreExecute() {
progressBar.setVisibility(View.VISIBLE); if (progressBar != null) {
progressBar.setVisibility(View.VISIBLE);
}
} }
@Override @Override
protected Bitmap doInBackground(Void... params) { 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 @Override
protected void onPostExecute(Bitmap bitmap) { protected void onPostExecute(Bitmap bitmap) {
progressBar.setVisibility(View.GONE); if (isValidRequest()) {
if (bitmap != null) { if (progressBar != null) {
imageView.setImageDrawable(new BitmapDrawable(getMapActivity().getResources(), bitmap)); progressBar.setVisibility(View.GONE);
}
if (bitmap != null && imageView != null) {
imageView.setImageDrawable(new BitmapDrawable(getMapActivity().getResources(), bitmap));
}
} }
} }
private boolean isValidRequest() {
return request == downloadRequestNumber.get();
}
} }
} }

View file

@ -29,7 +29,7 @@ public class MapillaryMenuController extends MenuController {
public boolean setActive(boolean active) { public boolean setActive(boolean active) {
if (image != null && getMenuType() == MenuType.STANDARD) { if (image != null && getMenuType() == MenuType.STANDARD) {
MapillaryImageDialog.show(getMapActivity(), image.getLatitude(), image.getLongitude(), 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; return false;
} else { } else {
return super.setActive(active); return super.setActive(active);

View file

@ -28,10 +28,8 @@ import net.osmand.plus.resources.ResourceManager;
import net.osmand.plus.views.ContextMenuLayer.IContextMenuProvider; import net.osmand.plus.views.ContextMenuLayer.IContextMenuProvider;
import net.osmand.plus.views.MapTileLayer; import net.osmand.plus.views.MapTileLayer;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils; import net.osmand.util.MapUtils;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -39,8 +37,8 @@ import java.util.Map.Entry;
class MapillaryVectorLayer extends MapTileLayer implements MapillaryLayer, IContextMenuProvider { class MapillaryVectorLayer extends MapTileLayer implements MapillaryLayer, IContextMenuProvider {
private static final int TILE_ZOOM = 14; public static final int TILE_ZOOM = 14;
private static final double EXTENT = 4096.0; public static final double EXTENT = 4096.0;
private LatLon selectedImageLocation; private LatLon selectedImageLocation;
private Float selectedImageCameraAngle; private Float selectedImageCameraAngle;
@ -70,7 +68,7 @@ class MapillaryVectorLayer extends MapTileLayer implements MapillaryLayer, ICont
selectedImage = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_mapillary_location); selectedImage = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_mapillary_location);
headingImage = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_mapillary_location_view_angle); 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 @Override
@ -123,6 +121,8 @@ class MapillaryVectorLayer extends MapTileLayer implements MapillaryLayer, ICont
int top = (int) Math.floor(tilesRect.top + ellipticTileCorrection); int top = (int) Math.floor(tilesRect.top + ellipticTileCorrection);
int width = (int) Math.ceil(tilesRect.right - left); int width = (int) Math.ceil(tilesRect.right - left);
int height = (int) Math.ceil(tilesRect.bottom + ellipticTileCorrection - top); 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) && boolean useInternet = (OsmandPlugin.getEnabledPlugin(OsmandRasterMapsPlugin.class) != null || OsmandPlugin.getEnabledPlugin(MapillaryPlugin.class) != null) &&
settings.USE_INTERNET_TO_DOWNLOAD_TILES.get() && settings.isInternetConnectionAvailable() && map.couldBeDownloadedFromInternet(); settings.USE_INTERNET_TO_DOWNLOAD_TILES.get() && settings.isInternetConnectionAvailable() && map.couldBeDownloadedFromInternet();
@ -131,23 +131,9 @@ class MapillaryVectorLayer extends MapTileLayer implements MapillaryLayer, ICont
Map<QuadPointDouble, Map> visiblePoints = new HashMap<>(); Map<QuadPointDouble, Map> visiblePoints = new HashMap<>();
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) { for (int j = 0; j < height; j++) {
int leftPlusI = left + i; int tileX = (left + i) / div;
int topPlusJ = top + j; 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); String tileId = mgr.calculateTileId(map, tileX, tileY, TILE_ZOOM);
GeometryTile tile = tiles.get(tileId); GeometryTile tile = tiles.get(tileId);
if (tile == null) { 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, protected void drawPoints(Canvas canvas, RotatedTileBox tileBox, int tileX, int tileY,
GeometryTile tile, Map<QuadPointDouble, Map> visiblePoints) { GeometryTile tile, Map<QuadPointDouble, Map> visiblePoints) {
Map<String, List<Point>> 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<Point> 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 dzoom = tileBox.getZoom() - TILE_ZOOM;
int mult = (int) Math.pow(2.0, dzoom); int mult = (int) Math.pow(2.0, dzoom);
QuadRect tileBounds = tileBox.getTileBounds(); QuadRect tileBounds = tileBox.getTileBounds();
@ -198,14 +168,11 @@ class MapillaryVectorLayer extends MapTileLayer implements MapillaryLayer, ICont
float ph = point.getHeight(); float ph = point.getHeight();
float pwd = pw / 2; float pwd = pw / 2;
float phd = ph / 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()); canvas.rotate(-tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
for (List<Point> points : seqMap.values()) {
for (int i = 0; i < points.size(); i++) { for (Geometry g : tile.getData()) {
Point p = points.get(i); if (g instanceof Point && !g.isEmpty() && g.getUserData() != null && g.getUserData() instanceof HashMap) {
Point p = (Point) g;
px = p.getCoordinate().x / EXTENT; px = p.getCoordinate().x / EXTENT;
py = p.getCoordinate().y / EXTENT; py = p.getCoordinate().y / EXTENT;
tx = (tileX + px) * mult; tx = (tileX + px) * mult;
@ -213,14 +180,8 @@ class MapillaryVectorLayer extends MapTileLayer implements MapillaryLayer, ICont
if (tileBounds.contains(tx, ty, tx, ty)) { if (tileBounds.contains(tx, ty, tx, ty)) {
x = tileBox.getPixXFromTile(tileX + px, tileY + py, TILE_ZOOM); x = tileBox.getPixXFromTile(tileX + px, tileY + py, TILE_ZOOM);
y = tileBox.getPixYFromTile(tileX + px, tileY + py, TILE_ZOOM); y = tileBox.getPixYFromTile(tileX + px, tileY + py, TILE_ZOOM);
//QuadRect rNow = calculateRect(x, y, pwm, phm); canvas.drawBitmap(point, x - pwd, y - phd, paintPoint);
//QuadRect rLast = calculateRect(lx, ly, pw, ph); visiblePoints.put(new QuadPointDouble(tileX + px, tileY + py), (Map) p.getUserData());
//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;
//}
} }
} }
} }
@ -342,22 +303,32 @@ class MapillaryVectorLayer extends MapTileLayer implements MapillaryLayer, ICont
private void getImagesFromPoint(RotatedTileBox tb, PointF point, List<? super MapillaryImage> images) { private void getImagesFromPoint(RotatedTileBox tb, PointF point, List<? super MapillaryImage> images) {
Map<QuadPointDouble, Map> points = this.visiblePoints; Map<QuadPointDouble, Map> points = this.visiblePoints;
if (points != null) { if (points != null) {
int ex = (int) point.x; float ex = point.x;
int ey = (int) point.y; float ey = point.y;
final int rp = getRadius(tb); final int rp = getRadius(tb);
int radius = rp * 3 / 2; int radius = rp * 3 / 2;
float x, y; float x, y;
double minSqDist = Double.NaN;
double sqDist;
MapillaryImage img = null;
for (Entry<QuadPointDouble, Map> entry : points.entrySet()) { for (Entry<QuadPointDouble, Map> entry : points.entrySet()) {
x = tb.getPixXFromTile(entry.getKey().x, entry.getKey().y, TILE_ZOOM); x = tb.getPixXFromTile(entry.getKey().x, entry.getKey().y, TILE_ZOOM);
y = tb.getPixYFromTile(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) { if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) {
MapillaryImage img = new MapillaryImage(MapUtils.getLatitudeFromTile(TILE_ZOOM, entry.getKey().y), sqDist = (x - ex) * (x - ex) + (y - ey) * (y - ey);
MapUtils.getLongitudeFromTile(TILE_ZOOM, entry.getKey().x)); if (img == null || minSqDist > sqDist) {
if (img.setData(entry.getValue())) { minSqDist = sqDist;
images.add(img); 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);
}
} }
} }