Icon

The gt-render module supplies two factories that can be used to teach the rendering system about your custom icons.

Notes: This is considered Advanced material because you need to register the factory you have created.

MarkFactory

The job of this class is to evaluate the provided expression (it should evaluate into a String) and construct a good Java Shape out of it that we can draw on the map.:

/*
 *    GeoTools - The Open Source Java GIS Toolkit
 *    http://geotools.org
 *
 *    (C) 2019, Open Source Geospatial Foundation (OSGeo)
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation;
 *    version 2.1 of the License.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 */

package org.geotools.render;

import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.GeneralPath;
import org.geotools.renderer.style.MarkFactory;
import org.opengis.feature.Feature;
import org.opengis.filter.expression.Expression;

class SplatMarkFactory implements MarkFactory {

    private static GeneralPath SPLAT;

    static {
        SPLAT = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
        SPLAT.moveTo(-0.2f, 0.9f);
        SPLAT.lineTo(0.266f, -0.5f);
        SPLAT.lineTo(-0.366f, -0.7f);
        SPLAT.lineTo(0.4f, 1.12f);
        SPLAT.lineTo(0.3f, 1.10f);
    }

    public Shape getShape(Graphics2D graphics, Expression symbolUrl, Feature feature)
            throws Exception {
        if (symbolUrl == null) {
            // cannot handle a null url
            return null;
        }
        // Evaluate the expression as a String
        String wellKnownName = symbolUrl.evaluate(feature, String.class);

        if (wellKnownName != null && wellKnownName.equalsIgnoreCase("splat")) {
            return SPLAT;
        }
        return null; // we do not know this one
    }
}

To use this class we are going to need to define a style that refers to this new mark:

        StyleBuilder builder = new StyleBuilder();
        FilterFactory2 ff = builder.getFilterFactory();

        Graphic splat = builder.createGraphic(null, builder.createMark("splat"), null);
        PointSymbolizer symbolizer = builder.createPointSymbolizer(splat);

        // builder will fill in all the other classes with defaults
        Style style = builder.createStyle(symbolizer);

To register your class you will need to:

  1. Create the following folder: META_INF/services/

  2. In this folder create a file: org.geotools.renderer.style.MarkFactory

    The contents of this file should list your implementation:

    org.geotools.demo.render.SplatMarkFactory
    

ExternalGraphicsFactory

This factory is much more capable, as it is not restricted to creating a simple shape.

This class is responsible for:

  • evaluate the provided expression (it should evaluate into a URL)

    A feature is allowing the expression to refer to attributes if needed.

  • construct a Java Icon

  • both a format and a size are provided for reference

Your implementation can:

  • implement a dynamic Icon directly (useful for symbols that need to be composed based on feature attributes)
  • or as simple as a straight SwingIcon backed by a PNG file contained in your jar.