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 Sample code and Tutorials by Open Source Geospatial Foundation, and others
 *    https://docs.geotools.org
 *
 *    To the extent possible under law, the author(s) have dedicated all copyright
 *    and related and neighboring rights to this software to the public domain worldwide.
 *    This software is distributed without any warranty.
 *
 *    You should have received a copy of the CC0 Public Domain Dedication along with this
 *    software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
 */
package org.geotools.render;

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

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();
        FilterFactory 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.