svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.geometry / org.gvsig.fmap.geometry.jts / src / main / java / org / gvsig / fmap / geom / jts / transform / Transform3D.java @ 42775
History | View | Annotate | Download (11.2 KB)
1 |
package org.gvsig.fmap.geom.jts.transform; |
---|---|
2 |
|
3 |
import org.gvsig.fmap.geom.Geometry; |
4 |
import org.gvsig.fmap.geom.GeometryLocator; |
5 |
import org.gvsig.fmap.geom.exception.CreateGeometryException; |
6 |
import org.gvsig.fmap.geom.jts.primitive.point.Point3D; |
7 |
import org.gvsig.fmap.geom.primitive.Point; |
8 |
import org.gvsig.fmap.geom.transform.Transform; |
9 |
|
10 |
public class Transform3D implements Transform { |
11 |
|
12 |
/**
|
13 |
* The constant used for testing results.
|
14 |
*/
|
15 |
public final static double ACCURACY = 1e-12; |
16 |
|
17 |
/**
|
18 |
* coefficients for x coordinate.
|
19 |
*/
|
20 |
protected double m00, m01, m02, m03; |
21 |
|
22 |
/**
|
23 |
* coefficients for y coordinate.
|
24 |
*/
|
25 |
protected double m10, m11, m12, m13; |
26 |
|
27 |
/**
|
28 |
* coefficients for z coordinate.
|
29 |
*/
|
30 |
protected double m20, m21, m22, m23; |
31 |
|
32 |
public Transform3D() {
|
33 |
// init to identity matrix
|
34 |
m00 = m11 = m22 = 1;
|
35 |
m01 = m02 = m03 = 0;
|
36 |
m10 = m12 = m13 = 0;
|
37 |
m20 = m21 = m23 = 0;
|
38 |
} |
39 |
|
40 |
public Transform3D(double[] coefs) { |
41 |
if (coefs.length == 9) { |
42 |
m00 = coefs[0];
|
43 |
m01 = coefs[1];
|
44 |
m02 = coefs[2];
|
45 |
m10 = coefs[3];
|
46 |
m11 = coefs[4];
|
47 |
m12 = coefs[5];
|
48 |
m20 = coefs[6];
|
49 |
m21 = coefs[7];
|
50 |
m22 = coefs[8];
|
51 |
} else if (coefs.length == 12) { |
52 |
m00 = coefs[0];
|
53 |
m01 = coefs[1];
|
54 |
m02 = coefs[2];
|
55 |
m03 = coefs[3];
|
56 |
m10 = coefs[4];
|
57 |
m11 = coefs[5];
|
58 |
m12 = coefs[6];
|
59 |
m13 = coefs[7];
|
60 |
m20 = coefs[8];
|
61 |
m21 = coefs[9];
|
62 |
m22 = coefs[10];
|
63 |
m23 = coefs[11];
|
64 |
} else {
|
65 |
throw new IllegalArgumentException( |
66 |
"Input array must have 9 or 12 elements");
|
67 |
} |
68 |
} |
69 |
|
70 |
public Transform3D(double xx, double yx, double zx, double tx, |
71 |
double xy, double yy, double zy, double ty, double xz, double yz, |
72 |
double zz, double tz) { |
73 |
m00 = xx; |
74 |
m01 = yx; |
75 |
m02 = zx; |
76 |
m03 = tx; |
77 |
m10 = xy; |
78 |
m11 = yy; |
79 |
m12 = zy; |
80 |
m13 = ty; |
81 |
m20 = xz; |
82 |
m21 = yz; |
83 |
m22 = zz; |
84 |
m23 = tz; |
85 |
} |
86 |
|
87 |
private Point createPoint3D(double x, double y, double z) { |
88 |
try {
|
89 |
Point point = GeometryLocator.getGeometryManager().createPoint(x, y, Geometry.SUBTYPES.GEOM2D);
|
90 |
point.setCoordinateAt(Geometry.DIMENSIONS.Z, z); |
91 |
return point;
|
92 |
} catch (CreateGeometryException ex) {
|
93 |
throw new RuntimeException("Can't create Point3D", ex); |
94 |
} |
95 |
} |
96 |
// ===================================================================
|
97 |
// accessors
|
98 |
|
99 |
public boolean isIdentity() { |
100 |
if (m00 != 1) { |
101 |
return false; |
102 |
} |
103 |
if (m11 != 1) { |
104 |
return false; |
105 |
} |
106 |
if (m22 != 0) { |
107 |
return false; |
108 |
} |
109 |
if (m01 != 0) { |
110 |
return false; |
111 |
} |
112 |
if (m02 != 0) { |
113 |
return false; |
114 |
} |
115 |
if (m03 != 0) { |
116 |
return false; |
117 |
} |
118 |
if (m10 != 0) { |
119 |
return false; |
120 |
} |
121 |
if (m12 != 0) { |
122 |
return false; |
123 |
} |
124 |
if (m13 != 0) { |
125 |
return false; |
126 |
} |
127 |
if (m20 != 0) { |
128 |
return false; |
129 |
} |
130 |
if (m21 != 0) { |
131 |
return false; |
132 |
} |
133 |
if (m23 != 0) { |
134 |
return false; |
135 |
} |
136 |
return true; |
137 |
} |
138 |
|
139 |
/**
|
140 |
* Returns the affine coefficients of the transform. Result is an array of
|
141 |
* 12 double.
|
142 |
*/
|
143 |
public double[] coefficients() { |
144 |
double[] tab = {m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23}; |
145 |
return tab;
|
146 |
} |
147 |
|
148 |
/**
|
149 |
* Computes the determinant of this transform. Can be zero.
|
150 |
*
|
151 |
* @return the determinant of the transform.
|
152 |
*/
|
153 |
private double determinant() { |
154 |
return m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m20 * m12)
|
155 |
+ m02 * (m10 * m21 - m20 * m11); |
156 |
} |
157 |
|
158 |
/**
|
159 |
* Computes the inverse affine transform.
|
160 |
*/
|
161 |
public Transform3D inverse() {
|
162 |
double det = this.determinant(); |
163 |
return new Transform3D( |
164 |
(m11 * m22 - m21 * m12) / det, |
165 |
(m21 * m02 - m01 * m22) / det, |
166 |
(m01 * m12 - m11 * m02) / det, |
167 |
(m01 * (m22 * m13 - m12 * m23) + m02 * (m11 * m23 - m21 * m13) |
168 |
- m03 * (m11 * m22 - m21 * m12)) / det, |
169 |
(m20 * m12 - m10 * m22) / det, |
170 |
(m00 * m22 - m20 * m02) / det, |
171 |
(m10 * m02 - m00 * m12) / det, |
172 |
(m00 * (m12 * m23 - m22 * m13) - m02 * (m10 * m23 - m20 * m13) |
173 |
+ m03 * (m10 * m22 - m20 * m12)) / det, |
174 |
(m10 * m21 - m20 * m11) / det, |
175 |
(m20 * m01 - m00 * m21) / det, |
176 |
(m00 * m11 - m10 * m01) / det, |
177 |
(m00 * (m21 * m13 - m11 * m23) + m01 * (m10 * m23 - m20 * m13) |
178 |
- m03 * (m10 * m21 - m20 * m11)) / det); |
179 |
} |
180 |
|
181 |
// ===================================================================
|
182 |
// general methods
|
183 |
/**
|
184 |
* Returns the affine transform created by applying first the affine
|
185 |
* transform given by <code>that</code>, then this affine transform.
|
186 |
*
|
187 |
* @param that the transform to apply first
|
188 |
* @return the composition this * that
|
189 |
*/
|
190 |
public Transform concatenate(Transform other) {
|
191 |
if (!(other instanceof Transform3D)) { |
192 |
throw new IllegalArgumentException("Can't concatenate an AffineTransform3D with a non AffineTransform2D (other " + other.toString() + ")"); |
193 |
} |
194 |
Transform3D that = (Transform3D) other; |
195 |
double n00 = m00 * that.m00 + m01 * that.m10 + m02 * that.m20;
|
196 |
double n01 = m00 * that.m01 + m01 * that.m11 + m02 * that.m21;
|
197 |
double n02 = m00 * that.m02 + m01 * that.m12 + m02 * that.m22;
|
198 |
double n03 = m00 * that.m03 + m01 * that.m13 + m02 * that.m23 + m03;
|
199 |
double n10 = m10 * that.m00 + m11 * that.m10 + m12 * that.m20;
|
200 |
double n11 = m10 * that.m01 + m11 * that.m11 + m12 * that.m21;
|
201 |
double n12 = m10 * that.m02 + m11 * that.m12 + m12 * that.m22;
|
202 |
double n13 = m10 * that.m03 + m11 * that.m13 + m12 * that.m23 + m13;
|
203 |
double n20 = m20 * that.m00 + m21 * that.m10 + m22 * that.m20;
|
204 |
double n21 = m20 * that.m01 + m21 * that.m11 + m22 * that.m21;
|
205 |
double n22 = m20 * that.m02 + m21 * that.m12 + m22 * that.m22;
|
206 |
double n23 = m20 * that.m03 + m21 * that.m13 + m22 * that.m23 + m23;
|
207 |
return new Transform3D( |
208 |
n00, n01, n02, n03, |
209 |
n10, n11, n12, n13, |
210 |
n20, n21, n22, n23); |
211 |
} |
212 |
|
213 |
/**
|
214 |
* Return the affine transform created by applying first this affine
|
215 |
* transform, then the affine transform given by <code>that</code>.
|
216 |
*
|
217 |
* @param other the transform to apply in a second step
|
218 |
* @return the composition that * this
|
219 |
*/
|
220 |
public Transform3D preConcatenate(Transform other) {
|
221 |
if (!(other instanceof Transform3D)) { |
222 |
throw new IllegalArgumentException("Can't concatenate an AffineTransform3D with a non AffineTransform3D (other " + other.toString() + ")"); |
223 |
} |
224 |
Transform3D that = (Transform3D) other; |
225 |
double n00 = that.m00 * m00 + that.m01 * m10 + that.m02 * m20;
|
226 |
double n01 = that.m00 * m01 + that.m01 * m11 + that.m02 * m21;
|
227 |
double n02 = that.m00 * m02 + that.m01 * m12 + that.m02 * m22;
|
228 |
double n03 = that.m00 * m03 + that.m01 * m13 + that.m02 * m23 + that.m03;
|
229 |
double n10 = that.m10 * m00 + that.m11 * m10 + that.m12 * m20;
|
230 |
double n11 = that.m10 * m01 + that.m11 * m11 + that.m12 * m21;
|
231 |
double n12 = that.m10 * m02 + that.m11 * m12 + that.m12 * m22;
|
232 |
double n13 = that.m10 * m03 + that.m11 * m13 + that.m12 * m23 + that.m13;
|
233 |
double n20 = that.m20 * m00 + that.m21 * m10 + that.m22 * m20;
|
234 |
double n21 = that.m20 * m01 + that.m21 * m11 + that.m22 * m21;
|
235 |
double n22 = that.m20 * m02 + that.m21 * m12 + that.m22 * m22;
|
236 |
double n23 = that.m20 * m03 + that.m21 * m13 + that.m22 * m23 + that.m23;
|
237 |
return new Transform3D( |
238 |
n00, n01, n02, n03, |
239 |
n10, n11, n12, n13, |
240 |
n20, n21, n22, n23); |
241 |
} |
242 |
|
243 |
/**
|
244 |
* Transforms the input point array, stores the result in the pre-allocated
|
245 |
* array, and returns a pointer to the result array. A new array is created
|
246 |
* if <code>res</code> is null or has length smaller than of src.
|
247 |
*
|
248 |
* @param src
|
249 |
* @param dst
|
250 |
* @return
|
251 |
*/
|
252 |
@Override
|
253 |
public Point[] transform(Point[] src, Point[] dst) { |
254 |
// Check validity of result array
|
255 |
if (dst == null || dst.length < src.length) { |
256 |
dst = new Point[src.length]; |
257 |
} |
258 |
|
259 |
// transform each input point
|
260 |
for (int i = 0; i < src.length; i++) { |
261 |
Point3D p = (Point3D) src[i]; |
262 |
dst[i] = createPoint3D( |
263 |
p.getX() * m00 + p.getY() * m01 + p.getZ() * m02 + m03, |
264 |
p.getX() * m10 + p.getY() * m11 + p.getZ() * m12 + m13, |
265 |
p.getX() * m20 + p.getY() * m21 + p.getZ() * m22 + m23); |
266 |
} |
267 |
return dst;
|
268 |
} |
269 |
|
270 |
/**
|
271 |
* Transforms the input point.
|
272 |
* @param src
|
273 |
* @return
|
274 |
*/
|
275 |
@Override
|
276 |
public Point transform(Point src) { |
277 |
Point3D p = (Point3D) src; |
278 |
return createPoint3D(
|
279 |
p.getX() * m00 + p.getY() * m01 + p.getZ() * m02 + m03, |
280 |
p.getX() * m10 + p.getY() * m11 + p.getZ() * m12 + m13, |
281 |
p.getX() * m20 + p.getY() * m21 + p.getZ() * m22 + m23); |
282 |
} |
283 |
|
284 |
/**
|
285 |
* Compares two transforms. Returns true if all inner fields are equal up to
|
286 |
* the precision given by Shape3D.ACCURACY.
|
287 |
*/
|
288 |
@Override
|
289 |
public boolean equals(Object obj) { |
290 |
if (!(obj instanceof Transform3D)) { |
291 |
return false; |
292 |
} |
293 |
|
294 |
double tab[] = ((Transform3D) obj).coefficients(); |
295 |
|
296 |
if (Math.abs(tab[0] - m00) > ACCURACY) { |
297 |
return false; |
298 |
} |
299 |
if (Math.abs(tab[1] - m01) > ACCURACY) { |
300 |
return false; |
301 |
} |
302 |
if (Math.abs(tab[2] - m02) > ACCURACY) { |
303 |
return false; |
304 |
} |
305 |
if (Math.abs(tab[3] - m03) > ACCURACY) { |
306 |
return false; |
307 |
} |
308 |
if (Math.abs(tab[4] - m10) > ACCURACY) { |
309 |
return false; |
310 |
} |
311 |
if (Math.abs(tab[5] - m11) > ACCURACY) { |
312 |
return false; |
313 |
} |
314 |
if (Math.abs(tab[6] - m12) > ACCURACY) { |
315 |
return false; |
316 |
} |
317 |
if (Math.abs(tab[7] - m13) > ACCURACY) { |
318 |
return false; |
319 |
} |
320 |
if (Math.abs(tab[8] - m20) > ACCURACY) { |
321 |
return false; |
322 |
} |
323 |
if (Math.abs(tab[9] - m21) > ACCURACY) { |
324 |
return false; |
325 |
} |
326 |
if (Math.abs(tab[10] - m22) > ACCURACY) { |
327 |
return false; |
328 |
} |
329 |
if (Math.abs(tab[11] - m23) > ACCURACY) { |
330 |
return false; |
331 |
} |
332 |
return true; |
333 |
} |
334 |
|
335 |
} |