GeoServer Blog

Dynamic Symbolizers (Part 2)

In our previous post on dynamic symbolizers, we saw how we can generate dynamic external symbolizers based on feature attributes using only a simple style (SLD).

Today we’ll see two other features of dynamic symbolizers, namely:

  • using decorative TrueType fonts as markers in your map

  • Programing your own dynamic symbolizer to extend existing ones, with full access to the current feature attributes

Using decorative True Type fonts as markers

As you may already know, the internet is filled with these funny dingbat TrueType (TTF) files that do not contain a recognizable font, but instead include a set of symbols. If you are a Windows user, you should be familiar with the Wingdings font.

Some commercial GIS software use characters in these fonts as point markers, so it’s no surprise that you can find some TTF fonts with cartographic symbols embedded.

As standard, you can use font characters by leveraging the TextSymbolizer.  You can specify a font (say, Wingdings), and then a specific character (or characters) to serve as a point. This works, but has two flaws:

  1. Since the markers are labels, not points, they are subject to “conflict resolution.”  Multiple overlapping labels are discarded in favor of a single label.  This means that not all points will necessarily be displayed.

  2. You are restricted to choosing the just the fill color of the marker (like a normal character).

Dynamic symbolizers come to the rescue again.  With dynamic symbolizers, you can use a character in a font as a PointSymbolizer.  The syntax for this is specified as:

ttf://FontName#code

