001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.projection.proj;
003
004import org.openstreetmap.josm.data.Bounds;
005import org.openstreetmap.josm.data.projection.ProjectionConfigurationException;
006
007/**
008 * A projection (in the narrow sense).
009 *
010 * Converts lat/lon the east/north and the other way around.
011 *
012 * Datum conversion, false easting / northing, origin of longitude
013 * and general scale factor is already applied when the projection is invoked.
014 *
015 * Lat/lon is not in degrees, but in radians (unlike other parts of JOSM).
016 * Additional parameters in the constructor arguments are usually still in
017 * degrees. So to avoid confusion, you can follow the convention, that
018 * coordinates in radians are called lat_rad/lon_rad or phi/lambda.
019 *
020 * East/north values are not in meters, but in meters divided by the semi major
021 * axis of the ellipsoid (earth radius). (Usually this is what you get anyway,
022 * unless you multiply by 'a' somehow implicitly or explicitly.)
023 *
024 */
025public interface Proj {
026
027    /**
028     * Replies a human readable name of this projection.
029     * @return The projection name. must not be null.
030     */
031    String getName();
032
033    /**
034     * Replies the Proj.4 identifier.
035     *
036     * @return The Proj.4 identifier (as reported by cs2cs -lp).
037     * If no id exists, return {@code null}.
038     */
039    String getProj4Id();
040
041    /**
042     * Initialize the projection using the provided parameters.
043     * @param params The projection parameters
044     *
045     * @throws ProjectionConfigurationException in case parameters are not suitable
046     */
047    void initialize(ProjParameters params) throws ProjectionConfigurationException;
048
049    /**
050     * Convert lat/lon to east/north.
051     *
052     * @param latRad the latitude in radians
053     * @param lonRad the longitude in radians
054     * @return array of length 2, containing east and north value in meters,
055     * divided by the semi major axis of the ellipsoid.
056     */
057    double[] project(double latRad, double lonRad);
058
059    /**
060     * Convert east/north to lat/lon.
061     *
062     * @param east east value in meters, divided by the semi major axis of the ellipsoid
063     * @param north north value in meters, divided by the semi major axis of the ellipsoid
064     * @return array of length 2, containing lat and lon in radians.
065     */
066    double[] invproject(double east, double north);
067
068    /**
069     * Return the bounds where this projection is applicable.
070     *
071     * This is a fallback for when the projection bounds are not specified
072     * explicitly.
073     *
074     * In this area, the round trip lat/lon -> east/north -> lat/lon should
075     * return the starting value with small error. In addition, regions with
076     * extreme distortions should be excluded, if possible.
077     *
078     * It need not be the absolute maximum, but rather an area that is safe to
079     * display in JOSM and contain everything that one would expect to use.
080     *
081     * @return the bounds where this projection is applicable, null if unknown
082     */
083    Bounds getAlgorithmBounds();
084
085    /**
086     * Return true, if a geographic coordinate reference system is represented.
087     *
088     * I.e. if it returns latitude/longitude values rather than Cartesian
089     * east/north coordinates on a flat surface.
090     * @return true, if it is geographic
091     */
092    boolean isGeographic();
093
094    /**
095     * Checks wether the result of projecting a lon coordinate only has a linear relation to the east coordinate and
096     * is not related to lat/north at all.
097     * @return <code>true</code> if lon has a linear relationship to east only.
098     * @since 10805
099     */
100    default boolean lonIsLinearToEast() {
101        return false;
102    }
103}