Git Product home page Git Product logo

sldreader's Introduction

SLDReader

npm version

Live demos

A javascript package that aims to bring styling from a sld document to popular mapping tools. The project consists of two parts:

  • An SLDReader that parses an SLD document into a style object.
  • A function createOlStyleFunction that converts the parsed style object into a function that you can use in OpenLayers to style features.

The OpenLayers style converter tries to be as efficient as possible by recycling OpenLayers Style instances whenever possible.

CONTRIBUTIONS WELCOME!

More information about the standards:

Examples

See docs/examples folder, to serve them locally

npm start

Api docs

Api docs

Restrictions on supported SLD Features

The SLDReader library can read both SLD v1.0 and SLD v1.1 documents, but not every part of the SLD standard is (or can be) implemented by the SLDReader and OpenLayers style converter (yet).

Symbolizers

PointSymbolizer

Marks with well known symbol names are supported: circle, square, triangle, star, cross, x, hexagon, octagon. ExternalGraphic icons are supported.

Two custom marks are also supported: horline for a horizontal line through the center and backslash for a line from the top left to the bottom right. Use backslash instead of horline if you want to have diagonal hashing as a polygon graphic fill.

Wellknown names that reference a symbol library, like ttf://CustomFont#42 are not supported. The Size and Rotation elements may be dynamic by using the PropertyName element.

Only one Graphic per PointSymbolizer is supported. Each Graphic can only have one Mark or one ExternalGraphic.

LineSymbolizer

Only these svg-parameters are supported:

  • stroke
  • stroke-width
  • stroke-opacity
  • stroke-linejoin
  • stroke-linecap
  • stroke-dasharray
  • stroke-dashoffset

GraphicStroke with Mark or ExternalGraphic is mostly supported.

GraphicFill and PerpendicularOffset are not supported.

Note about GraphicStroke

ExternalGraphic is mostly supported with these caveats:

  • Always add a Size-element, even if using an ExternalGraphic instead of a Mark.
  • SLD V1.0.0 does not officially support the Gap property. For this, SLDReader implements the same workaround that Geoserver uses. You can use the stroke-dasharray parameter to add a gap between stroke marks. To do this, use a dash array with two parameters: the first parameter being the size of the graphic and the second being the gap size. See the " GraphicStroke: ExternalGraphic" example.

GraphicStroke vendor options

The following QGIS vendor options are supported on line symbolizers with a graphic stroke:

  • <VendorOption name="placement">firstPoint</VendorOption>
  • <VendorOption name="placement">lastPoint</VendorOption>

See the demo page for an example.

PolygonSymbolizer

Polygons with static fill and stroke style parameters are supported. See LineSymbolizer above for supported properties for the polygon outline.

For polygon graphic fills, both ExternalGraphic and Mark graphic fills are supported. The Marks supported here are the same as for a point symbolizer, with the additional restriction that feature-dependent value cannot be used.

The following WellKnownNames used by QGIS simple fills can be used as well:

  • x
  • cross
  • line
  • horline
  • slash
  • backslash
  • brush://dense1 (till dense7)

TextSymbolizer

Dynamic Labels (with PropertyName elements), Font and Halo are supported. No vendor-specific options are supported. LabelPlacement or PointPlacement are supported. Graphic elements to display behind the label text are not supported.

  • For PointPlacement, Displacement is supported1.
  • For PointPlacement, Rotation is supported1. PropertyName as rotation value is supported.
  • For PointPlacement, AnchorPoint is partially supported. Since OpenLayers does not support fractional anchor points, the label anchor is snapped to the alignment closest to left/right/top/bottom/center alignment. For instance: an AnchorPointX of 0.1 is snapped to 0, corresponding to left alignment in OpenLayers.
  • For LinePlacement, PerpendicularOffset is not supported.

[1]: according to the SLD-spec, label rotation takes place before displacement, but OpenLayers applies displacement before rotation. Beware when combining rotation and displacement inside a single text symbolizer.

Dynamic parameter values

According to the SLD spec, most values can be mixed type (a combination of plain text and Filter expressions). This means that most values can depend on feature properties.

SLDReader supports dynamic values in these cases:

  • PointSymbolizer Size
  • PointSymbolizer Rotation
  • TextSymbolizer Label
  • SvgParameters used for styling:
    • stroke
    • stroke-opacity
    • stroke-width
    • fill
    • fill-opacity
    • font-family
    • font-style
    • font-weight
    • font-size

Note: dynamic parameter values currently have no effect on Marks used inside GraphicStroke or GraphicFill and will use SLD defaults instead.

Arithmetic operators

Operators Add, Sub, Mul, and Div are implemented by converting them to function expressions.

Units of measure

Only pixels are supported as unit of measure.

Geometry element

The use of a Geometry element to point to a different geometry property on a feature to use for styling is not supported.

Filter comparisons

The SLDReader library supports the following operators inside Filter elements:

  • PropertyIsEqualTo
  • PropertyIsNotEqualTo
  • PropertyIsLessThan
  • PropertyIsLessThanOrEqualTo
  • PropertyIsGreaterThan
  • PropertyIsGreaterThanOrEqualTo
  • PropertyIsNull
  • PropertyIsLike
  • PropertyIsBetween
  • And
  • Or
  • Not
  • FeatureId

Function support

SLDReader can parse <Function> elements, but the support for functions is vendor specific. Geoserver supports different functions than QGIS does. Since it's not feasible to support all possible vendor specific functions, SLDReader only supports a handful of them, listed below.

Functions supported by SLDReader

  • geometryType(geometry) -> string

    • Returns OpenLayers geometry type for the input geometry: (Multi)Point, (Multi)LineString, (Multi)Polygon, LinearRing, Circle, or GeometryCollection.
  • dimension(geometry) -> integer

    • Returns the dimension of the input geometry. 0 for points, 1 for lines and 2 for polygons.
    • Returns 0 for a GeometryCollection.
    • For a multipart geometry, returns the dimension of the part geometries.
    • See the dynamic styling demo for an example of dimension-based styling.
