Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

centerline function causes GEOS errors #7058

Open
geographika opened this issue Mar 28, 2024 · 8 comments
Open

centerline function causes GEOS errors #7058

geographika opened this issue Mar 28, 2024 · 8 comments
Milestone

Comments

@geographika
Copy link
Member

When using the centerline function for labels GEOS can return an error, which then stops all rendering. For example:

  LAYER
    NAME "lake-labels"
    STATUS OFF
    TYPE LINE
    CONNECTIONTYPE OGR
    CONNECTION "/vsicurl/https://github.com/MapServer/MapServer-demo/raw/main/data/lakespy2.shp"

    GEOMTRANSFORM (centerline([shape]))
    # GEOMTRANSFORM (centerline(densify([shape], 0.1)))
    CLASS
    LABEL
      COLOR 255 255 255
      TEXT (initcap("[LAKE_NAME]"))
      TYPE truetype
      SIZE 12
      PARTIALS false
      POSITION cc
      FORCE TRUE
      ANGLE FOLLOW
    END #label

    END

Without using densify when zoomed out MapServer returns the following:

<ServiceExceptionReport xmlns="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.3.0" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/wms/1.3.0/exceptions_1_3_0.xsd">
<ServiceException> msDrawMap(): Image handling error. Failed to draw layer named 'lake-labels'. msGeomTransformShape(): Expression parser error. Failed to process shape expression: centerline([shape]) yyparse(): Expression parser error. Executing centerline failed. msGEOSCenterline(): GEOS library error. Centerline generation failed, try densifying the shapes. </ServiceException>
</ServiceExceptionReport>

Probably best to log this as an error, but to proceed with rendering the rest of the image as best as possible?
Note - adding densify causes rendering to timeout when using a dataset with vsicurl.

@sdlime
Copy link
Member

sdlime commented Mar 29, 2024 via email

@geographika
Copy link
Member Author

@sdlime I found the features causing the issue. I see you already have a check for error-ing on features like this at

# should error, shapes are too simple and need to be densified

Below is a Mapfile to recreate the issue - just comment out PROCESSING "NATIVE_FILTER=FID NOT IN (127, 1112)" to see the error.

This is the Itasca lakes demo dataset. The issue with using densify is that it applies this to all features. When I applied the value 0.1 as shown in the example at https://mapserver.org/mapfile/geomtransform.html#centerline the request was still running after 10 minutes, and never finished. Without the 2 features causing an issue the centerlines and labels render fine.
The two features do render if a densify value of 5 is used and no other features display (again it takes too long if I try and use densify on the full dataset).

Possible options?

  1. Just ignore features that are too simple to support a centerline - either by catching an error and logging the index, or by checking the number of points in the shape?
  2. If a shape has too few points the automatically apply a densify to the shape, leaving the other features alone.

Without the above MapServer can happily return images until one of these features is in the extent and then errors start appearing.

MAP
    NAME "Lakes"
    EXTENT 393234 5208170 495403 5303964
    SIZE 800 600
    PROJECTION
        "init=epsg:26915"
    END
    IMAGETYPE "PNG"
    WEB
        METADATA
            "ows_enable_request" "*" 
            "ows_srs" "EPSG:4326 EPSG:3857" 
        END
    END
    LAYER
        NAME "lake-labels"
        STATUS ON
        TYPE LINE
        CONNECTIONTYPE OGR
        CONNECTION "/vsicurl/https://github.com/MapServer/MapServer-demo/raw/main/data/lakespy2.shp"
        GEOMTRANSFORM (centerline([shape]))
        PROCESSING "NATIVE_FILTER=FID NOT IN (127, 1112)"
        CLASS
            LABEL
                COLOR 0 0 0
                TEXT (initcap("[LAKE_NAME]"))
                TYPE TRUETYPE
                SIZE 12
                PARTIALS FALSE
                POSITION CC
                FORCE TRUE
                ANGLE FOLLOW
            END
        END
    END
END

The images below show the two features that cause the crash.

1 line - 5 points.
POLYGON ((440424.7375626485445537 5237938.6670050136744976, 440345.1583026284934022 5237850.5733449282124639, 440345.1715139870648272 5237850.6709027197211981, 440424.1131991900620051 5237940.3426641542464495, 440424.7375626485445537 5237938.6670050136744976))

image

1 line - 6 points.

POLYGON ((440788.6418735752231441 5238729.8965172320604324, 440789.6386071544839069 5238731.7499081995338202, 441057.2980431477772072 5238666.1359104206785560, 441058.7468873039470054 5238665.4803197206929326, 441057.2042083922424354 5238663.6359314732253551, 440788.6418735752231441 5238729.8965172320604324))

image

@sdlime
Copy link
Member

sdlime commented Mar 30, 2024

How do those features labels look after applying your auto densify patch? I'll try track down where the infinite loop exists. Seems to me that at least part of the fix is to avoid that regardless.

@jmckenna jmckenna added this to the 8.2.0 Release milestone Apr 1, 2024
@sdlime
Copy link
Member

sdlime commented Apr 17, 2024

Hmmm... I'm starting to think we might not want to do anything with this - yet. I'm trying understand where things break down to see if there is something automatic that can be done with these simple, elongated shapes. That said, I think maybe we should just live with the error and try and provide guidance on how to avoid it - so it's not a blocker for 8.2.

For example, in this particular case the layer definition is really inefficient in that we're not restricting labeling to features with non-null lake names. Given that the centerline function is computationally intensive, we should emphasize the need to isolate relevant features - and likely avoid the error as result. Yes, one could still run into issues so there is work to be done here.

@geographika
Copy link
Member Author

@sdlime - that sounds good to me - I just wanted to log the issue as I ran into it with the Itasca demo datasets. Agree it shouldn't be a blocker for 8.2, it has been an issue since the 8.0 release.

@sdlime
Copy link
Member

sdlime commented Apr 17, 2024

I don't think we're going to want to pursue the related pull request. My guess is that an alternative approach for simple, but weird features like these might be needed. I had a bunch of simple shape test cases (triangles, squares, etc...) on my old dev box that I need to retrieve.

Ideally I'd love to identify a way to isolate polygons that are candidates for curved labels and then use the horizontal labels for others - so basically two layers. Some sort of quick assessment of complexity or sinuosity. The ratio of polygon area to bounding box area might be one option.

I think it's fine to keep this ticket around though...

@sdlime
Copy link
Member

sdlime commented Apr 17, 2024

A simple square generates the error too:

MAP
  NAME 'square'
  EXTENT -50 -50 300 300
  SIZE 500 500

  SYMBOL NAME 'vertex' TYPE ELLIPSE POINTS 1 1 END FILLED TRUE END

  LAYER
    NAME 'square'
    TYPE POLYGON
    STATUS DEFAULT
    FEATURE
      POINTS
        100 100
        250 100
        250 250
        100 250
        100 100
      END
    END
    
    CLASS
      STYLE
        COLOR 181 181 181
        OUTLINECOLOR 51 51 51
      END
      STYLE
        # GEOMTRANSFORM (centerline(densify([shape],2)))
        GEOMTRANSFORM (centerline([shape]))
        COLOR 0 0 255
      END
    END
  END
END

Densifying fixes things. I think if one has a layer with a mix of simple and complex geometries is where things will get wonky.

I may be that simply getting to a minimal number of vertices is enough - I need to figure out where that limit is.

@sdlime
Copy link
Member

sdlime commented Apr 24, 2024

Looks like simple, convex shapes present the issue. A simple concave shape - e.g. start with a square and bump one side in - works great. There's probably a separate algorithm to consider under some conditions - convex + limited number of points.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants