Giter Site home page Giter Site logo

nieuwlandgeo / sldreader Goto Github PK

View Code? Open in Web Editor NEW
72.0 72.0 20.0 3.97 MB

SLD styling for online mapping libraries

Home Page: https://nieuwlandgeo.github.io/SLDReader

License: MIT License

JavaScript 100.00%
openlayers openlayers-plugins sld styled-layer-descriptor

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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sldreader's Issues

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.

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?

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.

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);

new kind of SLD

image

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

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.

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

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

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...

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

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>

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).

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

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)"

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.

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.

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).

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>

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.

"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).

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.

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?

GraphicStroke / Mark

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

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.

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

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?

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…

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.

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.

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

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>

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 / 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

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!

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.