/* (c) 2017 Open Source Geospatial Foundation - all rights reserved * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.opensearch.eo.kvp; import org.geoserver.platform.OWS20Exception; import org.geoserver.wfs.kvp.BBoxKvpParser; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.referencing.CRS; import org.geotools.referencing.crs.DefaultGeographicCRS; import org.opengis.referencing.FactoryException; import org.opengis.referencing.NoSuchAuthorityCodeException; import org.opengis.referencing.crs.CoordinateReferenceSystem; /** * A parser that allows dateline crossing envelopes * * @author Andrea Aime */ public class OpenSearchBBoxKvpParser extends BBoxKvpParser { @Override protected Object buildEnvelope(int countco, double minx, double miny, double minz, double maxx, double maxy, double maxz, String srs) throws NoSuchAuthorityCodeException, FactoryException { if (countco > 4) { throw new IllegalArgumentException( "Too many coordinates, openSearch cannot handle non flat envelopes yet"); } CoordinateReferenceSystem crs = srs == null ? null : CRS.decode(srs, true); if (crs != null && !CRS.equalsIgnoreMetadata(DefaultGeographicCRS.WGS84, crs)) { throw new OWS20Exception( "OpenSearch for EO requests only support boundig boxes in WGS84", OWS20Exception.OWSExceptionCode.InvalidParameterValue, "box"); } minx = rollLongitude(minx); maxx = rollLongitude(maxx); if (minx > maxx) { // dateline crossing case return new ReferencedEnvelope[] { new ReferencedEnvelope(minx, 180, miny, maxy, crs), new ReferencedEnvelope(-180, maxx, miny, maxy, crs), }; } else { return new ReferencedEnvelope(minx, maxx, miny, maxy, crs); } } protected static double rollLongitude(final double x) { double mod = (x + 180) % 360; if (mod == 0) { return x > 0 ? 180 : -180; } else { return mod - 180; } } }