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 }