Say, for example, that you would like the snowflake symbol from the Wingdings font as a marker in your map. You fire up the Windows charmap utility (the GNOME Character Map program works as well) and learn that the snowflake code is 0x54. (Actually, the code, is in fact 0xF054 (prefix the code with F0).

So your snowflake mark may look like:

<span class="nt"><Mark></span>
  <span class="nt"><WellKnownName></span>ttf://Wingdings#0xF054<span class="nt"></WellKnownName></span>
  <span class="nt"><Fill></span>
    <span class="nt"><CssParameter</span> <span class="na">name=</span><span class="s">"fill"</span><span class="nt">></span>#000088<span class="nt"></CssParameter></span>
  <span class="nt"></Fill></span>
<span class="nt"></Mark></span>

Here is the sample layer sf:archsites drawn with the above mark, and the full SLD.  Notice that the points that overlap are all shown, which would not have happened using a standard TextSymbolizer.

sf:archsites themed with a blue snowflake marerk

<span class="cp"><?xml version="1.0" encoding="ISO-8859-1"?></span>
<span class="nt"><StyledLayerDescriptor</span> <span class="na">version=</span><span class="s">"1.0.0"</span> <span class="na">xmlns=</span><span class="s">"http://www.opengis.net/sld"</span> <span class="na">xmlns:ogc=</span><span class="s">"http://www.opengis.net/ogc"</span>
  <span class="na">xmlns:xlink=</span><span class="s">"http://www.w3.org/1999/xlink"</span> <span class="na">xmlns:xsi=</span><span class="s">"http://www.w3.org/2001/XMLSchema-instance"</span>
  <span class="na">xsi:schemaLocation=</span><span class="s">"http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd"</span><span class="nt">></span>
  <span class="nt"><NamedLayer></span>
    <span class="nt"><Name></span>Snow symbol<span class="nt"></Name></span>
    <span class="nt"><UserStyle></span>
      <span class="nt"><Title></span>Snow symbol<span class="nt"></Title></span>
      <span class="nt"><Abstract></span>Marks each point with a snow symbol<span class="nt"></Abstract></span>

      <span class="nt"><FeatureTypeStyle></span>
        <span class="nt"><Rule></span>
          <span class="nt"><Title></span>Red square<span class="nt"></Title></span>
          <span class="nt"><PointSymbolizer></span>
            <span class="nt"><Graphic></span>
              <span class="nt"><Mark></span>
                <span class="nt"><WellKnownName></span>ttf://Wingdings#0xF054<span class="nt"></WellKnownName></span>
                <span class="nt"><Fill></span>
                  <span class="nt"><CssParameter</span> <span class="na">name=</span><span class="s">"fill"</span><span class="nt">></span>#000088<span class="nt"></CssParameter></span>
                <span class="nt"></Fill></span>
              <span class="nt"></Mark></span>
              <span class="nt"><Size></span>12<span class="nt"></Size></span>
            <span class="nt"></Graphic></span>
          <span class="nt"></PointSymbolizer></span>
        <span class="nt"></Rule></span>

      <span class="nt"></FeatureTypeStyle></span>
    <span class="nt"></UserStyle></span>
  <span class="nt"></NamedLayer></span>
<span class="nt"></StyledLayerDescriptor></span>

Using a TTF character as a PointSymbolizer has another advantage:  you can specify both the fill (inside) color and stroke (outside) color separately.

As we’ve seen before, you also have the option to embed CQL expressions inside the well known name. For example, you could embed the symbol code into a feature attribute, and have each feature use a different marker as a result!

Not happy with the current symbolizer sets? Build your own!

If you’re not happy with the symbolizing capabilities you can now build your own and plug it into GeoServer as any other extensions.

For details of how this can be done have a look at the dynamic symbolizer proposal in GeoTools, and see the sample TTFMarkFactory as an example:

If you haven’t yet employed dynamic symbolizers in your maps, now you have some reasons to do so.  Enjoy!

Read More

GeoServer, Google Maps, and Geo Search: A Request For Data

Are you or your organization serving data publicly via GeoServer?  Would you like this data to be searchable via Google Maps?

At OpenGeo we are testing out new “geo search” functionality in GeoServer.  We believe this is the future of finding geospatial information on the web.  While still in development, this functionality will be available to all in GeoServer 1.7.2 when it is released.

We have a sample of a search in Google Maps that brings up data served by GeoServer.  (You can click on the blue markers to see information about the data set.)

We are very interested in working with organizations with public data to help test this.  We are willing to donate resources to help configure your servers so that your public-facing data can become even more accessible.  When we announce this functionality to the world, your geospatial information will be prominently featured.

If you are interested please email me: mike AT opengeo DOT org.

Read More

GeoServer 1.7.1 Released

The GeoServer team is happy to announce the release of GeoServer 1.7.1!

The biggest improvement in this release is better Google Earth support.   Using revamped KML output (known as the KML “reflector”) GeoServer can now output vector super-overlays.  Prior to this version, data served by GeoServer when viewed in Google Earth would only update when the the camera stopped.  With super-overlays, however, views are updated dynamically.  Data is also broken up into regions which are used to sort features into a hierarchy so that more prominent features are visible at higher zoom levels and less prominent features become visible at lower zoom levels. Super-overlays also work on raster datasets, providing lower resolutions versions of imagery (overviews) at higher zoom levels and higher resolutions at lower zoom levels.

All of this is is a huge step for GeoServer, as it is now the first major GIS server to return placemarks, lines, and polygons with the super-overlay mechanism.  This means that serving data through Google Earth is a more seamless experience; your data will look like it is naturally part of Google Earth.  And with super-overlays, you can serve large amounts of data with minimal performance issues.

In addition to super-overlays, GeoServer now has support for adding a height attribute to features (also known as “extrudes”), which allows Google Earth to render data in 3-D. Height information is specified via a template, similar to how one specifies time attributes to create animations.  We have a nice tutorial on how to use the height feature with super-overlays, to see this in action, but here’s a quick screenshot.

Although the default mode of output using the improved KML reflector is now the super-overlay mode, the previous default, refresh mode, is still available. Also available is a download mode which outputs a self-contained KML file, useful for situations where server access is not necessary or possible.

Special thanks go out to David Winslow for all the great work implementing all the new KML functionality.

This version has more than just improved Google Earth support.  GeoServer now has an official SQL Server extension (described previously). In addition, there is a new and improved Oracle extension which provides better performance and security from the previous version.

Further improving the visualization experience is GeoWebCache, a WMS tile-caching program.  Previously available as an extension (and still available as a standalone product), GeoWebCache is now built-in to GeoServer and can vastly accelerate map rendering.  We will be talking more about GeoWebCache in a future post.

Finally, this version includes a new drag and drop installer for Mac OS X users.

As always with any GeoServer release a heap of other improvements and bug fixes are included. A total of 98 issues were handled for this release.

We’re very excited about this release, and we encourage you to download, try it out, and let us know what you think. Comments and feedback are always welcome on the mailing list, as the community is always interested to hear how people are using GeoServer. Stay tuned for the 1.7.2 release, slated for release in the next month or so, which will include new breakthroughs in support for GeoSearch.

Read More

Dynamic Symbolizers (Part 1)

When GeoServer 1.7.0 was released in October of 2008, it included some new features that many people might find useful.  One of those new features is support for dynamic symbolizers.

Dynamic symbolizers, which originated from a GeoTools styling subsystem improvement from this past summer, allows you to do three things:

  • Create external references that contain feature attributes as variables__

  • Use decorative true type fonts as markers in your map

  • Program your own dynamic symbolizer to extend existing ones, with full access to all of the current feature attributes

In this post we’ll cover the first item, and in the next post we’ll consider the other two.

**Dynamic Symbolizers With External References **

Say you want to make a map of the USA that shows each state’s flag superimposed on the state.  (You can use the topp:states layer, which comes standard with GeoServer.)  With the old symbolizer approach, you would have to do two things:

  • Find all the flags as images, possibly as small PNG/GIF images.

  • Write a different rule for each state, connecting each state with its respective flag.

Now, having to find the flags is a challenge, but it can be done.   This site, for example, has small flag graphics in JPEG format. The really time-consuming part is writing 50 different rules, each matching a state with its flag.

If we look closely at the image names, we can see a pattern.  The file names are all of the form:

tn_.jpg

And we happen to have the same state abbreviations in the STATE_ABBR attribute. Wouldn’t it be great if we could just link the attribute to the external graphics link?

With dynamic symbolizers, this can be done. You can embed CQL (Common Query Language) expressions inside a external graphics link or inside a well-known mark name, and have the expression be expanded dynamically.  To embed a CQL expression, all you have to do is to type it between the brackets in this form:  ${ }.

Let’s apply this to our case. The external graphics link might originally look like:

> > > > image/gif > > >

Note the file name:  tn_${STATE_ABBR}.jpg.  For each feature, the attribute name will be expanded, generating a different link for every feature. Unfortunately, that’s still not good enough, because the abbreviations are upper case, and the site links are case-sensitive and require lower case names. However, as we mentioned above, you can leverage the full power of CQL expressions in the dynamic symbolizer elements.  In this case, we can use the strToLowerCase function to change the values of our attributes to lower case.  With that, we have an instant flag map.

Sample USA states maps with flags

Here is the full SLD to generate this at home.

<span class="cp"><?xml version="1.0" encoding="ISO-8859-1"?></span>
<span class="nt"><StyledLayerDescriptor</span> <span class="na">version=</span><span class="s">"1.0.0"</span>
  <span class="na">xmlns=</span><span class="s">"http://www.opengis.net/sld"</span>
  <span class="na">xmlns:ogc=</span><span class="s">"http://www.opengis.net/ogc"</span>
  <span class="na">xmlns:xlink=</span><span class="s">"http://www.w3.org/1999/xlink"</span>
  <span class="na">xmlns:xsi=</span><span class="s">"http://www.w3.org/2001/XMLSchema-instance"</span>
  <span class="na">xsi:schemaLocation=</span><span class="s">"http://www.opengis.net/sld</span>
<span class="s">                      http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd"</span><span class="nt">></span>
  <span class="nt"><NamedLayer></span>
    <span class="nt"><Name></span>Default Polygon<span class="nt"></Name></span>
    <span class="nt"><UserStyle></span>
      <span class="nt"><Title></span>Flags of USA<span class="nt"></Title></span>
      <span class="nt"><FeatureTypeStyle></span>
        <span class="nt"><Rule></span>
          <span class="nt"><Name></span>Solid black outline<span class="nt"></Name></span>
          <span class="nt"><LineSymbolizer></span>
            <span class="nt"><Stroke/></span>
          <span class="nt"></LineSymbolizer></span>
        <span class="nt"></Rule></span>
      <span class="nt"></FeatureTypeStyle></span>
      <span class="nt"><FeatureTypeStyle></span>
        <span class="nt"><Rule></span>
          <span class="nt"><Name></span>Flags<span class="nt"></Name></span>
          <span class="nt"><Title></span>USA state flags<span class="nt"></Title></span>
          <span class="nt"><PointSymbolizer></span>
            <span class="nt"><Graphic></span>
              <span class="nt"><ExternalGraphic></span>
                <span class="nt"><OnlineResource</span> <span class="na">xlink:type=</span><span class="s">"simple"</span>
                  <span class="na">xlink:href=</span><span class="s">"http://www.usautoparts.net/bmw/images/states/tn_${strToLowerCase(STATE_ABBR)}.jpg"</span> <span class="nt">/></span>
                <span class="nt"><Format></span>image/gif<span class="nt"></Format></span>
              <span class="nt"></ExternalGraphic></span>
            <span class="nt"></Graphic></span>
          <span class="nt"></PointSymbolizer></span>
        <span class="nt"></Rule></span>
      <span class="nt"></FeatureTypeStyle></span>
    <span class="nt"></UserStyle></span>
  <span class="nt"></NamedLayer></span>
<span class="nt"></StyledLayerDescriptor></span>
Read More

Raster Symbolizer tricks - part 1

I am going to bother for a few mins in order to show a few things about the raster symbolizer implementation that has landed on 1.7. Ideally this should the first of a series of more posts, but I can’t guarantee on that :-).

