Skip to content

Streaming renderer aymbolizers pre processor extensions handling

Nuno Oliveira edited this page May 21, 2020 · 1 revision
  • Contact: fernandor777
  • TLDR: Streaming renderer aymbolizers pre-processor extensions handling

Description

This proposal if for adding Symbolizers pre-processor extensions handling to StreamingRenderer class. This means StreamingRenderer class will contain a new configurable Symbolizers pre-processor collection allowing to add or remove instances as needed.

The interface SymbolizersPreProcessor will be implemented for handling and enhance the current Symbolizers list, adding new symbolizers at runtime. If no changes are applied to the current Symbolizers list, null or the former Symbolizers list can be returned.

SymbolizersPreProcessor interface definition:

package org.geotools.renderer.lite;

import java.util.List;
import org.geotools.map.Layer;
import org.geotools.styling.Symbolizer;
import org.opengis.feature.Feature;

/**
 * Extension point interface for handling and transforming the Symbolizer list before sending it to
 * render phase. <br>
 * If no changes are done on the symbolizers list, the implementation must return the provided list
 * reference.
 */
public interface SymbolizersPreProcessor {

    /**
     * Declares if this pre-processor is applied to the layer involved.
     *
     * @param layer the layer to be rendered
     * @return true if this pre-processor can be applied to the layer
     */
    boolean appliesTo(Layer layer);

    /** Declares which attributes it might need in order to do its job. */
    List<String> getAttributes(Layer layer);

    /** Declares how much of an extra space is needed to catch the symbolizers it is about to add */
    double getBuffer(Layer layer, Style style);

    /**
     * Performs symbolizers list enhancements like adding, editing or removing symbolizers and
     * return the resulting list.
     *
     * @param feature the feature to be rendered
     * @param layer the layer owning the feature
     * @param symbolizers the symbolizers list to be processed before rendering
     * @return the enhanced {@link Symbolizer} list or null if no changes are applied. It can return
     *     the same symbolizers parameter without changes.
     */
    List<Symbolizer> apply(Feature feature, Layer layer, List<Symbolizer> symbolizers);
}

A set of add and remove methods for SymbolizersPreProcessor items will be added to StreamingRenderer class as following:

    /**
     * Adds a {@link SymbolizersPreProcessor} extension instance to the current collection.
     */
    public void addSymbolizersPreProcessor(SymbolizersPreProcessor symbolizersPreProcessor) {
        this.symbolizersPreProcessors.add(symbolizersPreProcessor);
    }
    
    /**
     * Adds {@link SymbolizersPreProcessor} extension instances to the current collection.
     */
    public void addSymbolizersPreProcessors(Collection<SymbolizersPreProcessor> symbolizersPreProcessors) {
        this.symbolizersPreProcessors.addAll(symbolizersPreProcessors);
    }
    
    /**
     * Removes a {@link SymbolizersPreProcessor} extension instance from the current collection.
     */
    public void removeSymbolizersPreProcessor(SymbolizersPreProcessor symbolizersPreProcessor) {
        this.symbolizersPreProcessors.remove(symbolizersPreProcessor);
    }

A preProcessSymbolizers method, executing the extensions chain logic and returning the final Symbolizers list, will be added to StreamingRenderer class as following:

     /**
     * Execute the {@link SymbolizersPreProcessor} extension points configured in this instance.
     * 
     * @param feature the feature for rendering
     * @param layer the layer instance for the feature
     * @param symbolizers the symbolizers to be enhanced
     * @return the enhanced symbolizers list, or the original if no extensions were applied
     */
    private List<Symbolizer> preProcessSymbolizers(Feature feature, Layer layer, List<Symbolizer> symbolizers) {
        ...
    }

