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

History | View | Annotate | Download (7.66 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.slf4j.Logger;
30
import org.slf4j.LoggerFactory;
31

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
174
            if (added == 0) {
175
                logger.error("Unable to reproject envelope with transf: " + trans.toString());
176
                return null;
177
            }
178

    
179
                return new Envelope2D(
180
                    res_min.getX(),
181
                    res_min.getY(),
182
                    res_max.getX(),
183
                    res_max.getY());
184
        }
185

    
186
        public static void registerPersistent() {
187
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
188
                if( manager.getDefinition(PERSISTENCE_DEFINITION_NAME)==null ) {
189
                        DynStruct definition = manager.addDefinition(
190
                                        Envelope2D.class,
191
                                        PERSISTENCE_DEFINITION_NAME,
192
                                        "Envelope2D persistence definition",
193
                                        null,
194
                                        null
195
                        );
196

    
197
                        definition.extend(manager.getDefinition(DefaultEnvelope.PERSISTENCE_DEFINITION_NAME));
198
                }
199
        }
200

    
201
    public Object clone() throws CloneNotSupportedException {
202
        return super.clone();
203
    }
204

    
205
    private void createPoints() {
206
        this.min = new Point2D(0, 0);
207
        this.max = new Point2D(0, 0);
208
    }
209

    
210
    public void add(Envelope envelope) {
211
        int i;
212
        if( envelope==null || envelope.isEmpty() ) {
213
            return;
214
        }
215
        if (isEmpty){
216
            createPoints();
217
            for (i=0;i<getDimension();i++){
218
                this.min.setCoordinateAt(i, envelope.getMinimum(i));
219
                this.max.setCoordinateAt(i, envelope.getMaximum(i));
220
            }
221
            isEmpty = false;
222
        } else {
223
            for (i=0;i<getDimension();i++){
224
                this.min.setCoordinateAt(i,
225
                    Math.min(this.min.getCoordinateAt(i), envelope.getMinimum(i)));
226
                this.max.setCoordinateAt(i,
227
                    Math.max(this.max.getCoordinateAt(i), envelope.getMaximum(i)));
228
            }
229
        }
230
    }
231
}
232