From c239c1db592716dfa9a9fe04cf878ce438d62486 Mon Sep 17 00:00:00 2001 From: Daniele Romagnoli Date: Mon, 7 Oct 2024 10:55:56 +0200 Subject: [PATCH] [GEOS-11605]: MapML Supporting custom TCRS/gridsets --- .../mapml/images/mapml_tcrs_menu.png | Bin 0 -> 4225 bytes .../mapml/images/mapml_tcrs_selector.png | Bin 0 -> 20448 bytes .../source/extensions/mapml/installation.rst | 29 +- .../geoserver/mapml/MapMLDocumentBuilder.java | 100 ++-- .../org/geoserver/mapml/MapMLFeatureUtil.java | 17 +- .../MapMLHTMLGetFeatureOutputFormat.java | 8 +- .../org/geoserver/mapml/MapMLHTMLOutput.java | 107 ++++- .../org/geoserver/mapml/MapMLURLBuilder.java | 64 +-- .../mapml/gwc/gridset/MapMLGridsets.java | 173 ++++++- .../java/org/geoserver/mapml/tcrs/Bounds.java | 5 + .../java/org/geoserver/mapml/tcrs/Point.java | 5 + .../org/geoserver/mapml/tcrs/TiledCRS.java | 49 +- .../mapml/tcrs/TiledCRSConstants.java | 451 +++++++++++++++--- .../geoserver/mapml/tcrs/TiledCRSFactory.java | 6 +- .../geoserver/mapml/tcrs/TiledCRSParams.java | 33 ++ .../mapml/tcrs/WrappingProjType.java | 90 ++++ .../mapml/web/MapMLTCRSSettingsPage.html | 21 + .../mapml/web/MapMLTCRSSettingsPage.java | 61 +++ .../mapml/web/MapMLTCRSSettingsPanel.html | 16 + .../mapml/web/MapMLTCRSSettingsPanel.java | 87 ++++ .../org/geoserver/mapml/web/img/icons/crs.png | Bin 0 -> 748 bytes .../java/org/geoserver/mapml/xml/Extent.java | 11 +- .../java/org/geoserver/mapml/xml/Link.java | 13 +- .../resources/GeoServerApplication.properties | 7 + .../src/main/resources/applicationContext.xml | 10 + .../mapml/src/main/resources/schema/mapml.rnc | 2 +- .../mapml/src/main/resources/schema/mapml.xsd | 4 +- .../MapMLGetFeatureOutputFormatTest.java | 2 +- .../org/geoserver/mapml/MapMLWMSTest.java | 21 +- .../mapml/tcrs/CustomTiledCRSTest.java | 240 ++++++++++ .../geoserver/mapml/web/MapMLTCRSTest.java | 69 +++ 31 files changed, 1482 insertions(+), 219 deletions(-) create mode 100644 doc/en/user/source/extensions/mapml/images/mapml_tcrs_menu.png create mode 100644 doc/en/user/source/extensions/mapml/images/mapml_tcrs_selector.png create mode 100644 src/extension/mapml/src/main/java/org/geoserver/mapml/tcrs/WrappingProjType.java create mode 100644 src/extension/mapml/src/main/java/org/geoserver/mapml/web/MapMLTCRSSettingsPage.html create mode 100644 src/extension/mapml/src/main/java/org/geoserver/mapml/web/MapMLTCRSSettingsPage.java create mode 100644 src/extension/mapml/src/main/java/org/geoserver/mapml/web/MapMLTCRSSettingsPanel.html create mode 100644 src/extension/mapml/src/main/java/org/geoserver/mapml/web/MapMLTCRSSettingsPanel.java create mode 100644 src/extension/mapml/src/main/java/org/geoserver/mapml/web/img/icons/crs.png create mode 100644 src/extension/mapml/src/test/java/org/geoserver/mapml/tcrs/CustomTiledCRSTest.java create mode 100644 src/extension/mapml/src/test/java/org/geoserver/mapml/web/MapMLTCRSTest.java diff --git a/doc/en/user/source/extensions/mapml/images/mapml_tcrs_menu.png b/doc/en/user/source/extensions/mapml/images/mapml_tcrs_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..2e0fdaf49b2647b867ad9ce3a035f8e36518bcb5 GIT binary patch literal 4225 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 O0BEV{sg^@+L;eSjS2$b% literal 0 HcmV?d00001 diff --git a/doc/en/user/source/extensions/mapml/images/mapml_tcrs_selector.png b/doc/en/user/source/extensions/mapml/images/mapml_tcrs_selector.png new file mode 100644 index 0000000000000000000000000000000000000000..5dc71756f8370b878a32e2caf144a4fa3e4605e5 GIT binary patch literal 20448 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 IGIYKEHyIk*P5=M^ literal 0 HcmV?d00001 diff --git a/doc/en/user/source/extensions/mapml/installation.rst b/doc/en/user/source/extensions/mapml/installation.rst index 1272d9405ac..c4b4fa45ba3 100644 --- a/doc/en/user/source/extensions/mapml/installation.rst +++ b/doc/en/user/source/extensions/mapml/installation.rst @@ -47,6 +47,33 @@ If the ``Represent multi-layer requests as multiple elements`` is checked (and t .. figure:: images/mapml_wms_multi_extent.png +TiledCRS +-------- +MapML supports 4 built-in TiledCRS: + +- MapML:WGS84 (or EPSG:4326) +- MapML:OSMTILE (or EPSG:3857) +- MapML:CBMTILE (or EPSG:3978) +- MapML:APSTILE (or EPSG:5936) + +In addition, is it possible to configure custom TiledCRS based on the available WMTS GridSets. +A new MapML TCRS Settings menu is available in the GeoServer UI on the Settings section: + +.. figure:: images/mapml_tcrs_menu.png + + +It provides a selector containing available GridSets. Administrator can select GridSets from the left list that will be converted to TiledCRSs. + + +.. figure:: images/mapml_tcrs_selector.png + + +Notes: + +- Gridsets containing ":" character in the name won't be listed +- Gridsets with not-numeric levels or without a common prefix won't be listed + + Styles ------ @@ -262,7 +289,7 @@ MapML resources will be available for any published WMS layers by making a GetMa **SRS/CRS** -Note that the WMS SRS or CRS must be one of the projections supported by MapML: +Note that the WMS SRS or CRS must be one of the built-in projections supported by MapML or one of the TCRS configured through the dedicated section. Built-in MapML CRS are: - MapML:WGS84 (or EPSG:4326) - MapML:OSMTILE (or EPSG:3857) diff --git a/src/extension/mapml/src/main/java/org/geoserver/mapml/MapMLDocumentBuilder.java b/src/extension/mapml/src/main/java/org/geoserver/mapml/MapMLDocumentBuilder.java index 51c40cd7f0a..684c96dc3b9 100644 --- a/src/extension/mapml/src/main/java/org/geoserver/mapml/MapMLDocumentBuilder.java +++ b/src/extension/mapml/src/main/java/org/geoserver/mapml/MapMLDocumentBuilder.java @@ -13,7 +13,6 @@ import static org.geoserver.mapml.MapMLConstants.MAPML_USE_FEATURES; import static org.geoserver.mapml.MapMLConstants.MAPML_USE_REMOTE; import static org.geoserver.mapml.MapMLConstants.MAPML_USE_TILES; -import static org.geoserver.mapml.MapMLHTMLOutput.PREVIEW_TCRS_MAP; import static org.geoserver.mapml.template.MapMLMapTemplate.MAPML_PREVIEW_HEAD_FTL; import static org.geoserver.mapml.template.MapMLMapTemplate.MAPML_XML_HEAD_FTL; import static org.geoserver.wms.capabilities.DimensionHelper.getDataType; @@ -66,6 +65,7 @@ import org.geoserver.gwc.layer.GeoServerTileLayer; import org.geoserver.mapml.tcrs.Bounds; import org.geoserver.mapml.tcrs.TiledCRS; +import org.geoserver.mapml.tcrs.WrappingProjType; import org.geoserver.mapml.template.MapMLMapTemplate; import org.geoserver.mapml.xml.AxisType; import org.geoserver.mapml.xml.Base; @@ -157,7 +157,7 @@ public class MapMLDocumentBuilder { private String imageFormat = DEFAULT_MIME_TYPE; private String baseUrl; private String baseUrlPattern; - private ProjType projType; + private WrappingProjType projType; private MetadataMap layerMeta; private int height; private int width; @@ -408,7 +408,7 @@ private MapMLLayerMetadata layersToOneMapMLLayerMetadata(List layers) mapMLLayerMetadata.setTimeEnabled(false); mapMLLayerMetadata.setElevationEnabled(false); mapMLLayerMetadata.setTransparent(transparent.orElse(false)); - ProjType projType = parseProjType(); + WrappingProjType projType = parseProjType(); mapMLLayerMetadata.setBbbox(layersToBBBox(layers, projType)); mapMLLayerMetadata.setQueryable(layersToQueryable(layers)); mapMLLayerMetadata.setLayerLabel(layersToLabel(layers)); @@ -422,9 +422,9 @@ private MapMLLayerMetadata layersToOneMapMLLayerMetadata(List layers) * Parses the projection into a ProjType, or throws a proper service exception indicating the * unsupported CRS */ - private ProjType parseProjType() { + private WrappingProjType parseProjType() { try { - return ProjType.fromValue(proj.toUpperCase()); + return new WrappingProjType(proj.toUpperCase()); } catch (IllegalArgumentException | FactoryException iae) { // figure out the parameter name (version dependent) and the actual original // string value for the srs/crs parameter @@ -488,10 +488,9 @@ private String layersToLabel(List layers) { * @param projType ProjType object * @return ReferencedEnvelope object */ - private ReferencedEnvelope layersToBBBox(List layers, ProjType projType) { - + private ReferencedEnvelope layersToBBBox(List layers, WrappingProjType projType) { ReferencedEnvelope bbbox; - bbbox = new ReferencedEnvelope(PREVIEW_TCRS_MAP.get(projType.value()).getCRS()); + bbbox = new ReferencedEnvelope(projType.getCRS()); for (int i = 0; i < layers.size(); i++) { RawLayer layer = layers.get(i); try { @@ -502,26 +501,20 @@ private ReferencedEnvelope layersToBBBox(List layers, ProjType projTyp .getResource() .boundingBox(); if (i == 0) { - bbbox = - layerBbbox.transform( - PREVIEW_TCRS_MAP.get(projType.value()).getCRS(), true); + bbbox = layerBbbox.transform(projType.getCRS(), true); } else { - bbbox.expandToInclude( - layerBbbox.transform( - PREVIEW_TCRS_MAP.get(projType.value()).getCRS(), true)); + bbbox.expandToInclude(layerBbbox.transform(projType.getCRS(), true)); } } catch (Exception e) { // get the default max/min of the pcrs from the TCRS - Bounds defaultBounds = PREVIEW_TCRS_MAP.get(projType.value()).getBounds(); + Bounds defaultBounds = projType.getTiledCRS().getBounds(); double x1, x2, y1, y2; x1 = defaultBounds.getMin().x; x2 = defaultBounds.getMax().x; y1 = defaultBounds.getMin().y; y2 = defaultBounds.getMax().y; // use the bounds of the TCRS as the default bounds for this layer - bbbox = - new ReferencedEnvelope( - x1, x2, y1, y2, PREVIEW_TCRS_MAP.get(projType.value()).getCRS()); + bbbox = new ReferencedEnvelope(x1, x2, y1, y2, projType.getCRS()); } } @@ -595,7 +588,7 @@ private MapMLLayerMetadata layerToMapMLLayerMetadata(RawLayer layer, String styl .orElse(DEFAULT_MIME_TYPE) .toString(); } - ProjType projType = parseProjType(); + WrappingProjType projType = parseProjType(); cqlFilter = cql != null ? cql : ""; tileLayerExists = gwc.hasTileLayer(isLayerGroup ? layerGroupInfo : layerInfo) @@ -843,15 +836,18 @@ private HeadContent prepareHead() throws IOException { selfStyleLink.setHref(selfStyleURL); links.add(selfStyleLink); // alternate projection links + ProjType builtInProj = projType.unwrap(); for (ProjType pt : ProjType.values()) { // skip the current proj - if (pt.equals(projType)) continue; + + if (pt.equals(builtInProj)) continue; try { Link projectionLink = new Link(); projectionLink.setRel(RelType.ALTERNATE); - projectionLink.setProjection(pt); + projectionLink.setProjection(pt.value()); // reproject the bounds - ReferencedEnvelope reprojectedBounds = reproject(projectedBox, pt); + ReferencedEnvelope reprojectedBounds = + reproject(projectedBox, new WrappingProjType(pt)); // Copy the base params to create one for self style Map projParams = new HashMap<>(wmsParams); projParams.put("crs", pt.getCRSCode()); @@ -972,9 +968,9 @@ private String buildStyles() throws IOException { * @throws FactoryException In the event of a factory error. * @throws TransformException In the event of a transform error. */ - private ReferencedEnvelope reproject(ReferencedEnvelope bounds, ProjType pt) + private ReferencedEnvelope reproject(ReferencedEnvelope bounds, WrappingProjType pt) throws FactoryException, TransformException { - CoordinateReferenceSystem targetCRS = PREVIEW_TCRS_MAP.get(pt.value()).getCRS(); + CoordinateReferenceSystem targetCRS = pt.getCRS(); // leverage the rendering ProjectionHandlers to build a set of envelopes // inside the valid area of the target CRS, and fuse them ProjectionHandler ph = ProjectionHandlerFinder.getHandler(bounds, targetCRS, true); @@ -1019,7 +1015,8 @@ private List prepareExtents() throws IOException { List extents = new ArrayList<>(); for (MapMLLayerMetadata mapMLLayerMetadata : mapMLLayerMetadataList) { Extent extent = new Extent(); - extent.setUnits(projType); + TiledCRS tiledCRS = projType.getTiledCRS(); + extent.setUnits(tiledCRS.getName()); extentList = extent.getInputOrDatalistOrLink(); // zoom @@ -1036,7 +1033,6 @@ private List prepareExtents() throws IOException { } Input extentZoomInput = new Input(); - TiledCRS tiledCRS = PREVIEW_TCRS_MAP.get(projType.value()); extentZoomInput.setName("z"); extentZoomInput.setType(InputType.ZOOM); // passing in max sld denominator to get min zoom @@ -1046,7 +1042,7 @@ private List prepareExtents() throws IOException { tiledCRS.getMinZoomForDenominator( scaleDenominators.getMaxValue().intValue())) : "0"); - int mxz = PREVIEW_TCRS_MAP.get(projType.value()).getScales().length - 1; + int mxz = tiledCRS.getScales().length - 1; // passing in min sld denominator to get max zoom String maxZoom = scaleDenominators != null @@ -1362,7 +1358,7 @@ private void generateTiledWMSClientLinks(MapMLLayerMetadata mapMLLayerMetadata) // of WGS84 is a cartesian cs per the table on this page: // https://docs.geotools.org/stable/javadocs/org/opengis/referencing/cs/package-summary.html#AxisNames // input.setAxis(previewTcrsMap.get(projType.value()).getCRS(UnitType.PCRS).getAxisByDirection(AxisDirection.DISPLAY_RIGHT)); - bbbox = new ReferencedEnvelope(PREVIEW_TCRS_MAP.get(projType.value()).getCRS()); + bbbox = new ReferencedEnvelope(projType.getCRS()); LayerInfo layerInfo = mapMLLayerMetadata.getLayerInfo(); try { @@ -1370,12 +1366,12 @@ private void generateTiledWMSClientLinks(MapMLLayerMetadata mapMLLayerMetadata) mapMLLayerMetadata.isLayerGroup() ? mapMLLayerMetadata.getLayerGroupInfo().getBounds() : layerInfo.getResource().boundingBox(); - bbbox = bbbox.transform(PREVIEW_TCRS_MAP.get(projType.value()).getCRS(), true); + bbbox = bbbox.transform(projType.getCRS(), true); } catch (Exception e) { // sometimes, when the geographicBox is right to 90N or 90S, in epsg:3857, // the transform method will throw. In that case, use the // bounds of the TCRS to define the geographicBox for the layer - TiledCRS t = PREVIEW_TCRS_MAP.get(projType.value()); + TiledCRS t = projType.getTiledCRS(); double x1 = t.getBounds().getMax().x; double y1 = t.getBounds().getMax().y; double x2 = t.getBounds().getMin().x; @@ -1392,7 +1388,7 @@ private void generateTiledWMSClientLinks(MapMLLayerMetadata mapMLLayerMetadata) input.setUnits(UnitType.TILEMATRIX); input.setPosition(PositionType.TOP_LEFT); input.setRel(InputRelType.TILE); - input.setAxis(projType == projType.WGS_84 ? AxisType.LONGITUDE : AxisType.EASTING); + input.setAxis(ProjType.WGS_84 == projType.unwrap() ? AxisType.LONGITUDE : AxisType.EASTING); input.setMin(Double.toString(bbbox.getMinX())); input.setMax(Double.toString(bbbox.getMaxX())); extentList.add(input); @@ -1404,7 +1400,7 @@ private void generateTiledWMSClientLinks(MapMLLayerMetadata mapMLLayerMetadata) input.setUnits(UnitType.TILEMATRIX); input.setPosition(PositionType.BOTTOM_LEFT); input.setRel(InputRelType.TILE); - input.setAxis(projType == projType.WGS_84 ? AxisType.LATITUDE : AxisType.NORTHING); + input.setAxis(ProjType.WGS_84 == projType.unwrap() ? AxisType.LATITUDE : AxisType.NORTHING); input.setMin(Double.toString(bbbox.getMinY())); input.setMax(Double.toString(bbbox.getMaxY())); extentList.add(input); @@ -1416,7 +1412,7 @@ private void generateTiledWMSClientLinks(MapMLLayerMetadata mapMLLayerMetadata) input.setUnits(UnitType.TILEMATRIX); input.setPosition(PositionType.TOP_RIGHT); input.setRel(InputRelType.TILE); - input.setAxis(projType == projType.WGS_84 ? AxisType.LONGITUDE : AxisType.EASTING); + input.setAxis(ProjType.WGS_84 == projType.unwrap() ? AxisType.LONGITUDE : AxisType.EASTING); input.setMin(Double.toString(bbbox.getMinX())); input.setMax(Double.toString(bbbox.getMaxX())); extentList.add(input); @@ -1428,7 +1424,7 @@ private void generateTiledWMSClientLinks(MapMLLayerMetadata mapMLLayerMetadata) input.setUnits(UnitType.TILEMATRIX); input.setPosition(PositionType.TOP_LEFT); input.setRel(InputRelType.TILE); - input.setAxis(projType == projType.WGS_84 ? AxisType.LATITUDE : AxisType.NORTHING); + input.setAxis(ProjType.WGS_84 == projType.unwrap() ? AxisType.LATITUDE : AxisType.NORTHING); input.setMin(Double.toString(bbbox.getMinY())); input.setMax(Double.toString(bbbox.getMaxY())); extentList.add(input); @@ -1490,7 +1486,7 @@ public void generateWMSClientLinks(MapMLLayerMetadata mapMLLayerMetadata) { try { // initialization is necessary so as to set the PCRS to which // the resource's geographicBox will be transformed, below. - bbbox = new ReferencedEnvelope(PREVIEW_TCRS_MAP.get(projType.value()).getCRS()); + bbbox = new ReferencedEnvelope(projType.getCRS()); bbbox = mapMLLayerMetadata.isLayerGroup ? mapMLLayerMetadata.getLayerGroupInfo().getBounds() @@ -1503,19 +1499,17 @@ public void generateWMSClientLinks(MapMLLayerMetadata mapMLLayerMetadata) { // the projectedBox.transform will leave the CRS set to that of whatever // was returned by layerInfo.getResource().boundingBox() or // layerGroupInfo.getBounds(), above. - bbbox = bbbox.transform(PREVIEW_TCRS_MAP.get(projType.value()).getCRS(), true); + bbbox = bbbox.transform(projType.getCRS(), true); } catch (Exception e) { // get the default max/min of the pcrs from the TCRS - Bounds defaultBounds = PREVIEW_TCRS_MAP.get(projType.value()).getBounds(); + Bounds defaultBounds = projType.getTiledCRS().getBounds(); double x1, x2, y1, y2; x1 = defaultBounds.getMin().x; x2 = defaultBounds.getMax().x; y1 = defaultBounds.getMin().y; y2 = defaultBounds.getMax().y; // use the bounds of the TCRS as the default bounds for this layer - bbbox = - new ReferencedEnvelope( - x1, x2, y1, y2, PREVIEW_TCRS_MAP.get(projType.value()).getCRS()); + bbbox = new ReferencedEnvelope(x1, x2, y1, y2, projType.getCRS()); } } @@ -1524,10 +1518,10 @@ public void generateWMSClientLinks(MapMLLayerMetadata mapMLLayerMetadata) { Input input = new Input(); input.setName("xmin"); input.setType(InputType.LOCATION); - input.setUnits(projType == projType.WGS_84 ? UnitType.GCRS : UnitType.PCRS); + input.setUnits(ProjType.WGS_84 == projType.unwrap() ? UnitType.GCRS : UnitType.PCRS); input.setPosition(PositionType.TOP_LEFT); input.setRel(InputRelType.IMAGE); - input.setAxis(projType == projType.WGS_84 ? AxisType.LONGITUDE : AxisType.EASTING); + input.setAxis(ProjType.WGS_84 == projType.unwrap() ? AxisType.LONGITUDE : AxisType.EASTING); input.setMin(Double.toString(bbbox.getMinX())); input.setMax(Double.toString(bbbox.getMaxX())); extentList.add(input); @@ -1536,10 +1530,10 @@ public void generateWMSClientLinks(MapMLLayerMetadata mapMLLayerMetadata) { input = new Input(); input.setName("ymin"); input.setType(InputType.LOCATION); - input.setUnits(projType == projType.WGS_84 ? UnitType.GCRS : UnitType.PCRS); + input.setUnits(ProjType.WGS_84 == projType.unwrap() ? UnitType.GCRS : UnitType.PCRS); input.setPosition(PositionType.BOTTOM_LEFT); input.setRel(InputRelType.IMAGE); - input.setAxis(projType == projType.WGS_84 ? AxisType.LATITUDE : AxisType.NORTHING); + input.setAxis(ProjType.WGS_84 == projType.unwrap() ? AxisType.LATITUDE : AxisType.NORTHING); input.setMin(Double.toString(bbbox.getMinY())); input.setMax(Double.toString(bbbox.getMaxY())); extentList.add(input); @@ -1548,10 +1542,10 @@ public void generateWMSClientLinks(MapMLLayerMetadata mapMLLayerMetadata) { input = new Input(); input.setName("xmax"); input.setType(InputType.LOCATION); - input.setUnits(projType == projType.WGS_84 ? UnitType.GCRS : UnitType.PCRS); + input.setUnits(ProjType.WGS_84 == projType.unwrap() ? UnitType.GCRS : UnitType.PCRS); input.setPosition(PositionType.TOP_RIGHT); input.setRel(InputRelType.IMAGE); - input.setAxis(projType == projType.WGS_84 ? AxisType.LONGITUDE : AxisType.EASTING); + input.setAxis(ProjType.WGS_84 == projType.unwrap() ? AxisType.LONGITUDE : AxisType.EASTING); input.setMin(Double.toString(bbbox.getMinX())); input.setMax(Double.toString(bbbox.getMaxX())); extentList.add(input); @@ -1560,10 +1554,10 @@ public void generateWMSClientLinks(MapMLLayerMetadata mapMLLayerMetadata) { input = new Input(); input.setName("ymax"); input.setType(InputType.LOCATION); - input.setUnits(projType == projType.WGS_84 ? UnitType.GCRS : UnitType.PCRS); + input.setUnits(ProjType.WGS_84 == projType.unwrap() ? UnitType.GCRS : UnitType.PCRS); input.setPosition(PositionType.TOP_LEFT); input.setRel(InputRelType.IMAGE); - input.setAxis(projType == projType.WGS_84 ? AxisType.LATITUDE : AxisType.NORTHING); + input.setAxis(ProjType.WGS_84 == projType.unwrap() ? AxisType.LATITUDE : AxisType.NORTHING); input.setMin(Double.toString(bbbox.getMinY())); input.setMax(Double.toString(bbbox.getMaxY())); extentList.add(input); @@ -2314,7 +2308,7 @@ static class MapMLLayerMetadata { private boolean isTransparent; private String layerName; private String layerTitle; - private ProjType projType; + private WrappingProjType projType; private String styleName; private boolean tileLayerExists; @@ -2361,7 +2355,7 @@ public void setUseFeatures(boolean useFeatures) { * @param isTransparent boolean * @param layerName String * @param layerTitle String - * @param projType ProjType object + * @param projType ProjType * @param styleName String * @param tileLayerExists boolean * @param useTiles boolean @@ -2378,7 +2372,7 @@ public MapMLLayerMetadata( boolean isTransparent, String layerName, String layerTitle, - ProjType projType, + WrappingProjType projType, String styleName, boolean tileLayerExists, boolean useTiles, @@ -2678,7 +2672,7 @@ public void setLayerTitle(String layerTitle) { * * @return ProjType */ - public ProjType getProjType() { + public WrappingProjType getProjType() { return projType; } @@ -2687,7 +2681,7 @@ public ProjType getProjType() { * * @param projType ProjType */ - public void setProjType(ProjType projType) { + public void setProjType(WrappingProjType projType) { this.projType = projType; } diff --git a/src/extension/mapml/src/main/java/org/geoserver/mapml/MapMLFeatureUtil.java b/src/extension/mapml/src/main/java/org/geoserver/mapml/MapMLFeatureUtil.java index 5fe33a7dec8..47ac81aa1a0 100644 --- a/src/extension/mapml/src/main/java/org/geoserver/mapml/MapMLFeatureUtil.java +++ b/src/extension/mapml/src/main/java/org/geoserver/mapml/MapMLFeatureUtil.java @@ -37,7 +37,6 @@ import org.geoserver.mapml.xml.Link; import org.geoserver.mapml.xml.Mapml; import org.geoserver.mapml.xml.Meta; -import org.geoserver.mapml.xml.ProjType; import org.geoserver.mapml.xml.RelType; import org.geoserver.ows.Request; import org.geoserver.ows.URLMangler; @@ -45,7 +44,6 @@ import org.geoserver.platform.ServiceException; import org.geoserver.wms.featureinfo.FeatureTemplate; import org.geotools.api.feature.simple.SimpleFeature; -import org.geotools.api.referencing.FactoryException; import org.geotools.api.referencing.crs.CoordinateReferenceSystem; import org.geotools.api.referencing.crs.GeodeticCRS; import org.geotools.api.style.Style; @@ -409,7 +407,7 @@ private static Set deduceProjectionAndExtent( if (requestCRS != null) { responseCRS = requestCRS; responseCRSCode = CRS.toSRS(requestCRS); - tcrs = TiledCRSConstants.lookupTCRS(responseCRSCode); + tcrs = TiledCRSConstants.lookupTCRSParams(responseCRSCode); if (tcrs != null) { projection.setContent(tcrs.getName()); crs = (responseCRS instanceof GeodeticCRS) ? "gcrs" : "pcrs"; @@ -453,7 +451,7 @@ private static String getExtent( "top-left-easting=%1$.2f,top-left-northing=%2$.2f,bottom-right-easting=%3$.2f,bottom-right-northing=%4$.2f"; double minLong, minLat, maxLong, maxLat; double minEasting, minNorthing, maxEasting, maxNorthing; - TiledCRSParams tcrs = TiledCRSConstants.lookupTCRS(responseCRSCode); + TiledCRSParams tcrs = TiledCRSConstants.lookupTCRSParams(responseCRSCode); try { if (responseCRS instanceof GeodeticCRS) { re = r.getLatLonBoundingBox(); @@ -507,14 +505,10 @@ public static List alternateProjections( ArrayList links = new ArrayList<>(); Set projections = TiledCRSConstants.tiledCRSBySrsName.keySet(); projections.forEach( - (String p) -> { + (String proj) -> { Link l = new Link(); - TiledCRSParams projection = TiledCRSConstants.lookupTCRS(p); - try { - l.setProjection(ProjType.fromValue(projection.getName())); - } catch (FactoryException e) { - throw new ServiceException("Invalid TCRS name"); - } + TiledCRSParams projection = TiledCRSConstants.lookupTCRSParams(proj); + l.setProjection(projection.getName()); l.setRel(RelType.ALTERNATE); query.put("srsName", "MapML:" + projection.getName()); HashMap kvp = new HashMap<>(query.size()); @@ -529,7 +523,6 @@ public static List alternateProjections( base, path, kvp, URLMangler.URLType.SERVICE))); links.add(l); }); - return links; } diff --git a/src/extension/mapml/src/main/java/org/geoserver/mapml/MapMLHTMLGetFeatureOutputFormat.java b/src/extension/mapml/src/main/java/org/geoserver/mapml/MapMLHTMLGetFeatureOutputFormat.java index d7cfd22d05a..609ef30943c 100644 --- a/src/extension/mapml/src/main/java/org/geoserver/mapml/MapMLHTMLGetFeatureOutputFormat.java +++ b/src/extension/mapml/src/main/java/org/geoserver/mapml/MapMLHTMLGetFeatureOutputFormat.java @@ -20,7 +20,7 @@ import javax.servlet.http.HttpServletRequest; import org.geoserver.catalog.LayerInfo; import org.geoserver.config.GeoServer; -import org.geoserver.mapml.xml.ProjType; +import org.geoserver.mapml.tcrs.WrappingProjType; import org.geoserver.ows.Dispatcher; import org.geoserver.ows.Request; import org.geoserver.ows.URLMangler; @@ -83,7 +83,7 @@ protected void write( ReferencedEnvelope projectedBbox = extractBbox(fc); LayerInfo layerInfo = gs.getCatalog().getLayerByName(fc.getSchema().getTypeName()); CoordinateReferenceSystem crs = projectedBbox.getCoordinateReferenceSystem(); - ProjType projType = parseProjType(request); + WrappingProjType projType = parseProjType(request); double longitude; double latitude; ReferencedEnvelope geographicBox; @@ -116,7 +116,7 @@ protected void write( osw.flush(); } - private ProjType parseProjType(Request request) throws ServiceException { + private WrappingProjType parseProjType(Request request) throws ServiceException { try { Map rawKvp = request.getRawKvp(); String srs; @@ -127,7 +127,7 @@ private ProjType parseProjType(Request request) throws ServiceException { } else { srs = "EPSG:4326"; } - return ProjType.fromValue(srs.toUpperCase()); + return new WrappingProjType(srs.toUpperCase()); } catch (IllegalArgumentException | FactoryException iae) { // figure out the parameter name (version dependent) and the actual original // string value for the srs/crs parameter diff --git a/src/extension/mapml/src/main/java/org/geoserver/mapml/MapMLHTMLOutput.java b/src/extension/mapml/src/main/java/org/geoserver/mapml/MapMLHTMLOutput.java index 4c45c3c817e..9ce6d2671ce 100644 --- a/src/extension/mapml/src/main/java/org/geoserver/mapml/MapMLHTMLOutput.java +++ b/src/extension/mapml/src/main/java/org/geoserver/mapml/MapMLHTMLOutput.java @@ -6,32 +6,27 @@ import static org.apache.commons.text.StringEscapeUtils.escapeHtml4; -import java.util.HashMap; +import java.util.Locale; import javax.servlet.http.HttpServletRequest; import org.geoserver.mapml.tcrs.Bounds; import org.geoserver.mapml.tcrs.Point; import org.geoserver.mapml.tcrs.TiledCRS; -import org.geoserver.mapml.xml.ProjType; +import org.geoserver.mapml.tcrs.TiledCRSParams; +import org.geoserver.mapml.tcrs.WrappingProjType; import org.geoserver.ows.URLMangler; import org.geoserver.ows.util.ResponseUtils; +import org.geotools.api.referencing.crs.CoordinateReferenceSystem; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.referencing.CRS; +import org.geotools.referencing.proj.PROJFormattable; +import org.geotools.referencing.proj.PROJFormatter; /** Class delegated to build an HTML Document embedding a MapML Viewer. */ public class MapMLHTMLOutput { - public static final HashMap PREVIEW_TCRS_MAP = new HashMap<>(); - - static { - PREVIEW_TCRS_MAP.put("OSMTILE", new TiledCRS("OSMTILE")); - PREVIEW_TCRS_MAP.put("CBMTILE", new TiledCRS("CBMTILE")); - PREVIEW_TCRS_MAP.put("APSTILE", new TiledCRS("APSTILE")); - PREVIEW_TCRS_MAP.put("WGS84", new TiledCRS("WGS84")); - } - private String layerLabel; private HttpServletRequest request; - private ProjType projType; + private WrappingProjType projType; private String sourceUrL; private int zoom = 0; private Double latitude = 0.0; @@ -54,7 +49,7 @@ private MapMLHTMLOutput(HTMLOutputBuilder builder) { public static class HTMLOutputBuilder { private String layerLabel; private HttpServletRequest request; - private ProjType projType; + private WrappingProjType projType; private String sourceUrL; private ReferencedEnvelope projectedBbox; private int zoom = 0; @@ -72,7 +67,7 @@ public HTMLOutputBuilder setRequest(HttpServletRequest request) { return this; } - public HTMLOutputBuilder setProjType(ProjType projType) { + public HTMLOutputBuilder setProjType(WrappingProjType projType) { this.projType = projType; return this; } @@ -127,6 +122,7 @@ public String toHTML() { .append("mapml-viewer:not(:defined) > * { display: none; } n") .append("map-layer { display: none; }\n") .append("\n") + .append(buildProjectionScript(projType)) .append("