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 @ 47351

History | View | Annotate | Download (16.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(IProjection projection){
95
        this();
96
        this.projection = projection;
97
    }
98

    
99
    public DefaultEnvelope(Point min, Point max, IProjection projection){
100
        super();
101
        this.min = min;
102
        this.max = max;
103
        isEmpty = false;
104
        this.projection = projection;
105
    }
106

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

    
137
    /**
138
     * Returns the center ordinate along the specified dimension.
139
     *
140
     * @param dimension DOCUMENT ME!
141
     *
142
     * @return DOCUMENT ME!
143
     */
144
    public double getCenter(int dimension) {
145
        if (isEmpty){
146
            throw new EnvelopeNotInitializedException();
147
        }
148
        return (min.getCoordinateAt(dimension) + max.getCoordinateAt(dimension)) * 0.5;
149
    }
150

    
151
    /**
152
     * Returns the envelope length along the specified dimension.
153
     *
154
     * @param dimension
155
     *
156
     * @return
157
     */
158
    public double getLength(int dimension) {
159
        if (isEmpty){
160
            throw new EnvelopeNotInitializedException();
161
        }
162
        if (max.getCoordinateAt(dimension) > min.getCoordinateAt(dimension)) {
163
            return max.getCoordinateAt(dimension) - min.getCoordinateAt(dimension);
164
        }
165

    
166
        return min.getCoordinateAt(dimension) - max.getCoordinateAt(dimension);
167
    }
168

    
169
    /**
170
     * A coordinate position consisting of all the minimal ordinates for each
171
     * dimension for all points within the Envelope.
172
     *
173
     * @return
174
     */
175
    public Point getLowerCorner() {
176
        return min;
177
    }
178

    
179
    /**
180
     * Returns the maximal ordinate along the specified dimension.
181
     *
182
     * @param dimension
183
     *
184
     * @return
185
     */
186
    public double getMaximum(int dimension) {
187
        if (isEmpty){
188
            throw new EnvelopeNotInitializedException();
189
        }
190
        return max.getCoordinateAt(dimension);
191
    }
192

    
193
    /**
194
     * Returns the minimal ordinate along the specified dimension.
195
     *
196
     * @param dimension
197
     *
198
     * @return
199
     */
200
    public double getMinimum(int dimension) {
201
        if (isEmpty){
202
            throw new EnvelopeNotInitializedException();
203
        }
204
        return min.getCoordinateAt(dimension);
205
    }
206

    
207
    /**
208
     * A coordinate position consisting of all the maximal ordinates for each
209
     * dimension for all points within the Envelope.
210
     *
211
     * @return
212
     */
213
    public Point getUpperCorner() {
214
        return max;
215
    }
216

    
217

    
218

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

    
253
    @Override
254
    public Geometry getBox2D() {
255
        if (isEmpty){
256
            throw new EnvelopeNotInitializedException();
257
        }
258
        try {
259
            Polygon polygon = manager.createPolygon(SUBTYPES.GEOM2D);
260
            polygon.addVertex(min.clone());
261
            polygon.addVertex(manager.createPoint(getMaximum(0),getMinimum(1), SUBTYPES.GEOM2D));
262
            polygon.addVertex(max.clone());
263
            polygon.addVertex(manager.createPoint(getMinimum(0),getMaximum(1), SUBTYPES.GEOM2D));
264
            polygon.addVertex(min.clone());
265
            polygon.setProjection(projection);
266
            return polygon;
267
        } catch (Exception e) {
268
            LOG.warn("Error creting the geometry from envelope", e);
269
        }
270
        return null;
271
    }
272

    
273
    @Override
274
    public boolean contains(Envelope envelope) {
275
        if (isEmpty){
276
            return false;
277
        }
278
        if((envelope == null) || (envelope.isEmpty())) {
279
            return false;
280
        }
281
        for (int i = 0; i < getDimension(); i++) {
282
            if (getMinimum(i) > envelope.getMinimum(i)
283
                || getMaximum(i) < envelope.getMaximum(i)) {
284
                return false;
285
            }
286
        }
287
        return true;
288
    }
289

    
290
    public boolean intersects(Envelope envelope) {
291
        if (isEmpty){
292
            return false;
293
        }
294
        if((envelope == null) || (envelope.isEmpty())) {
295
            return false;
296
        }
297
        int dimension = getDimension();
298
        for (int i = 0; i < dimension; i++) {
299
            if (getMinimum(i)>envelope.getMaximum(i)){
300
                return false;
301
            } else if (getMaximum(i)<envelope.getMinimum(i)){
302
                return false;
303
            }
304
        }
305
        return true;
306
    }
307

    
308
    public boolean equals(Object other) {
309
        if (!(other == null || other instanceof Envelope)) {
310
            return false;
311
        }
312
        Envelope otherEnv = (Envelope) other;
313
        if (isEmpty && otherEnv.isEmpty()){
314
            return true;
315
        }
316
        if (otherEnv.getDimension() != this.getDimension()) {
317
            return false;
318
        }
319
        for (int i = 0; i < this.getDimension(); i++) {
320
            if (otherEnv.getMinimum(i) != this.getMinimum(i)) {
321
                return false;
322
            }
323
            if (otherEnv.getMaximum(i) != this.getMaximum(i)) {
324
                return false;
325
            }
326
        }
327
        return true;
328
    }
329

    
330
    /* (non-Javadoc)
331
     * @see org.gvsig.fmap.geom.primitive.Envelope#setLowerCorner(org.gvsig.fmap.geom.primitive.Point)
332
     */
333
    public void setLowerCorner(Point lowerCorner) {
334
        this.min = lowerCorner;
335
        if (max != null){
336
            isEmpty = false;
337
        }
338
        this.min.setProjectionIffNull(projection);
339
        jtsGeom = null;
340
    }
341

    
342
    /* (non-Javadoc)
343
     * @see org.gvsig.fmap.geom.primitive.Envelope#setUpperCorner(org.gvsig.fmap.geom.primitive.Point)
344
     */
345
    public void setUpperCorner(Point upperCorner) {
346
        this.max = upperCorner;
347
        if (min != null){
348
            isEmpty = false;
349
        }
350
        this.max.setProjectionIffNull(projection);        
351
        jtsGeom = null;
352
    }
353

    
354
    public static void registerPersistent() {
355
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
356
        if( manager.getDefinition(PERSISTENCE_DEFINITION_NAME)==null ) {
357
            DynStruct definition = manager.addDefinition(
358
                DefaultEnvelope.class,
359
                PERSISTENCE_DEFINITION_NAME,
360
                "DefaultEnvelope persistence definition",
361
                null,
362
                null
363
            );
364

    
365
            definition.addDynFieldObject(LOWERCORNER_FIELD).setClassOfValue(Point.class).setMandatory(true);
366
            definition.addDynFieldObject(UPPERCORNER_FIELD).setClassOfValue(Point.class).setMandatory(true);
367
        }
368
    }
369

    
370
    public void loadFromState(PersistentState state)
371
    throws PersistenceException {
372
        setLowerCorner((Point)state.get(LOWERCORNER_FIELD));
373
        setUpperCorner((Point)state.get(UPPERCORNER_FIELD));
374
    }
375

    
376
    public void saveToState(PersistentState state) throws PersistenceException {
377
        state.set(LOWERCORNER_FIELD, min);
378
        state.set(UPPERCORNER_FIELD, max);
379
    }
380

    
381
    @Override
382
    public Object clone() throws CloneNotSupportedException {
383
        DefaultEnvelope other = (DefaultEnvelope) super.clone();
384
        other.setProjection(this.getProjection());
385
        if (!isEmpty){
386
            other.max = (Point) max.cloneGeometry();
387
            other.min = (Point) min.cloneGeometry();
388
        }
389
        return other;
390
    }
391

    
392
    @Override
393
    public boolean isEmpty() {
394
        return isEmpty;
395
    }
396

    
397
    @Override
398
    public void add(Geometry geometry) {
399
        if( geometry==null ) {
400
            return;
401
        }
402
        this.add(geometry.getEnvelope());
403
    }
404

    
405
    @Override
406
    public void clear() {
407
        isEmpty = true;
408
    }
409

    
410
    /* (non-Javadoc)
411
     * @see org.gvsig.fmap.geom.primitive.Envelope#intersects(org.gvsig.fmap.geom.Geometry)
412
     */
413
    @Override
414
    public boolean intersects(Geometry geometry) {
415
        if(geometry instanceof GeometryJTS){
416
            return getJTS().intersects(((GeometryJTS)geometry).getJTS());
417
        }
418
        return false;
419
    }
420

    
421

    
422
    /* (non-Javadoc)
423
     * @see org.gvsig.fmap.geom.primitive.Envelope#centerTo(org.gvsig.fmap.geom.primitive.Point)
424
     */
425
    @Override
426
    public void centerTo(Point p) {
427

    
428
        try {
429
            Point loweCorner = manager.createPoint(p.getX() - this.getLength(DIMENSIONS.X)/2,
430
                p.getY() - this.getLength(DIMENSIONS.Y)/2,
431
                    SUBTYPES.GEOM2D);
432
            Point upperCorner = manager.createPoint(p.getX() + this.getLength(DIMENSIONS.X)/2,
433
                p.getY() + this.getLength(DIMENSIONS.Y)/2,
434
                    SUBTYPES.GEOM2D);
435

    
436
            this.setLowerCorner(loweCorner);
437
            this.setUpperCorner(upperCorner);
438
        } catch (CreateGeometryException e) {
439
            LOG.error("Error creating corners to center the envelope", e);
440
        }
441
    }
442

    
443
    private com.vividsolutions.jts.geom.Geometry getJTS() {
444
        if (jtsGeom == null) {
445
            ArrayListCoordinateSequence coordinates = new ArrayListCoordinateSequence(new ArrayList<Coordinate>());
446
            coordinates.add(new com.vividsolutions.jts.geom.Coordinate(min.getX(), min.getY()));
447
            coordinates.add(new com.vividsolutions.jts.geom.Coordinate(getMaximum(0), getMinimum(1)));
448
            coordinates.add(new com.vividsolutions.jts.geom.Coordinate(max.getX(), max.getY()));
449
            coordinates.add(new com.vividsolutions.jts.geom.Coordinate(getMinimum(0), getMaximum(1)));
450
            coordinates.add(new com.vividsolutions.jts.geom.Coordinate(min.getX(), min.getY()));
451
            jtsGeom = JTSUtils.createJTSPolygon(coordinates);
452
        }
453
        return jtsGeom;
454
    }
455

    
456
    @Override
457
    public IProjection getProjection() {
458
        return this.projection;
459
    }
460

    
461
    @Override
462
    public void setProjectionIffNull(IProjection projection) {
463
        if (this.projection == null) {
464
            this.projection = projection;
465
        }
466
    }
467

    
468
    @Override
469
    public void setProjection(IProjection projection) {
470
        this.projection = projection;
471
    }
472

    
473
    @Override
474
    public boolean isCollapsed() {
475
        switch(this.getDimension()) {
476
            case 3:
477
                return this.isCollapsed(Geometry.SUBTYPES.GEOM3D);
478
            default:
479
            case 2:
480
                return this.isCollapsed(Geometry.SUBTYPES.GEOM2D);
481
        }
482
    }
483
    
484
    @Override
485
    public boolean isCollapsed(int subtype) {
486
        if( this.isEmpty ) {
487
            return true;
488
        }
489
        switch(subtype) {
490
            case Geometry.SUBTYPES.GEOM3DM:
491
                int m = this.getDimension()-1;
492
                if( this.getLength(m)!=0 ) {
493
                    return false;
494
                }
495
            case Geometry.SUBTYPES.GEOM2DM:
496
            case Geometry.SUBTYPES.GEOM3D:
497
                if( this.getLength(DIMENSIONS.Z)!=0 ) {
498
                    return false;
499
                }
500
            default:
501
            case Geometry.SUBTYPES.GEOM2D:
502
                if( this.getLength(DIMENSIONS.X)!=0 ) {
503
                    return false;
504
                }
505
                if( this.getLength(DIMENSIONS.Y)!=0 ) {
506
                    return false;
507
                }
508
                return true;
509
        }
510
    }
511

    
512
}