Changeset 19220 in josm


Ignore:
Timestamp:
2024-09-11T21:33:23+02:00 (2 months ago)
Author:
taylor.smock
Message:

See #11487: Have josm render data to tiles

Start adding basic rendering tests for tiled rendering.
Right now, the test only looks at a point in the center of the tile; there seems
to be some positioning/stretching issues at the edges that I need to debug and
fix.

Location:
trunk
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledTiledMapRenderer.java

    r19180 r19220  
    88import java.awt.Font;
    99import java.awt.Graphics2D;
     10import java.awt.GraphicsConfiguration;
    1011import java.awt.Image;
    1112import java.awt.Point;
     
    1314import java.awt.Transparency;
    1415import java.awt.event.MouseEvent;
    15 import java.awt.geom.AffineTransform;
    1616import java.awt.image.BufferedImage;
    1717import java.util.ArrayList;
     
    2222import java.util.Map;
    2323import java.util.Objects;
    24 import java.util.Optional;
    2524import java.util.Set;
    2625import java.util.concurrent.Executor;
     26import java.util.concurrent.ExecutorService;
    2727import java.util.function.Consumer;
    2828import java.util.stream.Collectors;
     
    5252    private int zoom;
    5353    private Consumer<TileZXY> notifier;
     54    private final ExecutorService worker;
    5455
    5556    /**
     
    6566    public StyledTiledMapRenderer(Graphics2D g, NavigatableComponent nc, boolean isInactiveMode) {
    6667        super(g, nc, isInactiveMode);
     68        this.worker = MainApplication.worker;
    6769    }
    6870
     
    7476            return;
    7577        }
    76         final Executor worker = MainApplication.worker;
     78        final Executor worker = this.worker;
    7779        final BufferedImage tempImage;
    7880        final Graphics2D tempG2d;
    7981        // I'd like to avoid two image copies, but there are some issues using the original g2d object
    80         tempImage = nc.getGraphicsConfiguration().createCompatibleImage(this.nc.getWidth(), this.nc.getHeight(), Transparency.TRANSLUCENT);
     82        tempImage = createCompatibleImage(nc, this.nc.getWidth(), this.nc.getHeight());
    8183        tempG2d = tempImage.createGraphics();
    8284        tempG2d.setComposite(AlphaComposite.DstAtop); // Avoid tile lines in large areas
     
    9496            final Point min = this.nc.getPoint(box2.getMin());
    9597            final Point max = this.nc.getPoint(box2.getMax());
    96             tileSize = max.x - min.x + BUFFER_PIXELS;
     98            tileSize = max.x - min.x;
    9799        }
    98100
     
    151153                    painted++;
    152154                }
    153                 // There seems to be an off-by-one error somewhere.
    154                 tempG2d.drawImage(tileImage, point.x + 1, point.y + 1, null, null);
     155                // There seems to be an off-by-one error somewhere. Seems to be tied to sign of lat/lon
     156                final int offset = (tile.lat() > 0 ? 1 : 0) + (tile.lon() >= 0 ? 1 : 0);
     157                tempG2d.drawImage(tileImage, point.x + 1, point.y + offset, null, null);
    155158            } else {
    156159                Logging.trace("StyledMapRenderer did not paint tile {1}", tile);
     
    250253
    251254        temporaryView.zoomTo(bounds.getCenter().getEastNorth(ProjectionRegistry.getProjection()), mapState.getScale());
    252         BufferedImage bufferedImage = Optional.ofNullable(nc.getGraphicsConfiguration())
    253                 .map(gc -> gc.createCompatibleImage(tileSize * xCount + xCount, tileSize * yCount + yCount, Transparency.TRANSLUCENT))
    254                 .orElseGet(() -> new BufferedImage(tileSize * xCount + xCount, tileSize * yCount + yCount, BufferedImage.TYPE_INT_ARGB));
     255        BufferedImage bufferedImage = createCompatibleImage(nc, width, height);
    255256        Graphics2D g2d = bufferedImage.createGraphics();
    256257        try {
    257258            g2d.setRenderingHints(Map.of(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
    258             g2d.setTransform(AffineTransform.getTranslateInstance(-BUFFER_TILES * (double) tileSize, -BUFFER_TILES * (double) tileSize));
    259259            final AbstractMapRenderer tilePainter = MapRendererFactory.getInstance().createActiveRenderer(g2d, temporaryView, false);
    260260            tilePainter.render(data, true, bounds);
     
    262262            g2d.dispose();
    263263        }
    264         return bufferedImage;
     264        final int bufferPixels = BUFFER_TILES * tileSize;
     265        return bufferedImage.getSubimage(bufferPixels, bufferPixels,
     266                width - 2 * bufferPixels + BUFFER_PIXELS, height - 2 * bufferPixels + BUFFER_PIXELS);
     267    }
     268
     269    private static BufferedImage createCompatibleImage(NavigatableComponent nc, int width, int height) {
     270        final GraphicsConfiguration gc = nc.getGraphicsConfiguration();
     271        if (gc == null) {
     272            return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
     273        }
     274        return gc.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
    265275    }
    266276
     
    319329                        for (TileLoader loader : tileCollection) {
    320330                            final TileZXY txy = loader.tile;
    321                             final int x = (txy.x() - minX) * (tileSize - BUFFER_PIXELS) + BUFFER_PIXELS / 2;
    322                             final int y = (txy.y() - minY) * (tileSize - BUFFER_PIXELS) + BUFFER_PIXELS / 2;
    323                             final int wh = tileSize - BUFFER_PIXELS / 2;
    324 
    325                             final BufferedImage tileImage = tImage.getSubimage(x, y, wh, wh);
     331                            final int x = (txy.x() - minX) * tileSize;
     332                            final int y = (txy.y() - minY) * tileSize;
     333                            final int wh = tileSize;
     334
     335                            final BufferedImage tileImage = tImage.getSubimage(x, y, wh + BUFFER_PIXELS, wh + BUFFER_PIXELS);
    326336                            loader.cacheTile(tileImage);
    327337                        }
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/TileZXY.java

    r19181 r19220  
    99
    1010/**
    11  * A record used for storing tile information for painting
     11 * A record used for storing tile information for painting.
     12 * The origin is upper-left, not lower-left (so more like Google tile coordinates than TMS tile coordinates).
    1213 * @since 19176
    1314 */
     
    144145     */
    145146    public static TileZXY latLonToTile(double lat, double lon, int zoom) {
    146         int xCoord = (int) Math.floor(Math.pow(2, zoom) * (180 + lon) / 360);
    147         int yCoord = (int) Math.floor(Math.pow(2, zoom) *
    148                 (1 - Math.log(Math.tan(Math.toRadians(lat)) + 1 / Math.cos(Math.toRadians(lat))) / Math.PI) / 2);
     147        final double zoom2 = Math.pow(2, zoom);
     148        final double latLog = Math.log(Math.tan(Math.toRadians(lat)) + 1 / Math.cos(Math.toRadians(lat)));
     149        final int xCoord = (int) Math.floor(zoom2 * (180 + lon) / 360);
     150        final int yCoord = (int) Math.floor(zoom2 * (1 - latLog / Math.PI) / 2);
    149151        return new TileZXY(zoom, xCoord, yCoord);
    150152    }
  • trunk/test/functional/org/openstreetmap/josm/gui/mappaint/MapCSSRendererTest.java

    r19056 r19220  
    222222        }
    223223        final BufferedImage reference = ImageIO.read(referenceImageFile);
     224        assertImageEquals(testIdentifier, reference, image, thresholdPixels, thresholdTotalColorDiff, diffImageConsumer);
     225    }
     226
     227    /**
     228     * Compares the reference image file with the actual images given as {@link BufferedImage}.
     229     * @param testIdentifier a test identifier for error messages
     230     * @param reference the reference image
     231     * @param image the actual image
     232     * @param thresholdPixels maximum number of differing pixels
     233     * @param thresholdTotalColorDiff maximum sum of color value differences
     234     * @param diffImageConsumer a consumer for a rendered image highlighting the differing pixels, may be null
     235     */
     236    public static void assertImageEquals(String testIdentifier, BufferedImage reference, BufferedImage image,
     237                                         int thresholdPixels, int thresholdTotalColorDiff, Consumer<BufferedImage> diffImageConsumer) {
    224238        assertEquals(reference.getWidth(), image.getWidth());
    225239        assertEquals(reference.getHeight(), image.getHeight());
Note: See TracChangeset for help on using the changeset viewer.