Changeset 36262 in osm for applications/editors/josm/plugins
- Timestamp:
- 2024-05-06T19:52:43+02:00 (8 months ago)
- Location:
- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideLayer.java
r36228 r36262 12 12 import java.awt.geom.Line2D; 13 13 import java.awt.image.BufferedImage; 14 import java.util.ArrayList; 14 15 import java.util.Comparator; 16 import java.util.List; 15 17 import java.util.Objects; 16 18 import java.util.logging.Logger; … … 28 30 import org.openstreetmap.josm.gui.dialogs.LayerListDialog; 29 31 import org.openstreetmap.josm.gui.dialogs.LayerListPopup; 32 import org.openstreetmap.josm.gui.draw.MapViewPath; 30 33 import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer; 31 34 import org.openstreetmap.josm.gui.layer.Layer; … … 279 282 } 280 283 281 for (var imageAbs : data.getImages()) { 282 if (imageAbs.visible() && mv != null && mv.contains(mv.getPoint(imageAbs))) { 283 drawImageMarker(g, imageAbs); 284 } 285 } 284 if (mv != null && mv.getDist100Pixel() < 100) { 285 for (var imageAbs : data.search(box.toBBox())) { 286 if (imageAbs.visible() && mv.contains(mv.getPoint(imageAbs))) { 287 drawImageMarker(g, imageAbs); 288 } 289 } 290 } else if (mv != null) { 291 // Generate sequence lines 292 final var sortedImages = new ArrayList<>(data.search(box.toBBox())); 293 sortedImages.sort(Comparator.naturalOrder()); 294 final var imagesToPaint = new ArrayList<StreetsideImage>(sortedImages.size()); 295 boolean containsSelected = false; 296 for (var image : sortedImages) { 297 if (!imagesToPaint.isEmpty() && imagesToPaint.getLast().greatCircleDistance(image) > 20) { 298 paintSequence(g, mv, imagesToPaint, containsSelected); 299 containsSelected = false; 300 imagesToPaint.clear(); 301 } 302 imagesToPaint.add(image); 303 if (image.equals(getData().getHighlightedImage())) { 304 containsSelected = true; 305 } 306 } 307 if (!imagesToPaint.isEmpty()) { 308 paintSequence(g, mv, imagesToPaint, containsSelected); 309 } 310 } 311 } 312 313 /** 314 * Paint an artificial sequence 315 * @param g The graphics to paint on 316 * @param mv The current mapview 317 * @param images The images to use for the sequence 318 * @param containsSelected {@code true} if the sequence has a selected or highlighted image 319 */ 320 private void paintSequence(Graphics2D g, MapView mv, List<StreetsideImage> images, boolean containsSelected) { 321 final var color = containsSelected ? StreetsideColorScheme.SEQ_HIGHLIGHTED 322 : StreetsideColorScheme.SEQ_UNSELECTED; 323 final var path = new MapViewPath(mv); 324 path.moveTo(images.get(0)); 325 for (int i = 1; i < images.size(); i++) { 326 path.lineTo(images.get(i)); 327 } 328 g.setColor(color); 329 g.draw(path); 286 330 } 287 331 … … 322 366 // Paint image marker 323 367 g.setColor(markerC); 324 g.fillOval(point.x - IMG_MARKER_RADIUS, point.y - IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS); 368 g.fillOval(point.x - IMG_MARKER_RADIUS, point.y - IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS, 369 2 * IMG_MARKER_RADIUS); 325 370 326 371 // Paint highlight for selected or highlighted images … … 328 373 g.setColor(Color.WHITE); 329 374 g.setStroke(new BasicStroke(2)); 330 g.drawOval(point.x - IMG_MARKER_RADIUS, point.y - IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS); 375 g.drawOval(point.x - IMG_MARKER_RADIUS, point.y - IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS, 376 2 * IMG_MARKER_RADIUS); 331 377 } 332 378 } … … 441 487 442 488 private record NearestImgToTargetComparator(StreetsideAbstractImage target) implements Comparator<StreetsideAbstractImage> { 443 @Override 444 public int compare(StreetsideAbstractImage img1, StreetsideAbstractImage img2) {445 return (int) Math.signum(img1.greatCircleDistance(target) - img2.greatCircleDistance(target));446 }447 } 448 } 489 490 @Override 491 public int compare(StreetsideAbstractImage img1, StreetsideAbstractImage img2) { 492 return (int) Math.signum(img1.greatCircleDistance(target) - img2.greatCircleDistance(target)); 493 } 494 }} -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideWalkAction.java
r36228 r36262 41 41 */ 42 42 public StreetsideWalkAction() { 43 super(tr("Walk mode"), new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT).setOptional(true), tr("Walk mode"),44 null, false, "streetsideWalk", true);43 super(tr("Walk mode"), new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT).setOptional(true), 44 tr("Walk mode"), null, false, "streetsideWalk", true); 45 45 } 46 46 -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideZoomAction.java
r36228 r36262 31 31 */ 32 32 public StreetsideZoomAction() { 33 super(tr("Zoom to selected image"), new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT).setOptional(true), 33 super(tr("Zoom to selected image"), 34 new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT).setOptional(true), 34 35 tr("Zoom to the currently selected Streetside image"), null, false, "mapillaryZoom", true); 35 36 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsidePreferenceSetting.java
r36228 r36262 134 134 @Override 135 135 public boolean ok() { 136 StreetsideProperties.DOWNLOAD_MODE 137 . put(DOWNLOAD_MODE.fromLabel(Objects.requireNonNull(downloadModeComboBox.getSelectedItem()).toString()).getPrefId());136 StreetsideProperties.DOWNLOAD_MODE.put(DOWNLOAD_MODE 137 .fromLabel(Objects.requireNonNull(downloadModeComboBox.getSelectedItem()).toString()).getPrefId()); 138 138 StreetsideProperties.DISPLAY_HOUR.put(displayHour.isSelected()); 139 139 StreetsideProperties.TIME_FORMAT_24.put(format24.isSelected()); -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ImageInfoPanel.java
r36228 r36262 124 124 final Collection<? extends OsmPrimitive> sel = event.getSelection(); 125 125 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 126 LOGGER.log(Logging.LEVEL_DEBUG, 127 "Selection changed. {0} primitives are selected.",sel == null ? 0 : sel.size());126 LOGGER.log(Logging.LEVEL_DEBUG, "Selection changed. {0} primitives are selected.", 127 sel == null ? 0 : sel.size()); 128 128 } 129 129 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/StreetsideViewerPanel.java
r36228 r36262 150 150 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 151 151 LOGGER.log(Logging.LEVEL_DEBUG, "Privacy link set for Streetside image {0} quadKey {1}", 152 new Object[] { bubbleId, newImageId});152 new Object[] { bubbleId, newImageId }); 153 153 } 154 154 -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ThreeSixtyDegreeViewerPanel.java
r36228 r36262 126 126 if (me.isSecondaryButtonDown()) { // JOSM viewer uses right-click for moving. 127 127 cameraTransform.setRy( 128 ((cameraTransform.ry.getAngle() - mouseDeltaX * modifierFactor * modifier * 2.0) % 360 + 540) 129 % 360- 180); // +128 ((cameraTransform.ry.getAngle() - mouseDeltaX * modifierFactor * modifier * 2.0) % 360 + 540) % 360 129 - 180); // + 130 130 cameraTransform.setRx( 131 ((cameraTransform.rx.getAngle() + mouseDeltaY * modifierFactor * modifier * 2.0) % 360 + 540) 132 % 360- 180); // -131 ((cameraTransform.rx.getAngle() + mouseDeltaY * modifierFactor * modifier * 2.0) % 360 + 540) % 360 132 - 180); // - 133 133 } else if (me.isPrimaryButtonDown()) { 134 134 final double z = camera.getTranslateZ(); -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/SequenceDownloadRunnable.java
r36260 r36262 14 14 import java.util.List; 15 15 import java.util.Objects; 16 import java.util.concurrent.Callable; 16 17 import java.util.function.Function; 17 18 import java.util.logging.Level; … … 19 20 20 21 import org.openstreetmap.josm.data.Bounds; 21 import org.openstreetmap.josm.plugins.streetside.StreetsideData;22 22 import org.openstreetmap.josm.plugins.streetside.StreetsideImage; 23 import org.openstreetmap.josm.plugins.streetside.utils.Streetside Properties;23 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL; 24 24 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3; 25 25 import org.openstreetmap.josm.tools.JosmRuntimeException; … … 34 34 * Download an area 35 35 */ 36 public final class SequenceDownloadRunnable extends BoundsDownloadRunnable {36 public final class SequenceDownloadRunnable extends BoundsDownloadRunnable implements Callable<List<StreetsideImage>> { 37 37 private static final Logger LOG = Logger.getLogger(BoundsDownloadRunnable.class.getCanonicalName()); 38 38 private static final Function<Bounds, URL> URL_GEN = APIv3::searchStreetsideImages; 39 private final StreetsideData data;39 private final List<StreetsideImage> images = new ArrayList<>(StreetsideURL.MAX_RETURN); 40 40 private String logo; 41 41 private String copyright; … … 43 43 /** 44 44 * Create a new downloader 45 * @param data The data to add to46 45 * @param bounds The bounds to download 47 46 */ 48 public SequenceDownloadRunnable(final StreetsideData data, finalBounds bounds) {47 public SequenceDownloadRunnable(final Bounds bounds) { 49 48 super(bounds); 50 this.data = data; 49 } 50 51 @Override 52 public List<StreetsideImage> call() { 53 this.run(); 54 return this.images; 51 55 } 52 56 … … 69 73 final long endTime = System.currentTimeMillis(); 70 74 LOG.log(Level.INFO, "Successfully loaded {0} Microsoft Streetside images in {1} seconds.", 71 new Object[] { this.data.getImages().size(), (endTime - startTime) / 1000});75 new Object[] { this.images.size(), (endTime - startTime) / 1000 }); 72 76 } catch (DateTimeParseException dateTimeParseException) { 73 77 // Added to debug #23658 -- a valid date string caused an exception … … 84 88 case "brandLogoUri" -> parseBrandLogoUri(parser); 85 89 case "copyright" -> parseCopyright(parser); 86 default -> { /* Do nothing for now */ } 90 default -> { 91 /* Do nothing for now */ } 87 92 } 88 93 } … … 106 111 while (parser.hasNext() && parser.next() == JsonParser.Event.START_OBJECT) { 107 112 while (parser.hasNext() && parser.currentEvent() != JsonParser.Event.END_OBJECT) { 108 if (parser.next() == JsonParser.Event.KEY_NAME 109 && "resources".equals(parser.getString())) { 113 if (parser.next() == JsonParser.Event.KEY_NAME && "resources".equals(parser.getString())) { 110 114 parser.next(); 111 115 List<StreetsideImage> bubbleImages = new ArrayList<>(); 112 116 parseResource(parser, bubbleImages); 113 this. data.addAll(bubbleImages, true);117 this.images.addAll(bubbleImages); 114 118 } 115 119 } … … 157 161 final var imageHeight = node.getInt("imageHeight"); 158 162 final var imageWidth = node.getInt("imageWidth"); 159 final var image = new StreetsideImage(id, lat, lon, heading, pitch, roll, vintageStart, 160 vintageEnd, this.logo, this.copyright, zoomMin, zoomMax, imageHeight, imageWidth, 161 imageUrlSubdomains); 163 final var image = new StreetsideImage(id, lat, lon, heading, pitch, roll, vintageStart, vintageEnd, 164 this.logo, this.copyright, zoomMin, zoomMax, imageHeight, imageWidth, imageUrlSubdomains); 162 165 bubbleImages.add(image); 163 166 LOG.info(() -> "Added image with id <" + image.id() + ">"); 164 if (Boolean.TRUE.equals(StreetsideProperties.PREDOWNLOAD_CUBEMAPS.get())) {165 this.data.downloadSurroundingCubemaps(image);166 }167 167 } else { 168 168 LOG.info(() -> MessageFormat.format("Unparsable JSON node object: {0}", node)); -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/StreetsideSquareDownloadRunnable.java
r36228 r36262 2 2 package org.openstreetmap.josm.plugins.streetside.io.download; 3 3 4 import java.util.concurrent.atomic.AtomicBoolean; 5 import java.util.concurrent.atomic.AtomicInteger; 6 7 import org.openstreetmap.gui.jmapviewer.TileXY; 4 8 import org.openstreetmap.josm.data.Bounds; 9 import org.openstreetmap.josm.plugins.streetside.StreetsideData; 5 10 import org.openstreetmap.josm.plugins.streetside.StreetsideLayer; 6 11 import org.openstreetmap.josm.plugins.streetside.gui.StreetsideMainDialog; 7 12 import org.openstreetmap.josm.plugins.streetside.utils.PluginState; 13 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL; 8 14 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideUtils; 9 15 … … 30 36 31 37 // Download basic sequence data synchronously 32 new SequenceDownloadRunnable(StreetsideLayer.getInstance().getData(), bounds).run(); 38 // Note that Microsoft limits the downloaded data to 500 images. So we need to split. 39 // Start with z16 tiles 40 final var zoom = 16; 41 final var cancelled = new AtomicBoolean(false); 42 final var counter = new AtomicInteger(); 43 final var data = StreetsideLayer.getInstance().getData(); 44 DownloadRunnable.download(zoom, bounds, cancelled, counter, data); 45 46 while (counter.get() > 0) { 47 try { 48 synchronized (counter) { 49 counter.wait(100); 50 } 51 } catch (InterruptedException e) { 52 cancelled.set(true); 53 Thread.currentThread().interrupt(); 54 } 55 } 56 // if (Boolean.TRUE.equals(StreetsideProperties.PREDOWNLOAD_CUBEMAPS.get())) { 57 // this.data.downloadSurroundingCubemaps(image); 58 // } 33 59 34 60 if (Thread.interrupted()) { … … 44 70 StreetsideMainDialog.getInstance().updateImage(); 45 71 } 72 73 private record DownloadRunnable(int zoom, int x, int y, AtomicBoolean cancelled, AtomicInteger counter, 74 StreetsideData data) implements Runnable { 75 76 @Override 77 public void run() { 78 try { 79 if (cancelled.get()) { 80 return; 81 } 82 final var newData = new SequenceDownloadRunnable(getBounds(zoom, x, y)).call(); 83 // Microsoft limits API responses to 500 at this time. Split up the bounds. 84 // Rather unfortunately, there are no hints in the response for this. So we have to use 85 // size checking. 86 if (newData.size() >= StreetsideURL.MAX_RETURN) { 87 download(zoom + 1, getBounds(zoom, x, y), cancelled, counter, data); 88 return; 89 } 90 if (cancelled.get()) { 91 return; 92 } 93 synchronized (data) { 94 data.addAll(newData); 95 } 96 } finally { 97 counter.decrementAndGet(); 98 synchronized (counter) { 99 counter.notifyAll(); 100 } 101 } 102 } 103 104 static void download(int zoom, Bounds bounds, AtomicBoolean cancelled, AtomicInteger counter, StreetsideData data) { 105 // Yes, we want max lat since tiles start at upper-left. 106 final var min = getTile(zoom, bounds.getMaxLat(), bounds.getMinLon()); 107 final var max = getTile(zoom, bounds.getMinLat(), bounds.getMaxLon()); 108 for (int x = min.getXIndex(); x <= max.getXIndex(); x++) { 109 for (int y = min.getYIndex(); y <= max.getYIndex(); y++) { 110 counter.incrementAndGet(); 111 Thread.ofVirtual().name("streetside-" + zoom + "/" + x + "/" + y) 112 .start(new DownloadRunnable(zoom, x, y, cancelled, counter, data)); 113 } 114 } 115 } 116 117 } 118 119 private static TileXY getTile(int zoom, double lat, double lon) { 120 final var x = (lon + 180) / 360 * Math.pow(2, zoom); 121 final var y = (1 - Math.log(Math.tan(lat * Math.PI / 180) + 1 / Math.cos(lat * Math.PI / 180)) / Math.PI) 122 * Math.pow(2, zoom - 1); 123 return new TileXY(x, y); 124 } 125 126 private static Bounds getBounds(int zoom, int x, int y) { 127 final var minLon = getLon(zoom, x); 128 final var maxLon = getLon(zoom, x + 1); 129 final var maxLat = getLat(zoom, y); 130 final var minLat = getLat(zoom, y + 1); 131 return new Bounds(minLat, minLon, maxLat, maxLon); 132 } 133 134 private static double getLon(int zoom, int x) { 135 return 360 * x / Math.pow(2, zoom) - 180; 136 } 137 138 private static double getLat(int zoom, int y) { 139 return Math.atan(Math.sinh(Math.PI - 2 * Math.PI * y / Math.pow(2, zoom))) * 180 / Math.PI; 140 } 46 141 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideURL.java
r36228 r36262 22 22 public final class StreetsideURL { 23 23 24 /** The maximum API responses */ 25 public static final int MAX_RETURN = 500; 24 26 private static final Logger LOGGER = Logger.getLogger(StreetsideURL.class.getCanonicalName()); 25 27 … … 50 52 final var ret = new StringBuilder(100); 51 53 if (parts != null) { 52 ret.append("?count= 500").append("&key=").append(StreetsideProperties.BING_MAPS_KEY.get());54 ret.append("?count=").append(MAX_RETURN).append("&key=").append(StreetsideProperties.BING_MAPS_KEY.get()); 53 55 if (parts.containsKey("bbox")) { 54 56 final String[] bbox = parts.get("bbox").split(",");
Note:
See TracChangeset
for help on using the changeset viewer.