0

Is it possible to use SVG with defined viewbox in GeoTools? I am trying to use SVG for styling layer features but if view box is defined it doesn't show up on the map.

Here is SVG that I am trying to use:

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.0//EN'
          'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'>
<svg fill-opacity="1" xmlns:xlink="http://www.w3.org/1999/xlink" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" width="16mm" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="0 0 160 160" height="16mm" xmlns="http://www.w3.org/2000/svg" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto">
    <!--Generated by the Batik Graphics2D SVG Generator-->
    <defs id="genericDefs"/>
    <g/>
    <g>
        <g>
            <circle fill="none" r="10" cx="80" cy="80"/>
            <circle fill="none" r="5" cx="80" cy="80"/>
            <circle fill="none" r="0.5" cx="80" cy="80"/>
            <line y2="60" fill="none" x1="80" x2="80" y1="70"/>
            <line y2="65" fill="none" x1="70" x2="90" y1="65"/>
            <line y2="60" fill="none" x1="70" x2="90" y1="60"/>
            <line y2="40" fill="none" x1="90" x2="80" y1="60"/>
            <line y2="60" fill="none" x1="80" x2="70" y1="40"/>
            <rect fill="none" x="78" width="4" height="8" y="50"/>
        </g>
    </g>
</svg>

I also tried to define all dimensions in mm but then I can't use width and height in mm, which is the need for positioning of the symbol. I am trying to symbolise point using this:

PointSymbolizer pointSymbolizer = sf.createPointSymbolizer(graphic, "the_geom");
Rule newRule = sb.createRule(pointSymbolizer);
newRule.setName(point);
File file = null;
file = new File(PointStyle.class.getResource("/trig.svg").getFile());
ExternalGraphic external = sb.createExternalGraphic( "file:///"+file, "image/svg+xml");
graphic.graphicalSymbols.clear();
graphic.graphicalSymbols.add(external);
FeatureTypeStyle featureTypeStyle = sb.createFeatureTypeStyle("Feature", newRule);
Style style = sb.createStyle();
style.featureTypeStyles().add(featureTypeStyle);
layer.setStyle(style);

I also tried to create style over SLD

public static Style createFromSLD(InputStream sld) {
    try {
        SLDParser stylereader = new SLDParser(sf, sld);
        Style style = stylereader.readXML()[0];
        return style;
    } catch (Exception e) {
    }
    return null;
};

SLD

        <Rule>
            <Name>THEME_ID</Name>
            <Title>THEME_ID</Title>
            <PointSymbolizer>
                <Graphic>
                    <ExternalGraphic>
                        <OnlineResource xlink:type="simple" xlink:href="file:///C:/sld/trig.svg"/>
                        <Format>image/svg+xml</Format>
                    </ExternalGraphic>
                </Graphic>
            </PointSymbolizer>
        </Rule>
5
  • Can you add the relevant code to the question
    – Ian Turton
    Commented Feb 26, 2017 at 19:25
  • added code that I was using to style a layer Commented Feb 26, 2017 at 19:49
  • It seems that this is connected to GEOT-3119 (osgeo-org.atlassian.net/browse/GEOT-3119), but there is no information how is that solved or where to look for this (in which class, I suppose that its SVGGraphicFactory). Maybe if somebody can give some starting tip where to look, I can make it working. Commented Feb 27, 2017 at 9:08
  • the patches are attached to the ticket, I've no idea if they were ever applied though
    – Ian Turton
    Commented Feb 27, 2017 at 9:14
  • didn't realise that patches contain a solution, this is the first time to use it. I have found a solution for this and will post it here, and open a ticket so it can be implemented. Thank you very much. Commented Feb 27, 2017 at 13:04

1 Answer 1

0

A solution is to edit class SVGGraphicsFactory.java and calculate values of width and height in pixels.

        private double parseDouble(String value) {
            try {
                return java.lang.Double.parseDouble(value);
            } catch (NumberFormatException arg2) {
+               if(value.endsWith("mm")){
+                   int trail = value.endsWith("mm") ? 2 : value.endsWith(" mm") ? 3 : 0;
+                   value = value.substring(0, value.length()-trail);
+                   java.lang.Integer ScreenResolution = java.awt.Toolkit.getDefaultToolkit().getScreenResolution();
+                   java.lang.Double valueDouble = java.lang.Double.parseDouble(value);
+                   java.lang.Double valueInpx = valueDouble*ScreenResolution/25.4;
+                   return valueInpx;
+               }else{
                    return java.lang.Double.parseDouble(value.replaceAll("\\D*$", ""));
+               }
            }
        } 

This is needed if somebody wants to get a desired "scale" between mm and size of symbol.

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.