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 / DefaultEnvelope.java @ 45941

History | View | Annotate | Download (15.2 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
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24

    
25
package org.gvsig.fmap.geom.jts.primitive;
26

    
27
import java.util.ArrayList;
28

    
29
import com.vividsolutions.jts.geom.Coordinate;
30
import org.cresques.cts.IProjection;
31

    
32
import org.slf4j.Logger;
33
import org.slf4j.LoggerFactory;
34

    
35
import org.gvsig.fmap.geom.Geometry;
36
import org.gvsig.fmap.geom.Geometry.DIMENSIONS;
37
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
38
import org.gvsig.fmap.geom.Geometry.TYPES;
39
import org.gvsig.fmap.geom.GeometryLocator;
40
import org.gvsig.fmap.geom.GeometryManager;
41
import org.gvsig.fmap.geom.exception.CreateGeometryException;
42
import org.gvsig.fmap.geom.jts.GeometryJTS;
43
import org.gvsig.fmap.geom.jts.util.ArrayListCoordinateSequence;
44
import org.gvsig.fmap.geom.jts.util.JTSUtils;
45
import org.gvsig.fmap.geom.primitive.Envelope;
46
import org.gvsig.fmap.geom.primitive.EnvelopeNotInitializedException;
47
import org.gvsig.fmap.geom.primitive.Line;
48
import org.gvsig.fmap.geom.primitive.Point;
49
import org.gvsig.fmap.geom.primitive.Polygon;
50
import org.gvsig.fmap.geom.primitive.Surface;
51
import org.gvsig.tools.ToolsLocator;
52
import org.gvsig.tools.dynobject.DynStruct;
53
import org.gvsig.tools.persistence.PersistenceManager;
54
import org.gvsig.tools.persistence.PersistentState;
55
import org.gvsig.tools.persistence.exception.PersistenceException;
56

    
57

    
58
/**
59
 * A minimum bounding box or rectangle. Regardless of dimension, an Envelope
60
 * can be represented without ambiguity as two direct positions (coordinate
61
 * points). To encode an Envelope, it is sufficient to encode these two
62
 * points. This is consistent with all of the data types in this
63
 * specification, their state is represented by their publicly accessible
64
 * attributes.
65

66
 * @author Vicente Caballero Navarro
67
 */
68
@SuppressWarnings("UseSpecificCatch")
69
public abstract class DefaultEnvelope implements Envelope, org.gvsig.tools.lang.Cloneable{
70
    private static final Logger LOG =
71
        LoggerFactory.getLogger(DefaultEnvelope.class);
72

    
73
    public static final String PERSISTENCE_DEFINITION_NAME = "Envelope";
74

    
75
    protected static final String LOWERCORNER_FIELD = "lowerCorner";
76
    protected static final String UPPERCORNER_FIELD = "upperCorner";
77

    
78
    protected Point min;
79
    protected Point max;
80

    
81
    protected boolean isEmpty;
82

    
83
    protected IProjection projection;
84

    
85
    private com.vividsolutions.jts.geom.Polygon jtsGeom = null;
86

    
87
    protected static GeometryManager manager = GeometryLocator.getGeometryManager();
88

    
89
    public DefaultEnvelope(){
90
        super();
91
        isEmpty = true;
92
    }
93

    
94
    public DefaultEnvelope(Point min, Point max){
95
        super();
96
        this.min = min;
97
        this.max = max;
98
        isEmpty = false;
99
    }
100

    
101
    public String toString() {
102
        if( this.isEmpty ) {
103
            return "POLYGON()";
104
        }
105
        // Para el 3D estaria mal ya que probablemente habria que devolber un cubo.
106
        StringBuilder builder = new StringBuilder();
107
        builder.append("POLYGON ((");
108
        builder.append(this.min.getX());
109
        builder.append(" ");
110
        builder.append(this.min.getY());
111
        builder.append(", ");
112
        builder.append(this.min.getX());
113
        builder.append(" ");
114
        builder.append(this.max.getY());
115
        builder.append(", ");
116
        builder.append(this.max.getX());
117
        builder.append(" ");
118
        builder.append(this.max.getY());
119
        builder.append(", ");
120
        builder.append(this.max.getX());
121
        builder.append(" ");
122
        builder.append(this.min.getY());
123
        builder.append(", ");
124
        builder.append(this.min.getX());
125
        builder.append(" ");
126
        builder.append(this.min.getY());
127
        builder.append("))");
128
        return builder.toString();
129
    }
130

    
131
    /**
132
     * Returns the center ordinate along the specified dimension.
133
     *
134
     * @param dimension DOCUMENT ME!
135
     *
136
     * @return DOCUMENT ME!
137
     */
138
    public double getCenter(int dimension) {
139
        if (isEmpty){
140
            throw new EnvelopeNotInitializedException();
141
        }
142
        return (min.getCoordinateAt(dimension) + max.getCoordinateAt(dimension)) * 0.5;
143
    }
144

    
145
    /**
146
     * Returns the envelope length along the specified dimension.
147
     *
148
     * @param dimension
149
     *
150
     * @return
151
     */
152
    public double getLength(int dimension) {
153
        if (isEmpty){
154
            throw new EnvelopeNotInitializedException();
155
        }
156
        if (max.getCoordinateAt(dimension) > min.getCoordinateAt(dimension)) {
157
            return max.getCoordinateAt(dimension) - min.getCoordinateAt(dimension);
158
        }
159

    
160
        return min.getCoordinateAt(dimension) - max.getCoordinateAt(dimension);
161
    }
162

    
163
    /**
164
     * A coordinate position consisting of all the minimal ordinates for each
165
     * dimension for all points within the Envelope.
166
     *
167
     * @return
168
     */
169
    public Point getLowerCorner() {
170
        return min;
171
    }
172

    
173
    /**
174
     * Returns the maximal ordinate along the specified dimension.
175
     *
176
     * @param dimension
177
     *
178
     * @return
179
     */
180
    public double getMaximum(int dimension) {
181
        if (isEmpty){
182
            throw new EnvelopeNotInitializedException();
183
        }
184
        return max.getCoordinateAt(dimension);
185
    }
186

    
187
    /**
188
     * Returns the minimal ordinate along the specified dimension.
189
     *
190
     * @param dimension
191
     *
192
     * @return
193
     */
194
    public double getMinimum(int dimension) {
195
        if (isEmpty){
196
            throw new EnvelopeNotInitializedException();
197
        }
198
        return min.getCoordinateAt(dimension);
199
    }
200

    
201
    /**
202
     * A coordinate position consisting of all the maximal ordinates for each
203
     * dimension for all points within the Envelope.
204
     *
205
     * @return
206
     */
207
    public Point getUpperCorner() {
208
        return max;
209
    }
210

    
211

    
212

    
213
    public Geometry getGeometry() {
214
        if (isEmpty){
215
            throw new EnvelopeNotInitializedException();
216
        }
217
        try {
218
            // point?
219
            if (this.min.getX() == this.max.getX() && this.min.getY() == this.max.getY()) {
220
                Point point = this.min.clone();
221
                point.setProjection(projection);
222
                return point;
223
            }
224
            // vertical or horizontal line?
225
            if (this.min.getX() == this.max.getX() ||
226
                this.min.getY() == this.max.getY()) {
227
                Line line = manager.createLine(SUBTYPES.GEOM2D);
228
                line.addVertex(min.clone());
229
                line.addVertex(max.clone());
230
                line.setProjection(projection);
231
                return line;
232
            }
233
            Polygon polygon = manager.createPolygon(SUBTYPES.GEOM2D);
234
            polygon.addVertex(min.clone());
235
            polygon.addVertex(manager.createPoint(getMaximum(0),getMinimum(1), SUBTYPES.GEOM2D));
236
            polygon.addVertex(max.clone());
237
            polygon.addVertex(manager.createPoint(getMinimum(0),getMaximum(1), SUBTYPES.GEOM2D));
238
            polygon.addVertex(min.clone());
239
            polygon.setProjection(projection);
240
            return polygon;
241
        } catch (Exception e) {
242
            LOG.warn("Error creting the geometry from envelope", e);
243
        }
244
        return null;
245
    }
246

    
247
    public boolean contains(Envelope envelope) {
248
        if (isEmpty){
249
            return false;
250
        }
251
        if((envelope == null) || (envelope.isEmpty())) {
252
            return false;
253
        }
254
        for (int i = 0; i < getDimension(); i++) {
255
            if (getMinimum(i) > envelope.getMinimum(i)
256
                || getMaximum(i) < envelope.getMaximum(i)) {
257
                return false;
258
            }
259
        }
260
        return true;
261
    }
262

    
263
    public boolean intersects(Envelope envelope) {
264
        if (isEmpty){
265
            return false;
266
        }
267
        if((envelope == null) || (envelope.isEmpty())) {
268
            return false;
269
        }
270
        int dimension = getDimension();
271
        for (int i = 0; i < dimension; i++) {
272
            if (getMinimum(i)>envelope.getMaximum(i)){
273
                return false;
274
            } else if (getMaximum(i)<envelope.getMinimum(i)){
275
                return false;
276
            }
277
        }
278
        return true;
279
    }
280

    
281
    public boolean equals(Object other) {
282
        if (!(other == null || other instanceof Envelope)) {
283
            return false;
284
        }
285
        Envelope otherEnv = (Envelope) other;
286
        if (isEmpty && otherEnv.isEmpty()){
287
            return true;
288
        }
289
        if (otherEnv.getDimension() != this.getDimension()) {
290
            return false;
291
        }
292
        for (int i = 0; i < this.getDimension(); i++) {
293
            if (otherEnv.getMinimum(i) != this.getMinimum(i)) {
294
                return false;
295
            }
296
            if (otherEnv.getMaximum(i) != this.getMaximum(i)) {
297
                return false;
298
            }
299
        }
300
        return true;
301
    }
302

    
303
    /* (non-Javadoc)
304
     * @see org.gvsig.fmap.geom.primitive.Envelope#setLowerCorner(org.gvsig.fmap.geom.primitive.Point)
305
     */
306
    public void setLowerCorner(Point lowerCorner) {
307
        this.min = lowerCorner;
308
        if (max != null){
309
            isEmpty = false;
310
        }
311
        this.min.setProjectionIffNull(projection);
312
        jtsGeom = null;
313
    }
314

    
315
    /* (non-Javadoc)
316
     * @see org.gvsig.fmap.geom.primitive.Envelope#setUpperCorner(org.gvsig.fmap.geom.primitive.Point)
317
     */
318
    public void setUpperCorner(Point upperCorner) {
319
        this.max = upperCorner;
320
        if (min != null){
321
            isEmpty = false;
322
        }
323
        this.max.setProjectionIffNull(projection);        
324
        jtsGeom = null;
325
    }
326

    
327
    public static void registerPersistent() {
328
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
329
        if( manager.getDefinition(PERSISTENCE_DEFINITION_NAME)==null ) {
330
            DynStruct definition = manager.addDefinition(
331
                DefaultEnvelope.class,
332
                PERSISTENCE_DEFINITION_NAME,
333
                "DefaultEnvelope persistence definition",
334
                null,
335
                null
336
            );
337

    
338
            definition.addDynFieldObject(LOWERCORNER_FIELD).setClassOfValue(Point.class).setMandatory(true);
339
            definition.addDynFieldObject(UPPERCORNER_FIELD).setClassOfValue(Point.class).setMandatory(true);
340
        }
341
    }
342

    
343
    public void loadFromState(PersistentState state)
344
    throws PersistenceException {
345
        setLowerCorner((Point)state.get(LOWERCORNER_FIELD));
346
        setUpperCorner((Point)state.get(UPPERCORNER_FIELD));
347
    }
348

    
349
    public void saveToState(PersistentState state) throws PersistenceException {
350
        state.set(LOWERCORNER_FIELD, min);
351
        state.set(UPPERCORNER_FIELD, max);
352
    }
353

    
354
    public Object clone() throws CloneNotSupportedException {
355
        DefaultEnvelope other = (DefaultEnvelope) super.clone();
356
        if (!isEmpty){
357
            other.max = (Point) max.cloneGeometry();
358
            other.min = (Point) min.cloneGeometry();
359
        }
360
        return other;
361
    }
362

    
363
    @Override
364
    public boolean isEmpty() {
365
        return isEmpty;
366
    }
367

    
368
    @Override
369
    public void add(Geometry geometry) {
370
        if( geometry==null ) {
371
            return;
372
        }
373
        this.add(geometry.getEnvelope());
374
    }
375

    
376
    @Override
377
    public void clear() {
378
        isEmpty = true;
379
    }
380

    
381
    /* (non-Javadoc)
382
     * @see org.gvsig.fmap.geom.primitive.Envelope#intersects(org.gvsig.fmap.geom.Geometry)
383
     */
384
    @Override
385
    public boolean intersects(Geometry geometry) {
386
        if(geometry instanceof GeometryJTS){
387
            return getJTS().intersects(((GeometryJTS)geometry).getJTS());
388
        }
389
        return false;
390
    }
391

    
392

    
393
    /* (non-Javadoc)
394
     * @see org.gvsig.fmap.geom.primitive.Envelope#centerTo(org.gvsig.fmap.geom.primitive.Point)
395
     */
396
    @Override
397
    public void centerTo(Point p) {
398

    
399
        try {
400
            Point loweCorner = manager.createPoint(p.getX() - this.getLength(DIMENSIONS.X)/2,
401
                p.getY() - this.getLength(DIMENSIONS.Y)/2,
402
                    SUBTYPES.GEOM2D);
403
            Point upperCorner = manager.createPoint(p.getX() + this.getLength(DIMENSIONS.X)/2,
404
                p.getY() + this.getLength(DIMENSIONS.Y)/2,
405
                    SUBTYPES.GEOM2D);
406

    
407
            this.setLowerCorner(loweCorner);
408
            this.setUpperCorner(upperCorner);
409
        } catch (CreateGeometryException e) {
410
            LOG.error("Error creating corners to center the envelope", e);
411
        }
412
    }
413

    
414
    private com.vividsolutions.jts.geom.Geometry getJTS() {
415
        if (jtsGeom == null) {
416
            ArrayListCoordinateSequence coordinates = new ArrayListCoordinateSequence(new ArrayList<Coordinate>());
417
            coordinates.add(new com.vividsolutions.jts.geom.Coordinate(min.getX(), min.getY()));
418
            coordinates.add(new com.vividsolutions.jts.geom.Coordinate(getMaximum(0), getMinimum(1)));
419
            coordinates.add(new com.vividsolutions.jts.geom.Coordinate(max.getX(), max.getY()));
420
            coordinates.add(new com.vividsolutions.jts.geom.Coordinate(getMinimum(0), getMaximum(1)));
421
            coordinates.add(new com.vividsolutions.jts.geom.Coordinate(min.getX(), min.getY()));
422
            jtsGeom = JTSUtils.createJTSPolygon(coordinates);
423
        }
424
        return jtsGeom;
425
    }
426

    
427
    @Override
428
    public IProjection getProjection() {
429
        return this.projection;
430
    }
431

    
432
    @Override
433
    public void setProjectionIffNull(IProjection projection) {
434
        if (this.projection == null) {
435
            this.projection = projection;
436
        }
437
    }
438

    
439
    @Override
440
    public void setProjection(IProjection projection) {
441
        this.projection = projection;
442
    }
443

    
444
    @Override
445
    public boolean isCollapsed() {
446
        switch(this.getDimension()) {
447
            case 3:
448
                return this.isCollapsed(Geometry.SUBTYPES.GEOM3D);
449
            default:
450
            case 2:
451
                return this.isCollapsed(Geometry.SUBTYPES.GEOM2D);
452
        }
453
    }
454
    
455
    @Override
456
    public boolean isCollapsed(int subtype) {
457
        if( this.isEmpty ) {
458
            return true;
459
        }
460
        switch(subtype) {
461
            case Geometry.SUBTYPES.GEOM3DM:
462
                int m = this.getDimension()-1;
463
                if( this.getLength(m)!=0 ) {
464
                    return false;
465
                }
466
            case Geometry.SUBTYPES.GEOM2DM:
467
            case Geometry.SUBTYPES.GEOM3D:
468
                if( this.getLength(DIMENSIONS.Z)!=0 ) {
469
                    return false;
470
                }
471
            default:
472
            case Geometry.SUBTYPES.GEOM2D:
473
                if( this.getLength(DIMENSIONS.X)!=0 ) {
474
                    return false;
475
                }
476
                if( this.getLength(DIMENSIONS.Y)!=0 ) {
477
                    return false;
478
                }
479
                return true;
480
        }
481
    }
482

    
483
}