All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ucar.unidata.geoloc.projection.proj4.CylindricalEqualAreaProjection Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2006 Jerry Huxtable
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * This file was semi-automatically converted from the public-domain USGS PROJ source.
 *
 * Changes by Bernhard Jenny, May 2007: added missing toString() and
 * isEqualArea(); this class now derives from CylindricalProjection instead of
 * Projection; removed isRectilinear, which is defined in the new superclass
 * CylindricalProjection; and removed trueScaleLatitude that did hide a field
 * of the Projection class of the same name.
 */

package ucar.unidata.geoloc.projection.proj4;

import java.util.Objects;
import ucar.nc2.constants.CDM;
import ucar.nc2.constants.CF;
import ucar.unidata.geoloc.*;

/**
 * CylindricalEqualArea Projection.
 * Port from proj4.
 */
public class CylindricalEqualAreaProjection extends ProjectionImpl {

  private double trueScaleLatitude, lon0; // degrees
  private double scaleFactor;
  private double projectionLongitude; // radians
  private double falseEasting;
  private double falseNorthing;
  private Earth earth;
  private double e;
  private double one_es;
  private double totalScale;

  private double qp;
  private double[] apa;

  // default WSG ellipsoid
  public CylindricalEqualAreaProjection() {
    this(0.0, 1.0, 0.0, 0.0, EarthEllipsoid.WGS84);
  }

  public CylindricalEqualAreaProjection(double lon0, double trueScaleLatitude, double falseEasting,
      double falseNorthing, Earth earth) {
    super("CylindricalEqualAreaProjection", false);

    Objects.requireNonNull(earth, "CEA constructor requires non-null Earth");

    this.lon0 = lon0;

    this.projectionLongitude = Math.toRadians(lon0);
    this.trueScaleLatitude = trueScaleLatitude; // LOOK not used

    this.falseEasting = falseEasting;
    this.falseNorthing = falseNorthing;

    this.earth = earth;
    this.e = earth.getEccentricity();
    double es = earth.getEccentricitySquared();
    this.one_es = 1 - es;
    this.totalScale = earth.getMajor() * .001; // scale factor for cartesion coords in km.

    double t = Math.toRadians(trueScaleLatitude);
    scaleFactor = Math.cos(t);

    if (!earth.isSpherical()) {
      t = Math.sin(t);
      scaleFactor /= Math.sqrt(1. - es * t * t);
      apa = MapMath.authset(es);
      qp = MapMath.qsfn(1., e, one_es);
    }

    addParameter(CF.GRID_MAPPING_NAME, CF.LAMBERT_CYLINDRICAL_EQUAL_AREA);
    addParameter(CF.LONGITUDE_OF_CENTRAL_MERIDIAN, lon0);
    addParameter(CF.STANDARD_PARALLEL, trueScaleLatitude);

    if ((falseEasting != 0.0) || (falseNorthing != 0.0)) {
      addParameter(CF.FALSE_EASTING, falseEasting);
      addParameter(CF.FALSE_NORTHING, falseNorthing);
      addParameter(CDM.UNITS, "km");
    }

    addParameter(CF.SEMI_MAJOR_AXIS, earth.getMajor());
    addParameter(CF.INVERSE_FLATTENING, 1.0 / earth.getFlattening());
  }

  @Override
  public ProjectionImpl constructCopy() {
    ProjectionImpl result =
        new CylindricalEqualAreaProjection(lon0, trueScaleLatitude, falseEasting, falseNorthing, earth);
    result.setDefaultMapArea(defaultMapArea);
    result.setName(name);
    return result;
  }

  @Override
  public String paramsToString() {
    return null;
  }

  public ProjectionPoint latLonToProj(LatLonPoint latlon, ProjectionPointImpl xy) {
    double lam = Math.toRadians(latlon.getLongitude() - lon0);
    double phi = Math.toRadians(latlon.getLatitude());
    if (earth.isSpherical()) {
      xy.setLocation(scaleFactor * lam, Math.sin(phi) / scaleFactor);
    } else {
      xy.setLocation(scaleFactor * lam, .5 * MapMath.qsfn(Math.sin(phi), e, one_es) / scaleFactor);
    }

    xy.setLocation(totalScale * xy.getX() + falseEasting, totalScale * xy.getY() + falseNorthing);
    return xy;
  }

  public LatLonPoint projToLatLon(ProjectionPoint ppt, LatLonPointImpl lp) {
    double x = (ppt.getX() - falseEasting) / totalScale; // assumes cartesion coords in km
    double y = (ppt.getY() - falseNorthing) / totalScale;

    if (earth.isSpherical()) {
      y *= scaleFactor;
      double t = Math.abs(y);

      if (t - MapMath.EPS10 <= 1.) {
        if (t >= 1.) {
          lp.setLatitude(Math.toDegrees(y < 0. ? -MapMath.HALFPI : MapMath.HALFPI));
        } else {
          lp.setLatitude(Math.toDegrees(Math.asin(y)));
        }
        lp.setLongitude(Math.toDegrees(x / scaleFactor));
      } else {
        throw new IllegalStateException();
      }
    } else {
      lp.setLatitude(Math.toDegrees(MapMath.authlat(Math.asin(2. * y * scaleFactor / qp), apa)));
      lp.setLongitude(lon0 + Math.toDegrees(x / scaleFactor));
    }
    return lp;
  }

  @Override
  public boolean crossSeam(ProjectionPoint pt1, ProjectionPoint pt2) {
    return false;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o)
      return true;
    if (o == null || getClass() != o.getClass())
      return false;

    CylindricalEqualAreaProjection that = (CylindricalEqualAreaProjection) o;

    if (Double.compare(that.falseEasting, falseEasting) != 0)
      return false;
    if (Double.compare(that.falseNorthing, falseNorthing) != 0)
      return false;
    if (Double.compare(that.projectionLongitude, projectionLongitude) != 0)
      return false;
    if (Double.compare(that.scaleFactor, scaleFactor) != 0)
      return false;
    if (!Objects.equals(earth, that.earth))
      return false;
    if ((defaultMapArea == null) != (that.defaultMapArea == null))
      return false; // common case is that these are null
    return defaultMapArea == null || that.defaultMapArea.equals(defaultMapArea);

  }

  @Override
  public int hashCode() {
    int result;
    long temp;
    temp = scaleFactor != 0.0d ? Double.doubleToLongBits(scaleFactor) : 0L;
    result = (int) (temp ^ (temp >>> 32));
    temp = projectionLongitude != 0.0d ? Double.doubleToLongBits(projectionLongitude) : 0L;
    result = 31 * result + (int) (temp ^ (temp >>> 32));
    temp = falseEasting != 0.0d ? Double.doubleToLongBits(falseEasting) : 0L;
    result = 31 * result + (int) (temp ^ (temp >>> 32));
    temp = falseNorthing != 0.0d ? Double.doubleToLongBits(falseNorthing) : 0L;
    result = 31 * result + (int) (temp ^ (temp >>> 32));
    result = 31 * result + (earth != null ? earth.hashCode() : 0);
    return result;
  }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy