Skip to content

Instantly share code, notes, and snippets.

@iljya
Last active February 12, 2021 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iljya/e67a2a245c6968e685c11498a8361fe0 to your computer and use it in GitHub Desktop.
Save iljya/e67a2a245c6968e685c11498a8361fe0 to your computer and use it in GitHub Desktop.
Mapserver ANCHORPOINTS with SVG symbols, SVG output - What's going on?
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
MAP
NAME SVG_ICON_ANCHORPOINT_TEST
STATUS ON
SIZE 100 100
EXTENT 0 0 0.001 0.001
IMAGECOLOR 255 255 255
IMAGETYPE svg
CONFIG "MS_ERRORFILE" "stderr"
SYMBOL
NAME "square_0_0"
TYPE svg
IMAGE "./square.svg"
ANCHORPOINT 0 0
END
SYMBOL
NAME "square_05_05"
TYPE svg
IMAGE "./square.svg"
ANCHORPOINT 0.5 0.5
END
SYMBOL
NAME "square_1_1"
TYPE svg
IMAGE "./square.svg"
ANCHORPOINT 1 1
END
SYMBOL
NAME "DEBUG"
TYPE ellipse
FILLED true
POINTS
1 1
END
END
LAYER
TYPE POINT
STATUS ON
FEATURE
POINTS
0.0004 0.0005
END
TEXT "P"
END
CLASS
STYLE
SYMBOL "square_0_0"
END
STYLE
COLOR 255 0 0
SYMBOL "DEBUG"
END
END
END
LAYER
TYPE POINT
STATUS ON
FEATURE
POINTS
0.0005 0.0005
END
TEXT "P"
END
CLASS
STYLE
SYMBOL "square_05_05"
END
STYLE
COLOR 255 0 0
SYMBOL "DEBUG"
END
END
END
LAYER
TYPE POINT
STATUS ON
FEATURE
POINTS
0.0006 0.0005
END
TEXT "P"
END
CLASS
STYLE
SYMBOL "square_1_1"
END
STYLE
COLOR 255 0 0
SYMBOL "DEBUG"
END
END
END
END
@iljya
Copy link
Author

iljya commented Feb 10, 2021

SVG symbols, SVG output, and Anchorpoints

Note the strange output produced by the above map file. It has:

  • three layers, each containing a single inline feature
  • uses svg output
  • each layer has an svg symbol (square) with one of three anchorpoints
  • additionally a circle symbol is used to mark the feature center

Note how the anchor points are not where they should be (see map.svg above). You have to zoom in to see properly.
svg.map

I use this command to render the map:
shp2img -o map.svg -m svg.map

If I change the output type to png, I get the expected result, with the symbols anchored at the correct point:

map

It is possible that this is related to these issues, but I'm not sure:

MapServer/MapServer#5593
https://trac.osgeo.org/mapserver/ticket/4184

@iljya
Copy link
Author

iljya commented Feb 10, 2021

MapServer version 7.4.3 OUTPUT=PNG OUTPUT=JPEG OUTPUT=KML SUPPORTS=PROJ SUPPORTS=AGG SUPPORTS=FREETYPE SUPPORTS=CAIRO SUPPORTS=SVG_SYMBOLS SUPPORTS=RSVG SUPPORTS=ICONV SUPPORTS=FRIBIDI SUPPORTS=WMS_SERVER SUPPORTS=WMS_CLIENT SUPPORTS=WFS_SERVER SUPPORTS=WFS_CLIENT SUPPORTS=WCS_SERVER SUPPORTS=SOS_SERVER SUPPORTS=FASTCGI SUPPORTS=THREADS SUPPORTS=GEOS SUPPORTS=PBF INPUT=JPEG INPUT=POSTGIS INPUT=OGR INPUT=GDAL INPUT=SHAPEFILE

@iljya
Copy link
Author

iljya commented Feb 10, 2021

Also doesn't work with 7.6.2.

MapServer version 7.6.2 OUTPUT=PNG OUTPUT=JPEG SUPPORTS=PROJ SUPPORTS=AGG SUPPORTS=FREETYPE SUPPORTS=CAIRO SUPPORTS=SVG_SYMBOLS SUPPORTS=RSVG SUPPORTS=ICONV SUPPORTS=FRIBIDI SUPPORTS=WMS_SERVER SUPPORTS=WFS_SERVER SUPPORTS=WCS_SERVER SUPPORTS=FASTCGI SUPPORTS=GEOS SUPPORTS=POINT_Z_M INPUT=JPEG INPUT=POSTGIS INPUT=OGR INPUT=GDAL INPUT=SHAPEFILE

@iljya
Copy link
Author

iljya commented Feb 11, 2021

I found the issue! The SVG symbol (square.svg) does not have a width/height set. If the width/height is set, the symbol is correctly anchored at the set anchorpoints.

The reason the results are so strange seems to be related to the fractional maxx/maxy set in the viewbox: they are apparently being cast to ints! I verified this by adding a print statement in mapcairo.c::msPreloadSVGSymbol() [0]:

    rsvg_handle_get_dimensions_sub (cache->svgc, &dim, NULL);
    symbol->sizex = dim.width;
    symbol->sizey = dim.height;
    fprintf( stderr, "width: %d height: %d\n", dim.width, dim.height);

The dimensions returned by rsvg_handle_get_dimensions_sub(...) are always ints [1].

[0] https://github.com/MapServer/MapServer/blob/main/mapcairo.c#L1000
[1] https://github.com/ImageMagick/librsvg/blob/main/rsvg-base.c#L1458

@jmckenna
Copy link

Thanks for all of this research. Added to docs as a note (MapServer/MapServer-documentation#446)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment