View Javadoc
1   /*
2    * @file
3    * This file contains implementation of
4    * com.irurueta.geometry.Transformation2D
5    *
6    * @author Alberto Irurueta (alberto@irurueta.com)
7    * @date October 25, 2012
8    */
9   package com.irurueta.geometry;
10  
11  import com.irurueta.algebra.AlgebraException;
12  import com.irurueta.algebra.Matrix;
13  
14  import java.util.ArrayList;
15  import java.util.List;
16  
17  /**
18   * This class performs transformations on 2D space.
19   * Transformations can be applied to any 2D geometric figure.
20   */
21  public abstract class Transformation2D {
22  
23      /**
24       * Empty constructor.
25       */
26      protected Transformation2D() {
27      }
28  
29      /**
30       * Transforms provided point using this transformation.
31       *
32       * @param inputPoint point to be transformed.
33       * @return transformed point.
34       */
35      public Point2D transformAndReturnNew(final Point2D inputPoint) {
36          final var outputPoint = Point2D.create();
37          transform(inputPoint, outputPoint);
38          return outputPoint;
39      }
40  
41      /**
42       * Transforms and updates provided point.
43       *
44       * @param point point to be transformed and updated.
45       */
46      public void transform(final Point2D point) {
47          transform(point, point);
48      }
49  
50      /**
51       * Transforms input point using this transformation and stores the result in
52       * provided output points.
53       *
54       * @param inputPoint  point to be transformed.
55       * @param outputPoint instance where transformed point data will be stored.
56       */
57      public abstract void transform(final Point2D inputPoint, final Point2D outputPoint);
58  
59      /**
60       * Transforms provided list of points using this transformation and returns
61       * a new one.
62       *
63       * @param inputPoints points to be transformed.
64       * @return transformed points.
65       */
66      public List<Point2D> transformPointsAndReturnNew(final List<Point2D> inputPoints) {
67          final var outputPoints = new ArrayList<Point2D>(inputPoints.size());
68          transformPoints(inputPoints, outputPoints);
69          return outputPoints;
70      }
71  
72      /**
73       * Transforms provided list of points using this transformation and stores
74       * the result in provided output list of points.
75       * Notice that any previous content in output list will be removed when
76       * calling this method.
77       *
78       * @param inputPoints  points to be transformed.
79       * @param outputPoints transformed points.
80       */
81      public void transformPoints(final List<Point2D> inputPoints, final List<Point2D> outputPoints) {
82  
83          outputPoints.clear();
84          for (final var point : inputPoints) {
85              outputPoints.add(Transformation2D.this.transformAndReturnNew(point));
86          }
87      }
88  
89      /**
90       * Transforms provided list of points using this transformation and
91       * overwriting their previous values.
92       *
93       * @param points points to be transformed and overwritten.
94       */
95      public void transformAndOverwritePoints(final List<Point2D> points) {
96          for (final var point : points) {
97              transform(point, point);
98          }
99      }
100 
101     /**
102      * Transforms a conic using this transformation and returns a new one.
103      *
104      * @param inputConic conic to be transformed.
105      * @return transformed conic.
106      * @throws NonSymmetricMatrixException raised if due to numerical precision
107      *                                     the resulting output conic matrix is not considered to be symmetric.
108      * @throws AlgebraException            raised if transform cannot be computed because of
109      *                                     numerical instabilities.
110      */
111     public Conic transformAndReturnNew(final Conic inputConic) throws NonSymmetricMatrixException, AlgebraException {
112         final var outputConic = new Conic();
113         transform(inputConic, outputConic);
114         return outputConic;
115     }
116 
117     /**
118      * Transforms and updates provided conic.
119      *
120      * @param conic conic to be transformed.
121      * @throws NonSymmetricMatrixException raised if due to numerical precision
122      *                                     the resulting conic matrix is not considered to be symmetric.
123      * @throws AlgebraException            raised if transform cannot be computed because of
124      *                                     numerical instabilities.
125      */
126     public void transform(final Conic conic) throws NonSymmetricMatrixException, AlgebraException {
127         transform(conic, conic);
128     }
129 
130     /**
131      * Transforms a conic using this transformation and stores the result into
132      * provided output conic.
133      *
134      * @param inputConic  conic to be transformed.
135      * @param outputConic instance where data of transformed conic will be
136      *                    stored.
137      * @throws NonSymmetricMatrixException raised if due to numerical precision
138      *                                     the resulting output conic matrix is not considered to be symmetric.
139      * @throws AlgebraException            raised if transform cannot be computed because of
140      *                                     numerical instabilities.
141      */
142     public abstract void transform(final Conic inputConic, final Conic outputConic) throws NonSymmetricMatrixException,
143             AlgebraException;
144 
145     /**
146      * Transforms a dual conic using this transformation and returns a new one.
147      *
148      * @param inputDualConic dual conic to be transformed.
149      * @return transformed dual conic.
150      * @throws NonSymmetricMatrixException raised if due to numerical precision
151      *                                     the resulting output conic matrix is not considered to be symmetric.
152      * @throws AlgebraException            raised if transform cannot be computed because
153      *                                     of numerical instabilities.
154      */
155     public DualConic transformAndReturnNew(final DualConic inputDualConic) throws NonSymmetricMatrixException,
156             AlgebraException {
157         final var outputDualConic = new DualConic();
158         transform(inputDualConic, outputDualConic);
159         return outputDualConic;
160     }
161 
162     /**
163      * Transforms and updates a dual conic using this transformation.
164      *
165      * @param dualConic dual conic to be transformed.
166      * @throws NonSymmetricMatrixException raised if due to numerical precision
167      *                                     the resulting conic matrix is not considered to be symmetric.
168      * @throws AlgebraException            raised if transform cannot be computed because
169      *                                     of numerical instabilities.
170      */
171     public void transform(final DualConic dualConic) throws NonSymmetricMatrixException, AlgebraException {
172         transform(dualConic, dualConic);
173     }
174 
175     /**
176      * Transforms a dual conic using this transformation and stores the result
177      * into provided output dual conic.
178      *
179      * @param inputDualConic  dual conic to be transformed.
180      * @param outputDualConic instance where data of transformed dual conic will
181      *                        be stored.
182      * @throws NonSymmetricMatrixException raised if due to numerical precision
183      *                                     the resulting output dual conic matrix is not considered to be symmetric.
184      * @throws AlgebraException            Raised if transform cannot be computed because
185      *                                     of numerical instabilities.
186      */
187     public abstract void transform(final DualConic inputDualConic, final DualConic outputDualConic)
188             throws NonSymmetricMatrixException, AlgebraException;
189 
190     /**
191      * Transforms provided line using this transformation and returns a new one.
192      *
193      * @param inputLine line to be transformed.
194      * @return transformed line.
195      * @throws AlgebraException raised if transform cannot be computed because
196      *                          of numerical instabilities.
197      */
198     public Line2D transformAndReturnNew(final Line2D inputLine) throws AlgebraException {
199         final var outputLine = new Line2D();
200         transform(inputLine, outputLine);
201         return outputLine;
202     }
203 
204     /**
205      * Transforms and updates provided line using this transformation.
206      *
207      * @param line line to be transformed and updated.
208      * @throws AlgebraException if transform cannot be computed because of
209      *                          numerical instabilities.
210      */
211     public void transform(final Line2D line) throws AlgebraException {
212         transform(line, line);
213     }
214 
215     /**
216      * Transforms provided input line using this transformation and stores the
217      * result into provided output line instance.
218      *
219      * @param inputLine  line to be transformed.
220      * @param outputLine instance where data of transformed line will be stored.
221      * @throws AlgebraException Raised if transform cannot be computed because
222      *                          of numerical instabilities.
223      */
224     public abstract void transform(final Line2D inputLine, final Line2D outputLine) throws AlgebraException;
225 
226     /**
227      * Transforms provided list of lines using this transformation and returns
228      * a new one.
229      *
230      * @param inputLines lines to be transformed.
231      * @return transformed lines.
232      * @throws AlgebraException raised if transform cannot be computed because
233      *                          of numerical instabilities.
234      */
235     public List<Line2D> transformLinesAndReturnNew(final List<Line2D> inputLines) throws AlgebraException {
236         final var outputLines = new ArrayList<Line2D>(inputLines.size());
237         transformLines(inputLines, outputLines);
238         return outputLines;
239     }
240 
241     /**
242      * Transforms provided list of lines using this transformation and stores
243      * the result in provided output list of lines.
244      * Notice that any previous content in output list will be removed when
245      * calling this method.
246      *
247      * @param inputLines  lines to be transformed.
248      * @param outputLines transformed lines.
249      * @throws AlgebraException raised if transform cannot be computed because
250      *                          of numerical instabilities.
251      */
252     public void transformLines(final List<Line2D> inputLines, final List<Line2D> outputLines) throws AlgebraException {
253         outputLines.clear();
254         for (final var line : inputLines) {
255             outputLines.add(Transformation2D.this.transformAndReturnNew(line));
256         }
257     }
258 
259     /**
260      * Transforms provided list of lines using this transformation and
261      * overwriting their previous values.
262      *
263      * @param lines lines to be transformed and overwritten.
264      * @throws AlgebraException raised if transform cannot be computed because
265      *                          of numerical instabilities.
266      */
267     public void transformAndOverwriteLines(final List<Line2D> lines) throws AlgebraException {
268         for (final var line : lines) {
269             transform(line, line);
270         }
271     }
272 
273     /**
274      * Transforms provided polygon using this transformation and returns a new
275      * one.
276      *
277      * @param inputPolygon polygon to be transformed.
278      * @return Transformed polygon.
279      */
280     public Polygon2D transformAndReturnNew(final Polygon2D inputPolygon) {
281         final var outVertices = transformPointsAndReturnNew(inputPolygon.getVertices());
282         try {
283             return new Polygon2D(outVertices);
284         } catch (final NotEnoughVerticesException ignore) {
285             // this will never happen because all existing polygons have enough
286             // vertices
287             return null;
288         }
289     }
290 
291     /**
292      * Transforms and updates provided polygon using this transformation.
293      *
294      * @param polygon polygon to be transformed.
295      */
296     public void transform(final Polygon2D polygon) {
297         transformAndOverwritePoints(polygon.getVertices());
298     }
299 
300     /**
301      * Transforms provided input polygon using this transformation and stores
302      * the result into provided output polygon instance.
303      *
304      * @param inputPolygon  polygon to be transformed.
305      * @param outputPolygon instance where transformed polygon data will be
306      *                      stored.
307      */
308     public void transform(final Polygon2D inputPolygon, final Polygon2D outputPolygon) {
309         try {
310             outputPolygon.setVertices(transformPointsAndReturnNew(inputPolygon.getVertices()));
311         } catch (final NotEnoughVerticesException ignore) {
312             // this will never happen because all existing polygons have enough
313             // vertices
314         }
315     }
316 
317     /**
318      * Transforms provided triangle using this transformation and returns a new
319      * one.
320      *
321      * @param inputTriangle triangle to be transformed.
322      * @return transformed triangle.
323      */
324     public Triangle2D transformAndReturnNew(final Triangle2D inputTriangle) {
325         final var vertex1 = Transformation2D.this.transformAndReturnNew(inputTriangle.getVertex1());
326         final var vertex2 = Transformation2D.this.transformAndReturnNew(inputTriangle.getVertex2());
327         final var vertex3 = Transformation2D.this.transformAndReturnNew(inputTriangle.getVertex3());
328         return new Triangle2D(vertex1, vertex2, vertex3);
329     }
330 
331     /**
332      * Transforms and updates provided input triangle using this transformation.
333      *
334      * @param triangle triangle to be transformed.
335      */
336     public void transform(final Triangle2D triangle) {
337         transform(triangle, triangle);
338     }
339 
340     /**
341      * Transforms provided input triangle using this transformation and stores
342      * the result into provided output triangle instance.
343      *
344      * @param inputTriangle  triangle to be transformed.
345      * @param outputTriangle instance where transformed triangle data will be
346      *                       stored
347      */
348     public void transform(final Triangle2D inputTriangle, final Triangle2D outputTriangle) {
349         outputTriangle.setVertex1(transformAndReturnNew(inputTriangle.getVertex1()));
350         outputTriangle.setVertex2(transformAndReturnNew(inputTriangle.getVertex2()));
351         outputTriangle.setVertex3(transformAndReturnNew(inputTriangle.getVertex3()));
352     }
353 
354     /**
355      * Represents this transformation as a 3x3 matrix.
356      * A point can be transformed as T * p, where T is the transformation matrix
357      * and p is a point expressed as an homogeneous vector.
358      *
359      * @return This transformation in matrix form.
360      */
361     public abstract Matrix asMatrix();
362 
363     /**
364      * Represents this transformation as a 3x3 matrix and stores the result in
365      * provided instance.
366      *
367      * @param m Instance where transformation matrix will be stored.
368      * @throws IllegalArgumentException Raised if provided instance is not a 3x3
369      *                                  matrix.
370      */
371     public abstract void asMatrix(final Matrix m);
372 }