Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Use CRS.transform to handle bounding boxes correctly when served by L…

…ayer, or when added using GetMapRequest. Refactor out a common method for toServerCRS for consistent handling
  • Loading branch information...
commit 056965fdc07b6c7e38ded42869bb8c1a781d63e5 1 parent 95c0946
Jody Garnett jodygarnett authored
23 modules/extension/wms/src/main/java/org/geotools/data/ows/CRSEnvelope.java
@@ -16,6 +16,7 @@
16 16 */
17 17 package org.geotools.data.ows;
18 18
  19 +import org.geotools.data.wms.request.AbstractGetMapRequest;
19 20 import org.geotools.factory.GeoTools;
20 21 import org.geotools.factory.Hints;
21 22 import org.geotools.geometry.GeneralDirectPosition;
@@ -107,7 +108,7 @@ public CRSEnvelope(String epsgCode, double minX, double minY, double maxX, doubl
107 108 this.maxY = maxY;
108 109 }
109 110 public CRSEnvelope(Envelope envelope) {
110   - this.srsName = envelope.getCoordinateReferenceSystem().getIdentifiers().iterator().next().toString();
  111 + this.srsName = CRS.toSRS( envelope.getCoordinateReferenceSystem());
111 112 //this.srsName = epsgCode;
112 113 this.minX = envelope.getMinimum(0);
113 114 this.maxX = envelope.getMaximum(0);
@@ -123,24 +124,12 @@ public CoordinateReferenceSystem getCoordinateReferenceSystem() {
123 124 synchronized (this) {
124 125 if (crs == null) {
125 126 try {
126   - if( srsName != null ){
127   - if( forceXY == null ){
128   - crs = CRS.decode(srsName);
129   - }
130   - else if( forceXY == Boolean.TRUE ){
131   - crs = CRS.decode(srsName,true);
132   - }
133   - else if( srsName.startsWith("EPSG:") && Boolean.getBoolean(GeoTools.FORCE_LONGITUDE_FIRST_AXIS_ORDER)){
134   - // how do we look up the unmodified axis order?
135   - String explicit = srsName.replace("EPSG:", "urn:x-ogc:def:crs:EPSG:");
136   - crs = CRS.decode(explicit,false);
137   - }
138   - else {
139   - crs = CRS.decode(srsName,false);
140   - }
  127 + String srs = srsName != null ? srsName : "CRS:84";
  128 + if( forceXY == null ){
  129 + crs = CRS.decode(srs);
141 130 }
142 131 else {
143   - crs = CRS.decode("CRS:84"); // implicit
  132 + crs = AbstractGetMapRequest.toServerCRS(srsName, forceXY );
144 133 }
145 134 } catch (NoSuchAuthorityCodeException e) {
146 135 crs = DefaultEngineeringCRS.CARTESIAN_2D;
25 modules/extension/wms/src/main/java/org/geotools/data/ows/Layer.java
@@ -816,7 +816,7 @@ public GeneralEnvelope getEnvelope(CoordinateReferenceSystem crs) {
816 816 Collection<Object> identifiers = new ArrayList<Object>();
817 817 identifiers.addAll( crs.getIdentifiers() );
818 818 if (crs == DefaultGeographicCRS.WGS84 || crs == DefaultGeographicCRS.WGS84_3D) {
819   - identifiers.add( "EPSG:4326" );
  819 + identifiers.add( "CRS:84" );
820 820 }
821 821 for (Object identifier : identifiers ) {
822 822 String srsName = identifier.toString();
@@ -850,12 +850,12 @@ public GeneralEnvelope getEnvelope(CoordinateReferenceSystem crs) {
850 850 layer = layer.getParent();
851 851 }
852 852
853   - if (latLonBBox == null) {
854   - // TODO could convert another bbox to latlon?
855   - tempBBox = new CRSEnvelope("EPSG:4326", -180, -90, 180, 90);
856   - } else {
857   - tempBBox = new CRSEnvelope("EPSG:4326", latLonBBox.getMinX(), latLonBBox
  853 + if (latLonBBox != null) {
  854 + tempBBox = new CRSEnvelope("CRS:84", latLonBBox.getMinX(), latLonBBox
858 855 .getMinY(), latLonBBox.getMaxX(), latLonBBox.getMaxY());
  856 + } else {
  857 + tempBBox = new CRSEnvelope("CRS:84", -180, -90, 180, 90);
  858 + // TODO could convert another bbox to latlon?
859 859 }
860 860 }
861 861
@@ -914,10 +914,15 @@ public GeneralEnvelope getEnvelope(CoordinateReferenceSystem crs) {
914 914 // TODO Attempt to figure out the valid area of the CRS and use that.
915 915
916 916 if (tempBBox != null) {
917   - GeneralEnvelope env = new GeneralEnvelope(new double[] { tempBBox.getMinX(),
918   - tempBBox.getMinY() },
919   - new double[] { tempBBox.getMaxX(), tempBBox.getMaxY() });
920   - env.setCoordinateReferenceSystem(crs);
  917 + GeneralEnvelope env;
  918 + try {
  919 + Envelope fixed = CRS.transform( tempBBox, crs );
  920 + env = new GeneralEnvelope( fixed );
  921 + } catch (TransformException e) {
  922 + env = new GeneralEnvelope(new double[] { tempBBox.getMinX(),tempBBox.getMinY() },
  923 + new double[] { tempBBox.getMaxX(), tempBBox.getMaxY() });
  924 + env.setCoordinateReferenceSystem(crs);
  925 + }
921 926 return env;
922 927 }
923 928
72 modules/extension/wms/src/main/java/org/geotools/data/wms/request/AbstractGetMapRequest.java
@@ -27,7 +27,15 @@
27 27 import org.geotools.data.ows.CRSEnvelope;
28 28 import org.geotools.data.ows.Layer;
29 29 import org.geotools.data.ows.StyleImpl;
  30 +import org.geotools.factory.GeoTools;
  31 +import org.geotools.referencing.CRS;
  32 +import org.geotools.referencing.crs.DefaultEngineeringCRS;
30 33 import org.opengis.geometry.BoundingBox;
  34 +import org.opengis.geometry.Envelope;
  35 +import org.opengis.referencing.FactoryException;
  36 +import org.opengis.referencing.NoSuchAuthorityCodeException;
  37 +import org.opengis.referencing.crs.CoordinateReferenceSystem;
  38 +import org.opengis.referencing.operation.TransformException;
31 39
32 40 /**
33 41 *
@@ -168,7 +176,10 @@ public void setSRS(String srs) {
168 176 * server has declared that a Layer is not subsettable, then the Client
169 177 * shall specify exactly the declared Bounding Box values in the GetMap
170 178 * request and the Server may issue a Service Exception otherwise."
171   - *
  179 + * <p>
  180 + * Yu must also call setSRS to provide the spatial reference system
  181 + * information (or CRS:84 will be assumed)
  182 + *
172 183 * @param bbox A string representing a bounding box in the format
173 184 * "minx,miny,maxx,maxy"
174 185 */
@@ -176,26 +187,51 @@ public void setBBox(String bbox) {
176 187 //TODO enforce non-subsettable layers
177 188 properties.setProperty(BBOX, bbox);
178 189 }
179   -
180   - public void setBBox(CRSEnvelope box){
181   - StringBuffer sb = new StringBuffer();
182   - sb.append(box.getMinX());
183   - sb.append(",");
184   - sb.append(box.getMinY()+",");
185   - sb.append(box.getMaxX()+",");
186   - sb.append(box.getMaxY());
187   - setBBox(sb.toString());
  190 +
  191 + public static CoordinateReferenceSystem toServerCRS(String srsName, boolean forceXY) {
  192 + try {
  193 + if (srsName != null) {
  194 + if (forceXY) {
  195 + return CRS.decode(srsName, true);
  196 + } else if (srsName.startsWith("EPSG:")
  197 + && Boolean.getBoolean(GeoTools.FORCE_LONGITUDE_FIRST_AXIS_ORDER)) {
  198 + // how do we look up the unmodified axis order?
  199 + String explicit = srsName.replace("EPSG:", "urn:x-ogc:def:crs:EPSG::");
  200 + return CRS.decode(explicit, false);
  201 + } else {
  202 + return CRS.decode(srsName, false);
  203 + }
  204 + }
  205 + else {
  206 + return CRS.decode("CRS:84");
  207 + }
  208 + } catch (NoSuchAuthorityCodeException e) {
  209 + } catch (FactoryException e) {
  210 + }
  211 + return DefaultEngineeringCRS.CARTESIAN_2D;
188 212 }
189   - public void setBBox(BoundingBox box) {
  213 + /**
  214 + * Sets BBOX and SRS using the provided Envelope.
  215 + */
  216 + public void setBBox(Envelope envelope){
  217 + String version = properties.getProperty(VERSION);
  218 + boolean forceXY = version == null || !version.startsWith("1.3");
  219 + String srsName = CRS.toSRS( envelope.getCoordinateReferenceSystem() );
  220 + setSRS( srsName );
  221 +
  222 + CoordinateReferenceSystem crs = toServerCRS( srsName, forceXY );
  223 + Envelope bbox;
  224 + try {
  225 + bbox = CRS.transform( envelope, crs);
  226 + } catch (TransformException e) {
  227 + bbox = envelope;
  228 + }
190 229 StringBuffer sb = new StringBuffer();
191   - sb.append(box.getMinX());
192   - sb.append(",");
193   - sb.append(box.getMinY());
  230 + sb.append(bbox.getMinimum(0));
194 231 sb.append(",");
195   - sb.append(box.getMaxX());
196   - sb.append(",");
197   - sb.append(box.getMaxY());
198   -
  232 + sb.append(bbox.getMinimum(1)+",");
  233 + sb.append(bbox.getMaximum(0)+",");
  234 + sb.append(bbox.getMaximum(1));
199 235 setBBox(sb.toString());
200 236 }
201 237 /**
10 modules/extension/wms/src/main/java/org/geotools/data/wms/request/GetMapRequest.java
@@ -24,6 +24,7 @@
24 24 import org.geotools.data.ows.Request;
25 25 import org.geotools.data.ows.StyleImpl;
26 26 import org.opengis.geometry.BoundingBox;
  27 +import org.opengis.geometry.Envelope;
27 28
28 29 /**
29 30 * Construct a WMS getMap request.
@@ -224,8 +225,13 @@
224 225 * "minx,miny,maxx,maxy"
225 226 */
226 227 public void setBBox(String bbox);
227   - public void setBBox(CRSEnvelope box);
228   - public void setBBox(BoundingBox box);
  228 +
  229 + /**
  230 + * Sets the BBOX and SRS information from the provided Envelope (such as a CRSEnvelope).
  231 + * @param box
  232 + */
  233 + public void setBBox(Envelope box);
  234 +
229 235
230 236 /**
231 237 * From the Web Map Service Implementation Specification: "The required
151 modules/extension/wms/src/test/java/org/geotools/data/wms/test/LocalGeoServerOnlineTest.java
@@ -16,8 +16,14 @@
16 16 */
17 17 package org.geotools.data.wms.test;
18 18
  19 +import java.awt.Color;
  20 +import java.awt.image.BufferedImage;
  21 +import java.io.InputStream;
19 22 import java.net.MalformedURLException;
20 23 import java.net.URL;
  24 +import java.util.Properties;
  25 +
  26 +import javax.imageio.ImageIO;
21 27
22 28 import junit.framework.TestCase;
23 29
@@ -25,12 +31,25 @@
25 31 import org.geotools.data.ServiceInfo;
26 32 import org.geotools.data.ows.CRSEnvelope;
27 33 import org.geotools.data.ows.Layer;
  34 +import org.geotools.data.ows.OperationType;
28 35 import org.geotools.data.ows.WMSCapabilities;
29 36 import org.geotools.data.wms.WebMapServer;
  37 +import org.geotools.data.wms.request.GetMapRequest;
  38 +import org.geotools.data.wms.response.GetMapResponse;
  39 +import org.geotools.factory.GeoTools;
  40 +import org.geotools.geometry.GeneralEnvelope;
30 41 import org.geotools.geometry.jts.ReferencedEnvelope;
  42 +import org.geotools.referencing.CRS;
  43 +import org.geotools.referencing.CRS.AxisOrder;
  44 +import org.geotools.referencing.crs.DefaultEngineeringCRS;
  45 +import org.geotools.referencing.crs.DefaultGeographicCRS;
  46 +import org.opengis.geometry.Envelope;
  47 +import org.opengis.referencing.FactoryException;
  48 +import org.opengis.referencing.NoSuchAuthorityCodeException;
31 49 import org.opengis.referencing.crs.CoordinateReferenceSystem;
32   -
33   -import com.vividsolutions.jts.geom.Coordinate;
  50 +import org.opengis.referencing.cs.CoordinateSystem;
  51 +import org.opengis.referencing.cs.CoordinateSystemAxis;
  52 +import org.opengis.util.GenericName;
34 53
35 54 /**
36 55 * This test case assume you have a default GeoServer 2.2 installed on 127.0.0.1 (ie localhost).
@@ -38,7 +57,8 @@
38 57 * This is being used to look at WMS 1.1.1 vs WMS 1.3.0 compatibility issues for uDig.
39 58 * <p>
40 59 *
41   - * <pre><code>
  60 + * <pre>
  61 + * <code>
42 62 * &lt;Layer queryable="1"&gt;
43 63 * &lt;Name&gt;nurc:Img_Sample&lt;/Name&gt;
44 64 * &lt;Title&gt;North America sample imagery&lt;/Title&gt;
@@ -70,7 +90,8 @@
70 90 * &lt;/LegendURL&gt;
71 91 * &lt;/Style&gt;
72 92 * &lt;/Layer&gt;
73   - * </code></pre>
  93 + * </code>
  94 + * </pre>
74 95 *
75 96 * </p>
76 97 *
@@ -159,50 +180,130 @@ public void testServiceInfo() {
159 180 assertNotNull(info.getDescription());
160 181 }
161 182
162   - String axisName(CoordinateReferenceSystem crs, int dimension ){
  183 + String axisName(CoordinateReferenceSystem crs, int dimension) {
163 184 return crs.getCoordinateSystem().getAxis(dimension).getName().getCode();
164 185 }
165   -
166   - public void testImgSample130() {
167   - Layer img_sample = find( "nurc:Img_Sample");
168   - assertNotNull("Img_Sample layer found", img_sample );
  186 +
  187 + public void testImgSample130() throws Exception {
  188 + Layer img_sample = find("nurc:Img_Sample");
  189 + assertNotNull("Img_Sample layer found", img_sample);
169 190 CRSEnvelope latLon = img_sample.getLatLonBoundingBox();
170   - assertEquals( "LatLonBoundingBox axis 0 name", "Geodetic longitude", axisName( latLon.getCoordinateReferenceSystem(), 0) );
171   - assertEquals( "LatLonBoundingBox axis 0 name", "Geodetic latitude", axisName( latLon.getCoordinateReferenceSystem(), 1) );
  191 + assertEquals("LatLonBoundingBox axis 0 name", "Geodetic longitude",
  192 + axisName(latLon.getCoordinateReferenceSystem(), 0));
  193 + assertEquals("LatLonBoundingBox axis 0 name", "Geodetic latitude",
  194 + axisName(latLon.getCoordinateReferenceSystem(), 1));
  195 +
  196 + boolean globalXY = Boolean.getBoolean("org.geotools.referencing.forceXY");
172 197
173 198 CRSEnvelope bounds = img_sample.getBoundingBoxes().get("EPSG:4326");
174   - assertEquals( "EPSG:4326 axis 0 name", "Geodetic latitude", axisName( bounds.getCoordinateReferenceSystem(), 0) );
175   - assertEquals( "EPSG:4326 axis 1 name", "Geodetic longitude", axisName( bounds.getCoordinateReferenceSystem(), 1) );
  199 + CoordinateReferenceSystem boundsCRS = bounds.getCoordinateReferenceSystem();
  200 + assertEquals( "EPSG:4326", AxisOrder.EAST_NORTH, CRS.getAxisOrder(boundsCRS) );
176 201
177 202 assertEquals("axis order 0 min", latLon.getMinimum(1), bounds.getMinimum(0));
178 203 assertEquals("axis order 1 min", latLon.getMinimum(0), bounds.getMinimum(1));
179 204 assertEquals("axis order 1 max", latLon.getMaximum(0), bounds.getMaximum(1));
180 205 assertEquals("axis order 1 min", latLon.getMaximum(1), bounds.getMaximum(0));
  206 +
  207 + // GETMAP
  208 + checkGetMap(wms, img_sample, DefaultGeographicCRS.WGS84);
  209 + checkGetMap(wms, img_sample, CRS.decode("CRS:84"));
  210 + checkGetMap(wms, img_sample, CRS.decode("EPSG:4326"));
  211 + checkGetMap(wms, img_sample, CRS.decode("urn:x-ogc:def:crs:EPSG::4326"));
181 212 }
182   -
  213 +
183 214 public void testImageSample111() throws Exception {
184   - WebMapServer wms111 = new WebMapServer( new URL(serverURL +"&VERSION=1.1.1") );
  215 + WebMapServer wms111 = new WebMapServer(new URL(serverURL + "&VERSION=1.1.1"));
185 216 WMSCapabilities caps = wms111.getCapabilities();
186   - assertEquals( "1.1.1", caps.getVersion() );
187   -
188   - Layer img_sample = find("nurc:Img_Sample",caps );
189   - assertNotNull("Img_Sample layer found", img_sample );
  217 + assertEquals("1.1.1", caps.getVersion());
  218 +
  219 + Layer img_sample = find("nurc:Img_Sample", caps);
  220 + assertNotNull("Img_Sample layer found", img_sample);
190 221 CRSEnvelope latLon = img_sample.getLatLonBoundingBox();
191   - assertEquals( "LatLonBoundingBox axis 0 name", "Geodetic longitude", axisName( latLon.getCoordinateReferenceSystem(), 0) );
192   - assertEquals( "LatLonBoundingBox axis 1 name", "Geodetic latitude", axisName( latLon.getCoordinateReferenceSystem(), 1) );
193   -
  222 + assertEquals("LatLonBoundingBox axis 0 name", "Geodetic longitude",
  223 + axisName(latLon.getCoordinateReferenceSystem(), 0));
  224 + assertEquals("LatLonBoundingBox axis 1 name", "Geodetic latitude",
  225 + axisName(latLon.getCoordinateReferenceSystem(), 1));
  226 +
194 227 CRSEnvelope bounds = img_sample.getBoundingBoxes().get("EPSG:4326");
195   - assertEquals( "EPSG:4326 axis 0 name", "Geodetic longitude", axisName( bounds.getCoordinateReferenceSystem(), 0) );
196   - assertEquals( "EPSG:4326 axis 1 name", "Geodetic latitude", axisName( bounds.getCoordinateReferenceSystem(), 1) );
197   -
  228 + CoordinateReferenceSystem boundsCRS = bounds.getCoordinateReferenceSystem();
  229 + assertEquals( "EPSG:4326", AxisOrder.EAST_NORTH, CRS.getAxisOrder(boundsCRS) );;
  230 +
198 231 assertEquals("axis order 0 min", latLon.getMinimum(0), bounds.getMinimum(0));
199 232 assertEquals("axis order 1 min", latLon.getMinimum(1), bounds.getMinimum(1));
200 233 assertEquals("axis order 1 max", latLon.getMaximum(0), bounds.getMaximum(0));
201 234 assertEquals("axis order 1 min", latLon.getMaximum(1), bounds.getMaximum(1));
  235 +
  236 + // GETMAP
  237 + checkGetMap(wms111, img_sample, DefaultGeographicCRS.WGS84);
  238 + checkGetMap(wms111, img_sample, CRS.decode("CRS:84"));
  239 + checkGetMap(wms111, img_sample, CRS.decode("EPSG:4326"));
  240 + checkGetMap(wms111, img_sample, CRS.decode("urn:x-ogc:def:crs:EPSG::4326"));
  241 +
  242 + }
  243 +
  244 + /**
  245 + * Check GetMap request functionality in the provided CRS.
  246 + * <p>
  247 + * Attempt is made to request the entire image.
  248 + *
  249 + * @param wms
  250 + * @param layer
  251 + * @param crs
  252 + */
  253 + private void checkGetMap(WebMapServer wms, Layer layer, CoordinateReferenceSystem crs)
  254 + throws Exception {
202 255
  256 + layer.clearCache();
  257 + CRSEnvelope latLon = layer.getLatLonBoundingBox();
  258 + GeneralEnvelope envelope = wms.getEnvelope(layer, crs);
  259 + assertFalse(envelope.isEmpty() || envelope.isNull() || envelope.isInfinite());
  260 + assertNotNull("Envelope "+CRS.toSRS(crs), envelope);
  261 +
  262 + GetMapRequest getMap = wms.createGetMapRequest();
  263 + OperationType operationType = wms.getCapabilities().getRequest().getGetMap();
  264 +
  265 + getMap.addLayer(layer);
  266 + String version = wms.getCapabilities().getVersion();
  267 + String srs = CRS.toSRS(envelope.getCoordinateReferenceSystem());
203 268
  269 + getMap.setBBox(envelope);
  270 + //getMap.setSRS( srs );
204 271
  272 + String format = format(operationType, "jpeg");
  273 + getMap.setFormat(format);
  274 + getMap.setDimensions(500, 500);
  275 +
  276 + URL url = getMap.getFinalURL();
  277 + GetMapResponse response = wms.issueRequest(getMap);
  278 + assertEquals("image/jpeg", response.getContentType());
  279 +
  280 + InputStream stream = response.getInputStream();
  281 + BufferedImage image = ImageIO.read(stream);
  282 + assertNotNull("jpeg", image);
  283 + assertEquals(500, image.getWidth());
  284 + assertEquals(500, image.getHeight());
205 285
  286 + int rgb = image.getRGB(250, 250);
  287 + Color sample = new Color(rgb);
  288 + boolean forceXY = Boolean.getBoolean(GeoTools.FORCE_LONGITUDE_FIRST_AXIS_ORDER);
  289 + String context = "srs="+srs+" forceXY="+forceXY+" Version="+version;
  290 + if(Color.WHITE.equals(sample)){
  291 + System.out.println("FAIL: "+ context+": GetMap BBOX=" + envelope);
  292 + System.out.println("--> " + url);
  293 + fail( context+": GetMap BBOX=" + envelope );
  294 + }
  295 + else {
  296 + //System.out.println("PASS: "+ context+": GetMap BBOX=" + bbox);
  297 + }
206 298
207 299 }
  300 +
  301 + private String format(OperationType operationType, String search) {
  302 + for (String format : operationType.getFormats()) {
  303 + if (format.contains(search)) {
  304 + return format;
  305 + }
  306 + }
  307 + return null; // not found
  308 + }
208 309 }

0 comments on commit 056965f

Please sign in to comment.
Something went wrong with that request. Please try again.