Copyright © 2010 ObjectFX Corporation
ObjectFX®, SpatialFX®, and SpatialRules™ are trademarks of ObjectFX Corporation. All other trademarks are the property of their respective trademark holders.
Various aspects of the SpatialFX technology are covered by one or more of the following U.S. Patents 6,604,046 and 7,010,426 and one or more pending patent applications.
Neither this documentation nor the software it describes may be copied, photocopied, reproduced, modified, translated, or converted to any alternative medium or format in whole or in part, except as explicitly stated in the user's license agreement with ObjectFX Corporation.
Table of Contents
List of Figures
List of Tables
SpatialRules is distributed as a ZIP file which contains the following directory structure:
bin |
Command-line tools. |
doc |
Contains all the documentation for SpatialRules. |
examples |
Contains several examples of how to use SpatialRules. |
lib |
Contains all of the jar files used by SpatialRules. Only the
|
xml |
Contains the XML DTDs and schemas used by SpatialRules. These schemas are required to be on the classpath when using XML-based formats. |
rules.properties |
The properties file for SpatialRules. |
SpatialRules takes advantage of Java asserts. Asserts should be enabled during development and quality assurance but turned off during production. The "-ea" command line option is one way to enable them:
java -ea <class>
The distribution includes a number of examples that demonstrate how to use and integrate the product. The urban or maritime examples are good places to start. These examples use command-line tools to add reference features and rules to the Rules Database. A data set is then submitted to SpatialRules for analysis.
To run the examples:
Place your license file
(rules-license.dat) in the root directory of
the distribution so that SpatialRules will find it. If you need to
change the name of the file or place it in a different location,
change the rules.license.file property in the
rules.properties file to specify the new
location of the license file.
By default, SpatialRules will create a database in
System.getProperty("user.home")/rules-db. To change the
location of this database change the
rules.db.path property to point to the location
where you want the database written.
Uncomment the following line in the
rules.properties file and change the "500" to
"1".
#rules.resultlistener.1=com.objectfx.rules.results.ConsoleResultPrinter,AllExpressions,500
Open a command-line window and change to the directory of
either examples/urban or
examples/maritime.
Start the example by running the
runExample.cmd script.
Both of these examples use the command-line import tools to set up
reference features and rules. This starts SpatialRules and sends some test
data for evaluation against the rules. The output from these examples
displays on the server's console. The result handling uses a provided
ResultListener named ConsoleResultPrinter that is registered in
rules.properties located in the SpatialRules home
directory.
The examples/src directory contains other
examples for integrating SpatialRules into Java applications. The basic
examples ClientSubmitExample and EmbeddedRulesExample are good starting
points for application integration. The example ClientSubmitExample shows
how to use the InputClient to submit data to a remote instance of
SpatialRules. The example EmbeddedRulesExample shows how to integrate
SpatialRules services directly into an application. The source code for
SpatialRules.java, is included to show you how all of
the components in SpatialRules are assembled for its default
configuration.
Table of Contents
A feature (com.objectfx.feature.Feature) is a
georeferenced object. All feature types have the following set of
properties:
ID |
A unique identifier for the feature. This ID must be unique for all features to get accurate results. |
Type |
Used to differentiate groups of features. Features with different types usually have different sets of attributes associated with them, for example. |
Name |
Usually, the common name of a feature and typically used for display only. The name property does not have the uniqueness constraints of the ID property. |
Geometry |
Describes the feature's size, shape, and position. The geometry could be just a single point or it could be a more complex shape like a line, polygon, or even a geometry collection. See Appendix C, Geometries for details on all the geometries that SpatialRules supports. |
Additional attributes (optional) |
An arbitrary set of name/value pairs for specifying
additional properties for the feature. Names are strings and
values are implementations of Comparable
(
|
Reference features are features that are loaded from the RulesDatabase and referenced in expressions by ID. They are usually stationary features such as:
Political boundaries
Road segments
Landmarks
Territorial waters
When the RulesService starts up, it reads the reference features into memory. So, you can update a reference feature while the RulesService is running, but you must refresh the RulesService to load the updated version of the reference feature.
To use a reference feature in an expression, you use a feature
reference (com.objectfx.feature.FeatureRef) and
specify the ID of the feature that you want to reference.
In the following example, we create a simple polygon and load it into the RulesDatabase as a reference feature:
// Open the database in read/write mode.
RulesDatabase db = new RulesDatabase();
db.open(false);
// Create a polygon using these coordinates
double[] xcoords = new double[]{-93.28504425760134, -93.28914266320392,
-93.28184399893699, -93.25426525140989,
-93.24244146407605, -93.24696669728736,
-93.26810267005514};
double[] ycoords = new double[]{44.99598347576073, 44.97599466749296,
44.96526126920738, 44.96573856680615,
44.98269977564994, 44.99491805950716,
45.00049357864552};
Polygon polygon = new Polygon2d(new LinearRing2d(xcoords, ycoords));
// Create a spatial feature by associating a name with the polygon
Feature feature = new SimpleFeature("exampleId", "rulesTarget",
"example label", polygon)
// Add the feature to the rule repository
db.addFeature(feature, true); //replaces an existing feature of this name.
//close the database
db.close();
A feature set
(com.objectfx.feature.FeatureSet) is a simple
collection that allows rule logic to be applied across a number of
reference features. A feature set is a named group of features that you
can reference in an expression so the rule logic is applied to all the
features in the group. For example, suppose you wish to monitor exit
conditions for each of the 50 U.S. states. Rather than writing 50
expressions, one for each state, you could create a feature set
containing all 50 state polygons with the exit condition using the
reference to the feature set.
![]() | |
|
If any features in a feature set overlap, a result target set will contain only one of the overlapping features even if there are multiple reference features involved in the evaluation. |
When the RulesService starts up, it reads the reference features in the feature set into memory. So, you can update the feature set contents while the RulesService is running, but you must refresh the RulesService to load the new set of reference features.
To use a feature set in an expression, you use a feature set
reference (com.objectfx.feature.FeatureSetRef)
and specify the ID of the feature set that you want to reference.
The following shows how to create a feature set and add it to the rules database:
// create a named feature set
FeatureSet featureSet = new FeatureSet("example feature set");
// Add spatial feature to the set
featureSet.add(new FeatureRef("exampleId"));
// Add featureSet in the rule repository
rulesDatabase.addFeatureSet(featureSet, false);
Dynamic features are the features that are submitted to
SpatialRules at runtime. Dynamic features differ from reference features
since they represent the state of the feature only at a specific point
in time called the captured date. The combination
of the dynamic feature's captured date and its geometry forms the
feature's location
(com.objectfx.rules.Location).
Below is an example of how to create a dynamic feature:
Map<String, Comparable> attributes = new HashMap<String, Comparable>();
attributes.put("speed", new Integer(0));
attributes.put("status", "green");
attributes.put("fuel", new Float(.85));
Location location = new Location(new Point2d(-93.27833, 44.98167), new Date());
new DynamicFeature("Twins Team Bus", "bus", attributes, location);
Expressions encode the conditions that you want to detect on your data stream. The subject of an expression is always the dynamic feature that was submitted, triggering the evaluation of the expression. The target of an expression is the feature or time period against which the subject is being compared. Some expressions like the clustering expression (Section 2.2.6, “Finding Clusters”) or the proximity expression (Section 2.2.5, “Detecting Proximity”) allow you to compare the subject against multiple targets. If an expression returns true, then the subject and all the targets against which the subject was compared will be available in the result (Chapter 4, Handling Output).
There are two basic types of expression: static and dynamic. Static expressions compare the subject's properties (usually the location) against relatively static values such as the location of a reference feature or a time period. On the other hand, dynamic expressions compare the subject's location to the locations of other dynamic features.
You can create expressions in Java or in an ObjectFX language called Script. Script is used to serialize expressions and other objects in SpatialRules. For example, if you export your Rules Database with DbAdmin (Section B.1.3, “dbadmin”), the output file will be written in Script. All of the examples in this section are written in Java, but you can find examples of all of the expressions in Appendix A, Script Reference.
If you choose to write your expressions using Script, the following
example illustrates how to use the Script Parser
(com.objectfx.script.parser.ScriptParser) to
convert the script into Java objects that can be added to the Rules
Database
String expression = "<expression in Script>"; List exps = ScriptParser.parse(expression, null);
To create a complete expression that you can add to the rules
database, you have to add your expression to an expression root
(com.objectfx.expression.ExpressionRoot). The
expression root takes only two parameters: a name that must be unique to
this expression root and the expression against which you want
SpatialRules to evaluate each dynamic feature.
For example, to create the simplest expression—one that would evaluate to true for every dynamic feature that was submitted to SpatialRules:
new ExpressionRoot("exp", BooleanExpression.TRUE);
Once your expression has been added to an expression root, it can be saved in Rules Database.
Expression roots can be disabled if you want to leave an expression in Rules Database but not have it active. Below is an example of how to disable an expression:
ExpressionRoot expression = db.getExpression("exp1");
expression.disable();
db.addExpression(expression, true);
The boolean operators allow you to combine multiple conditions into an expression. The boolean operators included in SpatialRules are:
and |
A binary operator that forms a logical
conjunction—its two operands must be true for it to return
true:
|
or |
A binary operator that forms a logical
disjunction—either of its two operands must be true for it
to return true:
|
not |
A unary operator that forms a logical negation—its
operand must return false for it to return true:
|
n of |
An n-ary operator that specifies a
cardinality—the number of operands that must return true
for it to return true:
|
For example, the following expression would return true whenever a dynamic feature with an attribute of "hazmatClass" whose value was 6 or 7 was at or within the boundary of one of the reference features in the feature set named "population centers":
new AndExp(new CoveredByExp(new FeatureSetRef("population centers")),
new OrExp(new Equals(new Property("hazmatClass"), new Literal(6)),
new Equals(new Property("hazmatClass"), new Literal(7))));
To test for direct interactions between features, SpatialRules provides both dynamic and static expressions for all supported geometry relations:
For example, the following expression would return true whenever a dynamic feature of type "weather" with an attribute of "windspeed" whose value was >= 25 intersected with any of the reference features in the feature set "cities":
new AndExp(new GreaterEquals(new Property("/weather/windspeed"),
new Literal(25)),
new IntersectsExp(new FeatureSetRef("cities")));
The enters
(com.objectfx.expression.leaf.EntersExp) and
exits (com.objectfx.expression.leaf.ExitsExp)
expressions allow you to detect when a dynamic feature enters or exits a
reference feature.
Enters is detected when a dynamic feature whose previous location was not within (as defined in Section C.2.3, “Contains/Within”) the reference feature but its current location report is. Exits is the inverse: the dynamic feature's previous location report was within the reference feature and its current location report is not.
![]() | |
|
Enters and exits both require at least two location reports for a dynamic feature. If the first report for a dynamic feature is within the reference feature, SpatialRules will not report an enters. Likewise, if the first report is outside the reference feature, it will not report an exits. |
To create an enters or exits expression, the only parameter you need is a reference to the reference feature or set:
new EntersExp(new FeatureSetRef("areas of interest"));
To detect when a dynamic feature is close to another feature, use
a close-to expression. If the other feature is a reference feature, you
use a static close-to expression
(com.objectfx.expression.leaf.CloseToExp); if
it's another dynamic feature, you use a dynamic close-to expression
(com.objectfx.expression.leaf.DynamicCloseToExp).
Both expressions take the following parameters:
distance |
A distance
( |
feature |
For static close-to expressions, a reference to a
reference feature
( |
For example, the following expression will return true any time a subject dynamic feature with an attribute of "cargotype" that has a value of "HAZMAT" comes within one mile of any of the features in the feature set "population centers":
new AndExp(new Equals(new Property("cargotype"),
new Literal("HAZMAT")),
new CloseToExp(
new Distance(1, LinearUnit.MILES),
new FeatureSetRef("population centers")));
The dynamic close-to expression can also take two additional parameters:
cardinality |
Specifies the number of targets that must be within the specified distance. |
timespan |
Specifies the maximum allowed time difference between the subject's captured date and the targets' captured date. |
For example, the following expression will return true any time a subject dynamic feature of type "A" is located within 50 kilometers of two dynamic features of type "B" whose location captured dates are no more than 30 minutes older than the captured date of the subject:
new AndExp(new Equals(new Property(Attributable.TYPE_ATTR),
new Literal("A")),
new DynamicCloseToExp(
new Distance(50, LinearUnit.KILOMETERS),
2,
new TimeSpan(30, TimeUnits.MINUTES),
new Equals(new Property(Attributable.TYPE_ATTR),
new Literal("B"))));
The cluster
(com.objectfx.expression.leaf.InClusterExp)
expression is closely related to the dynamic proximity expression: it
also looks for the specified number of dynamic features within a certain
distance, but it doesn't stop there. If it matches the distance and
cardinality constraints for the subject dynamic feature, it performs the
same test for each of the target features. If any of the target features
match the constraints, it continues on until it runs out of dynamic
features that meet the constraints. This set of features is the
cluster and the entire set can be included in the
result if you want it.
The cluster expression takes the following parameters:
distance |
Specifies the distance between the subject of the expression and the targets (i.e. dynamic features) |
cardinality |
Specifies the number of targets that must be within the required distance to create a cluster. |
resolve cluster |
Specifies whether all of the members of the cluster should be included in the set of targets in the result |
During evaluation of the cluster expression, any dynamic features that are found are put into one of three categories:
core member |
Any dynamic feature that meets the cardinality and distance constraints (has the specified number of features within the specified distance) is classified as a core object. |
border member |
Any dynamic feature that is found within the specified distance of a core member, but doesn't meet the cardinality constraint on its own, is classified as a border object and is considered part of the cluster. |
outlier |
Any dynamic feature that is not a core or border member and is classified as an outlier and is not considered part of the cluster. |
The figure below shows an illustration of a cluster with a cardinality of three.
The figure below shows how the number of features in a cluster jumps from three to five when the addition of a new dynamic feature changes an outlier into a border member of the cluster.
The number of features that are members of a cluster is limited to the number of connected (within the specified distance) core members plus any border members. Two clusters cannot be connected by common border members. For example, the figure below shows two different clusters that share a border member.
If you set the cardinality of the cluster to two you get any of the features that are within the specified distance of one another. In this case, there are no border members since any two features within the specified distance become core members as shown in the figure below.
To limit a cluster expression to a specific subset of the dynamic features, pair it with a comparator (Section 2.2.8.5, “Making Comparisons”) in an And expression:
new AndExp(new Equals(new Property(Attributable.TYPE_ATTR),
new Literal("cluster type")),
new InClusterExp(new Distance(5, LinearUnit.KILOMETERS), 4, false));
To restrict an expression to a specific period of time, use a
during expression
(com.objectfx.expression.leaf.DuringExp) that
references a period (see Section 2.6, “Creating Schedules and Intervals” for a
description of periods). The during expression will only return true if
the captured date of the dynamic feature is within the specified time
period.
For example, the following expression monitors an area of interest for activity only on the weekend:
new AndExp(new EntersExp(new FeatureRef("area of interest")),
new DuringExp(new PeriodRef("weekend")));
SpatialRules provides a set of expressions that allow you to compare values other than just the geometries of two features. The value expressions described in the following sections allow you to retrieve arbitrary values from features (Section 2.2.8.1, “Properties”), runtime variables (Section 2.2.8.3, “Variable References”), and literals (Section 2.2.8.2, “Literals”). The comparator expressions (Section 2.2.8.5, “Making Comparisons”) described at the end of this section describe the comparisons that you can make.
Property expressions
(com.objectfx.expression.value.Property)
retrieve values from the attributes of dynamic expressions. A property
expression takes only one parameter—the
path to the attribute to retrieve. The path
parameter uses an Xpath-like syntax to be compatible with [filter-encoding-spec]. There are two forms of the path
parameter that you can use. The first is a fully-rooted path that
scopes the property expression to dynamic features of the specified
type. If the type matches, the property expression will look for the
specified property and return the value:
new Property("/<type>/<attribute>");
The second form retrieves the value of the specified property from any dynamic feature:
new Property("<attribute>");
If there is no attribute with the specified name, then
null will be returned.
Literal values are added to expression trees by wrapping them
with the Scalar Literal
(com.objectfx.expression.value.Literal) class.
For example, the following statements create literals with date,
float, and string data types:
new Literal(new Date());
new Literal(2.71828);
new Literal("string value");
The supported literal types are:
integer/Integer
long/Long
double/Double
float/Float
String
Date (java.util.Date)
A Variable Reference
(com.objectfx.expression.value.VariableRef)
allows you to use variable values in expressions. For example, the
following variable reference would retrieve the value of the variable
named "THREAT_LEVEL":
new VariableRef("THREAT-LEVEL");
See Section 2.4, “Using Variables” for more details on creating and using variables.
For numerical values, the Math Operations class
(com.objectfx.expression.value.MathOp) provides
expressions for most of the Java math operations
(java.lang.Math). For example, the first
expression below would return the maximum value of its two operands
and the second would return the rounded integer of its
operand:
new MathOp.Max(new Property("weight"), new Literal(2000));
new MathOp.Rint(new Property("weight"));
The comparator expressions allow you to compare the values retrieved with the value expressions described above. The supported set of comparisons are listed below:
greater than |
Returns true if the left-hand value is greater than the right-hand value. new GreaterThan(new Literal(.25), new Property("/truck/fill"));
|
greater than or equal |
Returns true if the left-hand value is greater than or equal to the right-hand value. new GreaterEquals(new Literal(10000), new Property("altitude"));
|
equal |
Returns true if the left- and right-hand values are equal. new Equals(new VariableRef("alertStatus"), new Literal("red"));
|
less than or equal |
Returns true if the left-hand value is less than or equal to the right-hand value. new LessEquals(new Property("altitude"), new Literal(10000));
|
less than |
Returns true if the left-hand value is less than the right-hand value. new LessThan(new Property("/truck/fill"), new Literal(.25));
|
is like |
Returns true if the left-hand value contains the string specified by the regular expression specified in the right-hand value. new IsLike(new Property("zipCode"), new Regex("^554[0-9]{2}"));
|
is in |
Returns true if the left-hand value is in the collection specified in the right-hand value. Set<String> watchList = new HashSet<String>();
watchList.add("id1");
watchList.add("id2");
new IsIn(new Property("id"), new Literal(watchList));
|
![]() | |
|
Comparisons can only be made with like data types. Comparing a string to a date value or a double to an integer value will result in an exception. |
If you need to monitor the number of features that are within an
area for example, you can use the counting expressions: count less than
(com.objectfx.expression.leaf.CountLessThanExp)
and count greater than
(com.objectfx.expression.leaf.CountGreaterThanExp).
Both expressions take the following parameters:
count |
Is the number of features that the count must exceed or fall below for the expression to be true. |
relation expression |
A static relation expression (see Section 2.2.3, “Testing for Geometric Relationships”) to specify the spatial relationship that the subject features must have with the target to be counted. |
time span |
An optional time span that limits the count to a time window. Only those features whose captured date is on or after the date of the most recent feature's captured date minus the time span will be included in the count. |
feature discriminator |
A boolean expression used to restrict the count to only those dynamic features that match the given expression. |
add to targets |
A boolean value specifying whether all of the features should be added to the target set when the expression evaluates to true. If you don't need the features or the count is such a high value that reporting all of the features would be problematic, set this value to false. |
To monitor for a critical mass scenario, for example, you can use a count greater than expression to alert you when there are more than 50 dynamic features of "monitored type" at least in contact with a "monitored area":
Equals isType = new Equals(new Property(Attributable.TYPE_ATTR),
new Literal("monitored type"));
IntersectsExp intersects = new IntersectsExp(new FeatureRef("monitored area"));
CountGreaterThanExp countGt = new CountGreaterThanExp(50, intersects, null, isType, true);
If you only want a count expression to report once when the threshold was crossed, create a pair of count expressions and place them in a state transition expression (see Section 2.2.10, “Detecting Sequences of Events”). The following example creates a state transition expression that monitors an area for a count greater than 50:
CoveredByExp coveredBy = new CoveredByExp(new FeatureRef("monitored area"));
CountGreaterThanExp countGt
= new CountGreaterThanExp(50, coveredBy, null, BooleanExpression.TRUE, false);
CountLessThanExp countLt
= new CountLessThanExp(40, coveredBy, null, BooleanExpression.TRUE, false);
List<TransitionExp> transitions = new ArrayList<TransitionExp>();
transitions.add(new TransitionExp("exceeded count", countGt));
transitions.add(new TransitionExp("fell below count", countLt));
StateTransitionExp stateTransition = new StateTransitionExp(transitions);
Once the expression has evaluated to true, it will not be tested again until after the count has fallen below 40 (when the count less than expression evaluates to true). Using a lower value for the count less than expression eliminates any jitter.
To detect a specific sequence of events or just to temporarily
disable an expression once it has evaluated to true, you can use a state
transition expression
(com.objectfx.expression.state.StateTransitionExp).
State transition expressions take a list of named expressions called
transitions
(com.objectfx.expression.state.TransitionExp).
Only one of the transitions in the list will be evaluated at a time.
When a transition evaluates to true, its ID will be added to the result
and the next transition in the list will be the one whose expression is
evaluated.
For example, when SpatialRules starts up, the state transition expression marks the first transition in the list as the active transition. SpatialRules will use only the active transition to evaluate dynamic features:

Once the first transition evaluates to true, the second transition is marked as the active transition and all dynamic features are now evaluated against it:

When the second transition evaluates to true, the third transition is marked as the active transition:

When the final transition in the list has evaluated to true, SpatialRules moves the active transition mark back to the first expression in the list to restart the cycle:

A common use for the state transition expressions is with the count expressions (Section 2.2.9, “Tracking Counts”).
SpatialRules allows you to store and reference portions of expressions called fragments. A fragment is a logic statement that can be reused across a number of expressions. Fragment definitions by themselves are not evaluated. They must be referenced from a complete expression (ExpressionRoot) for evaluation to take place.
The following example shows how a rule fragment can be constructed using Java and applied to two rules. The fragment determines if any dynamic feature is within 50 meters of any other dynamic feature.
BooleanExpression proximity =
new DynamicCloseToExp(new Distance(50,
LinearUnit.METERS,
DistanceType.GREAT_CIRCLE),
BooleanExpression.TRUE);
ExpressionFragment frag =
new ExpressionFragment("fragment-example", proximity);
rulesDatabase.addExpressionFragment(frag, false);
The proximity fragment above is then applied to a rule looking for when HAZMAT vehicles are within 50 meters of one another.
Equals eq1 = new Equals(new Property("Restrictions"), new Literal("HAZMAT"));
FragmentRef fragmentRef = new FragmentRef("fragment-example");
AndExp exp1 = new AndExp(eq1, fragmentRef);
ExpressionRoot rule1 = new ExpressionRoot("exp-root1", exp1);
rulesDatabase.addExpression(rule1, false);
The same fragment is then applied to another rule looking for when objects on a WATCH-LIST are within 50 meters of one another.
Equals eq2 = new Equals(new Property("Status"), new Literal("WATCH-LIST"));
AndExp exp2 = new AndExp(eq2, fragmentRef);
ExpressionRoot rule2 = new ExpressionRoot("exp-root2", exp2);
rulesDatabase.addExpression(rule2, false);
In some cases, you might want to be able to adjust the value that an
expression is looking for at runtime without having to change the rule and
refresh RulesService. To support this, SpatialRules contains another
resource called a variable
(com.objectfx.expression.value.Variable). To create
a variable, you only need to create a new variable instance with a name
and an initial default value and add it to the rules database. The
variable can then be referenced in a rule during property comparisons or
calculations using a VariableRef
(com.objectfx.expression.value.VariableRef).
The value of a variable can be changed programmatically through the RulesService instance at runtime. The following example shows how to create a variable called "THREAT-LEVEL". The values correspond to the Department of Homeland Security threat levels:
Green
Blue
Yellow
Orange
Red
First, create the variable named "THREAT-LEVEL" with an initial value. This variable definition must be added to the rules database:
Variable var = new Variable("THREAT-LEVEL", "GREEN");
rulesDatabase.addVariable(var, false);
Next, create an expression. One part of the expression detects any dynamic features near another feature of type "hot-spot".
DynamicCloseToExp proximity =
new DynamicCloseToExp(new Distance(50, LinearUnit.METERS),
new Equals(new Literal("hot-spot"),
new Property(Attributable.TYPE_ATTR)));
The rest of the rule checks to see if an attribute called "THREAT-LEVEL" is either "ORANGE" or "RED".
BooleanExpression threatLevel = new OrExp(
new Equals(new VariableRef("THREAT-LEVEL"), new Literal("ORANGE"));
new Equals(new VariableRef("THREAT-LEVEL"), new Literal("RED")));
AndExp exp = new AndExp(proximity, threatLevel);
ExpressionRoot rule = new ExpressionRoot("proximity-and-threat", exp);
rulesDatabase.addExpression(rule, false);
To alter the variable's value at runtime, reference the RulesService
instance and call the setVariable() method. The
following example sets the value to "ORANGE".
rulesService.setVariable("THREAT-LEVEL", "ORANGE");
SpatialRules has the ability to collect history on dynamic features
that match specified criteria and submit that history as a new dynamic
feature using the MakeTrack
(com.objectfx.rules.track.MakeTrack) directive. The
extent of the history is controlled by either specifying a time range or a
count of dynamic feature reports.
A MakeTrack directive requires five parameters:
prefix |
The unique name or ID for this MakeTrack that also becomes the prefix for the ID of the track. This prefix is prepended onto the ID of the dynamic feature that is being tracked. |
submit original |
A boolean value that specifies whether the dynamic feature should also be submitted to the Rules Service (true) or used only for creating a track (false) then discarded. |
min |
The minimum number of location reports that are required to constitute a track or the minimum time span (the amount of time between the newest and oldest location reports for a feature). |
max |
The maximum number of location reports that can be in a track or the maximum time span (the amount of time between the newest and oldest location reports for a feature). |
feature selector |
A boolean expression that selects the features to be tracked. |
The minimum parameter indicates how much data is required for SpatialRules to form a track. For example, specifying a minimum of 10 means SpatialRules will not begin submitting tracks for evaluation on a dynamic feature until at least 10 locaiton reports for the dynamic feature are reported. Specifying 10 minutes means that the time between the captured dates for at least two dynamic features is greater than 10 minutes.
Tracks with a minimum count start forming when the min is reached. Subsequent reports are added to the track until the max is reached. The track is maintained with the max count, removing the oldest locations. Tracks with a minimum time start forming only when the time difference between the most recent and the oldest reports exceeds the minimum time. The oldest reports are only trimmed from the track when the difference between them and the most recent exceeds the maximum time. Thus MakeTracks that use time constraints are potentially subject to much greater variance in the number of reports that are actually in the track.
![]() | |
|
Regardless of whether time or a count is used for the minimum a track must be composed of two or more dynamic features (i.e., tracks of one are not allowed). |
The table below illustrates the differences between the elements in a track using a min/max count vs. a min/max time.
Table 2.1. Comparison of MakeTrack with count vs. time
| Report # | Captured Date | Track Contents | |||
|---|---|---|---|---|---|
| Count | Time (minutes) | ||||
| min = 2 | max = 5 | min = 10 | max = 60 | ||
| 1 | 12:00:00 | {} | {} | ||
| 2 | 12:06:00 | {1, 2} | {} | ||
| 3 | 12:11:00 | {1, 2, 3} | {1, 2, 3} | ||
| 4 | 12:21:00 | {1, 2, 3, 4} | {1, 2, 3, 4} | ||
| 5 | 13:01:00 | {1, 2, 3, 4, 5} | {2, 3, 4, 5} | ||
| 6 | 13:02:00 | {2, 3, 4, 5, 6} | {2, 3, 4, 5, 6} | ||
| 7 | 13:03:00 | {3, 4, 5, 6, 7} | {2, 3, 4, 5, 6, 7} | ||
| 8 | 13:05:00 | {4, 5, 6, 7, 8} | {2, 3, 4, 5, 6, 7, 8} | ||
| 9 | 14:06:00 | {5, 6, 7, 8, 9} | {} | ||
The min and max values can also be a mix of count and time. The following shows an example that declares a min value of 2 (count of 2 reports) and a max of 2 hours of history. This MakeTrack matches on any dynamic feature containing a property named "MaterialType" that has a value "HAZMAT".
BooleanExpression hazmatVehicles = new Equals(new Literal("HAZMAT"),
new Property("MaterialType"));
final TimeSpan maxTime = new TimeSpan(2, TimeUnits.HOURS);
MakeTrack hazmatTrack = new MakeTrack("HAZMAT-", false, 2, maxTime, hazmatVehicles);
The dynamic features created by MakeTrack are DynamicFeatureTrack instances whose geometry is always a linestring. MakeTrack can be used with features of any supported geometry type, however, only the centroid of the geometry is used to create the track.
It is important to understand that MakeTrack manufactures and maintains a dynamic feature that is derived from the actual dynamic feature submitted to SpatialRules. When a track is submitted, it will have all of the attributes of the most recent report used in the track. Only the ID and the geometry will be different—the ID will have the MakeTrack prefix prepended and the geometry will be the linestring of the track.
Tracks are useful for detecting when objects cross linear objects such as boundaries. For example, in the figure below, a MakeTrack could be paired with an intersection expression to detect when a dynamic feature has crossed a river.
Tracks are also useful to detect when a dynamic feature crosses the path of another. For example, in the figure below, a MakeTrack could be paired with a close to expression to detect when a ship approaches the path that a previous ship has taken.
Schedules and intervals are specified as periods
(com.objectfx.rules.time.Period). A period may
cover a fixed interval with a start date/time and end date/time or a
recurring schedule. For fixed periods a Java Date
(java.util.Date) object is used to define the start
and end of the period. A fixed time period may also be open-ended on one
end. This allows for specifying a period that begins as of a date or ends
as of a date.
To create a period with a fixed range from December 16, 2005 at 12:00 to December 19, 2005 at 18:00:
new Period(DateUtils.createDate("2005-12-16 12:00:00:000 GMT"),
DateUtils.createDate("2005-12-19 18:00:00:000 GMT"));
A period starting December 16, 2005 12:00 (Pacific Daylight Time) and continuing infinitely into the future:
new Period(DateUtils.createDate("2005-12-16 12:00:00:000 PDT"), null);
A period that includes anything before December 19, 2005 up to 18:00 (Central Standard Time):
new Period(null, DateUtils.createDate("2005-12-19 18:00:00:000 CST"));
Schedules or recurring periods offer the ability to monitor
schedules such as weekdays, weekends, every Monday and so forth. The
RecurringTime class
(com.objectfx.rules.time.RecurringTime) represents
the repeating aspects of the period.
An instance of RecurringTime can describe a day-of-week, day-of-month, month-of-year, hour, or minute. At runtime, the rule engine processes recurring times using GMT as the time zone basis. This means that location reports of 16:00 CST (GMT-6) and 14:00 PST (GMT-8) represent the GMT equivalent (they are both specifying 22:00 GMT).
Each component of a recurring time period is represented with an integer (such as Sunday is day 1, Wednesday is day 4 and so forth). The following table shows the ranges for each recurring time component:
Minute |
0-59 |
Hour |
0-23 |
Day of Week |
1-7, where Sunday=1 |
Day of Month |
1-31 |
Month of Year |
0-11; where January=0 |
In cases where the time component should be ignored, null is used. Below are some examples of creating recurring periods:
To create the period from 7:00 AM through 2:59:59 PM daily:
new Period(new RecurringTime(null, "7", null, null, null),
new RecurringTime(null, "14", null, null, null));
The weekday time period from 12:00 AM Monday through 11:59:59 PM Friday:
new Period(new RecurringTime(null, null, "2", null, null),
new RecurringTime(null, null, "6", null, null));
The weekday time period from 7:00 AM Monday through 1:59:59 PM Friday:
new Period(new RecurringTime(null, "7", "2", null, null),
new RecurringTime(null, "13", "6", null, null));
The weekend time period from Saturday, hour 0 through Sunday 11:59:59 PM:
new Period(new RecurringTime(null, null, "7", null, null),
new RecurringTime(null, null, "1", null, null));
Monday from hour 0 through 11:59:59 PM:
new Period(new RecurringTime(null, null, "2", null, null),
new RecurringTime(null, null, "2", null, null));
The period from the 7th day of each month through the 15th day of each month:
new Period(new RecurringTime(null, null, null, "7", null),
new RecurringTime(null, null, null, "15", null));
The period from January 1 at midnight through May 31 at 11:59:59 PM:
new Period(new RecurringTime(null, null, null, null, "0"),
new RecurringTime(null, null, null, null, "4"));
When you create a recurring period, the RecurringTime instances must both specify the same time slots. For example, you cannot create a period where the start is 6:00 AM and the end time is Monday.
In order to make an expression available to SpatialRules, the
expression must be added to the Rules Database
(com.objectfx.rules.database.RulesDatabase) where
all of the components of SpatialRules expressions are stored. When Rules
Service starts up, it reads all of the enabled expressions and any
referenced components from the Rules Database and loads them into
memory.
To create an instance of Rules Database, you can use the no-arg
constructor and Rules Database will read its configuration properties from
the rules.properties file (or use its defaults if
none are specified in the properties file). Or you can pass it a
properties (java.util.Properties) instance
containing the configuration properties that you want to set. See Section 5.2, “Database Configuration” for a list of all the configuration properties. For
example:
// Use either defaults or properties from rules.properties file RulesDatabase defaultDb = new RulesDatabase(); // Use a locally defined set of properties Properties myProps = new Properties(); myProps.setProperty(RulesDatabase.DB_PATH_PROP_NAME, "/home/me"); RulesDatabase myDb = new RulesDatabase(myProps);
To open the Rules Database, call the open()
method:
rulesDatabase.open(false);
The boolean parameter is used to specify whether or not the database should be opened in read-only mode. In the example above, the database is opened in read-write mode.
Once the database has been opened, you can add your expression:
rulesDatabase.addExpression(enterExpression, true);
The first parameter is the expression. The second parameter is a boolean that tells Rules Database whether or not to replace the existing version of the expression if it already exists. If this parameter is false and the expression already exists in the database, an exception is thrown.
Methods for adding, retrieving, updating, and deleting all expression components are included in the Rules Database API (see the API documentation for a complete listing of methods).
Finally, if you are through accessing the Rules Database, you must close it:
rulesDatabase.close();
![]() | |
|
You must call |
Rules Database can also be accessed remotely through Rules Server by
creating an instance of the Rules Admin Client
(com.objectfx.rules.server.client.admin.AdminClient)
and connecting it to a Rules Server. See the Rules Admin Client API
documentation for details of its API.
Table of Contents
SpatialRules is a modular, highly-configurable application. In its default, out-of-the-box configuration, it is set up to support high-volume use cases running as a stand-alone application. Dynamic features are submitted to it from remote hosts and any results are submitted to a message queue or external database. At the other extreme, just two of the components—Rules Service and Rules Database—are all that is required to give any application the ability to detect the spatiotemporal conditions described in Chapter 2, Creating Rules. The default SpatialRules configuration is illustrated in the figure below.
Some of the SpatialRules components are inactive by default.
Configuration properties in the rules.properties file
are used to activate them when needed.
The spatialrules.[sh|cmd] scripts located in
<install_dir>/bin will start up SpatialRules in
its default configuration. The included source for the SpatialRules class
located in <install_dir>/examples/SpatialRules.sh
shows how all of the SpatialRules components are managed for this
configuration.
The following sections provide an overview of each of the components in the figure above.
Rules Service
(com.objectfx.rules.RulesService) is the active,
runtime core of SpatialRules that performs the rule evaluations. Multiple
instances of RulesService can be created to run within a single JVM or
application. This allows for running multiple Rules Service instances that
contain different rules.
To create a new Rules Service, you must give it a Rules Database as
the source for its expression components. For example, to create a new
Rules Service where the Rules Database gets all of its configuration
parameters from the rules.properties
file:
RulesService rulesService = new RulesService(new RulesDatabase());
To start the Rules Service, just call the open() method. Rules Service will then read all of the enabled expressions from the Rules Database and initialize all of its indices:
rulesService.open();
If you make any changes to the Rules Database after opening the Rules Service, you will need to call the refresh() method to have Rules Service load the changes:
rulesService.refresh();
To submit dynamic features directly to the Rules Service, you can
either pass an instance of Result Handler
(com.objectfx.rules.results.ResultHandler) to the
submit() method to have any results passed on to it.
Or you can get a list of results back directly by just passing the dynamic
feature:
// Results passed to the result handler rulesService.submit(dynamicFeature, resultQueue); // Results returned directly List<Result> results = rulesService.submit(dynamicFeature);
To change the values of any variables that are used in any of your
expressions, just call the setVariable()
method:
rulesService.setVariable("myVar", new Integer(42));
And, when you are through using Rules Service, call the
close() method:
rulesService.close();
In its default operating mode as described above, dynamic features
are submitted to SpatialRules via an Input Client
(com.objectfx.rules.server.client.input.InputClient)
connected to a Rules Server
(com.objectfx.rules.server.RulesServer). Rules
Server is a dedicated server implementation for receiving dynamic features
and administrative commands from remote clients. As features are received,
they are placed into a configurable FIFO queue for submission to the Rules
Service. Administrative commands submitted by an Admin Client
(com.objectfx.rules.server.client.admin.AdminClient)
are submitted directly to the Rules Service or its attached Rules
Database.
To create a Rules Server instance:
ServerConfig config = ServerConfig.fromProperties(); RulesServer server = new RulesServer(config, rulesService);
The Server Config
(com.objectfx.rules.server.ServerConfig) above can
read the configuration parameters defined in the
rules.properties file or it can be configured
programmatically. The configuration parameters are:
hostname |
The name of the host on which the server should open a socket. The default is no host, i.e., all interfaces on the current host. |
port |
The port number on which the server should listen for client connections. The default is 10253. |
max connections |
The maximum size of the server's thread pool for processing input client requests, i.e., the maximum number of input connections that can be made to the server. The value must be greater than 0 and greater than or equal to the minimum number of threads. The default is 10. |
minimum threads |
The number of threads the server will always keep ready to handle a new client connection. The default is one. |
socket timeout |
The length of the timeout value for connections in milliseconds. If the client does not send anything for a period of this length, the connection will be closed. A value of zero disables timeouts. The default is 30000 (30 seconds). |
receive buffer size |
The size of a server socket's receive buffer in bytes. The default is 65536 (64k) |
use TCP_NODELAY |
Set TCP_NODELAY on the server's sockets. Refer to your operating system documentation for details. The default is false. |
Once instantiated, you only need to call
startup() on the instance. When
isReady() returns true, the Rules Server is ready to
accept connections. When done, just call
shutdown().
To connect to a Rules Server and submit dynamic features, you only need to create an Input Client instance, call open() on it, and submit your features:
InputClientConfig config = new InputClientConfig("MyExample");
config.setServerHost("host");
config.setServerPort(10253);
config.setConnectionType(ConnectionType.ASYNC);
InputClient client = new InputClient(config);
client.open();
InputResult inputResult = client.sendFeature(dynamicFeature);
if (inputResult.isError()) {
System.err.println(inputResult.getErrorMessage());
}
The configuration properties for an Input Client are:
name |
A name for the client connection. The name doesn't need to be unique, but it will be used for monitoring on the server. |
server host |
The host name of the server to which to connect. |
server port |
The port on the server where Rules Server is listening for connections. |
connection type |
The type of connection to make. For input clients, only two
choices are available: an |
When you are through submitting features to the server, call
close() on the input client to close the
connection.
The InputProcessor
(com.objectfx.rules.input.InputProcessor) is the
root of a chain of pre-processing steps for dynamic features submitted to
Rules Service. Input Processor is a Primary Submitter
(com.objectfx.rules.input.PrimarySubmitter) that
manages the life cycle of a submitter tree. In addition to forwarding
dynamic features to all of its children, it:
loads (if not provided as a parameter) the submitter tree
specified by the
rules.inputprocessor.submitter.<n>
properties in the rules.properties file.
cascades open() and
close() calls to all descendant
submitters.
creates (if not provided as a parameter), opens, and closes an Input Processor Database if required by one of the descendant submitters.
collects up all the Data Maintainers from the descendant submitters.
An Input Processor can be used together with RulesService by adding Rules Service as one of the descendants in the submitter tree. Or it can be used separately by adding a Forwarder to the submitter tree to forward dynamic features on to the machine where a Rules Service instance is running.
If you are using the default SpatialRules configuration, you must set the rules.primary property to enable the Input Processor:
rules.primary=InputProcessor
The Submitter interface
(com.objectfx.rules.input.Submitter) allows you
to create a chain of pre-processing steps through which a feature must
pass before being passed on to Rules Service for evaluation.
Pre-processing steps could include:
filters that selectively discard location reports based on
properties, for example, the provided Recency Filter
(com.objectfx.rules.input.RecencyFilter)
implementations that discards out-of-sequence location
reports.
enrichment steps that use data from external sources to supplement the attributes that are on an initial location report.
routers that submit location reports down different paths based on their properties.
To create a pre-processing step, you create an implementation of the Submitter interface and add it as a descendant of Input Processor. As a simple example, if you wanted to ensure that any out-of-sequence features submitted to the Rules Service were discarded, you would just add a Recency Filter to the pre-processing chain before Rules Service:
// Create a new RulesService--the end of the chain RulesService rulesService = new RulesService(new RulesDatabase()); // Then add it as a child to a RecencyFilter. List rulesServiceList = new ArrayList(); rulesServiceList.add(rulesService); RecencyFilter recencyFilter = new MemoryRecencyFilter(rulesServiceList); // In turn, add the recency filter as a child to InputProcessor. // InputProcessor will cascade the open() and close() calls for you. List recencyFilterList = new ArrayList(); recencyFilterList.add(recencyFilter); InputProcessor inputProcessor = new InputProcessor(recencyFilterList); inputProcessor.open();
Recency Filters discard any location report that they receive out of sequence, i.e., one whose captured date is older than the captured date on a previous report for the same feature ID. If the location report is more recent than the last report, a Recency Filter will pass it on to Rules Service.
In the example above, only one child was added to each parent to form a single chain. However, submitters can have multiple children, allowing you to create a tree of pre-processors if you need to. If, for example, you wanted to keep a history of all submitted features, you could create your own Submitter implementation that sends every feature it receives off to be stored in a database. Then all you need to do is add it as an additional child of Input Processor to receive all of the submitted location reports.
To close the Input Processor and all of its descendant submitters,
just call the close() method:
inputProcessor.close();
To add a submitter chain to the default SpatialRules configuration, you'll need to use the rules.inputprocessor.submitter.<n>.<p> property. This is a repeating property where the final two segments of the field change for each instance.
The syntax for this property is as follows:
rules.inputprocessor.submitter.<n>.<p>=<classname>[,<param>]*
where
n |
An integer that starts at 1 for the first submitter and increments by one for each subsequent submitter. If there is a gap in the sequence an IllegalArgumentException will be thrown. |
p |
An integer less than n that identifies the submitter that will be the parent of this submitter (the n value of a previous entry. If p is less than n an IllegalArgumentException will be thrown. |
classname |
The fully qualified name of a class implementing the
|
param |
Optional parameters to the constructor of classname. They will be be passed in to the constructor as a string array. |
For example, to create a simple submitter chain that looked like this:

you would add something like the following properties to your rules.properties file:
rules.primary=InputProcessor rules.inputprocessor.submitter.1.0=your.package.FeatureRecorder,arg1,arg2 rules.inputprocessor.submitter.2.1=com.objectfx.rules.input.MemoryRecencyFilter rules.inputprocessor.submitter.3.2=com.objectfx.rules.RulesService
But if you wanted to create something with a tee like the figure below where the feature recorder is on its own branch instead of upstream from the Rules Service:

you would change just change the parent ID of the property entry for the Recency Filter:
rules.primary=InputProcessor rules.inputprocessor.submitter.1.0=your.package.FeatureRecorder,arg1,arg2 rules.inputprocessor.submitter.2.0=com.objectfx.rules.input.MemoryRecencyFilter rules.inputprocessor.submitter.3.2=com.objectfx.rules.RulesService
Input Processor Database is a data store for all ObjectFX provided
Submitter implementations. Currently, the only submitter using the Input
Processor Database is the Disk-based Recency Filter
(com.objectfx.rules.input.DiskRecencyFilter)
which uses the database as a non-persistent, disk-based cache.
Input Processor database has the same configuration properties as other SpatialRules databases as described in Section 5.2, “Database Configuration”
Rules Runtime Database is a disk-based cache for some of the SpatialRules internal indexes. Its primary purpose is to support memory-intensive applications that can tolerate some reduction in throughput as index data is written to disk instead of being kept in memory.
Since it is only used as a cache, Rules Runtime Database doesn't have a public API and the data in it is non-persistent. However, it does have the same configuration properties as other SpatialRules databases as described in Section 5.2, “Database Configuration”
Rules Runtime Database is inactive by default. To enable it, you specify which index types you want written to disk. For example, to have the indexes for the enters and exits expressions written to disk[1]:
rules.index.diskbased=ENTERS_EXITS
During operation, Rules Service maintains information in memory about the dynamic features that have been submitted to it. The amount and type of information depends entirely on the expressions that are active. If your application is working with dynamic featues that have a limited life-cycle[2], you will need to adopt a strategy for aging data—a set of critieria for determining when a dynamic feature is stale, i.e., no longer considered current. If your strategy is the straightforward case of any dynamic feature beyond a certain age is stale, then you should be able to use the provided aging tools described in the next section. For more complex criteria, you will have to implement a custom aging solution as described in Section 3.5.2, “Custom Aging”.
SpatialRules provides a built-in data aging mechanism that is
configurable through the rules.properties file
using the three properties listed below:
rules.cleaner.maxage |
The property rules.cleaner.maxage specifies (in minutes) what the maximum acceptable age for a dynamic feature is. For example, the following setting would remove data that is an hour or more old. rules.cleaner.maxage=60 If a dynamic feature has not been updated for more than an hour it will be removed and no longer be available for rule evaluations. If this property is not set no aging takes place. |
rules.cleaner.checkinterval |
The property rules.cleaner.checkinterval specifies (in minutes) how often to check for stale data. The default is every 15 minutes, For example, the following specifies that data should be checked every 30 minutes: rules.cleaner.checkinterval=30 |
rules.cleaner.loginterval |
If aging is enabled, the Rules Service will log the IDs of any features that were removed from the system. The property rules.cleaner.loginterval specifies how long (in minutes) to wait between checks for aging results. The default is an interval four times longer than the check interval. The following specifies an interval of four hours. rules.cleaner.loginterval=240 |
If the default aging mechanism doesn't offer the level of control that your application requires, SpatialRules provides the necessary interfaces and tools for you to add your own aging code and have it run periodically.
The RulesService.getDataMaintainers() method
returns a collection of Data Maintainer
(com.objectfx.rules.maintainer.DataMaintainer)
instances. The Data Maintainer interface provides the methods to inspect
and remove dynamic features from SpatialRules. Maintainers provide
access to all of the dynamic features currently known and managed by
SpatialRules. There may be a number of maintainers for a specific Rules
Service instance. Each maintainer corresponds to different types of
expression categories. For example, the
enters-exits category refers to enter and exit
expressions whereas the proximity category refers
to closeTo types of expressions. A list of categories is found in the
API documentation for the Data Maintainer interface.
The number of maintainers and the number of dynamic feature references within the maintainers is subject to change depending on the data submitted to SpatialRules and the types of expressions currently loaded. For example, if there are no enter or exit expressions loaded there will be no maintainer with a category of enters-exits.
Each maintainer provides access to a set of Dated ID (com.objectfx.rules.maintainer.DatedId) objects. A dated ID contains the ID and timestamp of the dynamic feature. SpatialRules does not fully catalog all data submitted for evaluation. For example, attributes and type information may not be kept. As a result, only the ID and timestamp are available through the maintainer. If your aging strategy requires access to the attributes of the dynamic feature, you will have to look up the dynamic feature in an external data source that maintains the most current dynamic feature.
The following code example shows how to access maintainers and delete dynamic features from SpatialRules.
for (DataMaintainer maintainer : rulesService.getDataMaintainers()) {
System.out.println("Category: " + maintainer.getExpressionCategory());
try {
while (maintainer.hasNext()) {
DatedId id = maintainer.next();
if (isTooOld(id)) {
System.out.println(" Removing ID: " + id.getId()
+ " Captured Date: " + id.getCapturedDate());
maintainer.remove();
}
}
} finally {
maintainer.close();
}
}
Table of Contents
As data is processed, any expressions that evaluate to true produce
a result (com.objectfx.rules.results.Result).
Results have four properties:
Expression Name |
The name of the expression that evaluated to true. |
Subject |
The dynamic feature used to trigger the rule evaluation. |
Target Set |
The set of targets involved in evaluating the rule. A target might be a reference to a reference feature (or set), a dynamic feature, a dynamic track feature, or a reference to a period. A target set might include a mix of types depending on the expression. |
Date |
The timestamp when the result was created. |
The result is then passed to a result handler
(com.objectfx.rules.results.ResultHandler)
implementation. Result handlers are described in the next section.
When Rules Service creates a result, it passes it to a result
handler (com.objectfx.rules.results.ResultHandler)
implementation. The result handler is responsible for submitting the
result to it final destination. There are only two result handler
implementations provided with SpatialRules—Result Publisher and
Result Queue—both of which are described below. If neither of these
works for your application, you will have to create your own
implementation.
If you are calling an instance of Rules Service directly from within
your own code, just pass your result handler implementation to the
RulesService submit(DynamicFeature, ResultHandler)
method. Any results that RulesService creates will be passed to your
result handler. If you are customizing the
SpatialRules.java file, you'll need to pass an
instance of your result handler implementation to the Primary Submitter
Executor
(com.objectfx.rules.PrimarySubmitterExecutor)
constructor.
The following UML diagram shows the result handler hierarchy:

The Result Publisher
(com.objectfx.rules.results.ResultPublisher) and
Result Queue
(com.objectfx.rules.results.ResultQueue) are
implementations of
com.objectfx.rules.results.SubscriptionResultHandler—result
handlers that distribute results based on subscriptions. To receive
results from the Result Publisher or Result Queue, you create an
implementation of a Result Listener (described below) and then subscribe
to the results of an expression.
To subscribe a listener, call the subscribe(String,
ResultListener) method on the handler. The first argument is
either the name of the expression to which you want to subscribe or the
string "AllExpressions" if you want the results of all expressions to be
published to this listener. A listener can be subscribed to any number of
expressions and any number of listeners can be subscribed to an
expression.
To add a listener via properties, add an entry to the
rules.properties file with the following
format:
rules.resultlistener.<n>=<classname>,<expression name>[,<arg>]*
where
n |
Is an integer that starts at 1 for the first result listener and increments by one for each result listener. If there is a gap in the sequence, any listeners after the gap will not be loaded. If there are duplicate entries, the last entry listed wins. |
classname |
Is the fully qualified name of a class implementing the
|
expression name |
Is the name of the expression to whose results this listener is subscribing. Use "AllExpressions" to subscribe to all expressions. |
arg |
Is an optional parameter to the constructor of classname. Parameters will be be passed in as a string array. |
When the handler starts up, it will read the listener properties, instantiate the specified classes, and subscribe them to the specified expressions.
To unsubscribe a listener, call the unsubscribe(String
expressionName, ResultListener listener) method on the handler.
The first argument is either the name of the expression to which you want
to subscribe or the string "AllExpressions". Note that if you subscribed
the listener using "AllExpressions" as the expression name, you must
unsubscribe using the same string. You cannot subscribe to
"AllExpressions" and then unsubscribe from inidividual expressions.
By default, SpatialRules uses the Result Queue to publish results.
The Result Queue publishes asynchronously. Its
handle() method places the results in a blocking
queue instead of publishing them, allowing the calling thread to return. A
configurable thread pool monitors the blocking queue and publishes the
results to the listeners as they are received.
The Result Publisher publishes results synchronously. When its
handle() method is called, the results are published
to all subscribed listeners using the calling thread.
The figure below provides an overview of a Result Publisher or Queue publishing results to external systems via listeners.
A result listener
(com.objectfx.rules.results.ResultListener)
implementation forms the connection between SpatialRules and an external
service such as an alerting service or data store. There are only three
methods to implement on the Result Listener interface:

The open() and close()
methods are used to manage external resources such as JMS or JDBC
connections. When the Result Queue starts up, it calls the
open()method on all of the subscribed result
listeners. If the Result Queue is already started when the listener is
subscribed, it will call the open() method on it
before adding it. When the Result Queue is shut down, it calls
close() on all subscribed listeners.
The receive() method is called on the result
listener whenever the Result Queue receives a result to which the listener
is subscribed.
Table of Contents
SpatialRules uses three thread pools and two queues to manage the flow of dynamic features through the application. Each thread pool and queue has its own configuration options.
The figure below shows the location of the thread pools and queues in a typical SpatialRules deployment.
The Connection Thread Pool is used to service incoming connection requests from Input and Admin clients. It is the only dynamically sized thread pool with a new thread allocated for each incoming connection. Idle threads from terminated connections are shut down after a period of time if no new incoming request comes in.
The only configuration property for the Connection Thread Pool is rules.server.input.maxconnections. This property allows you to restrict the number of clients that can connect to the Rules Server. The default value is 10.
Connection threads use very little CPU when receiving dynamic features, so adjust the maximum thread count to suit your needs. For example, if you have a lot of short-term connections with spiking volumes, you may need to increase it to 100 or more to allow for the spikes in traffic. On the other hand, you might want to throttle down the spikes by disallowing connections if the total throughput is close to overloading the host machine.
The Submitter Thread Pool contains the threads that take dynamic features from the Input Queue and submit them to the Input Processor/Rules Service.
The only configuration property for the Submitter Thread Pool is rules.primary.threads. The default value is one.
Submitter threads generally have the most CPU intensive tasks including rule evaluation and reads/writes to the Input Processor and Rules Runtime Databases. In most cases, you should allocate one submitter thread for every CPU core on the host machine for best performance.
The Result Listener Thread Pool contains the threads that take results from the Output Queue and submit them to the result listeners.
The only configuration property for the Result Listener Thread Pool is rules.results.queue.threads. The default value is one.
The number of threads that you should allocate to the Result Listener Thread Pool depends on the frequency of results and the latency of the registered listeners.
A typical SpatialRules deployment has two queues in place to control the flow of objects through the application: the Input Queue and the Output Queue. Both queues have the same three configuration properties described below (each queue has a unique prefix to differentiate the properties):
type |
There are three types of queues supported by SpatialRules:
| ||||||
capacity |
The maximum capacity of the queue. The capacity property is only used if the queue's type is set to "BOUNDED." | ||||||
offer.timeout |
The offer timeout property specifies the number of milliseconds that the enqueue operation will wait for success. In the case of a bounded queue, this means that space is available in the queue. For a synchronous queue, this means that another thread is waiting to dequeue it. If the enqueue operation has not succeeded in the specified amount of time, it will be aborted and the object that it was trying to enqueue will be dropped. Setting the offer timeout to "-1", will cause the queue block indefinitely for the enqueue operation to succeed. Setting the offer timeout to "0" means that it must succeed immediately. |
The Input Queue sits right behind the Rules Server. As dynamic features are received from input connections they are placed on the Input Queue for threads from the Submitter Thread Pool to pick up and submit to the Input Processor/Rules Service.
The default settings for the Input Queue configure it as a synchronous queue with an offer timeout of "-1". In this configuration, if the Submitter Thread Pool falls behind, throughput on the input connections will slow to match the throughput of the Input Processor/Rules Service.
The default settings for all Input Queue properties are as follows:
rules.input.queue.type=SYNCHRONOUS rules.input.queue.capacity=10000 rules.input.queue.offer.timeout=-1
The Output Queue sits right in front of the Result Queue. Whenever a submitter thread receives a result, it attempts to enqueue the result in the Output Queue for distribution to listeners via the threads from the Result Listener Thread Pool.
The default settings for the Output Queue configure it as a bounded queue with a capacty of 2000 and an offer timeout of 20 milliseconds. In this configuration, if the Result Listener Thread Pool falls behind and the Output Queue reaches capacity, results will be discarded if the submitter thread has to wait more than 20 milliseconds for the enqueue operation to succeed.
The default settings for all Output Queue properties are as follows:
rules.results.queue.type=BOUNDED rules.results.queue.capacity=2000 rules.results.queue.offer.timeout=20
All of the SpatialRules databases share a common set of configuration properties described below. Each is differentiated by a prefix specific to a database:
Rules Database |
|
Input Processor Database |
|
Rules Runtime Database |
|
The common suffixes for the database configuration parameters are as follows:
|
The path on the filesystem where the database files will be written. This path must be unique to the database instance with some exceptions. The rules are as follows:
| ||||||
|
The amount of memory in bytes to allocate to the Berkeley DB cache. | ||||||
|
The percentage of JVM memory to allocate to the Berkeley DB
cache. Note that this property takes precedence over
| ||||||
|
The action to take when a transaction is committed. The choices are:
| ||||||
|
The number of threads that Berkeley DB will use to clean the database log files. For higher-volume (> 1000 transactions a second) and higher record-count applications, you may need to make this number up to three times the number of threads that are writing to the database. |
SpatialRules provides for remote monitoring of the following values using SNMP (Simple Network Management Protocol) Version 2 and JMX (Java Management Extensions):
application status—up or down.
number of dynamic features received per connection.
number of dynamic features dropped per connection.
number of results received by the Result Queue.
number of results dropped by the Result Queue.
The details on activating and using remote monitoring are described in the sections below.
SpatialRules also provides a simplistic, log-based method for
monitoring. If you set the property
rules.monitoring.log.dropped to true in your
rules.properties file, then a warn-level message (in
the log named "dropped-items.log") will be logged whenever a dynamic
feature is dropped at the input queue or a result is dropped at the output
queue.
![]() | |
|
Never set rules.monitoring.log.dropped to true on a production machine. If the machine falls behind enough to start dropping features or results, the cost of writing the messages to the log will only compound the problem. |
To enable remote monitoring of SpatialRules with SNMP, add
<monitoring_install_dir>/objectfx-rules-snmp-<version>.jar
to the SpatialRules classpath by uncommenting and editing the
following line in the
<rules_install_dir>/bin/launch.cmd
file:
rem set CP=%CP%;objectfx-rules-<monitoring implementation>.jar
or the following line in the
<rules_install_dir>/bin/launch.sh
file:
# CP=${CP};objectfx-rules-<monitoring implementation>.jar
Then, if you need to change any of the default properties for
the SNMP connection, copy the
<monitoring_install_dir>/rules-snmp.properties
file into the root of the rules installation folder and edit the
properties as necessary. The properties that you can change
are:
rules.snmp.host |
Set the host for the SNMP agent to run on. The default is "0.0.0.0"—all interfaces of the current host. |
rules.snmp.port |
Set the port number for the Agent to use. The default is 161. |
rules.snmp.community |
Set the community name to use for the SNMP connection. The default is "public" |
When you start SpatialRules, it will automatically find and load the SNMP agent so that it can communicate with SNMP clients.
Finally, import the SpatialRules MIB
(<monitoring_install_dir>/SPATIAL-RULES-MIB.txt)
into your SNMP monitoring tool.
SpatialRules also includes a limited SNMP client that you can
start by invoking the snmpviewer.cmd or
snmpviewer.sh scripts in the
<monitoring_install_dir>/bin folder. To use
the client, you must first copy
<rules_install_dir>/objectfx-rules-monitoring-<version>.jar
to <monitoring_install_dir>/lib.
The arguments to the script are
snmpviewer
[-frame]
{host}
{port}
{community name}
[polling interval]
The options to the snmpviewer command are as follows:
-frame |
If specified, brings up a GUI version of the client as shown in Figure 5.2, “Monitoring with SpatialRules SNMP Client”. If not specified, the values will be written to the console. |
host |
The name of the host where the SpatialRules SNMP agent is running. |
port |
The port to use to connect to the SpatialRules SNMP agent. |
community name |
The community name that the SpatialRules SNMP agent is using ("public" if using default setting). |
polling interval |
The polling interval in seconds. If specified using the console client, the client will continue to poll the agent and print the current values. If not specified, the console client will print the current values and exit. |
To enable remote monitoring of SpatialRules with JMX, add
<monitoring_install_dir>/objectfx-rules-jmx-<version>.jar
to the SpatialRules classpath by uncommenting and editing the following
line in the
<rules_install_dir>/bin/launch.cmd
file:
rem set CP=%CP%;objectfx-rules-<monitoring implementation>.jar
or the following line in the
<rules_install_dir>/bin/launch.sh
file:
# CP=${CP};objectfx-rules-<monitoring implementation>.jar
Then edit the setting for the JMX_REMOTE
variable in the
<rules_install_dir>/bin/launch.sh or
<rules_install_dir>/bin/launch.cmd file and
uncomment the JVMARGS variable:
# Settings for remote monitoring with JConsole. Alter as needed.
JMX_REMOTE="-Dcom.sun.management.jmxremote\
-Dcom.sun.management.jmxremote.port=10254\
-Dcom.sun.management.jmxremote.authenticate=false\
-Dcom.sun.management.jmxremote.ssl=false"
# Uncomment the line below to enable remote monitoring.
#JVMARGS=${JMX_REMOTE}
When you start SpatialRules, it will automatically register its MBean.
To view the values in JConsole, connect to SpatialRules with JConsole and click on the MBean tab and open the com.objectfx tree entry as shown in the figure below.
Table of Contents
A boolean expression that returns true if both of its child expressions return true:
(and <boolean expression>, <boolean expression>)
Example:
(and (eq (property "/Truck/Restrictions"), "HAZMAT"), (eq (property "LEVEL"), (variableRef "CURRENT-THREAT-LEVEL")))
A boolean spatial relation expression that returns true if the subject and the target features are within the specified distance.
There are two forms of the closeTo expression. To test for proximity to a reference features, use this form:
(closeTo <distance>, <featureRef>|<featureSetRef>)
where:
distance |
Is one of the distance expressions that specifies how close the subject dynamic feature must be to the target reference feature. |
featureRef |
Is a reference to a reference feature. See Section A.25, “featureRef”. |
featureSetRef |
Is a reference to a reference feature set. See Section A.27, “featureSetRef”. The subject dynamic feature only needs to within the specified distance to one of the features in the feature set. |
Example:
(closeTo (km "10.0", "greatCircle"), (featureRef "AOI 4"))
To test for proximity to one or more dynamic features, use this form:
(closeTo <distance>, [<cardinality>, <timespan>,] <feature>)
where:
distance |
Is one of the distance expressions that specifies how close the subject dynamic feature must be to the target dynamic feature. |
cardinality |
Is the minimum number of target dynamic features that must be within the specified distance of the subject dynamic feature. |
timespan |
Is one of the timespan expressions that specifies the maximum age of a target dynamic feature relative to the subject dynamic feature. Any target dynamic feature whose timestamp is more than timespan older than the subject dynamic feature will be excluded from the count. |
feature |
Is a dynamic feature selector expression. See Section A.24, “feature”. |
Example:
(closeTo (mi "6.0", "greatCircle"), (feature true)) (closeTo (m "500.0", "greatCircle"), "4", (minutes "60"), (feature true))
A boolean spatial relation expression that returns true if a dynamic feature completely contains (see Section C.2.3, “Contains/Within”) a target feature.
(contains <feature>|<featureRef>|<featureSetRef>)
where:
feature |
Is a dynamic feature selector expression. See Section A.24, “feature”. |
featureRef |
Is a reference to a reference feature. See Section A.25, “featureRef”. |
featureSetRef |
Is a reference to a reference feature set. See Section A.27, “featureSetRef”. The subject dynamic feature only needs to contain one of the features in the feature set. |
![]() | |
|
The contains relationship is the inverse of the within relationship. |
For example, to determine when a dynamic feature contains a reference feature:
(contains (featureRef "containee"))
Or a dynamic feature contains a previously submitted dynamic feature:
(contains (feature (eq (property "type"), "containee"))
A boolean spatial expression that returns true if the number of dynamic features that have the specified spatial relation to an area exceeds the specified value within a specified time.
(countGt "<number>", <relation expression>, <timespan>, <discriminator>)
where:
number |
The number of dynamic features that the count must exceed for the expression to evaluate to true. | |||
relation expression |
Only the dynamic features that have this geometric relation with the reference feature will be counted. The relation expression must be one of: contains, disjoint, intersects, overlaps, or within.
| |||
timespan |
The maximum timespan for the count. Any feature whose timestamp is before the most recently counted feature's timestamp minus this timespan will be dropped from the count. See Section A.68, “Time Spans” for timespan expressions. | |||
discriminator |
Only the dynamic features for which the discriminator expression returns true will be counted. |
The following example returns true if more than 10 "HAZMAT" trucks are within Zone-A in a 100 hour period.
(countGt "10", (within (featureRef "zone-A")), (hours "100"), (feature (eq (property "/Truck/Restrictions"), "HAZMAT")))
A boolean spatial expression that returns true if the number of dynamic features that have the specified spatial relation to an area is less than a specified value within a specified time.
(countLt "<number>", <relation expression>, <timespan>, <discriminator>)
where:
number |
The number of dynamic features that the count must fall below for the expression to evaluate to true. | |||
relation expression |
Only the dynamic features that have this geometric relation with the reference feature will be counted. The relation expression must be one of: contains, disjoint, intersects, overlaps, or within.
| |||
timespan |
The maximum timespan for the count. Any feature whose timestamp is before the most recently counted feature's timestamp minus this timespan will be dropped from the count. See Section A.68, “Time Spans” for timespan expressions. | |||
discriminator |
Only the dynamic features for which the discriminator expression returns true will be counted. |
The following example returns true if less than 10 "HAZMAT" trucks are within Zone-A in a 100 hour period.
(countLt "10", (within (featureRef "zone-A")), (hours "100"), (feature (eq (property "/Truck/Restrictions"), "HAZMAT")))
A boolean spatial relation expression that returns true if a dynamic feature is covered by (see Section C.2.4, “Covers/Covered By”) a target feature.
(coveredBy <feature>|<featureRef>|<featureSetRef>)
where:
feature |
Is a dynamic feature selector expression. See Section A.24, “feature”. |
featureRef |
Is a reference to a reference feature. See Section A.25, “featureRef”. |
featureSetRef |
Is a reference to a reference feature set. See Section A.27, “featureSetRef”. The subject dynamic feature only needs to be covered by one of the features in the feature set. |
![]() | |
|
The covered by relationship is the inverse of the covers relationship and is closely related to the within relationship. |
For example, to determine when a dynamic feature is covered by a reference feature:
(coveredBy (featureRef "AOI-1"))
Or a dynamic feature is covered by a previously submitted dynamic feature:
(coveredBy (feature (eq (property "type"), "covering feature"))
A boolean spatial relation expression that returns true if a dynamic feature covers (see Section C.2.4, “Covers/Covered By”) a target feature.
(covers <feature>|<featureRef>|<featureSetRef>)
where:
feature |
Is a dynamic feature selector expression. See Section A.24, “feature”. |
featureRef |
Is a reference to a reference feature. See Section A.25, “featureRef”. |
featureSetRef |
Is a reference to a reference feature set. See Section A.27, “featureSetRef”. The subject dynamic feature only needs to cover one of the features in the feature set. |
![]() | |
|
The covers relationship is the inverse of the covered by relationship and is closely related to the contains relationship. |
For example, to determine when a dynamic feature covers a reference feature:
(covers (featureRef "covered"))
Or a dynamic feature covers a previously submitted dynamic feature:
(covers (feature (eq (property "type"), "covered"))
A boolean spatial relation expression that returns true if a dynamic feature is disjoint (see Section C.2.2, “Disjoint”) with a target feature.
![]() | |
|
The disjoint relationship is the negation of the intersects relationship. |
(disjoint <feature>|<featureRef>|<featureSetRef>)
where:
feature |
Is a dynamic feature selector expression. See Section A.24, “feature”. |
featureRef |
Is a reference to a reference feature. See Section A.25, “featureRef”. |
featureSetRef |
Is a reference to a reference feature set. See Section A.27, “featureSetRef”. The subject dynamic feature only needs to be disjoint with one of the features in the feature set, so, although it's allowed, it's probably impractical. |
Disjoint with a reference feature:
(disjoint (featureRef "AOI 1"))
Disjoint with a dynamic feature:
(disjoint (feature (eq (property "type"), "tagalong"))
A boolean temporal expression that returns true if a dynamic feature has a captured date that falls within the referenced period.
(during <periodRef>)
Example:
(during (periodRef "Weekend"))
Defines a dynamic feature.
(dynamicFeature "<id>", "<type>", "<name>", (location <capturedDate>, <geometry>)[, (attr "<key>", "<value>")]*)
where:
id |
Is a unique string identifier for the feature. |
type |
Is a string specifying the feature's type. |
name |
Is a string specifying the feature's name. |
capturedDate |
Is a date string as defined in Section A.66.6, “date”. |
geometry |
Is any supported geometry. |
key |
Is a string key for an attribute. |
value |
Is the value for the attribute (use the data types defined in Section A.66, “Data Types”). |
For example:
(dynamicFeature "BTA5670", "civil air", "Continental Express 5670",
(location
"2010-04-08 16:25:25.538 CDT",
(point "-88.25,42.283")),
(attr "Route", "KICT./.IRK.BENKY1.KORD/0030"),
(attr "Airspeed", (int "352")),
(attr "Altitude", (int "10000")))
A boolean spatial expression that returns true if a dynamic feature entered a reference feature, i.e., the dynamic feature is within the specified feature for the first time.
(enters <featureRef>|<featureSetRef>)
where:
featureRef |
Is a reference to a reference feature. See Section A.25, “featureRef”. |
featureSetRef |
Is a reference to a reference feature set. See Section A.27, “featureSetRef”. The subject dynamic feature only needs to be disjoint with one of the features in the feature set, so, although it's allowed, it's probably impractical. |
Enters the bounds of a reference feature:
(enters (featureRef "state-MN"))
A boolean comparator expression that returns true if the result of two value expressions are equal:
(eq <value expression>, <value expression>)
where value expression is one of the value expressions, e.g., property, a literal value, or one of the arithmetic operators.
Example:
(eq (property "/Truck/VIN"), "1BXPEI38573")
A boolean spatial expression that returns true if a dynamic feature exited a reference feature, i.e., the dynamic feature was within the specified feature at its previous location and now isn't.
(exits <featureRef>|<featureSetRef>)
where:
featureRef |
Is a reference to a reference feature. See Section A.25, “featureRef”. |
featureSetRef |
Is a reference to a reference feature set. See Section A.27, “featureSetRef”. The subject dynamic feature only needs to be disjoint with one of the features in the feature set, so, although it's allowed, it's probably impractical. |
Exits the bounds of a reference feature:
(exits (featureRef "state-MN"))
A boolean expression that returns true if its child expression
returns true. An expression is used to associate a
name with a boolean expression so that it can be evaluated by Rules
Service.
(expression "name", <boolean expression>)
Expression names must be unique. Expression names are expressed as literals and may contain any combination of ASCII characters, although control characters should be avoided.
Hint: Using a dot-notation for expression names can be helpful for encoding classification and additional information into the rule that can be parsed during event handling. For example, "us.hazmat.within.7000.meters".
Defines an extruded geometry collection.
(extrudedGeometryCollection <geometry collection>, "<altitude>", "<height>")
where:
geometry collection |
Is a |
altitude |
Is the altitude of the base of the geometry collection in meters above sea level. |
height |
Is the height of the top of the geometry collection in meters above the base. |
For example:
(extrudedGeometryCollection
(geometryCollection
(polygon
(ring "-93.12,45.0 -93.04,45.0 -93.04,44.9 -93.15,44.9 -93.16,44.97 -93.12,45.0")),
(line "0.0,0.0 1.0,1.0 2.0,2.0 3.0,3.0 4.0,4.0"),
(point "-93.27833,44.98167")),
"456.45", "1290.76"))
Defines an extruded line-string geometry.
(extrudedLine <line>, "<altitude>", "<height>")
where:
line |
Is a |
altitude |
Is the altitude of the base of the line in meters above sea level. |
height |
Is the height of the top of the line in meters above the base. |
For example:
(extrudedLine (line "0.0,0.0 1.0,1.0 2.0,2.0 3.0,3.0 4.0,4.0"), "480.0", "150.0")
Defines an extruded multiline.
(extrudedMultiline <multiline>, "<altitude>", "<height>")
where:
multiline |
Is a |
altitude |
Is the altitude of the base of the multiline in meters above sea level. |
height |
Is the height of the top of the multiline in meters above the base. |
For example:
(extrudedMultiline
(multiline
(line "0.0,0.0 1.0,1.0 2.0,2.0 3.0,3.0 4.0,4.0"),
(line "0.0,1.0 1.0,2.0")),
"10000.0", "100.0")
Defines an extruded multipoint.
(extrudedMultipoint <multipoint>, "<altitude>", "<height>")
where:
multipoint |
Is a |
altitude |
Is the altitude of the base of the multipoint in meters above sea level. |
height |
Is the height of the top of the multipoint in meters above the base. |
For example:
(extrudedMultipoint
(multipoint
(point "-93.27833,44.98167"),
(point "4.1,1.0"),
(point "0.0,0.0")),
"1000.0", "10000.0")
Defines an extruded multipolygon.
(extrudedMultipolygon <multipolygon>, "<altitude>", "<height>")
where:
multipolygon |
Is a |
altitude |
Is the altitude of the base of the multipolygon in meters above sea level. |
height |
Is the height of the top of the multipolygon in meters above the base. |
For example:
(extrudedMultipolygon
(multipolygon
(polygon
(ring "-93.12,45.0 -93.04,45.0 -93.04,44.9 -93.15,44.9 -93.16,44.97 -93.12,45.0")),
(polygon
(ring "-93.3,45.0 -93.17,45.02 -93.2,44.909 -93.33,44.893 -93.36,44.956 -93.3,45.0"),
(ring "-93.31,44.95 -93.32,44.94 -93.32,44.939 -93.3,44.946 -93.31,44.95"),
(ring "-93.31,44.926 -93.313,44.91 -93.297,44.925 -93.31,44.926"))),
"0.0", "300.0")
Defines an extruded point geometry.
(extrudedPoint <point>, "<altitude>", "<height>")
where:
point |
Is a |
altitude |
Is the altitude of the base of the point in meters above sea level. |
height |
Is the height of the top of the point in meters above the base. |
For example:
(extrudedPoint (point "-93.27833,44.98167"), "250.0", "500.0")
Defines an extruded polygon geometry.
(extrudedPolygon <polygon>, "<altitude>", "<height>")
where:
polygon |
Is a polygon. |
altitude |
Is the altitude of the base of the polygon in meters above sea level. |
height |
Is the height of the top of the polygon in meters above the base. |
For example:
(extrudedPolygon
(polygon
(ring "-93.12,45.0 -93.04,45.0 -93.04,44.9 -93.15,44.9 -93.16,44.97 -93.12,45.0")),
"1045.0", "30.0")
A value expression that selects dynamic features. This expression is used as a discriminator in dynamic spatial expressions.
All previously reported dynamic features are evaluated against the
child boolean expression. Any feature that evaluates to true will be
returned by the feature expression and evaluated by
the parent expression.
(feature <boolean expression>)
For example, to scope a rule to only dynamic features of type "truck":
(feature (eq (property "type"), "truck"))
Or to scope a rule to only dynamic features with a "HAZMAT" restriction:
(feature (eq (property "Restrictions"), "HAZMAT"))
To return all dynamic features, use the true
expression:
(feature true)
Denotes a reference (by id) to a reference feature in the rule repository.
(featureRef "<feature id>")
Example:
(featureRef "state-MN")
Defines a set of one or more features in the rule repository. Feature sets are purely a grouping mechanism; expressions are independently evaluated against each feature in the set.
(featureSet "<id>", "<feature id>"[, "<feature id>"]*)
where:
id |
The unique ID for the feature set. |
feature id |
The ID of a reference feature that is stored in the Rules Database. |
Example:
(featureSet "fs-states Mid Atl", "state-NY", "state-PA", "state-NJ")
Denotes a reference (by id) to a featureSet in the rule repository.
(featureSetRef "<feature set id>")
Example:
(featureSetRef "fs-states Mid Atl")
Defines an expression that can be used as part of a larger expression.
(fragment "<name>", <boolean expression>)
where:
name |
Is the unique name for this fragment. |
boolean expression |
Is any boolean expression except for |
Example:
(fragment "truckType", (eq (property "type"), "truck"))
Denotes a reference (by name) to an expression fragment in the rule repository.
(fragment "<fragment name>")
Example:
(expression "truck enters Mid Atl states",
(and
(fragmentRef "truckType"),
(enters (featureSetRef "fs-states Mid Atl"))
)
)
A boolean comparator expression that returns true if the left-hand value expression (first child) is greater than or equal to the right-hand value expression (second child).
(ge <value expression>, <value expression>)
where value expression is one of the value expressions, e.g., property, a literal value, or one of the arithmetic operators.
Example:
(ge (property "/Truck/stops"), (int "3"))
Defines a geometry collection.
(geometryCollection <geometry>[, <geometry>]*)
where the geometry arguments are any combination of geometry types.
For example:
(geometryCollection
(polygon
(ring "-93.12,45.0 -93.04,45.0 -93.04,44.9 -93.15,44.9 -93.16,44.97 -93.12,45.0")),
(line "0.0,0.0 1.0,1.0 2.0,2.0 3.0,3.0 4.0,4.0"),
(point "1.0,2.1")))
A boolean comparator expression that returns true if the left-hand value expression (first child) is greater than the right-hand value expression (second child).
(gt <value expression>, <value expression>)
where value expression is one of the value expressions, e.g., property, a literal value, or one of the arithmetic operators.
Example:
(gt (property "/Truck/stops"), (int "3"))
A boolean spatial expression that returns true when it detects a cluster of dynamic features with the specified minimum number of dynamic features within the specified distance.
(inCluster <distance>, "<count>")
where:
distance |
Is one of the distance expressions that specifies the maximum distance between cluster members. |
count |
Is an integer that specifies the minimum number of members that must be present. |
For example, to specify a cluster of 3 or dynamic features within 100 meters of each other:
(inCluster (m "100.0"), "3")
To limit the cluster to only dynamic features meeting specific criteria, combine the cluster expression with a property expression. For example, to limit a cluster to dynamic features with a HAZMAT restriction:
(and
(inCluster (m "100.0"), "3"),
(eq
(property "Restrictions"), "HAZMAT")))
Returns true if a dynamic feature intersects (see Section C.2.1, “Intersects”) a target feature.
(intersects <feature>|<featureRef>|<featureSetRef>)
where:
feature |
Is a dynamic feature selector expression. See Section A.24, “feature”. |
featureRef |
Is a reference to a reference feature. See Section A.25, “featureRef”. |
featureSetRef |
Is a reference to a reference feature set. See Section A.27, “featureSetRef”. The subject dynamic feature only needs to be intersect one of the features in the feature set. |
For example, to detect when a dynamic feature intersects a reference feature:
(intersects (featureRef "AOI 2"))
Or when a dynamic feature intersects another dynamic feature:
(intersects (feature
(gt
(property "Contamination-Level"),
(variableRef "CurrentLevel"))))
A boolean comparator expression that returns true when the result of the left-hand value expression is a member of the collection returned by the right-hand value expression.
(isIn <scalar value expression>, <collection value expression>)
where:
scalar value expression |
Is a value expression that returns a single value. |
collection value expression |
Is a value expression that returns a collection. (Currently, this means only the collection literals set and list.) |
For example:
(isIn (property "id"), (set "watchId3", "watchId2", "watchId1"))
A boolean comparator expression that returns true when the result of the left-hand value expression (first child) is matched by the right-hand (second child) regular expression.
(isLike <value expression>, (regex <regex>))
where:
value expression |
Is one of the value expressions, e.g., property, a literal value, or one of the arithmetic operators. |
regex |
Is a regular expression as documented in
|
For example, the following matches on Hostile, Unknown and Suspect variations of a military M2525B symbology code starting with the pattern S_PP, where the "_" could be an H, U, or S.
(isLike (property "code"), (regex "S[HUS]PP.*"))
In this example the following codes match the regular expression:
"SHPP------*****" "SUPP------*****" "SSPP------*****"
The code "SFPP------*****" would not match.
A boolean comparator expression that returns true if the left-hand value expression (first child) is less than or equal to the right-hand value expression (second child).
(le <value expression>, <value expression>)
where value expression is one of the value expressions, e.g., property, a literal value, or one of the arithmetic operators.
Example:
(le (property "/Truck/stops"), (int "3"))
Defines a line-string geometry.
(line "<lon>,<lat> [<lon>,<lat>]+)
where:
lon |
The longitude in decimal degrees as an easting, i.e., longitudes east of the Prime Meridian are positive; longitudes west are negative. |
lat |
The latitude in decimal degrees as a northing, i.e., latitudes north of the Equator are positive; latitudes south are negative. |
![]() | |
|
All geometry coordinates in SpatialRules must be in the CRS defined in Appendix B.3 of [wms-spec]. |
For example:
(line "0.0,0.0 1.0,1.0 2.0,2.0 3.0,3.0 4.0,4.0")
An ordered collection of values.
(list (<value>[, <value>]*]?)
where value is a literal value using one of the data types listed in Section A.66, “Data Types”.
A boolean comparator expression that returns true if the left-hand value expression (first child) is less than the right-hand value expression (second child).
(lt <value expression>, <value expression>)
where value expression is one of the value expressions, e.g., property, a literal value, or one of the arithmetic operators.
In the example below, the expression will return true if the value of the "arrival" attribute on a dynamic feature of type "Truck" is a date before 10AM Feb 18, 2008 Eastern Standard Time:
(lt (property "/Truck/arrival"), (date "2008-02-18 10:00:00:000 EST"))
An expression that directs SpatialRules to maintain a history track for dynamic features matching the provided feature filter. The track length may be specified by count, time span, or a combination of both. When enough locations for a dynamic feature have been recorded to meet the specified criteria, the track will be submitted as a new dynamic feature.
(makeTrack "<prefix>", "<resubmit>", <min>, <max>, <feature>)
where:
prefix |
Is a unique identifier for the expression that will be prepended onto the ID of the dynamic feature from which the track was derived. The result will be used as the ID for the new dynamic feature containing the track. All the remaining properties on the track's dynamic feature will be copied from the most recently received dynamic feature belonging to the track. |
resubmit |
Either "true" or "false" indicating whether the original dynamic feature should be submitted to SpatialRules (true) or it should be dropped (false) and only the resulting tracks should be submitted. |
min |
Is either an integer value specifying the minimum number of locations that must be in the track or a timespan specifying the minimum time difference between the most recent location and the oldest location in the history before a track can be made. |
max |
Is either an integer value specifying the maximum number of locations that can be in the track or a timespan specifying the maximum time difference between the most recent and the oldest locations in the history that can be included in the track. |
feature |
Is a |
The example below directs SpatialRules to create tracks for any dynamic feature that has an attribute "Restrictions" with a value of "HAZMAT". Those dynamic features will not be submitted to SpatialRules, only their tracks. The tracks must have a minimum of two locations but not more than ten:
(makeTrack "HAZMAT-10", false,
(int "2"), (int "10"),
(feature (eq (property "Restrictions"), "HAZMAT")))
This example changes the one above to say that there must be at least 10 minutes worth of locations in a track, but not more than 30 minutes worth:
(makeTrack "HAZMAT-30-Minutes", false,
(minutes "10"), (minutes "30"),
(feature (eq (property "Restrictions"), "HAZMAT")))
Defines a multi-line-string geometry.
(multiline <line>[, <line>]*)
where
the line arguments are any combination of lines.
For example:
(multiline
(line "0.0,0.0 1.0,1.0 2.0,2.0 3.0,3.0 4.0,4.0"),
(line "0.0,1.0 1.0,2.0"))
Defines a multipoint geometry.
(multipoint <point>[, <point>]*)
where
the point arguments are any combination of points.
For example:
(multipoint
(point "1.0,2.1"),
(point "4.1,1.0"),
(point "0.0,0.0"))
Defines a multipolygon geometry.
(multipolygon <polygon>[, <polygon>]*)
where
the polygon arguments are any combination of polygons that meet the
constraints of a valid multipolygon.
For example:
(multipolygon
(polygon
(ring "-93.12,45.0 -93.04,45.0 -93.04,44.9 -93.15,44.9 -93.16,44.97 -93.12,45.0")),
(polygon
(ring "-93.3,45.0 -93.17,45.02 -93.2,44.909 -93.33,44.893 -93.36,44.956 -93.3,45.0"),
(ring "-93.31,44.95 -93.32,44.94 -93.32,44.939 -93.3,44.946 -93.31,44.95"),
(ring "-93.31,44.926 -93.313,44.91 -93.297,44.925 -93.31,44.926")))
A boolean n-ary expression that returns true when the specified number of child expressions return true.
(nOf "all"|"<count>", <boolean expression> [, <boolean expression>]*)
where:
all |
Indicates that all expressions must be true. |
count |
Is an integer specifying how many of the child boolean
expressions must be true for the |
boolean expression |
Any boolean expression except |
Specifying "1" for the count is equivalent to putting all of the
child expressions in or
expressions. Specifying "all" for the count is equivalent to putting all
of the child expressions in and expressions.
For example, if only one of a set of conditions needs to be met:
(nOf "1", (eq (property "LEVEL"), "YELLOW"), (eq (property "LEVEL"), "ORANGE"), (eq (property "LEVEL"), "RED"))
Or if all of the conditions must be met:
(nOf "all", (eq (property "type"), "TRUCK"), (eq (property "Restrictions"), "HAZMAT"), (eq (property "Origin"), "Cuba"))
nOf is most useful in cases where more than one
condition must be true, but not all. In this example any 2 of the 3
conditions can result in true:
(nOf "2", (eq (property "Material"), "Chlorine"), (eq (property "Material"), "Fluorine"), (eq (property "Material"), "Anhydrous Ammonia"))
Negates its child boolean expression.
(not <expression>) (not (eq (property "/Truck/Restrictions"), "HAZMAT"))
A boolean expression that returns true if one of its two child expressions returns true:
(or <boolean expression>, <boolean expression>)
where boolean expression is any boolean
expression except expression.
For example:
(or (eq (property "/Truck/Restrictions"), "HAZMAT"), (eq (property "LEVEL"), "RED"))
Returns true if a dynamic feature overlaps (see Section C.2.5, “Overlaps”) a target feature.
(overlaps <feature>|<featureRef>|<featureSetRef>)
where:
feature |
Is a dynamic feature selector expression. See Section A.24, “feature”. |
featureRef |
Is a reference to a reference feature. See Section A.25, “featureRef”. |
featureSetRef |
Is a reference to a reference feature set. See Section A.27, “featureSetRef”. The subject dynamic feature only needs to be overlap one of the features in the feature set. |
Overlaps a reference feature:
(overlaps (featureRef "AOI 2"))
Overlaps a dynamic feature:
(overlaps (feature
(gt
(property "Contamination-Level"),
(variableRef "CurrentLevel"))))
Defines a time period for an interval or schedule.
(period "<name>", (date "<start>"), (date "<end>"))
where:
name |
Is a unique identifier for the period. |
start |
Is the starting time for a fixed, one-time interval using a date string as described in Section A.66.6, “date”. |
end |
Is the end time for a fixed, one-time interval using a date string as described in Section A.66.6, “date”. |
The second form
(period "<name>", (recurringTime <start>, (recurringTime <end>))
where:
name |
Is a unique identifier for the period. |
start |
Is the starting time for a recurring time period as described in Section A.54, “recurringTime”. |
end |
Is the end time for a recurring time period as described in Section A.54, “recurringTime”. |
For example, to create a time interval with fixed start and end times:
(period "fixed-period", (date "2008-02-13 14:34:09.781 CST"), (date "2008-02-13 21:34:09.781 CST"))
Or, to create a schedule for every Saturday through Sunday:
(period "Weekend", (recurringTime "0", "0", "7", null, null), (recurringTime "59", "23", "1", null, null))
Denotes a reference (by name) to a period in the rule repository.
(periodRef "<period name>")
For example:
(expression "equipment left a construction site on a weekend",
(and
(during (periodRef "Weekend"))
(and
(fragmentRef "equipmentType"),
(exits (featureSetRef "fs-construction-site"))
)
)
)
Defines a point geometry.
(point "<lon>,<lat>")
where:
lon |
The longitude in decimal degrees as an easting, i.e., longitudes east of the Prime Meridian are positive; longitudes west are negative. |
lat |
The latitude in decimal degrees as a northing, i.e., latitudes north of the Equator are positive; latitudes south are negative. |
![]() | |
|
All geometry coordinates in SpatialRules must be in the CRS defined in Appendix B.3 of [wms-spec]. |
For example:
(point "-93.27833,44.98167")
Defines a polygon geometry.
(polygon <ring>[, <ring>]*)
where
the first ring is the
exterior boundary of the polygon and all other rings are holes.
For example, a polygon with just an exterior boundary:
(polygon (ring "-93.3,45.0 -93.17,45.02 -93.2,44.909 -93.33,44.893 -93.36,44.956 -93.3,45.0"))
And a polygon with two holes:
(polygon (ring "-93.3,45.0 -93.17,45.02 -93.2,44.909 -93.33,44.893 -93.36,44.956 -93.3,45.0"), (ring "-93.31,44.95 -93.32,44.94 -93.32,44.939 -93.3,44.946 -93.31,44.95"), (ring "-93.31,44.926 -93.313,44.91 -93.297,44.925 -93.31,44.926"))
A value expression that retrieves the value of an attribute from a dynamic feature.
(property "<property path>")
where property path is an XPath-like expression to reference the feature's properties. There
Keywords "id" and "type" may be specified to reference the ID and type values of a dynamic feature.
Get the feature's type:
(property "type")
Get the value of the "Contamination-Level" attribute from all dynamic features of type "Zone":
(property "/Zone/Contamination-Level")
Get the value of the "Contamination-Level" attribute from all dynamic features:
(property "Contamination-Level")
Get the feature's ID:
(property "id")
Specifies the repeating aspects of a time period.
(recurringTime "<minute>", "<hour>", "<day-of-week>",
"<day-of-month>", "<month-of-year>")
where:
minute |
The minute of the hour (0-59). |
hour |
The hour of the day using a 24-hour clock (023). |
day-of-week |
The day of the week as an integer from 17. |
day-of-month |
The day of the month (131). |
month-of-year |
The month of the year as an integer from 011. |
For example, to specify a recurring time that occurs every half hour only on Tuesdays:
(recurringTime "30", null, "3", null, null)
Defines a feature to be used as a reference feature.
(referenceFeature "<id>", "<type>", "<name>", <geometry>[, (attr "<key>", "<value>")]*)
where:
id |
Is a unique string identifier for the feature. |
type |
Is a string specifying the feature's type. |
name |
Is a string specifying the feature's name. |
geometry |
Is any supported geometry. |
key |
Is a string key for an attribute. |
value |
Is the value for the attribute (use the datatypes defined in Section A.66, “Data Types”). |
For example:
(referenceFeature "stadium.1", "stadium", "Target Field", (point "-93.27833,44.98167"), (attr "bestSection", "3"), (attr "claimToFame", "Home of the Twins"))
Defines a ring geometry.
(ring "<lon>,<lat> [<lon>,<lat>]+")
where:
lon |
The longitude in decimal degrees as an easting, i.e., longitudes east of the Prime Meridian are positive; longitudes west are negative. |
lat |
The latitude in decimal degrees as a northing, i.e., latitudes north of the Equator are positive; latitudes south are negative. |
![]() | |
|
All geometry coordinates in SpatialRules must be in the CRS defined in Appendix B.3 of [wms-spec]. |
For example:
(ring "0.0,0.0 5.5,0.0 5.6,1.1 0.0,2.32 0.0,0.0")
An unordered collection of unique values (duplicates will be dropped if present).
(set (<value>[, <value>]*]?)
where value is a literal value using one of the data types listed in Section A.66, “Data Types”.
A boolean expression that steps through its children, evaluating only the "current" child until the child evaluates to true. Once a child evaluates to true, the next (or first if the current child was the last in the list) child in the list is selected as the "current" child.
(stateTransition (transition "<name>", <boolean expression>) [,
(transition "<name>", <boolean expression>)]+)
Each transition expression is defined by the keyword "transition", an identifier, and a complete rule, which is a boolean expression.
(stateTransition
(transition "enterA", (within (feature (eq
(property "type"),
"Zone_A")))),
(transition "enterB", (within (feature (eq
(property "type"),
"Zone_B")))),
(transition "exitArea", (exits (featureRef "Area_C"))))
Defines a variable with an initial value.
(variable "<name>", <literal>|<data type>)
Create a variable with an initial string value:
(variable "THREAT-LEVEL", "GREEN")
Create a variable with an initial double value:
(variable "threshold", (double "16.75"))
Denotes a reference (by name) to a variable in the rule repository.
(variableRef "<variable name>")
The current value of the "THREAT-LEVEL" variable is "ORANGE" or "RED":
(or (eq (variableRef "THREAT-LEVEL", "ORANGE")), (eq (variableRef "THREAT-LEVEL", "RED")) )
Returns true if a dynamic feature is completely contained (see Section C.2.3, “Contains/Within”) by a target feature.
(within <feature>|<featureRef>|<featureSetRef>)
where:
feature |
Is a dynamic feature selector expression. See Section A.24, “feature”. |
featureRef |
Is a reference to a reference feature. See Section A.25, “featureRef”. |
featureSetRef |
Is a reference to a reference feature set. See Section A.27, “featureSetRef”. The subject dynamic feature only needs to be contained in one of the features in the feature set. |
Within the bounds of a reference feature:
(within (featureRef "state-MN"))
Within the bounds of a dynamic feature:
(within (feature (eq (property "type"), "perimeter"))
SpatialRules expressions provide a number of operators for performing calculations to derive values during rule evaluation. For more definition see the Java documentation for the java.lang.Math class.
Arithmetic operators can take literal values, variables, properties, or other arithmetic operators as arguments. Arithmetic operators expect that their value arguments return a value of type java.lang.Number at runtime-they will not convert string values. You will get an exception if a non-number is returned.
Unary operators take only one argument.
(<unary operator> <value>)
For example,
(sqrt (abs (variableRef "var")))
The following unary operators are supported:
abs |
Absolute value. |
sin |
Sin of a value. |
cos |
Cosine of a value. |
tan |
Tangent of a value. |
asin |
Arc tangent of a value. |
acos |
Arc cosine of a value. |
atan |
Arc tangent of a value. |
exp |
Euler's number. Computes e to a power specified. |
log |
Logarithm of a value. |
sqrt |
Square root of a value. |
ceil |
Ceiling of a value. |
floor |
Floor of a value. |
rint |
Rounds a value expression to the nearest mathematical integer. |
Binary operators take only two arguments.
(<binary operator> <value>, <value>)
For example,
(mul (div (int "5"), (int "9")), (sub (property "temperature"), (int "32")))
The following binary operators are supported:
add |
Adds two values. |
sub |
Subtracts two values. |
mul |
Multiplies two values. |
div |
Divides two values. |
min |
Computes the minimum of two values. |
max |
Computes the maximum of two values. |
atan2 |
Converts the values of two expressions to the theta phase of polar coordinates (r, theta). This is computed by taking the arc tangent of right over left. |
pow |
Number to a power (exponent) |
Data types are essentially literals with a type name so that the string value can be converted to the appropriate data type when the RulesScript is parsed. Data types have the following general form:
(<type> "<value>")
The following data types are available:
Character data. Strings are left unconverted as a Java String. This is the default data type and does not need to be explicitly specified.
Example comparing a property to a literal string value:
(eq (property "/Truck/Restrictions"), (char "HAZMAT"))))
Integer numeric. Values are converted to a Java int. The range for an "int" value is (-231) to (231-1).
(int "5")
Integer numeric. Values are converted to a Java long. The range for a "long" value is (-263) to (263-1).
(long "5")
Floating point numeric. Values are converted internally to a Java float. Java float values are defined by the 64-bit IEEE 754 floating-point numbers.
(float "5.5")
Floating point numeric. Values are converted internally to a Java double. Java double values are defined by the 64-bit IEEE 754 floating-point numbers.
(double "5.5")
Distances have the following general form:
(<units> "<double-value>"[, "<distance-type>"])
The distance-type indicates how the measurement is performed. The following distance types are available: greatCircle and euclidean. If no distance-type is specified, greatCircle is used.
The following distance units are available:
m |
Meters |
km |
Kilometers |
ft |
Feet |
mi |
Miles |
nmi |
Nautical Miles |
deg |
Degree Angle |
Table of Contents
There are a number of utilities available in the distribution that can assist with maintaining and setting up rules.
These tools are available as command-line scripts to be run directly from a shell. There are also corresponding Java classes that can be used to perform the same functions programmatically. The Java classes are documented in the API documentation.
All of the command-line scripts (located in the
bin directory) use a common script named
launch.[cmd|sh]. The launcher script contains
centralizes all of the classpath setup, evironment handling, etc. For
example, the following is a line taken from the submit
script:
call "%HERE%\launch.cmd" com.objectfx.rules.tools.SubmitDynamicFeatures %*
Each command has a unique set of command line parameters. The parameters for each are defined below.
The import command is used to import reference reatures from a file or URL. Features can automatically be added to a feature set by specifying a name. A number of data formats are supported such as KML, KMZ, GeoRSS, and Shapefiles.
The import command has the following general form:
import
[-featureSet name]
-format type
[-overwrite]
[-prefixIds]
-properties
filename
-source
filename|url
The options are:
-featureSet <name> |
Specifying a featureSet name will cause all features loaded to also be added to a featureSet of the name specified. |
-format <type> |
Import data format. Valid values are
|
-overwrite |
If specified, existing versions of the feature will be overwritten. |
-prefixIds |
If specified, feature IDs will be prefixed with "<feature type>-". |
-properties <filename> |
Properties file to use. |
-source <filename|url> |
Input source filename or URL. |
-help |
Display usage. |
The corresponding Java class for this command is
com.objectfx.rules.tools.ImportReferenceFeatures.
The submit command is used to submit data for evaluation to a SpatialRules server. The data can be provided in any number of formats including KML, KMZ, Shapefile and GeoRSS.
The submit command has the following general form:
submit
-format type
-properties
filename
-source
filename|url
The options are:
-format <type> |
Import data format. Valid values are
|
-properties <filename> |
Properties file to use. |
-source <filename|url> |
Input source filename or URL. |
-help |
Display usage. |
The corresponding Java class for this command is
com.objectfx.rules.tools.SubmitDynamicFeatures.
The dbadmin command is used to manage the RulesDatabase. This command provides a way to import and export the entire contents of a RulesDatabase to a text form. Databases can be created and emptied (cleaned) as well.
The dbadmin command has the following general form:
dbadmin
{
-clean
| -create
| -import filename
[-overwrite]
| -export filename
[-xf]
| -help
}
The options are:
-clean |
Removes all data from the database. |
-create |
Creates a new empty database. |
-export <filename> |
Export the entire contents of a database to a text format. |
-xf |
If specified, export everything except for reference features. |
-import <filename> |
Import items from a text format. |
-overwrite |
If specified, existing items will be overwritten by any with the same ID. |
-help |
Display usage. |
The corresponding Java class for this command is
com.objectfx.rules.tools.DbAdmin.
Launches the server provided by ObjectFX.
The spatialrules command has the following options:
-h,-help |
Prints usage information. |
-s, -service |
Runs spatial rules without console exit option. |
![]() | |
|
The source code for the SpatialRules server is provided in the examples distribution. This is useful for modifying the server as necessary. |
Cron (com.objectfx.rules.cron.Cron) is a
simple scheduling utility provided by SpatialRules for implementing
services that periodically perform some task. The most common use of Cron
is to periodically scan the indexes of Rules Service to remove any data
that is considered out-of-date (see Section 3.5, “Aging Data”), but it
could also be used to monitor a drop-box, e.g., a directory where inbound
files are written, containing dynamic features to be submitted.
There is only one method for starting up Cron:
startup(). When startup() is called, Cron
checks to see if it has any jobs that need to be scheduled for
execution. If there are, it creates the schedule for those jobs and then
begins executing the schedule.
To start up Cron:
Cron.getInstance().startup();
Cron jobs are created by implementing the Callable
(java.util.concurrent.Callable) interface and
then submitting the implementation to Cron with one of the
addJob() methods. When you submit a callable to Cron, it is
associated with three properties used to create jobs:
job name |
A unique name for the job. If you attempt to add a callable with a duplicate name an exception will be thrown. |
group name |
Group names are used to limit the concurrency of jobsno two jobs from the same group can be executing at the same time. Before submitting a job for execution, Cron will ensure that no job from the same group is currently executing. if one is still in progress, it will cancel the job that it was about to submit. Group names are also used to aggregate the results from jobs. The results from all jobs within the group are put in one collection that is retrieved by the group name (see below for details). |
schedule |
A schedule can be either a fixed time using an instance of
Date ( |
The following is an example of a simple Cron job that writes a message to the console every 10 seconds.
Callable callable = new Callable(){
public Object call() throws Exception {
System.out.println("Called at " + new Date());
return null;
}
};
Cron cron = Cron.getInstance();
cron.addJob("Test-Group", "My-Job", callable, new TimeSpan(10, TimeUnit.SECONDS));
cron.startup();
To remove a job, just call removeJob(String jobName).
This method returns true if a job with the specified name exists and is
removed, otherwise it returns false.
Cron.getInstance().removeJob("My-Job");
Whenever a job is scheduled for execution, a Future
(java.util.concurrent.Future) is created for it
and added to a collection so that it can be retrieved asynchronously.
The Futures are added to FIFO queuesone for each groupwith a limit of
200 Futures on each to prevent them from growing indefinitely.
To retrieve the collection of all completed Futures for a group,
call getResults(String groupName). Any Futures for that
group that have not yet completed will be left in the queue.
For example, to iterate over the results and collect them up:
List<MyJobResult> results = new ArrayList<MyJobResult>()
for (Future future : Cron.getInstance().getResults("MyGroupName")) {
if (!future.isCancelled()) {
try {
list.add((MyJobResult) future.get());
} catch (final Exception e) {
// Save results that had exceptions also.
list.add(new MyJobResult(e));
}
}
}
There are two methods for shutting down Cron:
The shutdown() method will wait up to ten
seconds for any in-progress jobs to complete.
The shutdown(long timeout) method will wait up
to the specified number of milliseconds for any in-progress jobs
to complete.
For example, to have Cron wait up to five seconds for any currently executing jobs:
Cron.getInstance().shutdown(5000);
When you call one of the shutdown methods, Cron stops queuing jobs for execution and then waits for the selected timeout period. If it reaches the end of the timeout period and not all of the jobs have completed, Cron will interrupt all of the still-executing threads and then return from the shutdown call.
To ensure a safe shutdown, any jobs that cannot tolerate an unexpected shutdown should either include a method for you to signal a shutdown or they should be able to detect when Cron interrupts the thread in which they are executing. The threads that Cron uses to execute tasks are all daemon threads. When the JVM exits, all Cron threads will be terminated, regardless of their current state.
Table of Contents
Geometries provide a way to define the geographic characteristics of a feature, relating it to the earth. The geometry model is based on [spatial-schema] with support for points, line strings, polygons, and collections. Geometries are two-dimensional, consist of X,Y coordinate pairs, and are associated with a Coordinate Reference System, which describes the coordinate space in which the geometry is defined. The following sections describe the geometry object model and details pertaining to each geometry type.
The class diagram below depicts the geometry class hierarchy and the relationships between the geometry types. The following sections detail each of the classes shown in the diagram.
The geometry interface
(com.objectfx.geometry.Geometry) is the root of the
class hierarchy. It defines properties and methods common to all geometry
implementations. These are listed below:
Coordinate Reference System |
A geometry's Coordinate Reference System (CRS) describes the
coordinate space in which the geometry's coordinates are defined.
The CRS may be queries using the
|
dimensionality |
A geometry may have a dimension of 0, 1, or 2. 0-dimensional
geometries have no length or area (e.g. a point), 1- dimensional
geometries have a length (e.g. a line string), and 2-dimensional
geometries have an area (e.g. a polygon). The dimension of a
geometry may be queried using the |
validity |
The validity of a geometry describes how well the coordinates in a geometry fit the rules set forth in section 6.1 of the [simple-feature-spec] document. The type of geometry dictates the validity rules; refer to the specification and the geometry sections below for more details on the validity rules for each geometry type. Geometry validity directly affects how a geometry interacts
with other geometries and its behavior within the system; results
are indeterminate if a geometry is invalid. Validity may be
evaluated for a geometry using the |
centroid |
A geometry's centroid is its mathematical centroid,
represented by a point geometry. The result point is not
guaranteed to be on the object. This property may be queried using
the For heterogeneous collections of primitive geometries, calculation of the centroid only takes into account those of the largest dimension. For example, when calculating the centroid of a collection including both points and polygons, the average is taken weighted only by area. Since points have no area they do not contribute to the result. |
envelope |
The envelope of a geometry is its minimum bounding rectangle
(MBR), represented as an |
spatial relations |
All geometries define the following set of spatial relation methods:
These spatial relations are discussed in more detail in Section C.2, “Spatial Relations”. |
distance |
Distance between geometries can be evaluated using both great circle and euclidean methods. Distance is calculated by finding the two closest points on the geometries being compared, which are not necessarily supplied coordinate values, and calculating the distance between them based on the Coordinate Reference System being used. For a geometry with a geographic Coordinate Reference
System, the |
A point (com.objectfx.geometry.Point) is a
zero-dimensional object, consisting of an X and Y coordinate value,
representing a single location in space. Points can be used to define
features such as vehicle locations, landmarks, and hazardous waste
sites.
A point's boundary is the empty set. Point geometries have no validity constraints.
The following example illustrates how an instance of a point is constructed in the default Coordinate Reference System (WGS84):
Point pt1 = new Point2d(34, 46);
A line string
(com.objectfx.geometry.LineString) is a
one-dimensional sequence of two or more points which define a path. Line
strings can be used to define features such as highways, streams, or the
path of a moving object.
The boundary of a line string is its two endpoints. The interior of a line string is defined as the connected set of segments which lie between the endpoints. A line string must have at least 2 distinct points. A line string containing points that are all topologically equivalent is invalid.
The following example illustrates how an instance of a line string is constructed in the default Coordinate Reference System (WGS84):
double[] xs = new double[] { -100, -95, -92 };
double[] ys = new double[] { 35, 39, 32 };
LineString lineString = new LineString2d(xs, ys);
A linear ring
(com.objectfx.geometry.LinearRing) is a type of
line string which is closed and simple. A linear ring is closed because
its start point is equal to its end point, and it is simple because it
does not pass through the same point more than once. Linear rings are most
often used to describe the exterior and interior boundaries of a polygon.
Linear rings do not contain any area; a polygon should be used if the
intent is to describe an area of space.
A linear ring's boundary is the empty set and being closed, the interior of a linear ring is continuous.
The figure below depicts a valid linear ring.
The following figure shows examples of invalid linear rings: (A) shows a linear ring which self intersects. (B) shows a linear ring with a spike, a section which doubles back on itself. (C) shows a linear ring which intersects itself at a point.
The following example illustrates how an instance of a linear ring is constructed in the default Coordinate Reference System (WGS84):
double[] xs = new double[] { -100, -100, -95, -95, -100 };
double[] ys = new double[] { 35, 40, 40, 35, 35 };
LinearRing linearRing = new LinearRing2d(xs, ys);Note that the last coordinate in a linear ring is not required during construction. If omitted, a closing x,y coordinate pair equivalent to the first will be added to the input coordinates.
A polygon (com.objectfx.geometry.Polygon) is
a two-dimensional surface stored as a sequence of points defining its
exterior bounding ring and 0 or more interior rings defining its holes. A
polygon may be used to describe features that have an area, such as
political boundaries, land masses, or areas of interest.
The boundary of a polygon is defined by the set of linear rings making up its exterior and interior boundaries. A polygon's interior is defined by the area spanning between, but not including, its exterior and interior rings. In addition to the validity constraints imposed by its set of linear rings, the interior rings of a polygon may only intersect the exterior or other interior rings at a single tangent point. They cannot cross nor share an edge.
The figure below depicts valid polygons. (A) shows a polygon with no interior rings. (B) shows a polygon with two interior rings. (C) shows a polygon with three interior rings, one touching the exterior ring at a tangent point, and two others intersecting at a tangent point.
The figure below depicts invalid polygons. (A) shows a polygon with an interior ring intersecting at more than one tangent point. (B) shows a polygon with interior rings intersecting at more than one tangent point. (C) shows a polygon with an interior ring that is not completely enclosed by the exterior ring.
The following example illustrates how an instance of a polygon is constructed, with and without interior rings in the default Coordinate Reference System (WGS84):
double[] exteriorXs = new double[] { -100, -100, -90, -90, -100 };
double[] exteriorYs = new double[] { 30, 40, 40, 30, 30 };
LinearRing exteriorRing = new LinearRing2d(exteriorXs, exteriorYs);
Polygon noHoles = new Polygon2d(exteriorRing);
double[] interiorXs = new double[] { -99, -99, -97, -97, -99 };
double[] interiorYs = new double[] { 37, 38, 38, 37, 37 };
LinearRing interiorRing = new LinearRing2d(interiorXs, interiorYs);
LinearRing[] interiorRings = new LinearRing[] { interiorRing };
Polygon withHoles = new Polygon2d(exteriorRing, interiorRings);
A multi-point
(com.objectfx.geometry.MultiPoint) is a
zero-dimensional geometry consisting of a collection of point geometries
that are not connected or ordered in any way. All member points must be of
the same Coordinate Reference System. Multi-point geometries can be used
to describe features such as disease outbreaks or traffic incidents
locations in a particular area.
The boundary of an multi-point is the empty-set. Multi-point geometries have no validity constraints; member points may be disjoint or overlapping.
The following example illustrates the construction of a multi-point geometry in the default Coordinate Reference System (WGS84):
Point pt1 = new Point2d(34, 46);
Point pt2 = new Point2d(25, 54);
Point pt3 = new Point2d(29, 41);
Point[] points = new Point[] { pt1, pt2, pt3 };
MultiPoint multiPoint = new MultiPoint2d(points);
A multi-line string
(com.objectfx.geometry.MultiLineString) is
one-dimensional geometry consisting of a collection of line string
geometries, which must all be of the same Coordinate Reference System. If
all member geometries have endpoints which intersect, the boundary is the
empty set. Multi-line strings can be used to describe such features as
highway networks or river deltas.
The boundary of an multi-line string is considered to be any endpoints of member line strings which do not intersect other member line strings. Member line strings may be disjoint or overlapping. Multi-line string geometries must contain valid line strings in order to be considered valid.
The following example illustrates the construction of a multi-line string geometry in the default Coordinate Reference System (WGS84):
LineString ls1 = new LineString2d(
new double[] { 10, 11, 12 },
new double[] { 13, 14, 15 });
LineString ls2 = new LineString2d(
new double[] { 7, 6, 5 },
new double[] { 4, 3, 2 });
LineString[] lineStrings = new LineString[] { ls1, ls2 };
MultiLineString multiLineString = new MultiLineString2d(lineStrings);
A multi-polygon
(com.objectfx.geometry.MultiPolygon) is a
2-dimensional geometry consisting of a collection of polygon geometries.
All member polygons must be of the same Coordinate Reference System. The
boundary of a multi-polygon consists of its member polygon's exterior and
interior rings. The interior consists of the combined interiors of its
member polygons. Multi-polygons can be used to describe features such as
non-contiguous land masses (e.g. Hawaii) or political boundaries.
Multi-polygons must contain valid polygons in order to be considered valid. In addition, the boundaries of its member polygons may only intersect at a finite number of points. This means that members may not share an edge, as they would intersect at a continuous number of points.
The figure depicts three examples of valid multi-polygons. (A) shows a multi-polygon with two member polygons. (B) shows a multi-polygon with two member polygons intersecting at a finite number of points. (C) shows a polygon with an interior ring nested within the interior ring of another polygon.
The following figure show examples of invalid multi-polygons: (A) shows a multi-polygon with overlapping member polygons. (B) shows a multi-polygon with one member connected by a segment.
The following example illustrates the construction of a multi-polygon in the default Coordinate Reference System (WGS84):
LinearRing poly1ExteriorRing = new LinearRing2d(
new double[] { -100, -100, -90, -90, -100 },
new double[] { 30, 40, 40, 30, 30 });
Polygon polygon1 = new Polygon2d(poly1ExteriorRing);
LinearRing poly2ExteriorRing = new LinearRing2d(
new double[] { 50, 50, 60, 60, 50 },
new double[] { 10, 20, 20, 10, 10 });
LinearRing poly2InteriorRing = new LinearRing2d(
new double[] { 52, 52, 58, 58, 52 },
new double[] { 12, 18, 18, 12, 12 });
LinearRing[] poly2InteriorRings = new LinearRing[] { poly2InteriorRing };
Polygon polygon2 = new Polygon2d(poly2ExteriorRing, poly2InteriorRings);
Polygon[] memberPolygons = new Polygon[] { polygon1, polygon2 };
MultiPolygon multiPolygon = new MultiPolygon2d(memberPolygons);
A geometry collection
(com.objectfx.geometry.GeometryCollection) is a
heterogeneous collection of geometries. Geometry collections may contain
other geometry collections. All member geometries in a collection must be
associated with the same Coordinate Reference System. Geometry collections
are valid only if all their member geometries are valid.
The following example illustrates the construction of a geometry collection in the default Coordinate Reference System (WGS84):
Point point = new Point2d(54, 23);
LineString lineString = new LineString2d(
new double[] { 7, 6, 5 },
new double[] { 4, 3, 2 });
LinearRing polyExteriorRing = new LinearRing2d(
new double[] { -100, -100, -90, -90, -100 },
new double[] { 30, 40, 40, 30, 30 });
Polygon polygon = new Polygon2d(polyExteriorRing);
Geometry[] memberGeometries = new Geometry[] { point, lineString, polygon};
GeometryCollection geometryCollection = new GeometryCollection2d(memberGeometries);
An envelope (com.objectfx.geometry.Envelope)
is a two dimensional geometry specified by two corners, the lower left and
upper right. Envelopes are used to represent the minimum bounding
rectangle (MBR) of a geometry, per
Geometry.getEnvelope(), and also as search geometries
when querying data for map image generation and simple area searches.
Envelopes enforce that the minimum X ordinate is <= the maximum X
ordinate and the minimum Y ordinate is <= the maximum Y value.
The following example illustrates how to construct an Envelope geometry in the default Coordinate Reference System (WGS84):
double minX = -105.0; double minY = 25.0; double maxX = -82.0; double maxY = 51.0; Envelope envelope = new Envelope(minX, minY, maxX, maxY);
An alternative way of constructing an envelope is to use the factory
method Envelope.createEnvelope(). The following
example shows how to create an envelope using the
createEnvelope() method in the WGS84 Coordinate
Reference System:
Envelope envelope = Envelope.createEnvelope(minX, minY, maxX, maxY, Geometry.WGS84);
The createEnvelope() method also allows
construction of an envelope which spans the anti-meridian, provided that
the Coordinate Reference System has a continuous X-axis which can
wraparound, as with a geographic Coordinate Reference System. By
specifying a maximum X value that is > the minimum X value, it is
inferred that the envelope intends to span the anti-meridian. In these
cases a wrapped envelope will be created. Wrapped envelopes are discussed
in the next section.
A wrapped envelope
(com.objectfx.geometry.WrappedEnvelope) is a
specialization of an envelope, which contains an eastern and western
envelope pair sharing a boundary on the anti-meridian. This type of
envelope is most commonly used in queries when the area of interest spans
the anti-meridian, or as the envelope of a geometry collection where the
minimum bounding rectangle's shortest longitudinal path lies across the
anti-meridian. Further details about dealing with geometries which span
the anti-meridian can be found in Section C.4, “Boundary Cases”.
Wrapped envelopes may only be created using the
Envelope.createEnvelope() factory method, specifying
a specifying a maximum X value that is > the minimum X value. The
following example shows the creation of a wrapped envelope in the WGS84
Coordinate Reference System which spans the anti-meridian:
double minX = 160.0; double minY = 25.0; double maxX = -170.0; double maxY = 51.0; // note that minX > maxX WrappedEnvelope envelope = (WrappedEnvelope) Envelope.createEnvelope(minX, minY, maxX, maxY, Geometry.WGS84);
The spatial relationship between geometry objects can be determined by a set of methods inherent on each geometry type. The relations are based on the relation operators and the Dimensionally Extended 9 Intersection Model (DE-9IM) developed by Clementini, et al. laid forth in section 6.1.15 of [simple-feature-spec]. Implemented relations include: intersects, disjoint, contains, within, and overlaps. A covers relation is added in addition to the relations defined in the [simple-feature-spec]. The touches and crosses relationships are currently unsupported.
Each of the supported relation methods is described in the following sections. For a more thorough treatment of spatial relations, refer to the [simple-feature-spec]. To frame the overview, we need to cover a couple key ideas. First, the [simple-feature-spec] categorizes a geometry's points as belonging to either the interior, boundary or exterior. The boundary consists of points or lines that separate the interior from the exterior. The boundary of a point is the empty set. The boundary of a line consists of its end points. The boundary of a polygon is the line that describes its perimeter. The interior consists of points that are in the geometry but not on its boundary, and the exterior consists of those points that are not in the geometry's interior or boundary. Secondly, the OGC specification categorizes geometry by dimension. Points have a dimension of 0. Lines have a dimension of 1, and polygons have a dimension of 2. When a relation is computed between two geoemtries, we can think of the result as a geometry with dimensions of -1 (no relation), 0, 1, or 2.
The following sections describe the supported spatial relations along with tables and figures used to describe the relationships. The possible values found in the tables and their meanings are listed below:
T means an intersection must exist
F means an intersection must not exist.
* means it does not matter if an intersection exists or not. Applicable to the intersection geometry dimensions of -1, 0, 1, or 2;
0 means an intersection must exist and the intersection geometry must have a dimension of 0 (a point).
1 means an intersection must exist and the intersection geometry must have a dimension of 1 (a line string).
2 means an intersection must exist and the intersection geometry must have a dimension of 2 (a polygon).
Geometries intersect with each other if their boundaries and/or interiors intersect. The following set of tables illustrates the possible intersects cases.
Geometry A intersects geometry B is TRUE if the interiors of A and B intersect.
| Intersects | Geometry B | |||
| Interior | Boundary | Exterior | ||
| Geometry A | Interior | T | * | * |
| Boundary | * | * | * | |
| Exterior | * | * | * | |
Geometry A intersects geometry B is TRUE if the boundary points of A intersect with the boundary points of B.
| Intersects | Geometry B | |||
| Interior | Boundary | Exterior | ||
| Geometry A | Interior | * | T | * |
| Boundary | * | * | * | |
| Exterior | * | * | * | |
Geometry A intersects geometry B is TRUE if the boundary points of A intersect with the interior of B.
| Intersects | Geometry B | |||
| Interior | Boundary | Exterior | ||
| Geometry A | Interior | * | * | * |
| Boundary | T | * | * | |
| Exterior | * | * | * | |
Geometry A intersects geometry B is TRUE if the boundary points of A intersect with the boundary points of B.
| Intersects | Geometry B | |||
| Interior | Boundary | Exterior | ||
| Geometry A | Interior | * | * | * |
| Boundary | * | T | * | |
| Exterior | * | * | * | |
Geometries are considered disjoint if their boundaries and interiors do not intersect. Disjoint is the exact opposite of intersect. As the following table illustrates, geometry A is disjoint from geometry B if there is no intersection between the interior and boundary of A and the interior and boundary of B.
| Disjoint | Geometry B | |||
| Interior | Boundary | Exterior | ||
| Geometry A | Interior | F | F | * |
| Boundary | F | F | * | |
| Exterior | * | * | * | |
A geometry contains another geometry if the interior and boundary of the comparison geometry is completely contained in the interior of the other geometry. Contains is the exact opposite of within; any geometry A containing geometry B means that B is within A. In the following table, geometry A contains geometry B if all of the interior of A intersects with the interior of B and there is no intersection between the exterior of A and the interior and boundary of B.
| Contains | Geometry B | |||
| Interior | Boundary | Exterior | ||
| Geometry A | Interior | T | * | * |
| Boundary | * | * | * | |
| Exterior | F | F | * | |
A geometry is within another geometry if its interior and boundary are completely contained in the interior of the other geometry. The following table illustrates that geometry A is within geometry B if the interior of A intersects with the interior of B and there is no intersection between the interior and boundary of A with the exterior of B. Within is the exact opposite of contains.
| Within | Geometry B | |||
| Interior | Boundary | Exterior | ||
| Geometry A | Interior | T | * | F |
| Boundary | * | * | F | |
| Exterior | * | * | * | |
A geometry covers another geometry if it that geometry is completely contained in the interior or boundary of another geometry. Covers differs from contains in that the intersection of A's interior points with B's interior points can be a null set. For example, a point on a polygons boundary is covered by that polygon, but it is not contained by that polygon. The first set of tables below shows the patterns for the covers relation.
Geometry A covers geometry B is TRUE if the interiors of A and B intersect and there is no intersection between the exterior of A and the interior and boundary of B.
| Covers | Geometry B | |||
| Interior | Boundary | Exterior | ||
| Geometry A | Interior | T | * | * |
| Boundary | * | * | * | |
| Exterior | F | F | * | |
Geometry A covers geometry B is TRUE if the interior of A intersects with the boundary of B and there is no intersection between the exterior of A and the interior and boundary of B. This is shown in the polygon - line and polygon - point examples in Figure C.9, “Examples of Covers Relationship”.
| Covers | Geometry B | |||
| Interior | Boundary | Exterior | ||
| Geometry A | Interior | * | T | * |
| Boundary | * | * | * | |
| Exterior | F | F | * | |
Geometry A covers geometry B is TRUE if the boundary of A intersects the interior of B and there is no intersection between the exterior of A the interior and boundary of B. This is shown in the line - point example in Figure C.9, “Examples of Covers Relationship”.
| Covers | Geometry B | |||
| Interior | Boundary | Exterior | ||
| Geometry A | Interior | * | * | * |
| Boundary | T | * | * | |
| Exterior | F | F | * | |
Geometry A covers geometry B is TRUE if the boundary of A intersects the boundary of B and there is no intersection between the exterior of A and the interior and boundary of B.
| Covers | Geometry B | |||
| Interior | Boundary | Exterior | ||
| Geometry A | Interior | * | * | * |
| Boundary | * | T | * | |
| Exterior | F | F | * | |
Geometry A covered by geometry B is TRUE if the interior of A intersects with the interior of B and there is no intersection between the interior and boundary of A and the exterior of B.
| Covered By | Geometry B | |||
| Interior | Boundary | Exterior | ||
| Geometry A | Interior | T | * | F |
| Boundary | * | * | F | |
| Exterior | * | * | * | |
Geometry A covered by geometry B is TRUE if the interior of A intersects with the boundary of B and there is no intersection between the interior and boundary of A and the exterior of B.
| Covered By | Geometry B | |||
| Interior | Boundary | Exterior | ||
| Geometry A | Interior | * | T | F |
| Boundary | * | * | F | |
| Exterior | * | * | * | |
Geometry A covered by geometry B is TRUE if the boundary of A intersects with the interior of B and there is no intersection between the interior and boundary of A and the exterior of B.
| Covered By | Geometry B | |||
| Interior | Boundary | Exterior | ||
| Geometry A | Interior | * | * | F |
| Boundary | T | * | F | |
| Exterior | * | * | * | |
Geometry A covered by geometry B is TRUE if the boundary of A intersects with the boundary of B and there is no intersection between the interior and boundary of A and the exterior of B.
| Covered By | Geometry B | |||
| Interior | Boundary | Exterior | ||
| Geometry A | Interior | * | * | F |
| Boundary | * | T | F | |
| Exterior | * | * | * | |
Overlaps only compares geometries of the same spatial dimension and checks that the intersection set of both geometries results in a different geometry of the same spatial dimension. For example, A overlaps B if the intersection of A and B's interior points is not an empty set and the intersection of A's interior points and B's exterior points is not an empty set and the intersection of B's interior points and A's exterior points is not an empty set.
The following table shows how relations of polygon to polygon, multi-point to multi-point, and multi-polygon to multi-polygon are interpreted. A overlaps B is TRUE if the interior and exterior of A intersects the interior and exterior of B. This is shown in the polygon - polygon example in Figure C.10, “Examples of Overlaps Relationship”.
| Overlaps | Geometry B | |||
| Interior | Boundary | Exterior | ||
| Geometry A | Interior | T | * | T |
| Boundary | * | * | * | |
| Exterior | T | * | * | |
The following table shows how relations of line string to line string and multi-line string to multi-line string are interpreted. Geometry A overlaps geometry B if the interior of A intersects the interior of B as a 1-dimensional geometry (a line string), the exterior of A intersects the interior of B, and there is no intersection between the interior of A with the exterior of B. This is shown in the line - line example in Figure C.10, “Examples of Overlaps Relationship”. Overlaps is FALSE if the intersection of the interiors results in a 0-dimensional geometry (a point).
| Overlaps | Geometry B | |||
| Interior | Boundary | Exterior | ||
| Geometry A | Interior | 1 | * | F |
| Boundary | * | * | * | |
| Exterior | T | * | * | |
SpatialRules supports a limited set of three-dimensional (3D) geometries called extruded geometries. An extruded geometry is a two-dimensional (2D) geometry that supports an altitude and a height. Sometimes these geometries are also referred to as "two-and-a-half-D" geometries. For example, here is a simple polygon and an extruded version of the same polygon (seen from an oblique view):

A LineString becomes a wall when extruded:

And a point becomes a post:

Geometry coordinates are interpreted strictly in 2-dimensional linear fashion. As such, geometries based on geodetic, or geographic angular, coordinates have special considerations when dealing with boundary cases along the edges of the coordinate space. The following sections cover how to represent datasets which need to correctly span the anti-meridian and/or the poles.
The anti-meridian, the boundary between the 180th and -180th meridians, is one area which special attention needs to be paid when using non-collection geometries, such as line strings, polygons, and envelopes. Non-collection geometries are not allowed to span the anti-meridian; they must be split on the anti-meridian and grouped into geometry collections. Each member geometry needs to include coordinates up to and including the anti-meridian boundary coordinates. Geometries that are not separated into regions which do not span the anti-meridian are interpreted strictly in 2-dimensional linear space and will be interpreted as if they span the opposite meridian (the prime meridian).
Take for instance a polygon defined by the following geometry OGC Well-Known Text (WKT):
POLYGON((150 -20,150 25,-150 25,-150 0))
Based solely on these coordinates it would be interpreted to span the area from -150 to 150 longitude. The figure below depicts how the above polygon would be interpreted. As you can see it crosses the prime meridian, which are the left and right edges of the figure below, and not the anti-meridian as we are intending.
In order to span the anti-meridian, the polygon described above must be split into a multi-polygon representing the discrete areas between 150 and 180 longitude and between -180 and -150 longitude. To do this a segment running along the anti-meridian on both sides must be present in the coordinate values. This is shown in the following multi-polygon WKT:
MULTIPOLYGON(((150 -20,150 25,180 25,180 -20)),((-180 -20,-180 25,-150 25, -150 -20)))
The figure below depicts the above multi-polygon with boundary coordinates highlighted. As you can see it spans the area up to and including the anti-meridian on both sides, giving the correct spatial coverage.
The same restriction applies also to line strings and envelopes,
point geometries cannot cross the anti-meridian so they are exempt. Line
strings must be split into multi-line strings; envelopes must be
represented as a wrapped envelope, a two-part envelope, which is created
using the Envelope.createEnvelope() method. Refer to
the discussion on wrapped envelope geometries in Section C.1, “Geometry Object Model” for more details on creating them.
Polygons or envelopes based on geodetic coordinates which need to span polar regions also have special considerations. Since geometries are 2-dimensional and interpreted linearly, these geometries must be created with coordinates representing the boundaries of the longitudinal and latitudinal axes of the coordinate system.
Consider the following figure which depicts a geodetic area encompassing the north pole, from about 70 degrees north latitude up to 90 degrees north latitude. This figure shows the earth as a sphere and how the area would appear as viewed from directly over the pole.
To properly represent an area encompassing a pole like the one described in the above figure, the geometry's coordinate array must include coordinate pairs with the minimum and maximum longitudinal (X) axis values coupled with the maximum or minimum latitudinal (Y) axis values, depending on the pole being encompassed.
In the above figure, the north pole is a single point at 90 degrees which encompassing all longitudinal axis values. In order to accurately represent this area in a 2-dimensional geometry, that single point must be turned into a segment. This can be done by using the minimum and maximum longitude values coupled with the maximum latitude value (e.g. a segment with coordinates of -180,90 to 180,90). The other segments of the polygon run along both sides of the anti-meridian boundary down to the minimum latitude with a final segment spanning the longitudinal axis on the minimum latitude. This creates a band which spans the entire longitudinal axis and spans from 70 degrees north latitude up to 90 degrees north latitude. The coordinates needed to represent this polygon are shown in the following OGC Well-Known Text (WKT):
POLYGON((-180 80,-180 90,180 90,180 80))
The figure below depicts how the geometry defined above would look in the Plate Carrée projection for reference. As you can see in this projection, the single point of the pole is actually represented by a segment spanning the entire longitudinal axis. The boundary coordinates discussed above are highlighted.
The following additional examples in OGC Well-known text show special or unusual cases. These are included to illustrate how the coordinates of a polygon need to be constructed to be interpreted correctly with longitude/latitude data.
POLYGON((-180 -90,-180 90,180 90, 180 -90)) is the
entire Earth.
POLYGON((-180 -90,-180 30,180 30,180 -90)) is the
entire Earth below latitude 30 (inverse of example above).
POLYGON((25 -90,25 90,50 90,50 -90)) is a band from
the South Pole to the North Pole between longitudes 25 and 50.
POLYGON((10 -90, 10 50, 40 50, 40 -90)) is a band
from the South Pole to latitude 50 between longitudes 10 and
40.
POLYGON((-180 -10,-180 5,180 5,180 -10)) is a band
that wraps the equator from 10 degrees south to 5 degrees
north.
The following is a glossary of terms used by SpatialRules. This glossary contains current as well as older and obsolete terms for historical reference.
Version 2.0 only. Represented a spatial or temporal bound defining a specific region of space or time. This concept was replaced by "reference feature" for spatial bounds and "period" for temporal bounds
Version 2.0 only. Represented a collection of bounds that can be referenced from a rule to apply logic over a set of spatial or temporal bounds. This term has been replaced with FeatureSet.
Part of an expression used to compare values.
Version 2.0 only. The Java class used to represent a named spatial or temporal bound. This has been replaced with Feature.
Different data types are supported for attribute values. The types must be explicitly indicated when performing operations on different data types. Supported data types include (char, number, date)
As of version 3.0. Objects that are submitted to SpatialRules for evaluation. In previous versions this was named Locatable or LocatableObject.
The logic used to encode a rule. The terms rule and expression are interchangeable. An expression can be encoded using Java or RulesScript.
Class used by applications to communicate with the SpatialRules server. The input client provides mechanisms for converting data formats and handling errors.
Version 2.0 only. Refers to a location report submitted to the rule engine. This term is synonymous with "object of interest" or "entity". This term has been replaced with "Dynamic Feature."
The position (lon, lat) and capture time referenced in a location report. For versions 3.0 and above the location may contain any supported geometry.
Refers to a single piece of data about a Dynamic Feature that can be submitted to the rule engine for evaluation. The data contains an ID, type, location/geometry, timestamp, and an optional set of business attributes.
Open Geospatial Consortium (www.opengeospatial.org).
The Java class used to represent a recurring time frame.
The object containing evaluation results including the subject, a set of targets, and the name of the rule that evaluated to True.
Service that resides within the SpatialRules server that accepts incoming data. The Rules Server communicates with the InputClient.
SpatialRules server that is run from the command line.
The subject object of interest (i.e., DynamicFeature) that is evaluated by a set of rules. When a rule evaluates to True, the result will contain the subject feature that was involved in making the expression True.
The target is either a bounds or locatable involved in a rule expression. When a rule evaluates to True, the result will contain a list of zero or more targets that were involved in making the expression True.
Version 2.0 only. The Java class used to represent a temporal bounds, either fixed or recurring. This has been replaced with Period.
[crs] Geographic information — Spatial referencing by coordinates. 2004-08-02. International Organization for Standardization (ISO). ISO/DIS 19111.
[filter-encoding-spec] OpenGIS® Filter Encoding Implementation Specification. 1.1.0. 3 May 2005. Open Geospatial Consortium Inc.. Panagiotis A. Vretanos. OGC 04-095.
[simple-feature-spec] OpenGIS® Implementation Specification for Geographic information — Simple feature access — Part 1: Common architecture. 1.2.0. 2006-10-05. Open Geospatial Consortium Inc.. John R. Herring. OGC 06-103r3.