001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.layer.imagery; 003 004import java.awt.geom.AffineTransform; 005import java.awt.geom.Point2D; 006 007import org.openstreetmap.gui.jmapviewer.interfaces.IProjected; 008 009/** 010 * Class that fixes the position of a tile in a given coordinate space. 011 * 012 * This is done by storing the coordinates of the tile origin and the opposite 013 * tile corner. 014 * <p> 015 * It may represent a reprojected tile, i.e. the tile is rotated / deformed in an 016 * arbitrary way. In general, the tile origin cannot be expected to be the 017 * upper left corner of the rectangle that is spanned by the 2 points. 018 * <p> 019 * The coordinate space may be 020 * <ul> 021 * <li>pixel coordinates of the image file</li> 022 * <li>projected coordinates (east / north)</li> 023 * <li>screen pixel coordinates</li> 024 * </ul> 025 * @since 11846 026 */ 027public class TileAnchor { 028 029 protected final Point2D tileOrigin, nextTileOrigin; 030 031 /** 032 * Create a new tile anchor. 033 * @param tileOrigin position of the tile origin 034 * @param nextTileOrigin position of the opposite tile corner, i.e. the 035 * origin of the tile with index (x+1,y+1), when current tile has index (x,y) 036 */ 037 public TileAnchor(Point2D tileOrigin, Point2D nextTileOrigin) { 038 this.tileOrigin = tileOrigin; 039 this.nextTileOrigin = nextTileOrigin; 040 } 041 042 /** 043 * Constructs a new {@code TileAnchor}. 044 * @param tileOrigin position of the tile origin 045 * @param nextTileOrigin position of the opposite tile corner, i.e. the 046 * origin of the tile with index (x+1,y+1), when current tile has index (x,y) 047 */ 048 public TileAnchor(IProjected tileOrigin, IProjected nextTileOrigin) { 049 this.tileOrigin = new Point2D.Double(tileOrigin.getEast(), tileOrigin.getNorth()); 050 this.nextTileOrigin = new Point2D.Double(nextTileOrigin.getEast(), nextTileOrigin.getNorth()); 051 } 052 053 /** 054 * Returns the position of the tile origin. 055 * @return the position of the tile origin 056 */ 057 public Point2D getTileOrigin() { 058 return tileOrigin; 059 } 060 061 /** 062 * Returns the position of the opposite tile corner. 063 * @return the position of the opposite tile corner, i.e. the 064 * origin of the tile with index (x+1,y+1), when current tile has index (x,y) 065 */ 066 public Point2D getNextTileOrigin() { 067 return nextTileOrigin; 068 } 069 070 @Override 071 public String toString() { 072 return "TileAnchor{" + tileOrigin + "; " + nextTileOrigin + '}'; 073 } 074 075 /** 076 * Create a transformation that converts points from this coordinate space 077 * to another coordinate space. 078 * @param other tile anchor of the tile in the target coordinate space 079 * @return affine transformation from this coordinate space to the target 080 * coordinate space 081 */ 082 public AffineTransform convert(TileAnchor other) { 083 Point2D src1 = this.getTileOrigin(); 084 Point2D src2 = this.getNextTileOrigin(); 085 Point2D dest1 = other.getTileOrigin(); 086 Point2D dest2 = other.getNextTileOrigin(); 087 088 double scaleX = (dest2.getX() - dest1.getX()) / (src2.getX() - src1.getX()); 089 double scaleY = (dest2.getY() - dest1.getY()) / (src2.getY() - src1.getY()); 090 double offsetX0 = dest1.getX() - scaleX * src1.getX(); 091 double offsetY0 = dest1.getY() - scaleY * src1.getY(); 092 return new AffineTransform(scaleX, 0, 0, scaleY, offsetX0, offsetY0); 093 } 094}