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.euclidean; 18 19 /** Base class for affine transform matrices in Euclidean space. 20 * 21 * @param <V> Vector/point implementation type defining the space. 22 * @param <M> Matrix transform implementation type. 23 */ 24 public abstract class AbstractAffineTransformMatrix< 25 V extends EuclideanVector<V>, 26 M extends AbstractAffineTransformMatrix<V, M>> 27 implements EuclideanTransform<V> { 28 29 /** Apply this transform to the given vector, ignoring translations and normalizing the 30 * result. This is equivalent to {@code transform.applyVector(vec).normalize()} but without 31 * the intermediate vector instance. 32 * 33 * @param vec the vector to transform 34 * @return the new, transformed unit vector 35 * @throws IllegalArgumentException if the transformed vector coordinates cannot be normalized 36 * @see #applyVector(EuclideanVector) 37 */ 38 public abstract V applyDirection(V vec); 39 40 /** Get the determinant of the matrix. 41 * @return the determinant of the matrix 42 */ 43 public abstract double determinant(); 44 45 /** {@inheritDoc} 46 * @throws IllegalStateException if the matrix cannot be inverted 47 */ 48 @Override 49 public abstract M inverse(); 50 51 /** Return a matrix containing only the linear portion of this transform. 52 * The returned instance contains the same matrix elements as this instance 53 * but with the translation component set to zero. 54 * @return a matrix containing only the linear portion of this transform 55 */ 56 public abstract M linear(); 57 58 /** Return a matrix containing the transpose of the linear portion of this transform. 59 * The returned instance is linear, meaning it has a translation component of zero. 60 * @return a matrix containing the transpose of the linear portion of this transform 61 */ 62 public abstract M linearTranspose(); 63 64 /** Return a transform suitable for transforming normals. The returned matrix is 65 * the inverse transpose of the linear portion of this instance, i.e. 66 * <code>N = (L<sup>-1</sup>)<sup>T</sup></code>, where <code>L</code> is the linear portion 67 * of this instance and <code>N</code> is the returned matrix. Note that normals 68 * transformed with the returned matrix may be scaled during transformation and require 69 * normalization. 70 * @return a transform suitable for transforming normals 71 * @throws IllegalStateException if the matrix cannot be inverted 72 * @see <a href="https://en.wikipedia.org/wiki/Normal_(geometry)#Transforming_normals">Transforming normals</a> 73 */ 74 public M normalTransform() { 75 return inverse().linearTranspose(); 76 } 77 78 /** {@inheritDoc} 79 * 80 * <p>This method returns true if the determinant of the matrix is positive.</p> 81 */ 82 @Override 83 public boolean preservesOrientation() { 84 return determinant() > 0.0; 85 } 86 }