Changeset 36194 in osm for applications/editors/josm/plugins/MicrosoftStreetside/src/org
- Timestamp:
- 2023-11-14T23:40:50+01:00 (14 months ago)
- Location:
- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside
- Files:
-
- 80 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.java
r34577 r36194 13 13 */ 14 14 public abstract class StreetsideAbstractImage implements Comparable<StreetsideAbstractImage> { 15 /** 16 * If two values for field cd differ by less than EPSILON both values are 17 * considered equal. 18 */ 19 private static final float EPSILON = 1e-5f; 20 21 protected String id; 22 23 // Image id of next image in sequence (decimal) 24 private long ne; 25 //Image id of previous image in sequence (decimal) 26 private long pr; 27 28 29 /** Sequence of pictures containing this object. */ 30 private StreetsideSequence sequence; 31 32 /** Position of the picture. */ 33 protected LatLon latLon; 34 /** Direction of the picture in degrees from true north. */ 35 protected double he; 36 /** Temporal position of the picture until it is uploaded. */ 37 private LatLon tempLatLon; 38 /** 39 * When the object is being dragged in the map, the temporal position is stored 40 * here. 41 */ 42 private LatLon movingLatLon; 43 /** Temporal direction of the picture until it is uploaded */ 44 private double tempHe; 45 /** 46 * When the object direction is being moved in the map, the temporal direction 47 * is stored here 48 */ 49 protected double movingHe; 50 /** Whether the image must be drown in the map or not */ 51 private boolean visible; 52 53 /** 54 * Creates a new object in the given position and with the given direction. 55 * {@link LatLon} 56 * 57 * @param id - the Streetside image id 58 * 59 * @param latLon 60 * The latitude and longitude of the image. 61 * @param he 62 * The direction of the picture (0 means north im Mapillary 63 * camera direction is not yet supported in the Streetside plugin). 64 */ 65 protected StreetsideAbstractImage(final String id, final LatLon latLon, final double he) { 66 this.id = id; 67 this.latLon = latLon; 68 tempLatLon = this.latLon; 69 movingLatLon = this.latLon; 70 this.he = he; 71 tempHe = he; 72 movingHe = he; 73 visible = true; 74 } 75 76 /** 77 * Creates a new object with the given id. 78 * 79 * @param id - the image id (All images require ids in Streetside) 80 */ 81 protected StreetsideAbstractImage(final String id) { 82 this.id = id; 83 84 visible = true; 85 } 86 87 /** 88 * @return the id 89 */ 90 public String getId() { 91 return id; 92 } 93 94 /** 95 * @param id 96 * the id to set 97 */ 98 public void setId(String id) { 99 this.id = id; 100 } 101 102 /** 103 * Returns the original direction towards the image has been taken. 104 * 105 * @return The direction of the image (0 means north and goes clockwise). 106 */ 107 public double getHe() { 108 return he; 109 } 110 111 /** 112 * Returns a LatLon object containing the original coordinates of the object. 113 * 114 * @return The LatLon object with the position of the object. 115 */ 116 public LatLon getLatLon() { 117 return latLon; 118 } 119 120 /** 121 * Returns the direction towards the image has been taken. 122 * 123 * @return The direction of the image (0 means north and goes clockwise). 124 */ 125 public double getMovingHe() { 126 return movingHe; 127 } 128 129 /** 130 * Returns a LatLon object containing the current coordinates of the object. 131 * When you are dragging the image this changes. 132 * 133 * @return The LatLon object with the position of the object. 134 */ 135 public LatLon getMovingLatLon() { 136 return movingLatLon; 137 } 138 139 /** 140 * Returns the sequence which contains this image. Never null. 141 * 142 * @return The StreetsideSequence object that contains this StreetsideImage. 143 */ 144 145 public StreetsideSequence getSequence() { 146 synchronized (this) { 147 if (sequence == null) { 148 sequence = new StreetsideSequence(); 149 sequence.add(this); 150 } 151 return sequence; 152 } 153 } 154 155 /** 156 * Returns the last fixed direction of the object. 157 * 158 * @return The last fixed direction of the object. 0 means north. 159 */ 160 public double getTempHe() { 161 return tempHe; 162 } 163 164 /** 165 * Returns the last fixed coordinates of the object. 166 * 167 * @return A LatLon object containing. 168 */ 169 public LatLon getTempLatLon() { 170 return tempLatLon; 171 } 172 173 /** 174 * Returns whether the object has been modified or not. 175 * 176 * @return true if the object has been modified; false otherwise. 177 */ 178 public boolean isModified() { 179 return !getMovingLatLon().equals(latLon) || Math.abs(getMovingHe() - he) > EPSILON; 180 } 181 182 /** 183 * Returns whether the image is visible on the map or not. 184 * 185 * @return True if the image is visible; false otherwise. 186 */ 187 public boolean isVisible() { 188 return visible; 189 } 190 191 /** 192 * Moves the image temporally to another position 193 * 194 * @param x 195 * The movement of the image in longitude units. 196 * @param y 197 * The movement of the image in latitude units. 198 */ 199 public void move(final double x, final double y) { 200 movingLatLon = new LatLon(tempLatLon.getY() + y, tempLatLon.getX() + x); 201 } 202 203 /** 204 * If the StreetsideImage belongs to a StreetsideSequence, returns the next 205 * image in the sequence. 206 * 207 * @return The following StreetsideImage, or null if there is none. 208 */ 209 public StreetsideAbstractImage next() { 210 synchronized (this) { 211 return getSequence().next(this); 212 } 213 } 214 215 /** 216 * If the StreetsideImage belongs to a StreetsideSequence, returns the previous 217 * image in the sequence. 218 * 219 * @return The previous StreetsideImage, or null if there is none. 220 */ 221 public StreetsideAbstractImage previous() { 222 synchronized (this) { 223 return getSequence().previous(this); 224 } 225 } 226 227 public void setHe(final double he) { 228 this.he = he; 229 } 230 231 public void setLatLon(final LatLon latLon) { 232 if (latLon != null) { 233 this.latLon = latLon; 234 } 235 } 236 237 /** 238 * Sets the StreetsideSequence object which contains the StreetsideImage. 239 * 240 * @param sequence 241 * The StreetsideSequence that contains the StreetsideImage. 242 * @throws IllegalArgumentException 243 * if the image is not already part of the 244 * {@link StreetsideSequence}. Call 245 * {@link StreetsideSequence#add(StreetsideAbstractImage)} first. 246 */ 247 public void setSequence(final StreetsideSequence sequence) { 248 synchronized (this) { 249 if (sequence != null && !sequence.getImages().contains(this)) { 250 throw new IllegalArgumentException(); 251 } 252 this.sequence = sequence; 253 } 254 } 255 256 /** 257 * Set's whether the image should be visible on the map or not. 258 * 259 * @param visible 260 * true if the image is set to be visible; false otherwise. 261 */ 262 public void setVisible(final boolean visible) { 263 this.visible = visible; 264 } 265 266 /** 267 * Called when the mouse button is released, meaning that the picture has 268 * stopped being dragged, so the temporal values are saved. 269 */ 270 public void stopMoving() { 271 tempLatLon = movingLatLon; 272 tempHe = movingHe; 273 } 274 275 /** 276 * Turns the image direction. 277 * 278 * @param he 279 * The angle the image is moving. 280 */ 281 public void turn(final double he) { 282 movingHe = tempHe + he; 283 } 284 285 /** 15 /** 16 * If two values for field cd differ by less than EPSILON both values are 17 * considered equal. 18 */ 19 private static final float EPSILON = 1e-5f; 20 21 protected String id; 22 /** 23 * Position of the picture. 24 */ 25 protected LatLon latLon; 26 //Image id of previous image in sequence (decimal) 27 private long pr; 28 /** 29 * Direction of the picture in degrees from true north. 30 */ 31 protected double he; 32 /** 33 * When the object direction is being moved in the map, the temporal direction 34 * is stored here 35 */ 36 protected double movingHe; 37 // Image id of next image in sequence (decimal) 38 private long ne; 39 /** 40 * Sequence of pictures containing this object. 41 */ 42 private StreetsideSequence sequence; 43 /** 44 * Temporal position of the picture until it is uploaded. 45 */ 46 private LatLon tempLatLon; 47 /** 48 * When the object is being dragged in the map, the temporal position is stored 49 * here. 50 */ 51 private LatLon movingLatLon; 52 /** 53 * Temporal direction of the picture until it is uploaded 54 */ 55 private double tempHe; 56 /** 57 * Whether the image must be drown in the map or not 58 */ 59 private boolean visible; 60 61 /** 62 * Creates a new object in the given position and with the given direction. 63 * {@link LatLon} 64 * 65 * @param id - the Streetside image id 66 * @param latLon The latitude and longitude of the image. 67 * @param he The direction of the picture (0 means north im Mapillary 68 * camera direction is not yet supported in the Streetside plugin). 69 */ 70 protected StreetsideAbstractImage(final String id, final LatLon latLon, final double he) { 71 this.id = id; 72 this.latLon = latLon; 73 tempLatLon = this.latLon; 74 movingLatLon = this.latLon; 75 this.he = he; 76 tempHe = he; 77 movingHe = he; 78 visible = true; 79 } 80 81 /** 82 * Creates a new object with the given id. 83 * 84 * @param id - the image id (All images require ids in Streetside) 85 */ 86 protected StreetsideAbstractImage(final String id) { 87 this.id = id; 88 89 visible = true; 90 } 91 92 /** 93 * @return the id 94 */ 95 public String getId() { 96 return id; 97 } 98 99 /** 100 * @param id the id to set 101 */ 102 public void setId(String id) { 103 this.id = id; 104 } 105 106 /** 107 * Returns the original direction towards the image has been taken. 108 * 109 * @return The direction of the image (0 means north and goes clockwise). 110 */ 111 public double getHe() { 112 return he; 113 } 114 115 public void setHe(final double he) { 116 this.he = he; 117 } 118 119 /** 120 * Returns a LatLon object containing the original coordinates of the object. 121 * 122 * @return The LatLon object with the position of the object. 123 */ 124 public LatLon getLatLon() { 125 return latLon; 126 } 127 128 public void setLatLon(final LatLon latLon) { 129 if (latLon != null) { 130 this.latLon = latLon; 131 } 132 } 133 134 /** 135 * Returns the direction towards the image has been taken. 136 * 137 * @return The direction of the image (0 means north and goes clockwise). 138 */ 139 public double getMovingHe() { 140 return movingHe; 141 } 142 143 /** 144 * Returns a LatLon object containing the current coordinates of the object. 145 * When you are dragging the image this changes. 146 * 147 * @return The LatLon object with the position of the object. 148 */ 149 public LatLon getMovingLatLon() { 150 return movingLatLon; 151 } 152 153 /** 154 * Returns the sequence which contains this image. Never null. 155 * 156 * @return The StreetsideSequence object that contains this StreetsideImage. 157 */ 158 159 public StreetsideSequence getSequence() { 160 synchronized (this) { 161 if (sequence == null) { 162 sequence = new StreetsideSequence(); 163 sequence.add(this); 164 } 165 return sequence; 166 } 167 } 168 169 /** 170 * Sets the StreetsideSequence object which contains the StreetsideImage. 171 * 172 * @param sequence 173 * The StreetsideSequence that contains the StreetsideImage. 174 * @throws IllegalArgumentException 175 * if the image is not already part of the 176 * {@link StreetsideSequence}. Call 177 * {@link StreetsideSequence#add(StreetsideAbstractImage)} first. 178 */ 179 public void setSequence(final StreetsideSequence sequence) { 180 synchronized (this) { 181 if (sequence != null && !sequence.getImages().contains(this)) { 182 throw new IllegalArgumentException(); 183 } 184 this.sequence = sequence; 185 } 186 } 187 188 /** 189 * Returns the last fixed direction of the object. 190 * 191 * @return The last fixed direction of the object. 0 means north. 192 */ 193 public double getTempHe() { 194 return tempHe; 195 } 196 197 /** 198 * Returns the last fixed coordinates of the object. 199 * 200 * @return A LatLon object containing. 201 */ 202 public LatLon getTempLatLon() { 203 return tempLatLon; 204 } 205 206 /** 207 * Returns whether the object has been modified or not. 208 * 209 * @return true if the object has been modified; false otherwise. 210 */ 211 public boolean isModified() { 212 return !getMovingLatLon().equals(latLon) || Math.abs(getMovingHe() - he) > EPSILON; 213 } 214 215 /** 216 * Returns whether the image is visible on the map or not. 217 * 218 * @return True if the image is visible; false otherwise. 219 */ 220 public boolean isVisible() { 221 return visible; 222 } 223 224 /** 225 * Set's whether the image should be visible on the map or not. 226 * 227 * @param visible 228 * true if the image is set to be visible; false otherwise. 229 */ 230 public void setVisible(final boolean visible) { 231 this.visible = visible; 232 } 233 234 /** 235 * Moves the image temporally to another position 236 * 237 * @param x The movement of the image in longitude units. 238 * @param y The movement of the image in latitude units. 239 */ 240 public void move(final double x, final double y) { 241 movingLatLon = new LatLon(tempLatLon.getY() + y, tempLatLon.getX() + x); 242 } 243 244 /** 245 * If the StreetsideImage belongs to a StreetsideSequence, returns the next 246 * image in the sequence. 247 * 248 * @return The following StreetsideImage, or null if there is none. 249 */ 250 public StreetsideAbstractImage next() { 251 synchronized (this) { 252 return getSequence().next(this); 253 } 254 } 255 256 /** 257 * If the StreetsideImage belongs to a StreetsideSequence, returns the previous 258 * image in the sequence. 259 * 260 * @return The previous StreetsideImage, or null if there is none. 261 */ 262 public StreetsideAbstractImage previous() { 263 synchronized (this) { 264 return getSequence().previous(this); 265 } 266 } 267 268 /** 269 * Called when the mouse button is released, meaning that the picture has 270 * stopped being dragged, so the temporal values are saved. 271 */ 272 public void stopMoving() { 273 tempLatLon = movingLatLon; 274 tempHe = movingHe; 275 } 276 277 /** 278 * Turns the image direction. 279 * 280 * @param he 281 * The angle the image is moving. 282 */ 283 public void turn(final double he) { 284 movingHe = tempHe + he; 285 } 286 287 /** 286 288 * @return the ne 287 289 */ -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideCubemap.java
r34399 r36194 12 12 public class StreetsideCubemap extends StreetsideAbstractImage { 13 13 14 15 16 17 18 14 /** 15 * If two values for field cd differ by less than EPSILON both values are considered equal. 16 */ 17 @SuppressWarnings("unused") 18 private static final float EPSILON = 1e-5f; 19 19 20 /** 21 * Main constructor of the class StreetsideCubemap 22 * 23 * @param quadId 24 * The Streetside id of the base frontal image of the cubemap 25 * in quternary 26 * @param latLon 27 * The latitude and longitude where it is positioned. 28 * @param he 29 * The direction of the images in degrees, meaning 0 north (camera 30 * direction is not yet supported in the Streetside plugin). 31 */ 32 public StreetsideCubemap(String quadId, LatLon latLon, double he) { 33 super(quadId, latLon, he); 34 } 20 /** 21 * Main constructor of the class StreetsideCubemap 22 * 23 * @param quadId The Streetside id of the base frontal image of the cubemap 24 * in quternary 25 * @param latLon The latitude and longitude where it is positioned. 26 * @param he The direction of the images in degrees, meaning 0 north (camera 27 * direction is not yet supported in the Streetside plugin). 28 */ 29 public StreetsideCubemap(String quadId, LatLon latLon, double he) { 30 super(quadId, latLon, he); 31 } 35 32 36 37 38 39 40 *- a StreetsideAbstract image object41 42 *StreetsideCubemaps are considered equal if they are associated43 *with the same image id - only one cubemap may be displayed at a44 *time. If the image selection changes, the cubemap changes.45 46 47 48 49 50 51 52 return id.compareTo(((StreetsideImage) image).getId());53 54 55 33 /** 34 * Comparison method for the StreetsideCubemap object. 35 * 36 * @param image 37 * - a StreetsideAbstract image object 38 * 39 * StreetsideCubemaps are considered equal if they are associated 40 * with the same image id - only one cubemap may be displayed at a 41 * time. If the image selection changes, the cubemap changes. 42 * 43 * @return result of the hashcode comparison. 44 * @see org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage 45 */ 46 @Override 47 public int compareTo(StreetsideAbstractImage image) { 48 if (image instanceof StreetsideImage) { 49 return id.compareTo(image.getId()); 50 } 51 return hashCode() - image.hashCode(); 52 } 56 53 57 58 59 60 61 62 63 64 65 66 54 /** 55 * HashCode StreetsideCubemap object. 56 * 57 * @return int hashCode 58 * @see org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage 59 */ 60 @Override 61 public int hashCode() { 62 return id.hashCode(); 63 } 67 64 68 69 70 71 72 73 74 75 76 65 /** 66 * stops ImageDisplay WalkAction (not currently supported by Streetside) 67 * 68 * @see org.openstreetmap.josm.plugins.streetside.actions.StreetsideWalkAction 69 */ 70 @Override 71 public void stopMoving() { 72 super.stopMoving(); 73 } 77 74 78 79 80 81 82 83 84 85 86 87 88 75 /** 76 * turns ImageDisplay WalkAction (not currently supported by Streetside) 77 * 78 * @param he - the direction the camera is facing (heading) 79 * 80 * @see org.openstreetmap.josm.plugins.streetside.actions.StreetsideWalkAction 81 */ 82 @Override 83 public void turn(double he) { 84 super.turn(he); 85 } 89 86 90 91 92 93 94 95 96 return StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get().booleanValue()?1016:510;97 87 /** 88 * @return the height of an assembled cubemap face for 16-tiled or 4-tiled imagery 89 * 90 * @see org.openstreetmap.josm.plugins.streetside.actions.StreetsideWalkAction 91 */ 92 public int getHeight() { 93 return Boolean.TRUE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) ? 1016 : 510; 94 } 98 95 99 96 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideData.java
r35601 r36194 37 37 private final Set<StreetsideAbstractImage> images = ConcurrentHashMap.newKeySet(); 38 38 /** 39 * All the images selected, can be more than one. 40 */ 41 private final Set<StreetsideAbstractImage> multiSelectedImages = ConcurrentHashMap.newKeySet(); 42 /** 43 * Listeners of the class. 44 */ 45 private final List<StreetsideDataListener> listeners = new CopyOnWriteArrayList<>(); 46 /** 47 * The bounds of the areas for which the pictures have been downloaded. 48 */ 49 private final List<Bounds> bounds; 50 /** 39 51 * The image currently selected, this is the one being shown. 40 52 */ … … 44 56 */ 45 57 private StreetsideAbstractImage highlightedImage; 46 /**47 * All the images selected, can be more than one.48 */49 private final Set<StreetsideAbstractImage> multiSelectedImages = ConcurrentHashMap.newKeySet();50 /**51 * Listeners of the class.52 */53 private final List<StreetsideDataListener> listeners = new CopyOnWriteArrayList<>();54 /**55 * The bounds of the areas for which the pictures have been downloaded.56 */57 private final List<Bounds> bounds;58 58 59 59 /** … … 64 64 bounds = new CopyOnWriteArrayList<>(); 65 65 66 // Adds the basic set of listeners. 67 Arrays.stream(StreetsidePlugin.getStreetsideDataListeners()).forEach(this::addListener); 68 addListener(StreetsideViewerDialog.getInstance().getStreetsideViewerPanel()); 69 addListener(StreetsideMainDialog.getInstance()); 70 addListener(ImageInfoPanel.getInstance()); 66 // Adds the basic set of listeners. 67 Arrays.stream(StreetsidePlugin.getStreetsideDataListeners()).forEach(this::addListener); 68 addListener(StreetsideViewerDialog.getInstance().getStreetsideViewerPanel()); 69 addListener(StreetsideMainDialog.getInstance()); 70 addListener(ImageInfoPanel.getInstance()); 71 } 72 73 /** 74 * Downloads surrounding images of this mapillary image in background threads 75 * 76 * @param streetsideImage the image for which the surrounding images should be downloaded 77 */ 78 private static void downloadSurroundingImages(StreetsideImage streetsideImage) { 79 MainApplication.worker.execute(() -> { 80 final int prefetchCount = StreetsideProperties.PRE_FETCH_IMAGE_COUNT.get(); 81 CacheAccess<String, BufferedImageCacheEntry> imageCache = Caches.ImageCache.getInstance().getCache(); 82 83 StreetsideAbstractImage nextImage = streetsideImage.next(); 84 StreetsideAbstractImage prevImage = streetsideImage.previous(); 85 86 for (int i = 0; i < prefetchCount; i++) { 87 if (nextImage != null) { 88 if (nextImage instanceof StreetsideImage && imageCache.get(nextImage.getId()) == null) { 89 CacheUtils.downloadPicture((StreetsideImage) nextImage); 90 } 91 nextImage = nextImage.next(); 92 } 93 if (prevImage != null) { 94 if (prevImage instanceof StreetsideImage && imageCache.get(prevImage.getId()) == null) { 95 CacheUtils.downloadPicture((StreetsideImage) prevImage); 96 } 97 prevImage = prevImage.previous(); 98 } 99 } 100 }); 101 } 102 103 /** 104 * Downloads surrounding images of this mapillary image in background threads 105 * 106 * @param streetsideImage the image for which the surrounding images should be downloaded 107 */ 108 public static void downloadSurroundingCubemaps(StreetsideImage streetsideImage) { 109 MainApplication.worker.execute(() -> { 110 final int prefetchCount = StreetsideProperties.PRE_FETCH_IMAGE_COUNT.get(); 111 CacheAccess<String, BufferedImageCacheEntry> imageCache = Caches.ImageCache.getInstance().getCache(); 112 113 StreetsideAbstractImage nextImage = streetsideImage.next(); 114 StreetsideAbstractImage prevImage = streetsideImage.previous(); 115 116 for (int i = 0; i < prefetchCount; i++) { 117 if (nextImage != null) { 118 if (nextImage instanceof StreetsideImage && imageCache.get(nextImage.getId()) == null) { 119 CacheUtils.downloadCubemap((StreetsideImage) nextImage); 120 } 121 nextImage = nextImage.next(); 122 } 123 if (prevImage != null) { 124 if (prevImage instanceof StreetsideImage && imageCache.get(prevImage.getId()) == null) { 125 CacheUtils.downloadCubemap((StreetsideImage) prevImage); 126 } 127 prevImage = prevImage.previous(); 128 } 129 } 130 }); 71 131 } 72 132 … … 86 146 * @param image The image to be added. 87 147 * @param update Whether the map must be updated or not 88 * (updates are currently unsupported by Streetside).148 * (updates are currently unsupported by Streetside). 89 149 */ 90 150 public void add(StreetsideAbstractImage image, boolean update) { 91 92 93 94 95 151 images.add(image); 152 if (update) { 153 StreetsideLayer.invalidateInstance(); 154 } 155 fireImagesAdded(); 96 156 } 97 157 … … 109 169 * 110 170 * @param newImages The set of images to be added. 111 * @param update Whether the map must be updated or not.171 * @param update Whether the map must be updated or not. 112 172 */ 113 173 public void addAll(Collection<? extends StreetsideAbstractImage> newImages, boolean update) { … … 119 179 } 120 180 121 /**181 /** 122 182 * Adds a new listener. 123 183 * … … 176 236 177 237 /** 238 * Returns the image under the mouse cursor. 239 * 240 * @return The image under the mouse cursor. 241 */ 242 public StreetsideAbstractImage getHighlightedImage() { 243 return highlightedImage; 244 } 245 246 /** 178 247 * Highlights the image under the cursor. 179 248 * … … 185 254 186 255 /** 187 * Returns the image under the mouse cursor.188 *189 * @return The image under the mouse cursor.190 */191 public StreetsideAbstractImage getHighlightedImage() {192 return highlightedImage;193 }194 195 /**196 256 * Returns a Set containing all images. 197 257 * … … 203 263 204 264 /** 265 * Sets a new {@link Collection} object as the used set of images. 266 * Any images that are already present, are removed. 267 * 268 * @param newImages the new image list (previously set images are completely replaced) 269 */ 270 public void setImages(Collection<StreetsideAbstractImage> newImages) { 271 synchronized (this) { 272 images.clear(); 273 images.addAll(newImages); 274 } 275 } 276 277 /** 205 278 * Returns a Set of all sequences, that the images are part of. 279 * 206 280 * @return all sequences that are contained in the Streetside data 207 281 */ … … 217 291 public StreetsideAbstractImage getSelectedImage() { 218 292 return selectedImage; 293 } 294 295 /** 296 * Selects a new image.If the user does ctrl + click, this isn't triggered. 297 * 298 * @param image The StreetsideImage which is going to be selected 299 */ 300 public void setSelectedImage(StreetsideAbstractImage image) { 301 setSelectedImage(image, false); 219 302 } 220 303 … … 229 312 * 230 313 * @throws IllegalStateException if the selected image is null or the selected image doesn't 231 * 314 * belong to a sequence. 232 315 */ 233 316 public void selectNext() { … … 242 325 * @param moveToPicture True if the view must me moved to the next picture. 243 326 * @throws IllegalStateException if the selected image is null or the selected image doesn't 244 * 327 * belong to a sequence. 245 328 */ 246 329 public void selectNext(boolean moveToPicture) { … … 263 346 * 264 347 * @throws IllegalStateException if the selected image is null or the selected image doesn't 265 * 348 * belong to a sequence. 266 349 */ 267 350 public void selectPrevious() { … … 277 360 * @param moveToPicture True if the view must me moved to the previous picture. 278 361 * @throws IllegalStateException if the selected image is null or the selected image doesn't 279 * 362 * belong to a sequence. 280 363 */ 281 364 public void selectPrevious(boolean moveToPicture) { … … 290 373 } 291 374 } 292 }293 294 /**295 * Selects a new image.If the user does ctrl + click, this isn't triggered.296 *297 * @param image The StreetsideImage which is going to be selected298 */299 public void setSelectedImage(StreetsideAbstractImage image) {300 setSelectedImage(image, false);301 375 } 302 376 … … 329 403 } 330 404 331 /**332 * Downloads surrounding images of this mapillary image in background threads333 * @param streetsideImage the image for which the surrounding images should be downloaded334 */335 private static void downloadSurroundingImages (StreetsideImage streetsideImage) {336 MainApplication.worker.execute(() -> {337 final int prefetchCount = StreetsideProperties.PRE_FETCH_IMAGE_COUNT.get();338 CacheAccess <String, BufferedImageCacheEntry> imageCache = Caches.ImageCache.getInstance().getCache();339 340 StreetsideAbstractImage nextImage = streetsideImage.next();341 StreetsideAbstractImage prevImage = streetsideImage.previous();342 343 for (int i = 0; i < prefetchCount; i++) {344 if (nextImage != null) {345 if (nextImage instanceof StreetsideImage &&346 imageCache.get(((StreetsideImage) nextImage).getId()) == null) {347 CacheUtils.downloadPicture((StreetsideImage) nextImage);348 }349 nextImage = nextImage.next();350 }351 if (prevImage != null) {352 if (prevImage instanceof StreetsideImage &&353 imageCache.get(((StreetsideImage) prevImage).getId()) == null) {354 CacheUtils.downloadPicture((StreetsideImage) prevImage);355 }356 prevImage = prevImage.previous();357 }358 }359 });360 }361 362 /**363 * Downloads surrounding images of this mapillary image in background threads364 * @param streetsideImage the image for which the surrounding images should be downloaded365 */366 public static void downloadSurroundingCubemaps(StreetsideImage streetsideImage) {367 MainApplication.worker.execute(() -> {368 final int prefetchCount = StreetsideProperties.PRE_FETCH_IMAGE_COUNT.get();369 CacheAccess<String, BufferedImageCacheEntry> imageCache = Caches.ImageCache.getInstance().getCache();370 371 StreetsideAbstractImage nextImage = streetsideImage.next();372 StreetsideAbstractImage prevImage = streetsideImage.previous();373 374 for (int i = 0; i < prefetchCount; i++) {375 if (nextImage != null) {376 if (nextImage instanceof StreetsideImage && imageCache.get(((StreetsideImage) nextImage).getId()) == null) {377 CacheUtils.downloadCubemap((StreetsideImage) nextImage);378 }379 nextImage = nextImage.next();380 }381 if (prevImage != null) {382 if (prevImage instanceof StreetsideImage && imageCache.get(((StreetsideImage) prevImage).getId()) == null) {383 CacheUtils.downloadCubemap((StreetsideImage) prevImage);384 }385 prevImage = prevImage.previous();386 }387 }388 });389 }390 391 405 private void fireSelectedImageChanged(StreetsideAbstractImage oldImage, StreetsideAbstractImage newImage) { 392 406 listeners.stream().filter(Objects::nonNull).forEach(lis -> lis.selectedImageChanged(oldImage, newImage)); 393 407 } 394 408 … … 403 417 } 404 418 405 /**406 * Sets a new {@link Collection} object as the used set of images.407 * Any images that are already present, are removed.408 *409 * @param newImages the new image list (previously set images are completely replaced)410 */411 public void setImages(Collection<StreetsideAbstractImage> newImages) {412 synchronized (this) {413 images.clear();414 images.addAll(newImages);415 }416 }417 418 419 @Override 419 420 public Collection<DataSource> getDataSources() { 420 421 return Collections.emptyList(); 421 422 } 422 423 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideDataListener.java
r34317 r36194 19 19 * manually clicking on the icon. 20 20 * 21 * @param oldImage 22 * Old selected {@link StreetsideAbstractImage} 23 * @param newImage 24 * New selected {@link StreetsideAbstractImage} 21 * @param oldImage Old selected {@link StreetsideAbstractImage} 22 * @param newImage New selected {@link StreetsideAbstractImage} 25 23 */ 26 void selectedImageChanged(StreetsideAbstractImage oldImage, 27 StreetsideAbstractImage newImage); 24 void selectedImageChanged(StreetsideAbstractImage oldImage, StreetsideAbstractImage newImage); 28 25 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideImage.java
r34429 r36194 18 18 */ 19 19 public class StreetsideImage extends StreetsideAbstractImage { 20 /**21 * Rn is a Bing Streetside image attribute - currently not22 * used, mapped or supported in the Streetside plugin -23 * left out initially because it's an unrequired complex object.24 */25 public static class Rn {26 // placeholder for Rn attribute (undocumented streetside complex inner type)27 }28 29 20 // latitude of the Streetside image 30 21 private double la; 31 32 22 //longitude of the Streetside image 33 23 private double lo; 34 35 24 // The bubble altitude, in meters above the WGS84 ellipsoid 36 25 private double al; 37 38 26 // Roll 39 27 private double ro; 40 41 28 // Pitch 42 29 private double pi; 43 44 30 // Blurring instructions - not currently used by the plugin 45 31 private String bl; 46 47 32 // Undocumented Attributes 48 33 private int ml; … … 55 40 * Main constructor of the class StreetsideImage 56 41 * 57 * @param id 42 * @param id The unique identifier of the image. 58 43 * @param latLon The latitude and longitude where it is positioned. 59 * @param he 44 * @param he The direction of the images in degrees, meaning 0 north. 60 45 */ 61 46 public StreetsideImage(String id, LatLon latLon, double he) { … … 64 49 65 50 public StreetsideImage(String id, double la, double lo) { 66 super(id, new LatLon(la, lo), 0.0);51 super(id, new LatLon(la, lo), 0.0); 67 52 } 68 53 69 54 public StreetsideImage(String id) { 70 55 super(id); 71 56 } 72 57 … … 82 67 */ 83 68 @Override 84 public String getId() {69 public String getId() { 85 70 return String.valueOf(id); 86 71 } 87 72 73 /** 74 * @param id the id to set 75 */ 76 @Override 77 public void setId(String id) { 78 this.id = id; 79 } 80 88 81 public UserProfile getUser() { 89 82 return getSequence().getUser(); 90 83 } 91 84 92 85 @Override 93 86 public String toString() { 94 return String.format( 95 "Image[id=%s,lat=%f,lon=%f,he=%f,user=%s]", 96 id, latLon.lat(), latLon.lon(), he, "null"//, cd 87 return String.format("Image[id=%s,lat=%f,lon=%f,he=%f,user=%s]", id, latLon.lat(), latLon.lon(), he, "null"//, cd 97 88 ); 98 89 } … … 106 97 public int compareTo(StreetsideAbstractImage image) { 107 98 if (image instanceof StreetsideImage) { 108 return id.compareTo( ((StreetsideImage) image).getId());99 return id.compareTo(image.getId()); 109 100 } 110 101 return hashCode() - image.hashCode(); … … 273 264 274 265 /** 275 * @param id the id to set276 */277 @Override278 public void setId(String id) {279 this.id = id;280 }281 282 /**283 266 * @return the rn 284 267 */ … … 293 276 this.rn = rn; 294 277 } 278 279 /** 280 * Rn is a Bing Streetside image attribute - currently not 281 * used, mapped or supported in the Streetside plugin - 282 * left out initially because it's an unrequired complex object. 283 */ 284 public static class Rn { 285 // placeholder for Rn attribute (undocumented streetside complex inner type) 286 } 295 287 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideLayer.java
r35978 r36194 17 17 import java.util.IntSummaryStatistics; 18 18 import java.util.Optional; 19 import java.util.logging.Logger; 19 20 20 21 import javax.swing.Action; 21 22 import javax.swing.Icon; 22 23 23 import org.apache.log4j.Logger;24 24 import org.openstreetmap.josm.data.Bounds; 25 25 import org.openstreetmap.josm.data.coor.ILatLon; … … 50 50 import org.openstreetmap.josm.tools.I18n; 51 51 import org.openstreetmap.josm.tools.ImageProvider.ImageSizes; 52 import org.openstreetmap.josm.tools.Logging; 52 53 53 54 /** … … 57 58 * @author nokutu 58 59 */ 59 public final class StreetsideLayer extends AbstractModifiableLayer implements 60 ActiveLayerChangeListener, StreetsideDataListener { 61 62 final static Logger logger = Logger.getLogger(StreetsideLayer.class); 63 64 /** The radius of the image marker */ 60 public final class StreetsideLayer extends AbstractModifiableLayer 61 implements ActiveLayerChangeListener, StreetsideDataListener { 62 63 private static final Logger LOGGER = Logger.getLogger(StreetsideLayer.class.getCanonicalName()); 64 65 /** 66 * The radius of the image marker 67 */ 65 68 private static final int IMG_MARKER_RADIUS = 7; 66 /** The radius of the circular sector that indicates the camera angle */ 69 /** 70 * The radius of the circular sector that indicates the camera angle 71 */ 67 72 private static final int CA_INDICATOR_RADIUS = 15; 68 /** The angle of the circular sector that indicates the camera angle */ 73 /** 74 * The angle of the circular sector that indicates the camera angle 75 */ 69 76 private static final int CA_INDICATOR_ANGLE = 40; 70 71 private static final DataSetListenerAdapter DATASET_LISTENER = 72 new DataSetListenerAdapter(e -> { 73 if (e instanceof DataChangedEvent && StreetsideDownloader.getMode() == DOWNLOAD_MODE.OSM_AREA) { 74 // When more data is downloaded, a delayed update is thrown, in order to 75 // wait for the data bounds to be set. 76 MainApplication.worker.execute(StreetsideDownloader::downloadOSMArea); 77 } 78 }); 79 80 /** Unique instance of the class. */ 81 private static StreetsideLayer instance; 82 /** The nearest images to the selected image from different sequences sorted by distance from selection. */ 83 private StreetsideImage[] nearestImages = {}; 84 /** {@link StreetsideData} object that stores the database. */ 85 private final StreetsideData data; 86 87 /** Mode of the layer. */ 88 public AbstractMode mode; 89 90 private volatile TexturePaint hatched; 91 92 private StreetsideLayer() { 93 super(I18n.tr("Microsoft Streetside Images")); 94 data = new StreetsideData(); 95 data.addListener(this); 96 } 77 /** 78 * Unique instance of the class. 79 */ 80 private static StreetsideLayer instance; 81 private static final DataSetListenerAdapter DATASET_LISTENER = new DataSetListenerAdapter(e -> { 82 if (e instanceof DataChangedEvent && StreetsideDownloader.getMode() == DOWNLOAD_MODE.OSM_AREA) { 83 // When more data is downloaded, a delayed update is thrown, in order to 84 // wait for the data bounds to be set. 85 MainApplication.worker.execute(StreetsideDownloader::downloadOSMArea); 86 } 87 }); 88 /** 89 * {@link StreetsideData} object that stores the database. 90 */ 91 private final StreetsideData data; 92 /** 93 * Mode of the layer. 94 */ 95 public AbstractMode mode; 96 /** 97 * The nearest images to the selected image from different sequences sorted by distance from selection. 98 */ 99 private StreetsideImage[] nearestImages = {}; 100 private volatile TexturePaint hatched; 101 102 private StreetsideLayer() { 103 super(I18n.tr("Microsoft Streetside Images")); 104 data = new StreetsideData(); 105 data.addListener(this); 106 } 107 108 public static void invalidateInstance() { 109 if (hasInstance()) { 110 getInstance().invalidate(); 111 } 112 } 113 114 private static synchronized void clearInstance() { 115 instance = null; 116 } 117 118 /** 119 * Returns the unique instance of this class. 120 * 121 * @return The unique instance of this class. 122 */ 123 public static synchronized StreetsideLayer getInstance() { 124 if (instance != null) { 125 return instance; 126 } 127 final StreetsideLayer layer = new StreetsideLayer(); 128 layer.init(); 129 instance = layer; // Only set instance field after initialization is complete 130 return instance; 131 } 132 133 /** 134 * @return if the unique instance of this layer is currently instantiated 135 */ 136 public static boolean hasInstance() { 137 return instance != null; 138 } 97 139 98 140 /** … … 120 162 if (StreetsidePlugin.getMapView() != null) { 121 163 StreetsideMainDialog.getInstance().streetsideImageDisplay.repaint(); 122 } 123 createHatchTexture(); 124 invalidate(); 125 } 126 127 public static void invalidateInstance() { 128 if (hasInstance()) { 129 getInstance().invalidate(); 130 } 164 } 165 createHatchTexture(); 166 invalidate(); 131 167 } 132 168 … … 153 189 } 154 190 155 private static synchronized void clearInstance() { 156 instance = null; 157 } 158 159 /** 160 * Returns the unique instance of this class. 191 /** 192 * Returns the {@link StreetsideData} object, which acts as the database of the 193 * Layer. 161 194 * 162 * @return The unique instance of this class. 163 */ 164 public static synchronized StreetsideLayer getInstance() { 165 if (instance != null) { 166 return instance; 167 } 168 final StreetsideLayer layer = new StreetsideLayer(); 169 layer.init(); 170 instance = layer; // Only set instance field after initialization is complete 171 return instance; 172 } 173 174 /** 175 * @return if the unique instance of this layer is currently instantiated 176 */ 177 public static boolean hasInstance() { 178 return instance != null; 179 } 180 181 /** 182 * Returns the {@link StreetsideData} object, which acts as the database of the 183 * Layer. 184 * 185 * @return The {@link StreetsideData} object that stores the database. 186 */ 187 @Override 188 public StreetsideData getData() { 189 return data; 190 } 195 * @return The {@link StreetsideData} object that stores the database. 196 */ 197 @Override 198 public StreetsideData getData() { 199 return data; 200 } 191 201 192 202 /** … … 194 204 * The "n-nearest image" is picked from the list of one image from every sequence that is nearest to the currently 195 205 * selected image, excluding the sequence to which the selected image belongs. 206 * 196 207 * @param n the index for picking from the list of "nearest images", beginning from 1 197 208 * @return the n-nearest image to the currently selected image … … 223 234 } 224 235 } catch (IllegalArgumentException e) { 236 Logging.trace(e); 225 237 // TODO: It would be ideal, to fix this properly. But for the moment let's catch this, for when a listener has already been removed. 226 238 } … … 228 240 } 229 241 230 231 @Override 242 @Override 232 243 public boolean isModified() { 233 244 return data.getImages().parallelStream().anyMatch(StreetsideAbstractImage::isModified); … … 289 300 for (StreetsideSequence seq : getData().getSequences()) { 290 301 if (seq.getImages().contains(selectedImage)) { 291 292 293 302 g.setColor( 303 seq.getId() == null ? StreetsideColorScheme.SEQ_IMPORTED_SELECTED : StreetsideColorScheme.SEQ_SELECTED 304 ); 294 305 } else { 295 296 297 306 g.setColor( 307 seq.getId() == null ? StreetsideColorScheme.SEQ_IMPORTED_UNSELECTED : StreetsideColorScheme.SEQ_UNSELECTED 308 ); 298 309 } 299 310 g.draw(MapViewGeometryUtil.getSequencePath(mv, seq)); … … 308 319 /** 309 320 * Draws an image marker onto the given Graphics context. 310 * @param g the Graphics context 321 * 322 * @param g the Graphics context 311 323 * @param img the image to be drawn onto the Graphics context 312 324 */ 313 325 private void drawImageMarker(final Graphics2D g, final StreetsideAbstractImage img) { 314 326 if (img == null || img.getLatLon() == null) { 315 logger.warn("An image is not painted, because it is null or has no LatLon!");327 LOGGER.warning("An image is not painted, because it is null or has no LatLon!"); 316 328 return; 317 329 } … … 325 337 markerC = StreetsideColorScheme.SEQ_HIGHLIGHTED; 326 338 directionC = StreetsideColorScheme.SEQ_HIGHLIGHTED_CA; 327 } else if (selectedImg != null && selectedImg.getSequence() != null && selectedImg.getSequence().equals(img.getSequence())) { 339 } else if (selectedImg != null && selectedImg.getSequence() != null 340 && selectedImg.getSequence().equals(img.getSequence())) { 328 341 markerC = StreetsideColorScheme.SEQ_SELECTED; 329 342 directionC = StreetsideColorScheme.SEQ_SELECTED_CA; … … 336 349 float alpha = 0.75f; 337 350 int type = AlphaComposite.SRC_OVER; 338 AlphaComposite composite = 339 AlphaComposite.getInstance(type, alpha); 351 AlphaComposite composite = AlphaComposite.getInstance(type, alpha); 340 352 g.setComposite(composite); 341 353 g.setColor(directionC); 342 g.fillArc(p.x - CA_INDICATOR_RADIUS, p.y - CA_INDICATOR_RADIUS, 2 * CA_INDICATOR_RADIUS, 2 * CA_INDICATOR_RADIUS, (int) (90 - /*img.getMovingHe()*/img.getHe() - CA_INDICATOR_ANGLE / 2d), CA_INDICATOR_ANGLE); 354 g.fillArc(p.x - CA_INDICATOR_RADIUS, p.y - CA_INDICATOR_RADIUS, 2 * CA_INDICATOR_RADIUS, 355 2 * CA_INDICATOR_RADIUS, (int) (90 - /*img.getMovingHe()*/img.getHe() - CA_INDICATOR_ANGLE / 2d), 356 CA_INDICATOR_ANGLE); 343 357 // Paint image marker 344 358 g.setColor(markerC); … … 351 365 g.drawOval(p.x - IMG_MARKER_RADIUS, p.y - IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS, 2 * IMG_MARKER_RADIUS); 352 366 } 353 367 } 354 368 355 369 @Override … … 365 379 @Override 366 380 public void mergeFrom(Layer from) { 367 throw new UnsupportedOperationException( 368 "This layer does not support merging yet"); 381 throw new UnsupportedOperationException("This layer does not support merging yet"); 369 382 } 370 383 371 384 @Override 372 385 public Action[] getMenuEntries() { 373 return new Action[]{ 374 LayerListDialog.getInstance().createShowHideLayerAction(), 375 LayerListDialog.getInstance().createDeleteLayerAction(), 376 new LayerListPopup.InfoAction(this) 377 }; 386 return new Action[] { LayerListDialog.getInstance().createShowHideLayerAction(), 387 LayerListDialog.getInstance().createDeleteLayerAction(), new LayerListPopup.InfoAction(this) }; 378 388 } 379 389 380 390 @Override 381 391 public Object getInfoComponent() { 382 IntSummaryStatistics seqSizeStats = getData().getSequences().stream().mapToInt(seq -> seq.getImages().size()).summaryStatistics(); 383 return new StringBuilder(I18n.tr("Streetside layer")) 384 .append('\n') 385 .append(I18n.tr( 386 "{0} sequences, each containing between {1} and {2} images (ø {3})", 387 getData().getSequences().size(), 388 seqSizeStats.getCount() <= 0 ? 0 : seqSizeStats.getMin(), 389 seqSizeStats.getCount() <= 0 ? 0 : seqSizeStats.getMax(), 390 seqSizeStats.getAverage() 391 )) 392 .append("\n\n") 393 .append("\n+ ") 394 .append(I18n.tr( 395 "{0} downloaded images", 396 getData().getImages().stream().filter(i -> i instanceof StreetsideImage).count() 397 )) 398 .append("\n= ") 399 .append(I18n.tr( 400 "{0} images in total", 401 getData().getImages().size() 402 )).toString(); 392 IntSummaryStatistics seqSizeStats = getData().getSequences().stream().mapToInt(seq -> seq.getImages().size()) 393 .summaryStatistics(); 394 return I18n.tr("Streetside layer") + '\n' 395 + I18n.tr("{0} sequences, each containing between {1} and {2} images (ø {3})", 396 getData().getSequences().size(), seqSizeStats.getCount() <= 0 ? 0 : seqSizeStats.getMin(), 397 seqSizeStats.getCount() <= 0 ? 0 : seqSizeStats.getMax(), seqSizeStats.getAverage()) 398 + "\n\n" + "\n+ " 399 + I18n.tr("{0} downloaded images", 400 getData().getImages().stream().filter(i -> i instanceof StreetsideImage).count()) 401 + "\n= " + I18n.tr("{0} images in total", getData().getImages().size()); 403 402 } 404 403 … … 449 448 * 450 449 * @param target the image for which you want to find the nearest other images 451 * @param limit the maximum length of the returned array450 * @param limit the maximum length of the returned array 452 451 * @return An array containing the closest images belonging to different sequences sorted by distance from target. 453 452 */ 454 453 private StreetsideImage[] getNearestImagesFromDifferentSequences(StreetsideAbstractImage target, int limit) { 455 454 return data.getSequences().parallelStream() 456 .filter(seq -> seq.getId() != null && !seq.getId().equals(target.getSequence().getId())) 457 .map(seq -> { // Maps sequence to image from sequence that is nearest to target 458 Optional<StreetsideAbstractImage> resImg = seq.getImages().parallelStream() 459 .filter(img -> img instanceof StreetsideImage && img.isVisible()) 460 .min(new NearestImgToTargetComparator(target)); 461 return resImg.orElse(null); 462 }) 463 .filter(img -> // Filters out images too far away from target 464 img != null && 465 img.getMovingLatLon().greatCircleDistance((ILatLon) target.getMovingLatLon()) 466 < StreetsideProperties.SEQUENCE_MAX_JUMP_DISTANCE.get() 467 ) 468 .sorted(new NearestImgToTargetComparator(target)) 469 .limit(limit) 470 .toArray(StreetsideImage[]::new); 455 .filter(seq -> seq.getId() != null && !seq.getId().equals(target.getSequence().getId())).map(seq -> { // Maps sequence to image from sequence that is nearest to target 456 Optional<StreetsideAbstractImage> resImg = seq.getImages().parallelStream() 457 .filter(img -> img instanceof StreetsideImage && img.isVisible()) 458 .min(new NearestImgToTargetComparator(target)); 459 return resImg.orElse(null); 460 }).filter(img -> // Filters out images too far away from target 461 img != null && img.getMovingLatLon().greatCircleDistance( 462 (ILatLon) target.getMovingLatLon()) < StreetsideProperties.SEQUENCE_MAX_JUMP_DISTANCE.get()) 463 .sorted(new NearestImgToTargetComparator(target)).limit(limit).toArray(StreetsideImage[]::new); 471 464 } 472 465 … … 496 489 this.target = target; 497 490 } 491 498 492 /* (non-Javadoc) 499 493 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) … … 501 495 @Override 502 496 public int compare(StreetsideAbstractImage img1, StreetsideAbstractImage img2) { 503 return (int) Math.signum( 504 img1.getMovingLatLon().greatCircleDistance((ILatLon) target.getMovingLatLon()) - 505 img2.getMovingLatLon().greatCircleDistance((ILatLon) target.getMovingLatLon()) 506 ); 507 } 508 } 497 return (int) Math.signum(img1.getMovingLatLon().greatCircleDistance((ILatLon) target.getMovingLatLon()) 498 - img2.getMovingLatLon().greatCircleDistance((ILatLon) target.getMovingLatLon())); 499 } 500 } 501 509 502 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsidePlugin.java
r36065 r36194 31 31 public static final ImageProvider LOGO = new ImageProvider("streetside-logo"); 32 32 33 /** Zoom action */ 33 /** 34 * Zoom action 35 */ 34 36 private static final StreetsideZoomAction ZOOM_ACTION = new StreetsideZoomAction(); 35 /** Walk action */ 37 /** 38 * Walk action 39 */ 36 40 private static final StreetsideWalkAction WALK_ACTION = new StreetsideWalkAction(); 37 41 … … 39 43 * Main constructor. 40 44 * 41 * @param info 42 * Required information of the plugin. Obtained from the jar file. 45 * @param info Required information of the plugin. Obtained from the jar file. 43 46 */ 44 47 public StreetsidePlugin(PluginInformation info) { … … 56 59 57 60 static StreetsideDataListener[] getStreetsideDataListeners() { 58 return new StreetsideDataListener[]{WALK_ACTION, ZOOM_ACTION, CubemapBuilder.getInstance()};61 return new StreetsideDataListener[] { WALK_ACTION, ZOOM_ACTION, CubemapBuilder.getInstance() }; 59 62 } 60 61 63 62 64 /** … … 65 67 public static StreetsideWalkAction getStreetsideWalkAction() { 66 68 return WALK_ACTION; 69 } 70 71 /** 72 * @return the current {@link MapView} without throwing a {@link NullPointerException} 73 */ 74 public static MapView getMapView() { 75 final MapFrame mf = MainApplication.getMap(); 76 if (mf != null) { 77 return mf.mapView; 78 } 79 return null; 67 80 } 68 81 … … 75 88 MainApplication.getMap().addToggleDialog(StreetsideMainDialog.getInstance(), false); 76 89 StreetsideMainDialog.getInstance().setImageInfoHelp(new ImageInfoHelpPopup( 77 MainApplication.getMap().addToggleDialog(ImageInfoPanel.getInstance(), false) 78 )); 90 MainApplication.getMap().addToggleDialog(ImageInfoPanel.getInstance(), false))); 79 91 MainApplication.getMap().addToggleDialog(StreetsideViewerDialog.getInstance(), false); 80 92 } … … 91 103 return new StreetsidePreferenceSetting(); 92 104 } 93 94 /**95 * @return the current {@link MapView} without throwing a {@link NullPointerException}96 */97 public static MapView getMapView() {98 final MapFrame mf = MainApplication.getMap();99 if (mf != null) {100 return mf.mapView;101 }102 return null;103 }104 105 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideSequence.java
r34399 r36194 17 17 public class StreetsideSequence { 18 18 19 19 /** 20 * The images in the sequence. 21 */ 22 private final List<StreetsideAbstractImage> images; 20 23 /** 21 24 * Unique identifier. Used only for {@link StreetsideImage} sequences. … … 23 26 private String id; 24 27 private UserProfile user; 25 26 28 private double la; 27 29 private double lo; 28 29 30 /** 30 31 * Epoch time when the sequence was created … … 32 33 private long cd; 33 34 34 /**35 * The images in the sequence.36 */37 private List<StreetsideAbstractImage> images;38 39 35 public StreetsideSequence(String id, Long ca) { 40 36 this.id = id; 41 37 cd = ca; 42 38 images = new CopyOnWriteArrayList<>(); … … 54 50 */ 55 51 public StreetsideSequence() { 56 52 images = new CopyOnWriteArrayList<>(); 57 53 } 58 54 59 55 public StreetsideSequence(String id, double la, double lo, long ca) { 60 61 62 63 64 65 }66 67 public StreetsideSequence(String id) {68 69 70 }56 this.id = id; 57 this.la = la; 58 this.lo = lo; 59 cd = ca; 60 images = new CopyOnWriteArrayList<>(); 61 } 62 63 public StreetsideSequence(String id) { 64 this.id = id; 65 images = new CopyOnWriteArrayList<>(); 66 } 71 67 72 68 /** … … 95 91 * 96 92 * @param image The {@link StreetsideAbstractImage} object whose next image is 97 * going to be returned. 98 * 93 * going to be returned. 99 94 * @return The next {@link StreetsideAbstractImage} object in the sequence. 100 *101 95 * @throws IllegalArgumentException if the given {@link StreetsideAbstractImage} object doesn't belong 102 * thethis sequence.96 * in this sequence. 103 97 */ 104 98 public StreetsideAbstractImage next(StreetsideAbstractImage image) { … … 118 112 * 119 113 * @param image The {@link StreetsideAbstractImage} object whose previous image is 120 * going to be returned. 121 * 114 * going to be returned. 122 115 * @return The previous {@link StreetsideAbstractImage} object in the sequence. 123 *124 116 * @throws IllegalArgumentException if the given {@link StreetsideAbstractImage} object doesn't belong 125 * the this sequence.117 * the this sequence. 126 118 */ 127 119 public StreetsideAbstractImage previous(StreetsideAbstractImage image) { … … 146 138 147 139 /** 148 * @param id the id to set149 */150 public void setId(String id) {151 this.id = id;152 }153 154 /**155 140 * @return the la 156 141 */ … … 214 199 } 215 200 201 /** 202 * @param id the id to set 203 */ 204 public void setId(String id) { 205 this.id = id; 206 } 207 216 208 public UserProfile getUser() { 217 209 return user; 218 210 } 219 211 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/ImageReloadAction.java
r34400 r36194 13 13 public class ImageReloadAction extends AbstractAction { 14 14 15 15 private static final long serialVersionUID = 7987479726049238315L; 16 16 17 18 19 17 public ImageReloadAction(final String name) { 18 super(name, ImageProvider.get("reload", ImageSizes.SMALLICON)); 19 } 20 20 21 22 23 if(StreetsideMainDialog.getInstance().getImage()!=null){24 25 26 21 @Override 22 public void actionPerformed(ActionEvent arg0) { 23 if (StreetsideMainDialog.getInstance().getImage() != null) { 24 CubemapBuilder.getInstance().reload(CubemapBuilder.getInstance().getCubemap().getId()); 25 } 26 } 27 27 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideDownloadAction.java
r34399 r36194 6 6 import java.awt.event.ActionEvent; 7 7 import java.awt.event.KeyEvent; 8 import java.util.logging.Level; 9 import java.util.logging.Logger; 8 10 9 import org.apache.log4j.Logger;10 11 import org.openstreetmap.josm.actions.JosmAction; 11 12 import org.openstreetmap.josm.gui.MainApplication; … … 26 27 public class StreetsideDownloadAction extends JosmAction { 27 28 29 public static final Shortcut SHORTCUT = Shortcut.registerShortcut("Streetside", "Open Streetside layer", 30 KeyEvent.VK_COMMA, Shortcut.SHIFT); 28 31 private static final long serialVersionUID = 4426446157849005029L; 29 30 public static final Shortcut SHORTCUT = Shortcut.registerShortcut("Streetside", "Open Streetside layer", KeyEvent.VK_COMMA, Shortcut.SHIFT); 31 32 final static Logger logger = Logger.getLogger(StreetsideDownloadAction.class); 32 private static final Logger LOGGER = Logger.getLogger(StreetsideDownloadAction.class.getCanonicalName()); 33 33 34 34 /** … … 36 36 */ 37 37 public StreetsideDownloadAction() { 38 super( 39 tr("Streetside"), 40 new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT), 41 tr("Open Streetside layer"), 42 SHORTCUT, 43 false, 44 "streetsideDownload", 45 false 46 ); 38 super(tr("Streetside"), new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT), 39 tr("Open Streetside layer"), SHORTCUT, false, "streetsideDownload", false); 47 40 } 48 41 49 42 @Override 50 43 public void actionPerformed(ActionEvent ae) { 51 if (!StreetsideLayer.hasInstance() || !MainApplication.getLayerManager().containsLayer(StreetsideLayer.getInstance())) { 44 if (!StreetsideLayer.hasInstance() 45 || !MainApplication.getLayerManager().containsLayer(StreetsideLayer.getInstance())) { 52 46 MainApplication.getLayerManager().addLayer(StreetsideLayer.getInstance()); 53 47 return; … … 64 58 } catch (IllegalArgumentException e) { 65 59 // If the StreetsideLayer is not managed by LayerManager but you try to set it as active layer 66 logger.warn(e);60 LOGGER.log(Level.WARNING, e.getMessage(), e); 67 61 } 68 62 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideDownloadViewAction.java
r34349 r36194 33 33 */ 34 34 public StreetsideDownloadViewAction() { 35 super( 36 I18n.tr(DESCRIPTION), 37 new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT), 38 I18n.tr(DESCRIPTION), 39 Shortcut.registerShortcut("Streetside area", I18n.tr(DESCRIPTION), KeyEvent.VK_PERIOD, Shortcut.SHIFT), 40 false, 41 "streetsideArea", 42 true 43 ); 35 super(I18n.tr(DESCRIPTION), new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT), 36 I18n.tr(DESCRIPTION), 37 Shortcut.registerShortcut("Streetside area", I18n.tr(DESCRIPTION), KeyEvent.VK_PERIOD, Shortcut.SHIFT), 38 false, "streetsideArea", true); 44 39 StreetsideProperties.DOWNLOAD_MODE.addListener(this); 45 40 initEnabledState(); … … 62 57 protected void updateEnabledState() { 63 58 super.updateEnabledState(); 64 setEnabled( 65 StreetsideLayer.hasInstance() && ( 66 StreetsideDownloader.getMode() == StreetsideDownloader.DOWNLOAD_MODE.OSM_AREA 67 || StreetsideDownloader.getMode() == StreetsideDownloader.DOWNLOAD_MODE.MANUAL_ONLY 68 ) 69 ); 59 setEnabled(StreetsideLayer.hasInstance() 60 && (StreetsideDownloader.getMode() == StreetsideDownloader.DOWNLOAD_MODE.OSM_AREA 61 || StreetsideDownloader.getMode() == StreetsideDownloader.DOWNLOAD_MODE.MANUAL_ONLY)); 70 62 } 71 63 -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideExportAction.java
r34577 r36194 14 14 import javax.swing.JOptionPane; 15 15 16 import org.apache.log4j.Logger;17 16 import org.openstreetmap.josm.actions.JosmAction; 18 17 import org.openstreetmap.josm.gui.MainApplication; … … 37 36 private static final long serialVersionUID = 6131359489725632369L; 38 37 39 final static Logger logger = Logger.getLogger(StreetsideExportAction.class);40 41 38 private StreetsideExportDialog dialog; 42 39 … … 47 44 super(tr("Export Streetside images"), new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT), 48 45 tr("Export Streetside images"), Shortcut.registerShortcut("Export Streetside", 49 tr("Export Streetside images"), KeyEvent.CHAR_UNDEFINED, 50 Shortcut.NONE),false, "streetsideExport", true);46 tr("Export Streetside images"), KeyEvent.CHAR_UNDEFINED, Shortcut.NONE), 47 false, "streetsideExport", true); 51 48 setEnabled(false); 52 49 } … … 63 60 dialog = new StreetsideExportDialog(ok); 64 61 pane.setMessage(dialog); 65 pane.setOptions(new JButton[] { ok, cancel});62 pane.setOptions(new JButton[] { ok, cancel }); 66 63 67 64 JDialog dlg = pane.createDialog(MainApplication.getMainFrame(), tr("Export Streetside images")); … … 70 67 71 68 // Checks if the inputs are correct and starts the export process. 72 if (pane.getValue() != null 73 && (int) pane.getValue() == JOptionPane.OK_OPTION 74 && dialog.chooser != null) { 69 if (pane.getValue() != null && (int) pane.getValue() == JOptionPane.OK_OPTION && dialog.chooser != null) { 75 70 if (dialog.group.isSelected(dialog.all.getModel())) { 76 71 export(StreetsideLayer.getInstance().getData().getImages()); … … 97 92 * Exports the given images from the database. 98 93 * 99 * @param images 100 * The set of images to be exported. 94 * @param images The set of images to be exported. 101 95 */ 102 96 public void export(Set<StreetsideAbstractImage> images) { 103 MainApplication.worker .execute(new StreetsideExportManager(images,104 dialog.chooser.getSelectedFile().toString()));97 MainApplication.worker 98 .execute(new StreetsideExportManager(images, dialog.chooser.getSelectedFile().toString())); 105 99 } 106 100 -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideWalkAction.java
r34577 r36194 32 32 33 33 private static final long serialVersionUID = 3454223919402245818L; 34 34 private final List<WalkListener> listeners = new ArrayList<>(); 35 35 private WalkThread thread; 36 private final List<WalkListener> listeners = new ArrayList<>();37 36 38 37 /** … … 40 39 */ 41 40 public StreetsideWalkAction() { 42 super(tr("Walk mode"), new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT), 43 tr("Walk mode"), null, 44 false, "streetsideWalk", true); 41 super(tr("Walk mode"), new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT), tr("Walk mode"), 42 null, false, "streetsideWalk", true); 45 43 } 46 44 … … 48 46 public void actionPerformed(ActionEvent arg0) { 49 47 StreetsideWalkDialog dialog = new StreetsideWalkDialog(); 50 JOptionPane pane = new JOptionPane(dialog, JOptionPane.PLAIN_MESSAGE, 51 JOptionPane.OK_CANCEL_OPTION); 48 JOptionPane pane = new JOptionPane(dialog, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION); 52 49 JDialog dlg = pane.createDialog(MainApplication.getMainFrame(), tr("Walk mode")); 53 50 dlg.setMinimumSize(new Dimension(400, 150)); 54 51 dlg.setVisible(true); 55 if (pane.getValue() != null 56 && (int) pane.getValue() == JOptionPane.OK_OPTION) { 57 thread = new WalkThread((int) dialog.spin.getValue(), 58 dialog.waitForPicture.isSelected(), 52 if (pane.getValue() != null && (int) pane.getValue() == JOptionPane.OK_OPTION) { 53 thread = new WalkThread((int) dialog.spin.getValue(), dialog.waitForPicture.isSelected(), 59 54 dialog.followSelection.isSelected(), dialog.goForward.isSelected()); 60 55 fireWalkStarted(); … … 72 67 * Adds a listener. 73 68 * 74 * @param lis 75 * The listener to be added. 69 * @param lis The listener to be added. 76 70 */ 77 71 public void addListener(WalkListener lis) { … … 83 77 * 84 78 * @param lis 85 * 79 * The listener to be added. 86 80 */ 87 81 public void removeListener(WalkListener lis) { -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideZoomAction.java
r34400 r36194 29 29 */ 30 30 public StreetsideZoomAction() { 31 super( 32 tr("Zoom to selected image"), 33 new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT), 34 tr("Zoom to the currently selected Streetside image"), 35 null, 36 false, 37 "mapillaryZoom", 38 true 39 ); 31 super(tr("Zoom to selected image"), new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT), 32 tr("Zoom to the currently selected Streetside image"), null, false, "mapillaryZoom", true); 40 33 } 41 34 … … 45 38 throw new IllegalStateException(); 46 39 } 47 MainApplication.getMap().mapView .zoomTo(StreetsideLayer.getInstance().getData()48 . getSelectedImage().getMovingLatLon());40 MainApplication.getMap().mapView 41 .zoomTo(StreetsideLayer.getInstance().getData().getSelectedImage().getMovingLatLon()); 49 42 } 50 43 … … 54 47 } 55 48 56 49 @Override 57 50 protected boolean listenToSelectionChange() { 58 51 return false; -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/WalkThread.java
r34416 r36194 4 4 import java.awt.image.BufferedImage; 5 5 import java.text.MessageFormat; 6 import java.util.logging.Logger; 6 7 7 8 import javax.swing.SwingUtilities; 8 9 9 import org.apache.log4j.Logger;10 10 import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage; 11 11 import org.openstreetmap.josm.plugins.streetside.StreetsideData; … … 16 16 import org.openstreetmap.josm.plugins.streetside.gui.StreetsideMainDialog; 17 17 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties; 18 18 import org.openstreetmap.josm.tools.Logging; 19 19 20 20 /** … … 24 24 */ 25 25 public class WalkThread extends Thread implements StreetsideDataListener { 26 private static final Logger LOGGER = Logger.getLogger(WalkThread.class.getCanonicalName()); 26 27 private final int interval; 27 28 private final StreetsideData data; 28 private boolean end;29 29 private final boolean waitForFullQuality; 30 30 private final boolean followSelected; 31 31 private final boolean goForward; 32 private boolean end; 32 33 private BufferedImage lastImage; 33 34 private volatile boolean paused; 34 35 final static Logger logger = Logger.getLogger(WalkThread.class);36 35 37 36 /** 38 37 * Main constructor. 39 38 * 40 * @param interval How often the images switch.39 * @param interval How often the images switch. 41 40 * @param waitForPicture If it must wait for the full resolution picture or just the 42 * thumbnail.41 * thumbnail. 43 42 * @param followSelected Zoom to each image that is selected. 44 * @param goForward true to go forward; false to go backwards.43 * @param goForward true to go forward; false to go backwards. 45 44 */ 46 public WalkThread(int interval, boolean waitForPicture, 47 boolean followSelected, boolean goForward) { 45 public WalkThread(int interval, boolean waitForPicture, boolean followSelected, boolean goForward) { 48 46 this.interval = interval; 49 47 waitForFullQuality = waitForPicture; … … 52 50 data = StreetsideLayer.getInstance().getData(); 53 51 data.addListener(this); 52 } 53 54 /** 55 * Downloads n images into the cache beginning from the supplied start-image (including the start-image itself). 56 * 57 * @param startImage the image to start with (this and the next n-1 images in the same sequence are downloaded) 58 * @param n the number of images to download 59 * @param type the quality of the image (full or thumbnail) 60 */ 61 private static void preDownloadImages(StreetsideImage startImage, int n, CacheUtils.PICTURE type) { 62 if (n >= 1 && startImage != null) { 63 CacheUtils.downloadPicture(startImage, type); 64 if (startImage.next() instanceof StreetsideImage && n >= 2) { 65 preDownloadImages((StreetsideImage) startImage.next(), n - 1, type); 66 } 67 } 54 68 } 55 69 … … 62 76 // Predownload next 10 thumbnails. 63 77 preDownloadImages((StreetsideImage) image.next(), 10, CacheUtils.PICTURE.THUMBNAIL); 64 if (StreetsideProperties.PREDOWNLOAD_CUBEMAPS.get()) {78 if (Boolean.TRUE.equals(StreetsideProperties.PREDOWNLOAD_CUBEMAPS.get())) { 65 79 preDownloadCubemaps((StreetsideImage) image.next(), 10); 66 80 } … … 68 82 // Start downloading 3 next full images. 69 83 StreetsideAbstractImage currentImage = image.next(); 70 84 preDownloadImages((StreetsideImage) currentImage, 3, CacheUtils.PICTURE.FULL_IMAGE); 71 85 } 72 86 } 73 87 try { 74 88 // Waits for full quality picture. 75 final BufferedImage displayImage = StreetsideMainDialog.getInstance().getStreetsideImageDisplay().getImage(); 89 final BufferedImage displayImage = StreetsideMainDialog.getInstance().getStreetsideImageDisplay() 90 .getImage(); 76 91 if (waitForFullQuality && image instanceof StreetsideImage) { 77 92 while (displayImage == lastImage || displayImage == null || displayImage.getWidth() < 2048) { … … 101 116 } 102 117 } catch (NullPointerException e) { 103 if (StreetsideProperties.DEBUGING_ENABLED.get()) {104 logger.debug(MessageFormat.format("Exception thrown in WalkThread: {0}", e.getMessage()));105 e.printStackTrace();118 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 119 LOGGER.log(Logging.LEVEL_DEBUG, 120 MessageFormat.format("Exception thrown in WalkThread: {0}", e.getMessage()), e); 106 121 } 107 122 return; … … 111 126 112 127 private void preDownloadCubemaps(StreetsideImage startImage, int n) { 113 128 if (n >= 1 && startImage != null) { 114 129 115 116 117 130 for (int i = 0; i < 6; i++) { 131 for (int j = 0; j < 4; j++) { 132 for (int k = 0; k < 4; k++) { 118 133 119 CacheUtils.downloadPicture(startImage, CacheUtils.PICTURE.CUBEMAP); 120 if (startImage.next() instanceof StreetsideImage && n >= 2) { 121 preDownloadCubemaps((StreetsideImage) startImage.next(), n - 1); 122 } 123 } 124 } 125 } 126 } 127 } 128 129 /** 130 * Downloads n images into the cache beginning from the supplied start-image (including the start-image itself). 131 * 132 * @param startImage the image to start with (this and the next n-1 images in the same sequence are downloaded) 133 * @param n the number of images to download 134 * @param type the quality of the image (full or thumbnail) 135 */ 136 private static void preDownloadImages(StreetsideImage startImage, int n, CacheUtils.PICTURE type) { 137 if (n >= 1 && startImage != null) { 138 CacheUtils.downloadPicture(startImage, type); 139 if (startImage.next() instanceof StreetsideImage && n >= 2) { 140 preDownloadImages((StreetsideImage) startImage.next(), n - 1, type); 134 CacheUtils.downloadPicture(startImage, CacheUtils.PICTURE.CUBEMAP); 135 if (startImage.next() instanceof StreetsideImage && n >= 2) { 136 preDownloadCubemaps((StreetsideImage) startImage.next(), n - 1); 137 } 138 } 139 } 141 140 } 142 141 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cache/CacheUtils.java
r34399 r36194 2 2 package org.openstreetmap.josm.plugins.streetside.cache; 3 3 4 import java.io.IOException; 5 import java.util.logging.Logger; 4 6 5 import java.io.IOException;6 7 import org.apache.log4j.Logger;8 7 import org.openstreetmap.josm.data.cache.CacheEntry; 9 8 import org.openstreetmap.josm.data.cache.CacheEntryAttributes; … … 11 10 import org.openstreetmap.josm.plugins.streetside.StreetsideImage; 12 11 import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapBuilder; 12 import org.openstreetmap.josm.tools.Logging; 13 13 14 14 /** … … 20 20 public final class CacheUtils { 21 21 22 final static Logger logger = Logger.getLogger(CacheUtils.class);22 private static final Logger LOGGER = Logger.getLogger(CacheUtils.class.getCanonicalName()); 23 23 24 private staticIgnoreDownload ignoreDownload = new IgnoreDownload();24 private static final IgnoreDownload ignoreDownload = new IgnoreDownload(); 25 25 26 /** Picture quality */ 27 public enum PICTURE { 28 /** Thumbnail quality picture (320 p) */ 29 THUMBNAIL, 30 /** Full quality picture (2048 p) */ 31 FULL_IMAGE, 32 /** Both of them */ 33 BOTH, 34 /** Streetside cubemap */ 35 CUBEMAP 36 } 26 private CacheUtils() { 27 // Private constructor to avoid instantiation 28 } 37 29 38 private CacheUtils() { 39 // Private constructor to avoid instantiation 40 } 30 /** 31 * Downloads the the thumbnail and the full resolution picture of the given 32 * image. Does nothing if it is already in cache. 33 * 34 * @param img The image whose picture is going to be downloaded. 35 */ 36 public static void downloadPicture(StreetsideImage img) { 37 downloadPicture(img, PICTURE.BOTH); 38 } 41 39 42 /** 43 * Downloads the the thumbnail and the full resolution picture of the given 44 * image. Does nothing if it is already in cache. 45 * 46 * @param img 47 * The image whose picture is going to be downloaded. 48 */ 49 public static void downloadPicture(StreetsideImage img) { 50 downloadPicture(img, PICTURE.BOTH); 51 } 40 /** 41 * Downloads the the thumbnail and the full resolution picture of the given 42 * image. Does nothing if it is already in cache. 43 * 44 * @param cm The image whose picture is going to be downloaded. 45 */ 46 public static void downloadCubemap(StreetsideImage cm) { 47 downloadPicture(cm, PICTURE.CUBEMAP); 48 } 52 49 53 /** 54 * Downloads the the thumbnail and the full resolution picture of the given 55 * image. Does nothing if it is already in cache. 56 * 57 * @param cm 58 * The image whose picture is going to be downloaded. 59 */ 60 public static void downloadCubemap(StreetsideImage cm) { 61 downloadPicture(cm, PICTURE.CUBEMAP); 62 } 50 /** 51 * Downloads the picture of the given image. Does nothing when it is already 52 * in cache. 53 * 54 * @param img The image to be downloaded. 55 * @param pic The picture type to be downloaded (full quality, thumbnail or 56 * both.) 57 */ 58 public static void downloadPicture(StreetsideImage img, PICTURE pic) { 59 switch (pic) { 60 case BOTH: 61 if (new StreetsideCache(img.getId(), StreetsideCache.Type.THUMBNAIL).get() == null) 62 submit(img.getId(), StreetsideCache.Type.THUMBNAIL, ignoreDownload); 63 if (new StreetsideCache(img.getId(), StreetsideCache.Type.FULL_IMAGE).get() == null) 64 submit(img.getId(), StreetsideCache.Type.FULL_IMAGE, ignoreDownload); 65 break; 66 case THUMBNAIL: 67 submit(img.getId(), StreetsideCache.Type.THUMBNAIL, ignoreDownload); 68 break; 69 case FULL_IMAGE: 70 // not used (relic from Mapillary) 71 break; 72 case CUBEMAP: 73 if (img.getId() == null) { 74 LOGGER.log(Logging.LEVEL_ERROR, "Download cancelled. Image id is null."); 75 } else { 76 CubemapBuilder.getInstance().downloadCubemapImages(img.getId()); 77 } 78 break; 79 default: 80 submit(img.getId(), StreetsideCache.Type.FULL_IMAGE, ignoreDownload); 81 break; 82 } 83 } 63 84 64 /** 65 * Downloads the picture of the given image. Does nothing when it is already 66 * in cache. 67 * 68 * @param img 69 * The image to be downloaded. 70 * @param pic 71 * The picture type to be downloaded (full quality, thumbnail or 72 * both.) 73 */ 74 public static void downloadPicture(StreetsideImage img, PICTURE pic) { 75 switch (pic) { 76 case BOTH: 77 if (new StreetsideCache(img.getId(), StreetsideCache.Type.THUMBNAIL).get() == null) 78 submit(img.getId(), StreetsideCache.Type.THUMBNAIL, ignoreDownload); 79 if (new StreetsideCache(img.getId(), StreetsideCache.Type.FULL_IMAGE).get() == null) 80 submit(img.getId(), StreetsideCache.Type.FULL_IMAGE, ignoreDownload); 81 break; 82 case THUMBNAIL: 83 submit(img.getId(), StreetsideCache.Type.THUMBNAIL, ignoreDownload); 84 break; 85 case FULL_IMAGE: 86 // not used (relic from Mapillary) 87 break; 88 case CUBEMAP: 89 if(img.getId()==null) { 90 logger.error("Download cancelled. Image id is null."); 91 } else { 92 CubemapBuilder.getInstance().downloadCubemapImages(img.getId()); 93 } 94 break; 95 default: 96 submit(img.getId(), StreetsideCache.Type.FULL_IMAGE, ignoreDownload); 97 break; 98 } 99 } 85 /** 86 * Requests the picture with the given key and quality and uses the given 87 * listener. 88 * 89 * @param key The key of the picture to be requested. 90 * @param type The quality of the picture to be requested. 91 * @param lis The listener that is going to receive the picture. 92 */ 93 public static void submit(String key, StreetsideCache.Type type, ICachedLoaderListener lis) { 94 try { 95 new StreetsideCache(key, type).submit(lis, false); 96 } catch (IOException e) { 97 LOGGER.log(Logging.LEVEL_ERROR, e.getMessage(), e); 98 } 99 } 100 100 101 /** 102 * Requests the picture with the given key and quality and uses the given 103 * listener. 104 * 105 * @param key 106 * The key of the picture to be requested. 107 * @param type 108 * The quality of the picture to be requested. 109 * @param lis 110 * The listener that is going to receive the picture. 111 */ 112 public static void submit(String key, StreetsideCache.Type type, 113 ICachedLoaderListener lis) { 114 try { 115 new StreetsideCache(key, type).submit(lis, false); 116 } catch (IOException e) { 117 logger.error(e); 118 } 119 } 101 /** 102 * Picture quality 103 */ 104 public enum PICTURE { 105 /** 106 * Thumbnail quality picture (320 p) 107 */ 108 THUMBNAIL, 109 /** 110 * Full quality picture (2048 p) 111 */ 112 FULL_IMAGE, 113 /** 114 * Both of them 115 */ 116 BOTH, 117 /** 118 * Streetside cubemap 119 */ 120 CUBEMAP 121 } 120 122 121 123 private static class IgnoreDownload implements ICachedLoaderListener { -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cache/Caches.java
r35466 r36194 5 5 import java.io.IOException; 6 6 import java.io.Serializable; 7 import java.util.logging.Logger; 7 8 8 9 import javax.swing.ImageIcon; … … 10 11 import org.apache.commons.jcs3.access.CacheAccess; 11 12 import org.apache.commons.jcs3.engine.behavior.IElementAttributes; 12 import org.apache.log4j.Logger;13 13 import org.openstreetmap.josm.data.Preferences; 14 14 import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry; … … 19 19 public final class Caches { 20 20 21 final static Logger logger = Logger.getLogger(Caches.class);21 private static final Logger LOGGER = Logger.getLogger(Caches.class.getCanonicalName()); 22 22 23 24 25 23 private Caches() { 24 // Private constructor to avoid instantiation 25 } 26 26 27 28 29 30 31 32 33 27 public static File getCacheDirectory() { 28 final File f = new File(Preferences.main().getPluginsDirectory().getPath() + "/MicrosoftStreetside/cache"); 29 if (!f.exists()) { 30 f.mkdirs(); 31 } 32 return f; 33 } 34 34 35 36 35 public abstract static class CacheProxy<K, V extends Serializable> { 36 private final CacheAccess<K, V> cache; 37 37 38 publicCacheProxy() {39 40 41 42 43 logger.warn("Could not initialize cache for " + getClass().getName(), e);44 45 46 47 38 protected CacheProxy() { 39 CacheAccess<K, V> c; 40 try { 41 c = createNewCache(); 42 } catch (IOException e) { 43 LOGGER.log(Logging.LEVEL_WARN, e, () -> "Could not initialize cache for " + getClass().getName()); 44 c = null; 45 } 46 cache = c; 47 } 48 48 49 49 protected abstract CacheAccess<K, V> createNewCache() throws IOException; 50 50 51 52 53 51 public V get(final K key) { 52 return cache == null ? null : cache.get(key); 53 } 54 54 55 56 57 58 59 60 55 public void put(final K key, final V value) { 56 if (cache != null) { 57 cache.put(key, value); 58 } 59 } 60 } 61 61 62 63 64 62 public static class ImageCache { 63 private static ImageCache instance; 64 private final CacheAccess<String, BufferedImageCacheEntry> cache; 65 65 66 67 68 69 70 71 72 73 74 75 66 public ImageCache() { 67 CacheAccess<String, BufferedImageCacheEntry> c; 68 try { 69 c = JCSCacheManager.getCache("streetside", 10, 10000, Caches.getCacheDirectory().getPath()); 70 } catch (Exception e) { 71 Logging.log(Logging.LEVEL_WARN, "Could not initialize the Streetside image cache.", e); 72 c = null; 73 } 74 cache = c; 75 } 76 76 77 public CacheAccess<String, BufferedImageCacheEntry> getCache() { 78 return cache; 79 } 77 public static ImageCache getInstance() { 78 synchronized (ImageCache.class) { 79 if (ImageCache.instance == null) { 80 ImageCache.instance = new ImageCache(); 81 } 82 return ImageCache.instance; 83 } 84 } 80 85 81 public static ImageCache getInstance() { 82 synchronized (ImageCache.class) { 83 if (ImageCache.instance == null) { 84 ImageCache.instance = new ImageCache(); 85 } 86 return ImageCache.instance; 87 } 88 } 89 } 86 public CacheAccess<String, BufferedImageCacheEntry> getCache() { 87 return cache; 88 } 89 } 90 90 91 92 93 91 public static class CubemapCache { 92 private static CubemapCache instance; 93 private final CacheAccess<String, BufferedImageCacheEntry> cache; 94 94 95 96 97 98 99 100 logger.warn("Could not initialize the Streetside cubemap cache.", e);101 102 103 104 95 public CubemapCache() { 96 CacheAccess<String, BufferedImageCacheEntry> c; 97 try { 98 c = JCSCacheManager.getCache("streetside", 10, 10000, Caches.getCacheDirectory().getPath()); 99 } catch (Exception e) { 100 LOGGER.log(Logging.LEVEL_WARN, "Could not initialize the Streetside cubemap cache.", e); 101 c = null; 102 } 103 cache = c; 104 } 105 105 106 public CacheAccess<String, BufferedImageCacheEntry> getCache() { 107 return cache; 108 } 106 public static CubemapCache getInstance() { 107 synchronized (CubemapCache.class) { 108 if (CubemapCache.instance == null) { 109 CubemapCache.instance = new CubemapCache(); 110 } 111 return CubemapCache.instance; 112 } 113 } 109 114 110 public static CubemapCache getInstance() { 111 synchronized (CubemapCache.class) { 112 if (CubemapCache.instance == null) { 113 CubemapCache.instance = new CubemapCache(); 114 } 115 return CubemapCache.instance; 116 } 117 } 118 } 115 public CacheAccess<String, BufferedImageCacheEntry> getCache() { 116 return cache; 117 } 118 } 119 119 120 121 120 public static class MapObjectIconCache extends CacheProxy<String, ImageIcon> { 121 private static CacheProxy<String, ImageIcon> instance; 122 122 123 124 125 126 127 128 129 130 123 public static CacheProxy<String, ImageIcon> getInstance() { 124 synchronized (MapObjectIconCache.class) { 125 if (MapObjectIconCache.instance == null) { 126 MapObjectIconCache.instance = new MapObjectIconCache(); 127 } 128 return MapObjectIconCache.instance; 129 } 130 } 131 131 132 133 134 135 136 132 @Override 133 protected CacheAccess<String, ImageIcon> createNewCache() throws IOException { 134 return JCSCacheManager.getCache("streetsideObjectIcons", 100, 1000, Caches.getCacheDirectory().getPath()); 135 } 136 } 137 137 138 139 138 public static class UserProfileCache extends CacheProxy<String, UserProfile> { 139 private static CacheProxy<String, UserProfile> instance; 140 140 141 142 143 144 145 146 147 148 141 public static CacheProxy<String, UserProfile> getInstance() { 142 synchronized (UserProfileCache.class) { 143 if (UserProfileCache.instance == null) { 144 UserProfileCache.instance = new UserProfileCache(); 145 } 146 return UserProfileCache.instance; 147 } 148 } 149 149 150 151 152 CacheAccess<String, UserProfile> cache = 153 JCSCacheManager.getCache("userProfile", 100, 1000,Caches.getCacheDirectory().getPath());154 155 156 157 158 159 150 @Override 151 protected CacheAccess<String, UserProfile> createNewCache() throws IOException { 152 CacheAccess<String, UserProfile> cache = JCSCacheManager.getCache("userProfile", 100, 1000, 153 Caches.getCacheDirectory().getPath()); 154 IElementAttributes atts = cache.getDefaultElementAttributes(); 155 atts.setMaxLife(604_800_000); // Sets lifetime to 7 days (604800000=1000*60*60*24*7) 156 cache.setDefaultElementAttributes(atts); 157 return cache; 158 } 159 } 160 160 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cache/StreetsideCache.java
r34412 r36194 18 18 public class StreetsideCache extends JCSCachedTileLoaderJob<String, BufferedImageCacheEntry> { 19 19 20 21 20 private final URL url; 21 private final String id; 22 22 23 /** 24 * Types of images. 25 * 26 * @author nokutu 27 */ 28 public enum Type { 29 /** Full quality image */ 30 FULL_IMAGE, 31 /** Low quality image */ 32 THUMBNAIL 33 } 23 /** 24 * Main constructor. 25 * 26 * @param id The id of the image. 27 * @param type The type of image that must be downloaded (THUMBNAIL or 28 * FULL_IMAGE). 29 */ 30 public StreetsideCache(final String id, final Type type) { 31 super(Caches.ImageCache.getInstance().getCache(), new TileJobOptions(50000, 50000, new HashMap<>(), 50000L)); 34 32 35 /** 36 * Main constructor. 37 * 38 * @param id 39 * The id of the image. 40 * @param type 41 * The type of image that must be downloaded (THUMBNAIL or 42 * FULL_IMAGE). 43 */ 44 public StreetsideCache(final String id, final Type type) { 45 super(Caches.ImageCache.getInstance().getCache(),new TileJobOptions(50000, 50000, new HashMap<String,String>(),50000l)); 33 if (id == null || type == null) { 34 this.id = null; 35 url = null; 36 } else { 37 this.id = id; 38 url = VirtualEarth.streetsideTile(id, type == Type.THUMBNAIL); 39 } 40 } 46 41 47 if (id == null || type == null) { 48 this.id = null; 49 url = null; 50 } else { 51 this.id = id; 52 url = VirtualEarth.streetsideTile(id, type == Type.THUMBNAIL); 53 } 54 } 42 @Override 43 public String getCacheKey() { 44 return id; 45 } 55 46 56 57 public String getCacheKey() {58 return id;59 47 @Override 48 public URL getUrl() { 49 return url; 50 } 60 51 61 62 public URL getUrl() {63 return url;64 52 @Override 53 protected BufferedImageCacheEntry createCacheEntry(byte[] content) { 54 return new BufferedImageCacheEntry(content); 55 } 65 56 66 @Override 67 protected BufferedImageCacheEntry createCacheEntry(byte[] content) { 68 return new BufferedImageCacheEntry(content); 69 } 57 @Override 58 protected boolean isObjectLoadable() { 59 if (cacheData == null) { 60 return false; 61 } 62 final byte[] content = cacheData.getContent(); 63 return content != null && content.length > 0; 64 } 70 65 71 @Override 72 protected boolean isObjectLoadable() { 73 if (cacheData == null) { 74 return false; 75 } 76 final byte[] content = cacheData.getContent(); 77 return content != null && content.length > 0; 78 } 66 /** 67 * Types of images. 68 * 69 * @author nokutu 70 */ 71 public enum Type { 72 /** 73 * Full quality image 74 */ 75 FULL_IMAGE, 76 /** 77 * Low quality image 78 */ 79 THUMBNAIL 80 } 79 81 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/CameraTransformer.java
r34416 r36194 11 11 public class CameraTransformer extends Group { 12 12 13 public enum RotateOrder {14 XYZ, XZY, YXZ, YZX, ZXY, ZYX15 }16 17 13 public Translate t = new Translate(); 18 14 public Translate p = new Translate(); 19 15 public Translate ip = new Translate(); 20 16 public Rotate rx = new Rotate(); 17 public Rotate ry = new Rotate(); 18 public Rotate rz = new Rotate(); 19 public Scale s = new Scale(); 20 21 21 { 22 22 rx.setAxis(Rotate.X_AXIS); 23 23 } 24 public Rotate ry = new Rotate(); 24 25 25 { 26 26 ry.setAxis(Rotate.Y_AXIS); 27 27 } 28 public Rotate rz = new Rotate(); 28 29 29 { 30 30 rz.setAxis(Rotate.Z_AXIS); 31 31 } 32 public Scale s = new Scale();33 32 34 33 public CameraTransformer() { … … 179 178 ip.setZ(0.0); 180 179 } 180 181 public enum RotateOrder { 182 XYZ, XZY, YXZ, YZX, ZXY, ZYX 183 } 181 184 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/CubemapBox.java
r34428 r36194 1 /* 2 * To change this license header, choose License Headers in Project Properties. 3 * To change this template file, choose Tools | Templates 4 * and open the template in the editor. 5 */ 6 1 // License: GPL. For details, see LICENSE file. 7 2 package org.openstreetmap.josm.plugins.streetside.cubemap; 8 3 … … 29 24 public class CubemapBox extends Group { 30 25 31 public enum CubemapBoxImageType {32 MULTIPLE, SINGLE33 }34 35 26 private final Affine affine = new Affine(); 36 37 private final ImageView front = new ImageView(), right = new ImageView(), back = new ImageView(), 38 left = new ImageView(), up = new ImageView(), down = new ImageView(); 27 private final ImageView front = new ImageView(); 28 private final ImageView right = new ImageView(); 29 private final ImageView back = new ImageView(); 30 private final ImageView left = new ImageView(); 31 private final ImageView up = new ImageView(); 32 private final ImageView down = new ImageView(); 33 private final ImageView[] views = new ImageView[] { front, right, back, left, up, down }; 34 private final Image frontImg; 35 private final Image rightImg; 36 private final Image backImg; 37 private final Image leftImg; 38 private final Image upImg; 39 private final Image downImg; 40 private final PerspectiveCamera camera; 41 private final CubemapBoxImageType imageType; 42 private Image singleImg; 43 private AnimationTimer timer; 39 44 40 45 { … … 47 52 48 53 } 49 private final ImageView[] views = new ImageView[] { front, right, back, left, up, down }; 50 51 private Image frontImg, rightImg, backImg, leftImg, upImg, downImg, singleImg; 52 53 private final PerspectiveCamera camera; 54 private AnimationTimer timer; 55 private final CubemapBoxImageType imageType; 56 57 public CubemapBox( 58 Image frontImg, Image rightImg, Image backImg, Image leftImg, Image upImg, Image downImg, double size, 59 PerspectiveCamera camera) { 54 55 public CubemapBox(Image frontImg, Image rightImg, Image backImg, Image leftImg, Image upImg, Image downImg, 56 double size, PerspectiveCamera camera) { 60 57 61 58 super(); … … 148 145 private void loadSingleImageViewports() { 149 146 layoutViews(); 150 double width = singleImg.getWidth(), height = singleImg.getHeight(); 147 double width = singleImg.getWidth(); 148 double height = singleImg.getHeight(); 151 149 152 150 // simple check to see if cells will be square … … 158 156 recalculateSize(cellSize); 159 157 160 double topx = cellSize, topy = 0, 161 162 botx = cellSize, boty = cellSize * 2, 163 164 leftx = 0, lefty = cellSize, 165 166 rightx = cellSize * 2, righty = cellSize, 167 168 fwdx = cellSize, fwdy = cellSize, 169 170 backx = cellSize * 3, backy = cellSize; 158 double topx = cellSize; 159 double topy = 0; 160 double botx = cellSize; 161 double boty = cellSize * 2; 162 double leftx = 0; 163 double lefty = cellSize; 164 double rightx = cellSize * 2; 165 double righty = cellSize; 166 double fwdx = cellSize; 167 double fwdy = cellSize; 168 double backx = cellSize * 3; 169 double backy = cellSize; 171 170 172 171 // add top padding x+, y+, width-, height … … 231 230 } 232 231 233 /* 234 * Properties 235 */ 232 public final double getSize() { 233 return size.get(); 234 } 235 236 public final void setSize(double value) { 237 size.set(value); 238 } /* 239 * Properties 240 */ 241 236 242 private final DoubleProperty size = new SimpleDoubleProperty() { 237 243 @Override … … 248 254 }; 249 255 250 public final double getSize() {251 return size.get();252 }253 254 public final void setSize(double value) {255 size.set(value);256 }257 258 256 public DoubleProperty sizeProperty() { 259 257 return size; … … 263 261 return views; 264 262 } 263 264 public enum CubemapBoxImageType { 265 MULTIPLE, SINGLE 266 } 267 265 268 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/CubemapBuilder.java
r36065 r36194 10 10 import java.util.Map; 11 11 import java.util.concurrent.Callable; 12 import java.util.concurrent.ConcurrentHashMap; 12 13 import java.util.concurrent.ExecutionException; 13 import java.util.concurrent.ConcurrentHashMap;14 14 import java.util.concurrent.ExecutorService; 15 15 import java.util.concurrent.Executors; 16 16 import java.util.concurrent.Future; 17 18 import org.apache.log4j.Logger; 17 import java.util.logging.Logger; 18 19 19 import org.openstreetmap.josm.gui.MainApplication; 20 import java.util.concurrent.ExecutionException;21 20 import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage; 22 21 import org.openstreetmap.josm.plugins.streetside.StreetsideCubemap; … … 27 26 import org.openstreetmap.josm.plugins.streetside.utils.GraphicsUtils; 28 27 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties; 28 import org.openstreetmap.josm.tools.Logging; 29 29 30 30 import javafx.scene.image.Image; … … 34 34 public class CubemapBuilder implements ITileDownloadingTaskListener, StreetsideDataListener { 35 35 36 final static Logger logger = Logger.getLogger(CubemapBuilder.class); 37 38 private static CubemapBuilder instance; 39 private StreetsideCubemap cubemap; 40 protected boolean isBuilding; 41 36 private static final Logger LOGGER = Logger.getLogger(CubemapBuilder.class.getCanonicalName()); 37 38 private static CubemapBuilder instance; 39 protected boolean isBuilding; 40 private StreetsideCubemap cubemap; 42 41 private long startTime; 43 42 44 43 private Map<String, BufferedImage> tileImages = new ConcurrentHashMap<>(); 45 44 private ExecutorService pool; 46 45 47 private int currentTileCount = 0; 46 private int currentTileCount = 0; 47 48 private CubemapBuilder() { 49 // private constructor to avoid instantiation 50 } 51 52 public static CubemapBuilder getInstance() { 53 if (instance == null) { 54 instance = new CubemapBuilder(); 55 } 56 return instance; 57 } 58 59 /** 60 * @return true, iff the singleton instance is present 61 */ 62 public static boolean hasInstance() { 63 return CubemapBuilder.instance != null; 64 } 65 66 /** 67 * Destroys the unique instance of the class. 68 */ 69 public static synchronized void destroyInstance() { 70 CubemapBuilder.instance = null; 71 } 48 72 49 73 /** … … 61 85 } 62 86 63 private CubemapBuilder() { 64 // private constructor to avoid instantiation 65 } 66 67 /** 87 /** 68 88 * Fired when any image is added to the database. 69 89 */ 70 90 @Override 71 72 73 74 75 91 public void imagesAdded() { 92 // Not implemented by the CubemapBuilder 93 } 94 95 /** 76 96 * Fired when the selected image is changed by something different from 77 97 * manually clicking on the icon. 78 98 * 79 * @param oldImage 80 * Old selected {@link StreetsideAbstractImage} 81 * @param newImage 82 * New selected {@link StreetsideAbstractImage} 83 * 99 * @param oldImage Old selected {@link StreetsideAbstractImage} 100 * @param newImage New selected {@link StreetsideAbstractImage} 84 101 * @see StreetsideDataListener 85 102 */ … … 87 104 public void selectedImageChanged(StreetsideAbstractImage oldImage, StreetsideAbstractImage newImage) { 88 105 89 90 106 startTime = System.currentTimeMillis(); 91 107 92 if (newImage != null) { 93 94 cubemap = null; 95 cubemap = new StreetsideCubemap(newImage.getId(), newImage.getLatLon(), newImage.getHe()); 96 currentTileCount = 0; 97 resetTileImages(); 98 99 // download cubemap images in different threads and then subsequently 100 // set the cubeface images in JavaFX 101 downloadCubemapImages(cubemap.getId()); 102 103 long runTime = (System.currentTimeMillis()-startTime)/1000; 104 if(StreetsideProperties.DEBUGING_ENABLED.get()) { 105 logger.debug(MessageFormat.format("Completed downloading tiles for {0} in {1} seconds.", newImage.getId() , runTime)); 106 } 107 } 108 } 109 110 public void reload(String imageId) { 111 if (cubemap != null && imageId.equals(cubemap.getId())) { 112 tileImages = new HashMap<>(); 113 downloadCubemapImages(imageId); 114 } 115 } 116 117 public void downloadCubemapImages(String imageId) { 118 ThreeSixtyDegreeViewerPanel panel360 = StreetsideViewerPanel.getThreeSixtyDegreeViewerPanel(); 119 if (panel360 != null && panel360.getScene() != panel360.getLoadingScene()) { 120 panel360.setScene(panel360.getLoadingScene()); 121 } 122 123 final int maxThreadCount = StreetsideProperties.DOWNLOAD_CUBEFACE_TILES_TOGETHER.get()?6:6 * CubemapUtils.getMaxCols() * CubemapUtils.getMaxRows(); 124 125 int fails = 0; 108 if (newImage != null) { 109 110 cubemap = null; 111 cubemap = new StreetsideCubemap(newImage.getId(), newImage.getLatLon(), newImage.getHe()); 112 currentTileCount = 0; 113 resetTileImages(); 114 115 // download cubemap images in different threads and then subsequently 116 // set the cubeface images in JavaFX 117 downloadCubemapImages(cubemap.getId()); 118 119 long runTime = (System.currentTimeMillis() - startTime) / 1000; 120 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 121 LOGGER.log(Logging.LEVEL_DEBUG, MessageFormat 122 .format("Completed downloading tiles for {0} in {1} seconds.", newImage.getId(), runTime)); 123 } 124 } 125 } 126 127 public void reload(String imageId) { 128 if (cubemap != null && imageId.equals(cubemap.getId())) { 129 tileImages = new HashMap<>(); 130 downloadCubemapImages(imageId); 131 } 132 } 133 134 public void downloadCubemapImages(String imageId) { 135 ThreeSixtyDegreeViewerPanel panel360 = StreetsideViewerPanel.getThreeSixtyDegreeViewerPanel(); 136 if (panel360 != null && panel360.getScene() != panel360.getLoadingScene()) { 137 panel360.setScene(panel360.getLoadingScene()); 138 } 139 140 final int maxThreadCount = Boolean.TRUE.equals(StreetsideProperties.DOWNLOAD_CUBEFACE_TILES_TOGETHER.get()) ? 6 141 : 6 * CubemapUtils.getMaxCols() * CubemapUtils.getMaxRows(); 142 143 int fails = 0; 126 144 127 145 // TODO: message for progress bar … … 132 150 long startTime = System.currentTimeMillis(); 133 151 134 if (CubemapBuilder.getInstance().getTileImages().keySet().size() > 0) {152 if (!CubemapBuilder.getInstance().getTileImages().keySet().isEmpty()) { 135 153 pool.shutdownNow(); 136 154 CubemapBuilder.getInstance().resetTileImages(); … … 142 160 List<Callable<List<String>>> tasks = new ArrayList<>(maxThreadCount); 143 161 144 if ( StreetsideProperties.DOWNLOAD_CUBEFACE_TILES_TOGETHER.get()) {162 if (Boolean.TRUE.equals(StreetsideProperties.DOWNLOAD_CUBEFACE_TILES_TOGETHER.get())) { 145 163 EnumSet.allOf(CubemapUtils.CubemapFaces.class).forEach(face -> { 146 String tileId = String.valueOf(imageId + face.getValue());164 String tileId = imageId + face.getValue(); 147 165 tasks.add(new TileDownloadingTask(tileId)); 148 166 }); … … 150 168 151 169 // launch 4-tiled (low-res) downloading tasks . . . 152 if ( !StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) {170 if (Boolean.FALSE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get())) { 153 171 // download all imagery for each cubeface at once 154 172 … … 158 176 for (int k = 0; k < CubemapUtils.getMaxRows(); k++) { 159 177 160 String tileId = String 161 .valueOf(imageId + CubemapUtils.getFaceNumberForCount(i) + Integer.valueOf(tileNr++).toString()); 178 String tileId = imageId + CubemapUtils.getFaceNumberForCount(i) + tileNr++; 162 179 tasks.add(new TileDownloadingTask(tileId)); 163 180 } 164 181 } 165 182 } 166 // launch 16-tiled (high-res) downloading tasks167 } else if ( StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) {183 // launch 16-tiled (high-res) downloading tasks 184 } else if (Boolean.TRUE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get())) { 168 185 169 186 for (int i = 0; i < CubemapUtils.NUM_SIDES; i++) { … … 171 188 for (int k = 0; k < CubemapUtils.getMaxRows(); k++) { 172 189 173 String tileId = String 174 .valueOf(imageId + CubemapUtils.getFaceNumberForCount(i) + String.valueOf(Integer.valueOf(j).toString() + Integer.valueOf(k).toString())); 190 String tileId = imageId + CubemapUtils.getFaceNumberForCount(i) + j + k; 175 191 tasks.add(new TileDownloadingTask(tileId)); 176 192 } … … 181 197 182 198 // execute tasks 183 184 199 MainApplication.worker.submit(() -> { 200 try { 185 201 List<Future<List<String>>> results = pool.invokeAll(tasks); 186 187 if (StreetsideProperties.DEBUGING_ENABLED.get() && results != null) {202 203 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get()) && results != null) { 188 204 for (Future<List<String>> ff : results) { 189 205 try { 190 logger.debug(MessageFormat.format("Completed tile downloading task {0} in {1} seconds.",ff.get().toString(), 191 (System.currentTimeMillis() - startTime)/1000)); 206 LOGGER.log(Logging.LEVEL_DEBUG, 207 MessageFormat.format("Completed tile downloading task {0} in {1} seconds.", 208 ff.get().toString(), (System.currentTimeMillis() - startTime) / 1000)); 192 209 } catch (ExecutionException e) { 193 logger.error(e);210 LOGGER.log(Logging.LEVEL_ERROR, e.getMessage(), e); 194 211 } 195 212 } 196 213 } 197 214 } catch (InterruptedException e) { 198 logger.error(e);199 } 200 215 LOGGER.log(Logging.LEVEL_ERROR, e.getMessage(), e); 216 } 217 }); 201 218 } catch (Exception ee) { 202 219 fails++; 203 logger.error("Error loading tile for image " + imageId); 204 ee.printStackTrace(); 220 LOGGER.log(Logging.LEVEL_ERROR, ee, () -> "Error loading tile for image " + imageId); 205 221 } 206 222 … … 208 224 long runTime = stopTime - startTime; 209 225 210 if (StreetsideProperties.DEBUGING_ENABLED.get()) { 211 logger.debug(MessageFormat.format("Tile imagery downloading tasks completed in {0} seconds.", runTime / 1000)); 226 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 227 LOGGER.log(Logging.LEVEL_DEBUG, 228 MessageFormat.format("Tile imagery downloading tasks completed in {0} seconds.", runTime / 1000)); 212 229 } 213 230 214 231 if (fails > 0) { 215 logger.error(Integer.valueOf(fails)+ " downloading tasks failed!");232 LOGGER.log(Logging.LEVEL_ERROR, fails + " downloading tasks failed!"); 216 233 } 217 234 } … … 222 239 * 223 240 * @param tileId 224 * 241 * the complete quadKey of the imagery tile, including cubeface and row/column in quaternary. 225 242 * @see TileDownloadingTask 226 243 */ … … 231 248 // and set the views in the cubemap box. 232 249 233 if (!tileId.startsWith(cubemap.getId())) {250 if (!tileId.startsWith(cubemap.getId())) { 234 251 return; 235 252 } … … 238 255 239 256 if (currentTileCount == (CubemapUtils.NUM_SIDES * CubemapUtils.getMaxCols() * CubemapUtils.getMaxRows())) { 240 if ( StreetsideProperties.DEBUGING_ENABLED.get()) {257 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 241 258 long endTime = System.currentTimeMillis(); 242 259 long runTime = (endTime - startTime) / 1000; 243 logger.debug( 244 MessageFormat.format( 245 "{0} tile images ready for building cumbemap faces for cubemap {1} in {2} seconds.", currentTileCount, 246 CubemapBuilder.getInstance().getCubemap().getId(), Long.toString(runTime)) 247 ); 260 LOGGER.log(Logging.LEVEL_DEBUG, MessageFormat.format( 261 "{0} tile images ready for building cumbemap faces for cubemap {1} in {2} seconds.", 262 currentTileCount, CubemapBuilder.getInstance().getCubemap().getId(), Long.toString(runTime))); 248 263 } 249 264 … … 258 273 * then the ImageViews of the cubemap are set with the new imagery. 259 274 * 260 * @see 261 */ 262 263 CubemapBox cmb = StreetsideViewerDialog.getInstance().getStreetsideViewerPanel().getCubemapBox();264 ImageView[] views = cmb.getViews();265 266 Image finalImages[] = new Image[CubemapUtils.NUM_SIDES]; 267 268 // build 4-tiled cubemap faces and crop buffers 269 if (!StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) { 270 for (int i = 0; i < CubemapUtils.NUM_SIDES; i++) {271 272 BufferedImage[] faceTileImages = new BufferedImage[CubemapUtils.getMaxCols() * CubemapUtils.getMaxRows()]; 273 274 for (int j = 0; j < (CubemapUtils.getMaxCols() * CubemapUtils.getMaxRows()); j++) { 275 String tileId = String.valueOf(getCubemap().getId() + CubemapUtils.getFaceNumberForCount(i) 276 + Integer.valueOf(j).toString()); 277 BufferedImage currentTile = tileImages.get(tileId);278 279 faceTileImages[j] = currentTile; 280 } 281 282 BufferedImage finalImg = GraphicsUtils.buildMultiTiledCubemapFaceImage(faceTileImages); 283 284 // rotate top cubeface 180 degrees - misalignment workaround 285 if (i == 4) { 286 finalImg = GraphicsUtils.rotateImage(finalImg); 287 } 288 finalImages[i] = GraphicsUtils.convertBufferedImage2JavaFXImage(finalImg); 289 } 290 // build 16-tiled cubemap faces and crop buffers 291 } else if (StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) { 292 for (int i = 0; i < CubemapUtils.NUM_SIDES; i++) {293 294 int tileCount = 0; 295 296 BufferedImage[] faceTileImages = new BufferedImage[StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY 297 .get() ? 16 : 4]; 298 299 for (int j = 0; j < CubemapUtils.getMaxCols(); j++) { 300 for (int k = 0; k < CubemapUtils.getMaxRows(); k++) {301 String tileId = String.valueOf(getCubemap().getId() + CubemapUtils.getFaceNumberForCount(i) 302 + CubemapUtils.convertDoubleCountNrto16TileNr( 303 String.valueOf(Integer.valueOf(j).toString() + Integer.valueOf(k).toString())));304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 275 * @see StreetsideCubemap 276 */ 277 private void buildCubemapFaces() { 278 StreetsideViewerDialog.getInstance(); 279 CubemapBox cmb = StreetsideViewerPanel.getCubemapBox(); 280 ImageView[] views = cmb.getViews(); 281 282 Image[] finalImages = new Image[CubemapUtils.NUM_SIDES]; 283 284 // build 4-tiled cubemap faces and crop buffers 285 if (Boolean.FALSE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get())) { 286 for (int i = 0; i < CubemapUtils.NUM_SIDES; i++) { 287 288 BufferedImage[] faceTileImages = new BufferedImage[CubemapUtils.getMaxCols() 289 * CubemapUtils.getMaxRows()]; 290 291 for (int j = 0; j < (CubemapUtils.getMaxCols() * CubemapUtils.getMaxRows()); j++) { 292 String tileId = getCubemap().getId() + CubemapUtils.getFaceNumberForCount(i) + j; 293 BufferedImage currentTile = tileImages.get(tileId); 294 295 faceTileImages[j] = currentTile; 296 } 297 298 BufferedImage finalImg = GraphicsUtils.buildMultiTiledCubemapFaceImage(faceTileImages); 299 300 // rotate top cubeface 180 degrees - misalignment workaround 301 if (i == 4) { 302 finalImg = GraphicsUtils.rotateImage(finalImg); 303 } 304 finalImages[i] = GraphicsUtils.convertBufferedImage2JavaFXImage(finalImg); 305 } 306 // build 16-tiled cubemap faces and crop buffers 307 } else if (Boolean.TRUE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get())) { 308 for (int i = 0; i < CubemapUtils.NUM_SIDES; i++) { 309 310 int tileCount = 0; 311 312 BufferedImage[] faceTileImages = new BufferedImage[Boolean.TRUE 313 .equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) ? 16 : 4]; 314 315 for (int j = 0; j < CubemapUtils.getMaxCols(); j++) { 316 for (int k = 0; k < CubemapUtils.getMaxRows(); k++) { 317 String tileId = getCubemap().getId() + CubemapUtils.getFaceNumberForCount(i) 318 + CubemapUtils.convertDoubleCountNrto16TileNr(j + Integer.toString(k)); 319 BufferedImage currentTile = tileImages.get(tileId); 320 faceTileImages[tileCount++] = currentTile; 321 } 322 } 323 BufferedImage finalImg = GraphicsUtils.buildMultiTiledCubemapFaceImage(faceTileImages); 324 // rotate top cubeface 180 degrees - misalignment workaround 325 if (i == 4) { 326 finalImg = GraphicsUtils.rotateImage(finalImg); 327 } 328 finalImages[i] = GraphicsUtils.convertBufferedImage2JavaFXImage(finalImg); 329 } 330 } 331 332 for (int i = 0; i < CubemapUtils.NUM_SIDES; i++) { 333 views[i].setImage(finalImages[i]); 334 } 320 335 321 336 StreetsideViewerDialog.getInstance().getStreetsideViewerPanel().revalidate(); … … 323 338 324 339 StreetsideViewerPanel.getThreeSixtyDegreeViewerPanel() 325 340 .setScene(StreetsideViewerPanel.getThreeSixtyDegreeViewerPanel().getCubemapScene()); 326 341 327 342 StreetsideViewerPanel.getThreeSixtyDegreeViewerPanel().revalidate(); … … 331 346 long runTime = (endTime - startTime) / 1000; 332 347 333 String message = MessageFormat.format("Completed downloading, assembling and setting cubemap imagery for cubemap {0} in {1} seconds.", cubemap.getId(), 334 runTime); 335 336 if (StreetsideProperties.DEBUGING_ENABLED.get()) { 337 logger.debug(message); 348 String message = MessageFormat.format( 349 "Completed downloading, assembling and setting cubemap imagery for cubemap {0} in {1} seconds.", 350 cubemap.getId(), runTime); 351 352 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 353 LOGGER.log(Logging.LEVEL_DEBUG, message); 338 354 } 339 355 … … 342 358 currentTileCount = 0; 343 359 isBuilding = false; 344 345 346 360 } 361 362 private void resetTileImages() { 347 363 tileImages = new HashMap<>(); 348 364 } 349 365 350 366 /** 351 * @return the cubemap 352 */ 353 public synchronized StreetsideCubemap getCubemap() { 354 return cubemap; 355 } 356 357 /** 358 * @param cubemap 359 * the cubemap to set 360 */ 361 public static void setCubemap(StreetsideCubemap cubemap) { 362 CubemapBuilder.getInstance().cubemap = cubemap; 363 } 364 365 public static CubemapBuilder getInstance() { 366 if (instance == null) { 367 instance = new CubemapBuilder(); 368 } 369 return instance; 370 } 371 372 /** 373 * @return true, iff the singleton instance is present 374 */ 375 public static boolean hasInstance() { 376 return CubemapBuilder.instance != null; 377 } 378 379 /** 367 * @return the cubemap 368 */ 369 public synchronized StreetsideCubemap getCubemap() { 370 return cubemap; 371 } 372 373 /** 374 * @param cubemap 375 * the cubemap to set 376 */ 377 public static void setCubemap(StreetsideCubemap cubemap) { 378 CubemapBuilder.getInstance().cubemap = cubemap; 379 } 380 381 /** 380 382 * @return the isBuilding 381 383 */ … … 383 385 return isBuilding; 384 386 } 385 386 387 /**388 * Destroys the unique instance of the class.389 */390 public static synchronized void destroyInstance() {391 CubemapBuilder.instance = null;392 }393 387 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/CubemapUtils.java
r36065 r36194 5 5 import java.util.HashMap; 6 6 import java.util.Map; 7 import java.util.logging.Logger; 7 8 import java.util.stream.Stream; 8 9 9 import org.apache.log4j.Logger;10 10 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties; 11 import org.openstreetmap.josm.tools.Logging; 11 12 12 13 public class CubemapUtils { 13 14 14 final static Logger logger = Logger.getLogger(CubemapUtils.class); 15 public static final String TEST_IMAGE_ID = "00000000"; 16 public static final int NUM_SIDES = 6; 17 private static final Logger LOGGER = Logger.getLogger(CubemapUtils.class.getCanonicalName()); 18 // numerical base for decimal conversion (quaternary in the case of Streetside) 19 private static final int NUM_BASE = 4; 20 public static Map<String[], String> directionConversion = new HashMap<>(); 21 public static Map<String, String> rowCol2StreetsideCellAddressMap = null; 22 23 // Intialize utility map for storing row to Streetside cell number conversions 24 static { 25 26 CubemapUtils.rowCol2StreetsideCellAddressMap = new HashMap<>(); 27 CubemapUtils.rowCol2StreetsideCellAddressMap.put("00", "00"); 28 CubemapUtils.rowCol2StreetsideCellAddressMap.put("01", "01"); 29 CubemapUtils.rowCol2StreetsideCellAddressMap.put("02", "10"); 30 CubemapUtils.rowCol2StreetsideCellAddressMap.put("03", "11"); 31 CubemapUtils.rowCol2StreetsideCellAddressMap.put("10", "02"); 32 CubemapUtils.rowCol2StreetsideCellAddressMap.put("11", "03"); 33 CubemapUtils.rowCol2StreetsideCellAddressMap.put("12", "12"); 34 CubemapUtils.rowCol2StreetsideCellAddressMap.put("13", "13"); 35 CubemapUtils.rowCol2StreetsideCellAddressMap.put("20", "20"); 36 CubemapUtils.rowCol2StreetsideCellAddressMap.put("21", "21"); 37 CubemapUtils.rowCol2StreetsideCellAddressMap.put("22", "30"); 38 CubemapUtils.rowCol2StreetsideCellAddressMap.put("23", "31"); 39 CubemapUtils.rowCol2StreetsideCellAddressMap.put("30", "22"); 40 CubemapUtils.rowCol2StreetsideCellAddressMap.put("31", "23"); 41 CubemapUtils.rowCol2StreetsideCellAddressMap.put("32", "32"); 42 CubemapUtils.rowCol2StreetsideCellAddressMap.put("33", "33"); 43 } 15 44 16 45 private CubemapUtils() { … … 18 47 } 19 48 20 public enum CubefaceType { 21 ONE(1), 22 FOUR(4), 23 SIXTEEN(16); 24 25 private final int value; 26 private static Map<Integer, CubefaceType> map = new HashMap<>(); 27 28 private CubefaceType(int value) { 29 this.value = value; 30 } 31 32 static { 33 for (CubefaceType cubefaceType : CubefaceType.values()) { 34 map.put(cubefaceType.value, cubefaceType); 35 } 36 } 37 38 public static CubefaceType valueOf(int cubefaceType) { 39 return map.get(cubefaceType); 40 } 41 42 public int getValue() { 43 return value; 44 } 45 } 46 47 public static enum CubemapFaces { 48 FRONT("01"), 49 RIGHT("02"), 50 BACK("03"), 51 LEFT("10"), 52 UP("11"), 53 DOWN("12"); 54 55 public static Stream<CubemapFaces> stream() { 56 return Stream.of(CubemapFaces.values()); 57 } 58 59 private final String value; 60 61 CubemapFaces(String value) { 62 this.value = value; 63 } 64 65 public String getValue() { 66 return value; 67 } 68 } 69 70 public static Map<String[],String> directionConversion = new HashMap<>(); 71 72 // numerical base for decimal conversion (quaternary in the case of Streetside) 73 private static final int NUM_BASE = 4; 74 public static final String TEST_IMAGE_ID = "00000000"; 75 public static final int NUM_SIDES = 6; 76 public static Map<String,String> rowCol2StreetsideCellAddressMap = null; 77 78 // Intialize utility map for storing row to Streetside cell number conversions 79 static { 80 81 CubemapUtils.rowCol2StreetsideCellAddressMap = new HashMap<>(); 82 CubemapUtils.rowCol2StreetsideCellAddressMap.put("00","00"); 83 CubemapUtils.rowCol2StreetsideCellAddressMap.put("01","01"); 84 CubemapUtils.rowCol2StreetsideCellAddressMap.put("02","10"); 85 CubemapUtils.rowCol2StreetsideCellAddressMap.put("03","11"); 86 CubemapUtils.rowCol2StreetsideCellAddressMap.put("10","02"); 87 CubemapUtils.rowCol2StreetsideCellAddressMap.put("11","03"); 88 CubemapUtils.rowCol2StreetsideCellAddressMap.put("12","12"); 89 CubemapUtils.rowCol2StreetsideCellAddressMap.put("13","13"); 90 CubemapUtils.rowCol2StreetsideCellAddressMap.put("20","20"); 91 CubemapUtils.rowCol2StreetsideCellAddressMap.put("21","21"); 92 CubemapUtils.rowCol2StreetsideCellAddressMap.put("22","30"); 93 CubemapUtils.rowCol2StreetsideCellAddressMap.put("23","31"); 94 CubemapUtils.rowCol2StreetsideCellAddressMap.put("30","22"); 95 CubemapUtils.rowCol2StreetsideCellAddressMap.put("31","23"); 96 CubemapUtils.rowCol2StreetsideCellAddressMap.put("32","32"); 97 CubemapUtils.rowCol2StreetsideCellAddressMap.put("33","33"); 98 } 99 100 public static int getMaxCols() { 101 return StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?4:2; 102 } 103 104 public static int getMaxRows() { 105 return getMaxCols(); 106 } 107 108 public static String convertDecimal2Quaternary(long inputNum) { 109 String res = null; 110 final StringBuilder sb = new StringBuilder(); 111 112 if (StreetsideProperties.DEBUGING_ENABLED.get()) { 113 logger.debug(MessageFormat.format("convertDecimal2Quaternary input: {0}", Long.toString(inputNum))); 114 } 115 116 while (inputNum > 0) { 117 sb.append(inputNum % CubemapUtils.NUM_BASE); 118 inputNum /= CubemapUtils.NUM_BASE; 119 } 120 121 res = sb.reverse().toString(); 122 123 if (StreetsideProperties.DEBUGING_ENABLED.get()) { 124 logger.debug(MessageFormat.format("convertDecimal2Quaternary output: {0}", res)); 125 } 126 127 return res; 128 } 129 130 public static String convertQuaternary2Decimal(String inputNum) { 131 132 final String res; 133 134 if (StreetsideProperties.DEBUGING_ENABLED.get()) { 135 logger.debug(MessageFormat.format("convertQuaternary2Decimal input: {0}", inputNum)); 136 } 137 138 int len = inputNum.length(); 49 public static int getMaxCols() { 50 return Boolean.TRUE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) ? 4 : 2; 51 } 52 53 public static int getMaxRows() { 54 return getMaxCols(); 55 } 56 57 public static String convertDecimal2Quaternary(long inputNum) { 58 String res = null; 59 final StringBuilder sb = new StringBuilder(); 60 61 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 62 LOGGER.log(Logging.LEVEL_DEBUG, 63 MessageFormat.format("convertDecimal2Quaternary input: {0}", Long.toString(inputNum))); 64 } 65 66 while (inputNum > 0) { 67 sb.append(inputNum % CubemapUtils.NUM_BASE); 68 inputNum /= CubemapUtils.NUM_BASE; 69 } 70 71 res = sb.reverse().toString(); 72 73 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 74 LOGGER.log(Logging.LEVEL_DEBUG, MessageFormat.format("convertDecimal2Quaternary output: {0}", res)); 75 } 76 77 return res; 78 } 79 80 public static String convertQuaternary2Decimal(String inputNum) { 81 82 final String res; 83 84 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 85 LOGGER.log(Logging.LEVEL_DEBUG, MessageFormat.format("convertQuaternary2Decimal input: {0}", inputNum)); 86 } 87 88 int len = inputNum.length(); 139 89 int power = 1; 140 90 int num = 0; 141 91 int i; 142 92 143 for (i = len - 1; i >= 0; i--) 144 { 145 if (Integer.parseInt(inputNum.substring(i,i+1)) >= CubemapUtils.NUM_BASE) 146 { 147 logger.error("Error converting quadkey " + inputNum + " to decimal."); 148 return "000000000"; 149 } 150 151 num += Integer.parseInt(inputNum.substring(i,i+1)) * power; 152 power = power * CubemapUtils.NUM_BASE; 153 } 154 155 res = Integer.toString(num); 156 157 if (StreetsideProperties.DEBUGING_ENABLED.get()) { 158 logger.debug(MessageFormat.format("convertQuaternary2Decimal output: {0}", res)); 159 } 160 161 return res; 162 } 163 164 public static String getFaceNumberForCount(int count) { 165 final String res; 166 167 switch (count) { 168 case 0: 169 res = CubemapFaces.FRONT.getValue(); 170 break; 171 case 1: 172 res = CubemapFaces.RIGHT.getValue(); 173 break; 174 case 2: 175 res = CubemapFaces.BACK.getValue(); 176 break; 177 case 3: 178 res = CubemapFaces.LEFT.getValue(); 179 break; 180 case 4: 181 res = CubemapFaces.UP.getValue(); 182 break; 183 case 5: 184 res = CubemapFaces.DOWN.getValue(); 185 break; 186 default: 187 res = null; 188 break; 189 } 190 return res; 191 } 192 193 public static int getTileWidth() { 194 // 4-tiled cubemap imagery has a 2-pixel overlap; 16-tiled has a 1-pixel 195 // overlap 196 if (!StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) { 197 return 255; 198 } else { 199 return 254; 200 } 201 } 202 203 public static int getTileHeight() { 204 // 4-tiled cubemap imagery has a 2-pixel overlap; 16-tiled has a 1-pixel 205 // overlap 206 if(!StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) { 207 return 255; 208 } else { 209 return 254; 210 } 211 } 212 213 public static int getCount4FaceNumber(String faceString) { 214 215 final int tileAddress; 216 217 switch (faceString) { 218 // back 219 case "03": tileAddress = 0; 220 break; 221 // down 222 case "12": tileAddress = 1; 223 break; 224 // front 225 case "01": tileAddress = 2; 226 break; 227 // left 228 case "10": tileAddress = 3; 229 break; 230 // right 231 case "02": tileAddress = 4; 232 break; 233 // up 234 case "11": tileAddress = 5; 235 break; 236 default: tileAddress = 6; 237 break; 238 } 239 240 return tileAddress; 241 } 242 243 public static String getFaceIdFromTileId(String tileId) { 244 // magic numbers - the face id is contained in the 16th and 17th positions 245 return tileId.substring(16, 18); 246 } 247 248 public static String convertDoubleCountNrto16TileNr(String countNr) { 249 String tileAddress; 250 251 switch (countNr) { 252 case "00": tileAddress = "00"; 253 break; 254 case "01": tileAddress = "01"; 255 break; 256 case "02": tileAddress = "10"; 257 break; 258 case "03": tileAddress = "11"; 259 break; 260 case "10": tileAddress = "02"; 261 break; 262 case "11": tileAddress = "03"; 263 break; 264 case "12": tileAddress = "12"; 265 break; 266 case "13": tileAddress = "13"; 267 break; 268 case "20": tileAddress = "20"; 269 break; 270 case "21": tileAddress = "21"; 271 break; 272 case "22": tileAddress = "30"; 273 break; 274 case "23": tileAddress = "31"; 275 break; 276 case "30": tileAddress = "22"; 277 break; 278 case "31": tileAddress = "23"; 279 break; 280 case "32": tileAddress = "32"; 281 break; 282 case "33": tileAddress = "33"; 283 break; 284 // shouldn't happen 285 default: tileAddress = null; 286 break; 287 } 288 289 return tileAddress; 290 } 93 for (i = len - 1; i >= 0; i--) { 94 if (Integer.parseInt(inputNum.substring(i, i + 1)) >= CubemapUtils.NUM_BASE) { 95 LOGGER.log(Logging.LEVEL_ERROR, "Error converting quadkey " + inputNum + " to decimal."); 96 return "000000000"; 97 } 98 99 num += Integer.parseInt(inputNum.substring(i, i + 1)) * power; 100 power = power * CubemapUtils.NUM_BASE; 101 } 102 103 res = Integer.toString(num); 104 105 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 106 LOGGER.log(Logging.LEVEL_DEBUG, MessageFormat.format("convertQuaternary2Decimal output: {0}", res)); 107 } 108 109 return res; 110 } 111 112 public static String getFaceNumberForCount(int count) { 113 final String res; 114 115 switch (count) { 116 case 0: 117 res = CubemapFaces.FRONT.getValue(); 118 break; 119 case 1: 120 res = CubemapFaces.RIGHT.getValue(); 121 break; 122 case 2: 123 res = CubemapFaces.BACK.getValue(); 124 break; 125 case 3: 126 res = CubemapFaces.LEFT.getValue(); 127 break; 128 case 4: 129 res = CubemapFaces.UP.getValue(); 130 break; 131 case 5: 132 res = CubemapFaces.DOWN.getValue(); 133 break; 134 default: 135 res = null; 136 break; 137 } 138 return res; 139 } 140 141 public static int getTileWidth() { 142 // 4-tiled cubemap imagery has a 2-pixel overlap; 16-tiled has a 1-pixel 143 // overlap 144 if (Boolean.FALSE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get())) { 145 return 255; 146 } else { 147 return 254; 148 } 149 } 150 151 public static int getTileHeight() { 152 // 4-tiled cubemap imagery has a 2-pixel overlap; 16-tiled has a 1-pixel 153 // overlap 154 if (Boolean.FALSE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get())) { 155 return 255; 156 } else { 157 return 254; 158 } 159 } 160 161 public static int getCount4FaceNumber(String faceString) { 162 163 final int tileAddress; 164 165 switch (faceString) { 166 // back 167 case "03": 168 tileAddress = 0; 169 break; 170 // down 171 case "12": 172 tileAddress = 1; 173 break; 174 // front 175 case "01": 176 tileAddress = 2; 177 break; 178 // left 179 case "10": 180 tileAddress = 3; 181 break; 182 // right 183 case "02": 184 tileAddress = 4; 185 break; 186 // up 187 case "11": 188 tileAddress = 5; 189 break; 190 default: 191 tileAddress = 6; 192 break; 193 } 194 195 return tileAddress; 196 } 197 198 public static String getFaceIdFromTileId(String tileId) { 199 // magic numbers - the face id is contained in the 16th and 17th positions 200 return tileId.substring(16, 18); 201 } 202 203 public static String convertDoubleCountNrto16TileNr(String countNr) { 204 String tileAddress; 205 206 switch (countNr) { 207 case "00": 208 tileAddress = "00"; 209 break; 210 case "01": 211 tileAddress = "01"; 212 break; 213 case "02": 214 tileAddress = "10"; 215 break; 216 case "03": 217 tileAddress = "11"; 218 break; 219 case "10": 220 tileAddress = "02"; 221 break; 222 case "11": 223 tileAddress = "03"; 224 break; 225 case "12": 226 tileAddress = "12"; 227 break; 228 case "13": 229 tileAddress = "13"; 230 break; 231 case "20": 232 tileAddress = "20"; 233 break; 234 case "21": 235 tileAddress = "21"; 236 break; 237 case "22": 238 tileAddress = "30"; 239 break; 240 case "23": 241 tileAddress = "31"; 242 break; 243 case "30": 244 tileAddress = "22"; 245 break; 246 case "31": 247 tileAddress = "23"; 248 break; 249 case "32": 250 tileAddress = "32"; 251 break; 252 case "33": 253 tileAddress = "33"; 254 break; 255 // shouldn't happen 256 default: 257 tileAddress = null; 258 break; 259 } 260 261 return tileAddress; 262 } 263 264 public enum CubefaceType { 265 ONE(1), FOUR(4), SIXTEEN(16); 266 267 private static final Map<Integer, CubefaceType> map = new HashMap<>(); 268 269 static { 270 for (CubefaceType cubefaceType : CubefaceType.values()) { 271 map.put(cubefaceType.value, cubefaceType); 272 } 273 } 274 275 private final int value; 276 277 CubefaceType(int value) { 278 this.value = value; 279 } 280 281 public static CubefaceType valueOf(int cubefaceType) { 282 return map.get(cubefaceType); 283 } 284 285 public int getValue() { 286 return value; 287 } 288 } 289 290 public enum CubemapFaces { 291 FRONT("01"), RIGHT("02"), BACK("03"), LEFT("10"), UP("11"), DOWN("12"); 292 293 private final String value; 294 295 CubemapFaces(String value) { 296 this.value = value; 297 } 298 299 public static Stream<CubemapFaces> stream() { 300 return Stream.of(CubemapFaces.values()); 301 } 302 303 public String getValue() { 304 return value; 305 } 306 } 291 307 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/ITileDownloadingTaskListener.java
r34428 r36194 1 // License: GPL. For details, see LICENSE file.1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.plugins.streetside.cubemap; 3 3 … … 10 10 public interface ITileDownloadingTaskListener { 11 11 12 /** 13 * Fired when a cubemap tile image is downloaded by a download worker. 14 * @param imageId image id 15 */ 16 void tileAdded(String imageId); 12 /** 13 * Fired when a cubemap tile image is downloaded by a download worker. 14 * 15 * @param imageId image id 16 */ 17 void tileAdded(String imageId); 17 18 18 19 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/TileDownloadingTask.java
r34428 r36194 10 10 import java.util.concurrent.Callable; 11 11 import java.util.concurrent.CopyOnWriteArrayList; 12 import java.util.logging.Logger; 12 13 13 14 import javax.imageio.ImageIO; 14 15 15 import org.apache.log4j.Logger;16 16 import org.openstreetmap.josm.plugins.streetside.cache.StreetsideCache; 17 17 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties; 18 18 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL; 19 20 import us.monoid.web.Resty; 19 import org.openstreetmap.josm.tools.Logging; 21 20 22 21 public class TileDownloadingTask implements Callable<List<String>> { 23 22 24 final static Logger logger = Logger.getLogger(TileDownloadingTask.class); 23 private static final Logger LOGGER = Logger.getLogger(TileDownloadingTask.class.getCanonicalName()); 24 /** 25 * Listeners of the class. 26 */ 27 private final List<ITileDownloadingTaskListener> listeners = new CopyOnWriteArrayList<>(); 28 protected CubemapBuilder cb; 29 boolean cancelled; 30 private String tileId; 31 private StreetsideCache cache; 25 32 26 private String tileId; 27 private StreetsideCache cache; 28 protected CubemapBuilder cb; 33 public TileDownloadingTask(String id) { 34 tileId = id; 35 cb = CubemapBuilder.getInstance(); 36 addListener(CubemapBuilder.getInstance()); 37 } 29 38 30 /** 31 * Listeners of the class. 32 */ 33 private final List<ITileDownloadingTaskListener> listeners = new CopyOnWriteArrayList<>(); 39 /** 40 * Adds a new listener. 41 * 42 * @param lis Listener to be added. 43 */ 44 public final void addListener(final ITileDownloadingTaskListener lis) { 45 listeners.add(lis); 46 } 34 47 35 boolean cancelled = false; 48 /** 49 * @return the tileId 50 */ 51 public String getId() { 52 return tileId; 53 } 36 54 37 public TileDownloadingTask(String id) { 38 tileId = id; 39 cb = CubemapBuilder.getInstance(); 40 addListener(CubemapBuilder.getInstance()); 41 } 55 /** 56 * @param id the tileId to set 57 */ 58 public void setId(String id) { 59 tileId = id; 60 } 42 61 43 /** 44 * Adds a new listener. 45 * 46 * @param lis Listener to be added. 47 */ 48 public final void addListener(final ITileDownloadingTaskListener lis) { 49 listeners.add(lis); 50 } 62 /** 63 * @return the cache 64 */ 65 public StreetsideCache getCache() { 66 return cache; 67 } 51 68 52 53 * @return the tileId 54 55 public String getId() {56 return tileId;57 69 /** 70 * @param cache the cache to set 71 */ 72 public void setCache(StreetsideCache cache) { 73 this.cache = cache; 74 } 58 75 59 60 * @param id the tileId to set 61 62 public void setId(String id) {63 tileId = id;64 76 /** 77 * @return the cb 78 */ 79 public CubemapBuilder getCb() { 80 return cb; 81 } 65 82 66 67 * @return the cache 68 69 public StreetsideCache getCache() {70 return cache;71 83 /** 84 * @param cb the cb to set 85 */ 86 public void setCb(CubemapBuilder cb) { 87 this.cb = cb; 88 } 72 89 73 /** 74 * @param cache the cache to set 75 */ 76 public void setCache(StreetsideCache cache) { 77 this.cache = cache; 78 } 79 80 /** 81 * @return the cb 82 */ 83 public CubemapBuilder getCb() { 84 return cb; 85 } 86 87 /** 88 * @param cb the cb to set 89 */ 90 public void setCb(CubemapBuilder cb) { 91 this.cb = cb; 92 } 93 94 /** 95 * @param cancelled the cancelled to set 96 */ 97 public void setCancelled(boolean cancelled) { 98 this.cancelled = cancelled; 99 } 90 /** 91 * @param cancelled the cancelled to set 92 */ 93 public void setCancelled(boolean cancelled) { 94 this.cancelled = cancelled; 95 } 100 96 101 97 @Override … … 104 100 List<String> res = new ArrayList<>(); 105 101 106 if ( StreetsideProperties.DOWNLOAD_CUBEFACE_TILES_TOGETHER.get()) {102 if (Boolean.TRUE.equals(StreetsideProperties.DOWNLOAD_CUBEFACE_TILES_TOGETHER.get())) { 107 103 // download all imagery for each cubeface at once 108 if ( !StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) {104 if (Boolean.FALSE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get())) { 109 105 // download low-res imagery 110 106 int tileNr = 0; 111 107 for (int j = 0; j < CubemapUtils.getMaxCols(); j++) { 112 108 for (int k = 0; k < CubemapUtils.getMaxRows(); k++) { 113 String quadKey = String.valueOf(tileId + Integer.valueOf(tileNr++).toString());109 String quadKey = tileId + tileNr++; 114 110 res.add(downloadTile(quadKey)); 115 111 } … … 119 115 for (int j = 0; j < CubemapUtils.getMaxCols(); j++) { 120 116 for (int k = 0; k < CubemapUtils.getMaxRows(); k++) { 121 String quadKey = String 122 .valueOf(tileId + String.valueOf(Integer.valueOf(j).toString() + Integer.valueOf(k).toString())); 117 String quadKey = tileId + j + k; 123 118 res.add(downloadTile(quadKey)); 124 119 } 125 120 } 126 121 } 127 // task downloads just one tile122 // task downloads just one tile 128 123 } else { 129 124 res.add(downloadTile(tileId)); … … 138 133 139 134 try { 140 img = ImageIO 141 .read(new Resty().bytes(StreetsideURL.VirtualEarth.streetsideTile(tileId, false).toExternalForm()).stream()); 135 img = ImageIO.read(StreetsideURL.VirtualEarth.streetsideTile(tileId, false)); 142 136 143 137 if (img == null) { 144 logger.error("Download of BufferedImage " + tileId + " is null!");138 LOGGER.log(Logging.LEVEL_ERROR, "Download of BufferedImage " + tileId + " is null!"); 145 139 } 146 140 … … 149 143 fireTileAdded(tileId); 150 144 151 if ( StreetsideProperties.DEBUGING_ENABLED.get()) {145 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 152 146 long endTime = System.currentTimeMillis(); 153 147 long runTime = (endTime - startTime) / 1000; 154 logger.debug(MessageFormat.format("Loaded image for {0} in {1} seconds.", tileId, runTime)); 148 LOGGER.log(Logging.LEVEL_DEBUG, 149 MessageFormat.format("Loaded image for {0} in {1} seconds.", tileId, runTime)); 155 150 } 156 151 } catch (IOException e) { 157 logger.error(MessageFormat.format("Error downloading image for tileId {0}", tileId));152 LOGGER.log(Logging.LEVEL_ERROR, MessageFormat.format("Error downloading image for tileId {0}", tileId), e); 158 153 return null; 159 154 } … … 161 156 } 162 157 163 164 165 158 private void fireTileAdded(String id) { 159 listeners.stream().filter(Objects::nonNull).forEach(lis -> lis.tileAdded(id)); 160 } 166 161 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideExportDialog.java
r34429 r36194 20 20 import org.openstreetmap.josm.plugins.streetside.StreetsideLayer; 21 21 22 23 22 /** 24 23 * GUI for exporting images. … … 30 29 31 30 private static final long serialVersionUID = -2746815082016025516L; 32 /** Button to export all downloaded images. */ 31 /** 32 * Button to export all downloaded images. 33 */ 33 34 public final JRadioButton all; 34 35 /** … … 41 42 */ 42 43 public final JRadioButton selected; 43 /** Group of button containing all the options. */ 44 /** 45 * Group of button containing all the options. 46 */ 44 47 public final ButtonGroup group; 45 48 private final JButton choose; 46 49 private final JLabel path; 47 /** File chooser. */ 50 private final JButton ok; 51 /** 52 * File chooser. 53 */ 48 54 public JFileChooser chooser; 49 private final JButton ok;50 55 51 56 /** 52 57 * Main constructor. 53 58 * 54 * @param ok 55 * The button for to OK option. 59 * @param ok The button for to OK option. 56 60 */ 57 61 public StreetsideExportDialog(JButton ok) { … … 75 79 sequence.setEnabled(StreetsideLayer.getInstance().getData().getSelectedImage() instanceof StreetsideImage); 76 80 if (StreetsideLayer.getInstance().getData().getMultiSelectedImages().isEmpty()) { 77 selected.setEnabled(false);81 selected.setEnabled(false); 78 82 } 79 83 … … 103 107 public void actionPerformed(ActionEvent e) { 104 108 chooser = new JFileChooser(); 105 chooser.setCurrentDirectory(new java.io.File(System 106 .getProperty("user.home"))); 109 chooser.setCurrentDirectory(new java.io.File(System.getProperty("user.home"))); 107 110 chooser.setDialogTitle(tr("Select a directory")); 108 111 chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); … … 121 124 * 122 125 * @author nokutu 123 *124 126 */ 125 127 public class RewriteButtonAction extends AbstractAction { 126 128 127 129 private static final long serialVersionUID = 1035332841101190301L; 128 129 private String lastPath;130 130 private final StreetsideExportDialog dlg; 131 private String lastPath; 131 132 132 133 /** 133 134 * Main constructor. 134 135 * 135 * @param dlg 136 * Parent dialog. 136 * @param dlg Parent dialog. 137 137 */ 138 138 public RewriteButtonAction(StreetsideExportDialog dlg) { … … 143 143 @Override 144 144 public void actionPerformed(ActionEvent arg0) { 145 choose 146 .setEnabled(true); 145 choose.setEnabled(true); 147 146 if (lastPath != null) { 148 147 dlg.path.setText(lastPath); -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideImageDisplay.java
r34349 r36194 33 33 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties; 34 34 35 36 35 /** 37 36 * This object is a responsible JComponent which lets you zoom and drag. It is … … 48 47 private final Collection<ImageDetection> detections = new ArrayList<>(); 49 48 50 /** The image currently displayed */ 49 /** 50 * The image currently displayed 51 */ 51 52 private volatile BufferedImage image; 52 53 … … 62 63 */ 63 64 private Rectangle selectedRect; 65 66 /** 67 * Main constructor. 68 */ 69 public StreetsideImageDisplay() { 70 ImgDisplayMouseListener mouseListener = new ImgDisplayMouseListener(); 71 addMouseListener(mouseListener); 72 addMouseWheelListener(mouseListener); 73 addMouseMotionListener(mouseListener); 74 75 StreetsideProperties.SHOW_DETECTED_SIGNS.addListener(valChanged -> repaint()); 76 } 77 78 private static Point getCenterImgCoord(Rectangle visibleRect) { 79 return new Point(visibleRect.x + visibleRect.width / 2, visibleRect.y + visibleRect.height / 2); 80 } 81 82 /** 83 * calculateDrawImageRectangle 84 * 85 * @param imgRect the part of the image that should be drawn (in image coordinates) 86 * @param compRect the part of the component where the image should be drawn (in 87 * component coordinates) 88 * @return the part of compRect with the same width/height ratio as the image 89 */ 90 private static Rectangle calculateDrawImageRectangle(Rectangle imgRect, Rectangle compRect) { 91 int x = 0; 92 int y = 0; 93 int w = compRect.width; 94 int h = compRect.height; 95 int wFact = w * imgRect.height; 96 int hFact = h * imgRect.width; 97 if (wFact != hFact) { 98 if (wFact > hFact) { 99 w = hFact / imgRect.height; 100 x = (compRect.width - w) / 2; 101 } else { 102 h = wFact / imgRect.width; 103 y = (compRect.height - h) / 2; 104 } 105 } 106 return new Rectangle(x + compRect.x, y + compRect.y, w, h); 107 } 108 109 private static void checkVisibleRectPos(Image image, Rectangle visibleRect) { 110 if (visibleRect.x < 0) { 111 visibleRect.x = 0; 112 } 113 if (visibleRect.y < 0) { 114 visibleRect.y = 0; 115 } 116 if (visibleRect.x + visibleRect.width > image.getWidth(null)) { 117 visibleRect.x = image.getWidth(null) - visibleRect.width; 118 } 119 if (visibleRect.y + visibleRect.height > image.getHeight(null)) { 120 visibleRect.y = image.getHeight(null) - visibleRect.height; 121 } 122 } 123 124 private static void checkVisibleRectSize(Image image, Rectangle visibleRect) { 125 if (visibleRect.width > image.getWidth(null)) { 126 visibleRect.width = image.getWidth(null); 127 } 128 if (visibleRect.height > image.getHeight(null)) { 129 visibleRect.height = image.getHeight(null); 130 } 131 } 132 133 /** 134 * Sets a new picture to be displayed. 135 * 136 * @param image The picture to be displayed. 137 * @param detections image detections 138 */ 139 public void setImage(BufferedImage image, Collection<ImageDetection> detections) { 140 synchronized (this) { 141 this.image = image; 142 this.detections.clear(); 143 if (detections != null) { 144 this.detections.addAll(detections); 145 } 146 selectedRect = null; 147 if (image != null) 148 visibleRect = new Rectangle(0, 0, image.getWidth(null), image.getHeight(null)); 149 } 150 repaint(); 151 } 152 153 /** 154 * Returns the picture that is being displayed 155 * 156 * @return The picture that is being displayed. 157 */ 158 public BufferedImage getImage() { 159 return image; 160 } 161 162 /** 163 * Paints the visible part of the picture. 164 */ 165 @Override 166 public void paintComponent(Graphics g) { 167 Image image; 168 Rectangle visibleRect; 169 synchronized (this) { 170 image = this.image; 171 visibleRect = this.visibleRect; 172 } 173 if (image == null) { 174 g.setColor(Color.black); 175 String noImageStr = StreetsideLayer.hasInstance() ? tr("No image selected") 176 : tr("Press \"{0}\" to download images", StreetsideDownloadAction.SHORTCUT.getKeyText()); 177 Rectangle2D noImageSize = g.getFontMetrics(g.getFont()).getStringBounds(noImageStr, g); 178 Dimension size = getSize(); 179 g.drawString(noImageStr, (int) ((size.width - noImageSize.getWidth()) / 2), 180 (int) ((size.height - noImageSize.getHeight()) / 2)); 181 } else { 182 Rectangle target = calculateDrawImageRectangle(visibleRect); 183 g.drawImage(image, target.x, target.y, target.x + target.width, target.y + target.height, visibleRect.x, 184 visibleRect.y, visibleRect.x + visibleRect.width, visibleRect.y + visibleRect.height, null); 185 if (selectedRect != null) { 186 Point topLeft = img2compCoord(visibleRect, selectedRect.x, selectedRect.y); 187 Point bottomRight = img2compCoord(visibleRect, selectedRect.x + selectedRect.width, 188 selectedRect.y + selectedRect.height); 189 g.setColor(new Color(128, 128, 128, 180)); 190 g.fillRect(target.x, target.y, target.width, topLeft.y - target.y); 191 g.fillRect(target.x, target.y, topLeft.x - target.x, target.height); 192 g.fillRect(bottomRight.x, target.y, target.x + target.width - bottomRight.x, target.height); 193 g.fillRect(target.x, bottomRight.y, target.width, target.y + target.height - bottomRight.y); 194 g.setColor(Color.black); 195 g.drawRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x, bottomRight.y - topLeft.y); 196 } 197 198 if (Boolean.TRUE.equals(StreetsideProperties.SHOW_DETECTED_SIGNS.get())) { 199 Point upperLeft = img2compCoord(visibleRect, 0, 0); 200 Point lowerRight = img2compCoord(visibleRect, getImage().getWidth(), getImage().getHeight()); 201 202 // Transformation, which can convert you a Shape relative to the unit square to a Shape relative to the Component 203 AffineTransform unit2compTransform = AffineTransform.getTranslateInstance(upperLeft.getX(), 204 upperLeft.getY()); 205 unit2compTransform.concatenate(AffineTransform.getScaleInstance(lowerRight.getX() - upperLeft.getX(), 206 lowerRight.getY() - upperLeft.getY())); 207 208 final Graphics2D g2d = (Graphics2D) g; 209 g2d.setStroke(new BasicStroke(2)); 210 for (ImageDetection d : detections) { 211 final Shape shape = d.getShape().createTransformedShape(unit2compTransform); 212 g2d.setColor(d.isTrafficSign() ? StreetsideColorScheme.IMAGEDETECTION_TRAFFICSIGN 213 : StreetsideColorScheme.IMAGEDETECTION_UNKNOWN); 214 g2d.draw(shape); 215 if (d.isTrafficSign()) { 216 g2d.drawImage(MapObject.getIcon(d.getValue()).getImage(), shape.getBounds().x, 217 shape.getBounds().y, shape.getBounds().width, shape.getBounds().height, null); 218 } 219 } 220 } 221 } 222 } 223 224 private Point img2compCoord(Rectangle visibleRect, int xImg, int yImg) { 225 Rectangle drawRect = calculateDrawImageRectangle(visibleRect); 226 return new Point(drawRect.x + ((xImg - visibleRect.x) * drawRect.width) / visibleRect.width, 227 drawRect.y + ((yImg - visibleRect.y) * drawRect.height) / visibleRect.height); 228 } 229 230 private Point comp2imgCoord(Rectangle visibleRect, int xComp, int yComp) { 231 Rectangle drawRect = calculateDrawImageRectangle(visibleRect); 232 return new Point(visibleRect.x + ((xComp - drawRect.x) * visibleRect.width) / drawRect.width, 233 visibleRect.y + ((yComp - drawRect.y) * visibleRect.height) / drawRect.height); 234 } 235 236 private Rectangle calculateDrawImageRectangle(Rectangle visibleRect) { 237 return calculateDrawImageRectangle(visibleRect, new Rectangle(0, 0, getSize().width, getSize().height)); 238 } 239 240 /** 241 * Zooms to 1:1 and, if it is already in 1:1, to best fit. 242 */ 243 public void zoomBestFitOrOne() { 244 Image image; 245 Rectangle visibleRect; 246 synchronized (this) { 247 image = this.image; 248 visibleRect = this.visibleRect; 249 } 250 if (image == null) 251 return; 252 if (visibleRect.width != image.getWidth(null) || visibleRect.height != image.getHeight(null)) { 253 // The display is not at best fit. => Zoom to best fit 254 visibleRect = new Rectangle(0, 0, image.getWidth(null), image.getHeight(null)); 255 } else { 256 // The display is at best fit => zoom to 1:1 257 Point center = getCenterImgCoord(visibleRect); 258 visibleRect = new Rectangle(center.x - getWidth() / 2, center.y - getHeight() / 2, getWidth(), getHeight()); 259 checkVisibleRectPos(image, visibleRect); 260 } 261 synchronized (this) { 262 this.visibleRect = visibleRect; 263 } 264 repaint(); 265 } 64 266 65 267 private class ImgDisplayMouseListener implements MouseListener, MouseWheelListener, MouseMotionListener { … … 121 323 // cursor doesn't move on the image. 122 324 Rectangle drawRect = calculateDrawImageRectangle(visibleRect); 123 visibleRect.x = mousePointInImg.x 124 + ((drawRect.x - e.getX()) * visibleRect.width) / drawRect.width; 125 visibleRect.y = mousePointInImg.y 126 + ((drawRect.y - e.getY()) * visibleRect.height) / drawRect.height; 325 visibleRect.x = mousePointInImg.x + ((drawRect.x - e.getX()) * visibleRect.width) / drawRect.width; 326 visibleRect.y = mousePointInImg.y + ((drawRect.y - e.getY()) * visibleRect.height) / drawRect.height; 127 327 // The position is also limited by the image size 128 328 checkVisibleRectPos(image, visibleRect); … … 134 334 } 135 335 136 /** Center the display on the point that has been clicked */ 336 /** 337 * Center the display on the point that has been clicked 338 */ 137 339 @Override 138 340 public void mouseClicked(MouseEvent e) { … … 146 348 if (image != null && Math.min(getSize().getWidth(), getSize().getHeight()) > 0) { 147 349 if (e.getButton() == StreetsideProperties.PICTURE_OPTION_BUTTON.get()) { 148 if (!StreetsideImageDisplay.this.visibleRect.equals(new Rectangle(0, 0, image.getWidth(null), image.getHeight(null)))) { 350 if (!StreetsideImageDisplay.this.visibleRect 351 .equals(new Rectangle(0, 0, image.getWidth(null), image.getHeight(null)))) { 149 352 // Zooms to 1:1 150 StreetsideImageDisplay.this.visibleRect = new Rectangle(0, 0, 151 image.get Width(null), image.getHeight(null));353 StreetsideImageDisplay.this.visibleRect = new Rectangle(0, 0, image.getWidth(null), 354 image.getHeight(null)); 152 355 } else { 153 356 // Zooms to best fit. 154 StreetsideImageDisplay.this.visibleRect = new Rectangle( 155 0, 357 StreetsideImageDisplay.this.visibleRect = new Rectangle(0, 156 358 (image.getHeight(null) - (image.getWidth(null) * getHeight()) / getWidth()) / 2, 157 image.getWidth(null), 158 (image.getWidth(null) * getHeight()) / getWidth() 159 ); 359 image.getWidth(null), (image.getWidth(null) * getHeight()) / getWidth()); 160 360 } 161 361 StreetsideImageDisplay.this.repaint(); … … 240 440 Point p = comp2imgCoord(visibleRect, e.getX(), e.getY()); 241 441 checkPointInVisibleRect(p, visibleRect); 242 Rectangle rect = new Rectangle(p.x < mousePointInImg.x ? p.x 243 : mousePointInImg.x, p.y < mousePointInImg.y ? p.y 244 : mousePointInImg.y, p.x < mousePointInImg.x ? mousePointInImg.x 245 - p.x : p.x - mousePointInImg.x, 246 p.y < mousePointInImg.y ? mousePointInImg.y - p.y : p.y 247 - mousePointInImg.y); 442 Rectangle rect = new Rectangle(p.x < mousePointInImg.x ? p.x : mousePointInImg.x, 443 p.y < mousePointInImg.y ? p.y : mousePointInImg.y, 444 p.x < mousePointInImg.x ? mousePointInImg.x - p.x : p.x - mousePointInImg.x, 445 p.y < mousePointInImg.y ? mousePointInImg.y - p.y : p.y - mousePointInImg.y); 248 446 checkVisibleRectSize(image, rect); 249 447 checkVisibleRectPos(image, rect); … … 273 471 // Check that the zoom doesn't exceed 2:1 274 472 if (selectedRect.width < getSize().width / 2) { 275 473 selectedRect.width = getSize().width / 2; 276 474 } 277 475 if (selectedRect.height < getSize().height / 2) { 278 476 selectedRect.height = getSize().height / 2; 279 477 } 280 478 // Set the same ratio for the visible rectangle and the display … … 289 487 // Keep the center of the selection 290 488 if (selectedRect.width != oldWidth) { 291 489 selectedRect.x -= (selectedRect.width - oldWidth) / 2; 292 490 } 293 491 if (selectedRect.height != oldHeight) { 294 492 selectedRect.y -= (selectedRect.height - oldHeight) / 2; 295 493 } 296 494 checkVisibleRectSize(image, selectedRect); … … 334 532 } 335 533 } 336 337 /**338 * Main constructor.339 */340 public StreetsideImageDisplay() {341 ImgDisplayMouseListener mouseListener = new ImgDisplayMouseListener();342 addMouseListener(mouseListener);343 addMouseWheelListener(mouseListener);344 addMouseMotionListener(mouseListener);345 346 StreetsideProperties.SHOW_DETECTED_SIGNS.addListener(valChanged -> repaint());347 }348 349 /**350 * Sets a new picture to be displayed.351 *352 * @param image The picture to be displayed.353 * @param detections image detections354 */355 public void setImage(BufferedImage image, Collection<ImageDetection> detections) {356 synchronized (this) {357 this.image = image;358 this.detections.clear();359 if (detections != null) {360 this.detections.addAll(detections);361 }362 selectedRect = null;363 if (image != null)364 visibleRect = new Rectangle(0, 0, image.getWidth(null),365 image.getHeight(null));366 }367 repaint();368 }369 370 /**371 * Returns the picture that is being displayed372 *373 * @return The picture that is being displayed.374 */375 public BufferedImage getImage() {376 return image;377 }378 379 /**380 * Paints the visible part of the picture.381 */382 @Override383 public void paintComponent(Graphics g) {384 Image image;385 Rectangle visibleRect;386 synchronized (this) {387 image = this.image;388 visibleRect = this.visibleRect;389 }390 if (image == null) {391 g.setColor(Color.black);392 String noImageStr = StreetsideLayer.hasInstance() ? tr("No image selected") : tr("Press \"{0}\" to download images", StreetsideDownloadAction.SHORTCUT.getKeyText());393 Rectangle2D noImageSize = g.getFontMetrics(g.getFont()).getStringBounds(394 noImageStr, g);395 Dimension size = getSize();396 g.drawString(noImageStr,397 (int) ((size.width - noImageSize.getWidth()) / 2),398 (int) ((size.height - noImageSize.getHeight()) / 2));399 } else {400 Rectangle target = calculateDrawImageRectangle(visibleRect);401 g.drawImage(image, target.x, target.y, target.x + target.width, target.y402 + target.height, visibleRect.x, visibleRect.y, visibleRect.x403 + visibleRect.width, visibleRect.y + visibleRect.height, null);404 if (selectedRect != null) {405 Point topLeft = img2compCoord(visibleRect, selectedRect.x,406 selectedRect.y);407 Point bottomRight = img2compCoord(visibleRect, selectedRect.x408 + selectedRect.width, selectedRect.y + selectedRect.height);409 g.setColor(new Color(128, 128, 128, 180));410 g.fillRect(target.x, target.y, target.width, topLeft.y - target.y);411 g.fillRect(target.x, target.y, topLeft.x - target.x, target.height);412 g.fillRect(bottomRight.x, target.y, target.x + target.width413 - bottomRight.x, target.height);414 g.fillRect(target.x, bottomRight.y, target.width, target.y415 + target.height - bottomRight.y);416 g.setColor(Color.black);417 g.drawRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x,418 bottomRight.y - topLeft.y);419 }420 421 if (StreetsideProperties.SHOW_DETECTED_SIGNS.get()) {422 Point upperLeft = img2compCoord(visibleRect, 0, 0);423 Point lowerRight = img2compCoord(visibleRect, getImage().getWidth(), getImage().getHeight());424 425 // Transformation, which can convert you a Shape relative to the unit square to a Shape relative to the Component426 AffineTransform unit2compTransform = AffineTransform.getTranslateInstance(upperLeft.getX(), upperLeft.getY());427 unit2compTransform.concatenate(AffineTransform.getScaleInstance(lowerRight.getX() - upperLeft.getX(), lowerRight.getY() - upperLeft.getY()));428 429 final Graphics2D g2d = (Graphics2D) g;430 g2d.setStroke(new BasicStroke(2));431 for (ImageDetection d : detections) {432 final Shape shape = d.getShape().createTransformedShape(unit2compTransform);433 g2d.setColor(d.isTrafficSign() ? StreetsideColorScheme.IMAGEDETECTION_TRAFFICSIGN : StreetsideColorScheme.IMAGEDETECTION_UNKNOWN);434 g2d.draw(shape);435 if (d.isTrafficSign()) {436 g2d.drawImage(437 MapObject.getIcon(d.getValue()).getImage(),438 shape.getBounds().x, shape.getBounds().y,439 shape.getBounds().width, shape.getBounds().height,440 null441 );442 }443 }444 }445 }446 }447 448 private Point img2compCoord(Rectangle visibleRect, int xImg, int yImg) {449 Rectangle drawRect = calculateDrawImageRectangle(visibleRect);450 return new Point(drawRect.x + ((xImg - visibleRect.x) * drawRect.width)451 / visibleRect.width, drawRect.y452 + ((yImg - visibleRect.y) * drawRect.height) / visibleRect.height);453 }454 455 private Point comp2imgCoord(Rectangle visibleRect, int xComp, int yComp) {456 Rectangle drawRect = calculateDrawImageRectangle(visibleRect);457 return new Point(458 visibleRect.x + ((xComp - drawRect.x) * visibleRect.width) / drawRect.width,459 visibleRect.y + ((yComp - drawRect.y) * visibleRect.height) / drawRect.height460 );461 }462 463 private static Point getCenterImgCoord(Rectangle visibleRect) {464 return new Point(visibleRect.x + visibleRect.width / 2, visibleRect.y + visibleRect.height / 2);465 }466 467 private Rectangle calculateDrawImageRectangle(Rectangle visibleRect) {468 return calculateDrawImageRectangle(visibleRect, new Rectangle(0, 0, getSize().width, getSize().height));469 }470 471 /**472 * calculateDrawImageRectangle473 *474 * @param imgRect475 * the part of the image that should be drawn (in image coordinates)476 * @param compRect477 * the part of the component where the image should be drawn (in478 * component coordinates)479 * @return the part of compRect with the same width/height ratio as the image480 */481 private static Rectangle calculateDrawImageRectangle(Rectangle imgRect, Rectangle compRect) {482 int x = 0;483 int y = 0;484 int w = compRect.width;485 int h = compRect.height;486 int wFact = w * imgRect.height;487 int hFact = h * imgRect.width;488 if (wFact != hFact) {489 if (wFact > hFact) {490 w = hFact / imgRect.height;491 x = (compRect.width - w) / 2;492 } else {493 h = wFact / imgRect.width;494 y = (compRect.height - h) / 2;495 }496 }497 return new Rectangle(x + compRect.x, y + compRect.y, w, h);498 }499 500 /**501 * Zooms to 1:1 and, if it is already in 1:1, to best fit.502 */503 public void zoomBestFitOrOne() {504 Image image;505 Rectangle visibleRect;506 synchronized (this) {507 image = this.image;508 visibleRect = this.visibleRect;509 }510 if (image == null)511 return;512 if (visibleRect.width != image.getWidth(null)513 || visibleRect.height != image.getHeight(null)) {514 // The display is not at best fit. => Zoom to best fit515 visibleRect = new Rectangle(0, 0, image.getWidth(null),516 image.getHeight(null));517 } else {518 // The display is at best fit => zoom to 1:1519 Point center = getCenterImgCoord(visibleRect);520 visibleRect = new Rectangle(center.x - getWidth() / 2, center.y521 - getHeight() / 2, getWidth(), getHeight());522 checkVisibleRectPos(image, visibleRect);523 }524 synchronized (this) {525 this.visibleRect = visibleRect;526 }527 repaint();528 }529 530 private static void checkVisibleRectPos(Image image, Rectangle visibleRect) {531 if (visibleRect.x < 0) {532 visibleRect.x = 0;533 }534 if (visibleRect.y < 0) {535 visibleRect.y = 0;536 }537 if (visibleRect.x + visibleRect.width > image.getWidth(null)) {538 visibleRect.x = image.getWidth(null) - visibleRect.width;539 }540 if (visibleRect.y + visibleRect.height > image.getHeight(null)) {541 visibleRect.y = image.getHeight(null) - visibleRect.height;542 }543 }544 545 private static void checkVisibleRectSize(Image image, Rectangle visibleRect) {546 if (visibleRect.width > image.getWidth(null)) {547 visibleRect.width = image.getWidth(null);548 }549 if (visibleRect.height > image.getHeight(null)) {550 visibleRect.height = image.getHeight(null);551 }552 }553 534 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideImageTreeCellRenderer.java
r34317 r36194 20 20 21 21 @Override 22 public Component getTreeCellRendererComponent( 23 JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus 24 ) { 22 public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, 23 int row, boolean hasFocus) { 25 24 super.getTreeCellRendererComponent(tree, value.toString(), sel, expanded, leaf, row, hasFocus); 26 25 setIcon(ICON); -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideMainDialog.java
r35202 r36194 12 12 import java.util.Arrays; 13 13 import java.util.List; 14 import java.util.logging.Logger; 14 15 15 16 import javax.imageio.ImageIO; … … 20 21 import javax.swing.SwingUtilities; 21 22 22 import org.apache.log4j.Logger;23 23 import org.openstreetmap.josm.data.cache.CacheEntry; 24 24 import org.openstreetmap.josm.data.cache.CacheEntryAttributes; … … 38 38 import org.openstreetmap.josm.tools.I18n; 39 39 import org.openstreetmap.josm.tools.ImageProvider; 40 import org.openstreetmap.josm.tools.Logging; 40 41 41 42 /** … … 45 46 * @author renerr18 46 47 */ 47 public final class StreetsideMainDialog extends ToggleDialog implements 48 ICachedLoaderListener, StreetsideDataListener { 49 50 private static final long serialVersionUID = 2645654786827812861L; 51 52 final static Logger logger = Logger.getLogger(StreetsideMainDialog.class); 48 public final class StreetsideMainDialog extends ToggleDialog implements ICachedLoaderListener, StreetsideDataListener { 53 49 54 50 public static final String BASE_TITLE = I18n.marktr("Microsoft Streetside image"); 55 56 private static final String MESSAGE_SEPARATOR = " — "; 57 58 private static StreetsideMainDialog instance; 59 60 private volatile StreetsideAbstractImage image; 61 62 private final SideButton nextButton = new SideButton(new NextPictureAction()); 51 private static final long serialVersionUID = 2645654786827812861L; 52 private static final Logger LOGGER = Logger.getLogger(StreetsideMainDialog.class.getCanonicalName()); 53 private static final String MESSAGE_SEPARATOR = " — "; 54 55 private static StreetsideMainDialog instance; 56 /** 57 * Button used to jump to the image following the red line 58 */ 59 public final SideButton redButton = new SideButton(new RedAction()); 60 /** 61 * Button used to jump to the image following the blue line 62 */ 63 public final SideButton blueButton = new SideButton(new BlueAction()); 64 private final SideButton nextButton = new SideButton(new NextPictureAction()); 63 65 private final SideButton previousButton = new SideButton(new PreviousPictureAction()); 64 /**65 * Button used to jump to the image following the red line66 */67 public final SideButton redButton = new SideButton(new RedAction());68 /**69 * Button used to jump to the image following the blue line70 */71 public final SideButton blueButton = new SideButton(new BlueAction());72 73 66 private final SideButton playButton = new SideButton(new PlayAction()); 74 67 private final SideButton pauseButton = new SideButton(new PauseAction()); 75 68 private final SideButton stopButton = new SideButton(new StopAction()); 76 69 /** 70 * Object containing the shown image and that handles zoom and drag 71 */ 72 public StreetsideImageDisplay streetsideImageDisplay; 73 public StreetsideCache thumbnailCache; 74 private volatile StreetsideAbstractImage image; 77 75 private ImageInfoHelpPopup imageInfoHelp; 78 79 /** 80 * Buttons mode. 81 * 82 * @author nokutu 83 */ 84 public enum MODE { 85 /** 86 * Standard mode to view pictures. 87 */ 88 NORMAL, 89 /** 90 * Mode when in walk. 91 */ 92 WALK 93 } 94 95 /** 96 * Object containing the shown image and that handles zoom and drag 97 */ 98 public StreetsideImageDisplay streetsideImageDisplay; 99 100 private StreetsideCache imageCache; 101 public StreetsideCache thumbnailCache; 102 103 private StreetsideMainDialog() { 104 super(I18n.tr(StreetsideMainDialog.BASE_TITLE), "streetside-main", I18n.tr("Open Streetside window"), null, 200, 105 true, StreetsidePreferenceSetting.class); 106 addShortcuts(); 107 108 streetsideImageDisplay = new StreetsideImageDisplay(); 109 110 blueButton.setForeground(Color.BLUE); 76 private StreetsideCache imageCache; 77 78 private StreetsideMainDialog() { 79 super(I18n.tr(StreetsideMainDialog.BASE_TITLE), "streetside-main", I18n.tr("Open Streetside window"), null, 200, 80 true, StreetsidePreferenceSetting.class); 81 addShortcuts(); 82 83 streetsideImageDisplay = new StreetsideImageDisplay(); 84 85 blueButton.setForeground(Color.BLUE); 111 86 redButton.setForeground(Color.RED); 112 87 113 setMode(MODE.NORMAL); 114 } 115 116 /** 117 * Adds the shortcuts to the buttons. 118 */ 88 setMode(MODE.NORMAL); 89 } 90 91 /** 92 * Returns the unique instance of the class. 93 * 94 * @return The unique instance of the class. 95 */ 96 public static synchronized StreetsideMainDialog getInstance() { 97 if (StreetsideMainDialog.instance == null) { 98 StreetsideMainDialog.instance = new StreetsideMainDialog(); 99 } 100 return StreetsideMainDialog.instance; 101 } 102 103 /** 104 * @return true, iff the singleton instance is present 105 */ 106 public static boolean hasInstance() { 107 return StreetsideMainDialog.instance != null; 108 } 109 110 /** 111 * Destroys the unique instance of the class. 112 */ 113 public static synchronized void destroyInstance() { 114 StreetsideMainDialog.instance = null; 115 } 116 117 /** 118 * Adds the shortcuts to the buttons. 119 */ 119 120 private void addShortcuts() { 120 121 nextButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("PAGE_DOWN"), "next"); 121 122 nextButton.getActionMap().put("next", new NextPictureAction()); 122 previousButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("PAGE_UP"), "previous"); 123 previousButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("PAGE_UP"), 124 "previous"); 123 125 previousButton.getActionMap().put("previous", new PreviousPictureAction()); 124 blueButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control PAGE_UP"), "blue"); 126 blueButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control PAGE_UP"), 127 "blue"); 125 128 blueButton.getActionMap().put("blue", new BlueAction()); 126 redButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control PAGE_DOWN"), "red"); 129 redButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control PAGE_DOWN"), 130 "red"); 127 131 redButton.getActionMap().put("red", new RedAction()); 128 132 } 129 133 130 /** 131 * Returns the unique instance of the class. 132 * 133 * @return The unique instance of the class. 134 */ 135 public static synchronized StreetsideMainDialog getInstance() { 136 if (StreetsideMainDialog.instance == null) { 137 StreetsideMainDialog.instance = new StreetsideMainDialog(); 138 } 139 return StreetsideMainDialog.instance; 140 } 141 142 /** 143 * @return true, iff the singleton instance is present 144 */ 145 public static boolean hasInstance() { 146 return StreetsideMainDialog.instance != null; 147 } 148 149 public synchronized void setImageInfoHelp(ImageInfoHelpPopup popup) { 150 imageInfoHelp = popup; 151 } 152 153 /** 154 * Sets a new mode for the dialog. 155 * 156 * @param mode The mode to be set. Must not be {@code null}. 157 */ 158 public void setMode(MODE mode) { 159 switch (mode) { 160 case WALK: 161 createLayout( 162 streetsideImageDisplay, 163 Arrays.asList(playButton, pauseButton, stopButton) 164 ); 134 public synchronized void setImageInfoHelp(ImageInfoHelpPopup popup) { 135 imageInfoHelp = popup; 136 } 137 138 /** 139 * Sets a new mode for the dialog. 140 * 141 * @param mode The mode to be set. Must not be {@code null}. 142 */ 143 public void setMode(MODE mode) { 144 switch (mode) { 145 case WALK: 146 createLayout(streetsideImageDisplay, Arrays.asList(playButton, pauseButton, stopButton)); 165 147 break; 166 148 case NORMAL: 167 149 default: 168 createLayout( 169 streetsideImageDisplay, 170 Arrays.asList(blueButton, previousButton, nextButton, redButton) 171 ); 150 createLayout(streetsideImageDisplay, Arrays.asList(blueButton, previousButton, nextButton, redButton)); 172 151 break; 173 174 175 if (MODE.NORMAL .equals(mode)) {152 } 153 disableAllButtons(); 154 if (MODE.NORMAL == mode) { 176 155 updateImage(); 177 156 } 178 157 revalidate(); 179 158 repaint(); 180 } 181 182 /** 183 * Destroys the unique instance of the class. 184 */ 185 public static synchronized void destroyInstance() { 186 StreetsideMainDialog.instance = null; 187 } 188 189 /** 190 * Downloads the full quality picture of the selected StreetsideImage and sets 191 * in the StreetsideImageDisplay object. 192 */ 193 public synchronized void updateImage() { 194 updateImage(true); 195 } 196 197 /** 198 * Downloads the picture of the selected StreetsideImage and sets in the 199 * StreetsideImageDisplay object. 200 * 201 * @param fullQuality If the full quality picture must be downloaded or just the 202 * thumbnail. 203 */ 204 public synchronized void updateImage(boolean fullQuality) { 205 if (!SwingUtilities.isEventDispatchThread()) { 206 SwingUtilities.invokeLater(this::updateImage); 207 } else { 208 if (!StreetsideLayer.hasInstance()) { 209 return; 210 } 211 if (image == null) { 212 streetsideImageDisplay.setImage(null, null); 213 setTitle(I18n.tr(StreetsideMainDialog.BASE_TITLE)); 214 return; 215 } 216 217 if (imageInfoHelp != null && StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.get() > 0 && imageInfoHelp.showPopup()) { 218 // Count down the number of times the popup will be displayed 219 StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.put(StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.get() - 1); 220 } 221 222 if (image instanceof StreetsideImage) { 223 final StreetsideImage streetsideImage = (StreetsideImage) image; 224 // Downloads the thumbnail. 225 streetsideImageDisplay.setImage(null, null); 226 if (thumbnailCache != null) { 227 thumbnailCache.cancelOutstandingTasks(); 228 } 229 thumbnailCache = new StreetsideCache(streetsideImage.getId(), 230 StreetsideCache.Type.THUMBNAIL); 231 try { 232 thumbnailCache.submit(this, false); 233 } catch (final IOException e) { 234 logger.error(e); 235 } 236 237 // Downloads the full resolution image. 238 if (fullQuality || new StreetsideCache(streetsideImage.getId(), 239 StreetsideCache.Type.FULL_IMAGE).get() != null) { 240 if (imageCache != null) { 241 imageCache.cancelOutstandingTasks(); 242 } 243 imageCache = new StreetsideCache(streetsideImage.getId(), 244 StreetsideCache.Type.FULL_IMAGE); 245 try { 246 imageCache.submit(this, false); 247 } catch (final IOException e) { 248 logger.error(e); 249 } 250 } 251 } 252 updateTitle(); 253 } 254 } 255 256 /** 159 } 160 161 /** 162 * Downloads the full quality picture of the selected StreetsideImage and sets 163 * in the StreetsideImageDisplay object. 164 */ 165 public synchronized void updateImage() { 166 updateImage(true); 167 } 168 169 /** 170 * Downloads the picture of the selected StreetsideImage and sets in the 171 * StreetsideImageDisplay object. 172 * 173 * @param fullQuality If the full quality picture must be downloaded or just the 174 * thumbnail. 175 */ 176 public synchronized void updateImage(boolean fullQuality) { 177 if (!SwingUtilities.isEventDispatchThread()) { 178 SwingUtilities.invokeLater(this::updateImage); 179 } else { 180 if (!StreetsideLayer.hasInstance()) { 181 return; 182 } 183 if (image == null) { 184 streetsideImageDisplay.setImage(null, null); 185 setTitle(I18n.tr(StreetsideMainDialog.BASE_TITLE)); 186 return; 187 } 188 189 if (imageInfoHelp != null && StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.get() > 0 190 && imageInfoHelp.showPopup()) { 191 // Count down the number of times the popup will be displayed 192 StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN 193 .put(StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.get() - 1); 194 } 195 196 if (image instanceof StreetsideImage) { 197 final StreetsideImage streetsideImage = (StreetsideImage) image; 198 // Downloads the thumbnail. 199 streetsideImageDisplay.setImage(null, null); 200 if (thumbnailCache != null) { 201 thumbnailCache.cancelOutstandingTasks(); 202 } 203 thumbnailCache = new StreetsideCache(streetsideImage.getId(), StreetsideCache.Type.THUMBNAIL); 204 try { 205 thumbnailCache.submit(this, false); 206 } catch (final IOException e) { 207 LOGGER.log(Logging.LEVEL_ERROR, e.getMessage(), e); 208 } 209 210 // Downloads the full resolution image. 211 if (fullQuality || new StreetsideCache(streetsideImage.getId(), StreetsideCache.Type.FULL_IMAGE) 212 .get() != null) { 213 if (imageCache != null) { 214 imageCache.cancelOutstandingTasks(); 215 } 216 imageCache = new StreetsideCache(streetsideImage.getId(), StreetsideCache.Type.FULL_IMAGE); 217 try { 218 imageCache.submit(this, false); 219 } catch (final IOException e) { 220 LOGGER.log(Logging.LEVEL_ERROR, e.getMessage(), e); 221 } 222 } 223 } 224 updateTitle(); 225 } 226 } 227 228 /** 257 229 * Disables all the buttons in the dialog 258 230 */ … … 264 236 } 265 237 266 /** 267 * Sets a new StreetsideImage to be shown. 268 * 269 * @param image The image to be shown. 270 */ 271 public synchronized void setImage(StreetsideAbstractImage image) { 272 this.image = image; 273 } 274 275 /** 276 * Updates the title of the dialog. 277 */ 278 public synchronized void updateTitle() { 279 if (!SwingUtilities.isEventDispatchThread()) { 280 SwingUtilities.invokeLater(this::updateTitle); 281 } else if (image != null) { 282 final StringBuilder title = new StringBuilder(I18n.tr(StreetsideMainDialog.BASE_TITLE)); 283 if (image instanceof StreetsideImage) { 284 title.append(StreetsideMainDialog.MESSAGE_SEPARATOR).append(MessageFormat.format("(heading {0}°)",Double.toString(image.getHe()))); 238 /** 239 * Updates the title of the dialog. 240 */ 241 public synchronized void updateTitle() { 242 if (!SwingUtilities.isEventDispatchThread()) { 243 SwingUtilities.invokeLater(this::updateTitle); 244 } else if (image != null) { 245 final StringBuilder title = new StringBuilder(I18n.tr(StreetsideMainDialog.BASE_TITLE)); 246 if (image instanceof StreetsideImage) { 247 title.append(StreetsideMainDialog.MESSAGE_SEPARATOR) 248 .append(MessageFormat.format("(heading {0}°)", Double.toString(image.getHe()))); 285 249 setTitle(title.toString()); 286 } 287 } 288 } 289 290 /** 291 * Returns the {@link StreetsideAbstractImage} object which is being shown. 292 * 293 * @return The {@link StreetsideAbstractImage} object which is being shown. 294 */ 295 public synchronized StreetsideAbstractImage getImage() { 296 return image; 297 } 298 299 /** 300 * Action class form the next image button. 301 * 302 * @author nokutu 303 */ 304 private static class NextPictureAction extends AbstractAction { 305 306 private static final long serialVersionUID = 6333692154558730392L; 307 308 /** 309 * Constructs a normal NextPictureAction 310 */ 311 NextPictureAction() { 312 super(I18n.tr("Next picture")); 313 putValue(Action.SHORT_DESCRIPTION, I18n.tr("Shows the next picture in the sequence")); 314 new ImageProvider("help", "next").getResource().attachImageIcon(this, true); 315 } 316 317 @Override 318 public void actionPerformed(ActionEvent e) { 319 StreetsideLayer.getInstance().getData().selectNext(); 320 } 321 } 322 323 /** 324 * Action class for the previous image button. 325 * 326 * @author nokutu 327 */ 328 private static class PreviousPictureAction extends AbstractAction { 329 330 private static final long serialVersionUID = 4390593660514657107L; 331 332 /** 333 * Constructs a normal PreviousPictureAction 334 */ 335 PreviousPictureAction() { 336 super(I18n.tr("Previous picture")); 337 putValue(Action.SHORT_DESCRIPTION, I18n.tr("Shows the previous picture in the sequence")); 338 new ImageProvider("help", "previous").getResource().attachImageIcon(this, true); 339 } 340 341 @Override 342 public void actionPerformed(ActionEvent e) { 343 StreetsideLayer.getInstance().getData().selectPrevious(); 344 } 345 } 346 347 /** 348 * Action class to jump to the image following the red line. 349 * 350 * @author nokutu 351 */ 352 private static class RedAction extends AbstractAction { 353 354 private static final long serialVersionUID = -1244456062285831231L; 355 356 /** 357 * Constructs a normal RedAction 358 */ 359 RedAction() { 360 putValue(Action.NAME, I18n.tr("Jump to red")); 361 putValue(Action.SHORT_DESCRIPTION, 362 I18n.tr("Jumps to the picture at the other side of the red line")); 363 new ImageProvider("dialogs", "red").getResource().attachImageIcon(this, true); 364 } 365 366 @Override 367 public void actionPerformed(ActionEvent e) { 368 if (StreetsideMainDialog.getInstance().getImage() != null) { 369 StreetsideLayer.getInstance().getData() 370 .setSelectedImage(StreetsideLayer.getInstance().getNNearestImage(1), true); 371 } 372 } 373 } 374 375 /** 376 * Action class to jump to the image following the blue line. 377 * 378 * @author nokutu 379 */ 380 private static class BlueAction extends AbstractAction { 381 382 private static final long serialVersionUID = 5951233534212838780L; 383 384 /** 385 * Constructs a normal BlueAction 386 */ 387 BlueAction() { 388 putValue(Action.NAME, I18n.tr("Jump to blue")); 389 putValue(Action.SHORT_DESCRIPTION, 390 I18n.tr("Jumps to the picture at the other side of the blue line")); 391 new ImageProvider("dialogs", "blue").getResource().attachImageIcon(this, true); 392 } 393 394 @Override 395 public void actionPerformed(ActionEvent e) { 396 if (StreetsideMainDialog.getInstance().getImage() != null) { 397 StreetsideLayer.getInstance().getData() 398 .setSelectedImage(StreetsideLayer.getInstance().getNNearestImage(2), true); 399 } 400 } 401 } 402 403 private static class StopAction extends AbstractAction implements WalkListener { 404 405 private static final long serialVersionUID = 8789972456611625341L; 406 407 private WalkThread thread; 408 409 /** 410 * Constructs a normal StopAction 411 */ 412 StopAction() { 413 putValue(Action.NAME, I18n.tr("Stop")); 414 putValue(Action.SHORT_DESCRIPTION, I18n.tr("Stops the walk.")); 415 new ImageProvider("dialogs/streetsideStop.png").getResource().attachImageIcon(this, true); 416 StreetsidePlugin.getStreetsideWalkAction().addListener(this); 417 } 418 419 @Override 420 public void actionPerformed(ActionEvent e) { 421 if (thread != null) { 422 thread.stopWalk(); 423 } 424 } 425 426 @Override 427 public void walkStarted(WalkThread thread) { 428 this.thread = thread; 429 } 430 } 431 432 private static class PlayAction extends AbstractAction implements WalkListener { 433 434 private static final long serialVersionUID = -1572747020946842769L; 435 436 private transient WalkThread thread; 437 438 /** 439 * Constructs a normal PlayAction 440 */ 441 PlayAction() { 442 putValue(Action.NAME, I18n.tr("Play")); 443 putValue(Action.SHORT_DESCRIPTION, I18n.tr("Continues with the paused walk.")); 444 new ImageProvider("dialogs/streetsidePlay.png").getResource().attachImageIcon(this, true); 445 StreetsidePlugin.getStreetsideWalkAction().addListener(this); 446 } 447 448 @Override 449 public void actionPerformed(ActionEvent e) { 450 if (thread != null) { 451 thread.play(); 452 } 453 } 454 455 @Override 456 public void walkStarted(WalkThread thread) { 457 if (thread != null) { 458 this.thread = thread; 459 } 460 } 461 } 462 463 private static class PauseAction extends AbstractAction implements WalkListener { 464 465 /** 466 * 467 */ 468 private static final long serialVersionUID = -8758326399460817222L; 469 private WalkThread thread; 470 471 /** 472 * Constructs a normal PauseAction 473 */ 474 PauseAction() { 475 putValue(Action.NAME, I18n.tr("Pause")); 476 putValue(Action.SHORT_DESCRIPTION, I18n.tr("Pauses the walk.")); 477 new ImageProvider("dialogs/streetsidePause.png").getResource().attachImageIcon(this, true); 478 StreetsidePlugin.getStreetsideWalkAction().addListener(this); 479 } 480 481 @Override 482 public void actionPerformed(ActionEvent e) { 483 thread.pause(); 484 } 485 486 @Override 487 public void walkStarted(WalkThread thread) { 488 this.thread = thread; 489 } 490 } 491 492 /** 493 * When the pictures are returned from the cache, they are set in the 494 * {@link StreetsideImageDisplay} object. 495 */ 496 @Override 497 public void loadingFinished(final CacheEntry data, final CacheEntryAttributes attributes, final LoadResult result) { 498 if (!SwingUtilities.isEventDispatchThread()) { 499 SwingUtilities.invokeLater(() -> loadingFinished(data, attributes, result)); 500 501 } else if (data != null && result == LoadResult.SUCCESS) { 502 try { 503 final BufferedImage img = ImageIO.read(new ByteArrayInputStream(data.getContent())); 504 if (img == null) { 505 return; 506 } 507 if ( 508 streetsideImageDisplay.getImage() == null 509 || img.getHeight() > streetsideImageDisplay.getImage().getHeight() 510 ) { 511 streetsideImageDisplay.setImage( 512 img, 513 null); 514 } 515 } catch (final IOException e) { 516 logger.error(e); 517 } 518 } 519 } 520 521 522 /** 523 * Creates the layout of the dialog. 524 * 525 * @param data The content of the dialog 526 * @param buttons The buttons where you can click 527 */ 528 public void createLayout(Component data, List<SideButton> buttons) { 529 removeAll(); 530 createLayout(data, true, buttons); 531 add(titleBar, BorderLayout.NORTH); 532 } 533 534 @Override 535 public void selectedImageChanged(StreetsideAbstractImage oldImage, StreetsideAbstractImage newImage) { 536 setImage(newImage); 537 if (newImage != null && newImage.getSequence() != null) { 538 if (newImage.next() != null) { 539 nextButton.setEnabled(true); 540 } 541 if (newImage.previous() != null) { 542 previousButton.setEnabled(true); 543 } 250 } 251 } 252 } 253 254 /** 255 * Returns the {@link StreetsideAbstractImage} object which is being shown. 256 * 257 * @return The {@link StreetsideAbstractImage} object which is being shown. 258 */ 259 public synchronized StreetsideAbstractImage getImage() { 260 return image; 261 } 262 263 /** 264 * Sets a new StreetsideImage to be shown. 265 * 266 * @param image The image to be shown. 267 */ 268 public synchronized void setImage(StreetsideAbstractImage image) { 269 this.image = image; 270 } 271 272 /** 273 * When the pictures are returned from the cache, they are set in the 274 * {@link StreetsideImageDisplay} object. 275 */ 276 @Override 277 public void loadingFinished(final CacheEntry data, final CacheEntryAttributes attributes, final LoadResult result) { 278 if (!SwingUtilities.isEventDispatchThread()) { 279 SwingUtilities.invokeLater(() -> loadingFinished(data, attributes, result)); 280 281 } else if (data != null && result == LoadResult.SUCCESS) { 282 try { 283 final BufferedImage img = ImageIO.read(new ByteArrayInputStream(data.getContent())); 284 if (img == null) { 285 return; 544 286 } 545 updateImage(); 546 } 547 548 @Override 549 public void imagesAdded() { 550 // This method is enforced by StreetsideDataListener, but only selectedImageChanged() is needed 551 } 552 553 /** 554 * @return the streetsideImageDisplay 555 */ 556 public StreetsideImageDisplay getStreetsideImageDisplay() { 557 return streetsideImageDisplay; 558 } 559 560 /** 561 * @param streetsideImageDisplay the streetsideImageDisplay to set 562 */ 563 public void setStreetsideImageDisplay(StreetsideImageDisplay streetsideImageDisplay) { 564 this.streetsideImageDisplay = streetsideImageDisplay; 565 } 287 if (streetsideImageDisplay.getImage() == null 288 || img.getHeight() > streetsideImageDisplay.getImage().getHeight()) { 289 streetsideImageDisplay.setImage(img, null); 290 } 291 } catch (final IOException e) { 292 LOGGER.log(Logging.LEVEL_ERROR, e.getMessage(), e); 293 } 294 } 295 } 296 297 /** 298 * Creates the layout of the dialog. 299 * 300 * @param data The content of the dialog 301 * @param buttons The buttons where you can click 302 */ 303 public void createLayout(Component data, List<SideButton> buttons) { 304 removeAll(); 305 createLayout(data, true, buttons); 306 add(titleBar, BorderLayout.NORTH); 307 } 308 309 @Override 310 public void selectedImageChanged(StreetsideAbstractImage oldImage, StreetsideAbstractImage newImage) { 311 setImage(newImage); 312 if (newImage != null && newImage.getSequence() != null) { 313 if (newImage.next() != null) { 314 nextButton.setEnabled(true); 315 } 316 if (newImage.previous() != null) { 317 previousButton.setEnabled(true); 318 } 319 } 320 updateImage(); 321 } 322 323 @Override 324 public void imagesAdded() { 325 // This method is enforced by StreetsideDataListener, but only selectedImageChanged() is needed 326 } 327 328 /** 329 * @return the streetsideImageDisplay 330 */ 331 public StreetsideImageDisplay getStreetsideImageDisplay() { 332 return streetsideImageDisplay; 333 } 334 335 /** 336 * @param streetsideImageDisplay the streetsideImageDisplay to set 337 */ 338 public void setStreetsideImageDisplay(StreetsideImageDisplay streetsideImageDisplay) { 339 this.streetsideImageDisplay = streetsideImageDisplay; 340 } 341 342 /** 343 * Buttons mode. 344 * 345 * @author nokutu 346 */ 347 public enum MODE { 348 /** 349 * Standard mode to view pictures. 350 */ 351 NORMAL, 352 /** 353 * Mode when in walk. 354 */ 355 WALK 356 } 357 358 /** 359 * Action class form the next image button. 360 * 361 * @author nokutu 362 */ 363 private static class NextPictureAction extends AbstractAction { 364 365 private static final long serialVersionUID = 6333692154558730392L; 366 367 /** 368 * Constructs a normal NextPictureAction 369 */ 370 NextPictureAction() { 371 super(I18n.tr("Next picture")); 372 putValue(Action.SHORT_DESCRIPTION, I18n.tr("Shows the next picture in the sequence")); 373 new ImageProvider("help", "next").getResource().attachImageIcon(this, true); 374 } 375 376 @Override 377 public void actionPerformed(ActionEvent e) { 378 StreetsideLayer.getInstance().getData().selectNext(); 379 } 380 } 381 382 /** 383 * Action class for the previous image button. 384 * 385 * @author nokutu 386 */ 387 private static class PreviousPictureAction extends AbstractAction { 388 389 private static final long serialVersionUID = 4390593660514657107L; 390 391 /** 392 * Constructs a normal PreviousPictureAction 393 */ 394 PreviousPictureAction() { 395 super(I18n.tr("Previous picture")); 396 putValue(Action.SHORT_DESCRIPTION, I18n.tr("Shows the previous picture in the sequence")); 397 new ImageProvider("help", "previous").getResource().attachImageIcon(this, true); 398 } 399 400 @Override 401 public void actionPerformed(ActionEvent e) { 402 StreetsideLayer.getInstance().getData().selectPrevious(); 403 } 404 } 405 406 /** 407 * Action class to jump to the image following the red line. 408 * 409 * @author nokutu 410 */ 411 private static class RedAction extends AbstractAction { 412 413 private static final long serialVersionUID = -1244456062285831231L; 414 415 /** 416 * Constructs a normal RedAction 417 */ 418 RedAction() { 419 putValue(Action.NAME, I18n.tr("Jump to red")); 420 putValue(Action.SHORT_DESCRIPTION, I18n.tr("Jumps to the picture at the other side of the red line")); 421 new ImageProvider("dialogs", "red").getResource().attachImageIcon(this, true); 422 } 423 424 @Override 425 public void actionPerformed(ActionEvent e) { 426 if (StreetsideMainDialog.getInstance().getImage() != null) { 427 StreetsideLayer.getInstance().getData() 428 .setSelectedImage(StreetsideLayer.getInstance().getNNearestImage(1), true); 429 } 430 } 431 } 432 433 /** 434 * Action class to jump to the image following the blue line. 435 * 436 * @author nokutu 437 */ 438 private static class BlueAction extends AbstractAction { 439 440 private static final long serialVersionUID = 5951233534212838780L; 441 442 /** 443 * Constructs a normal BlueAction 444 */ 445 BlueAction() { 446 putValue(Action.NAME, I18n.tr("Jump to blue")); 447 putValue(Action.SHORT_DESCRIPTION, I18n.tr("Jumps to the picture at the other side of the blue line")); 448 new ImageProvider("dialogs", "blue").getResource().attachImageIcon(this, true); 449 } 450 451 @Override 452 public void actionPerformed(ActionEvent e) { 453 if (StreetsideMainDialog.getInstance().getImage() != null) { 454 StreetsideLayer.getInstance().getData() 455 .setSelectedImage(StreetsideLayer.getInstance().getNNearestImage(2), true); 456 } 457 } 458 } 459 460 private static class StopAction extends AbstractAction implements WalkListener { 461 462 private static final long serialVersionUID = 8789972456611625341L; 463 464 private WalkThread thread; 465 466 /** 467 * Constructs a normal StopAction 468 */ 469 StopAction() { 470 putValue(Action.NAME, I18n.tr("Stop")); 471 putValue(Action.SHORT_DESCRIPTION, I18n.tr("Stops the walk.")); 472 new ImageProvider("dialogs/streetsideStop.png").getResource().attachImageIcon(this, true); 473 StreetsidePlugin.getStreetsideWalkAction().addListener(this); 474 } 475 476 @Override 477 public void actionPerformed(ActionEvent e) { 478 if (thread != null) { 479 thread.stopWalk(); 480 } 481 } 482 483 @Override 484 public void walkStarted(WalkThread thread) { 485 this.thread = thread; 486 } 487 } 488 489 private static class PlayAction extends AbstractAction implements WalkListener { 490 491 private static final long serialVersionUID = -1572747020946842769L; 492 493 private transient WalkThread thread; 494 495 /** 496 * Constructs a normal PlayAction 497 */ 498 PlayAction() { 499 putValue(Action.NAME, I18n.tr("Play")); 500 putValue(Action.SHORT_DESCRIPTION, I18n.tr("Continues with the paused walk.")); 501 new ImageProvider("dialogs/streetsidePlay.png").getResource().attachImageIcon(this, true); 502 StreetsidePlugin.getStreetsideWalkAction().addListener(this); 503 } 504 505 @Override 506 public void actionPerformed(ActionEvent e) { 507 if (thread != null) { 508 thread.play(); 509 } 510 } 511 512 @Override 513 public void walkStarted(WalkThread thread) { 514 if (thread != null) { 515 this.thread = thread; 516 } 517 } 518 } 519 520 private static class PauseAction extends AbstractAction implements WalkListener { 521 522 /** 523 * 524 */ 525 private static final long serialVersionUID = -8758326399460817222L; 526 private WalkThread thread; 527 528 /** 529 * Constructs a normal PauseAction 530 */ 531 PauseAction() { 532 putValue(Action.NAME, I18n.tr("Pause")); 533 putValue(Action.SHORT_DESCRIPTION, I18n.tr("Pauses the walk.")); 534 new ImageProvider("dialogs/streetsidePause.png").getResource().attachImageIcon(this, true); 535 StreetsidePlugin.getStreetsideWalkAction().addListener(this); 536 } 537 538 @Override 539 public void actionPerformed(ActionEvent e) { 540 thread.pause(); 541 } 542 543 @Override 544 public void walkStarted(WalkThread thread) { 545 this.thread = thread; 546 } 547 } 566 548 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsidePreferenceSetting.java
r34433 r36194 9 9 import java.io.IOException; 10 10 import java.io.InputStream; 11 import java.util.logging.Logger; 11 12 12 13 import javax.imageio.ImageIO; … … 26 27 import javax.swing.SwingUtilities; 27 28 28 import org.apache.log4j.Logger;29 29 import org.openstreetmap.josm.actions.ExpertToggleAction; 30 30 import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane; … … 41 41 import org.openstreetmap.josm.tools.GBC; 42 42 import org.openstreetmap.josm.tools.I18n; 43 import org.openstreetmap.josm.tools.Logging; 43 44 44 45 /** … … 50 51 public class StreetsidePreferenceSetting implements SubPreferenceSetting, StreetsideLoginListener { 51 52 52 final static Logger logger = Logger.getLogger(StreetsidePreferenceSetting.class); 53 54 private final JComboBox<String> downloadModeComboBox = new JComboBox<>(new String[]{ 55 DOWNLOAD_MODE.VISIBLE_AREA.getLabel(), 56 DOWNLOAD_MODE.OSM_AREA.getLabel(), 57 DOWNLOAD_MODE.MANUAL_ONLY.getLabel() 58 }); 59 60 private final JCheckBox displayHour = 61 new JCheckBox(I18n.tr("Display hour when the picture was taken"), StreetsideProperties.DISPLAY_HOUR.get()); 62 private final JCheckBox format24 = 63 new JCheckBox(I18n.tr("Use 24 hour format"), StreetsideProperties.TIME_FORMAT_24.get()); 64 private final JCheckBox moveTo = 65 new JCheckBox(I18n.tr("Move to picture''s location with next/previous buttons"), StreetsideProperties.MOVE_TO_IMG.get()); 66 private final JCheckBox hoverEnabled = 67 new JCheckBox(I18n.tr("Preview images when hovering its icon"), StreetsideProperties.HOVER_ENABLED.get()); 68 private final JCheckBox cutOffSeq = 69 new JCheckBox(I18n.tr("Cut off sequences at download bounds"), StreetsideProperties.CUT_OFF_SEQUENCES_AT_BOUNDS.get()); 70 private final JCheckBox imageLinkToBlurEditor = 71 new JCheckBox( 53 private static final Logger logger = Logger.getLogger(StreetsidePreferenceSetting.class.getCanonicalName()); 54 55 private final JComboBox<String> downloadModeComboBox = new JComboBox<>( 56 new String[] { DOWNLOAD_MODE.VISIBLE_AREA.getLabel(), DOWNLOAD_MODE.OSM_AREA.getLabel(), 57 DOWNLOAD_MODE.MANUAL_ONLY.getLabel() }); 58 59 private final JCheckBox displayHour = new JCheckBox(I18n.tr("Display hour when the picture was taken"), 60 StreetsideProperties.DISPLAY_HOUR.get()); 61 private final JCheckBox format24 = new JCheckBox(I18n.tr("Use 24 hour format"), 62 StreetsideProperties.TIME_FORMAT_24.get()); 63 private final JCheckBox moveTo = new JCheckBox(I18n.tr("Move to picture''s location with next/previous buttons"), 64 StreetsideProperties.MOVE_TO_IMG.get()); 65 private final JCheckBox hoverEnabled = new JCheckBox(I18n.tr("Preview images when hovering its icon"), 66 StreetsideProperties.HOVER_ENABLED.get()); 67 private final JCheckBox cutOffSeq = new JCheckBox(I18n.tr("Cut off sequences at download bounds"), 68 StreetsideProperties.CUT_OFF_SEQUENCES_AT_BOUNDS.get()); 69 private final JCheckBox imageLinkToBlurEditor = new JCheckBox( 72 70 I18n.tr("When opening Streetside image in web browser, show the blur editor instead of the image viewer"), 73 StreetsideProperties.IMAGE_LINK_TO_BLUR_EDITOR.get() 74 ); 75 private final JCheckBox developer = 76 new JCheckBox(I18n.tr("Enable experimental beta-features (might be unstable)"), StreetsideProperties.DEVELOPER.get()); 71 StreetsideProperties.IMAGE_LINK_TO_BLUR_EDITOR.get()); 72 private final JCheckBox developer = new JCheckBox(I18n.tr("Enable experimental beta-features (might be unstable)"), 73 StreetsideProperties.DEVELOPER.get()); 77 74 private final SpinnerNumberModel preFetchSize = new SpinnerNumberModel( 78 StreetsideProperties.PRE_FETCH_IMAGE_COUNT.get().intValue(), 79 0, 80 Integer.MAX_VALUE, 81 1 82 ); 75 StreetsideProperties.PRE_FETCH_IMAGE_COUNT.get().intValue(), 0, Integer.MAX_VALUE, 1); 83 76 private final JButton loginButton = new StreetsideButton(new LoginAction(this)); 84 77 private final JButton logoutButton = new StreetsideButton(new LogoutAction()); … … 99 92 loginPanel.setBackground(StreetsideColorScheme.TOOLBAR_DARK_GREY); 100 93 JLabel brandImage = new JLabel(); 101 try (InputStream is = StreetsidePreferenceSetting.class.getResourceAsStream("/images/streetside-logo-white.png")) { 94 try (InputStream is = StreetsidePreferenceSetting.class 95 .getResourceAsStream("/images/streetside-logo-white.png")) { 102 96 if (is != null) { 103 97 brandImage.setIcon(new ImageIcon(ImageIO.read(is))); 104 98 } else { 105 logger. warn("Could not load Streetside brand image!");99 logger.log(Logging.LEVEL_WARN, "Could not load Streetside brand image!"); 106 100 } 107 101 } catch (IOException e) { 108 logger. warn("While reading Streetside brand image, an IO-exception occured!");102 logger.log(Logging.LEVEL_WARN, "While reading Streetside brand image, an IO-exception occured!", e); 109 103 } 110 104 loginPanel.add(brandImage, 0); … … 121 115 mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 122 116 123 downloadModeComboBox.setSelectedItem(DOWNLOAD_MODE.fromPrefId(StreetsideProperties.DOWNLOAD_MODE.get()).getLabel()); 117 downloadModeComboBox 118 .setSelectedItem(DOWNLOAD_MODE.fromPrefId(StreetsideProperties.DOWNLOAD_MODE.get()).getLabel()); 124 119 125 120 JPanel downloadModePanel = new JPanel(); … … 147 142 mainPanel.add(developer, GBC.eol()); 148 143 } 149 StreetsideColorScheme.styleAsDefaultPanel( 150 mainPanel, downloadModePanel, displayHour, format24, moveTo, hoverEnabled, cutOffSeq, imageLinkToBlurEditor, developer, preFetchPanel 151 ); 144 StreetsideColorScheme.styleAsDefaultPanel(mainPanel, downloadModePanel, displayHour, format24, moveTo, 145 hoverEnabled, cutOffSeq, imageLinkToBlurEditor, developer, preFetchPanel); 152 146 mainPanel.add(Box.createVerticalGlue(), GBC.eol().fill(GridBagConstraints.BOTH)); 153 147 … … 156 150 synchronized (gui.getDisplayPreference().getTabPane()) { 157 151 gui.getDisplayPreference().addSubTab(this, "Streetside", new JScrollPane(container)); 158 gui.getDisplayPreference().getTabPane().setIconAt(gui.getDisplayPreference().getTabPane().getTabCount()-1, StreetsidePlugin.LOGO.setSize(12, 12).get()); 152 gui.getDisplayPreference().getTabPane().setIconAt(gui.getDisplayPreference().getTabPane().getTabCount() - 1, 153 StreetsidePlugin.LOGO.setSize(12, 12).get()); 159 154 } 160 155 … … 188 183 @Override 189 184 public boolean ok() { 190 StreetsideProperties.DOWNLOAD_MODE.put(DOWNLOAD_MODE.fromLabel(downloadModeComboBox.getSelectedItem().toString()).getPrefId()); 185 StreetsideProperties.DOWNLOAD_MODE 186 .put(DOWNLOAD_MODE.fromLabel(downloadModeComboBox.getSelectedItem().toString()).getPrefId()); 191 187 StreetsideProperties.DISPLAY_HOUR.put(displayHour.isSelected()); 192 188 StreetsideProperties.TIME_FORMAT_24.put(format24.isSelected()); … … 211 207 * 212 208 * @author nokutu 213 *214 209 */ 215 210 private static class LoginAction extends AbstractAction { … … 217 212 private static final long serialVersionUID = 8743119160917296506L; 218 213 219 214 private final transient StreetsideLoginListener callback; 220 215 221 216 LoginAction(StreetsideLoginListener loginCallback) { … … 242 237 private static final long serialVersionUID = -4146587895393766981L; 243 238 244 239 private LogoutAction() { 245 240 super(I18n.tr("Logout")); 246 241 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideViewerDialog.java
r34433 r36194 16 16 */ 17 17 18 public final class StreetsideViewerDialog extends ToggleDialog 19 { 18 public final class StreetsideViewerDialog extends ToggleDialog { 20 19 21 20 private static final long serialVersionUID = -8983900297628236197L; 22 21 23 22 private static final String BASE_TITLE = "360° Streetside Viewer"; 24 23 25 24 private static StreetsideViewerDialog instance; 26 25 27 28 29 30 privateStreetsideViewerPanel streetsideViewerPanel;26 /** 27 * Object containing the shown image and that handles zoom and drag 28 */ 29 private final StreetsideViewerPanel streetsideViewerPanel; 31 30 32 33 super(StreetsideViewerDialog.BASE_TITLE, "streetside-viewer", "Open Streetside Viewer window",34 null, 200, true,StreetsidePreferenceSetting.class);35 36 37 31 private StreetsideViewerDialog() { 32 super(StreetsideViewerDialog.BASE_TITLE, "streetside-viewer", "Open Streetside Viewer window", null, 200, true, 33 StreetsidePreferenceSetting.class); 34 streetsideViewerPanel = new StreetsideViewerPanel(); 35 createLayout(streetsideViewerPanel, true, null); 36 } 38 37 39 40 41 42 43 44 45 46 47 48 49 38 /** 39 * Returns the unique instance of the class. 40 * 41 * @return The unique instance of the class. 42 */ 43 public static synchronized StreetsideViewerDialog getInstance() { 44 if (StreetsideViewerDialog.instance == null) { 45 StreetsideViewerDialog.instance = new StreetsideViewerDialog(); 46 } 47 return StreetsideViewerDialog.instance; 48 } 50 49 51 52 53 54 55 56 50 /** 51 * @return true, iff the singleton instance is present 52 */ 53 public static boolean hasInstance() { 54 return StreetsideViewerDialog.instance != null; 55 } 57 56 58 59 60 61 62 63 57 /** 58 * Destroys the unique instance of the class. 59 */ 60 public static synchronized void destroyInstance() { 61 StreetsideViewerDialog.instance = null; 62 } 64 63 65 /** 66 * Creates the layout of the dialog. 67 * 68 * @param data 69 * The content of the dialog 70 * @param buttons 71 * The buttons where you can click 72 */ 73 public void createLayout(Component data, List<SideButton> buttons) { 74 removeAll(); 75 createLayout(data, true, buttons); 76 add(titleBar, BorderLayout.NORTH); 77 } 64 /** 65 * Creates the layout of the dialog. 66 * 67 * @param data The content of the dialog 68 * @param buttons The buttons where you can click 69 */ 70 public void createLayout(Component data, List<SideButton> buttons) { 71 removeAll(); 72 createLayout(data, true, buttons); 73 add(titleBar, BorderLayout.NORTH); 74 } 78 75 79 80 81 76 public StreetsideViewerPanel getStreetsideViewerPanel() { 77 return streetsideViewerPanel; 78 } 82 79 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideWalkDialog.java
r34317 r36194 21 21 private static final long serialVersionUID = 7974881240732957573L; 22 22 23 /** Spin containing the interval value. */ 23 /** 24 * Spin containing the interval value. 25 */ 24 26 public SpinnerModel spin; 25 /** Whether it must wait for the picture to be downloaded */ 27 /** 28 * Whether it must wait for the picture to be downloaded 29 */ 26 30 public JCheckBox waitForPicture; 27 /** Whether the view must follow the selected image. */ 31 /** 32 * Whether the view must follow the selected image. 33 */ 28 34 public JCheckBox followSelection; 29 /** Go forward or backwards */ 35 /** 36 * Go forward or backwards 37 */ 30 38 public JCheckBox goForward; 31 39 -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/boilerplate/SelectableLabel.java
r34317 r36194 10 10 public class SelectableLabel extends JTextPane { 11 11 12 private static final long serialVersionUID = 5432480892000739831L;13 14 12 public static final Font DEFAULT_FONT = UIManager.getFont("Label.font").deriveFont(Font.PLAIN); 15 13 public static final Color DEFAULT_BACKGROUND = UIManager.getColor("Panel.background"); 14 private static final long serialVersionUID = 5432480892000739831L; 16 15 17 16 public SelectableLabel() { -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/boilerplate/StreetsideButton.java
r34317 r36194 12 12 13 13 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideColorScheme; 14 15 14 16 15 public class StreetsideButton extends JButton { -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/dialog/ChooseGeoImageLayersDialog.java
r34399 r36194 27 27 public class ChooseGeoImageLayersDialog extends JDialog { 28 28 private static final long serialVersionUID = -1793622345412435234L; 29 private static final String QUESTION = I18n.marktr("Which image layers do you want to import into the Streetside layer?"); 29 private static final String QUESTION = I18n 30 .marktr("Which image layers do you want to import into the Streetside layer?"); 30 31 31 32 public ChooseGeoImageLayersDialog(final Component parent, final List<GeoImageLayer> layers) { 32 33 super(GuiHelper.getFrameForComponent(parent), I18n.tr(QUESTION)); 33 34 final Container c = getContentPane(); 34 35 c.setLayout(new BorderLayout(10, 10)); … … 64 65 protected static class GeoImageLayerListCellRenderer implements ListCellRenderer<GeoImageLayer> { 65 66 @Override 66 public Component getListCellRendererComponent( 67 JList<? extends GeoImageLayer> list, GeoImageLayer value, int index, boolean isSelected, boolean cellHasFocus 68 ) { 69 final JLabel result = value == null 70 ? null 67 public Component getListCellRendererComponent(JList<? extends GeoImageLayer> list, GeoImageLayer value, 68 int index, boolean isSelected, boolean cellHasFocus) { 69 final JLabel result = value == null ? null 71 70 /* i18n: {0} is the layer name, {1} the number of images in it */ 72 : new JLabel(I18n.tr("{0} ({1} images)", value.getName(), value.getImages().size()), value.getIcon(), SwingConstants.LEADING); 71 : new JLabel(I18n.tr("{0} ({1} images)", value.getName(), value.getImages().size()), 72 value.getIcon(), SwingConstants.LEADING); 73 73 if (result != null) { 74 74 result.setOpaque(true); 75 result.setBackground(isSelected ? UIManager.getColor("List.selectionBackground") : UIManager.getColor("List.background")); 75 result.setBackground(isSelected ? UIManager.getColor("List.selectionBackground") 76 : UIManager.getColor("List.background")); 76 77 } 77 78 return result; -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/AddTagToPrimitiveAction.java
r34577 r36194 44 44 int conflictResolution = JOptionPane.YES_OPTION; 45 45 if (target.hasKey(tag.getKey()) && !target.hasTag(tag.getKey(), tag.getValue())) { 46 conflictResolution = JOptionPane.showConfirmDialog( 47 MainApplication.getMainFrame(), 48 "<html>" + 49 I18n.tr("A tag with key <i>{0}</i> is already present on the selected OSM object.", tag.getKey()) + "<br>" + 50 I18n.tr( 51 "Do you really want to replace the current value <i>{0}</i> with the new value <i>{1}</i>?", 52 target.get(tag.getKey()), 53 tag.getValue() 54 ) + "</html>", 55 I18n.tr("Tag conflict"), 56 JOptionPane.YES_NO_OPTION, 57 JOptionPane.WARNING_MESSAGE 58 ); 46 conflictResolution = JOptionPane.showConfirmDialog(MainApplication.getMainFrame(), "<html>" + I18n 47 .tr("A tag with key <i>{0}</i> is already present on the selected OSM object.", tag.getKey()) 48 + "<br>" 49 + I18n.tr( 50 "Do you really want to replace the current value <i>{0}</i> with the new value <i>{1}</i>?", 51 target.get(tag.getKey()), tag.getValue()) 52 + "</html>", I18n.tr("Tag conflict"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); 59 53 } 60 54 if (JOptionPane.YES_OPTION == conflictResolution) { -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ClipboardAction.java
r34433 r36194 67 67 /** 68 68 * Sets the component, under which the popup will be shown, which indicates that the key was copied to the clipboard. 69 * 69 70 * @param popupParent the component to set as parent of the popup 70 71 */ -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ImageInfoHelpPopup.java
r34412 r36194 7 7 import java.awt.IllegalComponentStateException; 8 8 import java.awt.event.ActionEvent; 9 import java.util.logging.Logger; 9 10 10 11 import javax.swing.AbstractAction; … … 14 15 import javax.swing.JTextPane; 15 16 16 import org.apache.log4j.Logger;17 17 import org.openstreetmap.josm.plugins.streetside.gui.boilerplate.SelectableLabel; 18 18 import org.openstreetmap.josm.plugins.streetside.gui.boilerplate.StreetsideButton; … … 21 21 import org.openstreetmap.josm.tools.I18n; 22 22 import org.openstreetmap.josm.tools.ImageProvider; 23 import org.openstreetmap.josm.tools.Logging; 23 24 24 25 public class ImageInfoHelpPopup extends JPopupMenu { … … 26 27 private static final long serialVersionUID = -1721594904273820586L; 27 28 28 final static Logger logger = Logger.getLogger(ImageInfoHelpPopup.class);29 private static final Logger LOGGER = Logger.getLogger(ImageInfoHelpPopup.class.getCanonicalName()); 29 30 30 31 private final Component invokerComp; … … 44 45 mainText.setContentType("text/html"); 45 46 mainText.setFont(SelectableLabel.DEFAULT_FONT); 46 mainText.setText("<html><div style='width:250px'>" +47 "Welcome to the Microsoft Streetside JOSM Plugin. To view the vector bubbles for the 360 degree imagery, select Imagery->Streetside from the JOSM menu."48 + "<br><br>"49 + "Once the blue bubbles appear on the map, click on a vector bubble and undock/maximize the 360 viewer to view the imagery."50 + "</div></html>");47 mainText.setText("<html><div style='width:250px'>" 48 + "Welcome to the Microsoft Streetside JOSM Plugin. To view the vector bubbles for the 360 degree imagery, select Imagery->Streetside from the JOSM menu." 49 + "<br><br>" 50 + "Once the blue bubbles appear on the map, click on a vector bubble and undock/maximize the 360 viewer to view the imagery." 51 + "</div></html>"); 51 52 add(mainText, BorderLayout.CENTER); 52 53 … … 56 57 infoButton.addActionListener(e -> setVisible(false)); 57 58 bottomBar.add(infoButton); 58 59 StreetsideButton closeBtn = new StreetsideButton(new AbstractAction() { 59 60 60 61 private static final long serialVersionUID = 2853315308169651854L; 61 62 62 63 64 65 66 67 63 @Override 64 public void actionPerformed(ActionEvent e) { 65 setVisible(false); 66 StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.put(0); 67 } 68 }); 68 69 69 70 71 70 closeBtn.setText(I18n.tr("I got it, close this.")); 71 bottomBar.add(closeBtn); 72 add(bottomBar, BorderLayout.SOUTH); 72 73 73 74 74 setBackground(Color.WHITE); 75 } 75 76 76 77 /** … … 84 85 return true; 85 86 } catch (IllegalComponentStateException e) { 86 logger.warn(I18n.tr("Could not show ImageInfoHelpPopup, because probably the invoker component has disappeared from screen.", e)); 87 LOGGER.log(Logging.LEVEL_WARN, I18n.tr( 88 "Could not show ImageInfoHelpPopup, because probably the invoker component has disappeared from screen.", 89 e)); 87 90 } 88 91 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ImageInfoPanel.java
r34416 r36194 7 7 import java.awt.datatransfer.StringSelection; 8 8 import java.util.Collection; 9 import java.util.logging.Logger; 9 10 10 11 import javax.swing.JLabel; … … 12 13 import javax.swing.JTextPane; 13 14 14 import org.apache.log4j.Logger;15 15 import org.openstreetmap.josm.data.osm.DataSelectionListener; 16 16 import org.openstreetmap.josm.data.osm.OsmPrimitive; … … 27 27 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL; 28 28 import org.openstreetmap.josm.tools.I18n; 29 import org.openstreetmap.josm.tools.Logging; 29 30 30 31 public final class ImageInfoPanel extends ToggleDialog implements StreetsideDataListener, DataSelectionListener { 31 32 private static final long serialVersionUID = 4141847503072417190L; 32 33 33 final static Logger logger = Logger.getLogger(ImageInfoPanel.class);34 private static final Logger LOGGER = Logger.getLogger(ImageInfoPanel.class.getCanonicalName()); 34 35 35 36 private static ImageInfoPanel instance; … … 44 45 45 46 private ImageInfoPanel() { 46 super( 47 I18n.tr("Streetside 360° image info"), 48 "streetside-info", 49 I18n.tr("Displays detail information on the currently selected Streetside image"), 50 null, 51 150 52 ); 47 super(I18n.tr("Streetside 360° image info"), "streetside-info", 48 I18n.tr("Displays detail information on the currently selected Streetside image"), null, 150); 53 49 SelectionEventManager.getInstance().addSelectionListener(this); 54 50 … … 153 149 */ 154 150 @Override 155 public synchronized void selectedImageChanged(final StreetsideAbstractImage oldImage, final StreetsideAbstractImage newImage) { 156 logger.info(String.format( 157 "Selected Streetside image changed from %s to %s.", 158 oldImage instanceof StreetsideImage ? ((StreetsideImage) oldImage).getId() : "‹none›", 159 newImage instanceof StreetsideImage ? ((StreetsideImage) newImage).getId() : "‹none›" 160 )); 151 public synchronized void selectedImageChanged(final StreetsideAbstractImage oldImage, 152 final StreetsideAbstractImage newImage) { 153 LOGGER.info(String.format("Selected Streetside image changed from %s to %s.", 154 oldImage instanceof StreetsideImage ? oldImage.getId() : "‹none›", 155 newImage instanceof StreetsideImage ? newImage.getId() : "‹none›")); 161 156 162 157 imgKeyValue.setEnabled(newImage instanceof StreetsideImage); 163 final String newImageKey = newImage instanceof StreetsideImage ? ((StreetsideImage) newImage).getId(): null;158 final String newImageKey = newImage instanceof StreetsideImage ? newImage.getId() : null; 164 159 if (newImageKey != null) { 165 imageLinkChangeListener = b -> imgLinkAction.setURL( 166 StreetsideURL.MainWebsite.browseImage(newImageKey) 167 ); 160 imageLinkChangeListener = b -> imgLinkAction.setURL(StreetsideURL.MainWebsite.browseImage(newImageKey)); 168 161 imageLinkChangeListener.valueChanged(null); 169 162 StreetsideProperties.IMAGE_LINK_TO_BLUR_EDITOR.addListener(imageLinkChangeListener); … … 184 177 } 185 178 186 final boolean partOfSequence = newImage != null && newImage.getSequence() != null && newImage.getSequence().getId() != null; 179 final boolean partOfSequence = newImage != null && newImage.getSequence() != null 180 && newImage.getSequence().getId() != null; 187 181 seqKeyValue.setEnabled(partOfSequence); 188 182 if (partOfSequence) { … … 199 193 public synchronized void selectionChanged(final SelectionChangeEvent event) { 200 194 final Collection<? extends OsmPrimitive> sel = event.getSelection(); 201 if (StreetsideProperties.DEBUGING_ENABLED.get()) { 202 logger.debug(String.format("Selection changed. %d primitives are selected.", sel == null ? 0 : sel.size())); 195 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 196 LOGGER.log(Logging.LEVEL_DEBUG, 197 String.format("Selection changed. %d primitives are selected.", sel == null ? 0 : sel.size())); 203 198 } 204 199 addStreetsideTagAction.setTarget(sel != null && sel.size() == 1 ? sel.iterator().next() : null); -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/StreetsideViewerHelpPopup.java
r34412 r36194 8 8 import java.awt.event.ActionEvent; 9 9 import java.text.MessageFormat; 10 import java.util.logging.Logger; 10 11 11 12 import javax.swing.AbstractAction; … … 15 16 import javax.swing.JTextPane; 16 17 17 import org.apache.log4j.Logger;18 18 import org.openstreetmap.josm.plugins.streetside.gui.boilerplate.SelectableLabel; 19 19 import org.openstreetmap.josm.plugins.streetside.gui.boilerplate.StreetsideButton; … … 22 22 import org.openstreetmap.josm.tools.I18n; 23 23 import org.openstreetmap.josm.tools.ImageProvider; 24 24 import org.openstreetmap.josm.tools.Logging; 25 25 26 26 public class StreetsideViewerHelpPopup extends JPopupMenu { 27 27 28 28 private static final long serialVersionUID = -7840242522398163839L; 29 29 30 final static Logger logger = Logger.getLogger(StreetsideViewerHelpPopup.class);30 private static final Logger LOGGER = Logger.getLogger(StreetsideViewerHelpPopup.class.getCanonicalName()); 31 31 32 33 32 private final Component invokerComp; 33 private boolean alreadyDisplayed; 34 34 35 35 public StreetsideViewerHelpPopup(Component invoker) { 36 36 37 38 39 37 invokerComp = invoker; 38 removeAll(); 39 setLayout(new BorderLayout()); 40 40 41 42 43 44 41 JPanel topBar = new JPanel(); 42 topBar.add(new JLabel(ImageProvider.get("streetside-logo-white"))); 43 topBar.setBackground(StreetsideColorScheme.TOOLBAR_DARK_GREY); 44 add(topBar, BorderLayout.NORTH); 45 45 46 JTextPane mainText = new JTextPane(); 47 mainText.setContentType("text/html"); 48 mainText.setFont(SelectableLabel.DEFAULT_FONT); 49 mainText.setText("<html><div style='width:250px'>" + 50 "Welcome to the Microsoft Streetside JOSM Plugin. To view the vector bubbles for the 360 degree imagery, select Imagery->Streetside from the JOSM menu." 51 + "<br><br>" 52 + 53 "Once the blue bubbles appear on the map, click on a vector bubble and undock/maximize the 360 viewer to view the imagery." 54 + "</div></html>"); 55 add(mainText, BorderLayout.CENTER); 46 JTextPane mainText = new JTextPane(); 47 mainText.setContentType("text/html"); 48 mainText.setFont(SelectableLabel.DEFAULT_FONT); 49 mainText.setText("<html><div style='width:250px'>" 50 + "Welcome to the Microsoft Streetside JOSM Plugin. To view the vector bubbles for the 360 degree imagery, select Imagery->Streetside from the JOSM menu." 51 + "<br><br>" 52 + "Once the blue bubbles appear on the map, click on a vector bubble and undock/maximize the 360 viewer to view the imagery." 53 + "</div></html>"); 54 add(mainText, BorderLayout.CENTER); 56 55 57 58 59 60 61 62 63 56 JPanel bottomBar = new JPanel(); 57 bottomBar.setBackground(new Color(0x00FFFFFF, true)); 58 StreetsideButton infoButton = new StreetsideButton(ImageInfoPanel.getInstance().getToggleAction()); 59 infoButton.addActionListener(e -> setVisible(false)); 60 bottomBar.add(infoButton); 61 StreetsideButton closeBtn = new StreetsideButton(new AbstractAction() { 62 private static final long serialVersionUID = -6193886964751195196L; 64 63 65 66 67 68 69 70 64 @Override 65 public void actionPerformed(ActionEvent e) { 66 setVisible(false); 67 StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.put(0); 68 } 69 }); 71 70 72 73 bottomBar.add(closeBtn);74 add(bottomBar, BorderLayout.SOUTH);71 closeBtn.setText(I18n.tr("I got it, close this.")); 72 bottomBar.add(closeBtn); 73 add(bottomBar, BorderLayout.SOUTH); 75 74 76 setBackground(Color.WHITE); 75 setBackground(Color.WHITE); 76 } 77 78 /** 79 * @return <code>true</code> if the popup is displayed 80 */ 81 public boolean showPopup() { 82 if (!alreadyDisplayed && invokerComp.isShowing()) { 83 try { 84 show(invokerComp, invokerComp.getWidth(), 0); 85 alreadyDisplayed = true; 86 return true; 87 } catch (IllegalComponentStateException e) { 88 LOGGER.log(Logging.LEVEL_ERROR, MessageFormat.format( 89 "Could not show ImageInfoHelpPopup, because probably the invoker component has disappeared from screen. {0}", 90 e.getMessage()), e); 91 } 92 } 93 return false; 94 } 77 95 } 78 79 /**80 * @return <code>true</code> if the popup is displayed81 */82 public boolean showPopup() {83 if (!alreadyDisplayed && invokerComp.isShowing()) {84 try {85 show(invokerComp, invokerComp.getWidth(), 0);86 alreadyDisplayed = true;87 return true;88 } catch (IllegalComponentStateException e) {89 logger.error(MessageFormat.format("Could not show ImageInfoHelpPopup, because probably the invoker component has disappeared from screen. {0}", e.getMessage()));90 }91 }92 return false;93 }94 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/StreetsideViewerPanel.java
r36065 r36194 1 // License: GPL. For details, see LICENSE file.1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.plugins.streetside.gui.imageinfo; 3 3 … … 5 5 import java.awt.GraphicsEnvironment; 6 6 import java.text.MessageFormat; 7 import java.util.logging.Logger; 7 8 8 9 import javax.swing.JCheckBox; … … 10 11 import javax.swing.SwingUtilities; 11 12 12 import org.apache.log4j.Logger;13 13 import org.openstreetmap.josm.data.preferences.AbstractProperty.ValueChangeListener; 14 14 import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage; … … 24 24 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL; 25 25 import org.openstreetmap.josm.tools.I18n; 26 import org.openstreetmap.josm.tools.Logging; 26 27 27 public final class StreetsideViewerPanel extends JPanel 28 implements StreetsideDataListener { 28 public final class StreetsideViewerPanel extends JPanel implements StreetsideDataListener { 29 29 30 30 private static final long serialVersionUID = 4141847503072417190L; 31 31 32 final static Logger logger = Logger.getLogger(StreetsideViewerPanel.class); 33 34 private JCheckBox highResImageryCheck; 35 private WebLinkAction imgLinkAction; 36 private ImageReloadAction imgReloadAction; 37 private ValueChangeListener<Boolean> imageLinkChangeListener; 38 39 private static ThreeSixtyDegreeViewerPanel threeSixtyDegreeViewerPanel; 40 32 private static final Logger LOGGER = Logger.getLogger(StreetsideViewerPanel.class.getCanonicalName()); 33 private static ThreeSixtyDegreeViewerPanel threeSixtyDegreeViewerPanel; 34 private JCheckBox highResImageryCheck; 35 private WebLinkAction imgLinkAction; 36 private ImageReloadAction imgReloadAction; 37 private ValueChangeListener<Boolean> imageLinkChangeListener; 41 38 private StreetsideViewerHelpPopup streetsideViewerHelp; 42 39 43 40 public StreetsideViewerPanel() { 44 41 45 42 super(new BorderLayout()); 46 43 47 SwingUtilities.invokeLater(() -> initializeAndStartGUI());44 SwingUtilities.invokeLater(this::initializeAndStartGUI); 48 45 49 46 selectedImageChanged(null, null); 50 47 51 setToolTipText(I18n.tr("Select Microsoft Streetside from the Imagery menu, then click on a blue vector bubble..")); 52 } 48 setToolTipText( 49 I18n.tr("Select Microsoft Streetside from the Imagery menu, then click on a blue vector bubble..")); 50 } 53 51 54 private void initializeAndStartGUI() { 52 public static CubemapBox getCubemapBox() { 53 return threeSixtyDegreeViewerPanel.getCubemapBox(); 54 } 55 55 56 threeSixtyDegreeViewerPanel = new ThreeSixtyDegreeViewerPanel(); 56 /** 57 * @return the threeSixtyDegreeViewerPanel 58 */ 59 public static ThreeSixtyDegreeViewerPanel getThreeSixtyDegreeViewerPanel() { 60 return threeSixtyDegreeViewerPanel; 61 } 62 63 private void initializeAndStartGUI() { 64 65 threeSixtyDegreeViewerPanel = new ThreeSixtyDegreeViewerPanel(); 57 66 58 67 if (!GraphicsEnvironment.isHeadless()) { … … 60 69 } 61 70 62 63 64 65 71 add(threeSixtyDegreeViewerPanel, BorderLayout.CENTER); 72 revalidate(); 73 repaint(); 74 JPanel checkPanel = new JPanel(); 66 75 67 76 imgReloadAction = new ImageReloadAction("Reload"); 68 77 69 78 StreetsideButton imgReloadButton = new StreetsideButton(imgReloadAction); 70 79 71 highResImageryCheck = new JCheckBox("High resolution"); 72 highResImageryCheck.setSelected(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()); 73 highResImageryCheck.addActionListener( 74 action -> StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.put(highResImageryCheck.isSelected()) 75 ); 76 StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.addListener( 77 valueChange -> highResImageryCheck.setSelected(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) 78 ); 79 checkPanel.add(highResImageryCheck, BorderLayout.WEST); 80 checkPanel.add(imgReloadButton, BorderLayout.EAST); 80 highResImageryCheck = new JCheckBox("High resolution"); 81 highResImageryCheck.setSelected(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()); 82 highResImageryCheck.addActionListener( 83 action -> StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.put(highResImageryCheck.isSelected())); 84 StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.addListener(valueChange -> highResImageryCheck 85 .setSelected(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get())); 86 checkPanel.add(highResImageryCheck, BorderLayout.WEST); 87 checkPanel.add(imgReloadButton, BorderLayout.EAST); 81 88 82 89 JPanel privacyLink = new JPanel(); 83 90 84 85 86 91 imgLinkAction = new WebLinkAction("Report a privacy concern with this image", null); 92 privacyLink.add(new StreetsideButton(imgLinkAction, true)); 93 checkPanel.add(privacyLink, BorderLayout.PAGE_END); 87 94 88 95 add(threeSixtyDegreeViewerPanel, BorderLayout.CENTER); 89 96 90 91 92 97 JPanel bottomPanel = new JPanel(); 98 bottomPanel.add(checkPanel, BorderLayout.NORTH); 99 bottomPanel.add(privacyLink, BorderLayout.SOUTH); 93 100 94 95 101 add(bottomPanel, BorderLayout.PAGE_END); 102 } 96 103 97 98 99 100 101 102 103 104 105 106 107 104 /* 105 * (non-Javadoc) 106 * 107 * @see 108 * org.openstreetmap.josm.plugins.streetside.StreetsideDataListener#imagesAdded( 109 * ) 110 */ 111 @Override 112 public void imagesAdded() { 113 // Method is not needed, but enforcesd by the interface StreetsideDataListener 114 } 108 115 109 110 111 112 113 114 115 116 117 118 119 116 /* 117 * (non-Javadoc) 118 * 119 * @see org.openstreetmap.josm.plugins.streetside.StreetsideDataListener# 120 * selectedImageChanged(org.openstreetmap.josm.plugins.streetside. 121 * StreetsideAbstractImage, 122 * org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage) 123 */ 124 @Override 125 public synchronized void selectedImageChanged(final StreetsideAbstractImage oldImage, 126 final StreetsideAbstractImage newImage) { 120 127 121 122 if(newImage!=null) {128 // method is invoked with null initially by framework 129 if (newImage != null) { 123 130 124 logger.info(String.format( 125 "Selected Streetside image changed from %s to %s.", 126 oldImage instanceof StreetsideImage ? ((StreetsideImage) oldImage).getId() : "‹none›", 127 newImage instanceof StreetsideImage ? ((StreetsideImage) newImage).getId() : "‹none›" 128 )); 131 LOGGER.info(String.format("Selected Streetside image changed from %s to %s.", 132 oldImage instanceof StreetsideImage ? oldImage.getId() : "‹none›", 133 newImage instanceof StreetsideImage ? newImage.getId() : "‹none›")); 129 134 130 final String newImageId = CubemapBuilder.getInstance().getCubemap() !=null ? CubemapBuilder.getInstance().getCubemap().getId() : newImage instanceof StreetsideImage ? ((StreetsideImage) newImage).getId(): null; 131 if (newImageId != null) { 132 final String bubbleId = CubemapUtils.convertQuaternary2Decimal(newImageId); 133 imageLinkChangeListener = b -> imgLinkAction.setURL( 134 StreetsideURL.MainWebsite.streetsidePrivacyLink(bubbleId) 135 ); 135 final String newImageId = CubemapBuilder.getInstance().getCubemap() != null 136 ? CubemapBuilder.getInstance().getCubemap().getId() 137 : newImage instanceof StreetsideImage ? ((StreetsideImage) newImage).getId() : null; 138 if (newImageId != null) { 139 final String bubbleId = CubemapUtils.convertQuaternary2Decimal(newImageId); 140 imageLinkChangeListener = b -> imgLinkAction 141 .setURL(StreetsideURL.MainWebsite.streetsidePrivacyLink(bubbleId)); 136 142 137 if(StreetsideProperties.DEBUGING_ENABLED.get()) { 138 logger.debug(MessageFormat.format("Privacy link set for Streetside image {0} quadKey {1}", bubbleId, newImageId)); 139 } 143 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 144 LOGGER.log(Logging.LEVEL_DEBUG, MessageFormat 145 .format("Privacy link set for Streetside image {0} quadKey {1}", bubbleId, newImageId)); 146 } 140 147 141 imageLinkChangeListener.valueChanged(null); 142 StreetsideProperties.CUBEMAP_LINK_TO_BLUR_EDITOR.addListener(imageLinkChangeListener); 143 } else { 144 if (imageLinkChangeListener != null) { 145 StreetsideProperties.CUBEMAP_LINK_TO_BLUR_EDITOR.removeListener(imageLinkChangeListener); 146 imageLinkChangeListener = null; 147 } 148 imgLinkAction.setURL(null); 149 } 150 } 151 } 152 153 public static CubemapBox getCubemapBox() { 154 return threeSixtyDegreeViewerPanel.getCubemapBox(); 155 } 156 157 /** 158 * @return the threeSixtyDegreeViewerPanel 159 */ 160 public static ThreeSixtyDegreeViewerPanel getThreeSixtyDegreeViewerPanel() { 161 return threeSixtyDegreeViewerPanel; 162 } 148 imageLinkChangeListener.valueChanged(null); 149 StreetsideProperties.CUBEMAP_LINK_TO_BLUR_EDITOR.addListener(imageLinkChangeListener); 150 } else { 151 if (imageLinkChangeListener != null) { 152 StreetsideProperties.CUBEMAP_LINK_TO_BLUR_EDITOR.removeListener(imageLinkChangeListener); 153 imageLinkChangeListener = null; 154 } 155 imgLinkAction.setURL(null); 156 } 157 } 158 } 163 159 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ThreeSixtyDegreeViewerPanel.java
r34774 r36194 1 // License: GPL. For details, see LICENSE file.1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.plugins.streetside.gui.imageinfo; 3 3 … … 11 11 import javafx.scene.PointLight; 12 12 import javafx.scene.Scene; 13 import javafx.scene.SceneAntialiasing; 13 14 import javafx.scene.control.Label; 14 import javafx.scene.SceneAntialiasing;15 15 import javafx.scene.control.TextArea; 16 16 import javafx.scene.image.Image; … … 26 26 27 27 private static final long serialVersionUID = -4940350009018422000L; 28 28 private static final CameraTransformer cameraTransform = new CameraTransformer(); 29 private static final double cameraDistance = 5000; 29 30 private static Scene cubemapScene; 30 31 31 private static Scene defaultScene; 32 32 private static Scene loadingScene; 33 34 33 private static Group root; 35 34 private static Group subGroup; 36 35 private static CubemapBox cubemapBox; 37 36 private static PerspectiveCamera camera; 38 private static CameraTransformer cameraTransform = new CameraTransformer();39 40 37 private static double mousePosX; 41 38 private static double mousePosY; … … 44 41 private static double mouseDeltaX; 45 42 private static double mouseDeltaY; 46 private static double cameraDistance = 5000;47 48 43 private static Image front; 49 44 private static Image right; … … 55 50 public ThreeSixtyDegreeViewerPanel() { 56 51 57 }58 59 public void initialize() {60 61 root = new Group();62 63 camera = new PerspectiveCamera(true);64 cameraTransform.setTranslate(0, 0, 0);65 cameraTransform.getChildren().addAll(camera);66 camera.setNearClip(0.1);67 camera.setFarClip(1000000.0);68 camera.setFieldOfView(42);69 camera.setTranslateZ(-cameraDistance);70 final PointLight light = new PointLight(Color.WHITE);71 72 cameraTransform.getChildren().add(light);73 light.setTranslateX(camera.getTranslateX());74 light.setTranslateY(camera.getTranslateY());75 light.setTranslateZ(camera.getTranslateZ());76 77 root.getChildren().add(cameraTransform);78 79 final double size = 100000D;80 81 cubemapBox = new CubemapBox(front, right, back, left, up, down, size, camera);82 83 subGroup = new Group();84 subGroup.getChildren().add(cameraTransform);85 86 createLoadingScene();87 88 Platform.runLater(new Runnable() {89 @Override90 public void run() {91 setScene(createDefaultScene());92 }93 });94 52 } 95 53 … … 177 135 if (me.isPrimaryButtonDown()) { 178 136 cameraTransform.ry.setAngle( 179 ((cameraTransform.ry.getAngle() + mouseDeltaX * modifierFactor * modifier * 2.0) % 360 + 540) % 360 - 180180 ); // +137 ((cameraTransform.ry.getAngle() + mouseDeltaX * modifierFactor * modifier * 2.0) % 360 + 540) 138 % 360 - 180); // + 181 139 cameraTransform.rx.setAngle( 182 ((cameraTransform.rx.getAngle() - mouseDeltaY * modifierFactor * modifier * 2.0) % 360 + 540) % 360 - 180183 ); // -140 ((cameraTransform.rx.getAngle() - mouseDeltaY * modifierFactor * modifier * 2.0) % 360 + 540) 141 % 360 - 180); // - 184 142 185 143 } else if (me.isSecondaryButtonDown()) { … … 212 170 } 213 171 172 public void initialize() { 173 174 root = new Group(); 175 176 camera = new PerspectiveCamera(true); 177 cameraTransform.setTranslate(0, 0, 0); 178 cameraTransform.getChildren().addAll(camera); 179 camera.setNearClip(0.1); 180 camera.setFarClip(1000000.0); 181 camera.setFieldOfView(42); 182 camera.setTranslateZ(-cameraDistance); 183 final PointLight light = new PointLight(Color.WHITE); 184 185 cameraTransform.getChildren().add(light); 186 light.setTranslateX(camera.getTranslateX()); 187 light.setTranslateY(camera.getTranslateY()); 188 light.setTranslateZ(camera.getTranslateZ()); 189 190 root.getChildren().add(cameraTransform); 191 192 final double size = 100000D; 193 194 cubemapBox = new CubemapBox(front, right, back, left, up, down, size, camera); 195 196 subGroup = new Group(); 197 subGroup.getChildren().add(cameraTransform); 198 199 createLoadingScene(); 200 201 Platform.runLater(() -> setScene(createDefaultScene())); 202 } 203 214 204 public CubemapBox getCubemapBox() { 215 205 if (cubemapBox == null) { -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/WebLinkAction.java
r34416 r36194 5 5 import java.io.IOException; 6 6 import java.net.URL; 7 import java.util.logging.Logger; 7 8 8 9 import javax.swing.AbstractAction; 9 10 import javax.swing.JOptionPane; 10 11 11 import org.apache.log4j.Logger;12 12 import org.openstreetmap.josm.gui.Notification; 13 13 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideUtils; 14 14 import org.openstreetmap.josm.tools.ImageProvider; 15 15 import org.openstreetmap.josm.tools.ImageProvider.ImageSizes; 16 import org.openstreetmap.josm.tools.Logging; 16 17 17 18 public class WebLinkAction extends AbstractAction { … … 19 20 private static final long serialVersionUID = -8168227661356480455L; 20 21 21 final static Logger logger = Logger.getLogger(WebLinkAction.class);22 private static final Logger LOGGER = Logger.getLogger(WebLinkAction.class.getCanonicalName()); 22 23 23 24 private URL url; … … 45 46 } catch (IOException e1) { 46 47 String msg = "Could not open the URL " + url == null ? "‹null›" : url + " in a browser"; 47 logger.warn(msg, e1);48 LOGGER.log(Logging.LEVEL_WARN, msg, e1); 48 49 new Notification(msg).setIcon(JOptionPane.WARNING_MESSAGE).show(); 49 50 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/StreetsideRecord.java
r34400 r36194 17 17 */ 18 18 public class StreetsideRecord { 19 /** The unique instance of the class. */ 20 private static StreetsideRecord instance; 19 /** 20 * The unique instance of the class. 21 */ 22 private static StreetsideRecord instance; 21 23 22 private final List<StreetsideRecordListener> listeners = new ArrayList<>();24 private final List<StreetsideRecordListener> listeners = new ArrayList<>(); 23 25 24 /** The set of commands that have taken place or that have been undone. */ 25 public List<StreetsideCommand> commandList; 26 /** Last written command. */ 27 public int position; 26 /** 27 * The set of commands that have taken place or that have been undone. 28 */ 29 public List<StreetsideCommand> commandList; 30 /** 31 * Last written command. 32 */ 33 public int position; 28 34 29 /** 30 * Main constructor. 31 */ 32 public StreetsideRecord() { 33 this.commandList = new ArrayList<>(); 34 this.position = -1; 35 /** 36 * Main constructor. 37 */ 38 public StreetsideRecord() { 39 this.commandList = new ArrayList<>(); 40 this.position = -1; 41 } 42 43 /** 44 * Returns the unique instance of the class. 45 * 46 * @return The unique instance of the class. 47 */ 48 public static synchronized StreetsideRecord getInstance() { 49 if (StreetsideRecord.instance == null) 50 StreetsideRecord.instance = new StreetsideRecord(); 51 return StreetsideRecord.instance; 52 } 53 54 /** 55 * Adds a listener. 56 * 57 * @param lis The listener to be added. 58 */ 59 public void addListener(StreetsideRecordListener lis) { 60 this.listeners.add(lis); 61 } 62 63 /** 64 * Removes the given listener. 65 * 66 * @param lis The listener to be removed. 67 */ 68 public void removeListener(StreetsideRecordListener lis) { 69 this.listeners.remove(lis); 70 } 71 72 /** 73 * Adds a new command to the list. 74 * 75 * @param command The command to be added. 76 */ 77 public void addCommand(final StreetsideCommand command) { 78 79 if (command instanceof StreetsideExecutableCommand) 80 ((StreetsideExecutableCommand) command).execute(); 81 // Checks if it is a continuation of last command 82 if (this.position != -1) { 83 boolean equalSets = true; 84 for (StreetsideAbstractImage img : this.commandList.get(this.position).images) { 85 equalSets = command.images.contains(img) && equalSets; 86 } 87 for (StreetsideAbstractImage img : command.images) { 88 equalSets = this.commandList.get(this.position).images.contains(img) && equalSets; 89 } 90 if (equalSets && this.commandList.get(this.position).getClass() == command.getClass()) { 91 this.commandList.get(this.position).sum(command); 92 fireRecordChanged(); 93 return; 94 } 95 } 96 // Adds the command to the last position of the list. 97 this.commandList.add(this.position + 1, command); 98 this.position++; 99 while (this.commandList.size() > this.position + 1) { 100 this.commandList.remove(this.position + 1); 101 } 102 fireRecordChanged(); 103 } 104 105 /** 106 * Undo latest command. 107 */ 108 public void undo() { 109 if (this.position <= -1) { 110 return; 111 } 112 this.commandList.get(this.position).undo(); 113 this.position--; 114 fireRecordChanged(); 115 } 116 117 /** 118 * Redoes latest undone action. 119 */ 120 public void redo() { 121 if (position + 1 >= commandList.size()) { 122 return; 123 } 124 this.position++; 125 this.commandList.get(this.position).redo(); 126 fireRecordChanged(); 127 } 128 129 private void fireRecordChanged() { 130 this.listeners.stream().filter(Objects::nonNull).forEach(StreetsideRecordListener::recordChanged); 131 } 132 133 /** 134 * Resets the object to its start state. 135 */ 136 public void reset() { 137 this.commandList.clear(); 138 this.position = -1; 139 } 35 140 } 36 37 /**38 * Returns the unique instance of the class.39 *40 * @return The unique instance of the class.41 */42 public static synchronized StreetsideRecord getInstance() {43 if (StreetsideRecord.instance == null)44 StreetsideRecord.instance = new StreetsideRecord();45 return StreetsideRecord.instance;46 }47 48 /**49 * Adds a listener.50 *51 * @param lis52 * The listener to be added.53 */54 public void addListener(StreetsideRecordListener lis) {55 this.listeners.add(lis);56 }57 58 /**59 * Removes the given listener.60 *61 * @param lis62 * The listener to be removed.63 */64 public void removeListener(StreetsideRecordListener lis) {65 this.listeners.remove(lis);66 }67 68 /**69 * Adds a new command to the list.70 *71 * @param command72 * The command to be added.73 */74 public void addCommand(final StreetsideCommand command) {75 76 if (command instanceof StreetsideExecutableCommand)77 ((StreetsideExecutableCommand) command).execute();78 // Checks if it is a continuation of last command79 if (this.position != -1) {80 boolean equalSets = true;81 for (StreetsideAbstractImage img : this.commandList.get(this.position).images) {82 equalSets = command.images.contains(img) && equalSets;83 }84 for (StreetsideAbstractImage img : command.images) {85 equalSets = this.commandList.get(this.position).images.contains(img) && equalSets;86 }87 if (equalSets && this.commandList.get(this.position).getClass() == command.getClass()) {88 this.commandList.get(this.position).sum(command);89 fireRecordChanged();90 return;91 }92 }93 // Adds the command to the last position of the list.94 this.commandList.add(this.position + 1, command);95 this.position++;96 while (this.commandList.size() > this.position + 1) {97 this.commandList.remove(this.position + 1);98 }99 fireRecordChanged();100 }101 102 /**103 * Undo latest command.104 */105 public void undo() {106 if (this.position <= -1) {107 return;108 }109 this.commandList.get(this.position).undo();110 this.position--;111 fireRecordChanged();112 }113 114 /**115 * Redoes latest undone action.116 */117 public void redo() {118 if (position + 1 >= commandList.size()) {119 return;120 }121 this.position++;122 this.commandList.get(this.position).redo();123 fireRecordChanged();124 }125 126 private void fireRecordChanged() {127 this.listeners.stream().filter(Objects::nonNull).forEach(StreetsideRecordListener::recordChanged);128 }129 130 /**131 * Resets the object to its start state.132 */133 public void reset() {134 this.commandList.clear();135 this.position = -1;136 }137 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/StreetsideRecordListener.java
r34317 r36194 11 11 public interface StreetsideRecordListener { 12 12 13 /**14 * Fired when any command is undone or redone.15 */16 void recordChanged();13 /** 14 * Fired when any command is undone or redone. 15 */ 16 void recordChanged(); 17 17 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandJoin.java
r34317 r36194 27 27 * @param b the second image, that is joined with the first one 28 28 * @throws IllegalArgumentException if the images are already in the same sequence 29 * @throws NullPointerException if {@code a} or {@code b} is null29 * @throws NullPointerException if {@code a} or {@code b} is null 30 30 */ 31 31 public CommandJoin(final StreetsideAbstractImage a, final StreetsideAbstractImage b) { -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandMove.java
r34416 r36194 22 22 * Main constructor. 23 23 * 24 * @param images 25 * Set of images that are going to be moved. 26 * @param x 27 * How much the x coordinate increases. 28 * @param y 29 * How much the y coordinate increases. 24 * @param images Set of images that are going to be moved. 25 * @param x How much the x coordinate increases. 26 * @param y How much the y coordinate increases. 30 27 */ 31 public CommandMove(Set<StreetsideAbstractImage> images, double x, 32 double y) { 28 public CommandMove(Set<StreetsideAbstractImage> images, double x, double y) { 33 29 super(images); 34 30 this.x = x; … … 56 52 @Override 57 53 public String toString() { 58 return trn("Moved {0} image", "Moved {0} images", images.size(), 59 images.size()); 54 return trn("Moved {0} image", "Moved {0} images", images.size(), images.size()); 60 55 } 61 56 -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandTurn.java
r34432 r36194 21 21 * Main constructor. 22 22 * 23 * @param images 24 * Set of images that is turned. 25 * @param ca 26 * How much the images turn. 23 * @param images Set of images that is turned. 24 * @param ca How much the images turn. 27 25 */ 28 26 public CommandTurn(Set<StreetsideAbstractImage> images, double ca) { … … 51 49 @Override 52 50 public String toString() { 53 return trn("Turned {0} image", "Turned {0} images", images.size(), 54 images.size()); 51 return trn("Turned {0} image", "Turned {0} images", images.size(), images.size()); 55 52 } 56 53 -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandUnjoin.java
r34416 r36194 24 24 * Main constructor. 25 25 * 26 * @param images 27 * The two images that are going to be unjoined. Must be of exactly 28 * size 2. 29 * @throws IllegalArgumentException 30 * if the List size is different from 2. 26 * @param images The two images that are going to be unjoined. Must be of exactly 27 * size 2. 28 * @throws IllegalArgumentException if the List size is different from 2. 31 29 */ 32 30 public CommandUnjoin(List<StreetsideAbstractImage> images) { -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/StreetsideCommand.java
r34317 r36194 14 14 */ 15 15 public abstract class StreetsideCommand { 16 /** Set of {@link StreetsideAbstractImage} objects affected by the command */ 17 public Set<StreetsideAbstractImage> images; 16 /** 17 * Set of {@link StreetsideAbstractImage} objects affected by the command 18 */ 19 public Set<StreetsideAbstractImage> images; 18 20 19 /** 20 * Main constructor. 21 * 22 * @param images 23 * The images that are affected by the command. 24 */ 25 public StreetsideCommand(Set<StreetsideAbstractImage> images) { 26 this.images = new ConcurrentSkipListSet<>(images); 21 /** 22 * Main constructor. 23 * 24 * @param images The images that are affected by the command. 25 */ 26 protected StreetsideCommand(Set<StreetsideAbstractImage> images) { 27 this.images = new ConcurrentSkipListSet<>(images); 28 } 29 30 /** 31 * Undoes the action. 32 */ 33 public abstract void undo(); 34 35 /** 36 * Redoes the action. 37 */ 38 public abstract void redo(); 39 40 /** 41 * If two equal commands are applied consecutively to the same set of images, 42 * they are summed in order to reduce them to just one command. 43 * 44 * @param command The command to be summed to last command. 45 */ 46 public abstract void sum(StreetsideCommand command); 47 48 @Override 49 public abstract String toString(); 27 50 } 28 29 /**30 * Undoes the action.31 */32 public abstract void undo();33 34 /**35 * Redoes the action.36 */37 public abstract void redo();38 39 /**40 * If two equal commands are applied consecutively to the same set of images,41 * they are summed in order to reduce them to just one command.42 *43 * @param command44 * The command to be summed to last command.45 */46 public abstract void sum(StreetsideCommand command);47 48 @Override49 public abstract String toString();50 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/StreetsideExecutableCommand.java
r34317 r36194 14 14 public abstract class StreetsideExecutableCommand extends StreetsideCommand { 15 15 16 /** 17 * Main constructor. 18 * 19 * @param images 20 * The set of images affected by the command. 21 */ 22 public StreetsideExecutableCommand(Set<StreetsideAbstractImage> images) { 23 super(images); 16 /** 17 * Main constructor. 18 * 19 * @param images The set of images affected by the command. 20 */ 21 protected StreetsideExecutableCommand(Set<StreetsideAbstractImage> images) { 22 super(images); 23 } 24 25 /** 26 * Executes the command. It is run when the command is added to the history 27 * record. 28 */ 29 public abstract void execute(); 24 30 } 25 26 /**27 * Executes the command. It is run when the command is added to the history28 * record.29 */30 public abstract void execute();31 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/BoundsDownloadRunnable.java
r34432 r36194 7 7 import java.net.URL; 8 8 import java.net.URLConnection; 9 import java.text.MessageFormat;10 9 import java.util.function.Function; 10 import java.util.logging.Logger; 11 11 12 import org.apache.log4j.Logger;13 12 import org.openstreetmap.josm.data.Bounds; 14 13 import org.openstreetmap.josm.gui.Notification; … … 17 16 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3; 18 17 import org.openstreetmap.josm.tools.ImageProvider.ImageSizes; 18 import org.openstreetmap.josm.tools.Logging; 19 19 20 20 public abstract class BoundsDownloadRunnable implements Runnable { 21 21 22 final static Logger logger = Logger.getLogger(BoundsDownloadRunnable.class);22 private static final Logger LOGGER = Logger.getLogger(BoundsDownloadRunnable.class.getCanonicalName()); 23 23 24 24 protected Bounds bounds; 25 protected abstract Function<Bounds, URL> getUrlGenerator();26 25 27 p ublicBoundsDownloadRunnable(final Bounds bounds) {26 protected BoundsDownloadRunnable(final Bounds bounds) { 28 27 this.bounds = bounds; 29 28 } 29 30 /** 31 * Logs information about the given connection via {@link Logger}. 32 * If it's a {@link HttpURLConnection}, the request method, the response code and the URL itself are logged. 33 * Otherwise only the URL is logged. 34 * 35 * @param con the {@link URLConnection} for which information is logged 36 * @param info an additional info text, which is appended to the output in braces 37 * @throws IOException if {@link HttpURLConnection#getResponseCode()} throws an {@link IOException} 38 */ 39 public static void logConnectionInfo(final URLConnection con, final String info) throws IOException { 40 final StringBuilder message; 41 if (con instanceof HttpURLConnection) { 42 message = new StringBuilder(((HttpURLConnection) con).getRequestMethod()).append(' ').append(con.getURL()) 43 .append(" → ").append(((HttpURLConnection) con).getResponseCode()); 44 } else { 45 message = new StringBuilder("Download from ").append(con.getURL()); 46 } 47 if (info != null && info.length() >= 1) { 48 message.append(" (").append(info).append(')'); 49 } 50 LOGGER.info(message::toString); 51 } 52 53 protected abstract Function<Bounds, URL> getUrlGenerator(); 30 54 31 55 @Override 32 56 public void run() { 33 57 URL nextURL = getUrlGenerator().apply(bounds); 34 if (StreetsideProperties.DEBUGING_ENABLED.get()) {35 logger.debug(MessageFormat.format("Downloading bounds: URL: {0}", nextURL.toString()));58 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 59 LOGGER.log(Logging.LEVEL_DEBUG, "Downloading bounds: URL: {0}", nextURL); 36 60 } 37 61 try { 38 62 while (nextURL != null) { 39 63 if (Thread.interrupted()) { 40 logger.error(getClass().getSimpleName() + " for " + bounds.toString() + " interrupted!"); 64 LOGGER.log(Logging.LEVEL_ERROR, "{0} for {1} interrupted!", 65 new Object[] { getClass().getSimpleName(), bounds }); 41 66 return; 42 67 } … … 46 71 } 47 72 } catch (IOException e) { 48 String message = "Could not read from URL " + nextURL.toString()+ "!";49 logger.warn(message, e);73 String message = "Could not read from URL " + nextURL + "!"; 74 LOGGER.log(Logging.LEVEL_WARN, message, e); 50 75 if (!GraphicsEnvironment.isHeadless()) { 51 new Notification(message) 52 .setIcon(StreetsidePlugin.LOGO.setSize(ImageSizes.LARGEICON).get()) 53 .setDuration(Notification.TIME_LONG) 54 .show(); 76 new Notification(message).setIcon(StreetsidePlugin.LOGO.setSize(ImageSizes.LARGEICON).get()) 77 .setDuration(Notification.TIME_LONG).show(); 55 78 } 56 e.printStackTrace();57 79 } 58 }59 60 /**61 * Logs information about the given connection via {@link Logger}.62 * If it's a {@link HttpURLConnection}, the request method, the response code and the URL itself are logged.63 * Otherwise only the URL is logged.64 * @param con the {@link URLConnection} for which information is logged65 * @param info an additional info text, which is appended to the output in braces66 * @throws IOException if {@link HttpURLConnection#getResponseCode()} throws an {@link IOException}67 */68 public static void logConnectionInfo(final URLConnection con, final String info) throws IOException {69 final StringBuilder message;70 if (con instanceof HttpURLConnection) {71 message = new StringBuilder(((HttpURLConnection) con).getRequestMethod())72 .append(' ').append(con.getURL())73 .append(" → ").append(((HttpURLConnection) con).getResponseCode());74 } else {75 message = new StringBuilder("Download from ").append(con.getURL());76 }77 if (info != null && info.length() >= 1) {78 message.append(" (").append(info).append(')');79 }80 logger.info(message.toString());81 80 } 82 81 -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/SequenceDownloadRunnable.java
r34433 r36194 2 2 package org.openstreetmap.josm.plugins.streetside.io.download; 3 3 4 import java.io.BufferedInputStream;5 4 import java.io.IOException; 6 5 import java.net.URL; … … 11 10 import java.util.List; 12 11 import java.util.function.Function; 12 import java.util.logging.Logger; 13 13 14 14 import org.openstreetmap.josm.data.Bounds; … … 22 22 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideSequenceIdGenerator; 23 23 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3; 24 import org.openstreetmap.josm.tools.Logging; 24 25 25 import com.fasterxml.jackson.core.JsonParseException; 26 import com.fasterxml.jackson.core.JsonParser; 27 import com.fasterxml.jackson.core.JsonToken; 28 import com.fasterxml.jackson.databind.DeserializationFeature; 29 import com.fasterxml.jackson.databind.JsonMappingException; 30 import com.fasterxml.jackson.databind.ObjectMapper; 31 import com.fasterxml.jackson.databind.node.ObjectNode; 26 import jakarta.json.Json; 27 import jakarta.json.JsonException; 28 import jakarta.json.JsonObject; 29 import jakarta.json.JsonValue; 30 import jakarta.json.stream.JsonParser; 32 31 33 32 public final class SequenceDownloadRunnable extends BoundsDownloadRunnable { 34 35 private final StreetsideData data; 36 33 private static final Logger LOG = Logger.getLogger(BoundsDownloadRunnable.class.getCanonicalName()); 37 34 private static final Function<Bounds, URL> URL_GEN = APIv3::searchStreetsideImages; 35 private final StreetsideData data; 38 36 39 37 public SequenceDownloadRunnable(final StreetsideData data, final Bounds bounds) { … … 54 52 final long startTime = System.currentTimeMillis(); 55 53 56 ObjectMapper mapper = new ObjectMapper();57 // Creation of Jackson Object Mapper necessary for Silverlight 2.0 JSON Syntax parsing:58 // (no double quotes in JSON on attribute names)59 mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);54 try (JsonParser parser = Json.createParser(con.getInputStream())) { 55 if (!parser.hasNext() || parser.next() != JsonParser.Event.START_ARRAY) { 56 throw new IllegalStateException("Expected an array"); 57 } 60 58 61 // Allow unrecognized properties - won't break with addition of new attributes 62 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); 59 StreetsideImage previous = null; 63 60 64 try { 65 JsonParser parser = mapper.getFactory().createParser(new BufferedInputStream(con.getInputStream())); 66 if(parser.nextToken() != JsonToken.START_ARRAY) { 67 parser.close(); 68 throw new IllegalStateException("Expected an array"); 69 } 70 71 StreetsideImage previous = null; 72 73 while (parser.nextToken() == JsonToken.START_OBJECT) { 61 while (parser.hasNext() && parser.next() == JsonParser.Event.START_OBJECT) { 74 62 // read everything from this START_OBJECT to the matching END_OBJECT 75 63 // and return it as a tree model ObjectNode 76 ObjectNode node = mapper.readTree(parser);64 JsonObject node = parser.getObject(); 77 65 // Discard the first sequence ('enabled') - it does not contain bubble data 78 66 if (node.get("id") != null && node.get("la") != null && node.get("lo") != null) { 79 StreetsideImage image = new StreetsideImage(CubemapUtils.convertDecimal2Quaternary(node.path("id").asLong()), new LatLon(node.path("la").asDouble(), node.get("lo").asDouble()), node.get("he").asDouble()); 80 if(previous!=null) { 67 StreetsideImage image = new StreetsideImage( 68 CubemapUtils.convertDecimal2Quaternary(node.getJsonNumber("id").longValue()), 69 new LatLon(node.getJsonNumber("la").doubleValue(), node.getJsonNumber("lo").doubleValue()), 70 node.getJsonNumber("he").doubleValue()); 71 if (previous != null) { 81 72 image.setPr(Long.parseLong(previous.getId())); 82 73 previous.setNe(Long.parseLong(image.getId())); … … 84 75 } 85 76 previous = image; 86 image.setAd(node.path("ad").asInt()); 87 image.setAl(node.path("al").asDouble()); 88 image.setBl(node.path("bl").asText()); 89 image.setMl(node.path("ml").asInt()); 90 image.setNbn(node.findValuesAsText("nbn")); 91 image.setNe(node.path("ne").asLong()); 92 image.setPbn(node.findValuesAsText("pbn")); 93 image.setPi(node.path("pi").asDouble()); 94 image.setPr(node.path("pr").asLong()); 95 image.setRo(node.path("ro").asDouble()); 77 if (node.containsKey("ad")) 78 image.setAd(node.getJsonNumber("ad").intValue()); 79 if (node.containsKey("al")) 80 image.setAl(node.getJsonNumber("al").doubleValue()); 81 if (node.containsKey("bl")) 82 image.setBl(node.getString("bl")); 83 if (node.containsKey("ml")) 84 image.setMl(node.getJsonNumber("ml").intValue()); 85 if (node.containsKey("ne")) 86 image.setNe(node.getJsonNumber("ne").longValue()); 87 if (node.containsKey("pi")) 88 image.setPi(node.getJsonNumber("pi").doubleValue()); 89 if (node.containsKey("pr")) 90 image.setPr(node.getJsonNumber("pr").longValue()); 91 if (node.containsKey("ro")) 92 image.setRo(node.getJsonNumber("ro").doubleValue()); 93 if (node.containsKey("nbn")) 94 image.setNbn(node.getJsonArray("nbn").getValuesAs(JsonValue::toString)); 95 if (node.containsKey("pbn")) 96 image.setPbn(node.getJsonArray("pbn").getValuesAs(JsonValue::toString)); 96 97 97 98 // Add list of cubemap tile images to images … … 103 104 // Initialize four-tiled cubemap faces (four images per cube side with 18-length 104 105 // Quadkey) 105 if ( !StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) {106 StreetsideImage tile = new StreetsideImage( String.valueOf(image.getId() + Integer.valueOf(i)));106 if (Boolean.FALSE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get())) { 107 StreetsideImage tile = new StreetsideImage(image.getId() + i); 107 108 tiles.add(tile); 108 109 } 109 110 // Initialize four-tiled cubemap faces (four images per cub eside with 20-length 110 111 // Quadkey) 111 if ( StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) {112 if (Boolean.TRUE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get())) { 112 113 for (int j = 0; j < 4; j++) { 113 StreetsideImage tile = new StreetsideImage( 114 String.valueOf( 115 image.getId() + face.getValue() + CubemapUtils.rowCol2StreetsideCellAddressMap 116 .get(String.valueOf(Integer.valueOf(i).toString() + Integer.valueOf(j).toString())) 117 )); 114 StreetsideImage tile = new StreetsideImage(image.getId() + face.getValue() 115 + CubemapUtils.rowCol2StreetsideCellAddressMap 116 .get(i + Integer.toString(j))); 118 117 tiles.add(tile); 119 118 } … … 122 121 }); 123 122 124 125 logger.info("Added image with id <" + image.getId() + ">");126 if ( StreetsideProperties.PREDOWNLOAD_CUBEMAPS.get()) {123 bubbleImages.add(image); 124 LOG.info("Added image with id <" + image.getId() + ">"); 125 if (Boolean.TRUE.equals(StreetsideProperties.PREDOWNLOAD_CUBEMAPS.get())) { 127 126 StreetsideData.downloadSurroundingCubemaps(image); 128 127 } 129 128 } else { 130 logger.info(MessageFormat.format("Unparsable JSON node object: {0}",node.toString()));129 LOG.info(MessageFormat.format("Unparsable JSON node object: {0}", node)); 131 130 } 132 131 } 133 134 parser.close(); 135 136 } catch (JsonParseException e) { 137 logger.error(MessageFormat.format("JSON parsing error occured during Streetside sequence download {0}",e.getMessage())); 138 } catch (JsonMappingException e) { 139 logger.error(MessageFormat.format("JSON mapping error occured during Streetside sequence download {0}",e.getMessage())); 132 } catch (ClassCastException | JsonException e) { 133 LOG.log(Logging.LEVEL_ERROR, e, () -> MessageFormat 134 .format("JSON parsing error occurred during Streetside sequence download {0}", e.getMessage())); 140 135 } catch (IOException e) { 141 logger.error(MessageFormat.format("Input/output error occured during Streetside sequence download {0}",e.getMessage())); 136 LOG.log(Logging.LEVEL_ERROR, e, () -> MessageFormat 137 .format("Input/output error occurred during Streetside sequence download {0}", e.getMessage())); 142 138 } 143 139 144 /** Top Level Bubble Metadata in Streetside are bubble (aka images) not Sequences 140 /* 141 * Top Level Bubble Metadata in Streetside are bubble (aka images) not Sequences 145 142 * so a sequence needs to be created and have images added to it. If the distribution 146 143 * of Streetside images is non-sequential, the Mapillary "Walking Action" may behave 147 144 * unpredictably. 148 * */145 */ 149 146 seq.add(bubbleImages); 150 147 151 if ( StreetsideProperties.CUT_OFF_SEQUENCES_AT_BOUNDS.get()) {148 if (Boolean.TRUE.equals(StreetsideProperties.CUT_OFF_SEQUENCES_AT_BOUNDS.get())) { 152 149 for (StreetsideAbstractImage img : seq.getImages()) { 153 150 if (bounds.contains(img.getLatLon())) { … … 168 165 169 166 final long endTime = System.currentTimeMillis(); 170 logger.info(MessageFormat.format("Sucessfully loaded {0} Microsoft Streetside images in {1} seconds.", seq.getImages().size(),(endTime-startTime)/1000)); 167 LOG.info(MessageFormat.format("Successfully loaded {0} Microsoft Streetside images in {1} seconds.", 168 seq.getImages().size(), (endTime - startTime) / 1000)); 171 169 } 172 170 -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/StreetsideDownloader.java
r34399 r36194 5 5 import java.util.concurrent.ThreadPoolExecutor; 6 6 import java.util.concurrent.TimeUnit; 7 8 import org.apache.log4j.Logger; 7 import java.util.logging.Logger; 8 9 9 import org.openstreetmap.josm.data.Bounds; 10 10 import org.openstreetmap.josm.data.coor.LatLon; … … 15 15 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties; 16 16 import org.openstreetmap.josm.tools.I18n; 17 import org.openstreetmap.josm.tools.Logging; 17 18 18 19 /** … … 24 25 public final class StreetsideDownloader { 25 26 26 final static Logger logger = Logger.getLogger(StreetsideDownloader.class); 27 28 /** Possible download modes. */ 27 private static final Logger LOGGER = Logger.getLogger(StreetsideDownloader.class.getCanonicalName()); 28 /** 29 * Max area to be downloaded 30 */ 31 private static final double MAX_AREA = StreetsideProperties.MAX_DOWNLOAD_AREA.get(); 32 /** 33 * Executor that will run the petitions. 34 */ 35 private static ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 5, 100, TimeUnit.SECONDS, 36 new ArrayBlockingQueue<>(100), new ThreadPoolExecutor.DiscardPolicy()); 37 /** 38 * Indicates whether the last download request has been rejected because it requested an area that was too big. 39 * Iff true, the last download has been rejected, if false, it was executed. 40 */ 41 private static boolean stoppedDownload; 42 43 private StreetsideDownloader() { 44 // Private constructor to avoid instantiation 45 } 46 47 /** 48 * Downloads all images of the area covered by the OSM data. 49 */ 50 public static void downloadOSMArea() { 51 if (MainApplication.getLayerManager().getEditLayer() == null) { 52 return; 53 } 54 if (isAreaTooBig(MainApplication.getLayerManager().getEditLayer().data.getDataSourceBounds().stream() 55 .map(Bounds::getArea).reduce(0.0, Double::sum))) { 56 return; 57 } 58 MainApplication.getLayerManager().getEditLayer().data.getDataSourceBounds().stream() 59 .filter(bounds -> !StreetsideLayer.getInstance().getData().getBounds().contains(bounds)) 60 .forEach(bounds -> { 61 StreetsideLayer.getInstance().getData().getBounds().add(bounds); 62 StreetsideDownloader.getImages(bounds.getMin(), bounds.getMax()); 63 }); 64 } 65 66 /** 67 * Gets all the images in a square. It downloads all the images of all the 68 * sequences that pass through the given rectangle. 69 * 70 * @param minLatLon The minimum latitude and longitude of the rectangle. 71 * @param maxLatLon The maximum latitude and longitude of the rectangle 72 */ 73 public static void getImages(LatLon minLatLon, LatLon maxLatLon) { 74 if (minLatLon == null || maxLatLon == null) { 75 throw new IllegalArgumentException(); 76 } 77 getImages(new Bounds(minLatLon, maxLatLon)); 78 } 79 80 /** 81 * Gets the images within the given bounds. 82 * 83 * @param bounds A {@link Bounds} object containing the area to be downloaded. 84 */ 85 public static void getImages(Bounds bounds) { 86 run(new StreetsideSquareDownloadRunnable(bounds)); 87 } 88 89 /** 90 * Returns the current download mode. 91 * 92 * @return the currently enabled {@link DOWNLOAD_MODE} 93 */ 94 public static DOWNLOAD_MODE getMode() { 95 return DOWNLOAD_MODE.fromPrefId(StreetsideProperties.DOWNLOAD_MODE.get()); 96 } 97 98 private static void run(Runnable t) { 99 executor.execute(t); 100 } 101 102 /** 103 * If some part of the current view has not been downloaded, it is downloaded. 104 */ 105 public static void downloadVisibleArea() { 106 Bounds view = MainApplication.getMap().mapView.getRealBounds(); 107 if (isAreaTooBig(view.getArea())) { 108 return; 109 } 110 if (isViewDownloaded(view)) { 111 return; 112 } 113 StreetsideLayer.getInstance().getData().getBounds().add(view); 114 getImages(view); 115 } 116 117 private static boolean isViewDownloaded(Bounds view) { 118 int n = 15; 119 boolean[][] inside = new boolean[n][n]; 120 for (int i = 0; i < n; i++) { 121 for (int j = 0; j < n; j++) { 122 if (isInBounds(new LatLon(view.getMinLat() + (view.getMaxLat() - view.getMinLat()) * ((double) i / n), 123 view.getMinLon() + (view.getMaxLon() - view.getMinLon()) * ((double) j / n)))) { 124 inside[i][j] = true; 125 } 126 } 127 } 128 for (int i = 0; i < n; i++) { 129 for (int j = 0; j < n; j++) { 130 if (!inside[i][j]) 131 return false; 132 } 133 } 134 return true; 135 } 136 137 /** 138 * Checks if the given {@link LatLon} object lies inside the bounds of the 139 * image. 140 * 141 * @param latlon The coordinates to check. 142 * @return true if it lies inside the bounds; false otherwise; 143 */ 144 private static boolean isInBounds(LatLon latlon) { 145 return StreetsideLayer.getInstance().getData().getBounds().parallelStream().anyMatch(b -> b.contains(latlon)); 146 } 147 148 /** 149 * Checks if the area for which Streetside images should be downloaded is too big. This means that probably 150 * lots of Streetside images are going to be downloaded, slowing down the 151 * program too much. A notification is shown when the download has stopped or continued. 152 * 153 * @param area area to check 154 * @return {@code true} if the area is too big 155 */ 156 private static boolean isAreaTooBig(final double area) { 157 final boolean tooBig = area > MAX_AREA; 158 if (!stoppedDownload && tooBig) { 159 new Notification(I18n 160 .tr("The Streetside layer has stopped downloading images, because the requested area is too big!") 161 + (getMode() == DOWNLOAD_MODE.VISIBLE_AREA 162 ? "\n" + I18n 163 .tr("To solve this problem, you could zoom in and load a smaller area of the map.") 164 : (getMode() == DOWNLOAD_MODE.OSM_AREA ? "\n" + I18n.tr( 165 "To solve this problem, you could switch to download mode ''{0}'' and load Streetside images for a smaller portion of the map.", 166 DOWNLOAD_MODE.MANUAL_ONLY) : ""))).setIcon(StreetsidePlugin.LOGO.get()) 167 .setDuration(Notification.TIME_LONG).show(); 168 } 169 if (stoppedDownload && !tooBig) { 170 new Notification("The Streetside layer now continues to download images…") 171 .setIcon(StreetsidePlugin.LOGO.get()).show(); 172 } 173 stoppedDownload = tooBig; 174 return tooBig; 175 } 176 177 /** 178 * Stops all running threads. 179 */ 180 public static void stopAll() { 181 executor.shutdownNow(); 182 try { 183 executor.awaitTermination(30, TimeUnit.SECONDS); 184 } catch (InterruptedException e) { 185 LOGGER.log(Logging.LEVEL_ERROR, e.getMessage(), e); 186 } 187 executor = new ThreadPoolExecutor(3, 5, 100, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100), 188 new ThreadPoolExecutor.DiscardPolicy()); 189 } 190 191 /** 192 * Possible download modes. 193 */ 29 194 public enum DOWNLOAD_MODE { 30 195 VISIBLE_AREA("visibleArea", I18n.tr("everything in the visible area")), … … 34 199 MANUAL_ONLY("manualOnly", I18n.tr("only when manually requested")); 35 200 36 public final staticDOWNLOAD_MODE DEFAULT = OSM_AREA;201 public static final DOWNLOAD_MODE DEFAULT = OSM_AREA; 37 202 38 203 private final String prefId; … … 42 207 this.prefId = prefId; 43 208 this.label = label; 209 } 210 211 public static DOWNLOAD_MODE fromPrefId(String prefId) { 212 for (DOWNLOAD_MODE mode : DOWNLOAD_MODE.values()) { 213 if (mode.getPrefId().equals(prefId)) { 214 return mode; 215 } 216 } 217 return DEFAULT; 218 } 219 220 public static DOWNLOAD_MODE fromLabel(String label) { 221 for (DOWNLOAD_MODE mode : DOWNLOAD_MODE.values()) { 222 if (mode.getLabel().equals(label)) { 223 return mode; 224 } 225 } 226 return DEFAULT; 44 227 } 45 228 … … 57 240 return label; 58 241 } 59 60 public static DOWNLOAD_MODE fromPrefId(String prefId) {61 for (DOWNLOAD_MODE mode : DOWNLOAD_MODE.values()) {62 if (mode.getPrefId().equals(prefId)) {63 return mode;64 }65 }66 return DEFAULT;67 }68 69 public static DOWNLOAD_MODE fromLabel(String label) {70 for (DOWNLOAD_MODE mode : DOWNLOAD_MODE.values()) {71 if (mode.getLabel().equals(label)) {72 return mode;73 }74 }75 return DEFAULT;76 }77 }78 79 /** Max area to be downloaded */80 private static final double MAX_AREA = StreetsideProperties.MAX_DOWNLOAD_AREA.get();81 82 /** Executor that will run the petitions. */83 private static ThreadPoolExecutor executor = new ThreadPoolExecutor(84 3, 5, 100, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100), new ThreadPoolExecutor.DiscardPolicy());85 86 /**87 * Indicates whether the last download request has been rejected because it requested an area that was too big.88 * Iff true, the last download has been rejected, if false, it was executed.89 */90 private static boolean stoppedDownload;91 92 private StreetsideDownloader() {93 // Private constructor to avoid instantiation94 }95 96 /**97 * Gets all the images in a square. It downloads all the images of all the98 * sequences that pass through the given rectangle.99 *100 * @param minLatLon The minimum latitude and longitude of the rectangle.101 * @param maxLatLon The maximum latitude and longitude of the rectangle102 */103 public static void getImages(LatLon minLatLon, LatLon maxLatLon) {104 if (minLatLon == null || maxLatLon == null) {105 throw new IllegalArgumentException();106 }107 getImages(new Bounds(minLatLon, maxLatLon));108 }109 110 /**111 * Gets the images within the given bounds.112 *113 * @param bounds A {@link Bounds} object containing the area to be downloaded.114 */115 public static void getImages(Bounds bounds) {116 run(new StreetsideSquareDownloadRunnable(bounds));117 }118 119 /**120 * Returns the current download mode.121 *122 * @return the currently enabled {@link DOWNLOAD_MODE}123 */124 public static DOWNLOAD_MODE getMode() {125 return DOWNLOAD_MODE.fromPrefId(StreetsideProperties.DOWNLOAD_MODE.get());126 }127 128 private static void run(Runnable t) {129 executor.execute(t);130 }131 132 /**133 * If some part of the current view has not been downloaded, it is downloaded.134 */135 public static void downloadVisibleArea() {136 Bounds view = MainApplication.getMap().mapView.getRealBounds();137 if (isAreaTooBig(view.getArea())) {138 return;139 }140 if (isViewDownloaded(view)) {141 return;142 }143 StreetsideLayer.getInstance().getData().getBounds().add(view);144 getImages(view);145 }146 147 private static boolean isViewDownloaded(Bounds view) {148 int n = 15;149 boolean[][] inside = new boolean[n][n];150 for (int i = 0; i < n; i++) {151 for (int j = 0; j < n; j++) {152 if (isInBounds(new LatLon(view.getMinLat()153 + (view.getMaxLat() - view.getMinLat()) * ((double) i / n),154 view.getMinLon() + (view.getMaxLon() - view.getMinLon())155 * ((double) j / n)))) {156 inside[i][j] = true;157 }158 }159 }160 for (int i = 0; i < n; i++) {161 for (int j = 0; j < n; j++) {162 if (!inside[i][j])163 return false;164 }165 }166 return true;167 }168 169 /**170 * Checks if the given {@link LatLon} object lies inside the bounds of the171 * image.172 *173 * @param latlon The coordinates to check.174 *175 * @return true if it lies inside the bounds; false otherwise;176 */177 private static boolean isInBounds(LatLon latlon) {178 return StreetsideLayer.getInstance().getData().getBounds().parallelStream().anyMatch(b -> b.contains(latlon));179 }180 181 /**182 * Downloads all images of the area covered by the OSM data.183 */184 public static void downloadOSMArea() {185 if (MainApplication.getLayerManager().getEditLayer() == null) {186 return;187 }188 if (isAreaTooBig(MainApplication.getLayerManager().getEditLayer().data.getDataSourceBounds().parallelStream().map(Bounds::getArea).reduce(0.0, Double::sum))) {189 return;190 }191 MainApplication.getLayerManager().getEditLayer().data.getDataSourceBounds().stream().filter(bounds -> !StreetsideLayer.getInstance().getData().getBounds().contains(bounds)).forEach(bounds -> {192 StreetsideLayer.getInstance().getData().getBounds().add(bounds);193 StreetsideDownloader.getImages(bounds.getMin(), bounds.getMax());194 });195 }196 197 /**198 * Checks if the area for which Streetside images should be downloaded is too big. This means that probably199 * lots of Streetside images are going to be downloaded, slowing down the200 * program too much. A notification is shown when the download has stopped or continued.201 * @param area area to check202 * @return {@code true} if the area is too big203 */204 private static boolean isAreaTooBig(final double area) {205 final boolean tooBig = area > MAX_AREA;206 if (!stoppedDownload && tooBig) {207 new Notification(208 I18n.tr("The Streetside layer has stopped downloading images, because the requested area is too big!") + (209 getMode() == DOWNLOAD_MODE.VISIBLE_AREA210 ? "\n"+I18n.tr("To solve this problem, you could zoom in and load a smaller area of the map.")211 : (getMode() == DOWNLOAD_MODE.OSM_AREA ? "\n"+I18n.tr("To solve this problem, you could switch to download mode ''{0}'' and load Streetside images for a smaller portion of the map.", DOWNLOAD_MODE.MANUAL_ONLY): "")212 )213 ).setIcon(StreetsidePlugin.LOGO.get()).setDuration(Notification.TIME_LONG).show();214 }215 if (stoppedDownload && !tooBig) {216 new Notification("The Streetside layer now continues to download images…").setIcon(StreetsidePlugin.LOGO.get()).show();217 }218 stoppedDownload = tooBig;219 return tooBig;220 }221 222 /**223 * Stops all running threads.224 */225 public static void stopAll() {226 executor.shutdownNow();227 try {228 executor.awaitTermination(30, TimeUnit.SECONDS);229 } catch (InterruptedException e) {230 logger.error(e);231 }232 executor = new ThreadPoolExecutor(3, 5, 100, TimeUnit.SECONDS,233 new ArrayBlockingQueue<>(100), new ThreadPoolExecutor.DiscardPolicy());234 242 } 235 243 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/StreetsideSquareDownloadRunnable.java
r34412 r36194 2 2 package org.openstreetmap.josm.plugins.streetside.io.download; 3 3 4 import org.apache.log4j.Logger;5 4 import org.openstreetmap.josm.data.Bounds; 6 5 import org.openstreetmap.josm.plugins.streetside.StreetsideLayer; … … 11 10 public class StreetsideSquareDownloadRunnable implements Runnable { 12 11 13 final static Logger logger = Logger.getLogger(StreetsideSquareDownloadRunnable.class);14 15 12 private final Bounds bounds; 16 13 … … 19 16 * 20 17 * @param bounds the bounds of the area that should be downloaded 21 *22 18 */ 23 19 public StreetsideSquareDownloadRunnable(Bounds bounds) { -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/export/StreetsideExportDownloadThread.java
r34416 r36194 6 6 import java.io.IOException; 7 7 import java.util.concurrent.ArrayBlockingQueue; 8 import java.util.logging.Logger; 8 9 9 10 import javax.imageio.ImageIO; 10 11 11 import org.apache.log4j.Logger;12 12 import org.openstreetmap.josm.data.cache.CacheEntry; 13 13 import org.openstreetmap.josm.data.cache.CacheEntryAttributes; … … 17 17 import org.openstreetmap.josm.plugins.streetside.cache.CacheUtils; 18 18 import org.openstreetmap.josm.plugins.streetside.cache.StreetsideCache; 19 import org.openstreetmap.josm.tools.Logging; 19 20 20 21 /** … … 26 27 * @see StreetsideExportWriterThread 27 28 */ 28 public class StreetsideExportDownloadThread extends Thread implements 29 ICachedLoaderListener { 29 public class StreetsideExportDownloadThread extends Thread implements ICachedLoaderListener { 30 30 31 final static Logger logger = Logger.getLogger(StreetsideExportDownloadThread.class);31 private static final Logger LOGGER = Logger.getLogger(StreetsideExportDownloadThread.class.getCanonicalName()); 32 32 33 33 private final ArrayBlockingQueue<BufferedImage> queue; … … 39 39 * Main constructor. 40 40 * 41 * @param image 42 * Image to be downloaded. 43 * @param queue 44 * Queue of {@link BufferedImage} objects for the 41 * @param image Image to be downloaded. 42 * @param queue Queue of {@link BufferedImage} objects for the 45 43 * {@link StreetsideExportWriterThread}. 46 * @param queueImages 47 * Queue of {@link StreetsideAbstractImage} objects for the 44 * @param queueImages Queue of {@link StreetsideAbstractImage} objects for the 48 45 * {@link StreetsideExportWriterThread}. 49 46 */ 50 public StreetsideExportDownloadThread(StreetsideImage image, 51 ArrayBlockingQueue<BufferedImage> queue, 47 public StreetsideExportDownloadThread(StreetsideImage image, ArrayBlockingQueue<BufferedImage> queue, 52 48 ArrayBlockingQueue<StreetsideAbstractImage> queueImages) { 53 49 this.queue = queue; … … 63 59 64 60 @Override 65 public synchronized void loadingFinished(CacheEntry data, 66 CacheEntryAttributes attributes, LoadResult result) { 61 public synchronized void loadingFinished(CacheEntry data, CacheEntryAttributes attributes, LoadResult result) { 67 62 try { 68 63 synchronized (StreetsideExportDownloadThread.class) { 69 queue 70 .put(ImageIO.read(new ByteArrayInputStream(data.getContent()))); 64 queue.put(ImageIO.read(new ByteArrayInputStream(data.getContent()))); 71 65 queueImages.put(image); 72 66 } 73 67 } catch (InterruptedException | IOException e) { 74 logger.error(e);68 LOGGER.log(Logging.LEVEL_ERROR, e.getMessage(), e); 75 69 } 76 70 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/export/StreetsideExportManager.java
r34429 r36194 11 11 import java.util.concurrent.ThreadPoolExecutor; 12 12 import java.util.concurrent.TimeUnit; 13 import java.util.logging.Logger; 13 14 14 import org.apache.log4j.Logger;15 15 import org.openstreetmap.josm.gui.PleaseWaitRunnable; 16 16 import org.openstreetmap.josm.gui.progress.swing.PleaseWaitProgressMonitor; 17 17 import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage; 18 18 import org.openstreetmap.josm.plugins.streetside.StreetsideImage; 19 import org.openstreetmap.josm.tools.Logging; 19 20 20 21 /** … … 32 33 public class StreetsideExportManager extends PleaseWaitRunnable { 33 34 34 final static Logger logger = Logger.getLogger(StreetsideExportManager.class);35 private static final Logger LOGGER = Logger.getLogger(StreetsideExportManager.class.getCanonicalName()); 35 36 36 37 private final ArrayBlockingQueue<BufferedImage> queue = new ArrayBlockingQueue<>(10); 37 38 private final ArrayBlockingQueue<StreetsideAbstractImage> queueImages = new ArrayBlockingQueue<>(10); 38 39 39 private int amount;40 private Set<StreetsideAbstractImage> images;41 private String path;40 private final int amount; 41 private final Set<StreetsideAbstractImage> images; 42 private final String path; 42 43 43 44 private Thread writer; … … 48 49 * 49 50 * @param images Set of {@link StreetsideAbstractImage} objects to be exported. 50 * @param path Export path.51 * @param path Export path. 51 52 */ 52 53 public StreetsideExportManager(Set<StreetsideAbstractImage> images, String path) { 53 super( 54 tr("Downloading") + "…", 55 new PleaseWaitProgressMonitor(tr("Exporting Streetside Images")), 56 true 57 ); 54 super(tr("Downloading") + "…", new PleaseWaitProgressMonitor(tr("Exporting Streetside Images")), true); 58 55 this.images = images == null ? new HashSet<>() : images; 59 56 this.path = path; … … 70 67 protected void realRun() throws IOException { 71 68 // Starts a writer thread in order to write the pictures on the disk. 72 writer = new StreetsideExportWriterThread(path, queue, 73 queueImages, amount, getProgressMonitor()); 69 writer = new StreetsideExportWriterThread(path, queue, queueImages, amount, getProgressMonitor()); 74 70 writer.start(); 75 71 if (path == null) { … … 77 73 writer.join(); 78 74 } catch (InterruptedException e) { 79 logger.error(e);75 LOGGER.log(Logging.LEVEL_ERROR, e.getMessage(), e); 80 76 } 81 77 return; 82 78 } 83 ex = new ThreadPoolExecutor(20, 35, 25, TimeUnit.SECONDS, 84 new ArrayBlockingQueue<>(10)); 79 ex = new ThreadPoolExecutor(20, 35, 25, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10)); 85 80 for (StreetsideAbstractImage image : images) { 86 81 if (image instanceof StreetsideImage) { 87 82 try { 88 ex.execute(new StreetsideExportDownloadThread( 89 (StreetsideImage) image, queue, queueImages)); 83 ex.execute(new StreetsideExportDownloadThread((StreetsideImage) image, queue, queueImages)); 90 84 } catch (Exception e) { 91 logger.error(e);85 LOGGER.log(Logging.LEVEL_ERROR, e.getMessage(), e); 92 86 } 93 87 } … … 99 93 } 100 94 } catch (Exception e) { 101 logger.error(e);95 LOGGER.log(Logging.LEVEL_ERROR, e.getMessage(), e); 102 96 } 103 97 } … … 105 99 writer.join(); 106 100 } catch (InterruptedException e) { 107 logger.error(e);101 LOGGER.log(Logging.LEVEL_ERROR, e.getMessage(), e); 108 102 } 109 103 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/export/StreetsideExportWriterThread.java
r34429 r36194 9 9 import java.io.OutputStream; 10 10 import java.util.concurrent.ArrayBlockingQueue; 11 import java.util.logging.Logger; 11 12 12 13 import javax.imageio.ImageIO; … … 20 21 import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory; 21 22 import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet; 22 import org.apache.log4j.Logger;23 23 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 24 24 import org.openstreetmap.josm.gui.progress.swing.PleaseWaitProgressMonitor; 25 25 import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage; 26 import org.openstreetmap.josm.tools.Logging; 26 27 27 28 /** … … 33 34 public class StreetsideExportWriterThread extends Thread { 34 35 35 final static Logger logger = Logger.getLogger(StreetsideExportWriterThread.class);36 private static final Logger LOGGER = Logger.getLogger(StreetsideExportWriterThread.class.getCanonicalName()); 36 37 37 38 private final String path; … … 44 45 * Main constructor. 45 46 * 46 * @param path 47 * Path to write the pictures. 48 * @param queue 49 * Queue of {@link StreetsideAbstractImage} objects. 50 * @param queueImages 51 * Queue of {@link BufferedImage} objects. 52 * @param amount 53 * Amount of images that are going to be exported. 54 * @param monitor 55 * Progress monitor. 47 * @param path Path to write the pictures. 48 * @param queue Queue of {@link StreetsideAbstractImage} objects. 49 * @param queueImages Queue of {@link BufferedImage} objects. 50 * @param amount Amount of images that are going to be exported. 51 * @param monitor Progress monitor. 56 52 */ 57 public StreetsideExportWriterThread(String path, 58 ArrayBlockingQueue<BufferedImage> queue, 59 ArrayBlockingQueue<StreetsideAbstractImage> queueImages, int amount, 60 ProgressMonitor monitor) { 53 public StreetsideExportWriterThread(String path, ArrayBlockingQueue<BufferedImage> queue, 54 ArrayBlockingQueue<StreetsideAbstractImage> queueImages, int amount, ProgressMonitor monitor) { 61 55 this.path = path; 62 56 this.queue = queue; … … 76 70 img = queue.take(); 77 71 mimg = queueImages.take(); 78 79 72 80 73 // Transforms the image into a byte array. … … 100 93 101 94 gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION); 102 gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION, 103 RationalNumber.valueOf(mimg.getMovingHe())); 95 gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION, RationalNumber.valueOf(mimg.getMovingHe())); 104 96 105 97 exifDirectory.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL); … … 111 103 os.close(); 112 104 } catch (InterruptedException e) { 113 logger.info("Streetside export cancelled");105 LOGGER.info("Streetside export cancelled"); 114 106 return; 115 107 } catch (IOException | ImageReadException | ImageWriteException e) { 116 logger.error(e);108 LOGGER.log(Logging.LEVEL_ERROR, e.getMessage(), e); 117 109 } 118 110 -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/mode/AbstractMode.java
r34400 r36194 22 22 * @see StreetsideLayer 23 23 */ 24 public abstract class AbstractMode extends MouseAdapter implements 25 ZoomChangeListener { 24 public abstract class AbstractMode extends MouseAdapter implements ZoomChangeListener { 26 25 27 26 private static final int DOWNLOAD_COOLDOWN = 2000; … … 33 32 public int cursor = Cursor.DEFAULT_CURSOR; 34 33 34 /** 35 * Resets the semiautomatic mode thread. 36 */ 37 public static void resetThread() { 38 semiautomaticThread.interrupt(); 39 semiautomaticThread = new SemiautomaticThread(); 40 } 41 35 42 protected StreetsideAbstractImage getClosest(Point clickPoint) { 36 43 double snapDistance = 10; … … 41 48 imagePoint.setLocation(imagePoint.getX(), imagePoint.getY()); 42 49 double dist = clickPoint.distanceSq(imagePoint); 43 if (minDistance > dist && clickPoint.distance(imagePoint) < snapDistance 44 && image.isVisible()) { 50 if (minDistance > dist && clickPoint.distance(imagePoint) < snapDistance && image.isVisible()) { 45 51 minDistance = dist; 46 52 closest = image; … … 53 59 * Paint the dataset using the engine set. 54 60 * 55 * @param g {@link Graphics2D} used for painting56 * @param mv The object that can translate GeoPoints to screen coordinates.61 * @param g {@link Graphics2D} used for painting 62 * @param mv The object that can translate GeoPoints to screen coordinates. 57 63 * @param box Area where painting is going to be performed 58 64 */ … … 68 74 } 69 75 70 /**71 * Resets the semiautomatic mode thread.72 */73 public static void resetThread() {74 semiautomaticThread.interrupt();75 semiautomaticThread = new SemiautomaticThread();76 }77 78 76 private static class SemiautomaticThread extends Thread { 79 77 80 /** If in semiautomatic mode, the last Epoch time when there was a download */ 78 /** 79 * If in semiautomatic mode, the last Epoch time when there was a download 80 */ 81 81 private long lastDownload; 82 82 -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/mode/SelectMode.java
r34627 r36194 35 35 */ 36 36 public class SelectMode extends AbstractMode { 37 private final StreetsideRecord record; 37 38 private StreetsideAbstractImage closest; 38 39 private StreetsideAbstractImage lastClicked; 39 private final StreetsideRecord record;40 40 private boolean nothingHighlighted; 41 41 private boolean imageHighlighted; … … 54 54 } 55 55 StreetsideAbstractImage closest = getClosest(e.getPoint()); 56 if (!(MainApplication.getLayerManager().getActiveLayer() instanceof StreetsideLayer) 57 && closest != null&& MainApplication.getMap().mapMode == MainApplication.getMap().mapModeSelect) {56 if (!(MainApplication.getLayerManager().getActiveLayer() instanceof StreetsideLayer) && closest != null 57 && MainApplication.getMap().mapMode == MainApplication.getMap().mapModeSelect) { 58 58 lastClicked = this.closest; 59 59 StreetsideLayer.getInstance().getData().setSelectedImage(closest); … … 63 63 } 64 64 // Double click 65 if (e.getClickCount() == 2 && StreetsideLayer.getInstance().getData().getSelectedImage() != null && closest != null) { 65 if (e.getClickCount() == 2 && StreetsideLayer.getInstance().getData().getSelectedImage() != null 66 && closest != null) { 66 67 closest.getSequence().getImages().forEach(StreetsideLayer.getInstance().getData()::addMultiSelectedImage); 67 68 } … … 75 76 StreetsideLayer.getInstance().getData().addMultiSelectedImage(closest); 76 77 // shift + click 77 } else if ( 78 e.getModifiers() == (InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK) 79 && lastClicked instanceof StreetsideImage 80 ) { 81 if (this.closest != null 82 && this.closest.getSequence() == lastClicked.getSequence()) { 78 } else if (e.getModifiers() == (InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK) 79 && lastClicked instanceof StreetsideImage) { 80 if (this.closest != null && this.closest.getSequence() == lastClicked.getSequence()) { 83 81 int i = this.closest.getSequence().getImages().indexOf(this.closest); 84 82 int j = lastClicked.getSequence().getImages().indexOf(lastClicked); 85 StreetsideLayer.getInstance().getData().addMultiSelectedImage( 86 i < j 87 ? new ConcurrentSkipListSet<>(this.closest.getSequence().getImages().subList(i, j + 1)) 88 : new ConcurrentSkipListSet<>(this.closest.getSequence().getImages().subList(j, i + 1)) 89 ); 83 StreetsideLayer.getInstance().getData().addMultiSelectedImage(i < j 84 ? new ConcurrentSkipListSet<>(this.closest.getSequence().getImages().subList(i, j + 1)) 85 : new ConcurrentSkipListSet<>(this.closest.getSequence().getImages().subList(j, i + 1))); 90 86 } 91 87 // click … … 98 94 public void mouseDragged(MouseEvent e) { 99 95 StreetsideAbstractImage highlightImg = StreetsideLayer.getInstance().getData().getHighlightedImage(); 100 if ( 101 MainApplication.getLayerManager().getActiveLayer() == StreetsideLayer.getInstance() 102 && SwingUtilities.isLeftMouseButton(e) 103 && highlightImg != null && highlightImg.getLatLon() != null 104 ) { 96 if (MainApplication.getLayerManager().getActiveLayer() == StreetsideLayer.getInstance() 97 && SwingUtilities.isLeftMouseButton(e) && highlightImg != null && highlightImg.getLatLon() != null) { 105 98 Point highlightImgPoint = MainApplication.getMap().mapView.getPoint(highlightImg.getTempLatLon()); 106 99 if (e.isShiftDown()) { // turn 107 StreetsideLayer.getInstance().getData().getMultiSelectedImages().parallelStream().filter(img -> !(img instanceof StreetsideImage) || StreetsideProperties.DEVELOPER.get()) 108 .forEach(img -> img.turn(Math.toDegrees(Math.atan2(e.getX() - highlightImgPoint.getX(), -e.getY() + highlightImgPoint.getY())) - highlightImg.getTempHe())); 100 StreetsideLayer.getInstance().getData().getMultiSelectedImages().parallelStream() 101 .filter(img -> !(img instanceof StreetsideImage) || StreetsideProperties.DEVELOPER.get()) 102 .forEach(img -> img.turn(Math.toDegrees( 103 Math.atan2(e.getX() - highlightImgPoint.getX(), -e.getY() + highlightImgPoint.getY())) 104 - highlightImg.getTempHe())); 109 105 } else { // move 110 106 LatLon eventLatLon = MainApplication.getMap().mapView.getLatLon(e.getX(), e.getY()); 111 LatLon imgLatLon = MainApplication.getMap().mapView.getLatLon(highlightImgPoint.getX(), highlightImgPoint.getY()); 112 StreetsideLayer.getInstance().getData().getMultiSelectedImages().parallelStream().filter(img -> !(img instanceof StreetsideImage) || StreetsideProperties.DEVELOPER.get()) 113 .forEach(img -> img.move(eventLatLon.getX() - imgLatLon.getX(), eventLatLon.getY() - imgLatLon.getY())); 107 LatLon imgLatLon = MainApplication.getMap().mapView.getLatLon(highlightImgPoint.getX(), 108 highlightImgPoint.getY()); 109 StreetsideLayer.getInstance().getData().getMultiSelectedImages().parallelStream() 110 .filter(img -> !(img instanceof StreetsideImage) || StreetsideProperties.DEVELOPER.get()) 111 .forEach(img -> img.move(eventLatLon.getX() - imgLatLon.getX(), 112 eventLatLon.getY() - imgLatLon.getY())); 114 113 } 115 114 StreetsideLayer.invalidateInstance(); … … 127 126 double to = data.getSelectedImage().getMovingHe(); 128 127 record.addCommand(new CommandTurn(data.getMultiSelectedImages(), to - from)); 129 } else if (!Objects.equals(data.getSelectedImage().getTempLatLon(), data.getSelectedImage().getMovingLatLon())) { 128 } else if (!Objects.equals(data.getSelectedImage().getTempLatLon(), 129 data.getSelectedImage().getMovingLatLon())) { 130 130 LatLon from = data.getSelectedImage().getTempLatLon(); 131 131 LatLon to = data.getSelectedImage().getMovingLatLon(); 132 record.addCommand(new CommandMove(data.getMultiSelectedImages(), to.getX() - from.getX(), to.getY() - from.getY())); 132 record.addCommand( 133 new CommandMove(data.getMultiSelectedImages(), to.getX() - from.getX(), to.getY() - from.getY())); 133 134 } 134 data.getMultiSelectedImages().parallelStream().filter(Objects::nonNull).forEach(StreetsideAbstractImage::stopMoving); 135 data.getMultiSelectedImages().parallelStream().filter(Objects::nonNull) 136 .forEach(StreetsideAbstractImage::stopMoving); 135 137 StreetsideLayer.invalidateInstance(); 136 138 } … … 142 144 public void mouseMoved(MouseEvent e) { 143 145 if (MainApplication.getLayerManager().getActiveLayer() instanceof OsmDataLayer 144 146 && MainApplication.getMap().mapMode != MainApplication.getMap().mapModeSelect) { 145 147 return; 146 148 } 147 if ( !StreetsideProperties.HOVER_ENABLED.get()) {149 if (Boolean.FALSE.equals(StreetsideProperties.HOVER_ENABLED.get())) { 148 150 return; 149 151 } … … 177 179 StreetsideMainDialog.getInstance().updateImage(false); 178 180 179 } else if (StreetsideLayer.getInstance().getData().getHighlightedImage() != closestTemp && closestTemp == null) { 181 } else if (StreetsideLayer.getInstance().getData().getHighlightedImage() != closestTemp 182 && closestTemp == null) { 180 183 StreetsideLayer.getInstance().getData().setHighlightedImage(null); 181 184 StreetsideMainDialog.getInstance().setImage(StreetsideLayer.getInstance().getData().getSelectedImage()); -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/ImageDetection.java
r34317 r36194 11 11 private final String value; 12 12 13 public ImageDetection(final Path2D shape, final String imageKey, final String key, final double score, final String packag, final String value) { 13 public ImageDetection(final Path2D shape, final String imageKey, final String key, final double score, 14 final String packag, final String value) { 14 15 super(shape, imageKey, key); 15 16 this.packag = packag; -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/KeyIndexedObject.java
r34317 r36194 46 46 } 47 47 KeyIndexedObject other = (KeyIndexedObject) obj; 48 if (!key.equals(other.key)) { 49 return false; 50 } 51 return true; 48 return key.equals(other.key); 52 49 } 53 50 -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/MapObject.java
r34416 r36194 18 18 private final long updatedTime; 19 19 20 public MapObject( 21 final LatLon coordinate, final String key, final String objPackage, final String value, 22 long firstSeenTime, long lastSeenTime, long updatedTime 23 ) { 20 public MapObject(final LatLon coordinate, final String key, final String objPackage, final String value, 21 long firstSeenTime, long lastSeenTime, long updatedTime) { 24 22 super(key); 25 23 if (objPackage == null || value == null || coordinate == null) { … … 34 32 } 35 33 36 public LatLon getCoordinate() {37 return coordinate;38 }39 40 34 /** 41 35 * @param objectTypeID the {@link String} representing the type of map object. This ID can be retrieved via 42 * {@link #getValue()} for any given {@link MapObject}.36 * {@link #getValue()} for any given {@link MapObject}. 43 37 * @return the icon, which represents the given objectTypeID 44 38 */ … … 51 45 } 52 46 return cachedIcon; 47 } 48 49 public LatLon getCoordinate() { 50 return coordinate; 53 51 } 54 52 -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/oauth/OAuthPortListener.java
r34577 r36194 1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.plugins.streetside.oauth; 3 4 3 5 4 import java.io.IOException; … … 10 9 import java.net.ServerSocket; 11 10 import java.net.Socket; 11 import java.nio.charset.StandardCharsets; 12 12 import java.util.Scanner; 13 import java.util.logging.Logger; 13 14 import java.util.regex.Matcher; 14 15 import java.util.regex.Pattern; 15 16 16 import org.apache.log4j.Logger;17 17 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties; 18 18 import org.openstreetmap.josm.tools.I18n; 19 import org.openstreetmap.josm.tools.Logging; 19 20 20 21 /** … … 26 27 */ 27 28 public class OAuthPortListener extends Thread { 28 public static final int PORT = 8763; 29 public static final int PORT = 8763; 30 protected static final String RESPONSE = String.format( 31 "<!DOCTYPE html><html><head><meta charset=\"utf8\"><title>%s</title></head><body>%s</body></html>", 32 I18n.tr("Streetside login"), I18n.tr("Login successful, return to JOSM.")); 33 private static final Logger LOGGER = Logger.getLogger(OAuthPortListener.class.getCanonicalName()); 34 private final StreetsideLoginListener callback; 29 35 30 final static Logger logger = Logger.getLogger(OAuthPortListener.class); 36 public OAuthPortListener(StreetsideLoginListener loginCallback) { 37 callback = loginCallback; 38 } 31 39 32 protected static final String RESPONSE = String.format( 33 "<!DOCTYPE html><html><head><meta charset=\"utf8\"><title>%s</title></head><body>%s</body></html>",34 I18n.tr("Streetside login"),35 I18n.tr("Login successful, return to JOSM.")36 );37 private final StreetsideLoginListener callback; 40 private static void writeContent(PrintWriter out) { 41 out.println("HTTP/1.1 200 OK"); 42 out.println("Content-Length: " + RESPONSE.length()); 43 out.println("Content-Type: text/html" + "\r\n\r\n"); 44 out.println(RESPONSE); 45 } 38 46 39 public OAuthPortListener(StreetsideLoginListener loginCallback) { 40 callback = loginCallback; 47 @Override 48 public void run() { 49 try (ServerSocket serverSocket = new ServerSocket(PORT); 50 Socket clientSocket = serverSocket.accept(); 51 PrintWriter out = new PrintWriter( 52 new OutputStreamWriter(clientSocket.getOutputStream(), StandardCharsets.UTF_8), true); 53 Scanner in = new Scanner( 54 new InputStreamReader(clientSocket.getInputStream(), StandardCharsets.UTF_8))) { 55 String s; 56 String accessToken = null; 57 while (in.hasNextLine()) { 58 s = in.nextLine(); 59 Matcher tokenMatcher = Pattern.compile("^.*&access_token=([^&]+)&.*$").matcher('&' + s + '&'); 60 if (tokenMatcher.matches()) { 61 accessToken = tokenMatcher.group(1); 62 break; 63 } else if (s.contains("keep-alive")) { 64 break; 65 } 66 } 67 68 writeContent(out); 69 out.flush(); 70 71 StreetsideUser.reset(); 72 73 LOGGER.info(I18n.tr("Successful login with Streetside, the access token is: {0}", accessToken)); 74 // Saves the access token in preferences. 75 StreetsideUser.setTokenValid(true); 76 StreetsideProperties.ACCESS_TOKEN.put(accessToken); 77 String username = StreetsideUser.getUsername(); 78 LOGGER.info(I18n.tr("The username is: {0}", username)); 79 if (callback != null) { 80 callback.onLogin(username); 81 } 82 } catch (BindException e) { 83 LOGGER.log(Logging.LEVEL_WARN, e.getMessage(), e); 84 } catch (IOException e) { 85 LOGGER.log(Logging.LEVEL_ERROR, e.getMessage(), e); 86 } 87 } 41 88 } 42 43 @Override44 public void run() {45 try (46 ServerSocket serverSocket = new ServerSocket(PORT);47 Socket clientSocket = serverSocket.accept();48 PrintWriter out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream(), "UTF-8"), true);49 Scanner in = new Scanner(new InputStreamReader(clientSocket.getInputStream(), "UTF-8"))50 ) {51 String s;52 String accessToken = null;53 while (in.hasNextLine()) {54 s = in.nextLine();55 Matcher tokenMatcher = Pattern.compile("^.*&access_token=([^&]+)&.*$").matcher('&'+s+'&');56 if (tokenMatcher.matches()) {57 accessToken = tokenMatcher.group(1);58 break;59 } else if (s.contains("keep-alive")) {60 break;61 }62 }63 64 writeContent(out);65 out.flush();66 67 StreetsideUser.reset();68 69 logger.info(I18n.tr("Successful login with Streetside, the access token is: {0}", accessToken));70 // Saves the access token in preferences.71 StreetsideUser.setTokenValid(true);72 StreetsideProperties.ACCESS_TOKEN.put(accessToken);73 String username = StreetsideUser.getUsername();74 logger.info(I18n.tr("The username is: {0}", username));75 if (callback != null) {76 callback.onLogin(username);77 }78 } catch (BindException e) {79 logger.warn(e);80 } catch (IOException e) {81 logger.error(e);82 }83 }84 85 private static void writeContent(PrintWriter out) {86 out.println("HTTP/1.1 200 OK");87 out.println("Content-Length: " + RESPONSE.length());88 out.println("Content-Type: text/html" + "\r\n\r\n");89 out.println(RESPONSE);90 }91 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/oauth/OAuthUtils.java
r36122 r36194 7 7 import java.net.HttpURLConnection; 8 8 import java.net.URL; 9 import java.nio.charset.StandardCharsets; 10 11 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties; 9 12 10 13 import jakarta.json.Json; … … 12 15 import jakarta.json.JsonObject; 13 16 import jakarta.json.JsonReader; 14 15 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;16 17 17 18 /** … … 23 24 public final class OAuthUtils { 24 25 25 private OAuthUtils() { 26 // Private constructor to avoid instantiation 26 private OAuthUtils() { 27 // Private constructor to avoid instantiation 28 } 29 30 /** 31 * Returns a JsonObject containing the result of making a GET request with the 32 * authorization header. 33 * 34 * @param url The {@link URL} where the request must be made. 35 * @return A JsonObject containing the result of the GET request. 36 * @throws IOException Errors relating to the connection. 37 */ 38 public static JsonObject getWithHeader(URL url) throws IOException { 39 HttpURLConnection con = (HttpURLConnection) url.openConnection(); 40 con.setRequestMethod("GET"); 41 con.setRequestProperty("Authorization", "Bearer " + StreetsideProperties.ACCESS_TOKEN.get()); 42 43 try (JsonReader reader = Json.createReader( 44 new BufferedReader(new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8)))) { 45 return reader.readObject(); 46 } catch (JsonException e) { 47 throw new IOException(e); 48 } 49 } 27 50 } 28 29 /**30 * Returns a JsonObject containing the result of making a GET request with the31 * authorization header.32 *33 * @param url34 * The {@link URL} where the request must be made.35 * @return A JsonObject containing the result of the GET request.36 * @throws IOException37 * Errors relating to the connection.38 */39 public static JsonObject getWithHeader(URL url) throws IOException {40 HttpURLConnection con = (HttpURLConnection) url.openConnection();41 con.setRequestMethod("GET");42 con.setRequestProperty("Authorization", "Bearer " + StreetsideProperties.ACCESS_TOKEN.get());43 44 try (45 JsonReader reader = Json.createReader(new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8")))46 ) {47 return reader.readObject();48 } catch (JsonException e) {49 throw new IOException(e);50 }51 }52 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/oauth/StreetsideLoginListener.java
r34317 r36194 11 11 * Should be called whenever the user logs into a mapillary account. 12 12 * E.g. for updating the GUI to reflect the login status. 13 * 13 14 * @param username the username that the user is now logged in with 14 15 */ 15 16 void onLogin(final String username); 17 16 18 /** 17 19 * Should be called whenever the user logs out of a mapillary account. -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/oauth/StreetsideUser.java
r34400 r36194 1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.plugins.streetside.oauth; 3 4 3 5 4 import java.util.Map; … … 15 14 public final class StreetsideUser { 16 15 17 private static String username; 18 private static String imagesPolicy; 19 private static String imagesHash; 20 /** If the stored token is valid or not. */ 21 private static boolean isTokenValid = true; 16 private static String username; 17 private static String imagesPolicy; 18 private static String imagesHash; 19 /** 20 * If the stored token is valid or not. 21 */ 22 private static boolean isTokenValid = true; 22 23 23 private StreetsideUser() { 24 // Private constructor to avoid instantiation 24 private StreetsideUser() { 25 // Private constructor to avoid instantiation 26 } 27 28 /** 29 * @return The username of the logged in user. 30 */ 31 public static synchronized String getUsername() { 32 // users are not currently supported in Streetside 33 return null; 34 } 35 36 /** 37 * @return A HashMap object containing the images_policy and images_hash 38 * strings. 39 */ 40 public static synchronized Map<String, String> getSecrets() { 41 // secrets are not currently supported in Streetside 42 return null; 43 } 44 45 /** 46 * Resets the MapillaryUser to null values. 47 */ 48 public static synchronized void reset() { 49 username = null; 50 imagesPolicy = null; 51 imagesHash = null; 52 isTokenValid = false; 53 StreetsideProperties.ACCESS_TOKEN.put(StreetsideProperties.ACCESS_TOKEN.getDefaultValue()); 54 } 55 56 public static synchronized void setTokenValid(boolean value) { 57 isTokenValid = value; 58 } 25 59 } 26 27 /**28 * @return The username of the logged in user.29 */30 public static synchronized String getUsername() {31 // users are not currently supported in Streetside32 return null;33 }34 35 /**36 * @return A HashMap object containing the images_policy and images_hash37 * strings.38 */39 public static synchronized Map<String, String> getSecrets() {40 // secrets are not currently supported in Streetside41 return null;42 }43 44 /**45 * Resets the MapillaryUser to null values.46 */47 public static synchronized void reset() {48 username = null;49 imagesPolicy = null;50 imagesHash = null;51 isTokenValid = false;52 StreetsideProperties.ACCESS_TOKEN.put(StreetsideProperties.ACCESS_TOKEN.getDefaultValue());53 }54 55 public static synchronized void setTokenValid(boolean value) {56 isTokenValid = value;57 }58 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/GraphicsUtils.java
r34577 r36194 6 6 import java.awt.image.BufferedImage; 7 7 import java.text.MessageFormat; 8 import java.util.logging.Logger; 8 9 9 import org. apache.log4j.Logger;10 import org.openstreetmap.josm.tools.Logging; 10 11 11 12 import javafx.application.Platform; 12 13 import javafx.scene.image.PixelWriter; 13 //import javafx.embed.swing.SwingFXUtils;14 //import javafx.scene.image.Image;15 14 import javafx.scene.image.WritableImage; 16 15 17 @SuppressWarnings({ "restriction"})18 16 public class GraphicsUtils { 19 17 20 final static Logger logger = Logger.getLogger(GraphicsUtils.class);18 private static final Logger LOGGER = Logger.getLogger(GraphicsUtils.class.getCanonicalName()); 21 19 22 20 private GraphicsUtils() { … … 24 22 } 25 23 26 27 28 29 30 31 32 33 34 35 36 37 38 24 public static javafx.scene.image.Image convertBufferedImage2JavaFXImage(BufferedImage bf) { 25 WritableImage res = null; 26 if (bf != null) { 27 res = new WritableImage(bf.getWidth(), bf.getHeight()); 28 PixelWriter pw = res.getPixelWriter(); 29 for (int x = 0; x < bf.getWidth(); x++) { 30 for (int y = 0; y < bf.getHeight(); y++) { 31 pw.setArgb(x, y, bf.getRGB(x, y)); 32 } 33 } 34 } 35 return res; 36 } 39 37 40 public static class PlatformHelper{38 public static BufferedImage buildMultiTiledCubemapFaceImage(final BufferedImage[] tiles) { 41 39 42 private PlatformHelper() { 43 // Private constructor to avoid instantiation 44 } 40 long start = System.currentTimeMillis(); 45 41 46 public static void run(Runnable treatment) { 47 if(treatment == null) throw new IllegalArgumentException("The treatment to perform can not be null"); 42 BufferedImage res = null; 48 43 49 if(Platform.isFxApplicationThread()) treatment.run(); 50 else Platform.runLater(treatment); 51 } 52 } 44 int pixelBuffer = Boolean.TRUE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) ? 2 : 1; 53 45 54 public static BufferedImage buildMultiTiledCubemapFaceImage(final BufferedImage[] tiles) { 46 BufferedImage[] croppedTiles = cropMultiTiledImages(tiles, pixelBuffer); 55 47 56 long start = System.currentTimeMillis(); 48 // we assume the no. of rows and cols are known and each chunk has equal width and height 49 int rows = Boolean.TRUE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) ? 4 : 2; 50 int cols = Boolean.TRUE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) ? 4 : 2; 57 51 58 BufferedImage res = null; 52 int chunkWidth; 53 int chunkHeight; 59 54 60 int pixelBuffer = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?2:1; 55 chunkWidth = croppedTiles[0].getWidth(); 56 chunkHeight = croppedTiles[0].getHeight(); 61 57 62 BufferedImage[] croppedTiles = cropMultiTiledImages(tiles, pixelBuffer); 58 //Initializing the final image 59 BufferedImage img = new BufferedImage(chunkWidth * cols, chunkHeight * rows, BufferedImage.TYPE_INT_ARGB); 63 60 64 int rows = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?4:2; //we assume the no. of rows and cols are known and each chunk has equal width and height 65 int cols = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?4:2; 66 67 int chunkWidth, chunkHeight; 68 69 chunkWidth = croppedTiles[0].getWidth(); 70 chunkHeight = croppedTiles[0].getHeight(); 71 72 //Initializing the final image 73 BufferedImage img = new BufferedImage(chunkWidth*cols, chunkHeight*rows, BufferedImage.TYPE_INT_ARGB); 74 75 int num = 0; 76 for (int i = 0; i < rows; i++) { 77 for (int j = 0; j < cols; j++) { 61 int num = 0; 62 for (int i = 0; i < rows; i++) { 63 for (int j = 0; j < cols; j++) { 78 64 // TODO: unintended mirror image created with draw call - requires 79 65 // extra reversal step - fix! 80 66 img.createGraphics().drawImage(croppedTiles[num], chunkWidth * j, (chunkHeight * i), null); 81 67 82 int width = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get() ? 1014 : 510; 68 int width = Boolean.TRUE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) ? 1014 69 : 510; 83 70 int height = width; 84 71 85 72 // BufferedImage for mirror image 86 res = new BufferedImage( 87 width, 88 height, BufferedImage.TYPE_INT_ARGB); 73 res = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 89 74 90 75 // Create mirror image pixel by pixel … … 106 91 } 107 92 108 if ( StreetsideProperties.DEBUGING_ENABLED.get()) {109 logger110 .debug(MessageFormat.format("Image concatenated in {0} millisecs.", (System.currentTimeMillis() - start)));93 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 94 LOGGER.log(Logging.LEVEL_DEBUG, 95 MessageFormat.format("Image concatenated in {0} millisecs.", (System.currentTimeMillis() - start))); 111 96 } 112 97 return res; 113 98 } 114 99 115 public static BufferedImage rotateImage(BufferedImage bufImg) { 116 AffineTransform tx = AffineTransform.getScaleInstance(-1, -1); 117 tx.translate(-bufImg.getWidth(null), -bufImg.getHeight(null)); 118 AffineTransformOp op = new AffineTransformOp(tx, 119 AffineTransformOp.TYPE_NEAREST_NEIGHBOR); 120 bufImg = op.filter(bufImg, null); 121 return bufImg; 122 } 100 public static BufferedImage rotateImage(BufferedImage bufImg) { 101 AffineTransform tx = AffineTransform.getScaleInstance(-1, -1); 102 tx.translate(-bufImg.getWidth(null), -bufImg.getHeight(null)); 103 AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR); 104 bufImg = op.filter(bufImg, null); 105 return bufImg; 106 } 123 107 124 108 private static BufferedImage[] cropMultiTiledImages(BufferedImage[] tiles, int pixelBuffer) { 125 109 126 110 long start = System.currentTimeMillis(); 127 111 128 112 BufferedImage[] res = new BufferedImage[tiles.length]; 129 113 130 for(int i=0; i<tiles.length;i++) {131 if(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) {132 res[i] = tiles[i].getSubimage(pixelBuffer, pixelBuffer, 256-pixelBuffer, 256-pixelBuffer);133 134 res[i] = tiles[i].getSubimage(pixelBuffer, pixelBuffer, 256-pixelBuffer, 256-pixelBuffer);135 136 114 for (int i = 0; i < tiles.length; i++) { 115 if (Boolean.TRUE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get())) { 116 res[i] = tiles[i].getSubimage(pixelBuffer, pixelBuffer, 256 - pixelBuffer, 256 - pixelBuffer); 117 } else { 118 res[i] = tiles[i].getSubimage(pixelBuffer, pixelBuffer, 256 - pixelBuffer, 256 - pixelBuffer); 119 } 120 } 137 121 138 if(StreetsideProperties.DEBUGING_ENABLED.get()) { 139 logger.debug(MessageFormat.format("Images cropped in {0} millisecs.", (System.currentTimeMillis()-start))); 140 } 122 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 123 LOGGER.log(Logging.LEVEL_DEBUG, 124 MessageFormat.format("Images cropped in {0} millisecs.", (System.currentTimeMillis() - start))); 125 } 141 126 142 return res; 143 } 127 return res; 128 } 129 130 public static class PlatformHelper { 131 132 private PlatformHelper() { 133 // Private constructor to avoid instantiation 134 } 135 136 public static void run(Runnable treatment) { 137 if (treatment == null) 138 throw new IllegalArgumentException("The treatment to perform can not be null"); 139 140 if (Platform.isFxApplicationThread()) 141 treatment.run(); 142 else 143 Platform.runLater(treatment); 144 } 145 } 144 146 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/ImageUtil.java
r34365 r36194 3 3 4 4 import java.awt.Image; 5 import java.util.logging.Logger; 5 6 6 7 import javax.swing.ImageIcon; 7 8 8 import org.apache.log4j.Logger;9 9 import org.openstreetmap.josm.tools.I18n; 10 import org.openstreetmap.josm.tools.Logging; 10 11 11 12 public final class ImageUtil { 12 13 13 final static Logger logger = Logger.getLogger(ImageUtil.class);14 private static final Logger LOGGER = Logger.getLogger(ImageUtil.class.getCanonicalName()); 14 15 15 16 private ImageUtil() { … … 19 20 /** 20 21 * Scales an {@link ImageIcon} to the desired size 22 * 21 23 * @param icon the icon, which should be resized 22 24 * @param size the desired length of the longest edge of the icon 23 25 * @return the resized {@link ImageIcon}. It is the same object that you put in, 24 * 26 * only the contained {@link Image} is exchanged. 25 27 */ 26 28 public static ImageIcon scaleImageIcon(final ImageIcon icon, int size) { 27 if (StreetsideProperties.DEBUGING_ENABLED.get()) {28 logger.debug(I18n.tr("Scale icon {0} → {1}", icon.getIconWidth(), size));29 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 30 LOGGER.log(Logging.LEVEL_DEBUG, I18n.tr("Scale icon {0} → {1}", icon.getIconWidth(), size)); 29 31 } 30 return new ImageIcon(icon.getImage().getScaledInstance( 31 icon.getIconWidth() >= icon.getIconHeight() ? size : Math.max(1, Math.round(icon.getIconWidth() / (float) icon.getIconHeight() * size)), 32 icon.getIconHeight() >= icon.getIconWidth() ? size : Math.max(1, Math.round(icon.getIconHeight() / (float) icon.getIconWidth() * size)), 33 Image.SCALE_SMOOTH 34 )); 32 return new ImageIcon( 33 icon.getImage() 34 .getScaledInstance( 35 icon.getIconWidth() >= icon.getIconHeight() ? size 36 : Math.max(1, 37 Math.round(icon.getIconWidth() / (float) icon.getIconHeight() * size)), 38 icon.getIconHeight() >= icon.getIconWidth() ? size 39 : Math.max(1, 40 Math.round(icon.getIconHeight() / (float) icon.getIconWidth() * size)), 41 Image.SCALE_SMOOTH)); 35 42 } 36 43 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/MapViewGeometryUtil.java
r34317 r36194 19 19 * can then easily be drawn on a {@link MapView}s {@link Graphics2D}-context. 20 20 */ 21 public final 21 public final class MapViewGeometryUtil { 22 22 private MapViewGeometryUtil() { 23 23 // Private constructor to avoid instantiation … … 26 26 /** 27 27 * Subtracts the download bounds from the rectangular bounds of the map view. 28 * @param mv the MapView that is used for the LatLon-to-Point-conversion and that determines 29 * the Bounds from which the downloaded Bounds are subtracted 28 * 29 * @param mv the MapView that is used for the LatLon-to-Point-conversion and that determines 30 * the Bounds from which the downloaded Bounds are subtracted 30 31 * @param downloadBounds multiple {@link Bounds} objects that represent the downloaded area 31 32 * @return the difference between the {@link MapView}s bounds and the downloaded area … … 41 42 Point p1 = mv.getPoint(bounds.getMin()); 42 43 Point p2 = mv.getPoint(bounds.getMax()); 43 Rectangle r = new Rectangle(Math.min(p1.x, p2.x), Math.min(p1.y, p2.y), 44 Math.abs(p2. x - p1.x), Math.abs(p2.y - p1.y));44 Rectangle r = new Rectangle(Math.min(p1.x, p2.x), Math.min(p1.y, p2.y), Math.abs(p2.x - p1.x), 45 Math.abs(p2.y - p1.y)); 45 46 a.subtract(new Area(r)); 46 47 } … … 51 52 * Converts a {@link StreetsideSequence} into a {@link Path2D} that can be drawn 52 53 * on the specified {@link NavigatableComponent}'s {@link Graphics2D}-context. 53 * @param nc the {@link NavigatableComponent} for which this conversion should be performed, typically a {@link MapView} 54 * 55 * @param nc the {@link NavigatableComponent} for which this conversion should be performed, typically a {@link MapView} 54 56 * @param seq the sequence to convert 55 57 * @return the {@link Path2D} object to which the {@link StreetsideSequence} has been converted -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/PluginState.java
r34577 r36194 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 5 6 import java.util.logging.Logger; 7 6 8 import javax.swing.JOptionPane; 7 9 8 import org.apache.log4j.Logger;9 10 import org.openstreetmap.josm.gui.MainApplication; 10 11 import org.openstreetmap.josm.tools.I18n; 12 import org.openstreetmap.josm.tools.Logging; 11 13 12 14 /** … … 16 18 public final class PluginState { 17 19 18 final static Logger logger = Logger.getLogger(PluginState.class);20 private static final Logger LOGGER = Logger.getLogger(PluginState.class.getCanonicalName()); 19 21 20 22 private static boolean submittingChangeset; 21 23 22 24 private static int runningDownloads; 23 /** Images that have to be uploaded. */ 25 /** 26 * Images that have to be uploaded. 27 */ 24 28 private static int imagesToUpload; 25 /** Images that have been uploaded. */ 29 /** 30 * Images that have been uploaded. 31 */ 26 32 private static int imagesUploaded; 27 33 … … 42 48 public static void finishDownload() { 43 49 if (runningDownloads == 0) { 44 logger.warn(I18n.tr("The amount of running downloads is equal to 0"));50 LOGGER.log(Logging.LEVEL_WARN, I18n.tr("The amount of running downloads is equal to 0")); 45 51 return; 46 52 } … … 65 71 return submittingChangeset; 66 72 } 67 /** 73 74 public static void setSubmittingChangeset(boolean isSubmitting) { 75 submittingChangeset = isSubmitting; 76 } 77 78 /** 68 79 * Checks if there is any running upload. 69 80 * … … 77 88 * Sets the amount of images that are going to be uploaded. 78 89 * 79 * @param amount 80 * The amount of images that are going to be uploaded. 90 * @param amount The amount of images that are going to be uploaded. 81 91 */ 82 92 public static void addImagesToUpload(int amount) { … … 102 112 imagesUploaded++; 103 113 if (imagesToUpload == imagesUploaded) { 104 114 finishedUploadDialog(imagesUploaded); 105 115 } 106 116 } 107 117 108 118 private static void finishedUploadDialog(int numImages) { 109 JOptionPane.showMessageDialog( 110 MainApplication.getMainFrame(), 111 tr("You have successfully uploaded {0} images to Bing.com", numImages), 112 tr("Finished upload"), 113 JOptionPane.INFORMATION_MESSAGE 114 ); 119 JOptionPane.showMessageDialog(MainApplication.getMainFrame(), 120 tr("You have successfully uploaded {0} images to Bing.com", numImages), tr("Finished upload"), 121 JOptionPane.INFORMATION_MESSAGE); 115 122 } 116 123 117 124 public static void notLoggedInToMapillaryDialog() { 118 JOptionPane.showMessageDialog( 119 MainApplication.getMainFrame(), 125 JOptionPane.showMessageDialog(MainApplication.getMainFrame(), 120 126 tr("You are not logged in, please log in to Streetside in the preferences"), 121 tr("Not Logged in to Streetside"), 122 JOptionPane.WARNING_MESSAGE 123 ); 127 tr("Not Logged in to Streetside"), JOptionPane.WARNING_MESSAGE); 124 128 } 125 129 … … 132 136 return tr("Uploading: {0}", "(" + imagesUploaded + "/" + imagesToUpload + ")"); 133 137 } 134 135 public static void setSubmittingChangeset(boolean isSubmitting) {136 submittingChangeset = isSubmitting;137 }138 138 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideColorScheme.java
r34317 r36194 51 51 /** 52 52 * Styles the given components as default panels (currently only the background is set to white) 53 * 53 54 * @param components the components to style as default panels (e.g. checkboxes also, that's why 54 * not only JPanels are accepted)55 * not only JPanels are accepted) 55 56 */ 56 57 public static void styleAsDefaultPanel(JComponent... components) { -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideProperties.java
r34433 r36194 14 14 15 15 public final class StreetsideProperties { 16 public static final BooleanProperty DELETE_AFTER_UPLOAD = new BooleanProperty("streetside.delete-after-upload", true); 16 public static final BooleanProperty DELETE_AFTER_UPLOAD = new BooleanProperty("streetside.delete-after-upload", 17 true); 17 18 public static final BooleanProperty DEVELOPER = new BooleanProperty("streetside.developer", false); 18 19 public static final BooleanProperty DISPLAY_HOUR = new BooleanProperty("streetside.display-hour", true); … … 20 21 public static final BooleanProperty MOVE_TO_IMG = new BooleanProperty("streetside.move-to-picture", true); 21 22 public static final BooleanProperty TIME_FORMAT_24 = new BooleanProperty("streetside.format-24", false); 22 public static final BooleanProperty IMAGE_LINK_TO_BLUR_EDITOR = new BooleanProperty("streetside.image-link-to-blur-editor", true); 23 public static final BooleanProperty CUBEMAP_LINK_TO_BLUR_EDITOR = new BooleanProperty("streetside.cubemap-link-to-blur-editor", true); 24 public static final IntegerProperty TILE_DOWNLOAD_THREAD_PAUSE_LEN_SEC = new IntegerProperty("streetside.tile-download-thread-pause-len-sec", 60); 25 public static final BooleanProperty PREDOWNLOAD_CUBEMAPS = new BooleanProperty("streetside.predownload-cubemaps", false); 23 public static final BooleanProperty IMAGE_LINK_TO_BLUR_EDITOR = new BooleanProperty( 24 "streetside.image-link-to-blur-editor", true); 25 public static final BooleanProperty CUBEMAP_LINK_TO_BLUR_EDITOR = new BooleanProperty( 26 "streetside.cubemap-link-to-blur-editor", true); 27 public static final IntegerProperty TILE_DOWNLOAD_THREAD_PAUSE_LEN_SEC = new IntegerProperty( 28 "streetside.tile-download-thread-pause-len-sec", 60); 29 public static final BooleanProperty PREDOWNLOAD_CUBEMAPS = new BooleanProperty("streetside.predownload-cubemaps", 30 false); 26 31 public static final BooleanProperty DEBUGING_ENABLED = new BooleanProperty("streetside.debugging-enabled", false); 27 public static final BooleanProperty DOWNLOAD_CUBEFACE_TILES_TOGETHER = new BooleanProperty("streetside.download-cubeface-tiles-together", false); 32 public static final BooleanProperty DOWNLOAD_CUBEFACE_TILES_TOGETHER = new BooleanProperty( 33 "streetside.download-cubeface-tiles-together", false); 28 34 29 35 /** … … 31 37 * Otherwise only all images (!) inside the download bounds are added, the others are discarded. 32 38 */ 33 public static final BooleanProperty CUT_OFF_SEQUENCES_AT_BOUNDS = 34 new BooleanProperty("streetside.cut-off-sequences-at-bounds", false);39 public static final BooleanProperty CUT_OFF_SEQUENCES_AT_BOUNDS = new BooleanProperty( 40 "streetside.cut-off-sequences-at-bounds", false); 35 41 public static final IntegerProperty MAPOBJECT_ICON_SIZE = new IntegerProperty("streetside.mapobjects.iconsize", 32); 36 public static final IntegerProperty MAX_MAPOBJECTS = new IntegerProperty("streetside.mapobjects.maximum-number", 200); 37 public static final BooleanProperty SHOW_DETECTED_SIGNS = new BooleanProperty("streetside.show-detected-signs", true); 38 public static final BooleanProperty SHOW_HIGH_RES_STREETSIDE_IMAGERY = new BooleanProperty("streetside.show-high-res-streetside-imagery", true); 42 public static final IntegerProperty MAX_MAPOBJECTS = new IntegerProperty("streetside.mapobjects.maximum-number", 43 200); 44 public static final BooleanProperty SHOW_DETECTED_SIGNS = new BooleanProperty("streetside.show-detected-signs", 45 true); 46 public static final BooleanProperty SHOW_HIGH_RES_STREETSIDE_IMAGERY = new BooleanProperty( 47 "streetside.show-high-res-streetside-imagery", true); 39 48 40 49 /** … … 45 54 * See {@code OsmDataLayer#PROPERTY_OUTSIDE_COLOR} 46 55 */ 47 public static final NamedColorProperty OUTSIDE_DOWNLOADED_AREA = new NamedColorProperty("outside downloaded area", Color.YELLOW); 56 public static final NamedColorProperty OUTSIDE_DOWNLOADED_AREA = new NamedColorProperty("outside downloaded area", 57 Color.YELLOW); 48 58 49 59 public static final DoubleProperty MAX_DOWNLOAD_AREA = new DoubleProperty("streetside.max-download-area", 0.015); 50 60 51 61 public static final IntegerProperty PICTURE_DRAG_BUTTON = new IntegerProperty("streetside.picture-drag-button", 3); 52 public static final IntegerProperty PICTURE_OPTION_BUTTON = new IntegerProperty("streetside.picture-option-button", 2); 62 public static final IntegerProperty PICTURE_OPTION_BUTTON = new IntegerProperty("streetside.picture-option-button", 63 2); 53 64 public static final IntegerProperty PICTURE_ZOOM_BUTTON = new IntegerProperty("streetside.picture-zoom-button", 1); 54 public static final IntegerProperty SEQUENCE_MAX_JUMP_DISTANCE = 55 new IntegerProperty("streetside.sequence-max-jump-distance", 100);65 public static final IntegerProperty SEQUENCE_MAX_JUMP_DISTANCE = new IntegerProperty( 66 "streetside.sequence-max-jump-distance", 100); 56 67 57 68 public static final StringProperty ACCESS_TOKEN = new StringProperty("streetside.access-token", null); 58 public static final StringProperty DOWNLOAD_MODE = 59 new StringProperty("streetside.download-mode",StreetsideDownloader.DOWNLOAD_MODE.DEFAULT.getPrefId());60 public static final StringProperty START_DIR = 61 new StringProperty("streetside.start-directory",System.getProperty("user.home"));62 public static final StringProperty URL_CLIENT_ID = 63 new StringProperty("streetside.url-clientid", System.getProperty("T1Fzd20xZjdtR0s1VDk5OFNIOXpYdzoxNDYyOGRkYzUyYTFiMzgz"));64 public static final StringProperty BING_MAPS_KEY = 65 new StringProperty("streetside.bing-maps-key", System.getProperty("AuftgJsO0Xs8Ts4M1xZUQJQXJNsvmh3IV8DkNieCiy3tCwCUMq76-WpkrBtNAuEm"));66 public static final StringProperty TEST_BUBBLE_ID = 67 new StringProperty("streetside.test-bubble-id", System.getProperty("80848005"));69 public static final StringProperty DOWNLOAD_MODE = new StringProperty("streetside.download-mode", 70 StreetsideDownloader.DOWNLOAD_MODE.DEFAULT.getPrefId()); 71 public static final StringProperty START_DIR = new StringProperty("streetside.start-directory", 72 System.getProperty("user.home")); 73 public static final StringProperty URL_CLIENT_ID = new StringProperty("streetside.url-clientid", 74 System.getProperty("streetside.url-clientid", "T1Fzd20xZjdtR0s1VDk5OFNIOXpYdzoxNDYyOGRkYzUyYTFiMzgz")); 75 public static final StringProperty BING_MAPS_KEY = new StringProperty("streetside.bing-maps-key", 76 System.getProperty("streetside.bing-maps-key", "AuftgJsO0Xs8Ts4M1xZUQJQXJNsvmh3IV8DkNieCiy3tCwCUMq76-WpkrBtNAuEm")); 77 public static final StringProperty TEST_BUBBLE_ID = new StringProperty("streetside.test-bubble-id", 78 System.getProperty("streetside.test-bubble-id", "80848005")); 68 79 69 80 /** … … 72 83 * Or opening the {@link ImageInfoPanel} immediately brings this number down to zero. 73 84 */ 74 public static final IntegerProperty IMAGEINFO_HELP_COUNTDOWN = 75 new IntegerProperty("streetside.imageInfo.helpDisplayedCountdown", 4);85 public static final IntegerProperty IMAGEINFO_HELP_COUNTDOWN = new IntegerProperty( 86 "streetside.imageInfo.helpDisplayedCountdown", 4); 76 87 77 88 /** … … 80 91 * Or opening the {@link StreetsideViewerPanel} immediately brings this number down to zero. 81 92 */ 82 public static final IntegerProperty STREETSIDE_VIEWER_HELP_COUNTDOWN = 83 new IntegerProperty("streetside.streetsideViewer.helpDisplayedCountdown", 4);93 public static final IntegerProperty STREETSIDE_VIEWER_HELP_COUNTDOWN = new IntegerProperty( 94 "streetside.streetsideViewer.helpDisplayedCountdown", 4); 84 95 85 96 /** 86 97 * The number of images to be prefetched when a streetside image is selected 87 98 */ 88 public static final IntegerProperty PRE_FETCH_IMAGE_COUNT = new IntegerProperty("streetside.prefetch-image-count", 2); 99 public static final IntegerProperty PRE_FETCH_IMAGE_COUNT = new IntegerProperty("streetside.prefetch-image-count", 100 2); 89 101 90 102 /** 91 103 * The number of images to be prefetched when a streetside image is selected 92 104 */ 93 public static final IntegerProperty PRE_FETCH_CUBEMAP_COUNT = new IntegerProperty("streetside.prefetch-image-count", 2);94 105 public static final IntegerProperty PRE_FETCH_CUBEMAP_COUNT = new IntegerProperty("streetside.prefetch-image-count", 106 2); 95 107 96 108 private StreetsideProperties() { -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideSequenceIdGenerator.java
r34577 r36194 9 9 * handle sequences of contiguous imagery, but Streetside only has implicit 10 10 * sequences defined by the "pre" and "ne" attributes. 11 * 12 * See {@link org.openstreetmap.josm.plugins.streetside.StreetsideSequence}11 * 12 * @see org.openstreetmap.josm.plugins.streetside.StreetsideSequence 13 13 */ 14 14 public class StreetsideSequenceIdGenerator { -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideURL.java
r34431 r36194 15 15 import java.util.Map; 16 16 import java.util.Map.Entry; 17 18 import org.apache.log4j.Logger; 17 import java.util.logging.Logger; 18 19 19 import org.openstreetmap.josm.data.Bounds; 20 20 import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils; … … 24 24 public final class StreetsideURL { 25 25 26 final static Logger logger = Logger.getLogger(StreetsideURL.class); 27 28 /** Base URL of the Bing Bubble API. */ 29 private static final String STREETSIDE_BASE_URL = "https://dev.virtualearth.net/mapcontrol/HumanScaleServices/GetBubbles.ashx"; 30 /** Base URL for Streetside privacy concerns. */ 26 private static final Logger LOGGER = Logger.getLogger(StreetsideURL.class.getCanonicalName()); 27 28 /** 29 * Base URL of the Bing Bubble API. 30 */ 31 private static final String STREETSIDE_BASE_URL = "https://dev.virtualearth.net/mapcontrol/HumanScaleServices/GetBubbles.ashx"; 32 /** 33 * Base URL for Streetside privacy concerns. 34 */ 31 35 private static final String STREETSIDE_PRIVACY_URL = "https://www.bing.com/maps/privacyreport/streetsideprivacyreport?bubbleid="; 32 36 33 private static final int OSM_BBOX_NORTH = 3; 34 private static final int OSM_BBOX_SOUTH = 1; 35 private static final int OSM_BBOXEAST = 2; 36 private static final int OSM_BBOX_WEST = 0; 37 38 public static final class APIv3 { 39 40 private APIv3() { 41 // Private constructor to avoid instantiation 42 } 43 44 public static URL searchStreetsideImages(Bounds bounds) { 45 return StreetsideURL.string2URL(StreetsideURL.STREETSIDE_BASE_URL, APIv3.queryStreetsideString(bounds)); 46 } 47 48 /** 49 * The APIv3 returns a Link header for each request. It contains a URL for requesting more results. 50 * If you supply the value of the Link header, this method returns the next URL, 51 * if such a URL is defined in the header. 52 * @param value the value of the HTTP-header with key "Link" 53 * @return the {@link URL} for the next result page, or <code>null</code> if no such URL could be found 54 */ 55 public static URL parseNextFromLinkHeaderValue(String value) { 56 if (value != null) { 57 // Iterate over the different entries of the Link header 58 for (final String link : value.split(",", Integer.MAX_VALUE)) { 59 boolean isNext = false; 60 URL url = null; 61 // Iterate over the parts of each entry (typically it's one `rel="‹linkType›"` and one like `<https://URL>`) 62 for (String linkPart : link.split(";", Integer.MAX_VALUE)) { 63 linkPart = linkPart.trim(); 64 isNext |= linkPart.matches("rel\\s*=\\s*\"next\""); 65 if (linkPart.length() >= 1 && linkPart.charAt(0) == '<' && linkPart.endsWith(">")) { 66 try { 67 url = new URL(linkPart.substring(1, linkPart.length() - 1)); 68 } catch (final MalformedURLException e) { 69 Logging.log(Logging.LEVEL_WARN, "Mapillary API v3 returns a malformed URL in the Link header.", e); 70 } 71 } 72 } 73 // If both a URL and the rel=next attribute are present, return the URL. Otherwise null is returned 74 if (url != null && isNext) { 75 return url; 76 } 77 } 78 } 79 return null; 80 } 81 82 public static String queryString(final Bounds bounds) { 83 if (bounds != null) { 84 final Map<String, String> parts = new HashMap<>(); 85 parts.put("bbox", bounds.toBBox().toStringCSV(",")); 86 return StreetsideURL.queryString(parts); 87 } 88 return StreetsideURL.queryString(null); 89 } 90 91 public static String queryStreetsideString(final Bounds bounds) { 92 if (bounds != null) { 93 final Map<String, String> parts = new HashMap<>(); 94 parts.put("bbox", bounds.toBBox().toStringCSV(",")); 95 return StreetsideURL.queryStreetsideBoundsString(parts); 96 } 97 return StreetsideURL.queryStreetsideBoundsString(null); 98 } 99 100 } 101 102 public static final class VirtualEarth { 103 private static final String BASE_URL_PREFIX = "https://t.ssl.ak.tiles.virtualearth.net/tiles/hs"; 104 private static final String BASE_URL_SUFFIX = ".jpg?g=6528&n=z"; 105 106 private VirtualEarth() { 107 // Private constructor to avoid instantiation 108 } 109 110 public static URL streetsideTile(final String id, boolean thumbnail) { 111 StringBuilder modifiedId = new StringBuilder(); 112 113 if (thumbnail) { 37 private static final int OSM_BBOX_NORTH = 3; 38 private static final int OSM_BBOX_SOUTH = 1; 39 private static final int OSM_BBOXEAST = 2; 40 private static final int OSM_BBOX_WEST = 0; 41 42 private StreetsideURL() { 43 // Private constructor to avoid instantiation 44 } 45 46 public static URL[] string2URLs(String baseUrlPrefix, String cubemapImageId, String baseUrlSuffix) { 47 List<URL> res = new ArrayList<>(); 48 49 switch (Boolean.TRUE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) ? 16 : 4) { 50 51 case 16: 52 53 EnumSet.allOf(CubemapUtils.CubemapFaces.class).forEach(face -> { 54 for (int i = 0; i < 4; i++) { 55 for (int j = 0; j < 4; j++) { 56 try { 57 final String urlStr = baseUrlPrefix + cubemapImageId 58 + CubemapUtils.rowCol2StreetsideCellAddressMap.get(String.valueOf(i) + j) 59 + baseUrlSuffix; 60 res.add(new URL(urlStr)); 61 } catch (final MalformedURLException e) { 62 LOGGER.log(Logging.LEVEL_ERROR, "Error creating URL String for cubemap " + cubemapImageId); 63 e.printStackTrace(); 64 } 65 66 } 67 } 68 }); 69 break; 70 71 case 4: 72 EnumSet.allOf(CubemapUtils.CubemapFaces.class).forEach(face -> { 73 for (int i = 0; i < 4; i++) { 74 75 try { 76 final String urlStr = baseUrlPrefix + cubemapImageId 77 + CubemapUtils.rowCol2StreetsideCellAddressMap.get(String.valueOf(i)) + baseUrlSuffix; 78 res.add(new URL(urlStr)); 79 } catch (final MalformedURLException e) { 80 LOGGER.log(Logging.LEVEL_WARN, "Error creating URL String for cubemap " + cubemapImageId); 81 e.printStackTrace(); 82 } 83 84 } 85 }); 86 break; // break is optional 87 default: 88 // Statements 89 } 90 return res.toArray(new URL[0]); 91 } 92 93 /** 94 * Builds a query string from it's parts that are supplied as a {@link Map} 95 * 96 * @param parts the parts of the query string 97 * @return the constructed query string (including a leading ?) 98 */ 99 static String queryString(Map<String, String> parts) { 100 final StringBuilder ret = new StringBuilder("?client_id=").append(StreetsideProperties.URL_CLIENT_ID.get()); 101 if (parts != null) { 102 for (final Entry<String, String> entry : parts.entrySet()) { 103 try { 104 ret.append('&').append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8.name())).append('=') 105 .append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8.name())); 106 } catch (final UnsupportedEncodingException e) { 107 LOGGER.log(Logging.LEVEL_WARN, e.getMessage(), e); // This should not happen, as the encoding is hard-coded 108 } 109 } 110 } 111 112 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 113 LOGGER.log(Logging.LEVEL_DEBUG, MessageFormat.format("queryString result: {0}", ret)); 114 } 115 116 return ret.toString(); 117 } 118 119 static String queryStreetsideBoundsString(Map<String, String> parts) { 120 final StringBuilder ret = new StringBuilder("?n="); 121 if (parts != null) { 122 final List<String> bbox = new ArrayList<>(Arrays.asList(parts.get("bbox").split(","))); 123 try { 124 ret.append(URLEncoder.encode(bbox.get(StreetsideURL.OSM_BBOX_NORTH), StandardCharsets.UTF_8.name())) 125 .append("&s=") 126 .append(URLEncoder.encode(bbox.get(StreetsideURL.OSM_BBOX_SOUTH), 127 StandardCharsets.UTF_8.name())) 128 .append("&e=") 129 .append(URLEncoder.encode(bbox.get(StreetsideURL.OSM_BBOXEAST), StandardCharsets.UTF_8.name())) 130 .append("&w=") 131 .append(URLEncoder.encode(bbox.get(StreetsideURL.OSM_BBOX_WEST), StandardCharsets.UTF_8.name())) 132 .append("&c=1000").append("&appkey=").append(StreetsideProperties.BING_MAPS_KEY.get()); 133 } catch (final UnsupportedEncodingException e) { 134 LOGGER.log(Logging.LEVEL_ERROR, e.getMessage(), e); // This should not happen, as the encoding is hard-coded 135 } 136 } 137 138 return ret.toString(); 139 } 140 141 static String queryByIdString(Map<String, String> parts) { 142 final StringBuilder ret = new StringBuilder("?id="); 143 try { 144 ret.append(URLEncoder.encode(StreetsideProperties.TEST_BUBBLE_ID.get(), StandardCharsets.UTF_8.name())); 145 ret.append('&').append(URLEncoder.encode("appkey=", StandardCharsets.UTF_8.name())).append('=') 146 .append(URLEncoder.encode(StreetsideProperties.BING_MAPS_KEY.get(), StandardCharsets.UTF_8.name())); 147 } catch (final UnsupportedEncodingException e) { 148 LOGGER.log(Logging.LEVEL_ERROR, e.getMessage(), e); // This should not happen, as the encoding is hard-coded 149 } 150 151 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 152 LOGGER.info("queryById result: " + ret); 153 } 154 return ret.toString(); 155 } 156 157 /** 158 * Converts a {@link String} into a {@link URL} without throwing a {@link MalformedURLException}. 159 * Instead such an exception will lead to an {@link Logger}. 160 * So you should be very confident that your URL is well-formed when calling this method. 161 * 162 * @param strings the Strings describing the URL 163 * @return the URL that is constructed from the given string 164 */ 165 static URL string2URL(String... strings) { 166 final StringBuilder builder = new StringBuilder(); 167 for (int i = 0; strings != null && i < strings.length; i++) { 168 builder.append(strings[i]); 169 } 170 try { 171 return new URL(builder.toString()); 172 } catch (final MalformedURLException e) { 173 LOGGER.log(Logging.LEVEL_ERROR, I18n.tr(String.format("The class '%s' produces malformed URLs like '%s'!", 174 StreetsideURL.class.getName(), builder), e)); 175 return null; 176 } 177 } 178 179 public static final class APIv3 { 180 181 private APIv3() { 182 // Private constructor to avoid instantiation 183 } 184 185 public static URL searchStreetsideImages(Bounds bounds) { 186 return StreetsideURL.string2URL(StreetsideURL.STREETSIDE_BASE_URL, APIv3.queryStreetsideString(bounds)); 187 } 188 189 /** 190 * The APIv3 returns a Link header for each request. It contains a URL for requesting more results. 191 * If you supply the value of the Link header, this method returns the next URL, 192 * if such a URL is defined in the header. 193 * 194 * @param value the value of the HTTP-header with key "Link" 195 * @return the {@link URL} for the next result page, or <code>null</code> if no such URL could be found 196 */ 197 public static URL parseNextFromLinkHeaderValue(String value) { 198 if (value != null) { 199 // Iterate over the different entries of the Link header 200 for (final String link : value.split(",", Integer.MAX_VALUE)) { 201 boolean isNext = false; 202 URL url = null; 203 // Iterate over the parts of each entry (typically it's one `rel="‹linkType›"` and one like `<https://URL>`) 204 for (String linkPart : link.split(";", Integer.MAX_VALUE)) { 205 linkPart = linkPart.trim(); 206 isNext |= linkPart.matches("rel\\s*=\\s*\"next\""); 207 if (linkPart.length() >= 1 && linkPart.charAt(0) == '<' && linkPart.endsWith(">")) { 208 try { 209 url = new URL(linkPart.substring(1, linkPart.length() - 1)); 210 } catch (final MalformedURLException e) { 211 Logging.log(Logging.LEVEL_WARN, 212 "Mapillary API v3 returns a malformed URL in the Link header.", e); 213 } 214 } 215 } 216 // If both a URL and the rel=next attribute are present, return the URL. Otherwise null is returned 217 if (url != null && isNext) { 218 return url; 219 } 220 } 221 } 222 return null; 223 } 224 225 public static String queryString(final Bounds bounds) { 226 if (bounds != null) { 227 final Map<String, String> parts = new HashMap<>(); 228 parts.put("bbox", bounds.toBBox().toStringCSV(",")); 229 return StreetsideURL.queryString(parts); 230 } 231 return StreetsideURL.queryString(null); 232 } 233 234 public static String queryStreetsideString(final Bounds bounds) { 235 if (bounds != null) { 236 final Map<String, String> parts = new HashMap<>(); 237 parts.put("bbox", bounds.toBBox().toStringCSV(",")); 238 return StreetsideURL.queryStreetsideBoundsString(parts); 239 } 240 return StreetsideURL.queryStreetsideBoundsString(null); 241 } 242 243 } 244 245 public static final class VirtualEarth { 246 private static final String BASE_URL_PREFIX = "https://t.ssl.ak.tiles.virtualearth.net/tiles/hs"; 247 private static final String BASE_URL_SUFFIX = ".jpg?g=6528&n=z"; 248 249 private VirtualEarth() { 250 // Private constructor to avoid instantiation 251 } 252 253 public static URL streetsideTile(final String id, boolean thumbnail) { 254 StringBuilder modifiedId = new StringBuilder(); 255 256 if (thumbnail) { 114 257 // pad thumbnail imagery with leading zeros 115 258 if (id.length() < 16) { … … 119 262 } 120 263 modifiedId.append(id).append("01"); 121 } else if(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()){ 122 // pad 16-tiled imagery with leading zeros 123 if (id.length() < 20) { 124 for (int i = 0; i < 20 - id.length(); i++) { 125 modifiedId.append("0"); 264 } else { 265 if (Boolean.TRUE.equals(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get())) { 266 // pad 16-tiled imagery with leading zeros 267 if (id.length() < 20) { 268 for (int i = 0; i < 20 - id.length(); i++) { 269 modifiedId.append("0"); 270 } 271 } 272 } else { 273 // pad 4-tiled imagery with leading zeros 274 if (id.length() < 19) { 275 for (int i = 0; i < 19 - id.length(); i++) { 276 modifiedId.append("0"); 277 } 278 } 126 279 } 127 280 modifiedId.append(id); 128 } 129 } else if(!StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) { 130 // pad 4-tiled imagery with leading zeros 131 if (id.length() < 19) { 132 for (int i = 0; i < 19 - id.length(); i++) { 133 modifiedId.append("0"); 134 } 135 modifiedId.append(id); 136 } 137 } 138 URL url = StreetsideURL.string2URL(VirtualEarth.BASE_URL_PREFIX + modifiedId.toString() + VirtualEarth.BASE_URL_SUFFIX); 139 if(StreetsideProperties.DEBUGING_ENABLED.get()) { 140 logger.debug(MessageFormat.format("Tile task URL {0} invoked.", url.toString())); 141 } 142 return url; 143 } 144 } 145 146 public static final class MainWebsite { 147 148 private MainWebsite() { 149 // Private constructor to avoid instantiation 150 } 151 152 /** 153 * Gives you the URL for the online viewer of a specific Streetside image. 154 * @param id the id of the image to which you want to link 155 * @return the URL of the online viewer for the image with the given image key 156 * @throws IllegalArgumentException if the image key is <code>null</code> 157 */ 158 public static URL browseImage(String id) { 159 if (id == null) { 160 throw new IllegalArgumentException("The image id may not be null!"); 161 } 162 163 StringBuilder modifiedId = new StringBuilder(); 281 } 282 URL url = StreetsideURL 283 .string2URL(VirtualEarth.BASE_URL_PREFIX + modifiedId + VirtualEarth.BASE_URL_SUFFIX); 284 if (Boolean.TRUE.equals(StreetsideProperties.DEBUGING_ENABLED.get())) { 285 LOGGER.log(Logging.LEVEL_DEBUG, MessageFormat.format("Tile task URL {0} invoked.", url)); 286 } 287 return url; 288 } 289 } 290 291 public static final class MainWebsite { 292 293 private MainWebsite() { 294 // Private constructor to avoid instantiation 295 } 296 297 /** 298 * Gives you the URL for the online viewer of a specific Streetside image. 299 * 300 * @param id the id of the image to which you want to link 301 * @return the URL of the online viewer for the image with the given image key 302 * @throws IllegalArgumentException if the image key is <code>null</code> 303 */ 304 public static URL browseImage(String id) { 305 if (id == null) { 306 throw new IllegalArgumentException("The image id may not be null!"); 307 } 308 309 StringBuilder modifiedId = new StringBuilder(); 164 310 165 311 // pad thumbnail imagery with leading zeros … … 171 317 modifiedId.append(id).append("01"); 172 318 173 return StreetsideURL.string2URL(MessageFormat.format("{0}{1}{2}",VirtualEarth.BASE_URL_PREFIX, modifiedId.toString(), VirtualEarth.BASE_URL_SUFFIX)); 174 } 175 176 /** 177 * Gives you the URL for the blur editor of the image with the given key. 178 * @param id the key of the image for which you want to open the blur editor 179 * @return the URL of the blur editor 180 * @throws IllegalArgumentException if the image key is <code>null</code> 181 */ 182 public static URL streetsidePrivacyLink(final String id) { 183 if (id == null) { 184 throw new IllegalArgumentException("The image id must not be null!"); 185 } 186 String urlEncodedId; 187 try { 188 urlEncodedId = URLEncoder.encode(id, StandardCharsets.UTF_8.name()); 189 } catch (final UnsupportedEncodingException e) { 190 logger.error(I18n.tr("Unsupported encoding when URL encoding", e)); 191 urlEncodedId = id; 192 } 193 return StreetsideURL.string2URL(StreetsideURL.STREETSIDE_PRIVACY_URL, urlEncodedId); 194 } 195 196 } 197 198 private StreetsideURL() { 199 // Private constructor to avoid instantiation 200 } 201 202 public static URL[] string2URLs(String baseUrlPrefix, String cubemapImageId, String baseUrlSuffix) { 203 List<URL> res = new ArrayList<>(); 204 205 switch (StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get() ? 16 : 4) { 206 207 case 16: 208 209 EnumSet.allOf(CubemapUtils.CubemapFaces.class).forEach(face -> { 210 for (int i = 0; i < 4; i++) { 211 for (int j = 0; j < 4; j++) { 212 try { 213 final String urlStr = baseUrlPrefix + cubemapImageId 214 + CubemapUtils.rowCol2StreetsideCellAddressMap 215 .get(String.valueOf(i) + String.valueOf(j)) 216 + baseUrlSuffix; 217 res.add(new URL(urlStr)); 218 } catch (final MalformedURLException e) { 219 logger.error("Error creating URL String for cubemap " + cubemapImageId); 220 e.printStackTrace(); 221 } 222 223 } 224 } 225 }); 226 break; 227 228 case 4: 229 EnumSet.allOf(CubemapUtils.CubemapFaces.class).forEach(face -> { 230 for (int i = 0; i < 4; i++) { 231 232 try { 233 final String urlStr = baseUrlPrefix + cubemapImageId 234 + CubemapUtils.rowCol2StreetsideCellAddressMap.get(String.valueOf(i)) + baseUrlSuffix; 235 res.add(new URL(urlStr)); 236 } catch (final MalformedURLException e) { 237 logger.error("Error creating URL String for cubemap " + cubemapImageId); 238 e.printStackTrace(); 239 } 240 241 } 242 }); 243 break; // break is optional 244 default: 245 // Statements 246 } 247 return res.stream().toArray(URL[]::new); 248 } 249 250 /** 251 * Builds a query string from it's parts that are supplied as a {@link Map} 252 * @param parts the parts of the query string 253 * @return the constructed query string (including a leading ?) 254 */ 255 static String queryString(Map<String, String> parts) { 256 final StringBuilder ret = new StringBuilder("?client_id=").append(StreetsideProperties.URL_CLIENT_ID.get()); 257 if (parts != null) { 258 for (final Entry<String, String> entry : parts.entrySet()) { 259 try { 260 ret.append('&') 261 .append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8.name())) 262 .append('=') 263 .append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8.name())); 264 } catch (final UnsupportedEncodingException e) { 265 logger.error(e); // This should not happen, as the encoding is hard-coded 266 } 267 } 268 } 269 270 if(StreetsideProperties.DEBUGING_ENABLED.get()) { 271 logger.debug(MessageFormat.format("queryString result: {0}", ret.toString())); 272 } 273 274 return ret.toString(); 275 } 276 277 static String queryStreetsideBoundsString(Map<String, String> parts) { 278 final StringBuilder ret = new StringBuilder("?n="); 279 if (parts != null) { 280 final List<String> bbox = new ArrayList<>(Arrays.asList(parts.get("bbox").split(","))); 281 try { 282 ret.append(URLEncoder.encode(bbox.get(StreetsideURL.OSM_BBOX_NORTH), StandardCharsets.UTF_8.name())) 283 .append("&s=") 284 .append(URLEncoder.encode(bbox.get(StreetsideURL.OSM_BBOX_SOUTH), StandardCharsets.UTF_8.name())) 285 .append("&e=") 286 .append(URLEncoder.encode(bbox.get(StreetsideURL.OSM_BBOXEAST), StandardCharsets.UTF_8.name())) 287 .append("&w=") 288 .append(URLEncoder.encode(bbox.get(StreetsideURL.OSM_BBOX_WEST), StandardCharsets.UTF_8.name())) 289 .append("&c=1000") 290 .append("&appkey=") 291 .append(StreetsideProperties.BING_MAPS_KEY.get()); 292 } catch (final UnsupportedEncodingException e) { 293 logger.error(e); // This should not happen, as the encoding is hard-coded 294 } 295 } 296 297 return ret.toString(); 298 } 299 300 static String queryByIdString(Map<String, String> parts) { 301 final StringBuilder ret = new StringBuilder("?id="); 302 try { 303 ret.append(URLEncoder.encode(StreetsideProperties.TEST_BUBBLE_ID.get(), StandardCharsets.UTF_8.name())); 304 ret.append('&').append(URLEncoder.encode("appkey=", StandardCharsets.UTF_8.name())).append('=') 305 .append(URLEncoder.encode(StreetsideProperties.BING_MAPS_KEY.get(), StandardCharsets.UTF_8.name())); 306 } catch (final UnsupportedEncodingException e) { 307 logger.error(e); // This should not happen, as the encoding is hard-coded 308 } 309 310 if(StreetsideProperties.DEBUGING_ENABLED.get()) { 311 logger.info("queryById result: " + ret.toString()); 312 } 313 return ret.toString(); 314 } 315 316 /** 317 * Converts a {@link String} into a {@link URL} without throwing a {@link MalformedURLException}. 318 * Instead such an exception will lead to an {@link Logger}. 319 * So you should be very confident that your URL is well-formed when calling this method. 320 * @param strings the Strings describing the URL 321 * @return the URL that is constructed from the given string 322 */ 323 static URL string2URL(String... strings) { 324 final StringBuilder builder = new StringBuilder(); 325 for (int i = 0; strings != null && i < strings.length; i++) { 326 builder.append(strings[i]); 327 } 328 try { 329 return new URL(builder.toString()); 330 } catch (final MalformedURLException e) { 331 logger.error(I18n.tr(String.format( 332 "The class '%s' produces malformed URLs like '%s'!", 333 StreetsideURL.class.getName(), 334 builder 335 ), e)); 336 return null; 337 } 338 } 319 return StreetsideURL.string2URL(MessageFormat.format("{0}{1}{2}", VirtualEarth.BASE_URL_PREFIX, modifiedId, 320 VirtualEarth.BASE_URL_SUFFIX)); 321 } 322 323 /** 324 * Gives you the URL for the blur editor of the image with the given key. 325 * 326 * @param id the key of the image for which you want to open the blur editor 327 * @return the URL of the blur editor 328 * @throws IllegalArgumentException if the image key is <code>null</code> 329 */ 330 public static URL streetsidePrivacyLink(final String id) { 331 if (id == null) { 332 throw new IllegalArgumentException("The image id must not be null!"); 333 } 334 String urlEncodedId; 335 try { 336 urlEncodedId = URLEncoder.encode(id, StandardCharsets.UTF_8.name()); 337 } catch (final UnsupportedEncodingException e) { 338 LOGGER.log(Logging.LEVEL_ERROR, I18n.tr("Unsupported encoding when URL encoding", e), e); 339 urlEncodedId = id; 340 } 341 return StreetsideURL.string2URL(StreetsideURL.STREETSIDE_PRIVACY_URL, urlEncodedId); 342 } 343 344 } 339 345 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideUtils.java
r34431 r36194 16 16 import org.apache.commons.imaging.common.RationalNumber; 17 17 import org.apache.commons.imaging.formats.tiff.constants.GpsTagConstants; 18 import org.apache.log4j.Logger;19 18 import org.openstreetmap.josm.data.Bounds; 20 19 import org.openstreetmap.josm.data.coor.LatLon; … … 32 31 public final class StreetsideUtils { 33 32 34 final static Logger logger = Logger.getLogger(StreetsideUtils.class);35 36 33 private static final double MIN_ZOOM_SQUARE_SIDE = 0.002; 37 34 … … 101 98 * 102 99 * @param degMinSec an array of length 3, the values in there are (in this order) 103 * 104 * @param ref 105 * 106 * 107 * 108 * 109 * 110 * 111 * 112 * 113 * 114 * 115 * 116 * 100 * degrees, minutes and seconds 101 * @param ref the latitude or longitude reference determining if the given value 102 * is: 103 * <ul> 104 * <li>north ( 105 * {@link GpsTagConstants#GPS_TAG_GPS_LATITUDE_REF_VALUE_NORTH}) or 106 * south ( 107 * {@link GpsTagConstants#GPS_TAG_GPS_LATITUDE_REF_VALUE_SOUTH}) of 108 * the equator</li> 109 * <li>east ( 110 * {@link GpsTagConstants#GPS_TAG_GPS_LONGITUDE_REF_VALUE_EAST}) or 111 * west ({@link GpsTagConstants#GPS_TAG_GPS_LONGITUDE_REF_VALUE_WEST} 112 * ) of the equator</li> 113 * </ul> 117 114 * @return the decimal degree-value for the given input, negative when west of 118 115 * 0-meridian or south of equator, positive otherwise 119 116 * @throws IllegalArgumentException if {@code degMinSec} doesn't have length 3 or if {@code ref} is 120 * 117 * not one of the values mentioned above 121 118 */ 122 119 public static double degMinSecToDouble(RationalNumber[] degMinSec, String ref) { … … 130 127 131 128 switch (ref) { 132 133 134 135 136 137 138 129 case GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF_VALUE_NORTH: 130 case GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF_VALUE_SOUTH: 131 case GpsTagConstants.GPS_TAG_GPS_LONGITUDE_REF_VALUE_EAST: 132 case GpsTagConstants.GPS_TAG_GPS_LONGITUDE_REF_VALUE_WEST: 133 break; 134 default: 135 throw new IllegalArgumentException("Invalid ref."); 139 136 } 140 137 … … 144 141 145 142 if (GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF_VALUE_SOUTH.equals(ref) 146 143 || GpsTagConstants.GPS_TAG_GPS_LONGITUDE_REF_VALUE_WEST.equals(ref)) { 147 144 result *= -1; 148 145 } … … 166 163 } 167 164 if ((imgA.next() != null || imgB.previous() != null) && (imgB.next() != null || imgA.previous() != null)) { 168 throw new IllegalArgumentException("You can only join an image at the end of a sequence with one at the beginning of another sequence."); 165 throw new IllegalArgumentException( 166 "You can only join an image at the end of a sequence with one at the beginning of another sequence."); 169 167 } 170 168 if (imgA.next() != null || imgB.previous() != null) { … … 223 221 /** 224 222 * Separates two images belonging to the same sequence. The two images have to be consecutive in the same sequence. 225 * Two new sequences are created and all images up to (and including) either {@code imgA} or {@code imgB} (whichever appears first in the sequence) are put into the first of the two sequences. 223 * Two new sequences are created and all images up to (and including) either {@code imgA} or {@code imgB} 224 * (whichever appears first in the sequence) are put into the first of the two sequences. 226 225 * All others are put into the second new sequence. 227 226 * … … 237 236 } 238 237 if (imgB.equals(imgA.next()) && imgA.equals(imgB.next())) { 239 throw new IllegalArgumentException("When unjoining with two images these must be consecutive in one sequence."); 238 throw new IllegalArgumentException( 239 "When unjoining with two images these must be consecutive in one sequence."); 240 240 } 241 241 … … 273 273 ret.append(I18n.tr("Total Streetside images: {0}", StreetsideLayer.getInstance().getToolTipText())); 274 274 } else if (PluginState.isSubmittingChangeset()) { 275 275 ret.append(I18n.tr("Submitting Streetside Changeset")); 276 276 } else { 277 277 ret.append(I18n.tr("No images found")); -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonDecoder.java
r36122 r36194 9 9 import java.util.function.Function; 10 10 11 import org.openstreetmap.josm.data.coor.LatLon; 12 import org.openstreetmap.josm.tools.I18n; 13 import org.openstreetmap.josm.tools.Logging; 14 11 15 import jakarta.json.JsonArray; 12 16 import jakarta.json.JsonNumber; 13 17 import jakarta.json.JsonObject; 14 18 import jakarta.json.JsonValue; 15 16 import org.openstreetmap.josm.data.coor.LatLon;17 import org.openstreetmap.josm.tools.I18n;18 import org.openstreetmap.josm.tools.Logging;19 19 20 20 public final class JsonDecoder { … … 29 29 * of the desired Java objects. The method, which converts the GeoJSON features into Java objects 30 30 * is given as a parameter to this method. 31 * @param <T> feature type 32 * @param json the {@link JsonObject} to be parsed 31 * 32 * @param <T> feature type 33 * @param json the {@link JsonObject} to be parsed 33 34 * @param featureDecoder feature decoder which transforms JSON objects to Java objects 34 35 * @return a {@link Collection} which is parsed from the given {@link JsonObject}, which contains GeoJSON. 35 * 36 * 36 * Currently a {@link HashSet} is used, but please don't rely on it, this could change at any time without 37 * prior notice. The return value will not be <code>null</code>. 37 38 */ 38 public static <T> Collection<T> decodeFeatureCollection(final JsonObject json, Function<JsonObject, T> featureDecoder) { 39 public static <T> Collection<T> decodeFeatureCollection(final JsonObject json, 40 Function<JsonObject, T> featureDecoder) { 39 41 final Collection<T> result = new HashSet<>(); 40 if ( 41 json != null && "FeatureCollection".equals(json.getString("type", null)) && json.containsKey("features") 42 ) { 42 if (json != null && "FeatureCollection".equals(json.getString("type", null)) && json.containsKey("features")) { 43 43 final JsonValue features = json.get("features"); 44 44 for (int i = 0; features instanceof JsonArray && i < ((JsonArray) features).size(); i++) { … … 58 58 * Decodes a {@link JsonArray} of exactly size 2 to a {@link LatLon} instance. 59 59 * The first value in the {@link JsonArray} is treated as longitude, the second one as latitude. 60 * 60 61 * @param json the {@link JsonArray} containing the two numbers 61 62 * @return the decoded {@link LatLon} instance, or <code>null</code> if the parameter is 62 * 63 * not a {@link JsonArray} of exactly size 2 containing two {@link JsonNumber}s. 63 64 */ 64 65 static LatLon decodeLatLon(final JsonArray json) { … … 72 73 /** 73 74 * Decodes a pair of double values, which are stored in a {@link JsonArray} of exactly size 2. 75 * 74 76 * @param json the {@link JsonArray} containing the two values 75 77 * @return a double array which contains the two values in the same order, or <code>null</code> 76 * 78 * if the parameter was not a {@link JsonArray} of exactly size 2 containing two {@link JsonNumber}s 77 79 */ 78 80 static double[] decodeDoublePair(final JsonArray json) { 79 if ( 80 json != null && 81 json.size() == 2 && 82 json.get(0) instanceof JsonNumber && 83 json.get(1) instanceof JsonNumber 84 ) { 85 return new double[]{json.getJsonNumber(0).doubleValue(), json.getJsonNumber(1).doubleValue()}; 81 if (json != null && json.size() == 2 && json.get(0) instanceof JsonNumber 82 && json.get(1) instanceof JsonNumber) { 83 return new double[] { json.getJsonNumber(0).doubleValue(), json.getJsonNumber(1).doubleValue() }; 86 84 } 87 85 return EMPTY_DOUBLE; … … 91 89 * Decodes a timestamp formatted as a {@link String} to the equivalent UNIX epoch timestamp 92 90 * (number of milliseconds since 1970-01-01T00:00:00.000+0000). 91 * 93 92 * @param timestamp the timestamp formatted according to the format <code>yyyy-MM-dd'T'HH:mm:ss.SSSX</code> 94 93 * @return the point in time as a {@link Long} value representing the UNIX epoch time, or <code>null</code> if the 95 * 96 * 94 * parameter does not match the required format (this also triggers a warning via 95 * {@link Logging}, or the parameter is <code>null</code>). 97 96 */ 98 97 static Long decodeTimestamp(final String timestamp) { … … 102 101 } catch (ParseException e) { 103 102 StackTraceElement calledBy = e.getStackTrace()[Math.min(e.getStackTrace().length - 1, 2)]; 104 Logging.warn(I18n.tr(String.format( 105 "Could not decode time from the timestamp `%s` (called by %s.%s:%d)", 106 timestamp, calledBy.getClassName(), calledBy.getMethodName(), calledBy.getLineNumber() 107 ), e)); 103 Logging.warn(I18n.tr(String.format("Could not decode time from the timestamp `%s` (called by %s.%s:%d)", 104 timestamp, calledBy.getClassName(), calledBy.getMethodName(), calledBy.getLineNumber()), e)); 108 105 } 109 106 } -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonImageDetectionDecoder.java
r36122 r36194 5 5 import java.awt.geom.Path2D; 6 6 7 import org.openstreetmap.josm.plugins.streetside.model.ImageDetection; 8 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3; 9 import org.openstreetmap.josm.tools.Logging; 10 7 11 import jakarta.json.JsonArray; 8 12 import jakarta.json.JsonNumber; 9 13 import jakarta.json.JsonObject; 10 14 import jakarta.json.JsonValue; 11 12 import org.openstreetmap.josm.plugins.streetside.model.ImageDetection;13 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3;14 import org.openstreetmap.josm.tools.Logging;15 15 16 16 /** … … 38 38 final Double score = scoreVal instanceof JsonNumber ? ((JsonNumber) scoreVal).doubleValue() : null; 39 39 final Shape shape = decodeShape(((JsonObject) properties).get("shape")); 40 if (shape instanceof Path2D && imageKey != null && key != null && score != null && packag != null && value != null) { 40 if (shape instanceof Path2D && imageKey != null && key != null && score != null && packag != null 41 && value != null) { 41 42 return new ImageDetection((Path2D) shape, imageKey, key, score, packag, value); 42 43 } … … 48 49 if (json instanceof JsonObject) { 49 50 if (!"Polygon".equals(((JsonObject) json).getString("type", null))) { 50 Logging.warn( 51 String.format("Image detections using shapes with type=%s are currently not supported!", 52 ((JsonObject) json).getString("type", "‹no type set›")) 53 ); 51 Logging.warn(String.format("Image detections using shapes with type=%s are currently not supported!", 52 ((JsonObject) json).getString("type", "‹no type set›"))); 54 53 } else { 55 54 final JsonValue coordinates = ((JsonObject) json).get("coordinates"); … … 64 63 /** 65 64 * Decodes a polygon (may be a multipolygon) from JSON 65 * 66 66 * @param json the json array to decode, must not be <code>null</code> 67 67 * @return the decoded polygon as {@link Path2D.Double} … … 83 83 /** 84 84 * Decodes a simple polygon (consisting of only one continuous path) from JSON 85 * 85 86 * @param json the json array to decode, must not be <code>null</code> 86 87 * @return the decoded polygon as {@link Path2D.Double} -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonSequencesDecoder.java
r36122 r36194 5 5 import java.util.function.Function; 6 6 7 import org.openstreetmap.josm.data.coor.LatLon; 8 import org.openstreetmap.josm.plugins.streetside.StreetsideImage; 9 import org.openstreetmap.josm.plugins.streetside.StreetsideSequence; 10 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3; 11 7 12 import jakarta.json.JsonArray; 8 13 import jakarta.json.JsonNumber; … … 10 15 import jakarta.json.JsonString; 11 16 import jakarta.json.JsonValue; 12 13 import org.openstreetmap.josm.data.coor.LatLon;14 import org.openstreetmap.josm.plugins.streetside.StreetsideImage;15 import org.openstreetmap.josm.plugins.streetside.StreetsideSequence;16 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3;17 17 18 18 /** … … 27 27 /** 28 28 * Parses a given {@link JsonObject} as a GeoJSON Feature into a {@link StreetsideSequence}. 29 * 29 30 * @param json the {@link JsonObject} to be parsed 30 31 * @return a {@link StreetsideSequence} that is parsed from the given {@link JsonObject}. If mandatory information is 31 * 32 * 32 * missing from the JSON or it's not meeting the expecting format in another way, <code>null</code> will be 33 * returned. 33 34 */ 34 35 public static StreetsideSequence decodeSequence(final JsonObject json) { … … 39 40 final JsonObject properties = json.getJsonObject("properties"); 40 41 final Long ca = properties == null ? null : JsonDecoder.decodeTimestamp(properties.getString("cd", null)); 41 if (properties != null && properties.getString("id", null) != null && properties.getString("user_key", null) != null && ca != null) { 42 if (properties != null && properties.getString("id", null) != null 43 && properties.getString("user_key", null) != null && ca != null) { 42 44 result = new StreetsideSequence(properties.getString("id", null), ca); 43 45 44 final Double[] hes = decodeCoordinateProperty( 45 properties, 46 "hes", 47 val -> val instanceof JsonNumber ? ((JsonNumber) val).doubleValue() : null, 48 Double.class 49 ); 50 final String[] imageIds = decodeCoordinateProperty( 51 properties, 52 "image_ids", 53 val -> val instanceof JsonString ? ((JsonString) val).getString() : null, 54 String.class 55 ); 46 final Double[] hes = decodeCoordinateProperty(properties, "hes", 47 val -> val instanceof JsonNumber ? ((JsonNumber) val).doubleValue() : null, Double.class); 48 final String[] imageIds = decodeCoordinateProperty(properties, "image_ids", 49 val -> val instanceof JsonString ? ((JsonString) val).getString() : null, String.class); 56 50 final LatLon[] geometry = decodeLatLons(json.getJsonObject("geometry")); 57 51 final int sequenceLength = Math.min(Math.min(hes.length, imageIds.length), geometry.length); … … 77 71 * @param clazz the desired type that the elements of the resulting array should have 78 72 * @return the supplied array converted from {@link JsonArray} to a java array of the supplied type, converted using 79 * 73 * the supplied function. Never <code>null</code>, in case of array==null, an array of length 0 is returned. 80 74 */ 81 75 @SuppressWarnings("unchecked") 82 private static <T> T[] decodeJsonArray(final JsonArray array, final Function<JsonValue, T> decodeValueFunction, final Class<T> clazz) { 76 private static <T> T[] decodeJsonArray(final JsonArray array, final Function<JsonValue, T> decodeValueFunction, 77 final Class<T> clazz) { 83 78 final T[] result; 84 79 if (array == null) { 85 result = 80 result = (T[]) Array.newInstance(clazz, 0); 86 81 } else { 87 82 result = (T[]) Array.newInstance(clazz, array.size()); … … 103 98 * @param key the key, which identifies the desired array inside the `coordinateProperties` object to be converted 104 99 * @param decodeValueFunction a function that converts the {@link JsonValue}s in the JSON array to java objects of the 105 * 100 * desired type 106 101 * @param clazz the {@link Class} object of the desired type, that the entries of the resulting array should have 107 102 * @return the resulting array, when converting the desired entry of the `coordinateProperties`. 108 * 109 * 103 * Never <code>null</code>. If no `coordinateProperties` are set, or if the desired key is not set or is not 104 * an array, then an empty array of the desired type is returned. 110 105 */ 111 106 @SuppressWarnings("unchecked") 112 private static <T> T[] decodeCoordinateProperty( 113 final JsonObject json, final String key, final Function<JsonValue, T> decodeValueFunction, final Class<T> clazz 114 ) { 107 private static <T> T[] decodeCoordinateProperty(final JsonObject json, final String key, 108 final Function<JsonValue, T> decodeValueFunction, final Class<T> clazz) { 115 109 final JsonValue coordinateProperties = json == null ? null : json.get("coordinateProperties"); 116 110 if (coordinateProperties instanceof JsonObject) { -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonStreetsideDecoder.java
r36122 r36194 23 23 * of the desired Java objects. The method, which converts the GeoJSON features into Java objects 24 24 * is given as a parameter to this method. 25 * @param <T> feature type 26 * @param json the {@link JsonObject} to be parsed 25 * 26 * @param <T> feature type 27 * @param json the {@link JsonObject} to be parsed 27 28 * @param featureDecoder feature decoder which transforms JSON objects to Java objects 28 29 * @return a {@link Collection} which is parsed from the given {@link JsonObject}, which contains GeoJSON. 29 * 30 * 30 * Currently a {@link HashSet} is used, but please don't rely on it, this could change at any time without 31 * prior notice. The return value will not be <code>null</code>. 31 32 */ 32 public static <T> Collection<T> decodeFeatureCollection(final JsonObject json, Function<JsonObject, T> featureDecoder) { 33 public static <T> Collection<T> decodeFeatureCollection(final JsonObject json, 34 Function<JsonObject, T> featureDecoder) { 33 35 return JsonDecoder.decodeFeatureCollection(json, featureDecoder); 34 36 } … … 37 39 * Decodes a {@link JsonArray} of exactly size 2 to a {@link LatLon} instance. 38 40 * The first value in the {@link JsonArray} is treated as longitude, the second one as latitude. 41 * 39 42 * @param json the {@link JsonArray} containing the two numbers 40 43 * @return the decoded {@link LatLon} instance, or <code>null</code> if the parameter is 41 * 44 * not a {@link JsonArray} of exactly size 2 containing two {@link JsonNumber}s. 42 45 */ 43 46 static LatLon decodeLatLon(final JsonArray json) { … … 48 51 * Decodes a timestamp formatted as a {@link String} to the equivalent UNIX epoch timestamp 49 52 * (number of milliseconds since 1970-01-01T00:00:00.000+0000). 53 * 50 54 * @param timestamp the timestamp formatted according to the format <code>yyyy-MM-dd'T'HH:mm:ss.SSSX</code> 51 55 * @return the point in time as a {@link Long} value representing the UNIX epoch time, or <code>null</code> if the 52 * 53 * 56 * parameter does not match the required format (this also triggers a warning via 57 * {@link Logging}, or the parameter is <code>null</code>). 54 58 */ 55 59 static Long decodeTimestamp(final String timestamp) { -
applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonStreetsideSequencesDecoder.java
r36122 r36194 5 5 import java.util.function.Function; 6 6 7 import org.openstreetmap.josm.data.coor.LatLon; 8 import org.openstreetmap.josm.plugins.streetside.StreetsideImage; 9 import org.openstreetmap.josm.plugins.streetside.StreetsideSequence; 10 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3; 11 7 12 import jakarta.json.JsonArray; 8 13 import jakarta.json.JsonNumber; … … 10 15 import jakarta.json.JsonString; 11 16 import jakarta.json.JsonValue; 12 13 import org.openstreetmap.josm.data.coor.LatLon;14 import org.openstreetmap.josm.plugins.streetside.StreetsideImage;15 import org.openstreetmap.josm.plugins.streetside.StreetsideSequence;16 import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3;17 17 18 18 /** … … 27 27 /** 28 28 * Parses a given {@link JsonObject} as a GeoJSON Feature into a {@link StreetsideSequence}. 29 * 29 30 * @param json the {@link JsonObject} to be parsed 30 31 * @return a {@link StreetsideSequence} that is parsed from the given {@link JsonObject}. If mandatory information is 31 * 32 * 32 * missing from the JSON or it's not meeting the expecting format in another way, <code>null</code> will be 33 * returned. 33 34 */ 34 35 public static StreetsideSequence decodeSequence(final JsonObject json) { … … 42 43 result = new StreetsideSequence(properties.getString("id", null), ca); 43 44 44 final Double[] cas = decodeCoordinateProperty( 45 properties, 46 "hes", 47 val -> val instanceof JsonNumber ? ((JsonNumber) val).doubleValue() : null, 48 Double.class 49 ); 50 final String[] imageIds = decodeCoordinateProperty( 51 properties, 52 "image_ids", 53 val -> val instanceof JsonString ? ((JsonString) val).getString() : null, 54 String.class 55 ); 45 final Double[] cas = decodeCoordinateProperty(properties, "hes", 46 val -> val instanceof JsonNumber ? ((JsonNumber) val).doubleValue() : null, Double.class); 47 final String[] imageIds = decodeCoordinateProperty(properties, "image_ids", 48 val -> val instanceof JsonString ? ((JsonString) val).getString() : null, String.class); 56 49 final LatLon[] geometry = decodeLatLons(json.getJsonObject("geometry")); 57 50 final int sequenceLength = Math.min(Math.min(cas.length, imageIds.length), geometry.length); … … 73 66 * @param image the {@link StreetsideImage} to be parsed 74 67 * @return a {@link StreetsideSequence} that is parsed from the given {@link JsonObject}. If mandatory information is 75 * 76 * 68 * missing from the JSON or it's not meeting the expecting format in another way, <code>null</code> will be 69 * returned. 77 70 */ 78 71 public static StreetsideImage decodeBubbleData(final StreetsideImage image) { … … 82 75 // Declare and instantiate new Streetside object to ensure proper setting of superclass attributes 83 76 StreetsideImage result = null; 84 if (image.getId() != null) {77 if (image.getId() != null) { 85 78 result = new StreetsideImage(image.getId(), new LatLon(image.getLa(), image.getLo()), 0.0); 86 79 result.setAl(image.getAl()); … … 103 96 * @param json the {@link JsonObject} to be parsed 104 97 * @return a {@link StreetsideSequence} that is parsed from the given {@link JsonObject}. If mandatory information is 105 * 106 * 98 * missing from the JSON or it's not meeting the expecting format in another way, <code>null</code> will be 99 * returned. 107 100 */ 108 101 public static StreetsideSequence decodeStreetsideSequence(final JsonObject json) { … … 112 105 StreetsideSequence result = null; 113 106 114 if (json.getString("id", null) != null && json.getString("la", null) != null && json.getString("lo", null) != null) { 115 result = new StreetsideSequence(json.getString("id", null), 116 json.getJsonNumber("la").doubleValue(), json.getJsonNumber("lo").doubleValue(), json.getJsonNumber("cd").longValue()); 107 if (json.getString("id", null) != null && json.getString("la", null) != null 108 && json.getString("lo", null) != null) { 109 result = new StreetsideSequence(json.getString("id", null), json.getJsonNumber("la").doubleValue(), 110 json.getJsonNumber("lo").doubleValue(), json.getJsonNumber("cd").longValue()); 117 111 } 118 112 … … 128 122 * @param clazz the desired type that the elements of the resulting array should have 129 123 * @return the supplied array converted from {@link JsonArray} to a java array of the supplied type, converted using 130 * 124 * the supplied function. Never <code>null</code>, in case of array==null, an array of length 0 is returned. 131 125 */ 132 126 @SuppressWarnings("unchecked") 133 private static <T> T[] decodeJsonArray(final JsonArray array, final Function<JsonValue, T> decodeValueFunction, final Class<T> clazz) { 127 private static <T> T[] decodeJsonArray(final JsonArray array, final Function<JsonValue, T> decodeValueFunction, 128 final Class<T> clazz) { 134 129 final T[] result; 135 130 if (array == null) { 136 result = 131 result = (T[]) Array.newInstance(clazz, 0); 137 132 } else { 138 133 result = (T[]) Array.newInstance(clazz, array.size()); … … 154 149 * @param key the key, which identifies the desired array inside the `coordinateProperties` object to be converted 155 150 * @param decodeValueFunction a function that converts the {@link JsonValue}s in the JSON array to java objects of the 156 * 151 * desired type 157 152 * @param clazz the {@link Class} object of the desired type, that the entries of the resulting array should have 158 153 * @return the resulting array, when converting the desired entry of the `coordinateProperties`. 159 * 160 * 154 * Never <code>null</code>. If no `coordinateProperties` are set, or if the desired key is not set or is not 155 * an array, then an empty array of the desired type is returned. 161 156 */ 162 157 @SuppressWarnings("unchecked") 163 private static <T> T[] decodeCoordinateProperty( 164 final JsonObject json, final String key, final Function<JsonValue, T> decodeValueFunction, final Class<T> clazz 165 ) { 158 private static <T> T[] decodeCoordinateProperty(final JsonObject json, final String key, 159 final Function<JsonValue, T> decodeValueFunction, final Class<T> clazz) { 166 160 final JsonValue coordinateProperties = json == null ? null : json.get("coordinateProperties"); 167 161 if (coordinateProperties instanceof JsonObject) {
Note:
See TracChangeset
for help on using the changeset viewer.