Book Image

GeoServer Cookbook

By : Stefano Iacovella
Book Image

GeoServer Cookbook

By: Stefano Iacovella

Overview of this book

Table of Contents (17 chapters)
GeoServer Cookbook
Credits
About the Author
Acknowledgments
About the Reviewers
www.PacktPub.com
Preface
Index

Improving performance with pregeneralized features


The feature type may contain a lot of coordinates. Also, if it's not a really big data, the simple vector datasets we use in this recipe contain a large number of vertices:

gisdata=> select sum(ST_NPoints(geom)) from countries;
sum
--------
548604

When you're creating a small-scale map, that is, a continent view, it does not make sense to have the GeoServer process all this data to output a really simplified rendering of the shapes. You are just wasting CPU time and degrading the performance of your server.

Having a simplified version of your data for general representation would be more practical, but you also want to have a detailed version of the data when your map goes to middle or large scale.

The idea behind the pregeneralized features module is to combine more versions of a feature type so that users of GeoServer can choose the one that is the best for each scale, while the user continues to use it as if it was a single feature type.

Note

Pregeneralized features are supported by an extension module. If you want to use this feature, you need to download the optional module. Please note that any extension module will follow the version of GeoServer. Installation is quite easy. Download the archive from http://geoserver.org/release/stable/ and extract the two JAR files into the WEB-INF/lib directory of the GeoServer installation.

How to do it…

  1. Start creating three generalized versions of countries for use in this recipe. The following instructions work for PostGIS:

    gisdata=> create table countries_0 as select admin, geom from countries;
    gisdata=> CREATE INDEX countries_0_geom_gist ON countries_0 USING gist(geom);
    gisdata=> create table countries_01 as select admin, ST_SimplifyPreserveTopology(geom,0.01) as geom from countries;
    gisdata=> CREATE INDEX countries_01_geom_gist ON countries_01 USING gist(geom);
    gisdata=> create table countries_05 as select admin, ST_SimplifyPreserveTopology(geom,0.05) as geom from countries;
    gisdata=>CREATE INDEX countries_05_geom_gist ON countries_05 USING gist(geom);
    gisdata=>create table countries_1 as select admin, ST_SimplifyPreserveTopology(geom,0.1) as geom from countries;
    gisdata=>CREATE INDEX countries_1_geom_gist ON countries_1 USING gist(geom);
    
  2. Create a new XML file, insert the following code snippet, and save it as geninfo_postgis.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <GeneralizationInfos version="1.0">
      <GeneralizationInfo dataSourceNameSpace="NaturalEarth" dataSourceName="PostGISLocal"  featureName="GeneralizedCountries" baseFeatureName="countries_0" geomPropertyName="geom">
        <Generalization dataSourceNameSpace="NaturalEarth" dataSourceName="PostGISLocal"  distance="1" featureName="countries_01" geomPropertyName="geom"/>
        <Generalization dataSourceNameSpace="NaturalEarth" dataSourceName="PostGISLocal"  distance="5" featureName="countries_05" geomPropertyName="geom"/>
        <Generalization dataSourceNameSpace="NaturalEarth" dataSourceName="PostGISLocal"  distance="10" featureName="countries_1" geomPropertyName="geom"/>
      </GeneralizationInfo>
    </GeneralizationInfos>
    
  3. Go to the data store section of the GeoServer web interface, click on Add new data store, and then select Generalizing data store:

  4. Input GeneralizedCountries as the name for the data store, and then point to the location of the geninfo_postgis.xml file. Change the org.geotools string to org.geoserver in the two textboxes and click on Save:

  5. You can now see the feature type you defined in the XML file and click on the Publish button. You are now done. Switch to the layer's preview to check whether GeoServer is properly visualizing the data.

How it works…

If you look at the layer preview, you will not see any difference from the countries' layers. You will observe a faster rendering; this is because GeoServer is indeed extracting geometries form the simplified table. Let's check what is happening behind the scenes.

Set the log detail in GeoServer to GEOTOOLS_DEVELOPER_LOGGING, and then open your GeoServer log with the tail command:

$: tail -f /opt/Tomcat7042/webapps/geoserver/data/logs/geoserver.log

Now open the preview for GeneralizedCountries. After the map is shown, you should see some rows that state GeoServer first evaluates the geometry distance from the map's scale. Select the table that is more appropriate to extract the features from:

INFO [org.geotools.data.gen] - Hint geometry distance: 0.5681250333785898
INFO [org.geotools.data.gen] - Hint geometry distance: 0.5681250333785898
INFO [org.geotools.data.gen] - Using generalizsation: PostGISLocal countries_1 geom 0.1

In the log, the actual query that is performed on the database is present, and you can check whether it is created on a simplified version of the countries. As you can see, it is indeed created on a simplified version of the countries. Actually, the version with a higher generalization degree, which contains the more simplified features, is used:

DEBUG [org.geotools.jdbc] - CREATE CONNECTION
DEBUG [org.geotools.jdbc] - SELECT encode(ST_AsBinary(ST_Force_2D("geom")),'base64') as "geom" FROM "public"."countries_1" WHERE  "geom" && ST_G
eomFromText('POLYGON ((-244.29375672340652 -121.77904978394649, -244.29375672340652 115.41315165161649, 244.29377198219652 115.41315165161649, 244.29377198219652 -121.7
7904978394649, -244.29375672340652 -121.77904978394649))', 4326)
 [org.geotools.jdbc] - CLOSE CONNECTION

From the database, you can check the total number of features in this table:

gisdata=> select sum(ST_NPoints(geom)) from countries_1;
  sum
-------
44085

Now, zoom in to your map and check what GeoServer writes in the log. When your map is centered on Europe, the map scale triggers GeoServer to use another table. If you inspect the log, you can indeed observe that now GeoServer is using the table countries_05:

INFO [org.geotools.data.gen] - Using generalizsation: PostGISLocal countries_05 geom 0.05

Check the database again; the total number of features is higher. However, you are using a fraction of them, as only a portion of the Earth is represented on the map, so you get finer detail without a slow rendering. This is attained using the following lines of code:

gisdata=> select sum(ST_NPoints(geom)) from countries_05;
  sum
-------
 66042

Continue to zoom in until you see in the log that GeoServer is using the original table, countries_0. You are now using the entire detailed geometries, but in a relatively small area:

DEBUG [org.geotools.jdbc] - SELECT encode(ST_AsBinary(ST_Force_2D("geom")),'base64') as "geom" FROM "public"."countries_0" WHERE  "geom" && ST_G
eomFromText('POLYGON ((6.016917772920612 4.379043245570911, 6.016917772920612 5.305575282428689, 7.925462806926788 5.305575282428689, 7.925462806926788 4.37904324557091
1, 6.016917772920612 4.379043245570911))', 4326)