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 = invMlfn(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}