View Javadoc
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  }