Transform1S.java
- /*
- * 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.geometry.spherical.oned;
- import org.apache.commons.geometry.core.Transform;
- /** Implementation of the {@link Transform} interface for spherical 1D points.
- *
- * <p>Similar to the Euclidean 1D
- * {@link org.apache.commons.geometry.euclidean.oned.AffineTransformMatrix1D AffineTransformMatrix1D},
- * this class performs transformations using an internal 1D affine transformation matrix. In the
- * Euclidean case, the matrix contains a scale factor and a translation. Here, the matrix contains
- * a scale/negation factor that takes the values -1 or +1, and a rotation value. This restriction on
- * the allowed values in the matrix is required in order to fulfill the geometric requirements
- * of the {@link Transform} interface. For example, if arbitrary scaling is allowed, the point {@code 0.5pi}
- * could be scaled by 4 to {@code 2pi}, which is equivalent to {@code 0pi}. However, if the inverse scaling
- * of {@code 1/4} is applied to {@code 0pi}, the result is {@code 0pi} and not {@code 0.5pi}. This breaks
- * the {@link Transform} requirement that transforms be inversible.
- * </p>
- *
- * <p>Instances of this class are guaranteed to be immutable.</p>
- */
- public final class Transform1S implements Transform<Point1S> {
- /** Static instance representing the identity transform. */
- private static final Transform1S IDENTITY = new Transform1S(1, 0);
- /** Static instance that negates azimuth values. */
- private static final Transform1S NEGATION = new Transform1S(-1, 0);
- /** Value to scale the point azimuth by. This will only be +1/-1. */
- private final double scale;
- /** Value to rotate the point azimuth by. */
- private final double rotate;
- /** Construct a new instance from its transform components.
- * @param scale scale value for the transform; must only be +1 or -1
- * @param rotate rotation value
- */
- private Transform1S(final double scale, final double rotate) {
- this.scale = scale;
- this.rotate = rotate;
- }
- /** Return true if the transform negates the azimuth values of transformed
- * points, regardless of any rotation applied subsequently.
- * @return true if the transform negates the azimuth values of transformed
- * points
- * @see #preservesOrientation()
- */
- public boolean isNegation() {
- return scale <= 0;
- }
- /** Get the rotation value applied by this instance, in radians.
- * @return the rotation value applied by this instance, in radians.
- */
- public double getRotation() {
- return rotate;
- }
- /** {@inheritDoc} */
- @Override
- public Point1S apply(final Point1S pt) {
- final double az = pt.getAzimuth();
- final double resultAz = (az * scale) + rotate;
- return Point1S.of(resultAz);
- }
- /** {@inheritDoc} */
- @Override
- public boolean preservesOrientation() {
- return !isNegation();
- }
- /** Return a new transform created by pre-multiplying this instance by a transform
- * producing a rotation with the given angle.
- * @param angle angle to rotate, in radians
- * @return a new transform created by pre-multiplying this instance by a transform
- * producing a rotation with the given angle
- * @see #createRotation(double)
- */
- public Transform1S rotate(final double angle) {
- return premultiply(createRotation(angle));
- }
- /** Return a new transform created by pre-multiplying this instance by a transform
- * that negates azimuth values.
- * @return a new transform created by pre-multiplying this instance by a transform
- * that negates azimuth values
- */
- public Transform1S negate() {
- return premultiply(createNegation());
- }
- /** Multiply the underlying matrix of this instance by that of the argument, eg,
- * {@code other * this}. The returned transform performs the equivalent of
- * {@code other} followed by {@code this}.
- * @param other transform to multiply with
- * @return a new transform computed by multiplying the matrix of this
- * instance by that of the argument
- */
- public Transform1S multiply(final Transform1S other) {
- return multiply(this, other);
- }
- /** Multiply the underlying matrix of the argument by that of this instance, eg,
- * {@code this * other}. The returned transform performs the equivalent of {@code this}
- * followed by {@code other}.
- * @param other transform to multiply with
- * @return a new transform computed by multiplying the matrix of the
- * argument by that of this instance
- */
- public Transform1S premultiply(final Transform1S other) {
- return multiply(other, this);
- }
- /** {@inheritDoc} */
- @Override
- public Transform1S inverse() {
- final double invScale = 1.0 / scale;
- final double resultRotate = -(rotate * invScale);
- return new Transform1S(invScale, resultRotate);
- }
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = (result * prime) + Double.hashCode(scale);
- result = (result * prime) + Double.hashCode(rotate);
- return result;
- }
- /**
- * Return true if the given object is an instance of {@link Transform1S}
- * and all transform element values are exactly equal.
- * @param obj object to test for equality with the current instance
- * @return true if all transform elements are exactly equal; otherwise false
- */
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof Transform1S)) {
- return false;
- }
- final Transform1S other = (Transform1S) obj;
- return Double.compare(scale, other.scale) == 0 &&
- Double.compare(rotate, other.rotate) == 0;
- }
- /** {@inheritDoc} */
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder();
- sb.append(this.getClass().getSimpleName())
- .append("[negate= ")
- .append(isNegation())
- .append(", rotate= ")
- .append(getRotation())
- .append(']');
- return sb.toString();
- }
- /** Return a transform instance representing the identity transform.
- * @return a transform instance representing the identity transform
- */
- public static Transform1S identity() {
- return IDENTITY;
- }
- /** Return a transform instance that negates azimuth values.
- * @return a transform instance that negates azimuth values.
- */
- public static Transform1S createNegation() {
- return NEGATION;
- }
- /** Return a transform instance that performs a rotation with the given
- * angle.
- * @param angle angle of the rotation, in radians
- * @return a transform instance that performs a rotation with the given
- * angle
- */
- public static Transform1S createRotation(final double angle) {
- return new Transform1S(1, angle);
- }
- /** Multiply two transforms together as matrices.
- * @param a first transform
- * @param b second transform
- * @return the transform computed as {@code a x b}
- */
- private static Transform1S multiply(final Transform1S a, final Transform1S b) {
- // calculate the matrix elements
- final double resultScale = a.scale * b.scale;
- final double resultRotate = (a.scale * b.rotate) + a.rotate;
- return new Transform1S(resultScale, resultRotate);
- }
- }