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

io.guise.framework.geometry.CompassPoint Maven / Gradle / Ivy

There is a newer version: 0.5.3
Show newest version
/*
 * Copyright © 2005-2008 GlobalMentor, Inc. 
 *
 * 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.
 */

package io.guise.framework.geometry;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * Navigational directions.
 * @author Garret Wilson
 * @see Wikipedia: Compass
 * @see Wikipedia: Boxing the Compass
 */
public enum CompassPoint {
	NORTH("N", new BigDecimal("0.00"), true, false), NORTH_BY_EAST("NbE", new BigDecimal("11.25"), false, false), NORTH_NORTHEAST("NNE", new BigDecimal("22.50"),
			false, false), NORTHEAST_BY_NORTH("NEbN", new BigDecimal("33.75"), false, false), NORTHEAST("NE", new BigDecimal("45.00"), false, true), NORTHEAST_BY_EAST(
			"NEbE", new BigDecimal("56.25"), false, false), EAST_NORTHEAST("ENE", new BigDecimal("67.50"), false, false), EAST_BY_NORTH("EbN",
			new BigDecimal("78.75"), false, false), EAST("E", new BigDecimal("90.00"), true, false), EAST_BY_SOUTH("EbS", new BigDecimal("101.25"), false, false), EAST_SOUTHEAST(
			"ESE", new BigDecimal("112.50"), false, false), SOUTHEAST_BY_EAST("SEbE", new BigDecimal("123.75"), false, false), SOUTHEAST("SE", new BigDecimal(
			"135.00"), false, true), SOUTHEAST_BY_SOUTH("SEbS", new BigDecimal("146.25"), false, false), SOUTH_SOUTHEAST("SSE", new BigDecimal("157.50"), false,
			false), SOUTH_BY_EAST("SbE", new BigDecimal("168.75"), false, false), SOUTH("S", new BigDecimal("180.00"), true, false), SOUTH_BY_WEST("SbW",
			new BigDecimal("191.25"), false, false), SOUTH_SOUTHWEST("SSW", new BigDecimal("202.50"), false, false), SOUTHWEST_BY_SOUTH("SWbS", new BigDecimal(
			"213.75"), false, false), SOUTHWEST("SW", new BigDecimal("225.00"), false, true), SOUTHWEST_BY_WEST("SWbW", new BigDecimal("236.26"), false, false), WEST_SOUTHWEST(
			"WSW", new BigDecimal("247.50"), false, false), WEST_BY_SOUTH("WbS", new BigDecimal("258.75"), false, false), WEST("W", new BigDecimal("270.00"), true,
			false), WEST_BY_NORTH("WbN", new BigDecimal("281.25"), false, false), WEST_NORTHWEST("WNW", new BigDecimal("292.50"), false, false), NORTHWEST_BY_WEST(
			"NWbW", new BigDecimal("303.75"), false, false), NORTHWEST("NW", new BigDecimal("315.00"), false, true), NORTHWEST_BY_NORTH("NWbN", new BigDecimal(
			"326.25"), false, false), NORTH_NORTHWEST("NNW", new BigDecimal("337.50"), false, false), NORTHBY_WEST("NbW", new BigDecimal("348.75"), false, false);

	/** The maximum bearing available; synonymous with {@link #NORTH}. */
	public static final BigDecimal MAX_BEARING = new BigDecimal(360);

	/** The abbreviation of this compass point. */
	private final String abbreviation;

	/** @return The abbreviation of this compass point. */
	public String getAbbreviation() {
		return abbreviation;
	}

	/** The compass direction. */
	private final BigDecimal bearing;

	/** @return The compass direction. */
	public BigDecimal getBearing() {
		return bearing;
	}

	/** Whether this compass point represents one of the four cardinal directions. */
	private final boolean cardinal;

	/** @return Whether this compass point represents one of the four cardinal directions. */
	public boolean isCardinal() {
		return cardinal;
	}

	/** Whether this compass point represents one of the four ordinal or intercardinal directions. */
	private final boolean ordinal;

	/** @return Whether this compass point represents one of the four ordinal or intercardinal directions. */
	public boolean isOrdinal() {
		return ordinal;
	}

