This article describes how to create custom topological relations for the
ILcd2DAdvancedBinaryTopology
interface.
Make sure you are familiar with the key concepts of the DE-9IM model before reading this article.
The method checkTopology
of an ILcd2DAdvancedBinaryTopology
instance has three parameters:
two shapes and the topological relation that you want to compute for these two shapes.
Instead of using a predefined topological relation , you can also define a custom relation.
Creating a custom topological relation requires a new implementation of the interface
ILcdIntersectionMatrixPattern
which can be passed on as third argument to the method checkTopology
.
This comes down to implementing the method matches
of the interfaceILcdIntersectionMatrixPattern
.
This method takes an ILcdIntersectionMatrix
instance as argument and returns a boolean value indicating whether this intersection matrix passes the set of conditions
imposed by the custom topological relation.
This set of conditions could depend on the nine elements of the intersection matrix and the dimensions of the two involved
shapes.
/**
* Custom defined topological relation which can be used with the {@link ILcd2DAdvancedBinaryTopology} interface.
* This example emulates the line-intersect relation which exists in
* {@linkplain ILcd2DBinaryTopology#LINE_INTERSECT the binary topology interface}.
*/
public static class LineIntersect implements ILcdIntersectionMatrixPattern {
@Override
public boolean matches(ILcdIntersectionMatrix aMatrix) {
// Get shape dimensions.
ELcdGeometryDimension dim1 = aMatrix.getShapeDimension(0);
ELcdGeometryDimension dim2 = aMatrix.getShapeDimension(1);
// Get required element dimensions.
ELcdGeometryDimension dimII = aMatrix.getDimension(ELcdGeometryRegion.INTERIOR, ELcdGeometryRegion.INTERIOR);
ELcdGeometryDimension dimIB = aMatrix.getDimension(ELcdGeometryRegion.INTERIOR, ELcdGeometryRegion.BOUNDARY);
ELcdGeometryDimension dimBI = aMatrix.getDimension(ELcdGeometryRegion.BOUNDARY, ELcdGeometryRegion.INTERIOR);
ELcdGeometryDimension dimBB = aMatrix.getDimension(ELcdGeometryRegion.BOUNDARY, ELcdGeometryRegion.BOUNDARY);
if (dim1 == ELcdGeometryDimension.POINT || dim2 == ELcdGeometryDimension.POINT) {
// Points do not line intersect
return false;
} else if (dim1 == ELcdGeometryDimension.LINE && dim2 == ELcdGeometryDimension.LINE) {
// Two lines intersect if their interiors and/or boundaries intersect.
return dimII != ELcdGeometryDimension.FALSE || dimIB != ELcdGeometryDimension.FALSE ||
dimBI != ELcdGeometryDimension.FALSE || dimBB != ELcdGeometryDimension.FALSE;
} else if (dim1 == ELcdGeometryDimension.LINE && dim2 == ELcdGeometryDimension.AREA) {
// A line and an area line intersect if the interior or the boundary
// of the line intersects the boundary of the area.
return dimIB != ELcdGeometryDimension.FALSE || dimBB != ELcdGeometryDimension.FALSE;
} else if (dim1 == ELcdGeometryDimension.AREA && dim2 == ELcdGeometryDimension.LINE) {
// A line and an area line intersect if the interior or the boundary
// of the line intersects the boundary of the area.
return dimBI != ELcdGeometryDimension.FALSE || dimBB != ELcdGeometryDimension.FALSE;
} else if (dim1 == ELcdGeometryDimension.AREA && dim2 == ELcdGeometryDimension.AREA) {
// Two areas line intersect if their boundaries intersect.
return dimBB != ELcdGeometryDimension.FALSE;
}
return false;
}
}
Once the relationship is created, you can use it like you use the predefined relationships:
public static void main(String[] args) {
// Test two shapes with the new LineIntersect relation.
TLcdXYPolyline shape1 = new TLcdXYPolyline(new TLcd2DEditablePointList(new ILcd2DEditablePoint[]{
new TLcdXYPoint(0.0, 0.0),
new TLcdXYPoint(10.0, 10.0)}, false));
TLcdXYPolyline shape2 = new TLcdXYPolyline(new TLcd2DEditablePointList(new ILcd2DEditablePoint[]{
new TLcdXYPoint(0.0, 10.0),
new TLcdXYPoint(10.0, 0.0)}, false));
// Create the advanced binary topology.
ILcd2DAdvancedBinaryTopology topology = new TLcdCartesianAdvancedBinaryTopology();
ILcdIntersectionMatrixPattern LINE_INTERSECT = new LineIntersect();
// Test if the shapes line intersect.
boolean line_intersects = topology.checkTopology(shape1, shape2, LINE_INTERSECT);
System.out.println("The lines intersect: " + line_intersects);
}
Full code
import com.luciad.geometry.topology.ELcdGeometryDimension;
import com.luciad.geometry.topology.ELcdGeometryRegion;
import com.luciad.geometry.topology.ILcd2DAdvancedBinaryTopology;
import com.luciad.geometry.topology.ILcdIntersectionMatrix;
import com.luciad.geometry.topology.ILcdIntersectionMatrixPattern;
import com.luciad.geometry.topology.cartesian.TLcdCartesianAdvancedBinaryTopology;
import com.luciad.geometry.topology.ILcd2DBinaryTopology;
import com.luciad.shape.shape2D.ILcd2DEditablePoint;
import com.luciad.shape.shape2D.TLcd2DEditablePointList;
import com.luciad.shape.shape2D.TLcdXYPoint;
import com.luciad.shape.shape2D.TLcdXYPolyline;
public class CreateCustomRelationSnippets {
/**
* Custom defined topological relation which can be used with the {@link ILcd2DAdvancedBinaryTopology} interface.
* This example emulates the line-intersect relation which exists in
* {@linkplain ILcd2DBinaryTopology#LINE_INTERSECT the binary topology interface}.
*/
public static class LineIntersect implements ILcdIntersectionMatrixPattern {
@Override
public boolean matches(ILcdIntersectionMatrix aMatrix) {
// Get shape dimensions.
ELcdGeometryDimension dim1 = aMatrix.getShapeDimension(0);
ELcdGeometryDimension dim2 = aMatrix.getShapeDimension(1);
// Get required element dimensions.
ELcdGeometryDimension dimII = aMatrix.getDimension(ELcdGeometryRegion.INTERIOR, ELcdGeometryRegion.INTERIOR);
ELcdGeometryDimension dimIB = aMatrix.getDimension(ELcdGeometryRegion.INTERIOR, ELcdGeometryRegion.BOUNDARY);
ELcdGeometryDimension dimBI = aMatrix.getDimension(ELcdGeometryRegion.BOUNDARY, ELcdGeometryRegion.INTERIOR);
ELcdGeometryDimension dimBB = aMatrix.getDimension(ELcdGeometryRegion.BOUNDARY, ELcdGeometryRegion.BOUNDARY);
if (dim1 == ELcdGeometryDimension.POINT || dim2 == ELcdGeometryDimension.POINT) {
// Points do not line intersect
return false;
} else if (dim1 == ELcdGeometryDimension.LINE && dim2 == ELcdGeometryDimension.LINE) {
// Two lines intersect if their interiors and/or boundaries intersect.
return dimII != ELcdGeometryDimension.FALSE || dimIB != ELcdGeometryDimension.FALSE ||
dimBI != ELcdGeometryDimension.FALSE || dimBB != ELcdGeometryDimension.FALSE;
} else if (dim1 == ELcdGeometryDimension.LINE && dim2 == ELcdGeometryDimension.AREA) {
// A line and an area line intersect if the interior or the boundary
// of the line intersects the boundary of the area.
return dimIB != ELcdGeometryDimension.FALSE || dimBB != ELcdGeometryDimension.FALSE;
} else if (dim1 == ELcdGeometryDimension.AREA && dim2 == ELcdGeometryDimension.LINE) {
// A line and an area line intersect if the interior or the boundary
// of the line intersects the boundary of the area.
return dimBI != ELcdGeometryDimension.FALSE || dimBB != ELcdGeometryDimension.FALSE;
} else if (dim1 == ELcdGeometryDimension.AREA && dim2 == ELcdGeometryDimension.AREA) {
// Two areas line intersect if their boundaries intersect.
return dimBB != ELcdGeometryDimension.FALSE;
}
return false;
}
}
public static void main(String[] args) {
// Test two shapes with the new LineIntersect relation.
TLcdXYPolyline shape1 = new TLcdXYPolyline(new TLcd2DEditablePointList(new ILcd2DEditablePoint[]{
new TLcdXYPoint(0.0, 0.0),
new TLcdXYPoint(10.0, 10.0)}, false));
TLcdXYPolyline shape2 = new TLcdXYPolyline(new TLcd2DEditablePointList(new ILcd2DEditablePoint[]{
new TLcdXYPoint(0.0, 10.0),
new TLcdXYPoint(10.0, 0.0)}, false));
// Create the advanced binary topology.
ILcd2DAdvancedBinaryTopology topology = new TLcdCartesianAdvancedBinaryTopology();
ILcdIntersectionMatrixPattern LINE_INTERSECT = new LineIntersect();
// Test if the shapes line intersect.
boolean line_intersects = topology.checkTopology(shape1, shape2, LINE_INTERSECT);
System.out.println("The lines intersect: " + line_intersects);
}
}