<Filter>
  <PropertyIsEqualTo>
    <Function name="dimension">
      <PropertyName>geometry</PropertyName>
    </Function>
    <Literal>1</Literal>
  </PropertyIsEqualTo>
</Filter>
  • substr(string, start, [length]) -> string

    • Returns part of a string, starting from start index, starting with 1 (!!).
    • Runs until the end if length is not given.
    • A negative start index -N means start N characters from the end.
    • If length is negative, omit the last length characters from the end of the string.
    • See QGIS docs for more info.
  • strSubstring(string, begin, end) -> string

    • Returns a new string that is a substring of this string. The substring begins at the specified begin and extends to the character at index endIndex - 1 (indexes are zero-based).
  • strSubstringStart(string, begin) -> string

    • Returns a new string that is a substring of this string. The substring begins at the specified begin and extends to the last character of the string.
    • A negative begin index means: start at that many characters from the end of the string.
  • in(test, ...candidates) -> boolean

    • Returns true if test value is present in the list of candidates arguments, using string-based, case sensitive, comparison.
    • Example: in('fox', 'the', 'quick', 'brown', 'fox') --> true.
    • Example: in(2, '1', '2', '3') --> true.
  • in2..in10

    • These are aliases for the in function, coming from (older) GeoServer versions that required a different function for different parameter counts.

Implementing your own function

It's possible to add support for a specific function yourself, using SLDReader.registerFunction(functionName, implementation).

Example:

SLDReader.registerFunction('strSubstringStart', (text, startIndex) =>
  text.slice(startIndex)
);

After registering your function implementation, you can use it for example in a filter expression:

<Filter>
  <PropertyIsEqualTo>
    <Function name="strSubstringStart">
      <PropertyName>title</PropertyName>
      <Literal>2</Literal>
    </Function>
    <Literal>LLO WORLD</Literal>
  </PropertyIsEqualTo>
</Filter>

The registered function will be called with the value of its child expressions as parameters.

Important notes:

  • <Literal> expression parameters are always passed as string. If your function expects numeric parameters, convert accordingly.
  • The type of <PropertyName> expressions depends on the feature. Typically, when serializing from GeoJSON, integer values are actual integers.
  • SLDReader does not check if the functions are called with the correct number of parameters. Make your function robust against receiving fewer parameters than expected.
  • Geometry-valued expressions will always be OpenLayers Geometry instances.
  • Unless specifically set for your features, the geometry property name is 'geometry' for OpenLayers features by default.
  • Make your functions as lenient as possible regarding possible inputs. Do not throw errors, but try to return a value that makes sense in that case. If you return null from a function implementation, the function fallback value will be used if one is specified in the SLD.
    • <Function name="someFunction" fallbackValue="42">

Supported OpenLayers version

The SLDReader has a peer dependency on OpenLayers version 5.3.0. Because there are no backwards incompatible changes between v7+ and v5.3, it is possible to use this library in a project that uses a later (v8+) version of OpenLayers.

This may change in the future if the newest version of OpenLayers stops being backwards compatible with this library, or when a juicy new must-have feature is introduced. When that happens, SLDReader will be based on that OpenLayers version.

Old Browsers

Some older browsers need polyfills to use this library. E.g. es6.array.find. When using the OpenLayers style converter, OpenLayers' own browser restrictions have to be taken into account as well.

Contributing

Creating an issue

Please include an example sld and if possible an example feature as GeoJSON.

Development dependencies

  • node (v14.18+) & npm
  • git
  • docker (optional, for running the live examples yourself)

Pull requests

Before starting on a pull request, please raise a Github issue first to prevent starting work on something we're already planning/working on.

When making a pull request, please:

  • Address only a single issue or add a single item of functionality.
  • Create a test for your functionality.
  • Follow eslint rules and apply prettier.
  • Update or add an example.

Commands

To install dependencies, test, build and document

npm install
npm test
npm run build
npm run docs
docker-compose up (runs doc website on :4000)

sldreader's People

Contributors

ajkopinga avatar alexanderkochibk avatar allartk avatar allyoucanmap avatar breiler avatar calinarens avatar dependabot[bot] avatar mentaljam avatar razi91 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sldreader's Issues

UserStyle

Some of my Geoserver SLD files start with:

<sld:StyledLayerDescriptor 
  version="1.0.0" 
  xmlns:sld="http://www.opengis.net/sld" 
  xmlns:ogc="http://www.opengis.net/ogc"
  xmlns:xlink="http://www.w3.org/1999/xlink" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd">

and others with:

<sld:UserStyle xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml">

which causes an error:

Cannot read property 'push' of undefined

due to the fact that StyledLayerDescriptor is missing. Both my styles are valid SLD's for geoserver, but fail in your reader.

Filter not parsing ogc:Function

I have the following Filter:

          <ogc:Filter>
            <ogc:And>
              <ogc:PropertyIsEqualTo>
                <ogc:Function name="in4">
                  <ogc:Function name="geometryType">
                      <ogc:PropertyName>the_geom</ogc:PropertyName>
                  </ogc:Function>
                  <ogc:Literal>Polygon</ogc:Literal>
                  <ogc:Literal>MultiPolygon</ogc:Literal>
                  <ogc:Literal>POLYGON</ogc:Literal>
                  <ogc:Literal>MULTIPOLYGON</ogc:Literal>
                </ogc:Function>
                <ogc:Literal>true</ogc:Literal>
              </ogc:PropertyIsEqualTo>
              <ogc:PropertyIsEqualTo>
              	<ogc:PropertyName>property_type</ogc:PropertyName>
                <ogc:Literal>U</ogc:Literal>
              </ogc:PropertyIsEqualTo>
            </ogc:And>
          </ogc:Filter>

The problem here is that your Reader only works if there is a "ogc:PropertyName" and not when "ogc:Function" is used. So, in the example above only the second part of the filter is handled correct.

Line Symbolizer currently not supported for polygons (but output by QGIS)

Line Symbolizer is currently not supported for polygons, but is in the SLD1.1 standard and would be useful as it is output by QGIS (3.18) for Symbol Layer Types "Outline: Simple Line" and "Outline: Marker Line". This would be particularly useful as in QGIS, this is the only way for polygon borders to specify custom dash lines and cap style. I have a working fix which just involves modifying the OlStyler() function to copy the line styling to the polygon switch clause:

      case 'Polygon':
      case 'MultiPolygon':
        // --- Start of additon ---
        for (var j$2 = 0; j$2 < line.length; j$2 += 1) {
          appendStyle(styles, line[j$2], feature, getLineStyle);
        }
        // --- End of addition ---
        for (var i = 0; i < polygon.length; i += 1) {
          appendStyle(styles, polygon[i], feature, getPolygonStyle);
        }
        for (var j$4 = 0; j$4 < text.length; j$4 += 1) {
          styles.push(getTextStyle(text[j$4], feature));
        }
        break;

I attach 2 SLD files which can be used to test these 2 symbol layer types with polygons.
test_sld_files.zip

SLD 1.1 specification for Line Symbolizer, section "11.1.2 Geometry" includes:
"If a polygon is used (or other “area” type), then its closed outline is used as the line string (with no end caps)"

Support al remaining comparison

Support al remaining comparison en logical operators of sld filters.

Note, the style of later matching rules will overwrite previous defined style! Better is to match only one rule per feature in your sld

TTF in PointSymbolizer - Graphic - Mark - WellKnownName

The following work in my Geoserver instance, but not in your reader. Just shows a box

          <sld:PointSymbolizer>
            <sld:Geometry>
              <ogc:PropertyName>geom_point</ogc:PropertyName>
            </sld:Geometry>
            <sld:Graphic>
              <sld:Mark>
                <sld:WellKnownName>ttf://Font Awesome 6 Pro Solid#0xef072</sld:WellKnownName>
                <sld:Fill>
                  <sld:CssParameter name="fill">#73ca2c</sld:CssParameter>
                </sld:Fill>
                <sld:Stroke>
                  <sld:CssParameter name="stroke">#232323</sld:CssParameter>
                  <sld:CssParameter name="stroke-width">0.5</sld:CssParameter>
                </sld:Stroke>
              </sld:Mark>
              <sld:Size>20</sld:Size>
            </sld:Graphic>
          </sld:PointSymbolizer>

How to implement SLD Reader

I currently try to implement the SLD Reader into my own openlayers project. I checked the live examples as well as the API, but I am still not able to implement it.

I implemented the code into my project as follows:

html file:
<head> <script src="node_modules\@nieuwlandgeo\sldreader\docs\assets\sldreader.js"></script> </head>

javascript file:
`var linien = new ol.layer.Vector({
title: 'Linienmaßnahmen',
source: new ol.source.Vector({
url: 'data/Linienmassnahmen.geojson',
format: new ol.format.GeoJSON()
}),
style: new ol.style.Style ({
stroke: new ol.style.Stroke ({
color: [0, 0, 0, 1.0],
width: 3.5
})
})
});

function applySLD(vectorLayer, text) {
const sldObject = SLDReader.Reader(text);
window.sldObject = sldObject;
const sldLayer = SLDReader.getLayer(sldObject);
const style = SLDReader.getStyle(sldLayer, 'Maßnahmen_Linien');
const featureTypeStyle = style.featuretypestyles[0];

const viewProjection = map.getView().getProjection();
vectorLayer.setStyle(SLDReader.createOlStyleFunction(featureTypeStyle, {
convertResolution: viewResolution => {
const viewCenter = map.getView().getCenter();
return ol.proj.getPointResolution(viewProjection, viewResolution, viewCenter);
},
}));
}

applySLD(linien, 'massnahmen_linien.sld');`

"massnahmen_linien" is the name of my sld file (I also attached it as a textfile). But I'm not sure if I use the applySLD() command right. If I run the code I get the error TypeError: n.getAttribute is not a function.

massnahmen_linien.txt

GraphicStroke / Windows display scale settings

If a user's Windows display scale settings is not 100%, the graphics in graphicstroke are drawn at an offset (e.g. at 125% the marks are drawn on the right side of the line). I know I coded this myself, but do you have any idea on how to fix this?

I noticed that the pixelRatio_ property on the render object is correctly at 1.25 (when the scale setting in Windows is at 125%), but it seems not be used in:
render.drawPoint(new geom.Point([point[0], point[1]]));

If I change the code to:
render.drawPoint(new geom.Point([point[0]/1.25, point[1]/1.25]));
it works.

Any idea on a general solution?

image

SVG externalgraphic files loaded as Image()

sldreader attempts to load SVG in external files as Image( ) in function loadExternalGraphic() which amongst other things will trigger image.onerror (instead of image.onload) callback as such files are not raster images. Strangely when running under Webpack (5.8.0) webpack-dev-server (3.11.0), it does actually call image.onload and my SVG images are correctly rendered. I do not understand why this should be as the standard JavaScript behaviour is to give an error on loading if setting image.src to an SVG file.

The outcome in my code is that SVG files although actually loaded by the browser (as visible in the Inspector Network tab) are then ignored and the fallback symbology is used. I should add that the imageLoadedCallback() function is otherwise proving very useful for me to update Canvas elements (part of a legend) with PNG (& SVG) when they have finally loaded, instead of blocking rendering of the whole legend.

Tested with sldreader 0.2.8 in Chrome 88.0.4324.104 (Official Build) (64-bit) under Windows 10.

Custom shapes

There are many wellknownshapes that are not so 'well known', used in QGIS and GeoServer, like equilateral_triangle or half_square. WDYT: should them be hard-coded in this lib, or there should be made an endpoint to add them in your app code? It could be solved with a simple map.

Some shapes requires more ellastic style system (like half_square) in openLayers, I'm working on it.

repeat a point or label

i want my point or texts be repeated at a specific distance but i cant!
like question marks and circles at this picture..
Uploading 5.PNG…

Posibility of Featuretypestyle can be blank

var featuretypestyle = {

Need to add:
obj.featuretypestyles = obj.featuretypestyles || [];

As in:

	FeatureTypeStyle: function (element, obj) {
		obj.featuretypestyles = obj.featuretypestyles || [];
		var featuretypestyle = {
			rules: [],
		};
		readNode(element, featuretypestyle);
		obj.featuretypestyles.push(featuretypestyle);
	},

If not, then the following line might give an error:

obj.featuretypestyles.push(featuretypestyle);

As obj.featuretypestyles might be null

Implementing AnchorPoint for TextSymbolizer PointPlacement

Currently with TextSymbolizer in sldreader "For PointPlacement, AnchorPoint is not supported". Although the OpenLayers equivalent is limited to the much cruder TextBaseline and TextAlign properties, it would be very helpful (certainly in using SLD generated by QGIS) if some support for this could be added. The code below is one possible method (based on code I currently use to work around the issue), where olStyle is an input TextSymbolizer rule and ftsTextsymbolizer is the FeatureTypeStyle TextSymbolizer extracted from the SLD:

var olStyleText = olStyle.getText();
var anchor = ftsTextsymbolizer.labelplacement.pointplacement.anchorpoint;
var anchorX = anchor.anchorpointx;
var anchorY = anchor.anchorpointy;
if (anchorX < 0.25) {
    olStyleText.setTextAlign('left');
} else if (anchorX > 0.75) {
    olStyleText.setTextAlign('right');
} else {
    olStyleText.setTextAlign('center');
}
if (anchorY < 0.25) {
    olStyleText.setTextBaseline('bottom');
} else if (anchorY > 0.75) {
    olStyleText.setTextBaseline('top');
} else {
    olStyleText.setTextBaseline('middle');
}

Although this might seem a crude mapping, I believe that in most cases the text symbolizer anchor point (within the label) is likely to be either in the middle (0.5) or at one edge (0.0 or 1.0). With QGIS 3.18, this works well (in combination with displacementx / displacementy) for labelled point symbols that use "offset from point" label placement when position is set to right, bottom, or bottom right.

Unfortunately there seems to be a bug in QGIS that it (currently) will not write out negative displacement values for labels, so labels in other position (above/left) tend to get their displacement values discarded. However, if the QGIS-output SLD is modified to add the missing displacement values that were specified in QGIS label settings, then the above code combined with sldreader gives very good text placement for all label positions.

Issues with labels and some symbols

I am currently working on a project including SLDReader that helps us a lot for managing layer style in a very easy way.
We developed the project with 0.1.2 but we got issues while upgrading to the version 0.2.4.

  • For point layers with labels (based on properties), the label and the layers are not displayed returning the following error:
TypeError: text.split is not a function3 Executor.js:183:23
    createLabel Executor.js:183
    drawLabelWithPointPlacement_ Executor.js:477
    execute_ Executor.js:650
    execute Executor.js:887
    execute ExecutorGroup.js:315
    renderFrame VectorTileLayer.js:504
    render Layer.js:220
    renderFrame Composite.js:112
    renderFrame_ PluggableMap.js:1245
    animationDelay_ PluggableMap.js:185
    <anonyme> self-hosted:875

However, labels are displayed for polygons layer.

  • For some layers (not all) the layer properties are not used for the style (color for ex.). The layers are uniformly rendered. I didn’t get any error and it is difficult to understand the potential reasons or differences with other layers that are working. It was working smoothly with the version 0.1.2

  • In the 0.1.2 it was possible to insert space / line break in label for ex.:

  <ogc:PropertyName>name</ogc:PropertyName><![CDATA[
]]>(<ogc:PropertyName>pop</ogc:PropertyName><![CDATA[ ]]>inhab.)

It is not working anymore in the last version.

So we end up by rolling back to the 0.1.2.
Thanks.

Online Live SLD Editor

Nice component. It would now be nice to have a live online SLD Editor where you preview your changes on the map as you edit the style. I mean editing the sld in a user friendly way (not just the raw sld file). I tried something some time back using:

https://github.com/highsource/ogc-schemas

especially with:

https://github.com/highsource/ogc-schemas/blob/master/scripts/lib/SLD_1_0_0_GeoServer.js

To build a style editor with rules and all that can be used in geoserver (Or with your component).

Basically the script above will transform a raw SLD to Javascript Objects, which can in turn be used again to fill your interface with the values. The good thing here is that you can the give back the Javascript Objects and it will transform it back to a SLD string (So it works bi-directional).

External Graphic dosn't work for line symbolizer

Here is the style i want to use for a line feature:

   <LineSymbolizer>
        <Stroke>
          <CssParameter name="stroke">#000000</CssParameter>
          <CssParameter name="stroke-width">1.06</CssParameter>
        </Stroke>
      </LineSymbolizer>
      <PointSymbolizer>
        <Graphic>
          <ExternalGraphic>
            <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="data:image/png;base64,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"/>
            <Format>image/png</Format>
          </ExternalGraphic>
          <Size>5</Size>
        </Graphic>
      </PointSymbolizer>

only the stroke is displayed and external graphic is ignored.

Sizes not always Pixels

Although you handle your style sizes as Pixels, that may not always be the case, for example the following means that the font size is 2 meters, not 2 pixels:

          <sld:TextSymbolizer uom="http://www.opengeospatial.org/se/units/metre">
            <sld:Label>
              <ogc:PropertyName>unitno</ogc:PropertyName>
            </sld:Label>
            <sld:Font>
              <sld:CssParameter name="font-family">Arial</sld:CssParameter>
              <sld:CssParameter name="font-size">2</sld:CssParameter>
              <sld:CssParameter name="font-style">normal</sld:CssParameter>
              <sld:CssParameter name="font-weight">normal</sld:CssParameter>
            </sld:Font>
            <sld:LabelPlacement>
              <sld:PointPlacement>
                <sld:AnchorPoint>
                  <sld:AnchorPointX>
                    <ogc:Literal>0.5</ogc:Literal>
                  </sld:AnchorPointX>
                  <sld:AnchorPointY>
                    <ogc:Literal>0.5</ogc:Literal>
                  </sld:AnchorPointY>
                </sld:AnchorPoint>
              </sld:PointPlacement>
            </sld:LabelPlacement>
            <sld:Halo>
              <sld:Radius>
                <ogc:Literal>0.5</ogc:Literal>
              </sld:Radius>
              <sld:Fill>
                <sld:CssParameter name="fill">#FFFFFF</sld:CssParameter>
                <sld:CssParameter name="fill-opacity">0.8</sld:CssParameter>
              </sld:Fill>
            </sld:Halo>
            <sld:Fill>
              <sld:CssParameter name="fill">#000000</sld:CssParameter>
            </sld:Fill>
            <sld:VendorOption name="maxDisplacement">10</sld:VendorOption>
            <sld:VendorOption name="spaceAround">0</sld:VendorOption>
            <sld:VendorOption name="group">false</sld:VendorOption>
            <sld:VendorOption name="repeat">0</sld:VendorOption>
            <sld:VendorOption name="partials">true</sld:VendorOption>
            <sld:VendorOption name="goodnessOfFit">1</sld:VendorOption>
          </sld:TextSymbolizer>

Also the same with PolygonSymbolizer, LineSymbolizer, etc...

Compability with OL 6.7.0 on node

First thanks for your great library. I use it for applying QGIS SLD styles to WFS layers and everything works fine with latest OL 6.7.0.

Now I need to use it with ol package from node and as sldreader is limited to OL 5.3 I had to install it using npm i @nieuwlandgeo/sldreader --force

But than the line of code const sldObject = SLDReader.Reader(sldXml); produces this error (Firefox):
Uncaught (in promise) TypeError: _sldreaderDefault.default is undefined

Which looks like that in Chrome:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'Reader')

