001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.projection;
003
004import java.util.function.Consumer;
005
006import org.openstreetmap.josm.data.Bounds;
007import org.openstreetmap.josm.data.ProjectionBounds;
008import org.openstreetmap.josm.data.coor.EastNorth;
009import org.openstreetmap.josm.data.coor.LatLon;
010
011/**
012 * A projection, i.e. a class that supports conversion from lat/lon
013 * to east/north and back.
014 *
015 * The conversion from east/north to the screen coordinates is simply a scale
016 * factor and x/y offset.
017 */
018public interface Projection extends Projecting {
019    /**
020     * The default scale factor in east/north units per pixel
021     * ({@link org.openstreetmap.josm.gui.NavigatableComponent#getState})).
022     * FIXME: misnomer
023     * @return the scale factor
024     */
025    double getDefaultZoomInPPD();
026
027    /**
028     * Convert from easting/norting to lat/lon.
029     *
030     * @param en the geographical point to convert (in projected coordinates)
031     * @return the corresponding lat/lon (WGS84)
032     */
033    LatLon eastNorth2latlon(EastNorth en);
034
035    /**
036     * Describe the projection in one or two words.
037     * @return the name / description
038     */
039    @Override
040    String toString();
041
042    /**
043     * Return projection code.
044     *
045     * This should be a unique identifier.
046     * If projection supports parameters, return a different code
047     * for each set of parameters.
048     *
049     * The EPSG code can be used (if defined for the projection).
050     *
051     * @return the projection identifier
052     */
053    String toCode();
054
055    /**
056     * Get the bounds of the world.
057     * @return the supported lat/lon rectangle for this projection
058     */
059    Bounds getWorldBoundsLatLon();
060
061    /**
062     * Get an approximate EastNorth box around the lat/lon world bounds.
063     *
064     * Note: The projection is only valid within the bounds returned by
065     * {@link #getWorldBoundsLatLon()}. The lat/lon bounds need not be a
066     * rectangular shape in east/north space. This method returns a box that
067     * contains this shape.
068     *
069     * @return EastNorth box around the lat/lon world bounds
070     */
071    ProjectionBounds getWorldBoundsBoxEastNorth();
072
073    /**
074     * Find lat/lon-box containing all the area of a given rectangle in
075     * east/north space.
076     *
077     * This is an approximate method. Points outside of the world should be ignored.
078     *
079     * @param pb the rectangle in projected space
080     * @return minimum lat/lon box, that when projected, covers <code>pb</code>
081     */
082    Bounds getLatLonBoundsBox(ProjectionBounds pb);
083
084    /**
085     * Get a box in east/north space of this projection, that fully contains an
086     * east/north box of another projection.
087     *
088     * Reprojecting a rectangular box from one projection to another may distort/rotate
089     * the shape of the box, so in general one needs to walk along the boundary
090     * in small steps to get a reliable result.
091     *
092     * This is an approximate method.
093     *
094     * @param box the east/north box given in projection <code>boxProjection</code>
095     * @param boxProjection the projection of <code>box</code>
096     * @return an east/north box in this projection, containing the given box
097     */
098    ProjectionBounds getEastNorthBoundsBox(ProjectionBounds box, Projection boxProjection);
099
100    /**
101     * Get the number of meters per unit of this projection. This more
102     * defines the scale of the map, than real conversion of unit to meters
103     * as this value is more less correct only along certain lines of true scale.
104     *
105     * Used by WMTS to properly scale tiles
106     * @return meters per unit of projection
107     */
108    double getMetersPerUnit();
109
110    /**
111     * Does this projection natural order of coordinates is North East,
112     * instead of East North
113     *
114     * @return true if natural order of coordinates is North East, false if East North
115     */
116    boolean switchXY();
117
118    /**
119     * Visit points along the edge of this bounds instance.
120     * <p>
121     * Depending on the shape in east/north space, it may simply visit the 4 corners
122     * or (more generally) several points along the curved edges.
123     * @param bounds the lat/lon rectangle to trace
124     * @param visitor a function to call for the points on the edge.
125     * @since 12818
126     */
127    void visitOutline(Bounds bounds, Consumer<EastNorth> visitor);
128}