1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.geometry.core; 18 19 import java.util.function.UnaryOperator; 20 21 /** Interface representing geometric transforms in a space, i.e. mappings from points to points. 22 * Implementations <em>must</em> fulfill a set of requirements, listed below, that preserve the 23 * consistency of partitionings on the space. Transforms that do not meet these requirements, while 24 * potentially valid mathematically, cannot be expected to produce correct results with algorithms 25 * that use this interface. 26 * 27 * <ol> 28 * <li>Transforms must represent functions that are <em>one-to-one</em> and <em>onto</em> (i.e. 29 * <a href="https://en.wikipedia.org/wiki/Bijection">bijections</a>). This means that every point 30 * in the space must be mapped to exactly one other point in the space. This also implies that the 31 * function is invertible.</li> 32 * <li>Transforms must preserve <a href="https://en.wikipedia.org/wiki/Collinearity">collinearity</a>. 33 * This means that if a set of points lie on a common hyperplane before the transform, then they must 34 * also lie on a common hyperplane after the transform. For example, if the Euclidean 2D points {@code a}, 35 * {@code b}, and {@code c} lie on line {@code L}, then the transformed points {@code a'}, {@code b'}, and 36 * {@code c'} must lie on line {@code L'}, where {@code L'} is the transformed form of the line.</li> 37 * <li>Transforms must preserve the concept of 38 * <a href="https://en.wikipedia.org/wiki/Parallel_(geometry)">parallelism</a> defined for the space. 39 * This means that hyperplanes that are parallel before the transformation must remain parallel afterwards, 40 * and hyperplanes that intersect must also intersect afterwards. For example, a transform that causes parallel 41 * lines to converge to a single point in Euclidean space (such as the projective transforms used to create 42 * perspective viewpoints in 3D graphics) would not meet this requirement. However, a transform that turns 43 * a square into a rhombus with no right angles would fulfill the requirement, since the two pairs of parallel 44 * lines forming the square remain parallel after the transformation. 45 * </li> 46 * </ol> 47 * 48 * <p>Transforms that meet the above requirements in Euclidean space (and other affine spaces) are known as 49 * <a href="https://en.wikipedia.org/wiki/Affine_transformation">affine transforms</a>. Common affine transforms 50 * include translation, scaling, rotation, reflection, and any compositions thereof. 51 * </p> 52 * 53 * @param <P> Point implementation type 54 * @see <a href="https://en.wikipedia.org/wiki/Geometric_transformation">Geometric Transformation</a> 55 */ 56 public interface Transform<P extends Point<P>> extends UnaryOperator<P> { 57 58 /** Get an instance representing the inverse transform. 59 * @return an instance representing the inverse transform 60 */ 61 Transform<P> inverse(); 62 63 /** Return true if the transform preserves the orientation of the space. 64 * For example, in Euclidean 2D space, this will be true for translations, 65 * rotations, and scalings but will be false for reflections. 66 * @return true if the transform preserves the orientation of the space 67 * @see <a href="https://en.wikipedia.org/wiki/Orientation_(vector_space)">Orientation</a> 68 */ 69 boolean preservesOrientation(); 70 }