	/**
	 * Abbreviation and bearing constructor.
	 * @param abbreviation The abbreviation of this compass point.
	 * @param bearing The compass direction.
	 * @param cardinal Whether this compass point represents one of the four cardinal directions.
	 * @param ordinal Whether this compass point represents one of the four ordinal or intercardinal directions.
	 */
	private CompassPoint(final String abbreviation, final BigDecimal bearing, final boolean cardinal, final boolean ordinal) {
		this.abbreviation = abbreviation;
		this.bearing = bearing;
		this.cardinal = cardinal;
		this.ordinal = ordinal;
	}

	/**
	 * Determines the closes compass point to the given bearing.
	 * @param bearing The bearing for which a compass point should be returned.
	 * @return The compass point closest to the given bearing.
	 * @throws IllegalArgumentException if the given bearing is greater than 360.
	 */
	public static CompassPoint getCompassPoint(final BigDecimal bearing) {
		final CompassPoint[] compassPoints = values(); //get the available compass points
		final int compassPointCount = compassPoints.length; //get the number of compass points available
		final int compassPointOrdinal = Math.round(checkBearing(bearing).divide(MAX_BEARING, RoundingMode.HALF_EVEN).multiply(new BigDecimal(compassPointCount))
				.floatValue()); //find out the ordinal of the nearest compass point: round((bearing/360)*32)
		return compassPoints[compassPointOrdinal == compassPointCount ? 0 : compassPointOrdinal]; //return the correct compass point (using NORTH for the 360 bearing at ordinal 32)		
	}

	/**
	 * Returns the ordinal or inter-cardinal compass point corresonding to 45 degrees between the given cardinal latitude and longitude compass points.
	 * @param latitudeCompassPoint The cardinal compass point of the latitude; either {@link CompassPoint#WEST} or {@link CompassPoint#EAST}.
	 * @param longitudeCompassPoint The cardinal compass point of the longitude; either {@link CompassPoint#NORTH} or {@link CompassPoint#SOUTH}.
	 * @return The ordinal compass position corresponding to 45 degrees between the given cardinal longitude and latitude compass points.
	 * @throws NullPointerException if the given latitude and/or longitude compass point is null.
	 * @throws IllegalArgumentException if the given latitude compass point is not {@link CompassPoint#WEST} or {@link CompassPoint#EAST}; and/or if the given
	 *           longitude compass point is not {@link CompassPoint#NORTH} or {@link CompassPoint#SOUTH}.
	 */
	public static CompassPoint getOrdinalCompassPoint(final CompassPoint latitudeCompassPoint, final CompassPoint longitudeCompassPoint) {
		switch(longitudeCompassPoint) {
			case NORTH:
				switch(latitudeCompassPoint) {
					case WEST:
						return CompassPoint.NORTHWEST;
					case EAST:
						return CompassPoint.NORTHEAST;
					default:
						throw new IllegalArgumentException("Latitude compass point " + latitudeCompassPoint + " must be either " + CompassPoint.WEST + " or "
								+ CompassPoint.WEST);
				}
			case SOUTH:
				switch(latitudeCompassPoint) {
					case WEST:
						return CompassPoint.SOUTHWEST;
					case EAST:
						return CompassPoint.SOUTHEAST;
					default:
						throw new IllegalArgumentException("Latitude compass point " + latitudeCompassPoint + " must be either " + CompassPoint.WEST + " or "
								+ CompassPoint.WEST);
				}
			default:
				throw new IllegalArgumentException("Longitude compass point " + longitudeCompassPoint + " must be either " + CompassPoint.NORTH + " or "
						+ CompassPoint.SOUTH);
		}
	}

	/**
	 * Checks to ensure that the given bearing is valid.
	 * @param bearing The bearing to check.
	 * @return The valid bearing.
	 * @throws IllegalArgumentException if the given bearing is greater than 360.
	 */
	public static BigDecimal checkBearing(final BigDecimal bearing) {
		if(bearing.compareTo(MAX_BEARING) > 0) { //if the bearing is greater than 360
			throw new IllegalArgumentException("Bearing " + bearing + " is greater than 360.");
		}
		return bearing; //return the bearing, which as been confirmed to be valid
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy