From 752711ef1fd368b81455b7395cf988233b056137 Mon Sep 17 00:00:00 2001 From: Stephan Reichhelm Date: Mon, 10 Oct 2022 12:39:37 +0200 Subject: [PATCH 1/8] add extension point for rendering of well known mark symbols --- .../rendering/r2d/Java2DFillRenderer.java | 32 ++- .../deegree/rendering/r2d/RenderHelper.java | 66 ++++- .../se/parser/GraphicSymbologyParser.java | 20 +- .../style/styling/mark/BoundedShape.java | 228 ++++++++++++++++++ .../styling/mark/WellKnownNameLoader.java | 86 +++++++ .../styling/mark/WellKnownNameManager.java | 150 ++++++++++++ .../org/deegree/style/utils/ShapeHelper.java | 134 ++++++---- .../org.deegree.workspace.Initializable | 1 + 8 files changed, 654 insertions(+), 63 deletions(-) create mode 100644 deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/mark/BoundedShape.java create mode 100644 deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/mark/WellKnownNameLoader.java create mode 100644 deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/mark/WellKnownNameManager.java create mode 100644 deegree-core/deegree-core-style/src/main/resources/META-INF/services/org.deegree.workspace.Initializable diff --git a/deegree-core/deegree-core-rendering-2d/src/main/java/org/deegree/rendering/r2d/Java2DFillRenderer.java b/deegree-core/deegree-core-rendering-2d/src/main/java/org/deegree/rendering/r2d/Java2DFillRenderer.java index 679849736f..ffd7704490 100644 --- a/deegree-core/deegree-core-rendering-2d/src/main/java/org/deegree/rendering/r2d/Java2DFillRenderer.java +++ b/deegree-core/deegree-core-rendering-2d/src/main/java/org/deegree/rendering/r2d/Java2DFillRenderer.java @@ -1,4 +1,3 @@ -//$HeadURL$ /*---------------------------------------------------------------------------- This file is part of deegree, http://deegree.org/ Copyright (C) 2001-2012 by: @@ -54,16 +53,13 @@ Occam Labs UG (haftungsbeschränkt) import static java.awt.image.BufferedImage.TYPE_INT_ARGB; import static org.deegree.commons.utils.math.MathUtils.round; -import static org.deegree.rendering.r2d.RenderHelper.renderMark; - +import static org.deegree.rendering.r2d.RenderHelper.renderMarkForFill; /** * Responsible for applying fill stylings to a graphics 2d. * * @author Andreas Schmitz - * @author last edited by: $Author: stranger $ - * - * @version $Revision: $, $Date: $ + * @author Stephan Reichhelm */ class Java2DFillRenderer { @@ -82,16 +78,18 @@ void applyGraphicFill( Graphic graphic, UOM uom ) { if ( graphic.image == null ) { int size = round( uomCalculator.considerUOM( graphic.size, uom ) ); - img = new BufferedImage( size, size, TYPE_INT_ARGB ); - Graphics2D g = img.createGraphics(); - Java2DRenderer renderer = new Java2DRenderer( g ); + if ( graphic.imageURL == null ) { - renderMark( graphic.mark, graphic.size < 0 ? 6 : size, uom, renderer.rendererContext, 0, 0, - graphic.rotation ); + img = renderMarkForFill( graphic.mark, graphic.size < 0 ? 6 : size, uom, graphic.rotation, + graphics != null ? graphics.getRenderingHints() : null ); + graphicBounds = getImageBounds( img, graphic, 0, 0, uom ); } else { + img = new BufferedImage( size, size, TYPE_INT_ARGB ); + Graphics2D g = img.createGraphics(); + Java2DRenderer renderer = new Java2DRenderer( g ); img = renderer.rendererContext.svgRenderer.prepareSvg( graphicBounds, graphic ); + g.dispose(); } - g.dispose(); } else { img = graphic.image; } @@ -111,6 +109,16 @@ void applyFill( Fill fill, UOM uom ) { } } + Rectangle2D.Double getImageBounds( BufferedImage image, Graphic graphic, double x, double y, UOM uom ) { + double width, height; + width = image.getWidth(); + height = image.getHeight(); + double x0 = x - width * graphic.anchorPointX + uomCalculator.considerUOM( graphic.displacementX, uom ); + double y0 = y - height * graphic.anchorPointY + uomCalculator.considerUOM( graphic.displacementY, uom ); + + return new Rectangle2D.Double( x0, y0, width, height ); + } + Rectangle2D.Double getGraphicBounds( Graphic graphic, double x, double y, UOM uom ) { double width, height; if ( graphic.image != null ) { diff --git a/deegree-core/deegree-core-rendering-2d/src/main/java/org/deegree/rendering/r2d/RenderHelper.java b/deegree-core/deegree-core-rendering-2d/src/main/java/org/deegree/rendering/r2d/RenderHelper.java index 25aa49d041..18d2724946 100644 --- a/deegree-core/deegree-core-rendering-2d/src/main/java/org/deegree/rendering/r2d/RenderHelper.java +++ b/deegree-core/deegree-core-rendering-2d/src/main/java/org/deegree/rendering/r2d/RenderHelper.java @@ -1,4 +1,3 @@ -//$HeadURL$ /*---------------------------------------------------------------------------- This file is part of deegree, http://deegree.org/ Copyright (C) 2001-2009 by: @@ -49,9 +48,13 @@ import static org.deegree.style.utils.ShapeHelper.getShapeFromMark; import static org.slf4j.LoggerFactory.getLogger; +import java.awt.Graphics2D; +import java.awt.RenderingHints; import java.awt.Shape; import java.awt.geom.AffineTransform; - +import java.awt.geom.GeneralPath; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; import org.deegree.commons.tom.ReferenceResolvingException; import org.deegree.commons.utils.DoublePair; import org.deegree.commons.utils.MapUtils; @@ -63,15 +66,14 @@ import org.deegree.geometry.GeometryTransformer; import org.deegree.style.styling.components.Mark; import org.deegree.style.styling.components.UOM; +import org.deegree.style.utils.ShapeHelper; import org.slf4j.Logger; /** * RenderHelper * * @author Andreas Schmitz - * @author last edited by: $Author$ - * - * @version $Revision$, $Date$ + * @author Stephan Reichhelm */ public class RenderHelper { @@ -108,6 +110,60 @@ public static void renderMark( Mark mark, int size, UOM uom, RendererContext con } } + /** + * Render Mark to be usable for texture filling of areas + * + * @param mark the mark to render + * @param size size + * @param uom unit of measure + * @param rotation angle measured in degrees + * @param hints rendering hints, if available + * @return rendered image + */ + public static BufferedImage renderMarkForFill( Mark mark, int size, UOM uom, double rotation, RenderingHints hints ) { + if ( size == 0 ) { + LOG.debug( "Not rendering a symbol because the size is zero." ); + return new BufferedImage( size, size, BufferedImage.TYPE_INT_ARGB ); + } + if ( mark.fill == null && mark.stroke == null ) { + LOG.debug( "Not rendering a symbol because no fill/stroke is available/configured." ); + return new BufferedImage( size, size, BufferedImage.TYPE_INT_ARGB ); + } + + Shape shape = ShapeHelper.getShapeFromMarkForFill( mark, size - 1, rotation ); + Rectangle2D box = shape.getBounds2D(); + + // TRICKY fall back to size if width or height is less than 1 (ex. a line) + int w = (int)Math.round(box.getWidth() < 1 ? size : box.getWidth()); + int h = (int)Math.round(box.getHeight() < 1 ? size : box.getHeight()); + + BufferedImage img = new BufferedImage( w, h, BufferedImage.TYPE_INT_ARGB ); + Graphics2D g = img.createGraphics(); + if ( hints != null ) { + // reuse current rendering hints (ex. anti-aliasing) + g.setRenderingHints( hints ); + } + Java2DRenderer renderer = new Java2DRenderer( g ); + + GeneralPath union = new GeneralPath( shape ); + double[] pos = { -w, -h, 0, -h, +w, -h, -w, 0, w, 0, -w, h, 0, h, w, h }; + for ( int i = 0, j = pos.length - 2; i < j; i += 2 ) { + AffineTransform at = AffineTransform.getTranslateInstance( pos[i], pos[i + 1] ); + union.append( shape.getPathIterator( at ), false ); + } + + if ( mark.fill != null ) { + renderer.rendererContext.fillRenderer.applyFill( mark.fill, uom ); + g.fill( union ); + } + if ( mark.stroke != null ) { + renderer.rendererContext.strokeRenderer.applyStroke( mark.stroke, uom, union, 0, null ); + } + + g.dispose(); + return img; + } + /** * @param mapWidth * @param mapHeight diff --git a/deegree-core/deegree-core-style/src/main/java/org/deegree/style/se/parser/GraphicSymbologyParser.java b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/se/parser/GraphicSymbologyParser.java index 31579bd5fc..ab28997e2f 100644 --- a/deegree-core/deegree-core-style/src/main/java/org/deegree/style/se/parser/GraphicSymbologyParser.java +++ b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/se/parser/GraphicSymbologyParser.java @@ -65,6 +65,7 @@ Occam Labs UG (haftungsbeschränkt) import java.util.List; import java.util.Map; +import java.util.function.Function; import javax.imageio.ImageIO; import javax.xml.stream.Location; import javax.xml.stream.XMLStreamException; @@ -82,6 +83,7 @@ Occam Labs UG (haftungsbeschränkt) import org.deegree.style.styling.components.Mark; import org.deegree.style.styling.components.Mark.SimpleMark; import org.deegree.style.styling.components.Stroke; +import org.deegree.style.styling.mark.WellKnownNameManager; import org.deegree.style.utils.ShapeHelper; import org.slf4j.Logger; @@ -243,9 +245,21 @@ private Pair> parseMark( XMLStreamReader in ) if ( in.getLocalName().equals( "WellKnownName" ) ) { String wkn = in.getElementText(); - try { - base.wellKnown = SimpleMark.valueOf( wkn.toUpperCase() ); - } catch ( IllegalArgumentException e ) { + Function resolver = ( str ) -> { + if ( context.location != null ) { + return context.location.resolveToUrl( str ); + } else { + try { + return resolve( str, in ); + } catch ( MalformedURLException e ) { + LOG.warn("Failed to resolve external WellKnownName resource {}: {} ", str, e.getMessage()); + LOG.trace( "Exception", e ); + return null; + } + } + }; + + if ( !WellKnownNameManager.load( base, wkn, resolver ) ) { LOG.warn( "Specified unsupported WellKnownName of '{}', using square instead.", wkn ); base.wellKnown = SimpleMark.SQUARE; } diff --git a/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/mark/BoundedShape.java b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/mark/BoundedShape.java new file mode 100644 index 0000000000..42cb638471 --- /dev/null +++ b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/mark/BoundedShape.java @@ -0,0 +1,228 @@ +/*---------------------------------------------------------------------------- + This file is part of deegree, http://deegree.org/ + Copyright (C) 2022 by: + - grit graphische Informationstechnik Beratungsgesellschaft mbH - + + This library is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at your option) + any later version. + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Contact information: + + grit graphische Informationstechnik Beratungsgesellschaft mbH + Landwehrstr. 143, 59368 Werne + Germany + http://www.grit.de/ + + lat/lon GmbH + Aennchenstr. 19, 53177 Bonn + Germany + http://lat-lon.de/ + + Department of Geography, University of Bonn + Prof. Dr. Klaus Greve + Postfach 1147, 53001 Bonn + Germany + http://www.geographie.uni-bonn.de/deegree/ + + e-mail: info@deegree.org + ----------------------------------------------------------------------------*/ +package org.deegree.style.styling.mark; + +import static java.util.Objects.requireNonNull; + +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +/** + * Extension of {@link Shape} which allows to specify the bounds explicitly + */ +public class BoundedShape implements Shape { + + private Shape shape; + + private Rectangle2D bounds = null; + + public BoundedShape( Shape shape ) { + requireNonNull( shape, "Shape can not be null" ); + this.shape = shape; + } + + /** + * Create Bounded Shape + * + * @param shp + * Source Shape + * @param bounds + * Explicit Bounds of Shape + * @return Bounded Shape + */ + public static BoundedShape of( Shape shp, Rectangle2D bounds ) { + BoundedShape s = new BoundedShape( shp ); + s.setBounds( bounds ); + return s; + } + + /** + * Create Bounded Shape + * + * @param at + * AffineTransform which is altered by a y-scale of -1 + * @param shp + * Source Shape + * @param bounds + * Explicit Bounds of Shape + * @return Bounded Shape + */ + public static BoundedShape of( AffineTransform at, Shape shp, Rectangle2D bounds ) { + BoundedShape s = new BoundedShape( at.createTransformedShape( shp ) ); + s.setBounds( bounds ); + return s; + } + + /** + * Inverted bounded Shape + * + * Y-Axis is scaled with -1 + * + * @param shp + * Source Shape + * @param bounds + * Explicit Bounds of Shape + * @return Bounded Shape + */ + public static BoundedShape inv( Shape shp, Rectangle2D bounds ) { + AffineTransform at = AffineTransform.getScaleInstance( 1.0, -1.0 ); + BoundedShape s = new BoundedShape( at.createTransformedShape( shp ) ); + s.setBounds( new Rectangle2D.Double( bounds.getX(), bounds.getY() * -1, bounds.getWidth(), + bounds.getHeight() ) ); + + return s; + } + + /** + * Inverted bounded Shape + * + * Y-Axis is scaled with -1 + * + * @param at + * AffineTransform which is altered by a y-scale of -1 + * @param shp + * Source Shape + * @param bounds + * Explicit Bounds of Shape + * @return Bounded Shape + */ + public static BoundedShape inv( AffineTransform at, Shape shp, Rectangle2D bounds ) { + at.scale( 1.0, -1.0 ); + BoundedShape s = new BoundedShape( at.createTransformedShape( shp ) ); + s.setBounds( new Rectangle2D.Double( bounds.getX(), bounds.getY() * -1, bounds.getWidth(), + bounds.getHeight() ) ); + + return s; + } + + /** + * Transformed Bounded Shape + * + * This transforms the shape and also his bounds + * + *

+ * NOTE: The transformation creates new bounds, which could create an undesired effect when rotated. + *

