Revision 41209

View differences:

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
27 27
import java.awt.geom.Rectangle2D;
28 28

  
29 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;
30 36
import org.gvsig.fmap.geom.primitive.Envelope;
31 37
import org.gvsig.fmap.geom.primitive.EnvelopeNotInitializedException;
32 38
import org.gvsig.fmap.geom.primitive.Point;
33 39
import org.gvsig.tools.ToolsLocator;
34 40
import org.gvsig.tools.dynobject.DynStruct;
35 41
import org.gvsig.tools.lang.Cloneable;
42
import org.gvsig.tools.locator.LocatorException;
36 43
import org.gvsig.tools.persistence.PersistenceManager;
37 44

  
38 45
/**
39 46
 * @author <a href="mailto:jpiera@gvsig.org">Jorge Piera</a>
40 47
 */
41 48
public class Envelope2D extends DefaultEnvelope implements Cloneable{
49
    
50
    private static final Logger logger = LoggerFactory.getLogger(Envelope2D.class);
51
    
42 52
	public static final String PERSISTENCE_DEFINITION_NAME = "Envelope2Dimensions";
43 53
	
44 54
	public Envelope2D() {
......
65 75
	 * @see org.gvsig.fmap.geom.primitive.Envelope#convert(org.cresques.cts.ICoordTrans)
66 76
	 */
67 77
	public Envelope convert(ICoordTrans trans) {
78
	    
68 79
	    if (isEmpty){
69 80
            throw new EnvelopeNotInitializedException();
70 81
        }
82
	    
83
	    if (trans == null) {
84
	        // clone
85
	        return new Envelope2D(this.getLowerCorner(), this.getUpperCorner());
86
	    }
87
	    
71 88
	    if (this.getDimension() > 2) {
72 89
			return null;
73 90
		}
74
		Rectangle2D rect = new Rectangle2D.Double(this.getMinimum(0), this
75
				.getMinimum(1), this.getLength(0), this.getLength(1));
76
		Rectangle2D rectDest = trans.convert(rect);
77
		if (rectDest == null){
78
			return null;
79
		}
80
		Point2D p1 = new Point2D(rectDest.getMinX(), rectDest.getMinY());
81
		Point2D p2 = new Point2D(rectDest.getMaxX(), rectDest.getMaxY());
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);
82 120

  
83
		return new Envelope2D(p1, p2);
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
	                    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
	                } else {
147
	                    if (sample_trans.getX() < res_min.getX()) {
148
	                        res_min.setLocation(sample_trans.getX(), res_min.getY());
149
	                    }
150
	                }
151
	                // Y
152
                    if (sample_trans.getY() > res_max.getY()) {
153
                        res_max.setLocation(res_max.getX(), sample_trans.getY());
154
                    } else {
155
                        if (sample_trans.getY() < res_min.getY()) {
156
                            res_min.setLocation(res_min.getX(), sample_trans.getY());
157
                        }
158
                    }
159
                    added++;
160
	        }
161
	    }
162
	    
163
	    if (added == 0) {
164
	        logger.error("Unable to reproject envelope with transf: " + trans.toString());
165
	        return null;
166
	    }
167
	    
168
		return new Envelope2D(
169
		    res_min.getX(),
170
		    res_min.getY(),
171
		    res_max.getX(),
172
		    res_max.getY());
84 173
	}
85 174

  
86 175
	public static void registerPersistent() {

Also available in: Unified diff