Is this because of incompatible OL versions or something else?

StrokeWidth passed as a string breaks OpenLayers 6.3.1

When SLDReader.Reader() extracts the object from the raw XML, number are all represented as strings. I have hit a problem where strokeWidth of "0.5" passed into OpenLayers 6.3.1 ol/Style/RegularShape.js causes the calculation in render() of size to fail as "+" is taken as string concatenation instead of floating point addition. Specifically the following line in RegularShape.prototype.render() where this.radius_ = 5.5 (not a string by this point) evaluates to NaN:

    var size = 2 * (this.radius_ + strokeWidth) + 1;

If I overwrite the strokeWidth value with a numeric version before calling the styler it works fine, i.e.:

featureTypeStyle.rules[0].pointsymbolizer.graphic.mark.stroke.styling.strokeWidth = 0.5;
vectorLayer.setStyle(SLDReader.createOlStyleFunction(featureTypeStyle

For more context, my QGIS SLD output has the following star symbology:

     <se:PointSymbolizer>
      <se:Graphic>
       <se:Mark>
        <se:WellKnownName>star</se:WellKnownName>
        <se:Fill>
         <se:SvgParameter name="fill">#2bc43d</se:SvgParameter>
        </se:Fill>
        <se:Stroke>
         <se:SvgParameter name="stroke">#232323</se:SvgParameter>
         <se:SvgParameter name="stroke-width">0.5</se:SvgParameter>
        </se:Stroke>
       </se:Mark>
       <se:Size>11</se:Size>
      </se:Graphic>
     </se:PointSymbolizer>

is converted to:

{
"name":"Single symbol",
"pointsymbolizer":{
   "graphic":{
      "mark":{
         "wellknownname":"star",
         "fill":{
            "styling":{"fill":"#2bc43d"}},
         "stroke":{
            "styling":{
               "stroke":"#232323",
               "strokeWidth":"0.5"}}},
   "size":"11"}}},
{

This is running in Windows 10 on Google Chrome Version 85.0.4183.83 using SLDReader 0.2.6 which has been processed by WebPack 4.44.0.

externalgraphic files not scaled for Device Pixel Ratio for polygon fills

externalgraphic files are not scaled to take account of Device Pixel Ratio when generating (polygon) fills. This results in patterns appearing very small on high DP ratio devices like iPhone X (dpr = 3.0). This seems to be fixable (I have tested this on both .png files and .svg files) by inserting:
imageRatio *= window.devicePixelRatio;
at line 2152 of sldreader.js (release 0.2.8):
https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio
However, if this gave unaccceptable support for older browsers (e.g. pre-IE11), then DEVICE_PIXEL_RATIO from import 'ol/has' could be used. (However, I don't really understand the "require" statements at the top of sldreader.js so wouldn't like to suggest how that could be added).

SLD 1.1.0 SvgParameter stroke-dasharray

I noticed that some styles, like dashed lines using stroke-dasharray, do work fine using CssParameter (SLD v1.0), but not using SvgParameter (SLD v1.1). Would it be possible to make this available:

<se:SvgParameter name="stroke-dasharray">4 2</se:SvgParameter>

Seems related to this issue.

Release v0.2.1.12 introduced some issues

Hi,

After updating from v0.2.6 to v0.2.15, I have noticed some unexpected behaviour. Which up until this moment I only can describe as unintentional behavior (error). See snippets and further comments below.

Looking at the two different images, one can see that on the v0.2.15 there are more points than there should be (compared to v0.2.6), the triangles are also different (look at the rotation). The points/circles are at different positions. v0.2.6 is showing how it should look like. I've gone through the different versions and these issues was introduced with the v0.2.12 release. Thanks :) !

v0.2.6 running

image

v0.2.15 running

image

OLStyler stroke of polygon is visible around tiles when greater than tile buffer (tiled maps)

When stroke width is greater than tile buffer (or tile buffer is small) the tile grid is visible.
Current SLDReader implementation creates a polygon style from a single OL Style source and the stroke is applied on top of fill.
SLD uses as test case.

<UserStyle>
 <FeatureTypeStyle>
  <Rule>
   <PolygonSymbolizer>
    <Fill>
     <CssParameter name="fill">#acdd7a</CssParameter>
    </Fill>
    <Stroke>
     <CssParameter name="stroke">#333</CssParameter>
     <CssParameter name="stroke-width">50</CssParameter>
    </Stroke>
   </PolygonSymbolizer>
  </Rule>
 </FeatureTypeStyle>
</UserStyle>

Image below shows what happen when stroke is greater than tile buffer.

actual_imp

A possible solution could be to split polyon style in an array that apply fill on top of stoke.
Here master...allyoucanmap:polygon-stroke the code implemented to get the result you can see in the below image

possible_soultion

There are still two issues in the proposed solution:

  • stroke-width needs to be multiply by 2 to be the right size when fill is rendered on top of it
  • if fill is missing the issue is still there as in the following image

without_fill

If this solution master...allyoucanmap:polygon-stroke could work I can provide a PR.

Request: Point Symbolizer changes to improve QGIS support

I include a code suggestion below to improve Point Symbolizer support in function getWellKnownSymbol() for QGIS (3.18). Changes are:

  • adding 'cross2' as an alias for 'x' (goodness knows why QGIS calls it that instead of SLD standard 'x'!)
  • adding 'diamond'
  • modifying octagon default angle so it is flat at top/bottom rather than pointed (both to match QGIS and to be generally a more useful default)
      case 'octagon':
        return new style.RegularShape({
          angle: Math.PI / 8,
          fill: fill,
          points: 8,
          radius: radius,
          stroke:
            stroke ||
            new style.Stroke({
              color: fillColor,
              width: radius / 2,
            }),
          rotation: rotationRadians,
        });

      case 'cross2':
      case 'x':
        return new style.RegularShape({
          angle: Math.PI / 4,
          fill: fill,
          points: 4,
          radius1: radius,
          radius2: 0,
          stroke:
            stroke ||
            new style.Stroke({
              color: fillColor,
              width: radius / 2,
            }),
          rotation: rotationRadians,
        });

      case 'diamond':
        return new style.RegularShape({
          angle: 0,
          fill: fill,
          points: 4,
          radius1: radius,
          stroke: stroke,
          rotation: rotationRadians,
        });

GraphicStroke / Mark

I would like to implement the GraphicStroke / Graphic / Mark on LineSymbolizer.
Are you already working on this?

"Gap" is ignored in marker line SLD exported from QGIS

For a "marker line" symbology from QGIS of 1.6mm orange circles spaced out 4mm apart along the path of a line, when this is rendered with SLDreader, there are no gaps between the circles. In the SLD written from QGIS the spacing appears to be encoded as se:Gap:

<?xml version="1.0" encoding="UTF-8"?> <StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" xmlns:se="http://www.opengis.net/se" version="1.1.0" xmlns:ogc="http://www.opengis.net/ogc"> <NamedLayer> <se:Name></se:Name> <UserStyle> <se:Name></se:Name> <se:FeatureTypeStyle> <se:Rule> <se:Name>Single symbol</se:Name> <se:LineSymbolizer> <se:VendorOption name="rotateMarker">0</se:VendorOption> <se:Stroke> <se:GraphicStroke> <se:Graphic> <se:Mark> <se:WellKnownName>circle</se:WellKnownName> <se:Fill> <se:SvgParameter name="fill">#ff8000</se:SvgParameter> </se:Fill> <se:Stroke> <se:SvgParameter name="stroke">#232323</se:SvgParameter> <se:SvgParameter name="stroke-width">0.5</se:SvgParameter> </se:Stroke> </se:Mark> <se:Size>6</se:Size> </se:Graphic> <se:Gap> <ogc:Literal>14</ogc:Literal> </se:Gap> </se:GraphicStroke> </se:Stroke> </se:LineSymbolizer> </se:Rule> </se:FeatureTypeStyle> </UserStyle> </NamedLayer> </StyledLayerDescriptor>

However, in the featureTypeStyle generated, this gap value does not get encoded anywhere:

{"rules":[ { "name":"Single symbol", "linesymbolizer":{ "vendoroption":{"rotatemarker":"0"}, "stroke":{ "graphicstroke":{ "graphic":{ "mark":{ "wellknownname":"circle", "fill":{ "styling":{"fill":"#ff8000"}}, "stroke":{ "styling":{ "stroke":"#232323", "strokeWidth":"0.5"} } }, "size":"6"}}}}}]};

Versions:

  • sldreader 0.2.7
  • OpenLayers 6.4.3
  • QGIS 3.10.5

As a side comment - on the whole SLDreader seems to do a remarkably good job of rendering in a very similar style using the SLD produced by QGIS "Package Layers", with most of the minor styling issues being due to shortcomings in the SLD that has been written by QGIS (a typical example of which is the loss of opacity information unless it is part of a colour definition). However, my biggest hurdle is how to adapt an SLDreader-output style function to give a line style of width in metres/map units (the information for this isn't written out by QGIS in the SLD so I would be doing this manually afterwards).

Addition of functionality

Hi,

I was in touch with Arjen through mail asking about a VendorOption. He told me to create a Github issue including a full exmple of a SLD.

My email:
I have a specific question about SLDReader capabilities, namely regarding a VendorOption.

<VendorOption name="placement">lastPoint</VendorOption>
<VendorOption name="placement">firstPoint</VendorOption>

This works fine in QGIS but in our web application, where we use SLDReader it is not looking fine, see two pictures below for example. I was wondering if it is possible to have SLDReader also support the VendorOption used above?

Arjen's answer:
I think it should be possible to add this functionality, but probably not soon.
Can you create an issue in Github including a full example of an SLD that uses this placement?

The requested information.

LinearAnnotation.

As it ought to be shown:
arrow

As it is shown:
faulty arrow

LinearDimension.

As it ought to be shown:
bi-directional arrow

As it is shown:
faulty bi-directional arrow

SLD Example

styles.txt

new kind of SLD

image

hi,
would you help me to have this kind of SLD?
color are watercolor and ways are not straight...

Faulty recursive function makes functionality break

Our findings

Trying the latest release 0.2.14 for the new vendor options implemented completely breaks. We are certain to have found the reason for this.

Looking at the function called renderStrokeMarks in sldreader.js, we can see that it is a recursive function that do not give itself all the parameters, specifically, the parameter called options is not given recursively (sldreaderjs:2178 and sldreader.js:2195). This renders "options" as undefined which causes an error further down in the code (sldreader.js:2224).

Picture with comments on found faulty code

image

Picture of where the error occurs

image

Picture of our fix (locally)

image

Cheers!

Sizes in string

Widths and sizes are parsed from XML as strings, then without casts, they are used in addictions. Those sizes should be parsed into float, before using in computing, like:

  const radius = 0.5 * size;

to

  const radius = 0.5 * parseFloat(size);

Same thing with styleParams.strokeWidth in simpleStyles.js#28

With that fix, it works fine. But any idea how it would work with issue #36?

rotating graphics

hi , thanks for your answer.
according to what you said , I've hosted my images but now this is my problem that I can't rotate the graphics base on my line's direction.
I would appreciate your help, thank you.

!https://user-images.githubusercontent.com/114813009/200122654-7f3f5178-2af7-4a8e-8996-28b0668a82f6.png

!https://user-images.githubusercontent.com/114813009/200122678-eb745aeb-a38a-4d95-af8d-aa97f2ce4eb7.png

my html:

<title>Parcel Sandbox</title>
<script src="src/ol.js"></script> <script src="src/sldreader.js"></script> <script> /** * @param {object} vector layer * @param {string} text the xml text * apply sld */ / globals ol /

var map = new ol.Map({

layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
target: "map",
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
document.getElementById('map').style.width = "800px";
document.getElementById('map').style.height = "800px";
map.updateSize();

const geojsonObject = {
'type': 'FeatureCollection',
'crs': {
'type': 'name',
'properties': {
'name': 'EPSG:3857',
},
},
'features': [

{
  'type': 'Feature',
  'geometry': {
    'type': 'LineString',
    'coordinates': [
      [
        469629.1017841224,
        704443.6526761827
      ],
      [
        6379128.632567662,
        900122.4450862347
      ],
      [
        4774562.534805244,
        4970241.3272152925
      ],
      [
        8022830.488812092,
        6222585.598639618
      ],
      [
        10605790.548624765,
        -4813698.293287254
      ],
      [
        11036283.891926877,
        -4109254.64061107
      ]
    ],
  },
}

],
};
var vectorSource = new ol.source.Vector({
features: new ol.format.GeoJSON().readFeatures(geojsonObject),
});

var vectorLayer = new ol.layer.Vector({
source: vectorSource

});
map.addLayer(vectorLayer);

const mySLDString = `<sld:StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc" version="1.0.0">
sld:NameForPreview</sld:Name>
sld:TitleForPreview</sld:Title>
sld:AbstractForPreview</sld:Abstract>
sld:NamedLayer
sld:NameForPreview</sld:Name>
sld:UserStyle
sld:NameForPreview</sld:Name>
sld:IsDefault1</sld:IsDefault>
sld:FeatureTypeStyle
sld:NameForPreview</sld:Name>
sld:Rule

	<LineSymbolizer>
        <Stroke>
          <GraphicStroke>
            <Graphic>
              <ExternalGraphic>
                <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" 

xlink:href = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHcAAAARCAYAAADnlDPNAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAACfSURBVGhD7ZixEYAgDEWDjVO4gZ0FDqJzuoha6QYu4Z1ebHABSEH+/ddAQ/HvHYEkqKpkM58qT8H5n6UPaVc3zvKWyR13m7Dr4EOus7xNWgkglAsM5QJDucBQLjCUC0zQ6cj/3l+3iEFnIF2bNpXjLG/QuNn0bqQ6WJaBoVxgKBeYstly3FVeg/fay2zZWd6ym+tDiR3O8rIsA0O5sIh81eQ3NYyZzKUAAAAASUVORK5CYII="/>
image/png

5



	 </sld:Rule>
	 		 
  </sld:FeatureTypeStyle>
</sld:UserStyle>

</sld:NamedLayer>
</sld:StyledLayerDescriptor>`;

function applySLD(vectorLayer, text) {
const sldObject = SLDReader.Reader(text);
const sldLayer = SLDReader.getLayer(sldObject);
const style = SLDReader.getStyle(sldLayer);
console.log(style);
const featureTypeStyle = style.featuretypestyles[0];

const viewProjection = map.getView().getProjection();
vectorLayer.setStyle(
SLDReader.createOlStyleFunction(featureTypeStyle, {
// Use the convertResolution option to calculate a more accurate resolution.
convertResolution: (viewResolution) => {
const viewCenter = map.getView().getCenter();
return ol.proj.getPointResolution(
viewProjection,
viewResolution,
viewCenter
);
},
// If you use point icons with an ExternalGraphic, you have to use imageLoadCallback to
// to update the vector layer when an image finishes loading.
// If you do not do this, the image will only become visible after the next pan/zoom of the layer.
imageLoadedCallback: () => {
vectorLayer.changed();
}
})
);
}
applySLD(vectorLayer, mySLDString);

</script>

Invalid cachedPointStyle

Suppose you have an sld with a Point- and LineSymbolizer. You then create a style for a linestring geometry. You will get back this:

{
  "geometry_": {
    "disposed": false,
    "pendingRemovals_": null,
    "dispatching_": null,
    "listeners_": null,
    "revision_": 1,
    "ol_uid": "362",
    "values_": null,
    "extent_": [
      null,
      null,
      null,
      null
    ],
    "extentRevision_": -1,
    "simplifiedGeometryMaxMinSquaredTolerance": 0.07597034037581123,
    "simplifiedGeometryRevision": 1,
    "layout": "XY",
    "stride": 2,
    "flatCoordinates": [
      500641.7758006881,
      5392759.1374269985
    ]
  },
  "fill_": null,
  "image_": {
    "opacity_": 1,
    "rotateWithView_": false,
    "rotation_": 0,
    "scale_": 1,
    "scaleArray_": [
      1,
      1
    ],
    "displacement_": [
      0,
      0
    ],
    "canvas_": {
      "1": {}
    },
    "hitDetectionCanvas_": {},
    "fill_": {
      "color_": "rgba(199, 21, 133, 0)"
    },
    "origin_": [
      0,
      0
    ],
    "points_": null,
    "radius_": 9,
    "angle_": 0,
    "stroke_": {
      "color_": "rgba(199, 21, 133, 0.5)",
      "lineDash_": null,
      "lineDashOffset_": null,
      "width_": 18
    },
    "size_": [
      36,
      36
    ],
    "renderOptions_": {
      "strokeStyle": "rgba(199, 21, 133, 0.5)",
      "strokeWidth": 18,
      "size": 36,
      "lineDash": null,
      "lineDashOffset": null,
      "lineJoin": "round",
      "miterLimit": 10
    }
  },
  "renderer_": null,
  "hitDetectionRenderer_": null,
  "stroke_": null,
  "text_": null
}

The "geometry" property is important in the json above.

Now if you create a new style for a point geometry the memoizeStyleFunction will give you back the same style created by the linestring geometry because it has the same symbolizer. But the "geometry" in the cached style will not have the coordinates of the point geometry. Instead it has the coordinates calculated by the "getLineMidpoint" function of the linestring.

As a result openlayers will not render the coordinates of the point geometry but rather the coordinates in the "geometry" property of the style.

add an external graphic

I wanna add an external graphic to my map but when I use my SLD, just shows a small square.
I would appreciate your help...
Uploading externalgraphic.png…
sld:Rule

      <PointSymbolizer>
            <Graphic>
              <ExternalGraphic>
                <OnlineResource
                xlink:type="simple"
                xlink:href="F:\r.mardani\office\IMIDRO_SLD\html\graphics\three.png"/>
                <Format>image/png</Format>
              </ExternalGraphic>
			  <!--size>15</size-->
            </Graphic>
      </PointSymbolizer>
      		  
      		  
    
	 </sld:Rule>

If several layers use same externalGraphic URL, imageLoadedCallback() only called for one

If several layers use the same externalGraphic URL, imageLoadedCallback() will only be called for the first layer encountered. Thus if a second layer is being styled with the same imageURL, that layer will never be updated to use the externalGraphic image. Specifically, in function processExternalGraphicSymbolizers(), for the second (or subsequent) layer, if (imageLoadingState === IMAGE_LOADING) the second layer's imageLoadedCallback() function will be discarded.

I am wondering if there is an easy fix using a layer's "invalidated" flag, but haven't followed through the logic of how that works. One option would be to store a "callbacks" object containing multiple imageLoadedCallback() functions for each imageURL to be called in succession by the "image.onload" function. If this "callbacks" object uses the layer id as a key then that would avoid the problem of generating unnecessary callbacks when processExternalGraphicSymbolizers() is being executed for multiple symbols on one layer.

If it would help I can put together some code to demonstrate the problem sometime in the next day or two?

Leaflet implementation

Although all your examples work on Openlayers, how would you go about setting a sld file to a Leaflet Layer?

Currently, I have:

vectorLayer = L.geoJson(geoJson, {
        style: function(feature) {
            return {
                   width: 3,
                   weight: 3,
                   opacity: 1,
                   color: 'red',
                   fillOpacity: 0.1,
                   fillColor: 'red'
            };
        },
        pointToLayer: function (feature, latlng) {
            return L.circleMarker(latlng, {
                  radius: 16,
                  width: 3,
                  weight: 3,
                  opacity: 1,
                  color: "red",
                  fillOpacity: 0,
                  fillColor: "transparent"
            });
        }
}).addTo(map);

PerpendicularOffset not working for LineSymbolizer

The perpendicularoffset property for a linesymbolizer seems to not be working. Please find attached SLD with a regular "single line" stylerule and also a "double line" stylerule.

PerpendicularOffset_SampleSLD.txt

The double line is created by setting a PerpendicularOffset to the second LineSymbolizer but this doesn't seem to be showing correctly on the screen

The sample SLD works perfectly in GeoServer's "layer preview". See the comparison of results:

PerpendicularOffset_StyleComparison

Thanks - love the library

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.