001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.projection.proj;
003
004import static java.lang.Math.abs;
005import static java.lang.Math.cos;
006import static java.lang.Math.sin;
007import static java.lang.Math.sqrt;
008import static org.openstreetmap.josm.tools.I18n.tr;
009
010import org.openstreetmap.josm.data.Bounds;
011
012/**
013 * Sinusoidal projection (aka. Sanson–Flamsteed, Mercator equal-area projection)
014 * <p>
015 * This class has been derived from the implementation of the <a href="https://github.com/geotools/geotools">Geotools</a> project;
016 * git 577dd2d, org.geotools.referencing.operation.projection.Sinusoidal at the time of migration.
017 */
018public class Sinusoidal extends AbstractProj {
019
020    @Override
021    public String getName() {
022        return tr("Sinusoidal");
023    }
024
025    @Override
026    public String getProj4Id() {
027        return "sinu";
028    }
029
030    @Override
031    public double[] project(final double phi, final double lambda) {
032        if (spherical) {
033            return new double[]{lambda * cos(phi), phi};
034        } else {
035            final double s = sin(phi);
036            return new double[]{lambda * cos(phi) / sqrt(1. - e2 * s * s), mlfn(phi, s, cos(phi))};
037        }
038    }
039
040    @Override
041    public double[] invproject(final double east, final double north) {
042        if (spherical) {
043            return new double[]{north, east / cos(north)};
044        } else {
045            final double phi = inv_mlfn(north);
046            double s = abs(phi);
047            final double lambda;
048            if (abs(s - Math.PI / 2) < 1e-10) {
049                lambda = 0.;
050            } else if (s < Math.PI / 2) {
051                s = sin(phi);
052                lambda = (east * sqrt(1. - e2 * s * s) / cos(phi)) % Math.PI;
053            } else {
054                return new double[]{0., 0.}; // this is an error and should be handled somehow
055            }
056            return new double[]{phi, lambda};
057        }
058    }
059
060    @Override
061    public Bounds getAlgorithmBounds() {
062        return new Bounds(-90, -180, 90, 180, false);
063    }
064}