Dwins’s Weblog


GeoServer CSS – Conversion

Posted in Cool Stuff,Development,Open Source Software by dwins on July 25, 2010

When I first posted about GeoServer CSS, I was planning to follow up more frequently, but over the past couple of weekends I’ve been distracted by implementing some new features (integration with the Scala variant of GeoScriptstyled marks) as well as getting  away from the keyboard a bit.  This past week, however, I’ve been working on some speed improvements and I was thinking it would be nice to blog about those. Unfortunately, I haven’t explained what the conversion process is doing in the first place, so any discussion of performance would be a bit premature.  I suppose that means I should start at the beginning.

Last time I blogged about this, I said a bit about the parser that takes in a CSS file and breaks it up into objects that the Scala code inside GeoServer CSS can manipulate more easily.  The conversion process I’m talking about today disassembles and reassembles those rules into style components from the GeoTools API, and then you have a style that you can pass to GeoTools’s style serializer or straight to the renderer or whatever you like. Or, more graphically (ASCII art, woo):

 [CSS File] -- parser --> [CSS Objects] -- translator --> [SLD Objects]

The parser isn’t incredibly fast, but the real bottleneck is the translator.  Part of the point of the CSS converter in the first place is that CSS uses a very different model than SLD for combining rules: SLD uses the so-called Painter’s model, where each rule is applied in its entirety to any feature that matches its filter, and if multiple style rules apply to the same feature then they are drawn on top of each other.  CSS on the other hand, allows rules to override properties from other, less specific rules. The way I came up with to deal with this impedance mismatch was to inspect the rules, and produce one SLD rule for each possible combination of CSS rules.  For example, starting with this CSS source:

[a > 1] {
   fill: blue;
} 
[b < 2] {
   stroke: yellow;
}

We produce 3 SLD rules – one for the case where [a > 1 AND NOT b <2], one for [a > 1 AND B < 2], and one for [NOT A > 1 AND B < 2].  The fourth combination, with both rules negated, is a valid combination, but we throw it out since there are no styling attributes for that combination.  In general, there are (2^n – 1) potential SLD rules for a stylesheet containing n CSS rules.  That’s a lot; for only 10 input rules the output stylesheet could contain over 1000 rules.  I say “could” because there are some optimizations that can help to avoid enumerating all these possibilities… but as I said before, I’ll leave that for another post. After combining all these style rules, we still need to re-encode them as SLD.  Even this step is not straightforward as the CSS module unifies certain “contextual” filters with the SLD Filter concept, and also uses z-indexing instead of SLD’s “stack of featuretypes” model for controlling rendering order.

So, when a CSS rule combination is applicable to multiple featuretypes, or is applicable in multiple zoom ranges, or has symbolizers at multiple z-indexes, the equivalent SLD style will have multiple Rules corresponding to that single combination of CSS Rules.  So, we have to inspect the selectors to figure out the right set of SLD rules to produce.  In pseudocode:

featuretypes = extract_featuretypes(rule.selectors)
symbolizers_per_z_index = split_by_zindex(rule.symbolizers)
scale_ranges = extract_scale_ranges(rule.selectors)
for (ft in featuretypes)
    for (z, symbolizers in symbolizers_per_z_index)
        ftstyle = create_featuretypestyle(ft)
        for (range in scale_ranges)
             ftstyle += create_sld_rule(range, rule.selectors, symbolizers)
    output += ftstyle

Then, on top of that, we need to keep the total number of ftstyles produced as low as possible since each one requires an extra buffer at render time.  The code in Translator.css2sld does something similar, but shuffling all the rule combinations into one SLD style as it goes. So, clearly a lot going on here.  Sometime soon I’ll talk a bit about some of the things I’ve done to keep the conversion time under control (and for power users, how to make your styles friendly to the converter).

That is one semantic wiki!

Posted in Cool Stuff,Open Source Software by dwins on August 3, 2008

I talked a while back about this talk program I’ve been working on at TOPP (program as in scheduled events, not program as in software.)  So far I’ve been managing it using an OpenPlans project to organize things (one talk == one wiki page, plus a main page that lists all the talks ever given, grouped by whether they’ve been given yet or not (upcoming talks first, click the link above to see what I’m talking about).  So when someone wants to give a talk, there’s a pretty straightforward process:

  1. The speaker tells me (s)he wants to give a talk.
  2. I say “Great, put a page on the wiki so I don’t forget you told me that.”
  3. The speaker puts a page on the wiki.
  4. Later I talk to some other people who run things at TOPP and find a good time for a talk, so I go back and rearrange the main page on the wiki.
  5. A couple of days before the talk, I send an email to the office saying there’s going to be one.  (The actual timing varies as I am kind of forgetful, and sometimes I spend too much time trying to badger people into giving me a summary to include in the email.)

This left me thinking ‘man, I wish the wiki knew more about the data we’re keeping there so it could automate some of this stuff.’  So when I saw Semantic Mediawiki I was pretty excited, since basically all it is is a tool for making a wiki more aware of what’s in it.  Today I finally got around to installing it and went from a basic LAMP setup to talk management application (with HTML, RSS, and iCal versions of the upcoming talks schedule) in about 2 hours.  It’s pretty cool (by which I mean really awesome in potential, but relies a bit on having lots of people following some not amazingly well-advertised rules.  Semantic Forms looks like it will help, but I haven’t played with that yet.)  As long as all talks have their own page with a [[scheduled for::some date]] tag on it someplace, they get pulled in automagically to the various feeds.  I was even able to embed a nice autogenerated table of upcoming talks in the wiki main page with a search like

{{#ask: [[scheduled for::>now]] | ?speaker | ?audience | ?scheduled for}}

where the stuff in brackets is the query and everything that starts with a ? is some attribute I’d like to include in the table.  Pretty sweet right?  Aside from smart page listings in wiki pages, SMW allows browsing by the different attributes you add.  So in the table when it says ‘audience: Non-techies’ I can follow the link to a page about non-techies, which links to a listing of all pages that are tagged as having that audience in mind, which seems to me like it’s way better than hand-maintaining ‘interesting’ lists of pages.

Anyway, it looks like there’s a lot of potential here, but a little bit of polish should go into it before it’s ready to replace the current ‘David polices the wiki’ approach.