1

Using OpenLayers 6, my app will not display anything for a Polygon (or line) where all the vertices have the same coordinates.

Being that the style being used has a non-zero line thickness, I would like these zero-sized features to still be displayed (eg, as a dot with a diameter the same as the line thickness). Is this possible?

Eg, Attempting to display a polygon based on the following GeoJSON with 3 identical coordinate pairs displays nothing:

{ "type": "Polygon", "coordinates": [ [ [ -122.035835228206764, 37.336042860605609 ], [ -122.035835228206764, 37.336042860605609 ], [ -122.035835228206764, 37.336042860605609 ] ] ] }

Whereas, this one, with the first and last pair identical and the middle coordinate different displays as a straight line:

{ "type": "Polygon", "coordinates": [ [ [ -122.035835228206764, 37.336042860605609, 0.0 ], [ -122.029211830581957, 37.330858755040133, 0.0 ], [ -122.035835228206764, 37.336042860605609, 0.0 ] ] ] }

In both cases, the area of the polygon is zero. If a zero-area polygon with only 1 dimension can be displayed, why can a zero size polygon or a zero-length line not be displayed?

Or is there some other way that I could get these objects to appear?

It seems inconsistent that a polygon with zero-width displays when a line with zero length does not.

10
  • 1
    It is a corner case to make rendering rules for invalid geometries. Can't you fix them?
    – user30184
    Commented Mar 23, 2022 at 7:35
  • @user30184 I agree. But is it actually an invalid geometry? For my particular use-case, a Polygon with all vertices at the same coordinates is legitimate. Does OpenLayers consider that to be an invalid geometry? I'm not sure where in the documentation to look for that. All I can find in the documenation for the Polygon class is "an array of vertices' coordinates where the first coordinate and the last are equivalent", which is true in this case (it also has 3 vertices, which could also be considered a requirement). Commented Mar 23, 2022 at 8:38
  • By definition polygon is a 2-dimensional geometric object. See for example the OGC Simple features standard portal.ogc.org/files/?artifact_id=25355. If you have PostGIS you can test your geometries with postgis.net/docs/ST_IsValidReason.html and see that it reports them to be invalid.
    – user30184
    Commented Mar 23, 2022 at 8:47
  • @user30184 - Again, I sort of agree, but OpenLayers is happy to render a 1 dimensional Polygon. And also, is a polgyon with a zero width and zero height, still has a width and a height, making it two dimensional. Just zero in both dimensions. In the end, it all comes down to semantics, and what OpenLayers considers to be legitimate. I find it surprising that it will render a polgyon with one dimesion zero, but not with both dimensions zero. Commented Mar 23, 2022 at 8:49
  • 1
    Nice definition but others do not generally agree with it. I would say that 1 dimensional object has a length and 2 dimensional object has an area. Repeated vertices are also considered as errors and they should be removed. However, nothing prevents software like OpenLayers to render geometries which are invalid to the SF specification (and GeoJSON by the same datatracker.ietf.org/doc/html/rfc7946) but it is not surprising if they are not prepared to do that.
    – user30184
    Commented Mar 23, 2022 at 9:48

2 Answers 2

1

One possible solution would be to have a style function where geometry of a feature is checked. If it's polygon with three points with equal coordinates, circle style is returned with point geometry which has this coordinates, otherwise some default style is returned.

Code could then look something like this (tested):

var defaultStyle = new ol.layer.Vector().getStyleFunction()();

function pointStyle(coord) {
  var style = new ol.style.Style({
    image: new ol.style.Circle({
      radius: 2,
      fill: new ol.style.Fill({
        color: 'orange',
      }),
    }),
    geometry: new ol.geom.Point(coord)
  });
  
  return(style);
}

function myStyle(feature, resolution) {
  if (feature.getGeometry().getType() != 'Polygon') {
    return(defaultStyle);
  }

  const coordinates = feature.getGeometry().getCoordinates()[0];        
  if (coordinates.length == 3) {
    var isEqual = true;
    for (var i = 1; i < 3; i++) {
      if ((coordinates[0][0] != coordinates[i][0]) || (coordinates[0][1] != coordinates[i][1])) {
        isEqual = false;
        break;
      }
    }
    if (isEqual) {
      return(pointStyle(coordinates[0]));
    }
  }
  
  return(defaultStyle);
}
1
  • That makes sense. Thanks. Commented Mar 24, 2022 at 19:38
0

As pointed out in various comments (by @user30184 and @TomazicM) a polygon should be considered to have at least 4 vertices, where the first and last vertices are identical. The fact that OpenLayers will render a 3 vertex polygon as a one-dimensional line if the middle vertex is different to the other two is probably an anomoly, as it will not render a 3 vertex polygon (as either a line or a point) if all 3 vertices are identical.

This is reasonable, but the documentation for OpenLayers is not clear on this (that I can find).

Work Around:

(Based on the example at: https://openlayers.org/en/latest/examples/polygon-styles.html )

Something like the following can be added to the layer's style in order to render all of a polygon's (or line's) vertices as points.

This will render all the vertices for all polygons in the layer, which is not what I want for greater-than-zero-sized polygons. However, if I use a separate layer for the zero-sized-polygons and only apply the style addition to the zero-sized-polygons layer (and not to the normal, greater-than-zero-sized polgyons layer), then it works out OK.

I consider it to be a bit of kludge, so if anybody has a better solution, I'd still be interested to hear it.

        new ol.style.Style({
            image: new ol.style.Circle({
                stroke: new ol.style.Stroke({color: '#111111', width: 2}),
                fill: new ol.style.Fill({color: '#000000'}),
                radius: 10
        }),
        geometry: function (feature) {
            var origGeom = feature.getGeometry();
            if ( origGeom.getType() == 'Polygon' ) {
                coordinates = origGeom.getCoordinates()[0];
            } else {
                coordinates = origGeom.getCoordinates();
            }
            return new ol.geom.MultiPoint(coordinates);
        },

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.