You want to add logic to an OGC Filter that goes beyond the filtering capabilities offered by the standard.

Why do it?

The OGC Filter specification is a flexible, general-purpose filtering language that supports a wide variety of use cases. Within LuciadLightspeed, it can be used as follows:

  • As a stand-alone filtering language: you can use OGC Filters to filter data in a layer or model. This is illustrated by the sample available in samples.ogc.filter.model.

  • As a filtering language used within OGC SLD / SE: an OGC Filter allows you the flexibility to define SLD / SE styling rules that apply to just a subset of a data set. This is illustrated by the OGC SLD samples.

  • As a filtering language within the WFS: you can use OGC Filters to retrieve a data subset from a WFS. This is illustrated by the OGC WFS proxy samples.

On top of its built-in filtering capabilities, OGC Filter allows users to define custom filtering logic. For example, we have a ship with a known current speed, and a data set containing harbors. Now, we want to filter the harbor data set, and find out which of those harbors can be reached by the ship within 24 hours. We need to take into account that OGC Filter provides basic support for arithmetic calculations, but that there is no notion of a unit of measure; it is assumed that all values are defined in the same unit of measure. In the example, we relate speed to time, so we need additional logic to convert one measurement unit to the other.

How to do it?

To define custom logic, OGC Filter lets you use the concept of a function . A function has 0 or more arguments and can return a single value. That value can in turn can be used by other filtering capabilities.

The following steps explain how to add a custom function:

  1. Define an implementation of ILcdEvaluatorFunction. This interface defines the arguments and the logic of our function. Given the example above, we will write a function that calculates the time in hours to reach a harbor. In a later step, we can use the resulting value to compare it with the maximum number of hours allowed: 24.

    Our function has 3 arguments: a longitude coordinate and a latitude coordinate, expressing the position of the ship, and the speed of the ship, expressed in meters per second. Consequently, the implementation of the getArgumentCount() method looks as follows:

    @Override
    public int getArgumentCount() {
      return 3;
    }

    The OGC filtering logic uses these arguments to determine how many hours it takes the ship to reach a particular harbor:

    @Override
    public Object apply( Object[] aArguments, Object aCurrentObject, TLcdOGCFilterContext aOGCFilterContext ) {
      ILcdPoint harbor = (ILcdPoint) aCurrentObject;
      TLcdLonLatPoint currentPosition= new TLcdLonLatPoint(Double.parseDouble((String) aArguments[0]), Double.parseDouble((String) aArguments[1]));
      double speed = Double.parseDouble((String) aArguments[2])
      double distance = new TLcdEllipsoid().geodesicDistance(currentPosition, harbor);
      double time = distance / speed;
      return time / 3600d;
    }
  2. Register the implementation for all evaluators. If you use the static method TLcdOGCFilterEvaluator.registerDefaultFunction() to register the custom function, it will become available to all evaluators.
    The registration includes defining a name for the function, so that it can be referred to in an actual OGC Filter.

TLcdOGCFilterEvaluator.registerDefaultFunction(TLcdXMLName.getInstance(new QName("estimatedDurationToArrive")), customEvaluatorFunction);

How to use it?

The following code block shows how you can define an OGC Filter that uses the custom function:

TLcdOGCFunction function = new TLcdOGCFunction( "estimatedDurationToArrive" );
function.addArgument( new TLcdOGCLiteral( "-74.03777778" ) );
function.addArgument( new TLcdOGCLiteral( "40.55083333" ) );
function.addArgument( new TLcdOGCLiteral( "9.5" ) );

TLcdOGCBinaryComparisonOperator condition = new TLcdOGCBinaryComparisonOperator(
  TLcdOGCBinaryComparisonOperator.LESS_OR_EQUAL, function, new TLcdOGCLiteral( "24" ) );

TLcdOGCFilter filter = new TLcdOGCFilter( condition );

In this code block, we use the value resulting from the custom function, and determine whether it is less or equal with the maximum number of hours allowed to reach the harbor.