The preProcessSymbolizers method will be called in the StreamingRenderer::processSymbolizers main for-each clause, executing the the extensions chain logic and returning the final Symbolizers list to be used:

    private int processSymbolizers(
            final Graphics2D graphics,
            final RenderableFeature drawMe,
            final List<Symbolizer> symbolizers)
            throws Exception {
        int paintCommands = 0;
        
        for (Symbolizer symbolizer : preProcessSymbolizers(drawMe.feature, drawMe.layer, symbolizers)) {

            // ...
            

StreamingRenderer query preparation trims down the requested attributes to the minimum based on the Style, and adds pixels buffer based on global configuration. This extension point will allow us to request all the attributes we need for the dynamic symbolizers generation and to add more buffer size, both per layer basis.

The SymbolizersPreProcessor::getAttributes extension method will return the required feature attributes. These attributes will be added to the already collected ones from styles, so in the end the union between style and extensions attributes will be fetched in the final query.

On every call to rendering buffer, the extensions buffer by layer will be checked and rendering will use the max value. For this purpose the StreamingRenderer::getRenderingBuffer method will be enhanced, calling extensions buffer only if there are extensions registered for the layer (using the appliesTo extension method). The SymbolizersPreProcessor::getBuffer extension method will declare the required buffer. The maximun buffer got from global configuration and extension will be used in the end.

The modifications will allow extensions to create symbolizers on the fly and apply them based on some custom logic without requiring a static SLD definition for them.

For every operation described here, only registered extensions whose SymbolizersPreProcessor::appliesTo method returns true will be used.

References: Ticket

Assigned to Release

GeoTools 24.x; GeoTools 23.2

Status

Choose one of:

  • Under Discussion
  • In Progress
  • Completed
  • Rejected,
  • Deferred

Voting:

  • Andrea Aime:
  • Ian Turton:
  • Jody Garnett:
  • Nuno Oliveira:
  • Simone Giannecchini:
  • Torben Barsballe:

Tasks

Add new extensions methods to StreamingRenderer Class.

API Change

Create a new SymbolizersPreProcessor interface:

package org.geotools.renderer.lite;

import java.util.List;
import org.geotools.styling.Symbolizer;
import org.opengis.feature.Feature;

/**
 * Extension point interface for handling and transforming the Symbolizer list before sending it to
 * render phase. <br>
 * If no changes are done on the symbolizers list, the implementation must return the provided list
 * reference.
 */
public interface SymbolizersPreProcessor {

    /**
     * Declares if this pre-processor is applied to the layer involved.
     *
     * @param layer the layer to be rendered
     * @return true if this pre-processor can be applied to the layer
     */
    boolean appliesTo(Layer layer);

    /** Declares which attributes it might need in order to do its job. */
    List<String> getAttributes(Layer layer);

    /** Declares how much of an extra space is needed to catch the symbolizers it is about to add */
    double getBuffer(Layer layer, Style style);

    /**
     * Performs symbolizers list enhancements like adding, editing or removing symbolizers and
     * return the resulting list.
     *
     * @param feature the feature to be rendered
     * @param layer the layer owning the feature
     * @param symbolizers the symbolizers list to be processed before rendering
     * @return the enhanced {@link Symbolizer} list or null if no changes are applied. It can return
     *     the same symbolizers parameter without changes.
     */
    List<Symbolizer> apply(Feature feature, Layer layer, List<Symbolizer> symbolizers);
}

Add to StreamingRenderer methods:

    /**
     * Adds a {@link SymbolizersPreProcessor} extension instance to the current collection.
     */
    public void addSymbolizersPreProcessor(SymbolizersPreProcessor symbolizersPreProcessor) {
        this.symbolizersPreProcessors.add(symbolizersPreProcessor);
    }
    
    /**
     * Adds {@link SymbolizersPreProcessor} extension instances to the current collection.
     */
    public void addSymbolizersPreProcessors(Collection<SymbolizersPreProcessor> symbolizersPreProcessors) {
        this.symbolizersPreProcessors.addAll(symbolizersPreProcessors);
    }
    
    /**
     * Removes a {@link SymbolizersPreProcessor} extension instance from the current collection.
     */
    public void removeSymbolizersPreProcessor(SymbolizersPreProcessor symbolizersPreProcessor) {
        this.symbolizersPreProcessors.remove(symbolizersPreProcessor);
    }
Clone this wiki locally