Friday, March 4, 2011

Styling with GeoScript

Over the past few months one of the major developments in GeoScript has been an API for styling. I finally got around to implementing the api for GeoScript python and am happy with how things are progressing.

GeoScript, being based on GeoTools, naturally uses SLD as the underlying styling engine. Those who have used SLD know that it is a complicated beast. While it is a very powerful symbology language, it is also very complex and verbose. And for those not familiar with SLD and XML it represents a substantial learning curve. GeoScript hopes to make SLD a bit more approachable.

Let's start off with a simple example:

from geoscript.geom import *
from geoscript.style import *
from geoscript.render import draw

style = Stroke('black', 2) + Fill('gray', 0.75)
g = Point(0,0).buffer(0.2)

draw(g, style, (250,250))


Which results in:



The equivalent SLD for this style is:
<sld:UserStyle xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc">
<sld:FeatureTypeStyle>
<sld:Name>My Style</sld:Name>
<sld:Rule>
<sld:LineSymbolizer>
<sld:Stroke>
<sld:CssParameter name="stroke-width">2</sld:CssParameter>
</sld:Stroke>
</sld:LineSymbolizer>
<sld:PolygonSymbolizer>
<sld:Fill>
<sld:CssParameter name="fill-opacity">0.75</sld:CssParameter>
</sld:Fill>
</sld:PolygonSymbolizer>
</sld:Rule>
</sld:FeatureTypeStyle>
</sld:UserStyle>


Which is not all that bad as far as SLD goes. Let's look at a more complex example, one that anyone who as ever used GeoServer will be familiar with. The all too well known states layer that is styled with the popshade SLD. As far as SLD styles go popshade is actually relatively simple, but still involves hacking out about 100 lines of XML. What does the equivalent style look like with GeoScript?

style = Stroke()
style += Fill('#4DFF4D', 0.7).where('PERSONS < 2000000')
style += Fill('#FF4D4D', 0.7).where('PERSONS BETWEEN 2000000 AND 4000000')
style += Fill('#4D4DFF', 0.7).where('PERSONS > 4000000')
style += Label('STATE_ABBR').font('14 "Times New Roman"')


A bit more concise than the SLD equivalent. But for those who just can't go without their SLD remember that this is all geotools styling under the hood, so getting at the SLD is easy. So:

style.asSLD(sys.stdout)
style.asSLD('popshade.sld')


Dumps out the SLD that looks very similar to popshade.sld above.

Continuing on with another example of a style type that is frequently used: line casing. More specifically rendering two lines on top of each other with the "bottom" line styled a few pixels thicker than the "top" line to give the appearance of a border or casing. This technique is commonly used to style road data.



First the SLD:

<FeatureTypeStyle>
<Rule>
<LineSymbolizer>
<Stroke>
<CSSParameter name="stroke">#000000</CSSParameter>
<CSSParameter name="stroke-width">5</CSSParameter>
</Stroke>
</LineSymbolizer>
</Rule>
</FeatureTypeStyle>
<FeatureTypeStyle>
<Rule>
<LineSymbolizer>
<Stroke>
<CSSParameter name="stroke">#ffffff</CSSParameter>
<CSSParameter name="stroke-width">3</CSSParameter>
</Stroke>
</LineSymbolizer>
</Rule>
</FeatureTypeStyle>


Not bad, but in GeoScript it is a one liner:

style = Stroke('#000000', 6) + Stroke('#ffffff', 3).zindex(1)


Let's add some labels to those lines:

style += Label('name', '12pt Arial').linear(follow=True,group=True,repeat=25).halo(Fill('#ffffff'), 2)




Those are just a few examples. Check out the api docs for a complete list of what is available. More to come soon so stay tuned.

No comments:

Post a Comment

Post a Comment

Introducing GeoScript

GeoScript adds geo capabilities to dynamic scripting languages such as JavaScript, Python, Scala and Groovy.