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>
  • Can you add the relevant code to the question – Ian Turton Feb 26 '17 at 19:25
  • added code that I was using to style a layer – Zoran Kokeza Feb 26 '17 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. – Zoran Kokeza Feb 27 '17 at 9:08
  • the patches are attached to the ticket, I've no idea if they were ever applied though – Ian Turton Feb 27 '17 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. – Zoran Kokeza Feb 27 '17 at 13:04
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, privacy policy and cookie policy

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