Skip to content

Commit

Permalink
Merge branch 'panoramax_fixes'
Browse files Browse the repository at this point in the history
  • Loading branch information
simonpoole committed Jan 22, 2025
2 parents 26d5602 + 339c77c commit d08c774
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 50 deletions.
2 changes: 1 addition & 1 deletion src/main/assets/imagery/imagery_vespucci.geojson
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@
"type": "tms",
"tile_type": "mvt",
"category": "internal",
"url": "https://panoramax.openstreetmap.fr/api/map/{z}/{x}/{y}.pbf"
"url": "https://panoramax.xyz/api/map/{z}/{x}/{y}.mvt"
},
"type": "Feature"
},
Expand Down
10 changes: 2 additions & 8 deletions src/main/assets/panoramax-style.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,7 @@
"minzoom": 19,
"layout": {
"icon-image": "arrow",
"icon-rotate": {
"property": "heading",
"type": "identity"
}
"icon-rotate": ["to-number", ["get","heading"]]
},
"paint": {
"icon-color": "rgba(0, 215, 0, 1)"
Expand All @@ -83,10 +80,7 @@
"minzoom": 19,
"layout": {
"icon-image": "arrow",
"icon-rotate": {
"property": "heading",
"type": "identity"
}
"icon-rotate": ["to-number", ["get","heading"]]
},
"paint": {
"icon-color": "rgba(100, 200, 0, 1)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,36 +51,44 @@ public void run() {
try {
URL url = new URL(String.format(urlTemplate, sequenceId, apiKey));
Log.d(DEBUG_TAG, "query sequence: " + url.toString());
Request request = new Request.Builder().url(url).build();
OkHttpClient client = App.getHttpClient().newBuilder().connectTimeout(20000, TimeUnit.MILLISECONDS).readTimeout(20000, TimeUnit.MILLISECONDS)
.build();
Call mapillaryCall = client.newCall(request);
Response mapillaryCallResponse = mapillaryCall.execute();
if (!mapillaryCallResponse.isSuccessful()) {
return;
}
ResponseBody responseBody = mapillaryCallResponse.body();
try (InputStream inputStream = responseBody.byteStream()) {
if (inputStream == null) {
throw new IOException("null InputStream");
}
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = inputStream.read()) != -1) {
sb.append((char) cp);
}
JsonElement root = JsonParser.parseString(sb.toString());
if (!root.isJsonObject()) {
throw new IOException("root is not a JsonObject");
}
ArrayList<String> ids = getIds(root);
saveIdsAndUpdate(ids);
}
ArrayList<String> ids = new ArrayList<>();
querySequence(url, ids);
saveIdsAndUpdate(ids);
} catch (IOException ex) {
Log.e(DEBUG_TAG, "query sequence failed with " + ex.getMessage());
}
}

/**
* @param url
* @throws IOException
*/
protected void querySequence(URL url, ArrayList<String> ids) throws IOException {
Request request = new Request.Builder().url(url).build();
OkHttpClient client = App.getHttpClient().newBuilder().connectTimeout(20000, TimeUnit.MILLISECONDS).readTimeout(20000, TimeUnit.MILLISECONDS).build();
Call mapillaryCall = client.newCall(request);
Response mapillaryCallResponse = mapillaryCall.execute();
if (!mapillaryCallResponse.isSuccessful()) {
return;
}
ResponseBody responseBody = mapillaryCallResponse.body();
try (InputStream inputStream = responseBody.byteStream()) {
if (inputStream == null) {
throw new IOException("null InputStream");
}
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = inputStream.read()) != -1) {
sb.append((char) cp);
}
JsonElement root = JsonParser.parseString(sb.toString());
if (!root.isJsonObject()) {
throw new IOException("root is not a JsonObject");
}
getIds(root, ids);
}
}

/**
* Add ids list to state and update map
*
Expand All @@ -92,9 +100,10 @@ public void run() {
* Get list of ids from a sequence
*
* @param root top level JsonElement
* @param ids
* @return a List of ids
* @throws IOException if the ids can't be found
*/
@NonNull
protected abstract ArrayList<String> getIds(@NonNull JsonElement root) throws IOException;
protected abstract ArrayList<String> getIds(@NonNull JsonElement root, ArrayList<String> ids) throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -208,13 +208,12 @@ protected void saveIdsAndUpdate(ArrayList<String> ids) {
}

@Override
protected ArrayList<String> getIds(JsonElement root) throws IOException {
protected ArrayList<String> getIds(JsonElement root, ArrayList<String> ids) throws IOException {
JsonElement data = ((JsonObject) root).get(DATA_KEY);
if (!(data instanceof JsonArray)) {
throw new IOException("data not a JsonArray");
}
JsonArray idArray = data.getAsJsonArray();
ArrayList<String> ids = new ArrayList<>();
for (JsonElement element : idArray) {
if (element instanceof JsonObject) {
JsonElement temp = ((JsonObject) element).get(ID_KEY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class PanoramaxLoader extends NetworkImageLoader {
private static final int TAG_LEN = Math.min(LOG_TAG_LEN, PanoramaxLoader.class.getSimpleName().length());
protected static final String DEBUG_TAG = PanoramaxLoader.class.getSimpleName().substring(0, TAG_LEN);

final Map<String, String> urls;
private final Map<String, String> urls;

/**
* Construct a new loader
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,29 @@

import java.io.IOException;
import java.io.Serializable;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;

import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.text.SpannableString;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import de.blau.android.App;
import de.blau.android.Map;
import de.blau.android.R;
import de.blau.android.contract.FileExtensions;
Expand All @@ -35,6 +40,7 @@
import de.blau.android.prefs.Preferences;
import de.blau.android.util.DateFormatter;
import de.blau.android.util.SavingHelper;
import de.blau.android.util.ScreenMessage;
import de.blau.android.util.mvt.VectorTileRenderer;
import de.blau.android.util.mvt.style.Layer;
import de.blau.android.util.mvt.style.Style;
Expand All @@ -57,6 +63,8 @@ public class PanoramaxOverlay extends AbstractImageOverlay {
private static final String FIRST_SEQUENCE_KEY = "first_sequence";
private static final String SEQUENCES_KEY = "sequences";

private static final Pattern SEQUENCES_PATTERN = Pattern.compile("^\\[\\\"([^\\, ]+)\\\".*\\]$");

private static final String DEFAULT_PANORAMAX_STYLE_JSON = "panoramax-style.json";

/** this is the format used by panoramax */
Expand Down Expand Up @@ -88,6 +96,15 @@ static class State implements Serializable {
*/
public PanoramaxOverlay(@NonNull final Map map) {
super(map, PANORAMAX_TILES_ID, IMAGE_LAYER, DEFAULT_PANORAMAX_STYLE_JSON);
// hack so that we can follow the preferences
try {
Uri uri = Uri.parse(layerSource.getTileUrl());
Uri prefsUri = Uri.parse(App.getPreferences(map.getContext()).getPanoramaxApiUrl());
Log.i(DEBUG_TAG, "Change host from " + uri.getAuthority() + " to " + prefsUri.getAuthority());
uri.buildUpon().authority(prefsUri.getAuthority());
} catch (Exception ex) {
Log.e(DEBUG_TAG, "Unparsable tile url " + ex.getMessage());
}
setDateRange(panoramaxState.startDate, panoramaxState.endDate);
}

Expand Down Expand Up @@ -123,16 +140,10 @@ public void onSelected(FragmentActivity activity, de.blau.android.util.mvt.Vecto
}
// we ignore anything except the images for now
java.util.Map<String, Object> attributes = f.getAttributes();
String sequenceId = (String) attributes.get(FIRST_SEQUENCE_KEY);
if (sequenceId == null) {
Object o = attributes.get(SEQUENCES_KEY);
if (o instanceof String) {
sequenceId = (String) o;
}
}
String sequenceId = getSequenceId(attributes);

String id = (String) attributes.get(ID_KEY);
Log.e(DEBUG_TAG, "trying to retrieve sequence " + sequenceId + " for " + id);
Log.d(DEBUG_TAG, "trying to retrieve sequence " + sequenceId + " for " + id);
if (id != null && sequenceId != null) {
ArrayList<String> keys = panoramaxState != null ? panoramaxState.sequenceCache.get(sequenceId) : null;
if (keys == null) {
Expand All @@ -150,7 +161,30 @@ public void onSelected(FragmentActivity activity, de.blau.android.util.mvt.Vecto
panoramaxState.sequenceId = sequenceId;
return;
}
Log.e(DEBUG_TAG, "Sequence ID " + sequenceId + " ID " + id);
String message = activity.getString(R.string.toast_panoramax_sequence_error, sequenceId, id);
ScreenMessage.toastTopError(activity, message);
Log.e(DEBUG_TAG, message);
}

/**
* Try to determine the sequence id from the atributes
*
* @param attributes the attributes
* @return the id or null if it can't be found
*/
@Nullable
private String getSequenceId(@NonNull java.util.Map<String, Object> attributes) {
String sequenceId = (String) attributes.get(FIRST_SEQUENCE_KEY);
if (sequenceId == null) {
Object o = attributes.get(SEQUENCES_KEY);
if (o instanceof String) {
Matcher m = SEQUENCES_PATTERN.matcher((String) o);
if (m.find()) {
sequenceId = m.group(1);
}
}
}
return sequenceId;
}

/**
Expand All @@ -169,9 +203,13 @@ private void showImages(@NonNull FragmentActivity activity, @NonNull String id,
ImageViewerActivity.start(activity, ids, pos, new PanoramaxLoader(cacheDir, cacheSize, ids, panoramaxState.urlCache));
}
activity.runOnUiThread(() -> map.invalidate());
return;
} else {
Log.e(DEBUG_TAG, "image id " + id + " not found in sequence");
Log.e(DEBUG_TAG, "Image id " + id + " not found in sequence");
}
String message = activity.getString(R.string.toast_panoramax_image_not_in_sequence_error, id);
ScreenMessage.toastTopError(activity, message);
Log.e(DEBUG_TAG, message);
}

/**
Expand All @@ -182,6 +220,9 @@ private void showImages(@NonNull FragmentActivity activity, @NonNull String id,
*/
private class PanoramaxSequenceFetcher extends AbstractSequenceFetcher {

private static final String LINKS_KEY = "links";
private static final String REL_KEY = "rel";
private static final String NEXT_VALUE = "next";
private static final String FEATURES_KEY = "features";
private static final String ASSETS_KEY = "assets";
private static final String HD_KEY = "hd";
Expand Down Expand Up @@ -212,18 +253,29 @@ protected void saveIdsAndUpdate(ArrayList<String> ids) {
}

@Override
protected ArrayList<String> getIds(JsonElement root) throws IOException {
protected ArrayList<String> getIds(JsonElement root, ArrayList<String> ids) throws IOException {
JsonElement features = ((JsonObject) root).get(FEATURES_KEY);
if (!(features instanceof JsonArray)) {
throw new IOException("features not a JsonArray");
}
JsonArray featuresArray = features.getAsJsonArray();
ArrayList<String> ids = new ArrayList<>();
for (JsonElement element : featuresArray) {
if (element instanceof JsonObject) {
getIdAndUrl(ids, panoramaxState.urlCache, element);
}
}
// check for paginated response
JsonElement linksArray = ((JsonObject) root).get(LINKS_KEY);
if (linksArray instanceof JsonArray) {
for (JsonElement element : ((JsonArray) linksArray)) {
if (element instanceof JsonObject && ((JsonObject) element).has(REL_KEY)
&& NEXT_VALUE.equals(((JsonObject) element).get(REL_KEY).getAsString())) {
Log.d(DEBUG_TAG, "get next page");
querySequence(new URL(((JsonObject) element).get(HREF_KEY).getAsString()), ids);
break;
}
}
}
return ids;
}

Expand Down Expand Up @@ -255,6 +307,7 @@ private void getIdAndUrl(@NonNull List<String> ids, @NonNull java.util.Map<Strin
JsonElement href = ((JsonObject) hd).get(HREF_KEY);
if (href == null) {
Log.e(DEBUG_TAG, "href not found in sequence from API for id " + idString);
return;
}
urls.put(idString, href.getAsString());

Expand Down
2 changes: 2 additions & 0 deletions src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,8 @@
<string name="toast_no_roles_found">No roles found, all elements can be selected</string>
<string name="toast_no_preset_found">No matching preset found, all elements can be selected</string>
<string name="toast_undeleting_all_members">Undeleting all relation members with this element</string>
<string name="toast_panoramax_sequence_error">Unable to retrieve panoramax sequence id %1$s id %2$s</string>
<string name="toast_panoramax_image_not_in_sequence_error">Image id %1$s not found in sequence</string>
<!-- Error messages -->
<string name="error_mapsplit_missing_zoom">MapSplit sources must have min and max zoom set</string>
<string name="error_pbf_no_version">Version information missing in PBF file</string>
Expand Down

0 comments on commit d08c774

Please sign in to comment.