Changeset 14628 in josm for trunk/src/org
- Timestamp:
- 2019-01-03T20:06:44+01:00 (6 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/AutoScaleAction.java
r14397 r14628 292 292 mapView.zoomNext(); 293 293 break; 294 default: 295 BoundingXYVisitor bbox = getBoundingBox(); 296 if (bbox != null && bbox.getBounds() != null) { 297 mapView.zoomTo(bbox); 298 } 299 } 300 } 301 putValue("active", Boolean.TRUE); 294 case PROBLEM: 295 modeProblem(new ValidatorBoundingXYVisitor()); 296 break; 297 case DATA: 298 modeData(new BoundingXYVisitor()); 299 break; 300 case LAYER: 301 modeLayer(new BoundingXYVisitor()); 302 break; 303 case SELECTION: 304 case CONFLICT: 305 modeSelectionOrConflict(new BoundingXYVisitor()); 306 break; 307 case DOWNLOAD: 308 modeDownload(new BoundingXYVisitor()); 309 break; 310 } 311 putValue("active", Boolean.TRUE); 312 } 302 313 } 303 314 … … 328 339 } 329 340 330 private BoundingXYVisitor getBoundingBox() { 331 switch (mode) { 332 case PROBLEM: 333 return modeProblem(new ValidatorBoundingXYVisitor()); 334 case DATA: 335 return modeData(new BoundingXYVisitor()); 336 case LAYER: 337 return modeLayer(new BoundingXYVisitor()); 338 case SELECTION: 339 case CONFLICT: 340 return modeSelectionOrConflict(new BoundingXYVisitor()); 341 case DOWNLOAD: 342 return modeDownload(new BoundingXYVisitor()); 343 default: 344 return new BoundingXYVisitor(); 345 } 346 } 347 348 private static BoundingXYVisitor modeProblem(ValidatorBoundingXYVisitor v) { 341 private static void modeProblem(ValidatorBoundingXYVisitor v) { 349 342 TestError error = MainApplication.getMap().validatorDialog.getSelectedError(); 350 343 if (error == null) 351 return null;344 return; 352 345 v.visit(error); 353 346 if (v.getBounds() == null) 354 return null; 355 v.enlargeBoundingBox(Config.getPref().getDouble("validator.zoom-enlarge-bbox", 0.0002)); 356 return v; 357 } 358 359 private static BoundingXYVisitor modeData(BoundingXYVisitor v) { 347 return; 348 MainApplication.getMap().mapView.zoomTo(v); 349 } 350 351 private static void modeData(BoundingXYVisitor v) { 360 352 for (Layer l : MainApplication.getLayerManager().getLayers()) { 361 353 l.visitBoundingBox(v); 362 354 } 363 return v;364 } 365 366 private BoundingXYVisitormodeLayer(BoundingXYVisitor v) {355 MainApplication.getMap().mapView.zoomTo(v); 356 } 357 358 private void modeLayer(BoundingXYVisitor v) { 367 359 // try to zoom to the first selected layer 368 360 Layer l = getFirstSelectedLayer(); 369 361 if (l == null) 370 return null;362 return; 371 363 l.visitBoundingBox(v); 372 return v;373 } 374 375 private BoundingXYVisitormodeSelectionOrConflict(BoundingXYVisitor v) {364 MainApplication.getMap().mapView.zoomTo(v); 365 } 366 367 private void modeSelectionOrConflict(BoundingXYVisitor v) { 376 368 Collection<IPrimitive> sel = new HashSet<>(); 377 369 if (AutoScaleMode.SELECTION == mode) { … … 395 387 tr("Information"), 396 388 JOptionPane.INFORMATION_MESSAGE); 397 return null;389 return; 398 390 } 399 391 for (IPrimitive osm : sel) { 400 392 osm.accept(v); 401 393 } 402 403 // Increase the bounding box by up to 100% to give more context. 404 v.enlargeBoundingBoxLogarithmically(100); 405 // Make the bounding box at least 100 meter wide to 406 // ensure reasonable zoom level when zooming onto single nodes. 407 v.enlargeToMinSize(Config.getPref().getDouble("zoom_to_selection_min_size_in_meter", 100)); 408 return v; 409 } 410 411 private BoundingXYVisitor modeDownload(BoundingXYVisitor v) { 394 if (v.getBounds() == null) { 395 return; 396 } 397 398 // Do not zoom if the current scale covers the selection, #16706 399 final MapView mapView = MainApplication.getMap().mapView; 400 final double mapScale = mapView.getScale(); 401 final double minScale = v.getBounds().getScale(mapView.getWidth(), mapView.getHeight()); 402 v.enlargeBoundingBoxLogarithmically(); 403 final double maxScale = v.getBounds().getScale(mapView.getWidth(), mapView.getHeight()); 404 if (minScale <= mapScale && mapScale < maxScale) { 405 mapView.zoomTo(v.getBounds().getCenter()); 406 } else { 407 mapView.zoomTo(v); 408 } 409 } 410 411 private void modeDownload(BoundingXYVisitor v) { 412 412 if (lastZoomTime > 0 && 413 413 System.currentTimeMillis() - lastZoomTime > Config.getPref().getLong("zoom.bounds.reset.time", TimeUnit.SECONDS.toMillis(10))) { … … 438 438 } 439 439 } 440 return v;440 MainApplication.getMap().mapView.zoomTo(v); 441 441 } 442 442 -
trunk/src/org/openstreetmap/josm/data/ProjectionBounds.java
r12818 r14628 192 192 return !Utils.equalsEpsilon(minEast, maxEast) || !Utils.equalsEpsilon(minNorth, maxNorth); 193 193 } 194 195 /** 196 * Computes the scale of this bounds with respect to the given width/height. 197 * @param width the width 198 * @param height the height 199 * @return the computed scale 200 */ 201 public double getScale(final int width, final int height) { 202 // -20 to leave some border 203 int w = width - 20; 204 if (w < 20) { 205 w = 20; 206 } 207 int h = height - 20; 208 if (h < 20) { 209 h = 20; 210 } 211 212 double scaleX = getDeltaEast() / w; 213 double scaleY = getDeltaNorth() / h; 214 return Math.max(scaleX, scaleY); 215 } 216 217 private double getDeltaNorth() { 218 return maxNorth - minNorth; 219 } 220 221 private double getDeltaEast() { 222 return maxEast - minEast; 223 } 194 224 } -
trunk/src/org/openstreetmap/josm/data/osm/visitor/BoundingXYVisitor.java
r14379 r14628 3 3 4 4 import java.util.Collection; 5 import java.util.function.DoubleUnaryOperator; 5 6 6 7 import org.openstreetmap.josm.data.Bounds; … … 19 20 import org.openstreetmap.josm.data.osm.Way; 20 21 import org.openstreetmap.josm.data.projection.ProjectionRegistry; 21 import org.openstreetmap.josm.gui.MainApplication;22 import org.openstreetmap.josm.gui.MapFrame;23 22 import org.openstreetmap.josm.spi.preferences.Config; 24 23 … … 141 140 142 141 /** 143 * Enlarges the calculated bounding box by 0.00 2degrees.142 * Enlarges the calculated bounding box by 0.001 degrees. 144 143 * If the bounding box has not been set (<code>min</code> or <code>max</code> 145 144 * equal <code>null</code>) this method does not do anything. 146 145 */ 147 146 public void enlargeBoundingBox() { 148 enlargeBoundingBox(Config.getPref().getDouble("edit.zoom-enlarge-bbox", 0.002)); 147 final double enlarge = Config.getPref().getDouble("edit.zoom-enlarge-bbox", 0.001); 148 enlargeBoundingBox(enlarge, enlarge); 149 149 } 150 150 … … 154 154 * equal <code>null</code>) this method does not do anything. 155 155 * 156 * @param enlargeDegree number of degrees to enlarge on each side 157 */ 158 public void enlargeBoundingBox(double enlargeDegree) { 156 * @param enlargeDegreeX number of degrees to enlarge on each side along X 157 * @param enlargeDegreeY number of degrees to enlarge on each side along Y 158 */ 159 public void enlargeBoundingBox(double enlargeDegreeX, double enlargeDegreeY) { 159 160 if (bounds == null) 160 161 return; … … 162 163 LatLon maxLatlon = ProjectionRegistry.getProjection().eastNorth2latlon(bounds.getMax()); 163 164 bounds = new ProjectionBounds(new LatLon( 164 Math.max(-90, minLatlon.lat() - enlargeDegree ),165 Math.max(-180, minLatlon.lon() - enlargeDegree )).getEastNorth(ProjectionRegistry.getProjection()),165 Math.max(-90, minLatlon.lat() - enlargeDegreeY), 166 Math.max(-180, minLatlon.lon() - enlargeDegreeX)).getEastNorth(ProjectionRegistry.getProjection()), 166 167 new LatLon( 167 Math.min(90, maxLatlon.lat() + enlargeDegree ),168 Math.min(180, maxLatlon.lon() + enlargeDegree )).getEastNorth(ProjectionRegistry.getProjection()));169 } 170 171 /** 172 * Enlarges the bounding box up to <code>maxEnlargePercent</code>, depending on168 Math.min(90, maxLatlon.lat() + enlargeDegreeY), 169 Math.min(180, maxLatlon.lon() + enlargeDegreeX)).getEastNorth(ProjectionRegistry.getProjection())); 170 } 171 172 /** 173 * Enlarges the bounding box up to 0.001 degrees, depending on 173 174 * its size. If the bounding box is small, it will be enlarged more in relation 174 175 * to its beginning size. The larger the bounding box, the smaller the change, 175 * down to the minimum of 1% enlargement. 176 * 177 * Warning: if the bounding box only contains a single node, no expansion takes 178 * place because a node has no width/height. Use {@link #enlargeBoundingBox(double)} 179 * instead. 180 * 181 * Example: You specify enlargement to be up to 100%. 182 * 183 * Bounding box is a small house: enlargement will be 95–100%, i.e. 184 * making enough space so that the house fits twice on the screen in 185 * each direction. 186 * 187 * Bounding box is a large landuse, like a forest: Enlargement will 188 * be 1–10%, i.e. just add a little border around the landuse. 176 * down to 0.0 degrees. 189 177 * 190 178 * If the bounding box has not been set (<code>min</code> or <code>max</code> 191 179 * equal <code>null</code>) this method does not do anything. 192 * 193 * @param maxEnlargePercent maximum enlargement in percentage (100.0 for 100%) 194 */ 195 public void enlargeBoundingBoxLogarithmically(double maxEnlargePercent) { 180 */ 181 public void enlargeBoundingBoxLogarithmically() { 196 182 if (bounds == null) 197 183 return; 198 199 double diffEast = bounds.getMax().east() - bounds.getMin().east(); 200 double diffNorth = bounds.getMax().north() - bounds.getMin().north(); 201 202 double enlargeEast = Math.min(maxEnlargePercent - 10*Math.log(diffEast), 1)/100; 203 double enlargeNorth = Math.min(maxEnlargePercent - 10*Math.log(diffNorth), 1)/100; 204 205 visit(bounds.getMin().add(-enlargeEast/2, -enlargeNorth/2)); 206 visit(bounds.getMax().add(+enlargeEast/2, +enlargeNorth/2)); 207 } 208 209 /** 210 * Specify a degree larger than 0 in order to make the bounding box at least 211 * the specified size in width and height. The value is ignored if the 212 * bounding box is already larger than the specified amount. 213 * 214 * If the bounding box has not been set (<code>min</code> or <code>max</code> 215 * equal <code>null</code>) this method does not do anything. 216 * 217 * If the bounding box contains objects and is to be enlarged, the objects 218 * will be centered within the new bounding box. 219 * 220 * @param size minimum width and height in meter 221 */ 222 public void enlargeToMinSize(double size) { 223 if (bounds == null) 224 return; 225 // convert size from meters to east/north units 226 MapFrame map = MainApplication.getMap(); 227 double enSize = size * map.mapView.getScale() / map.mapView.getDist100Pixel() * 100; 228 visit(bounds.getMin().add(-enSize/2, -enSize/2)); 229 visit(bounds.getMax().add(+enSize/2, +enSize/2)); 184 final LatLon min = ProjectionRegistry.getProjection().eastNorth2latlon(bounds.getMin()); 185 final LatLon max = ProjectionRegistry.getProjection().eastNorth2latlon(bounds.getMax()); 186 final double deltaLat = max.lat() - min.lat(); 187 final double deltaLon = max.lon() - min.lon(); 188 // [0.001, 0.1] degree -> [0.001, 0.0] degree enlargement 189 final DoubleUnaryOperator enlargement = deg -> deg < 0.001 190 ? 0.001 191 : deg < 0.1 192 ? 0.001 - deg / 100 193 : 0.0; 194 enlargeBoundingBox(enlargement.applyAsDouble(deltaLon), enlargement.applyAsDouble(deltaLat)); 230 195 } 231 196 -
trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java
r14402 r14628 790 790 */ 791 791 public void zoomTo(ProjectionBounds box) { 792 // -20 to leave some border 793 int w = getWidth()-20; 794 if (w < 20) { 795 w = 20; 796 } 797 int h = getHeight()-20; 798 if (h < 20) { 799 h = 20; 800 } 801 802 double scaleX = (box.maxEast-box.minEast)/w; 803 double scaleY = (box.maxNorth-box.minNorth)/h; 804 double newScale = Math.max(scaleX, scaleY); 805 792 double newScale = box.getScale(getWidth(), getHeight()); 806 793 newScale = scaleFloor(newScale); 807 794 zoomTo(box.getCenter(), newScale);
Note:
See TracChangeset
for help on using the changeset viewer.