Ticket #13303: patch-mapview-hatched-stay-in-place.patch
| File patch-mapview-hatched-stay-in-place.patch, 12.3 KB (added by , 10 years ago) |
|---|
-
src/org/openstreetmap/josm/data/Bounds.java
diff --git a/src/org/openstreetmap/josm/data/Bounds.java b/src/org/openstreetmap/josm/data/Bounds.java index 067a9c3..8ce17fd 100644
a b import java.awt.geom.Rectangle2D; 7 7 import java.text.DecimalFormat; 8 8 import java.text.MessageFormat; 9 9 import java.util.Objects; 10 import java.util.function.Consumer; 10 11 11 12 import org.openstreetmap.josm.data.coor.LatLon; 12 13 import org.openstreetmap.josm.data.osm.BBox; 14 import org.openstreetmap.josm.data.projection.Projection; 13 15 import org.openstreetmap.josm.tools.CheckParameterUtil; 14 16 15 17 /** … … public class Bounds { 398 400 * @return the bounding box to Rectangle2D.Double 399 401 */ 400 402 public Rectangle2D.Double asRect() { 401 double w = maxLon-minLon + (crosses180thMeridian() ? 360.0 : 0.0);403 double w = getWidth(); 402 404 return new Rectangle2D.Double(minLon, minLat, w, maxLat-minLat); 403 405 } 404 406 407 private double getWidth() { 408 return maxLon-minLon + (crosses180thMeridian() ? 360.0 : 0.0); 409 } 410 405 411 public double getArea() { 406 double w = maxLon-minLon + (crosses180thMeridian() ? 360.0 : 0.0);412 double w = getWidth(); 407 413 return w * (maxLat - minLat); 408 414 } 409 415 … … public class Bounds { 441 447 maxLon = LatLon.toIntervalLon(maxLon); 442 448 } 443 449 450 /** 451 * Visit points along the edge of this bounds instance. 452 * @param projection The projection that should be used to determine how often the edge should be split along a given corner. 453 * @param visitor A function to call for the points on the edge. 454 */ 455 public void visitEdge(Projection projection, Consumer<LatLon> visitor) { 456 double width = getWidth(); 457 double height = maxLat - minLat; 458 //TODO: Use projection to see if there is any need for doing this along each axis. 459 int splitX = Math.max((int) width / 10, 10); 460 int splitY = Math.max((int) height / 10, 10); 461 462 for (int step = 0; step < splitX; step++) { 463 visitor.accept(new LatLon(minLat, minLon + width * step / splitX)); 464 } 465 for (int step = 0; step < splitY; step++) { 466 visitor.accept(new LatLon(minLat + height * step / splitY, maxLon)); 467 } 468 for (int step = 0; step < splitX; step++) { 469 visitor.accept(new LatLon(maxLat, maxLon - width * step / splitX)); 470 } 471 for (int step = 0; step < splitY; step++) { 472 visitor.accept(new LatLon(maxLat - height * step / splitY, minLon)); 473 } 474 } 475 444 476 @Override 445 477 public int hashCode() { 446 478 return Objects.hash(minLat, minLon, maxLat, maxLon); -
src/org/openstreetmap/josm/data/osm/visitor/BoundingXYVisitor.java
diff --git a/src/org/openstreetmap/josm/data/osm/visitor/BoundingXYVisitor.java b/src/org/openstreetmap/josm/data/osm/visitor/BoundingXYVisitor.java index b8f290c..553e85b 100644
a b public class BoundingXYVisitor extends AbstractVisitor { 53 53 */ 54 54 public void visit(Bounds b) { 55 55 if (b != null) { 56 visit(b.getMin()); 57 visit(b.getMax()); 56 b.visitEdge(Main.getProjection(), this::visit); 58 57 } 59 58 } 60 59 -
src/org/openstreetmap/josm/gui/MapView.java
diff --git a/src/org/openstreetmap/josm/gui/MapView.java b/src/org/openstreetmap/josm/gui/MapView.java index 63e4bb4..cdb1da9 100644
a b import java.awt.event.MouseAdapter; 17 17 import java.awt.event.MouseEvent; 18 18 import java.awt.event.MouseMotionListener; 19 19 import java.awt.geom.Area; 20 import java.awt.geom.GeneralPath;21 20 import java.awt.image.BufferedImage; 22 21 import java.beans.PropertyChangeEvent; 23 22 import java.beans.PropertyChangeListener; … … import org.openstreetmap.josm.data.ProjectionBounds; 45 44 import org.openstreetmap.josm.data.SelectionChangedListener; 46 45 import org.openstreetmap.josm.data.ViewportData; 47 46 import org.openstreetmap.josm.data.coor.EastNorth; 48 import org.openstreetmap.josm.data.coor.LatLon;49 47 import org.openstreetmap.josm.data.imagery.ImageryInfo; 50 48 import org.openstreetmap.josm.data.osm.DataSet; 51 49 import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors; … … LayerManager.LayerChangeListener, MainLayerManager.ActiveLayerChangeListener { 973 971 private void drawWorldBorders(Graphics2D tempG) { 974 972 tempG.setColor(Color.WHITE); 975 973 Bounds b = getProjection().getWorldBoundsLatLon(); 976 double lat = b.getMinLat();977 double lon = b.getMinLon();978 979 Point p = getPoint(b.getMin());980 981 GeneralPath path = new GeneralPath();982 983 double d = 1.0;984 path.moveTo(p.x, p.y);985 double max = b.getMax().lat();986 for (; lat <= max; lat += d) {987 p = getPoint(new LatLon(lat >= max ? max : lat, lon));988 path.lineTo(p.x, p.y);989 }990 lat = max; max = b.getMax().lon();991 for (; lon <= max; lon += d) {992 p = getPoint(new LatLon(lat, lon >= max ? max : lon));993 path.lineTo(p.x, p.y);994 }995 lon = max; max = b.getMinLat();996 for (; lat >= max; lat -= d) {997 p = getPoint(new LatLon(lat <= max ? max : lat, lon));998 path.lineTo(p.x, p.y);999 }1000 lat = max; max = b.getMinLon();1001 for (; lon >= max; lon -= d) {1002 p = getPoint(new LatLon(lat, lon <= max ? max : lon));1003 path.lineTo(p.x, p.y);1004 }1005 974 1006 975 int w = getWidth(); 1007 976 int h = getHeight(); 1008 977 1009 978 // Work around OpenJDK having problems when drawing out of bounds 1010 final Area border = new Area(path);979 final Area border = getState().getArea(b).getViewArea(); 1011 980 // Make the viewport 1px larger in every direction to prevent an 1012 981 // additional 1px border when zooming in 1013 982 final Area viewport = new Area(new Rectangle(-1, -1, w + 2, h + 2)); -
src/org/openstreetmap/josm/gui/MapViewState.java
diff --git a/src/org/openstreetmap/josm/gui/MapViewState.java b/src/org/openstreetmap/josm/gui/MapViewState.java index f7dcd8d..fc08ac9 100644
a b import java.awt.Container; 5 5 import java.awt.Point; 6 6 import java.awt.Rectangle; 7 7 import java.awt.geom.AffineTransform; 8 import java.awt.geom.Area; 9 import java.awt.geom.Path2D; 8 10 import java.awt.geom.Point2D; 9 11 import java.awt.geom.Point2D.Double; 10 12 import java.awt.geom.Rectangle2D; … … public final class MapViewState { 213 215 topLeft.north() / scale); 214 216 } 215 217 218 public LatLonRectangle getArea(Bounds bounds) { 219 return new LatLonRectangle(bounds); 220 } 221 216 222 /** 217 223 * Creates a new state that is the same as the current state except for that it is using a new center. 218 224 * @param newCenter The new center coordinate. … … public final class MapViewState { 490 496 } 491 497 } 492 498 499 /** 500 * This is a rectangle in lat/lon space. 501 * @author Michael Zangl 502 * @since xxx 503 */ 504 public class LatLonRectangle { 505 506 private Bounds bounds; 507 508 LatLonRectangle(Bounds bounds) { 509 this.bounds = new Bounds(bounds); 510 } 511 512 /** 513 * Gets the approximate area this shape covers in view space. 514 * @return The area in view space 515 */ 516 public Area getViewArea() { 517 Path2D area = new Path2D.Double(); 518 bounds.visitEdge(getProjection(), latlon -> { 519 MapViewPoint point = getPointFor(latlon); 520 if (area.getCurrentPoint() == null) { 521 area.moveTo(point.getInViewX(), point.getInViewY()); 522 } else { 523 area.lineTo(point.getInViewX(), point.getInViewY()); 524 } 525 }); 526 area.closePath(); 527 return new Area(area); 528 } 529 } 530 493 531 } -
src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
diff --git a/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java b/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java index 7bdfd1a..cef09f8 100644
a b import java.awt.Composite; 12 12 import java.awt.Graphics2D; 13 13 import java.awt.GraphicsEnvironment; 14 14 import java.awt.GridBagLayout; 15 import java.awt.Point;16 15 import java.awt.Rectangle; 17 16 import java.awt.TexturePaint; 18 17 import java.awt.event.ActionEvent; 19 18 import java.awt.geom.Area; 19 import java.awt.geom.Rectangle2D; 20 20 import java.awt.image.BufferedImage; 21 21 import java.io.File; 22 22 import java.util.ArrayList; … … import org.openstreetmap.josm.data.ProjectionBounds; 51 51 import org.openstreetmap.josm.data.SelectionChangedListener; 52 52 import org.openstreetmap.josm.data.conflict.Conflict; 53 53 import org.openstreetmap.josm.data.conflict.ConflictCollection; 54 import org.openstreetmap.josm.data.coor.EastNorth; 54 55 import org.openstreetmap.josm.data.coor.LatLon; 55 56 import org.openstreetmap.josm.data.gpx.GpxConstants; 56 57 import org.openstreetmap.josm.data.gpx.GpxData; … … import org.openstreetmap.josm.data.projection.Projection; 81 82 import org.openstreetmap.josm.data.validation.TestError; 82 83 import org.openstreetmap.josm.gui.ExtendedDialog; 83 84 import org.openstreetmap.josm.gui.MapView; 85 import org.openstreetmap.josm.gui.MapViewState.MapViewPoint; 84 86 import org.openstreetmap.josm.gui.dialogs.LayerListDialog; 85 87 import org.openstreetmap.josm.gui.dialogs.LayerListPopup; 86 88 import org.openstreetmap.josm.gui.io.AbstractIOTask; … … import org.openstreetmap.josm.tools.date.DateUtils; 110 112 * @since 17 111 113 */ 112 114 public class OsmDataLayer extends AbstractModifiableLayer implements Listener, SelectionChangedListener { 115 private static final int HATCHED_SIZE = 15; 113 116 /** Property used to know if this layer has to be saved on disk */ 114 117 public static final String REQUIRES_SAVE_TO_DISK_PROP = OsmDataLayer.class.getName() + ".requiresSaveToDisk"; 115 118 /** Property used to know if this layer has to be uploaded */ … … public class OsmDataLayer extends AbstractModifiableLayer implements Listener, S 303 306 private final ConflictCollection conflicts; 304 307 305 308 /** 306 * a painttexture for non-downloaded area309 * a texture for non-downloaded area 307 310 */ 308 private static volatile TexturePainthatched;311 private static volatile BufferedImage hatched; 309 312 310 313 static { 311 314 createHatchTexture(); … … public class OsmDataLayer extends AbstractModifiableLayer implements Listener, S 331 334 * Initialize the hatch pattern used to paint the non-downloaded area 332 335 */ 333 336 public static void createHatchTexture() { 334 BufferedImage bi = new BufferedImage( 15, 15, BufferedImage.TYPE_INT_ARGB);337 BufferedImage bi = new BufferedImage(HATCHED_SIZE, HATCHED_SIZE, BufferedImage.TYPE_INT_ARGB); 335 338 Graphics2D big = bi.createGraphics(); 336 339 big.setColor(getBackgroundColor()); 337 340 Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f); 338 341 big.setComposite(comp); 339 big.fillRect(0, 0, 15, 15);342 big.fillRect(0, 0, HATCHED_SIZE, HATCHED_SIZE); 340 343 big.setColor(getOutsideColor()); 341 344 big.drawLine(-1, 6, 6, -1); 342 345 big.drawLine(4, 16, 16, 4); 343 Rectangle r = new Rectangle(0, 0, 15, 15); 344 hatched = new TexturePaint(bi, r); 346 hatched = bi; 345 347 } 346 348 347 349 /** … … public class OsmDataLayer extends AbstractModifiableLayer implements Listener, S 407 409 if (bounds.isCollapsed()) { 408 410 continue; 409 411 } 410 Point p1 = mv.getPoint(bounds.getMin()); 411 Point p2 = mv.getPoint(bounds.getMax()); 412 Rectangle r = new Rectangle(Math.min(p1.x, p2.x), Math.min(p1.y, p2.y), Math.abs(p2.x-p1.x), Math.abs(p2.y-p1.y)); 413 a.subtract(new Area(r)); 412 413 a.subtract(mv.getState().getArea(bounds).getViewArea()); 414 414 } 415 415 416 416 // paint remainder 417 g.setPaint(hatched); 417 MapViewPoint anchor = mv.getState().getPointFor(new EastNorth(0, 0)); 418 Rectangle2D anchorRect = new Rectangle2D.Double(anchor.getInView().getX() % HATCHED_SIZE, 419 anchor.getInView().getY() % HATCHED_SIZE, HATCHED_SIZE, HATCHED_SIZE); 420 g.setPaint(new TexturePaint(hatched, anchorRect)); 418 421 g.fill(a); 419 422 } 420 423
