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

org.apache.commons.numbers.angle.PlaneAngle Maven / Gradle / Ivy

There is a newer version: 1.2
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.commons.numbers.angle;

/**
 * Represents the angle concept.
 */
public final class PlaneAngle {
    /** Zero. */
    public static final PlaneAngle ZERO = new PlaneAngle(0);
    /** Half-turn (aka π radians). */
    public static final PlaneAngle PI = new PlaneAngle(0.5);
    /** Conversion factor. */
    private static final double HALF_TURN = 0.5;
    /** Conversion factor. */
    private static final double TO_RADIANS = PlaneAngleRadians.TWO_PI;
    /** Conversion factor. */
    private static final double FROM_RADIANS = 1d / TO_RADIANS;
    /** Conversion factor. */
    private static final double TO_DEGREES = 360;
    /** Conversion factor. */
    private static final double FROM_DEGREES = 1d / TO_DEGREES;
    /** Value (in turns). */
    private final double value;

    /**
     * @param value Value in turns.
     */
    private PlaneAngle(double value) {
        this.value = value;
    }

    /**
     * @param angle (in turns).
     * @return a new intance.
     */
    public static PlaneAngle ofTurns(double angle) {
        return new PlaneAngle(angle);
    }

    /**
     * @param angle (in radians).
     * @return a new intance.
     */
    public static PlaneAngle ofRadians(double angle) {
        return new PlaneAngle(angle * FROM_RADIANS);
    }

    /**
     * @param angle (in degrees).
     * @return a new intance.
     */
    public static PlaneAngle ofDegrees(double angle) {
        return new PlaneAngle(angle * FROM_DEGREES);
    }

    /**
     * @return the value in turns.
     */
    public double toTurns() {
        return value;
    }

    /**
     * @return the value in radians.
     */
    public double toRadians() {
        return value * TO_RADIANS;
    }

    /**
     * @return the value in degrees.
     */
    public double toDegrees() {
        return value * TO_DEGREES;
    }

    /**
     * Normalize an angle in an interval of size 1 turn around a
     * center value.
     *
     * @param center Center of the desired interval for the result.
     * @return {@code a - k} with integer {@code k} such that
     * {@code center - 0.5 <= a - k < center + 0.5} (in turns).
     */
    public PlaneAngle normalize(PlaneAngle center) {
        final double lowerBound = center.value - HALF_TURN;
        final double upperBound = center.value + HALF_TURN;

        final double normalized = value - Math.floor(value - lowerBound);

        return normalized < upperBound ?
            new PlaneAngle(normalized) :
            // If value is too small to be representable compared to the
            // floor expression above (ie, if value + x = x), then we may
            // end up with a number exactly equal to the upper bound here.
            // In that case, subtract one from the normalized value so that
            // we can fulfill the contract of only returning results strictly
            // less than the upper bound.
            new PlaneAngle(normalized - 1);
    }

    /**
     * Test for equality with another object.
     * Objects are considered to be equal if the two values are exactly the
     * same, or both are {@code Double.NaN}.
     *
     * @param other Object to test for equality with this instance.
     * @return {@code true} if the objects are equal, {@code false} if
     * {@code other} is {@code null}, not an instance of {@code PlaneAngle},
     * or not equal to this instance.
     */
    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (other instanceof PlaneAngle) {
            return Double.doubleToLongBits(value) ==
                    Double.doubleToLongBits(((PlaneAngle) other).value);
        }
        return false;
    }

    /** {@inheritDoc} */
    @Override
    public int hashCode() {
        return Double.hashCode(value);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy