Statistics
| Revision:

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
}