red book

Table of Contents

1. Introduction
2. Ressources
Get and update sources
Local compilation
3. Datas
Batch handling
Manipulation with Reader/Writer
CSW service
IGN RM services
OpenStreetMap Tiled Maps Service
Sensor Observation Service
Web Map Server
4. Map
Règles de style
Cas spéciaux
Rendering steps
2D engine
Custom Graphic Objects
Custom Graphic Builder
Custom decoration
Custom Symbolizer
5. Process
What is a process ?
Create his process
The registry
Using process
Finding process
Exécution d'un processus
Process Quartz
Process Shell
Process XOffice
6. ObjectConverter
Create an ObjectConverter.
Using an ObjectConverter
7. Swing components
Map componants
Others components

List of Figures

1. GeoToolkit
2. GeoToolkit Model
4.1. Classes relatives aux maps
4.2. Classes relatives à la symbologie
4.3. Classes relatives aux styles
4.4. Pipeline image par défaut
4.5. Pipeline pour les images standard (png,jpg,tiff ... : habituellement 3 ou 4 bandes couleurs)
4.6. Pipeline pour les images type scientifique ( 1 bande )
4.7. Sélection de bande - un seul canal
4.8. Sélection de bande - Vert/bleu inversé
4.9. ColorMap - Interpolation
4.10. ColorMap - Catégorisation
4.11. Ajustement de contraste - aucun
4.12. Ajustement de contraste - Gamma
4.13. Ajustement de contraste - Histogramme
4.14. Ajustement de contraste - Normalisation
4.15. Contours
4.16. Effet de relief
4.17. Enging 2D class
4.18. Rendering steps
4.19. iReport 3.7.4 homepage
4.20. Source fields
4.21. Field class
4.22. fields properties window
4.23. Fields properties
4.24. Decorations samples :
5.1. Parameter description class and interface
5.2. Class and interfaces of parameters values
7.1. Displaying a map using JMap2D
7.2. Showing display properties using JContexTree
7.3. Navigation bar
7.4. Information bar
7.5. Selection bar
7.6. Edition toolbar
7.7. Coordinates toolbar
7.8. Elevation toolbar
7.9. Temporal toolbar
7.10. Config toolbar
7.11. Compass
7.12. Information panel
7.13. Displaying JMap2DFrame
7.14. window of attributes edition
7.15. window of style edition

List of Examples

3.1. List the different factories coverage
3.2. Using a CoverageReader
3.3. List the different factories server
3.4. Source :
3.5. Connecting to the IGN services
3.6. Connecting code to the IGN service
3.7. Connecting Service OpenStreetMap Tiled
3.8. Connecting code to the OSMTMS service
3.9. Connecting code to SOS server
3.10. Connecting code to SOS server
3.11. Connecting to WMS server
3.12. Connecting to WMS server
4.1. Création d'un MapContext
4.2. Création d'un MapContext
4.3. Style avec plusieurs règles
4.4. Divers examples de symbologie
4.5. Generating images
4.6. Create and show an image-map
4.7. Generating glyph
4.8. Creating and displaying a glyph
4.9. Generating report with JasperReport
4.10. Generating captions
4.11. Create and show a legend
4.12. Simple graphic Object
4.13. Bespoke object GraphicBuilder
4.14. Object graphic sur mesure
4.15. Make a new symbolizer
5.1. Code to create a registry
5.2. Registry Identification
5.3. Identifies Registry
5.4. Identifies Registry
5.5. Code to create ProcessDescriptor for an Addition
5.6. Describing input
5.7. Description of an entry with translation bunlde
5.8. Description entries
5.9. Example 1 : Finding process.
5.10. Example 2 : Execution of a simple process.
5.11. Exemple 3 : Execution of a complex process
5.12. Récupération de la liste des ProcessingRegistry et des ProcessDescriptor
5.13. Récupération d'un ProcessDescriptor en particulier
5.14. Registry méthodes
5.15. Création des paramètres d'entrées
5.16. Remplissage des paramètres d'entrées.
5.17. Création du processus.
5.18. Exécution et récupération de la sortie du processus.
5.19. CRS EPSG:27573
5.20. CRS transform EPSG:27573 EPSG:4326
5.21. Execution de process en ligne de commande
6.1. Complete source code from WKT String to JTS Geometry.
6.2. Convert WKT to Geometry
6.3. Example using a ConverterRegistry.
6.4. Convert WKT in Geometry
7.1. Demo of different widgets

