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 / Envelope2D.java @ 43411

History | View | Annotate | Download (8.18 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 org.cresques.cts.CoordTransRuntimeException;
28
import org.cresques.cts.ICoordTrans;
29
import org.gvsig.fmap.geom.Geometry;
30
import org.slf4j.Logger;
31
import org.slf4j.LoggerFactory;
32

    
33
import org.gvsig.fmap.geom.jts.primitive.point.Point2D;
34
import org.gvsig.fmap.geom.primitive.Envelope;
35
import org.gvsig.fmap.geom.primitive.EnvelopeNotInitializedException;
36
import org.gvsig.fmap.geom.primitive.Point;
37
import org.gvsig.tools.ToolsLocator;
38
import org.gvsig.tools.dynobject.DynStruct;
39
import org.gvsig.tools.lang.Cloneable;
40
import org.gvsig.tools.persistence.PersistenceManager;
41

    
42
/**
43
 * @author <a href="mailto:jpiera@gvsig.org">Jorge Piera</a>
44
 */
45
public class Envelope2D extends DefaultEnvelope implements Cloneable{
46

    
47
    private static final Logger logger = LoggerFactory.getLogger(Envelope2D.class);
48

    
49
        public static final String PERSISTENCE_DEFINITION_NAME = "Envelope2Dimensions";
50

    
51
        public Envelope2D() {
52
                super();
53
        }
54

    
55
        public Envelope2D(Point min, Point max) {
56
                super(min, max);
57
        }
58

    
59
        public Envelope2D(double minX,double minY,double maxX, double maxY){
60
                this(new Point2D(minX, minY), new Point2D(maxX, maxY));
61
        }
62

    
63
        /**
64
     * @param bounds
65
     */
66
    public Envelope2D(com.vividsolutions.jts.geom.Geometry bounds) {
67
        this();
68
        com.vividsolutions.jts.geom.Envelope envelope = bounds.getEnvelope().getEnvelopeInternal();
69
        setLowerCorner(new Point2D(envelope.getMinX(), envelope.getMinY()));
70
        setUpperCorner(new Point2D(envelope.getMaxX(), envelope.getMaxY()));
71
    }
72

    
73
    /**
74
     * @param envelope
75
     */
76
    public Envelope2D(com.vividsolutions.jts.geom.Envelope envelope) {
77
        this(new Point2D(envelope.getMinX(),envelope.getMinY()), new Point2D(envelope.getMaxX(),envelope.getMaxY()));
78
    }
79

    
80
    /* (non-Javadoc)
81
         * @see org.gvsig.fmap.geom.primitive.Envelope#getDimension()
82
         */
83
        public int getDimension() {
84
                return 2;
85
        }
86

    
87
        /*
88
         * (non-Javadoc)
89
         * @see org.gvsig.fmap.geom.primitive.Envelope#convert(org.cresques.cts.ICoordTrans)
90
         */
91
        public Envelope convert(ICoordTrans trans) {
92

    
93
            if (isEmpty){
94
            throw new EnvelopeNotInitializedException();
95
        }
96

    
97
            if (trans == null) {
98
                // clone
99
                return new Envelope2D(this.getLowerCorner(), this.getUpperCorner());
100
            }
101

    
102
            if (this.getDimension() > 2) {
103
                        return null;
104
                }
105

    
106
            // We'll reproject by taking samples like this:
107
            //
108
            //  *---*---*---*---*
109
        //  |               |
110
        //  *   *   *   *   *
111
        //  |               |
112
        //  *   *   *   *   *
113
        //  |               |
114
        //  *   *   *   *   *
115
        //  |               |
116
        //  *---*---*---*---*
117
            //
118
            // This is because:
119
            //
120
            // - In some CRS (for example EPSG:4326) the north/south pole is a "line"
121
            //   while in other CRS the north/south pole is a point, so if you
122
            //   reproject the bounding box of the world, the result can be absurd.
123
            // - Sometimes the top/bottom/right/bottom of one envelope
124
            //   corresponds to a strange point in the the other envelope
125
            //   (not even a point in the perimeter)
126
            // - More generally, reprojecting usually implies a rotation (the result
127
            //   is a rotated envelope) so it's better to use a few
128
            //   samples along the perimeter.
129

    
130
            double xmin = getMinimum(0);
131
            double ymin = getMinimum(1);
132
            double step_w = 0.0625 * (getMaximum(0) - xmin);
133
            double step_h = 0.125 * (getMaximum(1) - ymin);
134

    
135
            java.awt.geom.Point2D sample = null;
136
            java.awt.geom.Point2D sample_trans = null;
137
            // Init with worst values
138
        java.awt.geom.Point2D res_min = new java.awt.geom.Point2D.Double(
139
            Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
140
        java.awt.geom.Point2D res_max = new java.awt.geom.Point2D.Double(
141
            Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
142

    
143
        int added = 0;
144
            for (int i=0; i<=16; i++) {
145
                for (int j=0; j<=8; j++) {
146
                        sample = new java.awt.geom.Point2D.Double(
147
                            xmin + i * step_w,
148
                            ymin + j * step_h);
149
                        sample_trans = new java.awt.geom.Point2D.Double(0,0);
150
                        try {
151
                            sample_trans = trans.convert(sample, sample_trans);
152
                        } catch (Exception exc) {
153
                            // Unable to convert this one: ignore
154
                            continue;
155
                        }
156
                        // Update max/min found
157
                        // X
158
                        if (!Double.isInfinite(sample_trans.getX()) && sample_trans.getX() > res_max.getX()) {
159
                            res_max.setLocation(sample_trans.getX(), res_max.getY());
160
                            added++;
161
                        }
162
                    if (!Double.isInfinite(sample_trans.getX()) && sample_trans.getX() < res_min.getX()) {
163
                        res_min.setLocation(sample_trans.getX(), res_min.getY());
164
                        added++;
165
                    }
166
                        // Y
167
                    if (!Double.isInfinite(sample_trans.getY()) && sample_trans.getY() > res_max.getY()) {
168
                        res_max.setLocation(res_max.getX(), sample_trans.getY());
169
                        added++;
170
                    }
171
                    if (!Double.isInfinite(sample_trans.getY()) && sample_trans.getY() < res_min.getY()) {
172
                        res_min.setLocation(res_min.getX(), sample_trans.getY());
173
                        added++;
174
                    }
175
                }
176
            }
177

    
178
            if (added == 0) {
179
                logger.warn("Unable to reproject envelope with transf: " + trans.toString());
180
            Point min = (Point) this.getLowerCorner().cloneGeometry();
181
            Point max = (Point) this.getUpperCorner().cloneGeometry();
182
            min.reProject(trans);
183
            max.reProject(trans);
184
                return new Envelope2D(min,max);
185
            }
186

    
187
                return new Envelope2D(
188
                    res_min.getX(),
189
                    res_min.getY(),
190
                    res_max.getX(),
191
                    res_max.getY());
192
        }
193

    
194
        public static void registerPersistent() {
195
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
196
                if( manager.getDefinition(PERSISTENCE_DEFINITION_NAME)==null ) {
197
                        DynStruct definition = manager.addDefinition(
198
                                        Envelope2D.class,
199
                                        PERSISTENCE_DEFINITION_NAME,
200
                                        "Envelope2D persistence definition",
201
                                        null,
202
                                        null
203
                        );
204

    
205
                        definition.extend(manager.getDefinition(DefaultEnvelope.PERSISTENCE_DEFINITION_NAME));
206
                }
207
        }
208

    
209
    public Object clone() throws CloneNotSupportedException {
210
        return super.clone();
211
    }
212

    
213
    private void createPoints() {
214
        this.min = new Point2D(0, 0);
215
        this.max = new Point2D(0, 0);
216
    }
217

    
218
    public void add(Envelope envelope) {
219
        int i;
220
        if( envelope==null || envelope.isEmpty() ) {
221
            return;
222
        }
223
        if (isEmpty){
224
            createPoints();
225
            for (i=0;i<getDimension();i++){
226
                this.min.setCoordinateAt(i, envelope.getMinimum(i));
227
                this.max.setCoordinateAt(i, envelope.getMaximum(i));
228
            }
229
            isEmpty = false;
230
        } else {
231
            for (i=0;i<getDimension();i++){
232
                this.min.setCoordinateAt(i,
233
                    Math.min(this.min.getCoordinateAt(i), envelope.getMinimum(i)));
234
                this.max.setCoordinateAt(i,
235
                    Math.max(this.max.getCoordinateAt(i), envelope.getMaximum(i)));
236
            }
237
        }
238
    }
239
}
240