/* Copyright (C) 2001, 2006 United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All Rights Reserved. */ package gov.nasa.worldwind.geom; import gov.nasa.worldwind.util.Logging; /** * Represents a point in space defined by a latitude, longitude and distance from the origin. * <p/> * Instances of <code>PolarPoint</code> are immutable. * * @author Tom Gaskins * @version $Id: PolarPoint.java 2471 2007-07-31 21:50:57Z tgaskins $ */ public class PolarPoint { public static final PolarPoint ZERO = new PolarPoint(Angle.ZERO, Angle.ZERO, 0d); private final Angle latitude; private final Angle longitude; private final double radius; /** * Obtains a <code>PolarPoint</code> from radians and a radius. * * @param latitude the latitude in radians * @param longitude the longitude in radians * @param radius the distance form the center * @return a new <code>PolarPoint</code> */ public static PolarPoint fromRadians(double latitude, double longitude, double radius) { return new PolarPoint(Angle.fromRadians(latitude), Angle.fromRadians(longitude), radius); } /** * Obtains a <code>PolarPoint</code> from degrees and a radius. * * @param latitude the latitude in degrees * @param longitude the longitude in degrees * @param radius the distance form the center * @return a new <code>PolarPoint</code> */ public static PolarPoint fromDegrees(double latitude, double longitude, double radius) { return new PolarPoint(Angle.fromDegrees(latitude), Angle.fromDegrees(longitude), radius); } /** * Obtains a <code>PolarPoint</code> from a cartesian point. * * @param cartesianPoint the point to convert * @return the cartesian point expressed as a polar point * @throws IllegalArgumentException if <code>cartesianPoint</code> is null */ public static PolarPoint fromCartesian(Vec4 cartesianPoint) { if (cartesianPoint == null) { String message = Logging.getMessage("nullValue.PointIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } return PolarPoint.fromCartesian(cartesianPoint.x, cartesianPoint.y, cartesianPoint.z); } /** * Obtains a <code>PolarPoint</code> from cartesian coordinates. * * @param x the x coordinate of the cartesian point * @param y the y coordinate of the cartesian point * @param z the z coordinate of the cartesian point * @return a polar point located at (x,y,z) in cartesian space */ public static PolarPoint fromCartesian(double x, double y, double z) { double radius = Math.sqrt(x * x + y * y + z * z); double latRads = Math.atan2(y, Math.sqrt(x * x + z * z)); double lonRads = Math.atan2(x, z); return PolarPoint.fromRadians(latRads, lonRads, radius); } /** * Obtains a <code>PolarPoint</code> from two <code>angles</code> and a radius. * * @param latitude the latitude * @param longitude the longitude * @param radius the distance from the center * @throws IllegalArgumentException if <code>latitude</code> or <code>longitude</code> is null */ public PolarPoint(Angle latitude, Angle longitude, double radius) { if (latitude == null || longitude == null) { String message = Logging.getMessage("nullValue.LatitudeOrLongitudeIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } this.latitude = latitude; this.longitude = longitude; this.radius = radius; } /** * Obtains the latitude of this polar point * * @return this polar point's latitude */ public final Angle getLatitude() { return this.latitude; } /** * Obtains the longitude of this polar point * * @return this polar point's longitude */ public final Angle getLongitude() { return this.longitude; } /** * Obtains the radius of this polar point * * @return the distance from this polar point to its origin */ public final double getRadius() { return radius; } /** * Obtains a cartesian point equivalent to this <code>PolarPoint</code>, except in cartesian space. * * @return this polar point in cartesian coordinates */ public final Vec4 toCartesian() { return toCartesian(this.latitude, this.longitude, this.radius); } /** * Obtains a cartesian point from a given latitude, longitude and distance from center. This method is equivalent * to, but may perform faster than <code>Vec4 p = new PolarPoint(latitude, longitude, radius).toCartesian()</code> * * @param latitude the latitude * @param longitude the longitude * @param radius the distance from the origin * @return a cartesian point from two angles and a radius * @throws IllegalArgumentException if <code>latitude</code> or <code>longitude</code> is null */ public static Vec4 toCartesian(Angle latitude, Angle longitude, double radius) { if (latitude == null || longitude == null) { String message = Logging.getMessage("nullValue.LatitudeOrLongitudeIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } double x = radius * longitude.sin() * latitude.cos(); double y = radius * latitude.sin(); double z = radius * longitude.cos() * latitude.cos(); return new Vec4(x, y, z); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final gov.nasa.worldwind.geom.PolarPoint that = (gov.nasa.worldwind.geom.PolarPoint) o; if (Double.compare(that.radius, radius) != 0) return false; if (!latitude.equals(that.latitude)) return false; //noinspection RedundantIfStatement if (!longitude.equals(that.longitude)) return false; return true; } @Override public int hashCode() { int result; long temp; result = latitude.hashCode(); result = 29 * result + longitude.hashCode(); temp = radius != +0.0d ? Double.doubleToLongBits(radius) : 0L; result = 29 * result + (int) (temp ^ (temp >>> 32)); return result; } @Override public String toString() { return "(lat: " + this.latitude.toString() + ", lon: " + this.longitude.toString() + ", r: " + this.radius + ")"; } }