Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.geometry / org.gvsig.fmap.geometry.impl / src / main / java / org / gvsig / fmap / geom / primitive / impl / Envelope2D.java @ 41417

History | View | Annotate | Download (7.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.primitive.impl;
26

    
27
import java.awt.geom.Rectangle2D;
28

    
29
import org.cresques.cts.ICoordTrans;
30
import org.slf4j.Logger;
31
import org.slf4j.LoggerFactory;
32

    
33
import org.gvsig.fmap.geom.Geometry;
34
import org.gvsig.fmap.geom.GeometryLocator;
35
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
36
import org.gvsig.fmap.geom.primitive.Envelope;
37
import org.gvsig.fmap.geom.primitive.EnvelopeNotInitializedException;
38
import org.gvsig.fmap.geom.primitive.Point;
39
import org.gvsig.tools.ToolsLocator;
40
import org.gvsig.tools.dynobject.DynStruct;
41
import org.gvsig.tools.lang.Cloneable;
42
import org.gvsig.tools.locator.LocatorException;
43
import org.gvsig.tools.persistence.PersistenceManager;
44

    
45
/**
46
 * @author <a href="mailto:jpiera@gvsig.org">Jorge Piera</a>
47
 */
48
public class Envelope2D extends DefaultEnvelope implements Cloneable{
49
    
50
    private static final Logger logger = LoggerFactory.getLogger(Envelope2D.class);
51
    
52
        public static final String PERSISTENCE_DEFINITION_NAME = "Envelope2Dimensions";
53
        
54
        public Envelope2D() {
55
                super();        
56
        }
57

    
58
        public Envelope2D(Point min, Point max) {
59
                super(min, max);
60
        }
61

    
62
        public Envelope2D(double minX,double minY,double maxX, double maxY){
63
                this(new Point2D(minX, minY), new Point2D(maxX, maxY));
64
        }
65

    
66
        /* (non-Javadoc)
67
         * @see org.gvsig.fmap.geom.primitive.Envelope#getDimension()
68
         */
69
        public int getDimension() {
70
                return 2;
71
        }
72

    
73
        /*
74
         * (non-Javadoc)
75
         * @see org.gvsig.fmap.geom.primitive.Envelope#convert(org.cresques.cts.ICoordTrans)
76
         */
77
        public Envelope convert(ICoordTrans trans) {
78
            
79
            if (isEmpty){
80
            throw new EnvelopeNotInitializedException();
81
        }
82
            
83
            if (trans == null) {
84
                // clone
85
                return new Envelope2D(this.getLowerCorner(), this.getUpperCorner());
86
            }
87
            
88
            if (this.getDimension() > 2) {
89
                        return null;
90
                }
91
            
92
            // We'll reproject by taking samples like this:
93
            // 
94
            //  *---*---*---*---*
95
        //  |               |
96
        //  *   *   *   *   *
97
        //  |               |
98
        //  *   *   *   *   *
99
        //  |               |
100
        //  *   *   *   *   *
101
        //  |               |
102
        //  *---*---*---*---*
103
            // 
104
            // This is because:
105
            // 
106
            // - In some CRS (for example EPSG:4326) the north/south pole is a "line"
107
            //   while in other CRS the north/south pole is a point, so if you
108
            //   reproject the bounding box of the world, the result can be absurd.
109
            // - Sometimes the top/bottom/right/bottom of one envelope
110
            //   corresponds to a strange point in the the other envelope
111
            //   (not even a point in the perimeter)
112
            // - More generally, reprojecting usually implies a rotation (the result
113
            //   is a rotated envelope) so it's better to use a few
114
            //   samples along the perimeter.
115
            
116
            double xmin = getMinimum(0);
117
            double ymin = getMinimum(1);
118
            double step_w = 0.25 * (getMaximum(0) - xmin);
119
            double step_h = 0.25 * (getMaximum(1) - ymin);
120

    
121
            java.awt.geom.Point2D sample = null;
122
            java.awt.geom.Point2D sample_trans = null;
123
            // Init with worst values
124
        java.awt.geom.Point2D res_min = new java.awt.geom.Point2D.Double(
125
            Double.MAX_VALUE, Double.MAX_VALUE);
126
        java.awt.geom.Point2D res_max = new java.awt.geom.Point2D.Double(
127
            -Double.MAX_VALUE, -Double.MAX_VALUE);
128
           
129
        int added = 0;
130
            for (int i=0; i<5; i++) {
131
                for (int j=0; j<5; j++) {
132
                        sample = new java.awt.geom.Point2D.Double(
133
                            xmin + i * step_w,
134
                            ymin + j * step_h);
135
                        sample_trans = new java.awt.geom.Point2D.Double(0,0);
136
                        try {
137
                            sample_trans = trans.convert(sample, sample_trans);
138
                        } catch (Exception exc) {
139
                            // Unable to convert this one: ignore
140
                            continue;
141
                        }
142
                        // Update max/min found
143
                        // X
144
                        if (sample_trans.getX() > res_max.getX()) {
145
                            res_max.setLocation(sample_trans.getX(), res_max.getY());
146
                        }
147
                    if (sample_trans.getX() < res_min.getX()) {
148
                        res_min.setLocation(sample_trans.getX(), res_min.getY());
149
                    }
150
                        // Y
151
                    if (sample_trans.getY() > res_max.getY()) {
152
                        res_max.setLocation(res_max.getX(), sample_trans.getY());
153
                    }
154
                    if (sample_trans.getY() < res_min.getY()) {
155
                        res_min.setLocation(res_min.getX(), sample_trans.getY());
156
                    }
157
                    added++;
158
                }
159
            }
160
            
161
            if (added == 0) {
162
                logger.error("Unable to reproject envelope with transf: " + trans.toString());
163
                return null;
164
            }
165
            
166
                return new Envelope2D(
167
                    res_min.getX(),
168
                    res_min.getY(),
169
                    res_max.getX(),
170
                    res_max.getY());
171
        }
172

    
173
        public static void registerPersistent() {
174
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
175
                if( manager.getDefinition(PERSISTENCE_DEFINITION_NAME)==null ) {
176
                        DynStruct definition = manager.addDefinition(
177
                                        Envelope2D.class,
178
                                        PERSISTENCE_DEFINITION_NAME,
179
                                        "Envelope2D persistence definition",
180
                                        null, 
181
                                        null
182
                        ); 
183
                        
184
                        definition.extend(manager.getDefinition(DefaultEnvelope.PERSISTENCE_DEFINITION_NAME));        
185
                }
186
        }
187
        
188
    public Object clone() throws CloneNotSupportedException {
189
        return super.clone();
190
    }
191

    
192
    private void createPoints() {
193
        this.min = new Point2D(0, 0);
194
        this.max = new Point2D(0, 0);
195
    }
196
    
197
    public void add(Envelope envelope) {
198
        int i;
199
        if( envelope==null && envelope.isEmpty() ) {
200
            return;
201
        }
202
        if (isEmpty){
203
            createPoints();
204
            for (i=0;i<getDimension();i++){
205
                this.min.setCoordinateAt(i, envelope.getMinimum(i));
206
                this.max.setCoordinateAt(i, envelope.getMaximum(i));
207
            }
208
            isEmpty = false;
209
        } else {
210
            for (i=0;i<getDimension();i++){
211
                this.min.setCoordinateAt(i,
212
                    Math.min(this.min.getCoordinateAt(i), envelope.getMinimum(i)));
213
                this.max.setCoordinateAt(i,
214
                    Math.max(this.max.getCoordinateAt(i), envelope.getMaximum(i)));
215
            }
216
        }
217
    }
218
}
219