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 / primitive / Envelope3D.java @ 45943

History | View | Annotate | Download (9.03 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.fmap.geom.jts.primitive;
24

    
25
import com.vividsolutions.jts.geom.Coordinate;
26

    
27
import org.cresques.cts.ICoordTrans;
28
import org.cresques.cts.IProjection;
29

    
30
import org.gvsig.fmap.geom.jts.primitive.point.Point3D;
31
import org.gvsig.fmap.geom.primitive.Envelope;
32
import org.gvsig.fmap.geom.primitive.EnvelopeNotInitializedException;
33
import org.gvsig.fmap.geom.primitive.Point;
34
import org.gvsig.tools.ToolsLocator;
35
import org.gvsig.tools.dynobject.DynStruct;
36
import org.gvsig.tools.lang.Cloneable;
37
import org.gvsig.tools.persistence.PersistenceManager;
38

    
39
/**
40
 * @author <a href="mailto:jpiera@gvsig.org">Jorge Piera</a>
41
 */
42
public class Envelope3D extends DefaultEnvelope implements Cloneable {
43

    
44
    public static final String PERSISTENCE_DEFINITION_NAME = "Envelope3Dimensions";
45
    private static final int DIMENSION = 3;
46
    private boolean isZInitilized = false;
47

    
48
    public Envelope3D() {
49
        super();
50
    }
51

    
52
    public Envelope3D(IProjection projection) {
53
        super(projection);
54
    }
55

    
56
    public Envelope3D(Point min, Point max, IProjection projection) {
57
        super(min, max, projection);
58
    }
59

    
60
    /**
61
     * @param coordinates
62
     */
63
    public Envelope3D(Coordinate[] coordinates) {
64
        double minx = Double.POSITIVE_INFINITY;
65
        double miny = Double.POSITIVE_INFINITY;
66
        double minz = Double.POSITIVE_INFINITY;
67

    
68
        double maxx = Double.NEGATIVE_INFINITY;
69
        double maxy = Double.NEGATIVE_INFINITY;
70
        double maxz = Double.NEGATIVE_INFINITY;
71

    
72
        double x;
73
        double y;
74
        double z;
75

    
76
        for (int i = 0; i < coordinates.length; i++) {
77
            x = coordinates[i].x;
78
            y = coordinates[i].x;
79
            z = coordinates[i].x;
80
            minx = Math.min(x, minx);
81
            miny = Math.min(y, miny);
82
            minz = Math.min(z, minz);
83
            maxx = Math.max(x, maxx);
84
            maxy = Math.max(y, maxy);
85
            maxz = Math.max(z, maxz);
86
        }
87

    
88
        if (minx <= maxx && miny <= maxy && minz <= maxz) {
89
            min = new Point3D(minx, miny, minz);
90
            max = new Point3D(maxx, maxy, maxz);
91
            isEmpty = false;
92
        } else {
93
            isEmpty = true;
94
        }
95
    }
96

    
97
    /*
98
     * (non-Javadoc)
99
     *
100
     * @see org.gvsig.fmap.geom.primitive.Envelope#getDimension()
101
     */
102
    public int getDimension() {
103
        return DIMENSION;
104
    }
105

    
106
    /*
107
     * (non-Javadoc)
108
     *
109
     * @see
110
     * org.gvsig.fmap.geom.primitive.Envelope#convert(org.cresques.cts.ICoordTrans
111
     * )
112
     */
113
    public Envelope convert(ICoordTrans trans) {
114

    
115
        if (isEmpty) {
116
            throw new EnvelopeNotInitializedException();
117
        }
118

    
119
        if (trans == null) {
120
            // clone
121
            return new Envelope3D(this.getLowerCorner(), this.getUpperCorner(), this.projection);
122
        }
123

    
124
        // if (this.getDimension() > 2) {
125
        // return null;
126
        // }
127

    
128
        // We'll reproject by taking samples like this:
129
        //
130
        // *---*---*---*---*
131
        // | |
132
        // * * * * *
133
        // | |
134
        // * * * * *
135
        // | |
136
        // * * * * *
137
        // | |
138
        // *---*---*---*---*
139
        //
140
        // This is because:
141
        //
142
        // - In some CRS (for example EPSG:4326) the north/south pole is a
143
        // "line"
144
        // while in other CRS the north/south pole is a point, so if you
145
        // reproject the bounding box of the world, the result can be absurd.
146
        // - Sometimes the top/bottom/right/bottom of one envelope
147
        // corresponds to a strange point in the the other envelope
148
        // (not even a point in the perimeter)
149
        // - More generally, reprojecting usually implies a rotation (the result
150
        // is a rotated envelope) so it's better to use a few
151
        // samples along the perimeter.
152
        double xmin = getMinimum(0);
153
        double ymin = getMinimum(1);
154
        double step_w = 0.25 * (getMaximum(0) - xmin);
155
        double step_h = 0.25 * (getMaximum(1) - ymin);
156

    
157
        java.awt.geom.Point2D sample = null;
158
        java.awt.geom.Point2D sample_trans = null;
159
        // Init with worst values
160
        java.awt.geom.Point2D res_min = new java.awt.geom.Point2D.Double(Double.MAX_VALUE, Double.MAX_VALUE);
161
        java.awt.geom.Point2D res_max = new java.awt.geom.Point2D.Double(-Double.MAX_VALUE, -Double.MAX_VALUE);
162

    
163
        int added = 0;
164
        for (int i = 0; i < 5; i++) {
165
            for (int j = 0; j < 5; j++) {
166
                sample = new java.awt.geom.Point2D.Double(xmin + i * step_w, ymin + j * step_h);
167
                sample_trans = new java.awt.geom.Point2D.Double(0, 0);
168
                try {
169
                    sample_trans = trans.convert(sample, sample_trans);
170
                } catch (Exception exc) {
171
                    // Unable to convert this one: ignore
172
                    continue;
173
                }
174
                // Update max/min found
175
                // X
176
                if (sample_trans.getX() > res_max.getX()) {
177
                    res_max.setLocation(sample_trans.getX(), res_max.getY());
178
                }
179
                if (sample_trans.getX() < res_min.getX()) {
180
                    res_min.setLocation(sample_trans.getX(), res_min.getY());
181
                }
182
                // Y
183
                if (sample_trans.getY() > res_max.getY()) {
184
                    res_max.setLocation(res_max.getX(), sample_trans.getY());
185
                }
186
                if (sample_trans.getY() < res_min.getY()) {
187
                    res_min.setLocation(res_min.getX(), sample_trans.getY());
188
                }
189
                added++;
190
            }
191
        }
192

    
193
        if (added == 0) {
194
            // logger.error("Unable to reproject envelope with transf: " +
195
            // trans.toString());
196
            return null;
197
        }
198

    
199
        return new Envelope3D(
200
                new Point3D(res_min.getX(), res_min.getY(), this.min.getCoordinateAt(2)), 
201
                new Point3D(res_max.getX(), res_max.getY(), this.max.getCoordinateAt(2)),
202
        trans.getPDest());
203
    }
204

    
205
    public static void registerPersistent() {
206
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
207
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
208
            DynStruct definition =
209
                manager.addDefinition(Envelope3D.class, PERSISTENCE_DEFINITION_NAME,
210
                    "Envelope3D persistence definition", null, null);
211

    
212
            definition.extend(manager.getDefinition(DefaultEnvelope.PERSISTENCE_DEFINITION_NAME));
213
        }
214
    }
215

    
216
    public Object clone() throws CloneNotSupportedException {
217
        return super.clone();
218
    }
219

    
220
    private void createPoints() {
221
        this.min = new Point3D(0, 0, 0);
222
        this.max = new Point3D(0, 0, 0);
223
    }
224

    
225
    public void add(Envelope envelope) {
226
        int i;
227

    
228
        if (envelope == null || envelope.isEmpty()) {
229
            return;
230
        }
231

    
232
        int maxDimension = DIMENSION;
233

    
234
        if (envelope.getDimension() == 2) {
235
            maxDimension = 2;
236
        }
237

    
238
        if (this.isZInitilized) {
239
            for (i = 0; i < maxDimension; i++) {
240
                this.min.setCoordinateAt(i, Math.min(this.min.getCoordinateAt(i), envelope.getMinimum(i)));
241
                this.max.setCoordinateAt(i, Math.max(this.max.getCoordinateAt(i), envelope.getMaximum(i)));
242
            }
243
            return;
244
        }
245

    
246
        if (isEmpty) {
247
            createPoints();
248
            if (maxDimension == 3) {
249
                this.isZInitilized = true;
250
            }
251
            for (i = 0; i < maxDimension; i++) {
252
                this.min.setCoordinateAt(i, envelope.getMinimum(i));
253
                this.max.setCoordinateAt(i, envelope.getMaximum(i));
254
            }
255
            isEmpty = false;
256
        } else {
257
            if (maxDimension == DIMENSION) {
258
                this.min.setCoordinateAt(2, envelope.getMinimum(2));
259
                this.max.setCoordinateAt(2, envelope.getMaximum(2));
260
                this.isZInitilized = true;
261
            }
262
            for (i = 0; i < maxDimension; i++) {
263
                this.min.setCoordinateAt(i, Math.min(this.min.getCoordinateAt(i), envelope.getMinimum(i)));
264
                this.max.setCoordinateAt(i, Math.max(this.max.getCoordinateAt(i), envelope.getMaximum(i)));
265
            }
266
        }
267
    }
268
}