Figure 1. GeoToolkit


Figure 2. GeoToolkit Model

Geotoolkit Model

Geotookit is a library dedicated to mapping, however this area overlaps with many other areas. Included are the manipulating images, metadata geometries, the reverse engineering Mechanisms of databases, secure connection or user interfaces.

Today the project has more than one hundred modules.

Different resources are using in these tutorials. You will find common information in this chapter.

Compilation requiered :

When you have installed these, use this command to compile :

            mvn clean install -DskipTests

Compile time depends of your hardware and your Internet connection. The first compilation is longer to get differents packages missing (around thirty minutes the first time).

GeotoolKit Jars are in the subdirectory target.

Geotooltik implements The OGC standard and GeoAPI 3 .

In fact, we will use specific models for images and vectorial datas whatever the sources used.

  • Coverage / Coveragestore for raster images.
  • Feature / Datastore for vectorial datas and attributes.
  • Client / Server for remotes connection.

All formats are not always standardized, or can't be used in specific models. Particularly, results sent by some remote services which are standardized are not coverage or feature. We will find server which implements Datastore or CoverageStore. Geotoolkit manages communication between these services, provides authentication diposal, sending request, and traitment results.

GeotoolKit uses Java standard API for image processing. Image describes storage method and color space. Coverages add georeferencing informations and metadata.

GeotoolKit processes images based on Java standard API. Image describes storage model, color model. Coverage is an overlay which add georeferencing and metadata informations.

To get a coverage, we use a CoverageReader. It will improve control on image reading, by limiting the area reading or resolution. For image files (netcdf, geotiff, world image, ...) we use the utility class CoverageIO.
            final File input = new File("data/clouds.jpg");
            final GridCoverageReader reader = CoverageIO.createSimpleReader(input);

When we have a CoverageReader, we can access it metadatas.

            //print the iso 19115 metadata
            final Metadata metadata = reader.getMetadata();

Metadata object is a Java version metadata of ISO 19115-2 standard To do this operations, we will use a Coverage object :

            //read a piece of coverage
            final GridCoverageReadParam param = new GridCoverageReadParam();
            param.setEnvelope(new Rectangle2D.Double(0, 0, 100, 100), DefaultGeographicCRS.WGS84);

            final GridCoverage2D coverage = (GridCoverage2D), param);

GridCoverageReadParam object is useful to specify what it's item interest for reading. Coverage (or coveragereader) can be using to make a CoverageMapLayer.

            //create a mapcontext
            final MapContext context = MapBuilder.createContext();
            final CoverageMapLayer cl = MapBuilder.createCoverageLayer(reader,, "raster");

            //display it

GeotoolKit contains a large number of modules to connect to different remote services.

Each client work with class implement Server. We will find in this class :

Google Static Maps

Catalog Web Server (CSW) est un service de l'OGC fait pour renvoyer des métadonnées.

Standard :

                final MarshallerPool pool = CSWMarshallerPool.getInstance();
                Unmarshaller um = null;

                try {
                um = pool.acquireUnmarshaller();

                // build a new CSW client
                final CatalogServicesServer cswServer = new CatalogServicesServer(new URL(""), "2.0.2");

                * make a getCapabilities request
                final GetCapabilitiesRequest getCapa = cswServer.createGetCapabilities();

                InputStream is = getCapa.getResponseStream();

                // unmarshall the response
                Capabilities capabilities = (Capabilities) um.unmarshal(is);

                // print the title of the server

                * make a getRecords request
                final GetRecordsRequest getRecords = cswServer.createGetRecords();
                getRecords.setConstraint("Title like '%'");
                is = getRecords.getResponseStream();

                // unmarshall the response
                GetRecordsResponseType response = ((JAXBElement
                <GetRecordsResponseType>) um.unmarshal(is)).getValue();

                // print the number of result matching the request

                * retrieve results in dublin core

                is = getRecords.getResponseStream();

                // unmarshall the response
                response = ((JAXBElement
                    <GetRecordsResponseType>) um.unmarshal(is)).getValue();

                // print the first result (Dublin core)
                AbstractRecord record = response.getSearchResults().getAbstractRecord().get(0);

                * retrieve results in ISO 19139

                is = getRecords.getResponseStream();

                // unmarshall the response
                response = ((JAXBElement
                        <GetRecordsResponseType>) um.unmarshal(is)).getValue();

                // print the first result (ISO 19139)
                Metadata meta = (Metadata) response.getSearchResults().getAny().get(0);

                final String identifier = meta.getFileIdentifier();

                * make a getRecordById request
                final GetRecordByIdRequest getRecordById = cswServer.createGetRecordById();

                is = getRecordById.getResponseStream();

                // unmarshall the response
                GetRecordByIdResponse responseBi = ((JAXBElement
                            <GetRecordByIdResponse>) um.unmarshal(is)).getValue();

                // print the result (same as getRecords first result)
                meta = (Metadata) responseBi.getAny().get(0);

                } finally {
                if (um != null) {

Sensor Observation Service (SOS) is OGC service to return sensor datas.

Standard :

Example 3.10. Connecting code to SOS server

                final MarshallerPool pool = SOSMarshallerPool.getInstance();
                Unmarshaller um = null;

                try {
                um = pool.acquireUnmarshaller();

                // build a new SOS client
                final SensorObservationServiceServer sosServer = new SensorObservationServiceServer(new URL(""), "1.0.0");

                * make a getCapabilities request
                final GetCapabilitiesRequest getCapa = sosServer.createGetCapabilities();

                InputStream is = getCapa.getResponseStream();

                // unmarshall the response
                Capabilities capabilities = (Capabilities) um.unmarshal(is);

                // print the title of the server

                // extract a sensorML identifier and outputFormat to make a describeSensor request
                Operation describeSensorOperation = capabilities.getOperationsMetadata().getOperation("DescribeSensor");

                String sensorID = ((ValueType) describeSensorOperation.getParameter("procedure").getAllowedValues().getValueOrRange().get(0)).getValue();
                String outputFormat = ((ValueType) describeSensorOperation.getParameter("outputFormat").getAllowedValues().getValueOrRange().get(0)).getValue();

                // extract a all the parameters necessary to make a getObservation request
                Operation getObservationOperation = capabilities.getOperationsMetadata().getOperation("GetObservation");

                String offering = ((ValueType) getObservationOperation.getParameter("offering").getAllowedValues().getValueOrRange().get(0)).getValue();
                String responseFormat = ((ValueType) getObservationOperation.getParameter("responseFormat").getAllowedValues().getValueOrRange().get(0)).getValue();
                String phenomenon = ((ValueType) getObservationOperation.getParameter("observedProperty").getAllowedValues().getValueOrRange().get(0)).getValue();
                String procedure = ((ValueType) getObservationOperation.getParameter("procedure").getAllowedValues().getValueOrRange().get(0)).getValue();
                String featureOfInterest = ((ValueType) getObservationOperation.getParameter("featureOfInterest").getAllowedValues().getValueOrRange().get(0)).getValue();

                * make a DescribeSensor request
                final DescribeSensorRequest descSensor = sosServer.createDescribeSensor();

                is = descSensor.getResponseStream();

                // unmarshall the response
                AbstractSensorML sensorMLResponse = (AbstractSensorML) um.unmarshal(is);


                * make a GetObservation request
                final GetObservationRequest getObs = sosServer.createGetObservation();
                getObs.setFeatureOfInterest(new FeatureOfInterest(Arrays.asList(featureOfInterest)));

                is = getObs.getResponseStream();

                // unmarshall the response
                ObservationCollectionType getObsResponse = (ObservationCollectionType) um.unmarshal(is);


                } finally {
                if (um != null) {


A l'exception des couches spécifiques, MapContext, FeatureMapLayer et CoverageMapLayer sont créés en utilisant la classe MapBuilder.

Voici un exemple de création d'un MapContext avec différents types de couches :

                    //create a map context
                    final MapContext context = MapBuilder.createContext();

                    //create a feature layer
                    final FeatureCollection features = openShapeFile();
                    final MutableStyle featureStyle =;
                    final FeatureMapLayer featureLayer = MapBuilder.createFeatureLayer(features, featureStyle);

                    //create a coverage layer
                    final GridCoverageReader reader = openWorldFile();
                    final MutableStyle coverageStyle =;
                    final CoverageMapLayer coverageLayer = MapBuilder.createCoverageLayer(reader, coverageStyle,"background");

                    //create a WMS layer
                    final WebMapServer server = new WebMapServer(new URL(""), WMSVersion.v130);
                    final WMSMapLayer wmsLayer = new WMSMapLayer(server, "BlueMarble");

                    //add all layers in the context

                    //check the result


Il est aussi possible de créer une arborescence plutot qu'une liste. Les éléments utilisés pour symbolizer des noeuds sont des MapItem.

GeotoolKit utilise des fabriques pour créer les objets de style.

Il y en a trois :

  • MutableStyleFactory
  • FilterFactory
  • MutableSLDFactory

Vous vous demandez peut-être ce que vient faire ce 'Mutable' ici ?

En fait, toutes les interfaces de styles sont définies dans GeoAPI mais elles sont immutables. C'est pourquoi dans GeotoolKit on trouve ces mêmes interfaces précédées de 'Mutable' ainsi que des méthodes 'setter' sur les propriétés.

Ce ne sont pas strictement toutes les classes qui sont mutables, les filtres, expressions et symbols eux sont immutables pour des raisons de concurrence.

Quand vous créerez des styles, par moment il est préférable d'utiliser les valeurs par défaut pour certaines propriétés, ces valeurs sont accessibles comme des constantes sur la classe :

GeotoolKit contains a rendering engine. His name is GO2.

In the beginning, the engine was restricted to mapping data and existing styles stantard. Now, it is a true scenographer. His capacities are restricted at 2D rendering, but it's not limited to mapping datas. It is possible to define news symbols, renderering process etc.

For this task, we use one class : DefaultPortrayalService which contains two méthods :

  • portray : will generate a BufferedImage or will write image inside the given flow/file.
  • visit : will search elements which touch requested areava

Definition that we will draw and how it will do is splitting between 4 groups :

  • CanvasDef : define size of drawing box and color background.
  • SceneDef : define MapContext and element of the scene we will draw.
  • ViewDef : define geographical area we will draw and an azimuth (rotation).
  • OutputDef : define output flow (flow, files, uri,...).

GeotoolKit uses JasperReports API to generate report and atlas. It's the best Java API for generating report and has its own editor, IReport. We had to paint specials elements for maps, captions, scale bar...we need to edit specific report.

You can download IReport here :

Application preview :

If you don't know JasperReports or IReport, the documentations is available here.

When we create a report, we will use two types of informations during generating :

When we finish our report, parameters will be giving with a Map object, and fields will be converting in FeatureType.

will be processiong in FeatureType :

                    ║ name        │  min │  max │  nillable │  type         │  CRS │  UserData  ║
                    ║ CNTRY_NAME  │ 1    │ 1    │ true      │ String        │      │            ║
                    ║ POP_CNTRY   │ 1    │ 1    │ true      │ Integer       │      │            ║
                    ║ map3        │ 1    │ 1    │ true      │ MapDef        │      │            ║
                    ║ chart4      │ 1    │ 1    │ true      │ ChartDef      │      │            ║
                    ║ legend5     │ 1    │ 1    │ true      │ LegendDef     │      │ map=map3   ║
                    ║ scalebar6   │ 1    │ 1    │ true      │ ScaleBarDef   │      │ map=map3   ║
                    ║ northarrow7 │ 1    │ 1    │ true      │ NorthArrowDef │      │ map=map3   ║
                    ║ table8      │ 1    │ 1    │ true      │ JRDataSource  │      │            ║
                    ║ minimap     │ 1    │ 1    │ true      │ MapDef        │      │            ║

If we look binding of FeatureType, we see MapDef, ChartDef, LegendDef ...

They are types that GeotoolKit knows.

To define these types, we must edit class field in IReport :

The list of the recognized fields is :


For the types legend, scalebar and north arrow, It's necessary to indicate to which map the type relates. This information defines itself in the properties of the field:


  1. Template parser
                            final File template = ...
                            final Entry<JasperReport,FeatureType> entry = JasperReportService.prepareTemplate(template);
                            final JasperReport report = entry.getKey();
                            final FeatureType type = entry.getValue();

    This step will generate the FeatureType for the template.

  2. Prepare datas

    This part is depending of your template.

    We want create a FeatureCollection with the featuretype provided. This step depends of your template and your datas entered.

    Featuretype can be uniform, missing properties are replacing by null .

    You can specifiy the case when value is null.

  3. To generate report
                            final OutputDef output = new OutputDef(JasperReportService.MIME_PDF, new File("atlas.pdf"));
                            JasperReportService.generateReport(report, featureCollection, parameters, output);

    Duration of this step can be shorter or longer and use more memory or depending on the complexity of the relationship and the amount of data to be processed

For this class, one class is using : DefaultLegendService with two methods :

  • portray : will paint caption inside stream or BufferedImage.
  • legendPreferredSize : explore style and find optimal caption size.

You need a LegendTemplate object to create a caption. This object is using to contain general information like spacing, colors, or font familly...

To create a new treatment, you had to implement three things :

Registry are using inside the proccessing module of GeotoolKit to organize process which do the same type of treatment. For example, registry "math" contains only calculation process, the vector registry all process which work on vector layers.

Each registy contains an instance list describing process it contains. We can get the description of a process easily.

To create it factory, you can extend AbstractProcessingRegistry class and redefine the method getIdentification(). which allow to identify own our registry. Registy is identifying with an Identification object like in the next example.

You must initialize your Registy with it the treatment list (processus) that Registry contains. It must be an instance list of describer of each process. The easiest method is that each describer implements singleton pattern. And when we add a process, we add it descripber to registry initialization. The following example illustrates this principle

It's possible to make a dynamic initialization. You list available process into META-INF/service file and an iterator of the class ServiceRegistry on ProcessDescriptor interface like in the next example. You need to have the constructors of describers in public.

To finish the creating of your registry, you have to declare your class into org.geotoolkit.process.ProcessingRegistry file in a resources/META-INF/service folder of module. You have to do this to enable that the utility class ProcessFinder find your Registry and its process.

You have to describe your process during the creating process. This description must contain all input/output of your process, its name and few sentences about its work. It must allow to instantiate treatment itself by passing input parameters.

For input and output managing, we use in GeotoolKit the GeneralParameterDescriptor which was first an object of ISO_19111 standard.

Input and Output description is doing by ParameterDescriptorGroup creation. which regroup a set of GeneralParameterDescriptor. These GeneralParameterDesciptor can be sub-ParameterDescriptorGroup or ParameterDescriptor which discribe a parameter.

The next pseudo class diagram describes hierarchy among class and interfaces which define GeneralParameterDescriptor.

To create ParameterDescriptor or ParameterDescriptorGroup, we use default implementation of GeotoolKit DefaultParameterDescriptor and DefaultParameterDescriptorgourp.

In the next example, we will create input parameter of a process which calculate addition of two numbers. We have two ParameterDescriptor, one for each input number, and another ParameterDescriptorGroup to regroup them like INPUT.

DefaultParameterDescriptor has some constructor which depend of informations about parameter wanted.voulu. In previous example, we build our numbers by passing in order:

  • A unique name "first"
  • A description "Fisrt number"
  • Their binding class "Double.class"
  • Their default value. "null"
  • A boolean to say if this parameter is optionnal. "Double.class"

But we can also give the multiplicity for each parameter, aliases, their units or the list of allowed values. For more information refer to the Javadoc DefaultParameterDescriptor and DefaultParameterDescriptorgourp. This information is used when creating the input parameters to check insert values​​.

We can have translate for parameters descriptions of process like in the demo. We must have too created bundles in resources folder, and create ResourceInternationalString objects with the key defines by one translation. For parameters, we must build a Map of "properties" like in the next example.

Thereafter when you want to create the parameter values ​​to enter for giving our process, simply call the method createValue () on ParameterDescriptorGroup representing the process inputs. Then this method will return ParameterValueGroup built from ParameterDescriptor.

It only remains to finish the descriptor to implement the constructor with the identification and description of the process and its inputs / outputs and redefine CreateProcess () method as in the following example.

In this part, we will see how find and execute a simple process then another more complex like Union. You will find the links to the different examples.

To execute a process, you need before get its description. GeotoolKit has the utility class ProcessFinder which contain a set of static methods. This class get all ProcessingRegistry defined in files resources/META-INF/services/org.geotoolkit.process.ProcessingRegistry. And all descriptions that each ProcessFactory contains.

Dans l'exemple suivant on voit la récupération de la liste des ProcessingRegistry puis pour chaque registry la liste des ProcessDesciptor qu'elle contient.

On peux également récupérer plus rapidement un process en particulier en connaissant son nom et le nom de sa registry. Comme dans l'example suivant.

Une fois que l'on a une registry on peut appeler différentes méthodes dessus :

Une fois que l'on a la description d'un processus, il suffit de passer des valeurs aux paramètres d'entrées. Pour cela, il faut commencer par créer le groupe de paramètres d'entrée ( ParameterValueGroup) à partir de leurs descriptions ( ParameterDescriptorGroup) (définie dans la description complète du processus).

Pour cela on appel la méthode createValue() sur le descripteur du group de paramètre d'entrée. Comme dans l'exemple suivant.

Une fois qu'on a le ParameterValueGroup, il suffit de remplir les paramètres d'entrée avec les valeurs voulus. La récupération d'un parametre en particulier ce fait par son nom définie lors de la description de l'entrée dans le ProcessDescriptor.

Les paramètres d'entrée créer il ne reste plus qu'à créer et à exécuter processus et la récupération de la (des) donnée(s) en sortie. La création du processus ce fait à partir du descripteur avec la méthode createProcess() à laquelle on donne nos paramètres d'entrées.

L'exécution du traitement ce fait simplement par l'appel à la méthode call() sur l'objet process. Lequel retourne dans un ParameterValueGroup le groupe de paramètre de sortie. Il suffit alors de récupérer le paramètre voulu par le biai de son nom et ensuite d'extraire sa valeur.

Geotoolkit has several tools for the execution and process management.

Une partie des processus sont exécutables en ligne de commande. Ces outils servent principalement dans les environnements dépourvus d'interface utilisateur, mais peuvent aussi bien être utilisés pour faire du traitement en fond de plan.

Trois outils sont disponibles :

Geotoolkit Offer the possibility to create your own conversion objects. Most of the time theyre are used for simple type conversion (StringToFile, StringToURL, URLToFile ...), but it can also be used for more complex types. A list of casual simple type converters already exist and is available in Geotoolkit in package org.geotoolkit.util.converter.

A converter is defined by :

To create your own ObjectConverter, you need to implement ObjectConverter or extend the abstract class SimpleConverter.

The following example shows how to convert a WKT String in a JTS geometry.

The main method to implement is 'T convert(S source)' which makes the conversion from S to T type. Whenever an exception occurs on vérification or processing the conversion, the method must throw a NonconvertibleObjectException. Following example shows how to convert a String in a JTS Geometry after a few verifications.

The remaining methods are used to retrieve the source and targer classes, and additional flags to know if the converter preserve object natural sorting order, if they are some restrictions or if the order is reversed. For more informations check the Javadoc of ObjectConverter.

To use converters, we need to create a Registry which will hold a list of ObjectConverters and register it. Or we create the ObjectConverter and register it in the default ConverterRegistry using ServiceRegistry.

GeotoolKit offers a lot of swing components for cartography.