Anyway, today I have been playing with some bathymetry data for the geoSDI project. I cannot share them since it is classified data but I have been told that I can show some snapshots :-).

Here below you have the gdalinfo on one of the datasets:

Driver: GTiff/GeoTIFF Files: DEM_Vulcano_Lipari_Salina4326.tif Size is 3718, 3600 Coordinate System is: GEOGCS[“WGS 84”, …. AUTHORITY[“EPSG”,”4326”]] Origin = (14.747192412574043,38.660954215168857) Pixel Size = (0.000090196304703,-0.000090196304703) Metadata: AREA_OR_POINT=Point Image Structure Metadata: INTERLEAVE=BAND Corner Coordinates: …. Band 1 Block=3718x1 Type=Float32, ColorInterp=Gray

As you can see we are talking about Float data. First of all I retiled it with gdal_transalte (striped tiff are pretty bad performance-wise) then I added a few overview using gdaladdo with nearest neighbor interpolation. Once this was done I just throw it at the GeoServer and here is the result for an untiled request (here a detailed request ) and for a tiled request. Quick explanation, when you set up a raster with no real raster symbolizer element in its style (like for the raster.sld that ships with GeoServer) you can get strange results in case your data is raw, like bathymetries, DEMs and the like. What we do is trying to render something useful by doing a local contrast stretch, hence a tiled request can have the checkerboard approach and an untiled request can look fuzzy since maximum and minimum values are used for the stretch. In the future we might computer approximated statistics for a layer at configuration time and use them for the subsequent renderings.

Beside this I wanted to show a nice extension we implemented for the raster symbolizer element. Check this style as well as this one (notice that to use the secondo you have to uncheck SLD validation since the extension is not recognized by OGC schemas). They look like the same but if you check the second one you’ll see that the color map element looks like this while in the other one it looks like this . Well, long story short this is an extension I implemented in order to allow people to ask the GeoServer to symbolize raster data using as many colors as possible (specifically 65k) instead of limiting itself to 256. This results in much better looking images but you have to give away some performances. I guess it is something nice to have for layer that you want to cache with TileCache or GeowebCache.

To see you the differences, check the following:

I guess I have bothered enough.

Ciao a tutti.

PS. I found a minor bug today on the SLDParser which was not parsing the extended attribute. It is now fixed but unless you build things yourself, you won’t be able to test these things on 1.7.0. Drop me a few lines in case you want to try the differences and I’ll tell you how to fix this problem.

Read More