+ * + * @return The transformed bounded shape + */ + public BoundedShape transform( AffineTransform at ) { + if ( this.bounds == null ) { + return of( at, this.shape, null ); + } + Shape bnds = at.createTransformedShape( this.bounds ); + return of( at, this.shape, bnds.getBounds() ); + } + + public void setBounds( Rectangle2D bounds ) { + this.bounds = bounds; + } + + public boolean contains( double x, double y, double w, double h ) { + return shape.contains( x, y, w, h ); + } + + public boolean contains( double x, double y ) { + return shape.contains( x, y ); + } + + public boolean contains( Point2D p ) { + return shape.contains( (Point2D) p ); + } + + public boolean contains( Rectangle2D r ) { + return shape.contains( (Rectangle2D) r ); + } + + public Rectangle getBounds() { + if ( bounds != null ) + return new Rectangle( (int) bounds.getMinX(), (int) bounds.getMinY(), (int) bounds.getWidth(), + (int) bounds.getHeight() ); + return shape.getBounds(); + } + + public Rectangle2D getBounds2D() { + if ( bounds != null ) + return bounds; + return shape.getBounds2D(); + } + + public PathIterator getPathIterator( AffineTransform at, double flatness ) { + return shape.getPathIterator( at, flatness ); + } + + public PathIterator getPathIterator( AffineTransform at ) { + return shape.getPathIterator( at ); + } + + public boolean intersects( double x, double y, double w, double h ) { + return shape.intersects( x, y, w, h ); + } + + public boolean intersects( Rectangle2D r ) { + return shape.intersects( r ); + } + + @Override + public boolean equals( Object obj ) { + if ( obj instanceof BoundedShape ) { + BoundedShape other = (BoundedShape) obj; + boolean result = shape.equals( other.shape ); + if ( bounds == null ) + return result & ( other.bounds == null ); + return result & bounds.equals( other.bounds ); + } else if ( obj instanceof Shape ) { + if ( bounds == null ) + return shape.equals( obj ); + return false; + } + return super.equals( obj ); + } + + @Override + public int hashCode() { + int hascode = shape.hashCode(); + if ( bounds != null ) + hascode += hascode * 37 + bounds.hashCode(); + return hascode; + } +} \ No newline at end of file diff --git a/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/mark/WellKnownNameLoader.java b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/mark/WellKnownNameLoader.java new file mode 100644 index 0000000000..cc872e2e4f --- /dev/null +++ b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/mark/WellKnownNameLoader.java @@ -0,0 +1,86 @@ +/*---------------------------------------------------------------------------- + This file is part of deegree, http://deegree.org/ + Copyright (C) 2022 by: + - grit graphische Informationstechnik Beratungsgesellschaft mbH - + + This library is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at your option) + any later version. + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Contact information: + + grit graphische Informationstechnik Beratungsgesellschaft mbH + Landwehrstr. 143, 59368 Werne + Germany + http://www.grit.de/ + + lat/lon GmbH + Aennchenstr. 19, 53177 Bonn + Germany + http://lat-lon.de/ + + Department of Geography, University of Bonn + Prof. Dr. Klaus Greve + Postfach 1147, 53001 Bonn + Germany + http://www.geographie.uni-bonn.de/deegree/ + + e-mail: info@deegree.org + ----------------------------------------------------------------------------*/ +package org.deegree.style.styling.mark; + +import java.awt.Shape; +import java.net.URL; +import java.util.function.Function; + +import org.deegree.style.styling.components.Mark; + +/** + * Loader for loading Mark from custom WellKnownName + * + * @author Stephan Reichhelm + */ +public interface WellKnownNameLoader { + + /** + * Parse a WellKnownName Text into a mark + * + * @param wellKnownName + * WellKnownName to be parsed + * @param resolver + * Resolver to resolve relative locations into URL, can be null + * @return The Shape or null if this Loader is not responsible for that type of WellKnownName + */ + public Shape parse( String wellKnownName, Function resolver ); + + /** + * Apply the Shape to the Mark + * + * @param mark + * The Mark to be updated + * @param shape + * The previously created shape + */ + public default void apply( Mark mark, Shape shape ) { + mark.shape = shape; + } + + /** + * Get order value for this Loader + * + * Used to sort multiple factories and create a order list of loader + * + * @return int of position in list + */ + public default int order() { + return 1000; + } +} \ No newline at end of file diff --git a/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/mark/WellKnownNameManager.java b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/mark/WellKnownNameManager.java new file mode 100644 index 0000000000..5da7fe678d --- /dev/null +++ b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/mark/WellKnownNameManager.java @@ -0,0 +1,150 @@ +/*---------------------------------------------------------------------------- + This file is part of deegree, http://deegree.org/ + Copyright (C) 2022 by: + - grit graphische Informationstechnik Beratungsgesellschaft mbH - + + This library is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at your option) + any later version. + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Contact information: + + grit graphische Informationstechnik Beratungsgesellschaft mbH + Landwehrstr. 143, 59368 Werne + Germany + http://www.grit.de/ + + lat/lon GmbH + Aennchenstr. 19, 53177 Bonn + Germany + http://lat-lon.de/ + + Department of Geography, University of Bonn + Prof. Dr. Klaus Greve + Postfach 1147, 53001 Bonn + Germany + http://www.geographie.uni-bonn.de/deegree/ + + e-mail: info@deegree.org + ----------------------------------------------------------------------------*/ +package org.deegree.style.styling.mark; + +import static java.util.Comparator.comparingInt; +import static java.util.Objects.requireNonNull; +import static org.deegree.commons.utils.ArrayUtils.splitAsDoubles; + +import java.awt.Shape; +import java.awt.geom.Rectangle2D; +import java.net.URL; +import java.security.InvalidParameterException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.ServiceLoader; +import java.util.function.Function; + +import org.deegree.style.styling.components.Mark; +import org.deegree.style.styling.components.Mark.SimpleMark; +import org.deegree.workspace.Initializable; +import org.deegree.workspace.Workspace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WellKnownNameManager implements Initializable { + + private static final Logger LOG = LoggerFactory.getLogger( WellKnownNameManager.class ); + + private static ServiceLoader wellLnownNameLoader; + + private static List loaders; + + @Override + public void init( Workspace ws ) { + wellLnownNameLoader = ServiceLoader.load( WellKnownNameLoader.class, ws.getModuleClassLoader() ); + } + + private static synchronized void check() { + if ( loaders == null ) { + loaders = new ArrayList<>(); + try { + for ( WellKnownNameLoader loader : wellLnownNameLoader ) { + LOG.debug( "Laoading MarkLoader {} [Order: {}]", loader.getClass(), loader.order() ); + loaders.add( loader ); + } + Collections.sort( loaders, comparingInt( WellKnownNameLoader::order ) ); + } catch ( Exception e ) { + LOG.error( e.getMessage(), e ); + } + } + } + + public static boolean load( Mark mark, String wellKnownName, Function resolver ) { + try { + // workaround for static marks + mark.wellKnown = SimpleMark.valueOf( wellKnownName.toUpperCase() ); + return true; + } catch ( IllegalArgumentException e ) { + LOG.trace( "Could not Load wellKnownName as SimpleMark: {}", e.getMessage() ); + } + + check(); + requireNonNull( loaders, "MarkFactory has to been initialized from Workspace" ); + + Rectangle2D bounds = null; + String wkn; + int boundsStart = wellKnownName.lastIndexOf( '[' ); + if ( boundsStart == -1 ) { + wkn = wellKnownName; + } else { + wkn = wellKnownName.substring( 0, boundsStart ); + bounds = handleBounds( wellKnownName, boundsStart ); + } + + Shape s = null; + for ( WellKnownNameLoader loader : loaders ) { + s = loader.parse( wkn, resolver ); + if ( s != null ) { + if ( bounds != null ) { + loader.apply( mark, BoundedShape.of( s, bounds ) ); + } else { + loader.apply( mark, s ); + } + return true; + } + } + + return false; + } + + private static Rectangle2D handleBounds( String wellKnownName, int boundsStart ) { + try { + int boundsEnd = wellKnownName.indexOf( ']', boundsStart ); + if ( boundsEnd != -1 ) { + double[] vals = splitAsDoubles( wellKnownName.substring( boundsStart + 1, boundsEnd ), "," ); + if ( vals.length == 2 ) { + return new Rectangle2D.Double( 0.0, 0.0, vals[0], vals[1] ); + } else if ( vals.length == 4 ) { + return new Rectangle2D.Double( vals[0], vals[1], vals[2], vals[3] ); + } else { + throw new InvalidParameterException( "Invalid number of ordinates specified" ); + } + } else { + throw new InvalidParameterException( "Invalid Format" ); + } + } catch ( Exception ex ) { + LOG.warn( "Invalid bounds specified, either use [widht,heigt] or [minx,miny,widht,height]." ); + LOG.warn( "Bounds are ignored for WellKnownName {} error: {}", wellKnownName, ex.getMessage() ); + LOG.trace( "Exception", ex ); + // ignore bounds + } + return null; + } +} \ No newline at end of file diff --git a/deegree-core/deegree-core-style/src/main/java/org/deegree/style/utils/ShapeHelper.java b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/utils/ShapeHelper.java index 96b68af952..99503cca9f 100644 --- a/deegree-core/deegree-core-style/src/main/java/org/deegree/style/utils/ShapeHelper.java +++ b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/utils/ShapeHelper.java @@ -39,6 +39,7 @@ import static java.lang.Math.PI; import static java.lang.Math.max; import static java.lang.Math.toRadians; +import static org.deegree.commons.utils.math.MathUtils.isZero; import static org.deegree.commons.utils.TunableParameter.get; import static org.slf4j.LoggerFactory.getLogger; @@ -66,6 +67,7 @@ import org.apache.batik.gvt.RootGraphicsNode; import org.apache.xerces.parsers.SAXParser; import org.deegree.style.styling.components.Mark; +import org.deegree.style.styling.mark.BoundedShape; import org.slf4j.Logger; import org.w3c.dom.svg.SVGDocument; @@ -73,9 +75,7 @@ * RenderHelper * * @author Andreas Schmitz - * @author last edited by: $Author: aschmitz $ - * - * @version $Revision: 29875 $, $Date: 2011-03-04 14:27:10 +0100 (Fri, 04 Mar 2011) $ + * @author Stephan Reichhelm */ public class ShapeHelper { @@ -153,57 +153,64 @@ public static Path2D.Double calculateStarPolygon( final int edges, final int ski * @param size * @param rotation * @return a shape representing the mark + * @deprecated {@link #getShapeFromMark(Mark, double, double, boolean, double, double)} or {@link #getShapeFromMarkForFill(Mark, double, double)} */ public static Shape getShapeFromMark( Mark mark, double size, double rotation ) { return getShapeFromMark( mark, size, rotation, false, -1, -1 ); } + private static Shape getFontOrDefault(Mark mark, double size) { + Shape shape; + if ( mark.font != null ) { + FontRenderContext frc = new FontRenderContext( null, false, true ); + GlyphVector vec = mark.font.deriveFont( (float) size ) // + .createGlyphVector( frc, new int[] { mark.markIndex } ); + shape = vec.getOutline(); + } else { + GeneralPath path = new GeneralPath(); + shape = path; + + switch ( mark.wellKnown ) { + case CIRCLE: + path.append( new Ellipse2D.Double( 0, 0, size, size ), false ); + break; + case CROSS: { + double half = size / 2; + path.append( new Line2D.Double( half, 0, half, size ), false ); + path.append( new Line2D.Double( 0, half, size, half ), false ); + break; + } + case SQUARE: + path.append( new Rectangle2D.Double( 0, 0, size, size ), false ); + break; + case STAR: { + path.append( calculateStarPolygon( 5, 2, size ), false ); + break; + } + case TRIANGLE: + Path2D.Double path2 = new Path2D.Double(); + path2.moveTo( size / 2, 0 ); + path2.lineTo( 0, size ); + path2.lineTo( size, size ); + path2.closePath(); + path.append( path2, false ); + break; + case X: + path.append( new Line2D.Double( 0, 0, size, size ), false ); + path.append( new Line2D.Double( size, 0, 0, size ), false ); + break; + } + } + return shape; + } + public static Shape getShapeFromMark( Mark mark, double size, double rotation, boolean translate, double x, double y ) { Shape shape; if ( mark.shape != null ) { shape = mark.shape; } else { - if ( mark.font != null ) { - FontRenderContext frc = new FontRenderContext( null, false, true ); - GlyphVector vec = mark.font.deriveFont( (float) size ).createGlyphVector( frc, - new int[] { mark.markIndex } ); - shape = vec.getOutline(); - } else { - GeneralPath path = new GeneralPath(); - shape = path; - - switch ( mark.wellKnown ) { - case CIRCLE: - path.append( new Ellipse2D.Double( 0, 0, size, size ), false ); - break; - case CROSS: { - double half = size / 2; - path.append( new Line2D.Double( half, 0, half, size ), false ); - path.append( new Line2D.Double( 0, half, size, half ), false ); - break; - } - case SQUARE: - path.append( new Rectangle2D.Double( 0, 0, size, size ), false ); - break; - case STAR: { - path.append( calculateStarPolygon( 5, 2, size ), false ); - break; - } - case TRIANGLE: - Path2D.Double path2 = new Path2D.Double(); - path2.moveTo( size / 2, 0 ); - path2.lineTo( 0, size ); - path2.lineTo( size, size ); - path2.closePath(); - path.append( path2, false ); - break; - case X: - path.append( new Line2D.Double( 0, 0, size, size ), false ); - path.append( new Line2D.Double( size, 0, 0, size ), false ); - break; - } - } + shape = getFontOrDefault( mark, size ); } Rectangle2D box = shape.getBounds2D(); @@ -236,6 +243,47 @@ public static Shape getShapeFromMark( Mark mark, double size, double rotation, b return t.createTransformedShape( shape ); } + public static Shape getShapeFromMarkForFill( Mark mark, double size, double rotation ) { + Shape shape; + + if ( mark.shape != null ) { + shape = mark.shape; + } else { + shape = getFontOrDefault( mark, size ); + } + + Rectangle2D box; + AffineTransform t; + + if ( !isZero( rotation ) ) { + t = new AffineTransform(); + box = shape.getBounds2D(); + t.rotate( toRadians( rotation ), box.getCenterX(), box.getCenterY() ); + + if ( shape instanceof BoundedShape ) + shape = ( (BoundedShape) shape ).transform( t ); + else + shape = t.createTransformedShape( shape ); + + // align at 0/0 + box = shape.getBounds2D(); + t = AffineTransform.getTranslateInstance( -box.getMinX(), -box.getMinY() ); + } + + box = shape.getBounds2D(); + double cur = max( box.getWidth(), box.getHeight() ); + double fac = size / cur; + t = AffineTransform.getScaleInstance( fac, fac ); + t.translate( -box.getMinX(), -box.getMinY() ); + + if ( shape instanceof BoundedShape ) + shape = ( (BoundedShape) shape ).transform( t ); + else + shape = t.createTransformedShape( shape ); + + return shape; + } + /** * @param url * @param size diff --git a/deegree-core/deegree-core-style/src/main/resources/META-INF/services/org.deegree.workspace.Initializable b/deegree-core/deegree-core-style/src/main/resources/META-INF/services/org.deegree.workspace.Initializable new file mode 100644 index 0000000000..892c15a058 --- /dev/null +++ b/deegree-core/deegree-core-style/src/main/resources/META-INF/services/org.deegree.workspace.Initializable @@ -0,0 +1 @@ +org.deegree.style.styling.mark.WellKnownNameManager \ No newline at end of file From 8eca2f3c3e5fa0d3b50ab5f6efacc91f4f16944a Mon Sep 17 00:00:00 2001 From: Stephan Reichhelm Date: Mon, 10 Oct 2022 12:42:41 +0200 Subject: [PATCH 2/8] add well known mark implementations for shape:// extshape:// qgis:// and ttf:// based on geoserver implementation --- .../style/styling/wkn/ExtShapeLoader.java | 183 ++++++++++++ .../style/styling/wkn/QGisShapeLoader.java | 268 ++++++++++++++++++ .../style/styling/wkn/ShapeLoader.java | 123 ++++++++ .../style/styling/wkn/TrueTypeFontLoader.java | 127 +++++++++ ...ree.style.styling.mark.WellKnownNameLoader | 7 + 5 files changed, 708 insertions(+) create mode 100644 deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/ExtShapeLoader.java create mode 100644 deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/QGisShapeLoader.java create mode 100644 deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/ShapeLoader.java create mode 100644 deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/TrueTypeFontLoader.java create mode 100644 deegree-core/deegree-core-style/src/main/resources/META-INF/services/org.deegree.style.styling.mark.WellKnownNameLoader diff --git a/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/ExtShapeLoader.java b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/ExtShapeLoader.java new file mode 100644 index 0000000000..1efb26eef6 --- /dev/null +++ b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/ExtShapeLoader.java @@ -0,0 +1,183 @@ +/*---------------------------------------------------------------------------- + This file is part of deegree, http://deegree.org/ + + (C) 2002-2011, Open Source Geospatial Foundation (OSGeo) + This library is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at your option) + any later version. + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +----------------------------------------------------------------------------*/ +package org.deegree.style.styling.wkn; + +import static java.util.Collections.emptyMap; +import static org.deegree.commons.utils.kvp.KVPUtils.getDefaultDouble; +import static org.deegree.commons.utils.kvp.KVPUtils.getNormalizedKVPMap; + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.Rectangle2D; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.deegree.style.styling.mark.BoundedShape; +import org.deegree.style.styling.mark.WellKnownNameLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ExtShapeLoader implements WellKnownNameLoader { + + private static final Logger LOG = LoggerFactory.getLogger( ExtShapeLoader.class ); + + public static final String PREFIX = "extshape://"; + + private static Map SHAPES = null; + + private static synchronized void lazyLoad() { + if ( SHAPES == null ) { + SHAPES = new HashMap<>(); + GeneralPath gp; + AffineTransform inv = AffineTransform.getScaleInstance( 1.0, -1.0 ); + + gp = new GeneralPath(); + gp.moveTo( -0.145f, 0.000f ); + gp.lineTo( 0.000f, 0.175f ); + gp.lineTo( 0.105f, 0.000f ); + gp.closePath(); + SHAPES.put( "triangle", BoundedShape.inv( gp, new Rectangle2D.Double( -0.25, 0.25, 0.5, 0.5 ) ) ); + + gp = new GeneralPath(); + gp.moveTo( -0.125f, 0.000f ); + gp.curveTo( -0.125f, 0.000f, 0.000f, 0.250f, 0.125f, 0.000f ); + gp.closePath(); + SHAPES.put( "emicircle", BoundedShape.inv( gp, new Rectangle2D.Double( -0.25, 0.25, 0.5, 0.5 ) ) ); + + gp = new GeneralPath(); + gp.moveTo( -0.395f, 0.000f ); + gp.lineTo( -0.250f, -0.175f ); + gp.lineTo( -0.145f, 0.000f ); + gp.moveTo( 0.125f, 0.000f ); + gp.curveTo( 0.125f, 0.000f, 0.250f, 0.250f, 0.375f, 0.000f ); + gp.closePath(); + SHAPES.put( "triangleemicircle", BoundedShape.inv( gp, new Rectangle2D.Double( -0.25, 0.25, 0.5, 0.5 ) ) ); + + gp = new GeneralPath(); + gp.moveTo( 0f, 1f ); + gp.lineTo( 0.5, 0f ); + gp.lineTo( 0.1f, 0f ); + gp.lineTo( 0.1f, -1f ); + gp.lineTo( -0.1f, -1f ); + gp.lineTo( -0.1f, 0f ); + gp.lineTo( -0.5f, 0f ); + gp.closePath(); + SHAPES.put( "narrow", inv.createTransformedShape( gp ) ); + + AffineTransform at = AffineTransform.getQuadrantRotateInstance( 2 ); + at.scale( 1.0, -1.0 ); + gp = new GeneralPath(); + gp.moveTo( 0f, 1f ); + gp.lineTo( 0.5, 0f ); + gp.lineTo( 0.1f, 0f ); + gp.lineTo( 0.1f, -1.0f ); + gp.lineTo( -0.1f, -1.0f ); + gp.lineTo( -0.1f, 0f ); + gp.lineTo( -0.5f, 0f ); + gp.closePath(); + SHAPES.put( "sarrow", at.createTransformedShape( gp ) ); + + SHAPES.put( "arrow", buildDynamicArrow( 2, 0.2f, 0.5f ) ); + } + } + + @Override + public Shape parse( String wellKnownName, Function resolver ) { + if ( wellKnownName == null || !wellKnownName.startsWith( PREFIX ) ) + return null; + + String wkn = wellKnownName.substring( PREFIX.length() ).toLowerCase(); + Shape s; + + if ( wkn.startsWith( "arrow?" ) ) { + Map kvp; + try { + kvp = getNormalizedKVPMap( wkn.substring( 6 ), null ); + } catch ( UnsupportedEncodingException e ) { + LOG.warn( "Cloud not parse arrow? WellKnownName {}: {}", wkn, e.getMessage() ); + LOG.trace( "Exception", e ); + kvp = emptyMap(); + } + float heightRatio = rangeValue( kvp, "HR", 1.0f, 0.0f, 1000.0f ); + float thicknessRatio = rangeValue( kvp, "T", 0.2f, 0.0f, 1.0f ); + float baseRatio = rangeValue( kvp, "AB", 0.5f, 0.0f, 1.0f ); + + s = buildDynamicArrow( heightRatio, thicknessRatio, baseRatio ); + } else { + //debug//SHAPES=null; + lazyLoad(); + s = SHAPES.get( wkn ); + } + + return s; + } + + private float rangeValue( Map kvp, String key, float defaultValue, float min, float max ) { + float val = (float) getDefaultDouble( kvp, key, defaultValue ); + if ( val < min || val > max ) + return defaultValue; + return val; + } + + private static Shape buildDynamicArrow( float height, float thickness, float arrowBase ) { + GeneralPath gp = new GeneralPath(); + // start from the point of the arrow + gp.moveTo( 0f, height / 2 ); + // the right base of the arrow + float arrowBaseHeight = height / 2 - height * ( 1 - arrowBase ); + gp.lineTo( 0.5, arrowBaseHeight ); + // back to the center + float t2 = thickness / 2; + if ( t2 < 0.5 ) { + gp.lineTo( t2, arrowBaseHeight ); + } + // down to the base + gp.lineTo( t2, -height / 2 ); + if ( t2 > 0 ) { + // go the the other side of the base + gp.lineTo( -t2, -height / 2 ); + } + // back up to the arrow base + if ( t2 < 0.5 ) { + gp.lineTo( -t2, arrowBaseHeight ); + } + gp.lineTo( -0.5f, arrowBaseHeight ); + // and finish + gp.closePath(); + + return AffineTransform.getScaleInstance( 1.0, -1.0 ).createTransformedShape( gp ); + } + + @Override + public int order() { + return 5000; + } + + public static void main( String[] args ) { + lazyLoad(); + String list = SHAPES.entrySet().stream()// + .map( Map.Entry::getKey ) // + .map( str -> PREFIX + str ) // + .collect( Collectors.joining( "," ) ); + System.out.println( list ); + } +} \ No newline at end of file diff --git a/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/QGisShapeLoader.java b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/QGisShapeLoader.java new file mode 100644 index 0000000000..c482278460 --- /dev/null +++ b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/QGisShapeLoader.java @@ -0,0 +1,268 @@ +/*---------------------------------------------------------------------------- + This file is part of deegree, http://deegree.org/ + + (C) 2016, Open Source Geospatial Foundation (OSGeo) + This library is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at your option) + any later version. + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +----------------------------------------------------------------------------*/ +package org.deegree.style.styling.wkn; + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Arc2D; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Line2D; +import java.awt.geom.Rectangle2D; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.deegree.style.styling.mark.BoundedShape; +import org.deegree.style.styling.mark.WellKnownNameLoader; + +public class QGisShapeLoader implements WellKnownNameLoader { + + public static final String PREFIX = "qgis://"; + + private static Map SHAPES = null; + + private static synchronized void lazyLoad() { + if ( SHAPES == null ) { + SHAPES = new HashMap<>(); + GeneralPath gp; + AffineTransform at; + + // copy of shape://plus + gp = new GeneralPath(); + gp.moveTo( -0.5f, 0 ); + gp.lineTo( 0.5f, 0 ); + gp.moveTo( 0, -0.5f ); + gp.lineTo( 0, 0.5f ); + SHAPES.put( "cross", gp ); + + // copy of circle + SHAPES.put( "circle", new Ellipse2D.Double( -0.5, -0.5, 1.0, 1.0 ) ); + + gp = new GeneralPath( GeneralPath.WIND_EVEN_ODD ); + gp.moveTo( 0f, 1f ); + gp.lineTo( 0.866f, -0.8f ); + gp.lineTo( -0.866f, -0.8f ); + gp.lineTo( 0f, 1f ); + at = new AffineTransform(); + at.translate( 0, 0.10 ); + at.scale( 0.5, 0.5 ); + SHAPES.put( "triangle", BoundedShape.inv( at, gp, new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + // copy of triangle + gp = new GeneralPath( GeneralPath.WIND_EVEN_ODD ); + gp.moveTo( 0f, 1f ); + gp.lineTo( 0.866f, -0.5f ); + gp.lineTo( -0.866f, -0.5f ); + gp.lineTo( 0f, 1f ); + at = new AffineTransform(); + at.translate( 0, 0.25 ); + at.scale( 0.5, 0.5 ); + SHAPES.put( "equilateral_triangle", + BoundedShape.inv( at, gp, new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + gp = new GeneralPath( GeneralPath.WIND_EVEN_ODD ); + gp.moveTo( 0f, 0.5f ); + gp.lineTo( 0.2f, 0.1f ); + gp.lineTo( 0.5f, 0.1f ); + gp.lineTo( 0.2f, -0.1f ); + gp.lineTo( 0.5f, -0.5f ); + gp.lineTo( 0f, -0.2f ); + gp.lineTo( -0.5f, -0.5f ); + gp.lineTo( -0.2f, -0.1f ); + gp.lineTo( -0.5f, 0.1f ); + gp.lineTo( -0.2f, 0.1f ); + gp.lineTo( 0f, 0.5f ); + SHAPES.put( "star", BoundedShape.inv( gp, new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + // copy of shape://times + gp = new GeneralPath(); + gp.moveTo( -0.5f, 0.5f ); + gp.lineTo( 0.5f, -0.5f ); + gp.moveTo( -0.5f, -0.5f ); + gp.lineTo( 0.5f, 0.5f ); + SHAPES.put( "cross2", gp ); + + gp = new GeneralPath( GeneralPath.WIND_EVEN_ODD ); + gp.moveTo( 0.3f, -0.3f ); + gp.lineTo( 0.5f, 0.0f ); + gp.lineTo( 0.3f, 0.3f ); + gp.lineTo( 0.3f, 0.1f ); + gp.lineTo( -0.5f, 0.1f ); + gp.lineTo( -0.5f, -0.1f ); + gp.lineTo( 0.3f, -0.1f ); + gp.lineTo( 0.3f, -0.3f ); + at = new AffineTransform(); + at.rotate( -Math.PI / 2.0 ); + SHAPES.put( "arrow", BoundedShape.inv( at, gp, new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + gp = new GeneralPath(); + gp.moveTo( 0f, 1f ); + gp.lineTo( 1f, 0f ); + gp.lineTo( 0f, -1f ); + gp.lineTo( -1f, 0f ); + gp.lineTo( 0f, 1f ); + at = new AffineTransform(); + at.scale( 0.5, 0.5 ); + SHAPES.put( "diamond", BoundedShape.inv( at, gp, new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + gp = new GeneralPath(); + gp.moveTo( 0f, 1f ); + gp.lineTo( 0.9511f, 0.3090f ); + gp.lineTo( 0.5878f, -0.8090f ); + gp.lineTo( -0.5878f, -0.8090f ); + gp.lineTo( -0.9511f, 0.3090f ); + gp.lineTo( 0f, 1f ); + at = new AffineTransform(); + at.scale( 0.5, 0.5 ); + SHAPES.put( "pentagon", BoundedShape.inv( at, gp, new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + // copy of square + SHAPES.put( "rectangle", new Rectangle2D.Double( -0.5, -0.5, 1.0, 1.0 ) ); + + // copy of star + gp = new GeneralPath( GeneralPath.WIND_EVEN_ODD ); + gp.moveTo( -0.309f, -0.5f ); + gp.lineTo( -0.25f, -0.156f ); + gp.lineTo( -0.5f, 0.088f ); + gp.lineTo( -0.154f, 0.138f ); + gp.lineTo( 0.0f, 0.451f ); + gp.lineTo( 0.154f, 0.138f ); + gp.lineTo( 0.5f, 0.088f ); + gp.lineTo( 0.25f, -0.156f ); + gp.lineTo( 0.309f, -0.5f ); + gp.lineTo( 0.0f, -0.338 ); + gp.lineTo( -0.309f, -0.5f ); + SHAPES.put( "regular_star", BoundedShape.inv( gp, new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + // copy of shape://vertline + SHAPES.put( "line", new Line2D.Double( 0, -0.5, 0, 0.5 ) ); + + gp = new GeneralPath(); + gp.moveTo( -0.5f, 0.4f ); + gp.lineTo( 0, 0 ); + gp.lineTo( -0.5f, -0.4f ); + SHAPES.put( "arrowhead", BoundedShape.inv( gp, new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + gp = new GeneralPath(); + gp.moveTo( -0.5f, 0.4f ); + gp.lineTo( 0, 0 ); + gp.lineTo( -0.5f, -0.4f ); + gp.closePath(); + SHAPES.put( "filled_arrowhead", BoundedShape.inv( gp, new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + gp = new GeneralPath( GeneralPath.WIND_EVEN_ODD ); + gp.moveTo( -0.5f, -0.1f ); + gp.lineTo( -0.5f, -0.1f ); + gp.lineTo( -0.5f, 0.1f ); + gp.lineTo( -0.1f, 0.1f ); + gp.lineTo( -0.1f, 0.5f ); + gp.lineTo( 0.1f, 0.5f ); + gp.lineTo( 0.1f, 0.1f ); + gp.lineTo( 0.5f, 0.1f ); + gp.lineTo( 0.5f, -0.1f ); + gp.lineTo( 0.1f, -0.1f ); + gp.lineTo( 0.1f, -0.5f ); + gp.lineTo( -0.1f, -0.5f ); + gp.lineTo( -0.1f, -0.1f ); + gp.lineTo( -0.5f, -0.1f ); + SHAPES.put( "crossfill", BoundedShape.inv( gp, new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + gp = new GeneralPath( GeneralPath.WIND_EVEN_ODD ); + gp.moveTo( -0.5f, -0.5f ); + gp.lineTo( 0.5f, -0.5f ); + gp.lineTo( -0.5f, 0.5f ); + gp.lineTo( -0.5f, -0.5f ); + SHAPES.put( "diagonalhalfsquare", BoundedShape.inv( gp, new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + SHAPES.put( "halfsquare", BoundedShape.inv( new Rectangle2D.Double( -0.5, -0.5, 0.5, 1.0 ), + new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + gp = new GeneralPath(); + gp.moveTo( -0.4330f, -0.25f ); + gp.lineTo( -0.4330f, 0.25f ); + gp.lineTo( 0f, 0.5f ); + gp.lineTo( 0.4330f, 0.25f ); + gp.lineTo( 0.4330f, -0.25f ); + gp.lineTo( 0f, -0.5f ); + gp.lineTo( -0.4330f, -0.25f ); + SHAPES.put( "hexagon", BoundedShape.inv( gp, new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + gp = new GeneralPath( GeneralPath.WIND_EVEN_ODD ); + gp.moveTo( 0f, -0.5f ); + gp.lineTo( 0f, 0.5f ); + gp.lineTo( 0.5f, -0.5f ); + gp.lineTo( 0f, -0.5f ); + SHAPES.put( "lefthalftriangle", BoundedShape.inv( gp, new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + gp = new GeneralPath( GeneralPath.WIND_EVEN_ODD ); + gp.moveTo( 0f, -0.5f ); + gp.lineTo( 0f, 0.5f ); + gp.lineTo( -0.5f, -0.5f ); + gp.lineTo( 0f, -0.5f ); + SHAPES.put( "righthalftriangle", BoundedShape.inv( gp, new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + SHAPES.put( "quartercircle", + BoundedShape.inv( new Arc2D.Double( new Rectangle2D.Double( -0.5, -0.5, 1.0, 1.0 ), 180, 90, + Arc2D.PIE ), + new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + SHAPES.put( "semicircle", + BoundedShape.inv( new Arc2D.Double( new Rectangle2D.Double( -0.5, -0.5, 1.0, 1.0 ), 180, 180, + Arc2D.PIE ), + new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + SHAPES.put( "thirdcircle", + BoundedShape.inv( new Arc2D.Double( new Rectangle2D.Double( -0.5, -0.5, 1.0, 1.0 ), 150, 120, + Arc2D.PIE ), + new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + SHAPES.put( "quartersquare", BoundedShape.inv( new Rectangle2D.Double( -0.5, 0.0, 0.5, 0.5 ), + new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + } + } + + @Override + public Shape parse( String wellKnownName, Function resolver ) { + if ( wellKnownName == null || !wellKnownName.startsWith( PREFIX ) ) + return null; + + String wkn = wellKnownName.substring( PREFIX.length() ).toLowerCase(); + // debug//SHAPES = null; + lazyLoad(); + Shape s = SHAPES.get( wkn ); + + return s; + } + + @Override + public int order() { + return 1500; + } + + public static void main( String[] args ) { + lazyLoad(); + String list = SHAPES.entrySet().stream()// + .map( Map.Entry::getKey ) // + .map( str -> PREFIX + str ) // + .collect( Collectors.joining( "," ) ); + System.out.println( list ); + } +} diff --git a/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/ShapeLoader.java b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/ShapeLoader.java new file mode 100644 index 0000000000..f4f8cbe20c --- /dev/null +++ b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/ShapeLoader.java @@ -0,0 +1,123 @@ +/*---------------------------------------------------------------------------- + This file is part of deegree, http://deegree.org/ + + (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) + This library is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at your option) + any later version. + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +----------------------------------------------------------------------------*/ +package org.deegree.style.styling.wkn; + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Line2D; +import java.awt.geom.Rectangle2D; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.deegree.style.styling.mark.BoundedShape; +import org.deegree.style.styling.mark.WellKnownNameLoader; + +public class ShapeLoader implements WellKnownNameLoader { + + public static final String PREFIX = "shape://"; + + private static Map SHAPES = null; + + private static synchronized void lazyLoad() { + if ( SHAPES == null ) { + SHAPES = new HashMap<>(); + GeneralPath gp; + AffineTransform inv = AffineTransform.getScaleInstance( 1.0, -1.0 ); + + SHAPES.put( "vertline", new Line2D.Double( 0, -0.5, 0, 0.5 ) ); + SHAPES.put( "horline", new Line2D.Double( -0.5, 0, 0.5, 0 ) ); + SHAPES.put( "slash", new Line2D.Double( -0.5, 0.5, 0.5, -0.5 ) ); + SHAPES.put( "backslash", new Line2D.Double( -0.5, -0.5, 0.5, 0.5 ) ); + + gp = new GeneralPath(); + + SHAPES.put( "dot", BoundedShape.inv( new Ellipse2D.Double( -0.000001, -0.000001, 0.000001, 0.000001 ), + new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ) ); + + gp = new GeneralPath(); + gp.moveTo( -0.5f, 0 ); + gp.lineTo( 0.5f, 0 ); + gp.moveTo( 0, -0.5f ); + gp.lineTo( 0, 0.5f ); + SHAPES.put( "plus", inv.createTransformedShape( gp ) ); + + gp = new GeneralPath(); + gp.moveTo( -0.5f, 0.5f ); + gp.lineTo( 0.5f, -0.5f ); + gp.moveTo( -0.5f, -0.5f ); + gp.lineTo( 0.5f, 0.5f ); + SHAPES.put( "times", inv.createTransformedShape( gp ) ); + + gp = new GeneralPath(); + gp.moveTo( -0.5f, 0.2f ); + gp.lineTo( 0, 0 ); + gp.lineTo( -0.5f, -0.2f ); + SHAPES.put( "oarrow", BoundedShape.inv( gp, new Rectangle2D.Double( -0.5, 0.5, 1, 1 ) ) ); + + gp = new GeneralPath(); + gp.moveTo( -0.5f, 0.2f ); + gp.lineTo( 0, 0 ); + gp.lineTo( -0.5f, -0.2f ); + gp.closePath(); + SHAPES.put( "carrow", BoundedShape.inv( gp, new Rectangle2D.Double( -0.5, 0.5, 1, 1 ) ) ); + + gp = new GeneralPath(); + gp.moveTo( -0.5f, 0.3f ); + gp.lineTo( 0.5, 0 ); + gp.lineTo( -0.5f, -0.3f ); + SHAPES.put( "coarrow", BoundedShape.inv( gp, new Rectangle2D.Double( -0.32, 0.3, 0.6, 0.6 ) ) ); + + gp = new GeneralPath(); + gp.moveTo( -0.5f, 0.3f ); + gp.lineTo( 0.5, 0 ); + gp.lineTo( -0.5f, -0.3f ); + gp.closePath(); + SHAPES.put( "ccarrow", BoundedShape.inv( gp, new Rectangle2D.Double( -0.32, 0.3, 0.6, 0.6 ) ) ); + } + } + + @Override + public Shape parse( String wellKnownName, Function resolver ) { + if ( wellKnownName == null || !wellKnownName.startsWith( PREFIX ) ) + return null; + + String wkn = wellKnownName.substring( PREFIX.length() ).toLowerCase(); + + lazyLoad(); + Shape s = SHAPES.get( wkn ); + return s; + } + + @Override + public int order() { + return 500; + } + + public static void main( String[] args ) { + lazyLoad(); + String list = SHAPES.entrySet().stream()// + .map( Map.Entry::getKey ) // + .map( str -> PREFIX + str ) // + .collect( Collectors.joining( "," ) ); + System.out.println( list ); + } +} \ No newline at end of file diff --git a/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/TrueTypeFontLoader.java b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/TrueTypeFontLoader.java new file mode 100644 index 0000000000..bcbf312f72 --- /dev/null +++ b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/TrueTypeFontLoader.java @@ -0,0 +1,127 @@ +/*---------------------------------------------------------------------------- + This file is part of deegree, http://deegree.org/ + + (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) + This library is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at your option) + any later version. + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +----------------------------------------------------------------------------*/ +package org.deegree.style.styling.wkn; + +import java.awt.Font; +import java.awt.FontFormatException; +import java.awt.Shape; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.deegree.style.styling.mark.BoundedShape; +import org.deegree.style.styling.mark.WellKnownNameLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TrueTypeFontLoader implements WellKnownNameLoader { + + private static final Logger LOG = LoggerFactory.getLogger( TrueTypeFontLoader.class ); + + private static final String PREFIX = "ttf://"; + + private static final Map EXTERNAL_FONT_CACHE = new HashMap<>(); + + private static FontRenderContext FONT_RENDER_CONTEXT = new FontRenderContext( new AffineTransform(), false, false ); + + @Override + public Shape parse( String wellKnownName, Function resolver ) { + if ( wellKnownName == null || !wellKnownName.startsWith( PREFIX ) ) + return null; + + Matcher m = Pattern.compile( "[tT][tT][fF]://(.*)#(.*)" ).matcher( wellKnownName ); + if ( !m.matches() ) { + throw new IllegalArgumentException( "Invalid WellKnownName, use syntax ttf://#" ); + } + + String fontFamilyName = m.group( 1 ); + String code = m.group( 2 ); + char character; + try { + // see if a unicode escape sequence has been used + if ( code.startsWith( "U+" ) || code.startsWith( "\\u" ) ) + code = "0x" + code.substring( 2 ); + + // this will handle most numeric formats like decimal, hex and octal + character = (char) Integer.decode( code ).intValue(); + } catch ( NumberFormatException e ) { + throw new IllegalArgumentException( "Invalid character code specificated " + code, e ); + } + + // Load Character + Font font = load( fontFamilyName, resolver ); + + // handle charmap code reporting issues + if ( !font.canDisplay( character ) ) { + char alternative = (char) ( 0xF000 | character ); + if ( font.canDisplay( alternative ) ) { + character = alternative; + } + } + + GlyphVector textGlyphVector = font.createGlyphVector( FONT_RENDER_CONTEXT, new char[] { (char) character } ); + Shape s = textGlyphVector.getOutline(); + + // have the shape be centered in the origin, and sitting in a square of side 1 + Rectangle2D bounds = s.getBounds2D(); + AffineTransform tx = new AffineTransform(); + double max = Math.max( bounds.getWidth(), bounds.getHeight() ); + // all shapes are defined looking "upwards" (see ShapeMarkFactory or WellKnownMarkFactory) + // but the fonts ones are flipped to compensate for the fact the y coords grow from top + // to bottom on the screen. We have to flip the symbol so that it conforms to the + // other marks convention + tx.scale( 1 / max, -1 / max ); + tx.translate( -bounds.getCenterX(), -bounds.getCenterY() ); + + return BoundedShape.inv( tx.createTransformedShape( s ), new Rectangle2D.Double( -0.5, 0.5, 1.0, 1.0 ) ); + } + + private Font load( String fontFamilyName, Function resolver ) { + Font f = null; + if ( fontFamilyName.endsWith( ".ttf" ) ) { + // asume file and resolve as file + URL url = resolver != null ? resolver.apply( fontFamilyName ) : null; + if ( url == null ) { + LOG.warn( "Font \"{}\" cloud not be found/resolved to URL", fontFamilyName ); + throw new IllegalArgumentException( "Font \"" + fontFamilyName + "\" not found" ); + } + + f = EXTERNAL_FONT_CACHE.get( url ); + + try (InputStream is = url.openStream()) { + f = Font.createFont( Font.TRUETYPE_FONT, is ); + EXTERNAL_FONT_CACHE.put( url, f ); + } catch ( FontFormatException | IOException e ) { + LOG.warn( "Font \"{}\" cloud not be loaded: {}", fontFamilyName, e.getMessage() ); + throw new IllegalArgumentException( "Font \"" + fontFamilyName + "\" could not be loaded" ); + } + } else { + f = new Font( fontFamilyName, Font.PLAIN, 12 ); + } + + return f; + } +} \ No newline at end of file diff --git a/deegree-core/deegree-core-style/src/main/resources/META-INF/services/org.deegree.style.styling.mark.WellKnownNameLoader b/deegree-core/deegree-core-style/src/main/resources/META-INF/services/org.deegree.style.styling.mark.WellKnownNameLoader new file mode 100644 index 0000000000..edb1f28d7d --- /dev/null +++ b/deegree-core/deegree-core-style/src/main/resources/META-INF/services/org.deegree.style.styling.mark.WellKnownNameLoader @@ -0,0 +1,7 @@ +org.deegree.style.styling.wkn.ShapeLoader +org.deegree.style.styling.wkn.ExtShapeLoader +org.deegree.style.styling.wkn.TrueTypeFontLoader +org.deegree.style.styling.wkn.QGisShapeLoader +#org.deegree.style.styling.wkn.SvgPathLoader +#org.deegree.style.styling.wkn.WKTLoader +#org.deegree.style.styling.wkn.WKTLinearizeLoader \ No newline at end of file From 2bc1d9838c2c0d0a160d7df4355a459dbcf36f38 Mon Sep 17 00:00:00 2001 From: Stephan Reichhelm Date: Mon, 10 Oct 2022 12:44:07 +0200 Subject: [PATCH 3/8] add unit test to verify correct rendering of marks and hatches from mark --- .../point_wellknownname_extshape.gml | 23 +++ .../point_wellknownname_extshape.png | Bin 0 -> 1255 bytes .../point_wellknownname_extshape.xml | 22 +++ .../point_wellknownname_qgis.gml | 23 +++ .../point_wellknownname_qgis.png | Bin 0 -> 6667 bytes .../point_wellknownname_qgis.xml | 58 +++++++ .../point_wellknownname_shape.gml | 23 +++ .../point_wellknownname_shape.png | Bin 0 -> 2259 bytes .../point_wellknownname_shape.xml | 32 ++++ .../polygon_hatches_common.gml | 17 ++ .../polygon_hatches_common.png | Bin 0 -> 3484 bytes .../polygon_hatches_common.xml | 158 ++++++++++++++++++ .../polygon_hatches_custom_1.gml | 139 +++++++++++++++ .../polygon_hatches_custom_1.png | Bin 0 -> 72093 bytes .../polygon_hatches_custom_1.xml | 40 +++++ .../polygon_hatches_custom_2.gml | 139 +++++++++++++++ .../polygon_hatches_custom_2.png | Bin 0 -> 88000 bytes .../polygon_hatches_custom_2.xml | 40 +++++ 18 files changed, 714 insertions(+) create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_extshape.gml create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_extshape.png create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_extshape.xml create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_qgis.gml create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_qgis.png create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_qgis.xml create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_shape.gml create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_shape.png create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_shape.xml create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_common.gml create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_common.png create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_common.xml create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_1.gml create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_1.png create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_1.xml create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_2.gml create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_2.png create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_2.xml diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_extshape.gml b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_extshape.gml new file mode 100644 index 0000000000..d237a55a6d --- /dev/null +++ b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_extshape.gml @@ -0,0 +1,23 @@ + + + + 0.0 0.0 + 600.0 100.0 + + + + + 1 + dummy + + + 50.000000 50.000000 + + + + + diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_extshape.png b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_extshape.png new file mode 100644 index 0000000000000000000000000000000000000000..b8d613f782dd6f1fbd5b266f078c13ad945e8735 GIT binary patch literal 1255 zcmeAS@N?(olHy`uVBq!ia0y~yV2S{;Q#hD_pWc?Ln`9l-ry~oZ6(1P z@V=fscI|H|b>64vg*^0|s?QnB?U9yv{n=Ig`A3$9g#Mr03=>=gnFM_4h;uI})!4Ar zCdbT*+57$V_2i^~`wQHa+3w1E@E3(XS_sp!_`u~{%6|z*Zu93ymI>Al%DL#N_W1$V?2E!>ZkqlJD;MC zzgfTS{we)cDKTtcEnAMJgz-QA)vk0WaDujT_M^9RZujlF+1jTWncJTlAM$Vq&#Hoe zV_TgB^E5LYi?bIMoa1%B`%J5Ss{W3*o7S($3Om_c6?X2_j(-a|%%`-Uy5px=_aMXK zE!%X9HCbDEuh+Pyg`QjE7ud48E~(rv#PWIA;=F>+!&%~gtY+!_F5)|*RUB~Md2Mx!rEB&!?|ilonP0({bi6+WPQ)gjSyz{{x

f z{rQJdgByM}?u8#5MvRJt&Qq`ssr#`N$J6U0q+t9s*I5Uf zz+PYV$y9Z-(vbwm?I8O@t7>NK=Q1~qxfWl(;P-@WPgYHHoalUwv11tr{qZ;HPX}Kv VsBz4i04%^5JYD@<);T3K0RVAlHw^#) literal 0 HcmV?d00001 diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_extshape.xml b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_extshape.xml new file mode 100644 index 0000000000..81b84db3b0 --- /dev/null +++ b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_extshape.xml @@ -0,0 +1,22 @@ + + + + + extshape://arrow#FF00000.4#000000140 + 00 + extshape://emicircle#FF00000.4#000000140 + 1000 + extshape://narrow#FF00000.4#000000140 + 2000 + extshape://sarrow#FF00000.4#000000140 + 3000 + extshape://triangle#FF00000.4#000000140 + 4000 + extshape://triangleemicircle#FF00000.4#000000140 + 5000 + + diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_qgis.gml b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_qgis.gml new file mode 100644 index 0000000000..446573c47f --- /dev/null +++ b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_qgis.gml @@ -0,0 +1,23 @@ + + + + 0.0 0.0 + 1000.0 300.0 + + + + + 1 + dummy + + + 50.000000 250.000000 + + + + + diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_qgis.png b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_qgis.png new file mode 100644 index 0000000000000000000000000000000000000000..2c91b9bbd0ce07c1e7edd47011cff53c8365bd98 GIT binary patch literal 6667 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 + + + + qgis://arrow#FF00000.4#000000140 + 00 + qgis://arrowhead#FF00000.4#000000140 + 1000 + qgis://circle#FF00000.4#000000140 + 2000 + qgis://cross#FF00000.4#000000140 + 3000 + qgis://cross2#FF00000.4#000000140 + 4000 + qgis://crossfill#FF00000.4#000000140 + 5000 + qgis://diagonalhalfsquare#FF00000.4#000000140 + 6000 + qgis://diamond#FF00000.4#000000140 + 7000 + qgis://equilateral_triangle#FF00000.4#000000140 + 8000 + qgis://filled_arrowhead#FF00000.4#000000140 + 9000 + qgis://halfsquare#FF00000.4#000000140 + 0100 + qgis://hexagon#FF00000.4#000000140 + 100100 + qgis://lefthalftriangle#FF00000.4#000000140 + 200100 + qgis://line#FF00000.4#000000140 + 300100 + qgis://pentagon#FF00000.4#000000140 + 400100 + qgis://quartercircle#FF00000.4#000000140 + 500100 + qgis://quartersquare#FF00000.4#000000140 + 600100 + qgis://rectangle#FF00000.4#000000140 + 700100 + qgis://regular_star#FF00000.4#000000140 + 800100 + qgis://righthalftriangle#FF00000.4#000000140 + 900100 + qgis://semicircle#FF00000.4#000000140 + 0200 + qgis://star#FF00000.4#000000140 + 100200 + qgis://thirdcircle#FF00000.4#000000140 + 200200 + qgis://triangle#FF00000.4#000000140 + 300200 + + diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_shape.gml b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_shape.gml new file mode 100644 index 0000000000..dca71d4221 --- /dev/null +++ b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_shape.gml @@ -0,0 +1,23 @@ + + + + 0.0 0.0 + 1100.0 100.0 + + + + + 1 + dummy + + + 50.000000 50.000000 + + + + + diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_shape.png b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_shape.png new file mode 100644 index 0000000000000000000000000000000000000000..b288c5c9eb2f40d14d28b6f34b176f2190021e50 GIT binary patch literal 2259 zcmc&$`#;l*8~>c5#u1f-$}N{%Ix5R$*p$mTh$hQrg_4=07N=<=qn%0?&6g0SHQgkQ zX>5lXTR5(pRU~p;8qLx$g^mJkQb^5in_>U}6?(ZJKb;UZ*&mJ_wNu;jwtiz9wx3n0nHk}rZhFE* ziD$p`ZpzGV$?M6TlN-qj;;vcwjD~_Q5@u}%fZPjhKLCLDk9yeX$F7RwfazpnY58Gmm4QBVGUS{C#IA(Lhg75zNTX0TP<=flWt#K zN@rmi^$0jb8*V2^-ua&i{=-jE{8CpNCQ4cOdUt%*g$Dgvs+)^5pDK{|B1H2!9oU?d zoRzzUD@q1k389E6@>lWY5FjWh3$8xZzGG{5vCM4+|^j$7k+U2)8TrL-yLcGrl` z0xiG7K}`H@>F^9fKttK@T@yhBieX)iX8uJNO@9jF|lM<0hQ9Nm55d;Ngxpq{!tU_4C?^ zq&e6Fw_n$oDiR+v4>;uM__$26_-)BSESokWF>&>(*J4F)r(bu_w8*m)UdVMy=*J{G z&B4y1Q)|nc!2;crc{J?v?#|vz@{h9LUZQAYhwEar_xG|v$>bjQi*r57Iy8GW0&NO-7@zlMb$pS6PugV)o+MWIY|LEo@7Y368t3zQXg132~c1^=B1$!`<1d7&BJDpYtVW z-77EVf?wo9i+#TO39_4hl)rho=s1w)M*EuR(O6wXuSF|AO>yEEJL_FaqdzR$b4@L% zof6POgH@&CsFC$z=;BKrksj>DRO=Z zgj^AM%npX!M71FNFkkt`u_ztO9!{`^A=xR%PfQxe`m5G`dzfCo&%$KaRRL$?e#Rt2{e6_T3ep+p+ z=A9qrju}qcq1gWnqE`zoOh7T_23yBCqvXNy()m_7>|sr9GTr~55hry0S`DFh@`D3J z$7~knN~ou1d6JHn?uFHW**g7v&WZa%h0E(W<8*v1dj5Y4gA7%4s#)wA>r2k~SUR^U zv6E|ReJ$?(8wIijXG+3zQEUO}eHJ*K47KghHJ1l7qMdJ6yySjc87 zEm)-3;)NGmGacDf2x_7xd2z;%E9vVT1t)3yFabHN%{J3RZLcd{DO&L3+^*4W_Lxsz_h~?^DxoPa^ zB;J0q(f&(T0I9;$O4<)zVEKxYkdd4_B3Xve4$zL9BE&HgAH*PWt4}akYv%~~0|~hR zFVLEELE5fB`r1?rKBVmZlyYLIEH3aN-#U#-7xi^JVW0aLljiZ2n`#O#gQ=J6tjq}kvFB>;Fu`4>;||M?fJZ=QdUdw)*_rd9D;0A3y^-5IXuZ~hm?lrT~N literal 0 HcmV?d00001 diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_shape.xml b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_shape.xml new file mode 100644 index 0000000000..ae7fb17f0b --- /dev/null +++ b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_shape.xml @@ -0,0 +1,32 @@ + + + + + shape://backslash#FF00000.4#000000140 + 00 + shape://carrow#FF00000.4#000000140 + 1000 + shape://ccarrow#FF00000.4#000000140 + 2000 + shape://coarrow#FF00000.4#000000140 + 3000 + shape://dot#FF00000.4#000000140 + 4000 + shape://horline#FF00000.4#000000140 + 5000 + shape://oarrow#FF00000.4#000000140 + 6000 + shape://plus#FF00000.4#000000140 + 7000 + shape://slash#FF00000.4#000000140 + 8000 + shape://times#FF00000.4#000000140 + 9000 + shape://vertline#FF00000.4#000000140 + 10000 + + diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_common.gml b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_common.gml new file mode 100644 index 0000000000..1be7cd7043 --- /dev/null +++ b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_common.gml @@ -0,0 +1,17 @@ + + + + 0.0 0.0 + 500.0 100.0 + + + 110 10 10 90 90 90 90 10 10 10 + 2110 10 110 90 190 90 190 10 110 10 + 3210 10 210 90 290 90 290 10 210 10 + 4310 10 310 90 390 90 390 10 310 10 + 5410 10 410 90 490 90 490 10 410 10 + diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_common.png b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_common.png new file mode 100644 index 0000000000000000000000000000000000000000..829e69568965e9132c795d475d707b24fc0a5cae GIT binary patch literal 3484 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 literal 0 HcmV?d00001 diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_common.xml b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_common.xml new file mode 100644 index 0000000000..5e1609d16a --- /dev/null +++ b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_common.xml @@ -0,0 +1,158 @@ + + + + + + + app:id + 1 + + + + + + + + shape://horline + + #000000 + 1 + butt + + + 10 + + + + + #0000FF + 1 + butt + + + + + + + app:id + 2 + + + + + + + + shape://vertline + + #000000 + 1 + butt + + + 10 + + + + + #0000FF + 1 + butt + + + + + + + app:id + 3 + + + + + + + + shape://slash + + #000000 + 1 + butt + + + 10 + + + + + #0000FF + 1 + butt + + + + + + + app:id + 4 + + + + + + + + shape://backslash + + #000000 + 1 + butt + + + 10 + + + + + #0000FF + 1 + butt + + + + + + + app:id + 5 + + + + + + + + shape://times + + #000000 + 1 + butt + + + 10 + + + + + #0000FF + 1 + butt + + + + diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_1.gml b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_1.gml new file mode 100644 index 0000000000..432f448b88 --- /dev/null +++ b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_1.gml @@ -0,0 +1,139 @@ + + + + 0.0 0.0 + 1000.0 1000.0 + + + + 1110 10 10 90 90 90 90 10 10 10 + 22110 10 110 90 190 90 190 10 110 10 + 33210 10 210 90 290 90 290 10 210 10 + 44310 10 310 90 390 90 390 10 310 10 + 55410 10 410 90 490 90 490 10 410 10 + 66510 10 510 90 590 90 590 10 510 10 + 77610 10 610 90 690 90 690 10 610 10 + 88710 10 710 90 790 90 790 10 710 10 + 99810 10 810 90 890 90 890 10 810 10 + 1010910 10 910 90 990 90 990 10 910 10 + + 111110 110 10 190 90 190 90 110 10 110 + 1212110 110 110 190 190 190 190 110 110 110 + 1313210 110 210 190 290 190 290 110 210 110 + 1414310 110 310 190 390 190 390 110 310 110 + 1515410 110 410 190 490 190 490 110 410 110 + 1616510 110 510 190 590 190 590 110 510 110 + 1717610 110 610 190 690 190 690 110 610 110 + 1818710 110 710 190 790 190 790 110 710 110 + 1919810 110 810 190 890 190 890 110 810 110 + 2020910 110 910 190 990 190 990 110 910 110 + + 212110 210 10 290 90 290 90 210 10 210 + 2222110 210 110 290 190 290 190 210 110 210 + 2323210 210 210 290 290 290 290 210 210 210 + 2424310 210 310 290 390 290 390 210 310 210 + 2525410 210 410 290 490 290 490 210 410 210 + 2626510 210 510 290 590 290 590 210 510 210 + 2727610 210 610 290 690 290 690 210 610 210 + 2828710 210 710 290 790 290 790 210 710 210 + 2929810 210 810 290 890 290 890 210 810 210 + 3030910 210 910 290 990 290 990 210 910 210 + + 313110 310 10 390 90 390 90 310 10 310 + 3232110 310 110 390 190 390 190 310 110 310 + 3333210 310 210 390 290 390 290 310 210 310 + 3434310 310 310 390 390 390 390 310 310 310 + 3535410 310 410 390 490 390 490 310 410 310 + 3636510 310 510 390 590 390 590 310 510 310 + 3737610 310 610 390 690 390 690 310 610 310 + 3838710 310 710 390 790 390 790 310 710 310 + 3939810 310 810 390 890 390 890 310 810 310 + 4040910 310 910 390 990 390 990 310 910 310 + + 414110 410 10 490 90 490 90 410 10 410 + 4242110 410 110 490 190 490 190 410 110 410 + 4343210 410 210 490 290 490 290 410 210 410 + 4444310 410 310 490 390 490 390 410 310 410 + 4545410 410 410 490 490 490 490 410 410 410 + 4646510 410 510 490 590 490 590 410 510 410 + 4747610 410 610 490 690 490 690 410 610 410 + 4848710 410 710 490 790 490 790 410 710 410 + 4949810 410 810 490 890 490 890 410 810 410 + 5050910 410 910 490 990 490 990 410 910 410 + + 515110 510 10 590 90 590 90 510 10 510 + 5252110 510 110 590 190 590 190 510 110 510 + 5353210 510 210 590 290 590 290 510 210 510 + 5454310 510 310 590 390 590 390 510 310 510 + 5555410 510 410 590 490 590 490 510 410 510 + 5656510 510 510 590 590 590 590 510 510 510 + 5757610 510 610 590 690 590 690 510 610 510 + 5858710 510 710 590 790 590 790 510 710 510 + 5959810 510 810 590 890 590 890 510 810 510 + 6060910 510 910 590 990 590 990 510 910 510 + + 616110 610 10 690 90 690 90 610 10 610 + 6262110 610 110 690 190 690 190 610 110 610 + 6363210 610 210 690 290 690 290 610 210 610 + 6464310 610 310 690 390 690 390 610 310 610 + 6565410 610 410 690 490 690 490 610 410 610 + 6666510 610 510 690 590 690 590 610 510 610 + 6767610 610 610 690 690 690 690 610 610 610 + 6868710 610 710 690 790 690 790 610 710 610 + 6969810 610 810 690 890 690 890 610 810 610 + 7070910 610 910 690 990 690 990 610 910 610 + + 717110 710 10 790 90 790 90 710 10 710 + 7272110 710 110 790 190 790 190 710 110 710 + 7373210 710 210 790 290 790 290 710 210 710 + 7474310 710 310 790 390 790 390 710 310 710 + 7575410 710 410 790 490 790 490 710 410 710 + 7676510 710 510 790 590 790 590 710 510 710 + 7777610 710 610 790 690 790 690 710 610 710 + 7878710 710 710 790 790 790 790 710 710 710 + 7979810 710 810 790 890 790 890 710 810 710 + 8080910 710 910 790 990 790 990 710 910 710 + + 818110 810 10 890 90 890 90 810 10 810 + 8282110 810 110 890 190 890 190 810 110 810 + 8383210 810 210 890 290 890 290 810 210 810 + 8484310 810 310 890 390 890 390 810 310 810 + 8585410 810 410 890 490 890 490 810 410 810 + 8686510 810 510 890 590 890 590 810 510 810 + 8787610 810 610 890 690 890 690 810 610 810 + 8888710 810 710 890 790 890 790 810 710 810 + 8989810 810 810 890 890 890 890 810 810 810 + 9090910 810 910 890 990 890 990 810 910 810 + + 919110 910 10 990 90 990 90 910 10 910 + 9292110 910 110 990 190 990 190 910 110 910 + 9393210 910 210 990 290 990 290 910 210 910 + 9494310 910 310 990 390 990 390 910 310 910 + 9595410 910 410 990 490 990 490 910 410 910 + 9696510 910 510 990 590 990 590 910 510 910 + 9797610 910 610 990 690 990 690 910 610 910 + 9898710 910 710 990 790 990 790 910 710 910 + 9999810 910 810 990 890 990 890 910 810 910 + 100100910 910 910 990 990 990 990 910 910 910 + + diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_1.png b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_1.png new file mode 100644 index 0000000000000000000000000000000000000000..24eb02531c2798b7fd6869379b45ed616771286d GIT binary patch literal 72093 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%0D>#*4uS3JRoWX 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 F{SSrLG*AEl literal 0 HcmV?d00001 diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_1.xml b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_1.xml new file mode 100644 index 0000000000..d9c8f65829 --- /dev/null +++ b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_1.xml @@ -0,0 +1,40 @@ + + + + + + + + + + shape://vertline + + + #000000 + 1 + butt + + + + + + app:rotation + 5 + + + app:rotation + + + + + #0000FF + 1 + butt + + + + diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_2.gml b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_2.gml new file mode 100644 index 0000000000..432f448b88 --- /dev/null +++ b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_2.gml @@ -0,0 +1,139 @@ + + + + 0.0 0.0 + 1000.0 1000.0 + + + + 1110 10 10 90 90 90 90 10 10 10 + 22110 10 110 90 190 90 190 10 110 10 + 33210 10 210 90 290 90 290 10 210 10 + 44310 10 310 90 390 90 390 10 310 10 + 55410 10 410 90 490 90 490 10 410 10 + 66510 10 510 90 590 90 590 10 510 10 + 77610 10 610 90 690 90 690 10 610 10 + 88710 10 710 90 790 90 790 10 710 10 + 99810 10 810 90 890 90 890 10 810 10 + 1010910 10 910 90 990 90 990 10 910 10 + + 111110 110 10 190 90 190 90 110 10 110 + 1212110 110 110 190 190 190 190 110 110 110 + 1313210 110 210 190 290 190 290 110 210 110 + 1414310 110 310 190 390 190 390 110 310 110 + 1515410 110 410 190 490 190 490 110 410 110 + 1616510 110 510 190 590 190 590 110 510 110 + 1717610 110 610 190 690 190 690 110 610 110 + 1818710 110 710 190 790 190 790 110 710 110 + 1919810 110 810 190 890 190 890 110 810 110 + 2020910 110 910 190 990 190 990 110 910 110 + + 212110 210 10 290 90 290 90 210 10 210 + 2222110 210 110 290 190 290 190 210 110 210 + 2323210 210 210 290 290 290 290 210 210 210 + 2424310 210 310 290 390 290 390 210 310 210 + 2525410 210 410 290 490 290 490 210 410 210 + 2626510 210 510 290 590 290 590 210 510 210 + 2727610 210 610 290 690 290 690 210 610 210 + 2828710 210 710 290 790 290 790 210 710 210 + 2929810 210 810 290 890 290 890 210 810 210 + 3030910 210 910 290 990 290 990 210 910 210 + + 313110 310 10 390 90 390 90 310 10 310 + 3232110 310 110 390 190 390 190 310 110 310 + 3333210 310 210 390 290 390 290 310 210 310 + 3434310 310 310 390 390 390 390 310 310 310 + 3535410 310 410 390 490 390 490 310 410 310 + 3636510 310 510 390 590 390 590 310 510 310 + 3737610 310 610 390 690 390 690 310 610 310 + 3838710 310 710 390 790 390 790 310 710 310 + 3939810 310 810 390 890 390 890 310 810 310 + 4040910 310 910 390 990 390 990 310 910 310 + + 414110 410 10 490 90 490 90 410 10 410 + 4242110 410 110 490 190 490 190 410 110 410 + 4343210 410 210 490 290 490 290 410 210 410 + 4444310 410 310 490 390 490 390 410 310 410 + 4545410 410 410 490 490 490 490 410 410 410 + 4646510 410 510 490 590 490 590 410 510 410 + 4747610 410 610 490 690 490 690 410 610 410 + 4848710 410 710 490 790 490 790 410 710 410 + 4949810 410 810 490 890 490 890 410 810 410 + 5050910 410 910 490 990 490 990 410 910 410 + + 515110 510 10 590 90 590 90 510 10 510 + 5252110 510 110 590 190 590 190 510 110 510 + 5353210 510 210 590 290 590 290 510 210 510 + 5454310 510 310 590 390 590 390 510 310 510 + 5555410 510 410 590 490 590 490 510 410 510 + 5656510 510 510 590 590 590 590 510 510 510 + 5757610 510 610 590 690 590 690 510 610 510 + 5858710 510 710 590 790 590 790 510 710 510 + 5959810 510 810 590 890 590 890 510 810 510 + 6060910 510 910 590 990 590 990 510 910 510 + + 616110 610 10 690 90 690 90 610 10 610 + 6262110 610 110 690 190 690 190 610 110 610 + 6363210 610 210 690 290 690 290 610 210 610 + 6464310 610 310 690 390 690 390 610 310 610 + 6565410 610 410 690 490 690 490 610 410 610 + 6666510 610 510 690 590 690 590 610 510 610 + 6767610 610 610 690 690 690 690 610 610 610 + 6868710 610 710 690 790 690 790 610 710 610 + 6969810 610 810 690 890 690 890 610 810 610 + 7070910 610 910 690 990 690 990 610 910 610 + + 717110 710 10 790 90 790 90 710 10 710 + 7272110 710 110 790 190 790 190 710 110 710 + 7373210 710 210 790 290 790 290 710 210 710 + 7474310 710 310 790 390 790 390 710 310 710 + 7575410 710 410 790 490 790 490 710 410 710 + 7676510 710 510 790 590 790 590 710 510 710 + 7777610 710 610 790 690 790 690 710 610 710 + 7878710 710 710 790 790 790 790 710 710 710 + 7979810 710 810 790 890 790 890 710 810 710 + 8080910 710 910 790 990 790 990 710 910 710 + + 818110 810 10 890 90 890 90 810 10 810 + 8282110 810 110 890 190 890 190 810 110 810 + 8383210 810 210 890 290 890 290 810 210 810 + 8484310 810 310 890 390 890 390 810 310 810 + 8585410 810 410 890 490 890 490 810 410 810 + 8686510 810 510 890 590 890 590 810 510 810 + 8787610 810 610 890 690 890 690 810 610 810 + 8888710 810 710 890 790 890 790 810 710 810 + 8989810 810 810 890 890 890 890 810 810 810 + 9090910 810 910 890 990 890 990 810 910 810 + + 919110 910 10 990 90 990 90 910 10 910 + 9292110 910 110 990 190 990 190 910 110 910 + 9393210 910 210 990 290 990 290 910 210 910 + 9494310 910 310 990 390 990 390 910 310 910 + 9595410 910 410 990 490 990 490 910 410 910 + 9696510 910 510 990 590 990 590 910 510 910 + 9797610 910 610 990 690 990 690 910 610 910 + 9898710 910 710 990 790 990 790 910 710 910 + 9999810 910 810 990 890 990 890 910 810 910 + 100100910 910 910 990 990 990 990 910 910 910 + + diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_2.png b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/polygon_hatches_custom_2.png new file mode 100644 index 0000000000000000000000000000000000000000..671d53699ff537c0f8d75601202da0e43e768eca GIT binary patch literal 88000 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 i-)Q##`^6q_%({)3FPY`CX5Lr$pQZV + + + + + + + + + shape://vertline + + + #000000 + 3 + butt + + + + + + app:rotation + 6 + + + app:rotation + + + + + #0000FF + 1 + butt + + + + From 03b5c712aa6ffc05e5e11c7a8a04d2dde80b1089 Mon Sep 17 00:00:00 2001 From: Stephan Reichhelm Date: Mon, 10 Oct 2022 12:45:14 +0200 Subject: [PATCH 4/8] add helper function to simplify calculation of size for hatches (distance between hatching lines) --- .../function/styling/HatchingDistance.java | 165 ++++++++++++++++++ ...g.deegree.filter.function.FunctionProvider | 3 +- 2 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 deegree-core/deegree-core-filterfunctions/src/main/java/org/deegree/filter/function/styling/HatchingDistance.java diff --git a/deegree-core/deegree-core-filterfunctions/src/main/java/org/deegree/filter/function/styling/HatchingDistance.java b/deegree-core/deegree-core-filterfunctions/src/main/java/org/deegree/filter/function/styling/HatchingDistance.java new file mode 100644 index 0000000000..02ce9c8e69 --- /dev/null +++ b/deegree-core/deegree-core-filterfunctions/src/main/java/org/deegree/filter/function/styling/HatchingDistance.java @@ -0,0 +1,165 @@ +/*---------------------------------------------------------------------------- + This file is part of deegree, http://deegree.org/ + Copyright (C) 2022 by: + - grit graphische Informationstechnik Beratungsgesellschaft mbH - + + This library is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at your option) + any later version. + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Contact information: + + grit graphische Informationstechnik Beratungsgesellschaft mbH + Landwehrstr. 143, 59368 Werne + Germany + http://www.grit.de/ + + lat/lon GmbH + Aennchenstr. 19, 53177 Bonn + Germany + http://lat-lon.de/ + + Department of Geography, University of Bonn + Prof. Dr. Klaus Greve + Postfach 1147, 53001 Bonn + Germany + http://www.geographie.uni-bonn.de/deegree/ + + e-mail: info@deegree.org + ----------------------------------------------------------------------------*/ +package org.deegree.filter.function.styling; + +import static org.deegree.commons.utils.math.MathUtils.isZero; +import static org.deegree.filter.function.ParameterType.DOUBLE; + +import java.util.ArrayList; +import java.util.List; +import org.deegree.commons.tom.TypedObjectNode; +import org.deegree.commons.tom.primitive.PrimitiveValue; +import org.deegree.commons.utils.Pair; +import org.deegree.feature.property.SimpleProperty; +import org.deegree.filter.Expression; +import org.deegree.filter.FilterEvaluationException; +import org.deegree.filter.XPathEvaluator; +import org.deegree.filter.expression.Function; +import org.deegree.filter.function.FunctionProvider; +import org.deegree.filter.function.ParameterType; +import org.deegree.workspace.ResourceInitException; +import org.deegree.workspace.Workspace; + +public class HatchingDistance implements FunctionProvider { + + private static final String NAME = "HatchingDistance"; + + private static final List INPUTS = new ArrayList( 2 ); + + static { + INPUTS.add( DOUBLE ); + INPUTS.add( DOUBLE ); + } + + static void checkTwoArguments( String name, TypedObjectNode[] vals1, TypedObjectNode[] vals2 ) + throws + FilterEvaluationException { + if ( vals1.length == 0 || vals2.length == 0 ) { + String msg = "The " + name + " function expects two arguments, but "; + if ( vals1.length == 0 && vals2.length == 0 ) { + msg += "both arguments were missing."; + } else { + msg += "the "; + msg += vals1.length == 0 ? "first" : "second"; + msg += " argument was missing."; + } + throw new FilterEvaluationException( msg ); + } + } + + private static String extractAsText( TypedObjectNode tom ) { + PrimitiveValue pv = null; + if ( tom instanceof PrimitiveValue ) { + pv = (PrimitiveValue) tom; + } else if ( tom instanceof SimpleProperty ) { + pv = ( (SimpleProperty) tom ).getValue(); + } + if ( pv != null ) { + return pv.getAsText(); + } + return tom.toString(); + } + + @Override + public String getName() { + return NAME; + } + + @Override + public List getArgs() { + return INPUTS; + } + + @Override + public ParameterType getReturnType() { + return DOUBLE; + } + + @Override + public Function create( List params ) { + return new Function( NAME, params ) { + + private Pair extractValues( Expression first, Expression second, T f, + XPathEvaluator xpathEvaluator ) + throws + FilterEvaluationException { + TypedObjectNode[] vals1 = first.evaluate( f, xpathEvaluator ); + TypedObjectNode[] vals2 = second.evaluate( f, xpathEvaluator ); + + checkTwoArguments( NAME, vals1, vals2 ); + + return new Pair<>( Double.valueOf( extractAsText( vals1[0] ) ), + Double.valueOf( extractAsText( vals2[0] ) ) ); + } + + @Override + public TypedObjectNode[] evaluate( T obj, XPathEvaluator xpathEvaluator ) + throws + FilterEvaluationException { + Pair p = extractValues( getParams()[0], getParams()[1], obj, xpathEvaluator ); + double angle = p.getFirst(); + double distance; + while ( angle < 0.0 ) + angle += 90.0d; + while ( angle >= 90.0 ) + angle -= 90.0d; + + if ( isZero( angle ) ) { + distance = p.getSecond(); + } else { + double ak = p.getSecond() / Math.sin( Math.toRadians( angle ) ); + distance = ak / Math.cos( Math.toRadians( angle ) ); + } + + return new TypedObjectNode[] { new PrimitiveValue( Double.valueOf( distance ) ) }; + } + }; + } + + @Override + public void init( Workspace ws ) + throws + ResourceInitException { + // nothing to do + } + + @Override + public void destroy() { + // nothing to do + } +} \ No newline at end of file diff --git a/deegree-core/deegree-core-filterfunctions/src/main/resources/META-INF/services/org.deegree.filter.function.FunctionProvider b/deegree-core/deegree-core-filterfunctions/src/main/resources/META-INF/services/org.deegree.filter.function.FunctionProvider index af451db37c..3800ccf77f 100644 --- a/deegree-core/deegree-core-filterfunctions/src/main/resources/META-INF/services/org.deegree.filter.function.FunctionProvider +++ b/deegree-core/deegree-core-filterfunctions/src/main/resources/META-INF/services/org.deegree.filter.function.FunctionProvider @@ -11,4 +11,5 @@ org.deegree.filter.function.other.IDiv org.deegree.filter.function.other.IMod org.deegree.filter.function.other.ExtraProp org.deegree.filter.function.other.Upper -org.deegree.filter.function.other.Lower \ No newline at end of file +org.deegree.filter.function.other.Lower +org.deegree.filter.function.styling.HatchingDistance \ No newline at end of file From 1fbede0b500f8ecf29d997298afecef013246ad6 Mon Sep 17 00:00:00 2001 From: Stephan Reichhelm Date: Mon, 10 Oct 2022 12:45:55 +0200 Subject: [PATCH 5/8] add documentation for non-standard well known name hatches --- .../main/asciidoc/images/se_wkn/circle.png | Bin 0 -> 422 bytes .../src/main/asciidoc/images/se_wkn/cross.png | Bin 0 -> 90 bytes .../asciidoc/images/se_wkn/extshape_arrow.png | Bin 0 -> 195 bytes .../images/se_wkn/extshape_emicircle.png | Bin 0 -> 178 bytes .../images/se_wkn/extshape_narrow.png | Bin 0 -> 195 bytes .../images/se_wkn/extshape_sarrow.png | Bin 0 -> 258 bytes .../images/se_wkn/extshape_triangle.png | Bin 0 -> 204 bytes .../se_wkn/extshape_triangleemicircle.png | Bin 0 -> 237 bytes .../asciidoc/images/se_wkn/qgis_arrow.png | Bin 0 -> 187 bytes .../asciidoc/images/se_wkn/qgis_arrowhead.png | Bin 0 -> 288 bytes .../asciidoc/images/se_wkn/qgis_circle.png | Bin 0 -> 422 bytes .../asciidoc/images/se_wkn/qgis_cross.png | Bin 0 -> 90 bytes .../asciidoc/images/se_wkn/qgis_cross2.png | Bin 0 -> 223 bytes .../asciidoc/images/se_wkn/qgis_crossfill.png | Bin 0 -> 111 bytes .../images/se_wkn/qgis_diagonalhalfsquare.png | Bin 0 -> 178 bytes .../asciidoc/images/se_wkn/qgis_diamond.png | Bin 0 -> 403 bytes .../se_wkn/qgis_equilateral_triangle.png | Bin 0 -> 346 bytes .../images/se_wkn/qgis_filled_arrowhead.png | Bin 0 -> 279 bytes .../images/se_wkn/qgis_halfsquare.png | Bin 0 -> 96 bytes .../asciidoc/images/se_wkn/qgis_hexagon.png | Bin 0 -> 358 bytes .../images/se_wkn/qgis_lefthalftriangle.png | Bin 0 -> 272 bytes .../main/asciidoc/images/se_wkn/qgis_line.png | Bin 0 -> 86 bytes .../asciidoc/images/se_wkn/qgis_pentagon.png | Bin 0 -> 398 bytes .../images/se_wkn/qgis_quartercircle.png | Bin 0 -> 191 bytes .../images/se_wkn/qgis_quartersquare.png | Bin 0 -> 93 bytes .../asciidoc/images/se_wkn/qgis_rectangle.png | Bin 0 -> 96 bytes .../images/se_wkn/qgis_regular_star.png | Bin 0 -> 465 bytes .../images/se_wkn/qgis_righthalftriangle.png | Bin 0 -> 269 bytes .../images/se_wkn/qgis_semicircle.png | Bin 0 -> 282 bytes .../main/asciidoc/images/se_wkn/qgis_star.png | Bin 0 -> 491 bytes .../images/se_wkn/qgis_thirdcircle.png | Bin 0 -> 289 bytes .../asciidoc/images/se_wkn/qgis_triangle.png | Bin 0 -> 376 bytes .../images/se_wkn/shape_backslash.png | Bin 0 -> 114 bytes .../asciidoc/images/se_wkn/shape_carrow.png | Bin 0 -> 218 bytes .../asciidoc/images/se_wkn/shape_ccarrow.png | Bin 0 -> 321 bytes .../asciidoc/images/se_wkn/shape_coarrow.png | Bin 0 -> 326 bytes .../main/asciidoc/images/se_wkn/shape_dot.png | Bin 0 -> 159 bytes .../asciidoc/images/se_wkn/shape_horline.png | Bin 0 -> 82 bytes .../asciidoc/images/se_wkn/shape_oarrow.png | Bin 0 -> 232 bytes .../asciidoc/images/se_wkn/shape_plus.png | Bin 0 -> 90 bytes .../asciidoc/images/se_wkn/shape_slash.png | Bin 0 -> 160 bytes .../asciidoc/images/se_wkn/shape_times.png | Bin 0 -> 223 bytes .../asciidoc/images/se_wkn/shape_vertline.png | Bin 0 -> 86 bytes .../main/asciidoc/images/se_wkn/square.png | Bin 0 -> 96 bytes .../src/main/asciidoc/images/se_wkn/star.png | Bin 0 -> 463 bytes .../main/asciidoc/images/se_wkn/triangle.png | Bin 0 -> 410 bytes .../src/main/asciidoc/images/se_wkn/x.png | Bin 0 -> 223 bytes .../extshape_arrow_ab_01_10.png | Bin 0 -> 4675 bytes .../extshape_arrow_hr_02_20.png | Bin 0 -> 3608 bytes .../se_wkn_example/extshape_arrow_t_00_10.png | Bin 0 -> 1535 bytes .../images/se_wkn_example/hatch_10deg.png | Bin 0 -> 832 bytes .../images/se_wkn_example/hatch_backslash.png | Bin 0 -> 693 bytes .../images/se_wkn_example/hatch_slash.png | Bin 0 -> 707 bytes .../images/se_wkn_example/hatch_times.png | Bin 0 -> 736 bytes .../qgis_circle_hatch_bounded.png | Bin 0 -> 518 bytes .../qgis_circle_hatch_default.png | Bin 0 -> 1016 bytes .../ttf_fontawesome_external.png | Bin 0 -> 1059 bytes .../images/se_wkn_example/ttf_lucida_sans.png | Bin 0 -> 1485 bytes .../src/main/asciidoc/renderstyles.adoc | 222 ++++++++++++++++++ 59 files changed, 222 insertions(+) create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/circle.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/cross.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/extshape_arrow.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/extshape_emicircle.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/extshape_narrow.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/extshape_sarrow.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/extshape_triangle.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/extshape_triangleemicircle.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_arrow.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_arrowhead.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_circle.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_cross.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_cross2.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_crossfill.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_diagonalhalfsquare.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_diamond.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_equilateral_triangle.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_filled_arrowhead.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_halfsquare.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_hexagon.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_lefthalftriangle.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_line.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_pentagon.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_quartercircle.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_quartersquare.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_rectangle.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_regular_star.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_righthalftriangle.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_semicircle.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_star.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_thirdcircle.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_triangle.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_backslash.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_carrow.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_ccarrow.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_coarrow.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_dot.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_horline.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_oarrow.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_plus.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_slash.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_times.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_vertline.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/square.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/star.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/triangle.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/x.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/extshape_arrow_ab_01_10.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/extshape_arrow_hr_02_20.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/extshape_arrow_t_00_10.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/hatch_10deg.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/hatch_backslash.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/hatch_slash.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/hatch_times.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/qgis_circle_hatch_bounded.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/qgis_circle_hatch_default.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/ttf_fontawesome_external.png create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/ttf_lucida_sans.png diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/circle.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/circle.png new file mode 100644 index 0000000000000000000000000000000000000000..7c87562f539e184f8c9959542b08e2541268903c GIT binary patch literal 422 zcmV;X0a^ZuP)$38gef{ChO zy>JwR&r!JCf}JN=b|IOEr8I0$gA<20=}w;ymW8RJt8TbIhYf>-$>6harXRm6Z7#Gj zgZULzqg_Y~`l9s7Up=#9R;sL&R$#vY9)yVpKr>(rvbDl|$*db;76V|rj%o%(1#ZH+ zFirrpk*KA2#ZnWK!hHN}qZ<|G%NYMx;UD!d695O`a0)J>0=0@+VO9fRCycbfYm{Rj zYj!n<&%z`MhPxH6ZBJ`~*$OJ}R_Uoy+t)91@^%4K3$xw#<}Vg@Kg=}hCXrBWZGr;Rvs$6Bo(JakNr`~+I-ZSI5nV??r4e;JboQql0 Q1PO%?^;ZrAGQUiC nP_OmyqKBkuL5j482?N9T4yAj09@gjs6*G9c`njxgN@xNAtSA|I literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/extshape_arrow.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/extshape_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..c6008309627e6d6a02849a9594bffbf29c5e13b2 GIT binary patch literal 195 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;Am#2$kNX4z>1O>hu1_6RA7(Ui( z_*y&LONnRfX+PEUx)JaM2v2Ms#>!y=U0Wv$fIbyOF;1PNAWz77LJ1D^*8 z2^OagA28rN5x($PV7n&cy#knqBgrAqjwfyA|>1dG$h4{T@=`K;3L!(K2V$)vNlDbPWW afx(zdS^nao6UjhFFnGH9xvX1O>hu1_6RA7(Ui( z_*y&LONnRfX+PEUx)JaM2v2Ms#>!y=U0Wv$fIbyOF;@LjG2w>eD(&0|Nr`=T(h@Wr z%-$F>JL`GOX>B|>F{OU9p}`!^Iq)R3m2TmOL zpxD)zXgT2@)1zSJ#P80R@0Mge6=7Y`sC7kWt8GUp2ZPFiuQL_?fCd(XP_4&Q3BR9Pi6 kB31+#*RJeI+t|p;@F7i|{|z%oB+&f~p00i_>zopr0DNXvivR!s literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_arrow.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..c767021bc0ae4f9d9c3955f3cba0f1e2b42ff1d7 GIT binary patch literal 187 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;Alc$SgNX4z>1O>hg1_9hFj15AV zSN>nc!*flx1nmZ>PK%R2ITo%KJQ7{d)UX-#NLge( jSkdTw+(Bo?J_d$uY{kd6%5!A^UBlq%>gTe~DWM4f;_5oJ literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_arrowhead.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_arrowhead.png new file mode 100644 index 0000000000000000000000000000000000000000..c3b140659621cce7be27ff59b330fc1111bac939 GIT binary patch literal 288 zcmV+*0pI?KP)}*6px8hVe$2p-E6u=g0%+(7pp*#327>Tc28Ikn28P{C3=DUH(kc`i2*W-M z46B(L7~TPuSWv}45Y}N}I0aEcLR!UTSQG=pLZ}NpD0ZPW1H%Sj7(N9`8&DL6z|@_s z$iQ#_XxK%dlmbPud>fckfB|&|m}K@)l)piS9bjN6Vq;*q1LV%9C{csJbOweppch|4 mvNeU-4ym+B7_{Z#;06Gudt6&?Mdz3R0000$38gef{ChO zy>JwR&r!JCf}JN=b|IOEr8I0$gA<20=}w;ymW8RJt8TbIhYf>-$>6harXRm6Z7#Gj zgZULzqg_Y~`l9s7Up=#9R;sL&R$#vY9)yVpKr>(rvbDl|$*db;76V|rj%o%(1#ZH+ zFirrpk*KA2#ZnWK!hHN}qZ<|G%NYMx;UD!d695O`a0)J>0=0@+VO9fRCycbfYm{Rj zYj!n<&%z`MhPxH6ZBJ`~*$OJ}R_Uoy+t)91@^%4K3$xw#<}Vg@Kg=}hCXrBWZGr;Rvs$6Bo(JakNr`~+I-ZSI5nV??r4e;JboQql0 Q1PO%?^;ZrAGQUiC nP_OmyqKBkuL5j482?N9T4yAj09@gjs6*G9c`njxgN@xNAtSA|I literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_cross2.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_cross2.png new file mode 100644 index 0000000000000000000000000000000000000000..2bffb0b2144b8f38a710498f9a282b7f550f8de9 GIT binary patch literal 223 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqEGG z{0>N%!F+{h$3i`aKXM(m8U{KHv4@&@oD=yt4=iO!(=fcZT`_Dew;)$ymXgO;F0=R1 z3?H+Llmw$^R84qgRFjzH|kdxz4|_BjRB zy~<{>9;R2?T3X&Zcb@j}{PQ8G`O1fbl7V~y(^&&%{0QW_!N4W_zxYegY^_iRhOPTd V46j$GX98W!;OXk;vd$@?2>|2QP%{7k literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_crossfill.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_crossfill.png new file mode 100644 index 0000000000000000000000000000000000000000..aeaabbb46c3781d4939ae80c300c96260b5365c7 GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;=nWu|mNX4z>gayVw`dNe16fU%w zNXVH^*vIzoc| zzW>nLrgCcCRsJJg3PCxumq_1ueIaMT0b{058J>%pxC@NpS4mHpxnkPf>-@7c9?X@s zka)ozwj$s_R_(%u&2#@X8P7F4n6W(8;L=NhFJ)OwwsU7WYQJLAZ7*tG?A&_b-ohy& czs~n_>-gO=;_`1!2Reem)78&qol`;+0MJrHTmS$7 literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_diamond.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_diamond.png new file mode 100644 index 0000000000000000000000000000000000000000..14792fda4b954fa1bdff066f353bacf9b6a4e9cb GIT binary patch literal 403 zcmV;E0c`$>P)9`%sJ1z-}z1hW@;uX)xelMYzr3t4XcNtV)z<>WGQ@B z!CGio9SoL0b_Moqn7V`|0jA4gUtSl5N~U1Sk1$^gukxX!l*No;-ekFcgV`pymx#AN zBlbC_E?KU#Fx?JUh43tGEuoU>+zY1#GFNHu2$f9dQ8*B2Mlk(errie@L1D_>aO5z= zmP$D3?AaNt28HdyhMREW*Rd;MxdJ}!V9^w|4Vwacm-e{!V#;KO)sT9DIX~DAZ2bvS zlAAthgeR$-$p=fox(gdN+3lDt?R6{MIQy0-S=tn)WXaM#biui1W|^Qcr3PtEjliMj xHvMPjqc#W93CC`-cohHG9(QTSiBOhl;Wy$%)$lHW>iqx!002ovPDHLkV1m*Ox0e6_ literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_equilateral_triangle.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_equilateral_triangle.png new file mode 100644 index 0000000000000000000000000000000000000000..fdce10a85b4f2036499f6ac4f4fe1b57e185691b GIT binary patch literal 346 zcmV-g0j2(lP)T}jB^sMT++A7=e?UZ_G_kQ#|L2lrc&>fKAj%?vzfd%_oN0g}4;Q-dP|zCl*N&oJ!xZEM|J8O%`zs>xXNCEb1%Gz zo_#-nt9~%k8C=*HEko3mwho0wc(JV9fTmS=luCVJ+vW=Q4gdfE literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_filled_arrowhead.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_filled_arrowhead.png new file mode 100644 index 0000000000000000000000000000000000000000..152221f37f527a121b3f4844b7cd5fac17adecf3 GIT binary patch literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE?MkcwN$2@3=_EZo-kztN&$ z6`PTf!5+p-tRcn)oXpOq+RTS*6?V&aL~57`ym-DPn1@HzhKDD-aa}C4$m0b!90cml z9GIYe_CNts#tY5`J2;NAHGK$YYvXZdYrE^i!&BZ^q$MKFaoCQBXZ1`;iF=Gsbyp-Q zaJ)7!nA4=D&Dh1;lavs_QM!=*sNR;egc}SzhnG88GIt#kn6YcKsH6lR1MhAQk?;i? z)AE^%xeOMZW0-tKF6c1N;RDP(JgzxF^Bdm$oT8Ssq0vEqAIl})D<{e}TvAI6nBLwj b&cLv4MMTikLsd;cpE7v5`njxgN@xNAkAz@S literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_halfsquare.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_halfsquare.png new file mode 100644 index 0000000000000000000000000000000000000000..28b39a335e8753f7fb20bbf29fd6e4b8e1592496 GIT binary patch literal 96 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;=x~Gd{NX4z>gav{>{8`k_IxOfj tiK)19AduOeSH`qJMbhIf)3huGhK{Lc|L^8%JPOpp;OXk;vd$@?2>=z<8g2jp literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_hexagon.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_hexagon.png new file mode 100644 index 0000000000000000000000000000000000000000..a5c7020ccbd1f77dd2532edd8c0919cb8ce6a5cf GIT binary patch literal 358 zcmV-s0h#`ZP)QBL_*LYEiMv;2;%<`5kXMU z5`jx1Cj9};uXCv25xvKI>ZS({_j1p@pL_1%eh;{_LAqgEFgy>ZGBqP`whI2XVGFQ5 z2K6}Hlpw340q?S&@C1@9;*;<&1Fx5GWJ2=StB?u9%LF{H!J;E53RAOC9)*tsxcG!! zE6nO?$OoVmf{LEAW18zwZ9vKnWOco8Q-FHT7U%}_*ZaU;1{xaJgMt^B3cxl)kyLmb z9!0BnHQ09o>F1BZt?r+OIY$Ww;ZRyi^Bi*j!3uCJ@_ZBN<-D}D*bvl~p=8zc3S8;B z#FyIXV8#FxN8ss1+LvT??}O{_M|5TzKZW0+i{`pkU#sr|!@dG{MF0Q*07*qoM6N<$ Ef>+v{w*UYD literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_lefthalftriangle.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_lefthalftriangle.png new file mode 100644 index 0000000000000000000000000000000000000000..c2f1c4401e5c4f224fc90cd7b53ea0f563aef03e GIT binary patch literal 272 zcmV+r0q_2aP)9xx4<+e*%ZMikZq!@NRk;v(FB`jHsz^iQ&i0+h(t+xnjk%bjfq@mHbwDr zpY7Vt+kU&x&d!0)+8E<@R|=+J0#>GA6mD@Snt^3l3f!21K6GMmQNLsY>Q)*RSP0!| z95n$0XzOx<2vki#mm17frT=f0FYpS@BpfwYHvwH*FwwCOnopX5E-4*53|%v@2cE#w zuT{Q*E*aQst#1YnVWcY0T2GsRE;-l=^~}H-3_{N*nKc1j^03yP>9-&3C&^p?>^uOd WQh8w&UW8Tv00001PO%?^;ZrAGQ0E2 jm=;_)pqQj^k%8gte8Km#M62q63K=|I{an^LB{Ts56FU}J literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_pentagon.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_pentagon.png new file mode 100644 index 0000000000000000000000000000000000000000..f01ac7d0c502a55e0da903c9a7d60333fbb4a674 GIT binary patch literal 398 zcmV;90df9`P)A!S7?%)ZM_CL?mP#&VrI0^D7L!QX*;tI*f)ynTmy(TaSlA3Ti^)PZE~UgQ zEJP_Qu^zuuzVey*%sE&(^>#YndEe)IFTVqJtB$`~4KS%KQxCJ+L%(4~tKqZ>&X!=Y z8O|$Z<BE~4)eJ{U(NWbCAUSeqxgugMAP&h*n5K!8<=Ote*kt(ysriNQz8aiE-=rg zU`0K>@YP!Zqm6L+6JR@}G^m*@;TFQ{GmNo*+yTCM!criTW6ude* z*8xcvU_TtF+_fO-w3_r?CM}ssuJi?}+N5u*!(+X1Y4_#Z7o(dE>1y8wI1JlLAd&Cs s4c5Yq4KNBP@*m0v41cKJ)*}3`chfZZK?Vb4@c;k-07*qoM6N<$f|cQ~A^-pY literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_quartercircle.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_quartercircle.png new file mode 100644 index 0000000000000000000000000000000000000000..6d8b05a2c50c64231e0f2722974c87fb12522879 GIT binary patch literal 191 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;Ao2QFoNX4z>gazyq(i1LRNlcib zap*un^VG(N>;W(AZ?WXNX4z>gav{>{8`k_IxOfj qiK)19Advax6h8NZ8WOBO7#N-{N--<%FpUDLXYh3Ob6Mw<&;$V8K^blU literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_rectangle.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_rectangle.png new file mode 100644 index 0000000000000000000000000000000000000000..77030a4ce977b5708976d126e0310400a30a5f5e GIT binary patch literal 96 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;=x~Gd{NX4z>gav{>{8f7l1WtG_ sX6cu*$a=7%aWNa8IP=Qb13^HA+b^v+)4F9%2~Z1zr>mdKI;Vst03J6Q=Kufz literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_regular_star.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_regular_star.png new file mode 100644 index 0000000000000000000000000000000000000000..ecf46160ca0e27818c4c9ab7532c0426013394fa GIT binary patch literal 465 zcmV;?0WSWDP)rlCKDR zHflE1l-)RY=3PzGc<3Rf?R$%R2E@qNx#9?Y5mS!M408#1UUgryX zG^xJ?zJsuti^L2aurB#e0$+CLDN^Za%MOw1pb<_a?^xjaZ=8Oy#+Oy4F_?G4E9se* zT4^+_=3z!?%xlc9U3{YQrx{_5sO(HDYaI=m#@=$85Q!KqFj z6?>=_hs4mDSlPv$KDUl~IGcpsRalU=?nI;mIqnjK%f;}^BE%eQ*TR)8!ZL_g!n3^F z2if*#eOAW3ktgvYKT6o)a~KMSEbK6A+^e!f>aytuPp-Sa3Bk1&qr_eT00000NkvXX Hu0mjfHu%*Q literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_righthalftriangle.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_righthalftriangle.png new file mode 100644 index 0000000000000000000000000000000000000000..3e455279c323a0320d37df098c57f3653816d0c5 GIT binary patch literal 269 zcmV+o0rLKdP)?rLvY+cT?CB5 zvIx^x%r%&Uk{`}CG(^AzEb=gW$6SGBD5x{LTF@2&(=g9~^$BwW8qWvc=0CXuM+a{R TfRS0e00000NkvXXu0mjf^Nek< literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_semicircle.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_semicircle.png new file mode 100644 index 0000000000000000000000000000000000000000..338f0118442f7cc96a3ef99c3b920b74f681bbf1 GIT binary patch literal 282 zcmV+#0p=U^E-329SpFr!dPhteIenHZUNissVfptV2~Wh7D9-;*;LpTAHW}=6Kyk g^G9~&%9SHs0Qyy*@!9}_VQ9_|pCqcntJBZ>7LJ&a+ z8b`s3(V>(&DuN;i;^5Fpzh|DOnCg=RlY`@O_xs&9-}~L&1L;XAS(Ik!y<;<%VpuUi zKdfd0ufYd@LojXj4K!xVt_}87@1WVYu%0oyEeIN*S@SLaDzp+bCaz^$k>Kq%8OMU#9n0OB^5AaZ*mQz2689gtTDHE5iBHS^}p1>@d*4d5Orb3 zKt8~d`QtE`2e+Eh_i2H(!)z<;8>=peXiR?T54x&gM-BKLg^4~0i{)v&m?WZZcWWCi zwY;Hn_@kt63KzKNiVYO%JOIl!lVTb3Ed7frEmPOTYEw7#T=aWAv4A3CeIoW(h4Dd8 z1l8N*G(psU=D^Q%)=T#SLbCm-%cCyl?P}Po;uO=A?N@A002ovPDHLkV1nG~D7xa0=5j$ngF!JEE!OSg|8N|LMQp;cRuRM~R?&9t+T{xu41z%ncVKj{ zcwF9lBM5SAdMpO~Hu{vpp2?aA^%=gvvy{&&0q-(ZQx&wiW%DxX(qixxfu;;c)z8g2 nC5bOsU;0#7e?pXd+-Cd%Fb!#T_O(q`00000NkvXXu0mjf31oM^ literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_triangle.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/qgis_triangle.png new file mode 100644 index 0000000000000000000000000000000000000000..4bdacfb1b2cd29350542012c16b5d27abd0cd04d GIT binary patch literal 376 zcmV-;0f+vHP)(duB$K#e<5cyU3+X*jYm zimlJJ!=v__?t&YkOTW?@;VBLK24-N-?lm0?>rDtKmSEmM8{_b*`I%5!6P%~u*f1A+ zmzuu};|^hV=iNGp@TZC>8r4($icc7cmk_B?GLT% z2&5%oBMEn2m`fkrYTb4aFQ)CjtiY}xxCvX@MWJeidR2{9cym?pi>>Q{1z)feu4dt& z8fLM=>pOg?+!L5okxN#MAmB4(ZT$dDd4m0LIu2(+Fc&L+w`x@3aDV=JVUzf?U;8(7 Wr>nB8BEOda0000ga!siHZ7(JiRT+{ zw9jhW#qhCO;oE{`3+1+$Oi{Zh&wKfzf$YXaE2+RMU;hH4P$8{3#UpLO RYM^5oJYD@<);T3K0RX?1OH2R& literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_ccarrow.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_ccarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..1a3eb0b76da291f120704e6cd778f4820c61cb90 GIT binary patch literal 321 zcmV-H0lxl;P)1wHB0|wXAxu|i`vorjgr;)HMS@fun!-&`(4Z-oen6X>Xf-5AME-+v5m$8( zG)H^I6cMz0%b~#!9uD{1^F8<8_goIFYn5eNwQ%T!_XD_bz>%(Z{wz#O7K8^kG`FB9 z@v9xKbT1&RriDX@OsK(S9PSR`Wf$7p(9u}1Kv-+NriJqqA$bD#et47gQx9lpyj9=v zqWqT%XX(Rv7OoXXYt;8mZeIMOunviYa`r%V6S@lZQGJ@iY4{D>a1nyM56UCS22`~6 z%t($?;RnRjk6ItBtp@kAWT1GC|J;BOCO-kP5L(|NJM>t(nVZV zP|zIfry{6J_nOe+3l9g*Iq!4s{T&W0Ymv3KP}wT9-SD{s*Dl!m^8r-|r6mi(;}+C) zKv&{dCnU5S5H?f7Z`c>7W8NWt0k^yGvJOotEO-p{=z0ij^M@z4+Dt> zO4@$>YmSq`3Y@DWquVZOsV|;IRBRi*NS%G}c0*}aI1_r((Aj~*bn@<`jXyWPO7-Hd{{D+@~Cxpc(U{+Sb6^By?S2Rvx wUc{S{lG3v21CXI&*52pF^%N-O#mLOeaIk@0WuK(E1W-SNr>mdKI;Vst0P9F7*Z=?k literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_horline.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_horline.png new file mode 100644 index 0000000000000000000000000000000000000000..e8bd5c24b15b26896b47709d29eac4e676bfe076 GIT binary patch literal 82 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;=q^FBxNX4z>1PRu~2@=i!Lk=xY e5b0rB#K6!XF8F@ZW2SjPMGT&%`|W;8xzv}Qi+t?-VGD|v literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_plus.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_plus.png new file mode 100644 index 0000000000000000000000000000000000000000..599962731e727c7bacdcc672626b9b4e3e5ac61a GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;=qNj^vNX4z>1PO%?^;ZrAGQUiC nP_OmyqKBkuL5j482?N9T4yAj09@gjs6*G9c`njxgN@xNAtSA|I literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_slash.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_slash.png new file mode 100644 index 0000000000000000000000000000000000000000..47d71cc850c03ba0dd2f3446d00813234b7c75dd GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;Ax~Gd{NX4z>gavW}3l>H4@HzaM z6V-NzhkHR=qMpN_c~NaQ9e6)4Ty|P%MdA!rf&I&-owix=(nxqkqTCgp%@SF=dR8S) zb69(0N!EGG z{0>N%!F+{h$3i`aKXM(m8U{KHv4@&@oD=yt4=iO!(=fcZT`_Dew;)$ymXgO;F0=R1 z3?H+Llmw$^R84qgRFjzH|kdxz4|_BjRB zy~<{>9;R2?T3X&Zcb@j}{PQ8G`O1fbl7V~y(^&&%{0QW_!N4W_zxYegY^_iRhOPTd V46j$GX98W!;OXk;vd$@?2>|2QP%{7k literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_vertline.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/shape_vertline.png new file mode 100644 index 0000000000000000000000000000000000000000..9c6d420a7ca9634f84d02a5f13de110970fd702f GIT binary patch literal 86 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;=tfz}(NX4z>1PO%?^;ZrAGQ0E2 jm=;_)pqQj^k%8gte8Km#M62q63K=|I{an^LB{Ts56FU}J literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/square.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/square.png new file mode 100644 index 0000000000000000000000000000000000000000..77030a4ce977b5708976d126e0310400a30a5f5e GIT binary patch literal 96 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE;=x~Gd{NX4z>gav{>{8f7l1WtG_ sX6cu*$a=7%aWNa8IP=Qb13^HA+b^v+)4F9%2~Z1zr>mdKI;Vst03J6Q=Kufz literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/star.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/star.png new file mode 100644 index 0000000000000000000000000000000000000000..9b6ef317fcbb977f8824cc135e3c63658330a5f7 GIT binary patch literal 463 zcmV;=0WkiFP)cVcn}I|N8&6H`uLaJX}eNH$|#ffQ<$)61qG=ON6CNxJiH& zFYw}`Avg+SQSjtN+qLO%B>_9K;X?a{KcT73=^EHDfGw~X0|A@5R>wszqVof>7z)zh zyb`uwbZ8jO!=UCR6yBRK=Jdm4cz+8$C9o-dcLh`QnQ2rW%;m!69`x10dKGMii%q!C zW??8^`f8j8OzpS*=RmudJ(w2UY}~8`9FY50%Bi+8BiR||dRTP>8s^TBpXi%m?QV(+ zrR#AS92COYDfommqx1VX&7+2W{I|E`$PZJ7RTC^5R%-Ee9sDCOq5o&U!OK$dvjpmu z@WYzL>j+qjg}XMH7KCoG3@NX~_G#%-=Ao`cK!bek5MXYFZT7 z!dJqJ@vvjeqt#>JB=`J~*WlcYADzxulv`?Tax3`n^$z8Ph5~K>LJ8x5q*lBY{xD3)7V81{Oy|_$eVw+V>aM24VeqlzlruKq4s2CN2z-v?+IiV=2w0RSl5IekdOB>(^b07*qoM6N<$ Ef;MNjO8@`> literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/x.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn/x.png new file mode 100644 index 0000000000000000000000000000000000000000..2bffb0b2144b8f38a710498f9a282b7f550f8de9 GIT binary patch literal 223 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqEGG z{0>N%!F+{h$3i`aKXM(m8U{KHv4@&@oD=yt4=iO!(=fcZT`_Dew;)$ymXgO;F0=R1 z3?H+Llmw$^R84qgRFjzH|kdxz4|_BjRB zy~<{>9;R2?T3X&Zcb@j}{PQ8G`O1fbl7V~y(^&&%{0QW_!N4W_zxYegY^_iRhOPTd V46j$GX98W!;OXk;vd$@?2>|2QP%{7k literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/extshape_arrow_ab_01_10.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/extshape_arrow_ab_01_10.png new file mode 100644 index 0000000000000000000000000000000000000000..2d304eab7d78b65faee6b2f80ad0f79877d2a853 GIT binary patch literal 4675 zcmV-J61?q+P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D5!gvYK~#8N?VWu* zl4!9lTxJU6ycroqth9ASSWGl>YLJdF@}u4ELuX-yf- zMoUsuT3U*jHV3awp{L`OcI(vds=2luX6AO!le25*{ZI4xUgQ4GJ#$~*>-)W~>%N=y z_U&6a)HF3UnVOnHAx+q9wx*^g6jGzFuTNcF9SW&2GBWb<#~(u>HJ(0wx?sTqD5T7E z`g;BP^_)3#ppYih=IGDNZ1^tQ%@3`fFcD$62#x*&7+1$jAUu8#ags`23)6vZ|}ovpYwOAj7obTx_`13tD=Q=6@g)@%&?E&y zNTj;&zEjuKthsy{nxp{u?G=9c<@V@k+ugg;8$3JO+E%SuQ*-W|-4|a#lXR$Mu?Wu2 zfo5g}SFU7bWVm>F!3HTni-;(q(^Ix?Jycz-w{9J+pg=)E0k%mF)>mIq!^1bIsgaC~ zjy5zfJ39QfZ;wezl3@DQa`|#eUf$X2YSsDkx2#!%$6&7g_#@-it-9`R4d@cfaQzo88yb(|z~uz|hc=zyDo*(V|b6EYbet6CEX`PZbqER!|rj8@u=D z(f!fUABTtgMn~DBqxXl073R%TU%p&x|6DJSg5XYsU`s zF$8V685$bW)X*sP@gWoxw6(SA=<31-Nz>cYW1z3!9T$hs%cC8B5)6@h}-y$QUxxHO!;-w%y-ED1lHa5-S;mY&pgAQYP`0x%Y)!okzHcJRF+?lOj z{n?^Lxg=5oiPunVOP3 zJgls&M7tox3ow@Szuo)d7?l5oP zKJ~*7H`r`r6B9fh@8aSj)K57R!cA;g*d->jJ}eB%%F2e((T1y6IZ}dvfqJ8=YOJFp zN4`rvGBbPo`z4s*4E^*IC_OHRg{dxF2u*Tw*o+Ly!GkzF9%`|P4GJ3S>;xGH)b9cL z+QG)g`j!?+#e%fBxWgbd3lHZ$7kqB+*t~g+ni@%YsjI4bm)H3Ce8_9K0X@VdB?W6| zmzkF*=FhYzFpyPU%?JokU%VKa_>odun}6d5y{t^w0k4M1q>{;|%a+A#+Qb>prUay= zCD*Scu$`Wl zw}10ysO99y8#lJLwY9dkLMhRnW6kfMslyE|CdNQn*_f*Y09P2<(vtG!mrzTH*y!jO91a{D z>h~nz@r4BigM))mi$_ycRp*^MzC2rpG!+&7jg6_2IHUhOf9~hwQ|Ru_H&KswbZl>G zsyKTVYEkLx=peYc6?k||ntcR-9&*Oduj%5&*u8t9NmMvBRH?7;q#9}x;3sP!lSg`c zaSje5Ebex+wwkS7YqNZL4vBF1p`h$z|HMcZf;{(m}s#E;Ad#a^!6t2+!?WF5AXL$ zp-@0iKnA{bBCrh+p<;~;4oKk!{C*i(S$iEE_%7pltzX}F|Gq>D%iP375Y&i)nH&X zqD|sN2L?VE94ztnp3;kfib}b!ue+ODOG^thp`(t;d{;yH_#oF%ynv5H-@e^?`Eom3 zTjX+Mu)p8R$Vg#ylocGjM7$~Om5PdOyLOG;y$cc?G+|E0{}7~N3KTebnVB~tBL!XA znf3Mg?d@$H9pWrWJbC}+fz+e8c!Qf;z|Nge3yGtN$yRM`&-Lq}7Qm}FZ`LFw z<h9qIO(-bI&W?zRnzR&!%!!tkXcnvK>Q$7R zaRjY-3q{Pg-yXYmjm2W=>+3@k7a-ws6kKe6K(rd?%$YOJJd^YYOizsikQGw^fg>bH zB~sJU$d;A}qiBG+`S`PEC3HH}B9R&ug;7 z<8E$#o}R)w%87{q*&xbT0|1UnNTlfSaP*UoEp>IlRO&Z@f#_omz{}X!_n-d+1rG9* zDu-GY%hkhU%DLewiLo;{f^E(mdx8$&fU zyq;ccbTrf`=(=(xDLXq~m^=jlqQ()>Iq-Nip>6Q~eOEWPbOHfESwzeyg zi0p{PU=X%$MOgC|ieM9y#4o-81x`~_6Ew;A)5E`*0^vhnL*xI<%>zIG9GV31^3^My z{rh8*k~}>wijvs%$ zXb~u6_*TB4@UgeIhe9x-6*x6DHG($C31WuTH~?8O1>is6Gftd%IX;f2G?*(de*lMz z-M3GKGKbyKQBqaKyB$st3Lkw0N~&04?$Ej4)>c|s8H>X~jSg^9x!bn+d3m8(JUSQ@ zgi%%&x%!B)vAKEa67rr@-z{5|{`yz$otDA^GP??I?`H!8(E`3b5DvgagA9D@L|_{t z!p0gIGZp^fCMhK)2#ZBoeYhJLEtxyFu&@wn)Q|%L{7g-!+(pU_0fPZSs-d9)>Zu6X zu|v@MIx<)-E#sw26B81k7C=j7WjTw5K4S6$zT|H_J)KWJ4(~i{`=wu!umQg3AVPUii$b~KN)N6$rHbwI|XeZMvwCR`G@g%KW}f| zlVTPZXB8DO0s_QbE#{!QaAAFLaMqC{359#&UZ+|{d>uUz3f z-{EU-uR3RrXs5tSL~ZTJKmJj`l_Y{lXJB9egd7B^}!E`41DWE zU>hRRcz%cs8OTh|Zp2ACu$h@wL}JvGQ@L;6U{FH2U zq@%HM8b^XN$I4#Etyy*)cXYvHSKx%|+3{gY*9K7ru{! z6Agl{?&3LfL|A&0Awvc?zZFyM_4TIq_Pz1(=pR1B%Z-2k+ae>QySrOeRTY{hLL-yQ zD=RNksbVhca&Hq; zO5o&?fp47%Y(oTntdSu@1~0JNw_mzcbMvOivo_pBSz2ahW$}IfUTQ=HX4x`{+>*mV zUs>5&S65c%$dK`e02Wi8*4A@>`DN0hyhVmkT)aR>r=Xw!>i0->HRn%T=1h+l4l~l% z409xHFJd15U3SxT=~CIHOBC@Qn#oOqogJM{pY&)2sjlY8${ZOoe*e4+HyO#vE{29; z?ug?C913q_l$x3fwG0_DWPnuY!Gi~AmU2X+x3?Gle?JTWsTzF61xQ}tD+w{fyi89m z0GOUL;xKK#W|$*sdlB>a{GWFt6%002ovPDHLk FV1lPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D4XsH;K~#8N?VJrb zRQVpqX)9fo>gi>P-BjArQl5yBu}Rrx7&SIDLdJTTQ8ShsQd>KAw=SuuH5=OA?q;dX z6RpwArfr4H2p7psn=M7yr`ok;OX=C}kMqwnUS^zmYwJ3nr$^`a`=9zbbN=7o%Q;H- z#fuj@1aCg=?d=mMPDF-wcm*La?%%&ZWy%y}XpL7BrLnQm)YKFiTBD?-giIzQ12-ek z?*wl$;@sRxlP2Y4W+GcVfbylq#k#t>(xM{d(gMwQ?o6FJwYjko+1de=|7xPloH?_t zr3KmAp}D!)(b2K?$`xee2P!{-R_W^MLPy%+oJcfb?ATZeW%Bs(Sx1f_uNJs<>z3i9 zNwftECL0+1x2_I(HO&fJ+ck?8kryu1>gN_fr`ye%MR9OIwsznI1Q;3^u-C0awszPU z91KEUwmv->Wv3iH@GAuix?X>EihKqnVi`CnvP5Av!ubtme+m zVlo%cn9=(1p<{Bgw5CQI!#~y0k!5K~x3Ut|)$J-RJui`H_U>bFgM(YEsst=n#Hmxw zqelzQo<$2d7}hgC>}hnQY2a@TW3vw(I8YcK?qg;3Q%K15(o#B|4m%H>p*EtN98mu8 zz`$PR1LlT?#Zgh|e162njmV`5*Z~25wzVDd_s5hEr26`fdGdtGU})+ygipqw!8qva z3(5y`oSxpdfq{PO*8Tq5Z`cW%A}%`G&)OQ4564CZ1{=xbFn@n+NrQ-l!Y24=KUP;)V@r4#zTy`M1fxcc+P7~XvNZ?n zV|O>V+LDrD4rku9Y2bmae4I{qdi!mXo!!-|SFzL7;e39+kH0_EeD|L1C5zd#X%(@t zKjh|y1qEqDnektIajCHIRA}g!QKOJcM+dS%Zdh2QMDpeK?Z~Ab5lkjy;X+3sK6pogtIfUb#x+^FK=pS5P$zYvNZvG?2%mVzBOxlb7hjJXG~;d zXJ;p7YKpj+7>c>M)jRLNvB{)KAr1}+JRY`$hv6uG$d}ZWD-ZA9eR=EF%KUsAYwNaBI0w_xjvqaWT&j|jkkV>VX?O=O*9+ldg_4{$-!Gm>KS(MeQc|4v9Lm(*M$Inl8&X-4LSC>ml zir)0;g43r}dp{3#l18QGuvoGMxgXM-Hz|C+_}n?tk|oHcB+a*PJK5Wx=WGEDj zhwbj&lBy~-_gF97k3Vj$sex%9**$PioM_Y6&&F3>Uc1U)Qc~jM+k0WT0&k; z0R1+}#^z#XW)YX$t9)Rwv2oR=O?G3(kZf)D?AfDosT5>qQ$GAKo<`f@<|a@1z?{jG zOE+w&FDs+d>9A3d7a!f-K0f6G(4`k}xl=nk-CbRk4Fo_7Lw9%ISXjVV4vjiGPbFaA#BJYBr%-rgayFAW@Wy~v*^3rQ!ozpckSY`Sb1!AAc=%r@_}&Ko}Md=j8-gPj$bo_KH*ag=>OaG>rF?Da9X+)#EiT+ z=;-L6xwx>GEMelP=U$5zZE|*|Q>iMXn1roc-+t>YKRY{Q4+h=JYMz0?j?J5qtr8*r z{>dMG)UV<11@1`N+O@&!*Q@zN7Vf6_?Ab_}X9}`#mMtq(@|m1GV78}OSjbKm7?3NO zBoZVbWGm$FZ~GyKrKhK-9ynk$VFIK~e;XUwJ5+G}`jM)tf|?pCmC9nXAv-ABDnt9g z4h(cOHvW=ElXvfBDY<<+^2`}45{VZVXJTT4yz+s}!U+w%c<$Wk&`=odkQX1~Uw+|a zXYWZ$f-V5LD~SZW8xG*ju0olq!UABy6 zZVuTB*#qc)?RWX|`Ql=AUi*P$%x2G)#>5O1KhXN{;moaD%PT4@2Rsb!2QKk9G&DfE zDl03ikVpzIU9y6dV{L6mB0*WUv9TF5W(+z{Nub03djJ0HoE#TR%S}#BOXtp&x7FZ! z{#{v_UQ{%8;>6&P5GIp}XNZL?{&`GHfmod8?G4>2^5UTDufO=^sS(w#f^G&G}IC2R_@!5ATN`4wsdQ#bUT? z$R!6TfY+tcf=@n?eY`&;@S#ytQjF%$Kbn<=XJ^AlXET5PHw=d2v7(pq+qZp=9jmCT zQ}+1ku~|Vus?~g1_!3D%K|yYA z?x2^05x;Zix2dTYA|eJ3M?=zGpA!<+1_s9M*nwQ~3HJ0fdHOU?=3(`a#EZps&z@x{ z`L2ZG?7Y_06wf#YKxO{?;zgE4Nt-W%^eExjo8Vn?U_|{=u0kvPcaG|QErm?BX+}M~jV}`Yf3E9kS#*``Yk{N7V z$*o&gfBp4xQ`6PEcW<<`%zXDmjpPfJfX8b3bN!NK3o z4o@FGkb4~+hs(>4Nu?w8^`Q}f;w&2lCeNslkowx%G#{TK@5GQ`Q-GO;MQU1_tTLs= z#U86y2ie>6+}-i_#tPU|R(7nc43sI`nTvCC8NR-1)_hqqs;fDfnL?p((0>FbICYB4 zW`pvTonLxseDJ_NF)?xfet(7U=W{YL_V3&&=5Ulvn#+=sSW!`op&IyJ;EE0C!Eqeu`{m-~1+5Vf3>%2HpMYSPLWp0B5W@w*>kJ`& zZGpy#zMwS%g4X~-`~(EUl)wMK@gh(MU0q#tB!iajX}?(7i1G?T0RK->fZjmLh9JaG eKrk%P(fJ?EC0p zhxu%*ci`ORF`b9+=t^hy!c|<$x-YC$h+N{`#`Wk?(2@&^jaqd9=Ei9}B_}7?D>xr> zFkbTgbaB=1UwiLcR^Bh37i_hM|NMj*@9p;AD}FfXn%-Q?;+mQ{`(Diq*u!~rc0kNZ zg&O_oFVCI3bm`K!*VkYEwgZU*rKVaP`dIWc*=nwi{{Id8{+)b!djGzvssEP&{rS1}>ecmm_t*WH{UPAe(Pu4_^vu+!lx);>N&0v? z^_%xZUI+GPv$t-I&dzpsch5XDA;5`K)mP$^yhcpYL7;+HQE__zgO>ch-YtIr-kzUF zd!^gk+cQ_p04jT0zw|=q&*|O&POFFSkB^VvTle?D1BJ7xLZ@y7?BP8c-F>O~$BU;% z)upjtb*}7HPx2*cZp4r_A;^C8=`Y`*{d!0@Db8~n$Z!VPh_F&VxnS#&R zC+2|?R7o{_E=KkeX74qo$asAF3V4=<6>FVdQ I&MBb@00=PI6aWAK literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/hatch_10deg.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/hatch_10deg.png new file mode 100644 index 0000000000000000000000000000000000000000..bebd1c1772d3b4777b1bf2c9ebb4245d4bc4a520 GIT binary patch literal 832 zcmV-G1Hb%R8&+p z1c9uqSb;zQAprpivdjx_lICZ3=g$8#o4K?9B`=$_x0&Yb?ff@;JH~X?RaXh>X3cxJ z3{1VA+kOK;W!6o#O$eAzw)cUBS#?{s|LQ9YX501;+Z&!mnRQddadj{+ZJz+|2CGh7 z^4s<(6wDXf_ke|2b>f!S=u^qn1KZcY&#>xXx75K*)q=ia)xAaCavMxvcj_IFo>eFF z$}ih@Lcu)N$D6NMbrav*vIxwD?IS?XsH@a1TcKe3x+x6-n=1jlu3L4$0ZgRwoKY((c7uPFlN$nnm$hnhBcF} z)HOS)z%XamNnBGxcI{lV8yids*|p3wA7XpHN* zRAAV$>v^u}#RkKcUC;ZzY{JiCgJH|A=hZ{=|1;u#OfXE@^|BH$FJggV%dVH{e%k&P z>Y5U=Yee_a1V$|-WY>spPdDm88!$}Sb%^dV#5L=5@7lShY6_<0d)H^C!DUgY((hf% z*Bf0gF8$uM)G6Ycb-Q5XQH#u&_vxB87!T3QG&i6e%pOIK)b^5wWwe@(&1#Sfo_65D6lP7Ghy#6~xlQ z$|{W@XdyoET?je@dxgnevU|H5*qI&p$b;c73}0q{x4DTBAwq<35Wmb->{gg(P}HS( z5y6}WXs?%Jl7qwwC!&y327SrLu7$yvP&g5l9CXXJN{<@=*Lh2g+3b-5a8kuP?>QsVo(4)>?!xA+(HrXYNnJ+5%8S2g#zI1gVu$E@EP!MC3>>OEtCKcd&`P&6g~qU ze)dYg3gZ*tHAIfxe-40`+_^B;&%*dp9K4!7byXOj0k0%oGadl1GslT*DD2=RuBo`_ zF}`n7A=5Mi;C1HA$j52`yw02ho35es6D{uGJ<4mSu!Gl@^9i~J4TK%M|1k;rkv)g~ z4qkiU-tV2MYbgFiJ1BSc7P$jnTFirPOk6|t9y}~a3$(x;@Zt>DwB%QdHQ>c5uDJp& za|gV%oLDyEA?|>emUEfMH5`U4a=C`fki~`2yrGE86m3<$F6cUj!xU{($2FX$XcO0z zxC35V&WXr5EK0pNOCslZF*U$T%Q;tZ4W}vEB|Pd*9%la}RuZpvO(Ve&4&F-5)CD%9X1G>RY(_gN(tdf}TLN z024X&?2!T!)A`}5#v5?xDT3bV8fZ+|8&sI}U{bbpo-sjD90uJp>cNz>K?6F*1Vs^F zq|T@Z)3TvEDoMC~I%#>;Ny~r6a2=seLEBL{ru+VEhx}#I*n{8u01d`5ra}*`dPrQ; z*z*iJh)TZP0S`@i3F8)tfOi;1xe@_yimt^t#&8C_RnSh{PuE-lFAsXu)({c;S*)WC^;9*)C%0h7hJZov;26!u= zC1t6&03N2~4pd0em^6-1IM=ePEEWgA!!&8n9q;DzpSkqUU7oeM*~FeYt)ho7d;k~SudfHw*H zO5$0=VFvFAbm9Qd+mol;tz_F64l{VjGffA0-kuzpRd#^qElkb113Yhyf<8fGZU)cW zgL~{QK^ZrL_qQjjepd=6+zg(#XVyk)I4;pVj|0ne|eM(OF34tRb&7jaS};gAKI^$;~RQVv<*$&+R2falk< zK-XLpW2Bs-ZK?44|gbF4HsMoT+Ii;Ht_%HVi$h4C$h#%wyk^Y+Y9 pstVEp&#y=8pI%6oD_5@U)(`HWFG6rSY4QL7002ovPDHLkV1nz|Kbrsm literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/hatch_times.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/hatch_times.png new file mode 100644 index 0000000000000000000000000000000000000000..8e2c6a92cfba0dfaaf4874e64546a57cbc9a411e GIT binary patch literal 736 zcmV<60w4W}P)JN1_hJJ zC@LuUb&BE#`X0=I?vA&!yR!%L-aPoThy2}>$A4yjJG-M0u3WiFp}v``p;BY+L3w%1 zDLfuQ&l+ewEHQa`oUh=cHhT6zD^WN`_{L{R zp1gd?^9Xo6nUUVTPOh@67Hl(scZ&3{M)nDYK%>Q zw`Q7Mr~qF1&4t!#G{!c-!%6xet;X04c)g&nH0Bx#D|p+WT?cqUPeu;6Y#NENeFYDh zrsx1K=;@Qkb_aMt&j#qo0iN1}SEwGhf~WSJfoj|e-d|4_=u^%)>{syo9(-BoDrssc zKBBFa%^Kkjc&Zu#T_#Bl)pzhZK_8%D?trKAV5-jL&|(dEeh&_#Q_z?Lyr3s1(^KaF zFX%arlNt`2EHE`UQB%WZlLhWPnU2~R4!dZ_<*`0WW4P?1Es6-Qp>f(p+b%z6xC5Tb zvm-QLjOMnBb`+Q{rSt5=y$3Mz< zXk=(@7_x}>LS0NVP#-wsEqc1w_fG`v`P2B zp8Z<&>3P^D>(}PjuRZ(r$)>V$bIuFTq7CzN`X+CcKY8r(lh<3Hg#SEw;*MpUWNGpH z$>pWV|JV7Se64-*;}(Cv?BeRx({pV#pXa{IvGpl4`uQR4-I}Y_FK(vZ-pV&Ad}a-= zX*u69@!WSMdrv$O-nw&h+2TK)v1Li$CSA>(KLcoEnf1>f7C-AQvb|TyUta522IXdcgN+bwb1$|svIpDjJ}xBR*( z8Lwtp0fUj-Dfs#o)356$FIt)XYF3rFZ)|XWX`cP8UCZu0xua-O>bv*m&cl9wK!z+Z z3|JR}RbBVIc*PVb)xB)p%I#L$$aOqDa=KwM8(KbLh*2~7a2l=)}? literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/qgis_circle_hatch_default.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/qgis_circle_hatch_default.png new file mode 100644 index 0000000000000000000000000000000000000000..598ce6eafc1759c75f7ad170e43456728f23515b GIT binary patch literal 1016 zcmeAS@N?(olHy`uVBq!ia0vp^DIm+P)gjB|k!$L-BF z{`5c98&UXiSGd>2?1eML)T(dJvRC%$jB@S}S*jwwP9slj=YuTsMQh%;6)p@5%l~)2 zmHYZ^zP3C%RE>Yj4)&TeFwx zHal@$l$x6-(Ej8>l92A^?zhhm&JL4U@%+G%715iW*Evo9`+K$R&Pm}>Iz@GNTVH>b zm=aN%U37v$X46XRs5!fqUgN0NE!xL>=;wrHq0M<$`96AhT9xPR`o3l|`)u7sPOdp` zc3rhlnZIVCUGC@9efyRlT=to-BIfY1>6~}HWG+=Q^hHnMQI(EbcPMDt(R;F6G;J^O zZ`V5cee;s&Z`b#7cv(%GKPNUMarfTE-x?1|Ror4WpXZRz=vUF6_O4`}GL~~zl+k7{Uaehv0O?G`$wCD3R%F@vf?iT%c z^Jr>LS>&a)T5s>B-)t6leCpD_HU9?Z^k;|j*QaD##+_)&yIOjJdB+>q3o#ZpvCn-T z9#WFv4&^_xE;@MWyX^SSE_HUPPhU-ZG?zQp@c5eO&ymyI{U*si@wy%`f7@59;I2^f z6PfwaHd|tTe|_>MNp#Qp?<=!=b{*7PA$H*SqmX-PjE`>~mH2Yy_aY6my9sZCEiyP#0yT%wrk&K!mg%vcLCqWW~2Nl8w>B(ot{9gllc3VTWV~4$yR#e z1_t{i9yV3_})Fr<3bfw#1rGNZxyzjfbjy>s;=wH2Gv0rw-D8KlA v(S6tb-F4zaQ9#qmMQ!rQ6r-E})9V>|i$yFKPk4|E%+U;Hf@6u zihsf^bvb(Dv_Gr}r$Gu5;R~e{Cz{T3gI-;~zj-b^+?{jJ-R`~X%+3QpcK1BzJkRg@ z`~Un7#N+=lD$Ai|BAhLPzsuma3TU(WF@vB6>L$ar=b_^yyqSbmJ+S^oIBN4x!;;8@ zm;*1A!awb>!vLhyK6uC0XTgfdf|v?bCh;H;E|~E$x5r^dB!N6CA24%rnKskvhD~N# z?!1}VWAJ$-fk+$YQ$As205qLUk-KKVie+Mv1oANa>q`AkSnYwZk-P|N-F0tmQsjV) zgTGv<8wuPU59Iap@P@ml(0pA>i75I=*K6>ZkJJaL9~#^>(cu55ZkMUKi=?F0FiQ z()I&l^QyfLM%ASJMj()}R{f4SAX7cc1xU~yqc-ZjgqQTA3_ymE?IU{iKQo_fLTxtW z)Me4}gOO4UBnILDIU(DA5PYOwrAA*qqL#N$L!3wA%pL=YfedSG35qH{R9OHZc1PKh zEf1>A-VHqbL-;7m#5JXW8X3|$N+;`PX4)$>Q@;&6vt=e1AWgbu=28hH!=xZ}_LE&V zJr^K#R@T1-pX41#|NX3MFK!+sXCFMzx|Mm?$XxhT&zupJ78ppe=;tS)wIHTtTA2pA zOL5FQtWZE&C&N!Sbz{sKNT#SU8#;>MbVy5QBtR0{_tXsd`VVOId*3y+P$1Ssv)`{P zP6vT$gf^+fZKb}RJuIo6bApdQkeA`W zMEK4->{-3sy8sTQchX&wEjPXg&Cft*1zZ+$10kKpfpWO?6m)HXU17;@vCbDCH&ZQE z@z=FXbD4lNdyCc1T(veiTcs$H{`suXWB?VpzL(iu5FfK$Q}p=UKinG3I_Ayxy?h}Y z50hZ7WEwV!+j#=9w-A@ES~+B=?6gnn?(ELfeLY3yBg^G8GM%gA;YTy=LRZPP6Xe|X zEkvR6moD5HJBa0Bw!yX_MQ@R7xep@dw&qqw~T46|DeCEUOkl{ d9`T6wxCdfB1n7N0@2da+002ovPDHLkV1hk;1Y`gJ literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/ttf_lucida_sans.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/ttf_lucida_sans.png new file mode 100644 index 0000000000000000000000000000000000000000..265d12e0897a6ecf6df739840d8630455b6249fd GIT binary patch literal 1485 zcmV;;1v2`HP)82?$euC;3RIr^Zqm6k;j_YZ>w5exfHtYF51{V^iQKGFO@>c-4MlZ;9W=~F|C zT$UvkA=YB6SRZaiV!5`~!rZJ_E)9a)@7HdloA6FS=^l&v^hF^CW@De|>l+ zf%VIP$9N34PY+IHHd>^p9AGkvfc)1YxKu!)x=nyu~)A$}9!`3?B zh0kcHHQtKg#Wj^f#rU%*^XWi48M|u=@YcKhK9KQVNQ^tlkH5IKwAi?>ITH9-&^eFz z_qdNLD}YDHnQx2fM4bzn*%F}tHegi)@L(AK|0P<-6I_!(PRi*@Ic(1yLnw(8+}%Cn zfwrp|l@An?MO_X#ETKBQc+~)wFTh53> zVWJb8?J;p8JBjeN`p@U{PYRN4-q!^>;znS$F?yaJX77pU#{h4{1gonkJ&S?+y?*5` zM$|q+ES>N6G+Ya;^9mVT?=1Qm@UUqK*?(xsKi5o?9H07gg zBC*+HqZJ{>+=$hb%bCSHJlswWU=?>pf9ee2O$#w@Y&Q{dWlma-VzlClcPuYR=zT8p zLlv)*W`Y^LOqKK!V4=4`#OJBJmy;G%wl>^O1UB;aV)K*CMN}%H)9H?clJ$&Jflb~9 zp+lVI{qo4gB8j!lDo{ui+{|w(lsJW5CarY|Ia10~*<)+HGl8#EPDNTxqRpMmWaJks zrqk$6;otEgn|XgPckSV%>L+!bQ-Rkk>5pa=9+e+&-wmwri^<{*yglb2Kdn_LJ_WcU z$y$)7&}cW6_BBUZ$xynLp(*1RGb(-UYM%p+-W8llmhNfhsCI9Qc*~s99rZZ-6^;C2 z692bD5G<2$bzVw){_67{ z#p*>^cfDE+FKElNQ%qT}GKInC^{DG>ndF*no#irnp+}*k1#_DUDuNs`BdUUOl^>Sy zjJ<6|fLASB=vHros%=eqc>nas8kiKISI(M9sxLL;^@>{Ae!9?Cov;(?5O;qB%<|7> z`?-wKY6tRs_fn~`X{+g<)#&gcKPNcjO-p}0u)wwvEEIcl?hZp-d2y17755G3J?FtjkSYrIW^b1#pD$U8<0hW*{&F2R!t{%&I!$&l{W~f&V0tF1MSp4 zKQ!~QG;pTR1%P~`nQ~J`oOlR$)aq9jcXeK@<+lZZ`D{#dAL zyNtW_G9Bu*d1f%8JfTqU-m#RUz*nV8e(v;kl{257m07?X^wNR`6%zZ!N!pKZ;5h8^5vR&DI&Qs>p!pdGy + #FF0000 + 0.4 + + + #000000 + 1 + +---- + +====== Predefined symbols + +[cols="3"] +.Standard Symbold defined by SLD/SE specification +|=== +a| image:se_wkn/circle.png[] `circle` +a| image:se_wkn/triangle.png[] `triangle` +a| image:se_wkn/star.png[] `star` +a| image:se_wkn/square.png[] `square` +a| image:se_wkn/x.png[] `x` +| +|=== + +[cols="3"] +.Extended Symbols `shape://` +|=== +a| image:se_wkn/shape_backslash.png[] `shape://backslash` +a| image:se_wkn/shape_carrow.png[] `shape://carrow` +a| image:se_wkn/shape_ccarrow.png[] `shape://ccarrow` + +a| image:se_wkn/shape_coarrow.png[] `shape://coarrow` +a| image:se_wkn/shape_dot.png[] `shape://dot` +a| image:se_wkn/shape_horline.png[] `shape://horline` + +a| image:se_wkn/shape_oarrow.png[] `shape://oarrow` +a| image:se_wkn/shape_plus.png[] `shape://plus` +a| image:se_wkn/shape_slash.png[] `shape://slash` + +a| image:se_wkn/shape_times.png[] `shape://times` +a| image:se_wkn/shape_vertline.png[] `shape://vertline` +| +|=== + +[cols="30,30,40"] +.Extended Symbols `extshape://` +|=== +a| image:se_wkn/extshape_arrow.png[] `extshape://arrow` +a| image:se_wkn/extshape_emicircle.png[] `extshape://emicircle` +a| image:se_wkn/extshape_narrow.png[] `extshape://narrow` + +a| image:se_wkn/extshape_sarrow.png[] `extshape://sarrow` +a| image:se_wkn/extshape_triangle.png[] `extshape://triangle` +a| image:se_wkn/extshape_triangleemicircle.png[] `extshape://triangleemicircle` +|=== + +[cols="3"] +.Extended Symbols `qgis://` +|=== +a| image:se_wkn/qgis_arrow.png[] `qgis://arrow` +a| image:se_wkn/qgis_arrowhead.png[] `qgis://arrowhead` +a| image:se_wkn/qgis_circle.png[] `qgis://circle` + +a| image:se_wkn/qgis_cross.png[] `qgis://cross` +a| image:se_wkn/qgis_cross2.png[] `qgis://cross2` +a| image:se_wkn/qgis_crossfill.png[] `qgis://crossfill` + +a| image:se_wkn/qgis_diagonalhalfsquare.png[] `qgis://diagonalhalfsquare` +a| image:se_wkn/qgis_diamond.png[] `qgis://diamond` +a| image:se_wkn/qgis_equilateral_triangle.png[] `qgis://equilateral_triangle` + +a| image:se_wkn/qgis_filled_arrowhead.png[] `qgis://filled_arrowhead` +a| image:se_wkn/qgis_halfsquare.png[] `qgis://halfsquare` +a| image:se_wkn/qgis_hexagon.png[] `qgis://hexagon` + +a| image:se_wkn/qgis_lefthalftriangle.png[] `qgis://lefthalftriangle` +a| image:se_wkn/qgis_line.png[] `qgis://line` +a| image:se_wkn/qgis_pentagon.png[] `qgis://pentagon` + +a| image:se_wkn/qgis_quartercircle.png[] `qgis://quartercircle` +a| image:se_wkn/qgis_quartersquare.png[] `qgis://quartersquare` +a| image:se_wkn/qgis_rectangle.png[] `qgis://rectangle` + +a| image:se_wkn/qgis_regular_star.png[] `qgis://regular_star` +a| image:se_wkn/qgis_righthalftriangle.png[] `qgis://righthalftriangle` +a| image:se_wkn/qgis_semicircle.png[] `qgis://semicircle` + +a| image:se_wkn/qgis_star.png[] `qgis://star` +a| image:se_wkn/qgis_thirdcircle.png[] `qgis://thirdcircle` +a| image:se_wkn/qgis_triangle.png[] `qgis://triangle` +|=== + +====== Custom arrow with extshape://arrow + +The symbol `extshape://arrow` can be adapted to your own needs with three optional parameters which are: + + * `t`: thickness of the arrow base, in a value range between 0 and 1 with a standard of 0.2 + * `hr`: height over width ratio, in a value range between 0 and 1000 with a standard of 2 + * `ab`: arrow head base ration, in a value range between 0 and 1 with a standard of 0.5 + +.Example of `extshape://arrow` which varies `ab` between `0.1` and `1.0` +image::se_wkn_example/extshape_arrow_ab_01_10.png[] +.Example of `extshape://arrow` which varies `hr` between `0.2` and `2.0` +image::se_wkn_example/extshape_arrow_hr_02_20.png[] +.Example of `extshape://arrow` which varies `t` between `0.1` and `1.0` +image::se_wkn_example/extshape_arrow_t_00_10.png[] + +.Example +[source,xml] +---- +extshape://arrow?t=0.2&hr=2&ab=0.5 +---- + +====== Use Symbol from character code ttf:// + +Also TrueType font files can be used as source for symbols. +For TrueType fonts installed at System or Java level the syntax is `ttf://Font Name#code`. +If the font is not installed but available it can be sepcified +absolute or relative as `ttf://font.ttf#code`. + +The character code has to be specified in hexadecimal notation prefixed with `0x`, `U+` or `\u`. + +.Example of `ttf://` symbols +[cols="10,30,10,50"] +|=== +a| image::se_wkn_example/ttf_lucida_sans.png[] +a| `ttf://Lucida Sans#0x21BB` + +`ttf://Lucida Sans#U+21BB` + +`ttf://Lucida Sans#\u21bb` +a| image::se_wkn_example/ttf_fontawesome_external.png[] +a| `ttf://../fontawesome-webfont.ttf#0xf13d` +|=== + +TIP: The character code for fonts installed at System level can be looked up +via the system Character Map application. + +====== Spacing around the symbol + +For each symbol except the symbols `circle`, +`triangle`, `star`, `square` and `x` can be defined with an explicit bound. +This is particularly useful if you want to display an area fill with a symbol. + +This explicit limit can be specified either as width and height or as the +lower left and upper right corner. + +The syntax is: `wellknownname[width,height]` or `wellknownname[mix,miny,maxx,maxy]` + +[cols="10,40,10,40"] +|=== +a| image:se_wkn_example/qgis_circle_hatch_default.png[] +a| Regular symbol `qgis://circle` +a| image:se_wkn_example/qgis_circle_hatch_bounded.png[] +a| Symbol with explicit bounds `qgis://circle[-1,-1,3,2]` +|=== + +TIP: The width and height must be entered in the coordinate system of the symbol. +Most symbols are defined around the zero point with a width of 1.0. +Accordingly it is recommended to start with the values `[1,1]` or `[-0.5,-0.5,0.5,0.5]`. + +===== Simplified hatches + +To make hatching configuration easier, a new function `HatchingDistance` has been added, +which allows the user to define the size by specifying hatching angle and desired line spacing. + +The first parameter is the hatching angle, the second is the line spacing in the unit of the symboliser. + +.Example hatches +[cols="10a,15,25,10a,15,25",options="header"] +|=== +| | Rotation | WellKnownName | | Rotation | WellKnownName +| image:se_wkn_example/hatch_slash.png[] | 0 | `shape://slash` +| image:se_wkn_example/hatch_backslash.png[] | 0 | `shape://backslash` +| image:se_wkn_example/hatch_times.png[] | 0 | `shape://times` +| image:se_wkn_example/hatch_10deg.png[] | 10 | `shape://vertline` +|=== +.Symbolizer used in previous example +[source,xml] +---- + + + + + + + shape://slash + + #000000 + 1 + butt + + + + + 45 + 10 + + + 0 + + + + +---- +TIP: For of the shelf hates, which will create nice results, use the mark symbol `shape://slash`, `shape://backslash` +or `shape://times` for 45°, `shape://horline` for 0° and `shape://vertline` for 90° hatches. +For hatching with user-defined angles it is recommended to use `shape://vertline`. + +TIP: With user-defined distances or angles that are not divisible by 45, rounding inaccuracies may occur and become +visible in the results depending on the used styles. + +TIP: To get an even hatching we recommend to set the parameter `stroke-linecap` to `butt`. +This is especially recommended for transparent hatches + ===== Use of TTF files as Mark symbols You can use TrueType font files to use custom vector symbols in a From a32de828a5b41aa49c9d3b90908a3024a2f10f67 Mon Sep 17 00:00:00 2001 From: Stephan Reichhelm Date: Wed, 16 Nov 2022 12:59:15 +0100 Subject: [PATCH 6/8] Updated result for the changes in rendering --- .../r2d/RenderedStyleImageSimilarityTest.java | 3 ++- .../r2d/similaritytests/render_scene_fill.png | Bin 5993 -> 6094 bytes .../similaritytests/render_scene_fill_wkn.png | Bin 5410 -> 5686 bytes .../requests/lines/lines_graphicfill.png | Bin 5233 -> 8270 bytes 4 files changed, 2 insertions(+), 1 deletion(-) diff --git a/deegree-core/deegree-core-rendering-2d/src/test/java/org/deegree/rendering/r2d/RenderedStyleImageSimilarityTest.java b/deegree-core/deegree-core-rendering-2d/src/test/java/org/deegree/rendering/r2d/RenderedStyleImageSimilarityTest.java index 002aaf0cb6..3d35e5e528 100644 --- a/deegree-core/deegree-core-rendering-2d/src/test/java/org/deegree/rendering/r2d/RenderedStyleImageSimilarityTest.java +++ b/deegree-core/deegree-core-rendering-2d/src/test/java/org/deegree/rendering/r2d/RenderedStyleImageSimilarityTest.java @@ -74,6 +74,7 @@ import org.deegree.style.se.parser.SymbologyParser; import org.deegree.style.se.unevaluated.Style; import org.deegree.style.styling.Styling; +import org.deegree.style.styling.mark.WellKnownNameManager; import org.deegree.workspace.Destroyable; import org.deegree.workspace.Workspace; import org.deegree.workspace.standard.DefaultWorkspace; @@ -112,7 +113,7 @@ public class RenderedStyleImageSimilarityTest extends AbstractSimilarityTest { @BeforeClass public static void runBefore() { - //new WellKnownNameManager().init( ws ); + new WellKnownNameManager().init( ws ); FunctionManager fm = new FunctionManager(); fm.init( ws ); destroyableResources.add( fm ); diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/render_scene_fill.png b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/render_scene_fill.png index a23184aba8977d03d205767bdca2ade271b3a23f..6c8b9b286d02fe634252b587ce082611bdc9004f 100644 GIT binary patch literal 6094 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 oU|ZGr%|l@PO~Sf6{oY_E?O!Srvb literal 5993 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 diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/render_scene_fill_wkn.png b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/render_scene_fill_wkn.png index 9cf056ad640d8f0cc3388ae841d2b45f10ea535a..4f3a3725d6ccc27bb107ba75e587c412041174d6 100644 GIT binary patch literal 5686 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 S8VBaVRNCsgYPqWBf&T*)0lq5$ literal 5410 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 diff --git a/deegree-tests/deegree-wms-similarity-tests/src/test/resources/requests/lines/lines_graphicfill.png b/deegree-tests/deegree-wms-similarity-tests/src/test/resources/requests/lines/lines_graphicfill.png index 9f62eff8e21676d96098918d7f2ed8b4e082e6dd..e0918990c329cfdc29040681b9a2b99078518dff 100644 GIT binary patch literal 8270 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 z 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 Date: Mon, 10 Oct 2022 17:24:22 +0200 Subject: [PATCH 7/8] add implementation of WellKnownName type `svgpath://` reusing existing batik dependency includes documentation and unit test --- .../point_wellknownname_svgpath.gml | 23 ++++++ .../point_wellknownname_svgpath.png | Bin 0 -> 506 bytes .../point_wellknownname_svgpath.xml | 12 +++ .../style/styling/wkn/SvgPathLoader.java | 78 ++++++++++++++++++ ...ree.style.styling.mark.WellKnownNameLoader | 2 +- .../images/se_wkn_example/svgpath_example.png | Bin 0 -> 679 bytes .../src/main/asciidoc/renderstyles.adoc | 12 +++ 7 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_svgpath.gml create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_svgpath.png create mode 100644 deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_svgpath.xml create mode 100644 deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/SvgPathLoader.java create mode 100644 deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/svgpath_example.png diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_svgpath.gml b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_svgpath.gml new file mode 100644 index 0000000000..2df16aae77 --- /dev/null +++ b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_svgpath.gml @@ -0,0 +1,23 @@ + + + + 0.0 0.0 + 100.0 100.0 + + + + + 1 + dummy + + + 50.000000 50.000000 + + + + + diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_svgpath.png b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_svgpath.png new file mode 100644 index 0000000000000000000000000000000000000000..0570d4923735c24104a6eec802151802c26ee2b6 GIT binary patch literal 506 zcmeAS@N?(olHy`uVBq!ia0vp^DIm z8@7eSY}|5md8f&A?-`Gy)iZ7?zI%CRw(*3uH~y7_=BKS+cXr;#^;rhL&o5ZLY_8XmywA@!bk(i3TXuGJ-Rz{5 zt0PLP_MG~jF=1EN(PdAQHZW7#wZ3y|e*RAx8#f)3q{hm`H8&S8x8_e< zcT=`L`r+;EFO_`dzHHmX6>od<_t#D5IJE6<-sALBxK@Mi#lCHUiH=K7ey-oJZ+}^g z!JIEwCY|yZ(7m+vanr*k%cq6ZHDyd(Co9gQZo75KCt;WFlD9h&EMBfuojPA3YDxBS z*2A9ux-0*%++HCs&hz`%l}Xp;KWHU8M8T1e|M^pG*~)PL3BWjI@O1TaS?83{1OWKa B+LZtR literal 0 HcmV?d00001 diff --git a/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_svgpath.xml b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_svgpath.xml new file mode 100644 index 0000000000..a6c984d16a --- /dev/null +++ b/deegree-core/deegree-core-rendering-2d/src/test/resources/org/deegree/rendering/r2d/similaritytests/point_wellknownname_svgpath.xml @@ -0,0 +1,12 @@ + + + + + svgpath://m 8,14 0,-6 h -4.5 c 0,0 0,-7.5 6.6,-7.5 6,0 6.5,7.5 6.6,7.5 l -4.5,0 0,6 z m -4,0 v -2 h 2 v 2 z#FF00000.4#000000140 + 00 + + diff --git a/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/SvgPathLoader.java b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/SvgPathLoader.java new file mode 100644 index 0000000000..01703134ad --- /dev/null +++ b/deegree-core/deegree-core-style/src/main/java/org/deegree/style/styling/wkn/SvgPathLoader.java @@ -0,0 +1,78 @@ +/*---------------------------------------------------------------------------- + This file is part of deegree, http://deegree.org/ + Copyright (C) 2022 by: + - grit graphische Informationstechnik Beratungsgesellschaft mbH - + + This library is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at your option) + any later version. + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Contact information: + + grit graphische Informationstechnik Beratungsgesellschaft mbH + Landwehrstr. 143, 59368 Werne + Germany + http://www.grit.de/ + + lat/lon GmbH + Aennchenstr. 19, 53177 Bonn + Germany + http://lat-lon.de/ + + Department of Geography, University of Bonn + Prof. Dr. Klaus Greve + Postfach 1147, 53001 Bonn + Germany + http://www.geographie.uni-bonn.de/deegree/ + + e-mail: info@deegree.org + ----------------------------------------------------------------------------*/ +package org.deegree.style.styling.wkn; + +import java.awt.Shape; +import java.net.URL; +import java.util.function.Function; + +import org.apache.batik.parser.AWTPathProducer; +import org.apache.batik.parser.ParseException; +import org.apache.batik.parser.PathParser; +import org.deegree.style.styling.mark.WellKnownNameLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SvgPathLoader implements WellKnownNameLoader { + + private static final Logger LOG = LoggerFactory.getLogger( SvgPathLoader.class ); + + public static final String PREFIX = "svgpath://"; + + @Override + public Shape parse( String wellKnownName, Function resolver ) { + if ( wellKnownName == null || !wellKnownName.startsWith( PREFIX ) ) + return null; + + String wkn = wellKnownName.substring( PREFIX.length() ); + + Shape s = null; + AWTPathProducer pathProducer = new AWTPathProducer(); + PathParser pp = new PathParser(); + pp.setPathHandler( pathProducer ); + try { + pp.parse( wkn ); + s = pathProducer.getShape(); + } catch ( ParseException ex ) { + LOG.warn( "Could not Parse SVGPath {}: {}", wkn, ex.getMessage() ); + LOG.trace( "Exception", ex ); + } + + return s; + } +} \ No newline at end of file diff --git a/deegree-core/deegree-core-style/src/main/resources/META-INF/services/org.deegree.style.styling.mark.WellKnownNameLoader b/deegree-core/deegree-core-style/src/main/resources/META-INF/services/org.deegree.style.styling.mark.WellKnownNameLoader index edb1f28d7d..b0e8ce0f00 100644 --- a/deegree-core/deegree-core-style/src/main/resources/META-INF/services/org.deegree.style.styling.mark.WellKnownNameLoader +++ b/deegree-core/deegree-core-style/src/main/resources/META-INF/services/org.deegree.style.styling.mark.WellKnownNameLoader @@ -2,6 +2,6 @@ org.deegree.style.styling.wkn.ShapeLoader org.deegree.style.styling.wkn.ExtShapeLoader org.deegree.style.styling.wkn.TrueTypeFontLoader org.deegree.style.styling.wkn.QGisShapeLoader -#org.deegree.style.styling.wkn.SvgPathLoader +org.deegree.style.styling.wkn.SvgPathLoader #org.deegree.style.styling.wkn.WKTLoader #org.deegree.style.styling.wkn.WKTLinearizeLoader \ No newline at end of file diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/svgpath_example.png b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/images/se_wkn_example/svgpath_example.png new file mode 100644 index 0000000000000000000000000000000000000000..d9b6cd38bb09d094b2ecf8371e8b5f3476965253 GIT binary patch literal 679 zcmV;Y0$BZtP)(V|5}(V}Qk7C{mPE?Tsx7Oh-J3kjkJl1@RW7!gu1MNvVKVMLpX z9)wt}k{}9F7+hE_DiJ9yD`;*1gWi~h<6Q4!?zwS3_`{sLnDhP4`CbQ{{hwAT?Z`m; z0_dI(1NuFpZ{wcKTHpH@!hNleNmWwD7J%LI@~J)(NM3AS;4;PiB1` z&eX%LjqqYI49$a&lTejO0qmIz`3m?_C&xa>nL?-i%7CqfS2~Cv`p<*qyrHGqv|HgZ zd=f4OaegX2faX;K62(jHu`+Ims@d>;8$29@!%;yLN-=gtFoP!F;)19Z#IHuU90x$5 zOnwPwSbOe@8luKPw7`Y9Av`^WQwm?D9$TY=SS^UJ=arP@g79<~TD14jWSI_SnOV@c z4?4;X;VBC_!Su_QiZCFp%i#4NmBpk$jMl(2`En^J#0uTUPu0T4Bq5C6z;RP8X~W7G`BJO9*)=oV!~T<+UJ?}m$U1j(-sI%`{Ak%_@3`dC5=6T zCfh(p;gH6oZ>A;qYJQ8L*ER@Gn>3)x$DALK+|CGx!KkG=oK<*z@{{x>PX}^t1KhA3#7L1dVESD#kgfyJ zmIja|dfdt1x?&*t+i)}uAX_GKq-dUu^{VNl0i;P~n2G8&rHzMC5QoC<8RZM|-ywtm zvC15X192b@#DO>v2jW0t1}QbDr3WOy#ty`RI1mStvho{3&Yan7e*p>9Z}bR{KDqz^ N002ovPDHLkV1jr~INbmM literal 0 HcmV?d00001 diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/renderstyles.adoc b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/renderstyles.adoc index 4414e2e965..30a82773d0 100644 --- a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/renderstyles.adoc +++ b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/renderstyles.adoc @@ -771,6 +771,18 @@ image::se_wkn_example/extshape_arrow_t_00_10.png[] extshape://arrow?t=0.2&hr=2&ab=0.5 ---- +====== Custom Symbol from SVG path svg:// + +It is also possible to define a symbol from a SVG path data. +The syntax of SVG path data is described at https://www.w3.org/TR/SVG/paths.html#PathData + +.Example of custom symbol with \`svgpath://` +[cols="10,90"] +|=== +a|image::se_wkn_example/svgpath_example.png[] +a|`svgpath://m 8,14 0,-6 h -4.5 c 0,0 0,-7.5 6.6,-7.5 6,0 6.5,7.5 6.6,7.5 l -4.5,0 0,6 z m -4,0 v -2 h 2 v 2 z` +|=== + ====== Use Symbol from character code ttf:// Also TrueType font files can be used as source for symbols. From 2a1257a52a7cd47636bea96e68f5adea5774ebe1 Mon Sep 17 00:00:00 2001 From: Stephan Reichhelm Date: Wed, 23 Nov 2022 18:08:05 +0100 Subject: [PATCH 8/8] fix type --- .../src/main/asciidoc/renderstyles.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/renderstyles.adoc b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/renderstyles.adoc index 30a82773d0..fbeeb531e4 100644 --- a/deegree-services/deegree-webservices-handbook/src/main/asciidoc/renderstyles.adoc +++ b/deegree-services/deegree-webservices-handbook/src/main/asciidoc/renderstyles.adoc @@ -771,7 +771,7 @@ image::se_wkn_example/extshape_arrow_t_00_10.png[] extshape://arrow?t=0.2&hr=2&ab=0.5 ---- -====== Custom Symbol from SVG path svg:// +====== Custom Symbol from SVG path svgpath:// It is also possible to define a symbol from a SVG path data. The syntax of SVG path data is described at https://www.w3.org/TR/SVG/paths.html#PathData