Class AbstractConvexHyperplaneBoundedRegion<P extends Point<P>,S extends HyperplaneConvexSubset<P>>
- java.lang.Object
-
- org.apache.commons.geometry.core.partitioning.AbstractConvexHyperplaneBoundedRegion<P,S>
-
- Type Parameters:
P
- Point implementation typeS
- Hyperplane convex subset implementation type
- All Implemented Interfaces:
HyperplaneBoundedRegion<P>
,Splittable<P,HyperplaneBoundedRegion<P>>
,Region<P>
,Sized
- Direct Known Subclasses:
ConvexArea
,ConvexArea2S
,ConvexVolume
public abstract class AbstractConvexHyperplaneBoundedRegion<P extends Point<P>,S extends HyperplaneConvexSubset<P>> extends java.lang.Object implements HyperplaneBoundedRegion<P>
Base class for convex hyperplane-bounded regions. This class provides generic implementations of many algorithms related to convex regions.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description protected static class
AbstractConvexHyperplaneBoundedRegion.ConvexRegionBoundaryBuilder<P extends Point<P>,S extends HyperplaneConvexSubset<P>>
Internal class encapsulating the logic for building convex region boundaries from collections of hyperplanes.
-
Field Summary
Fields Modifier and Type Field Description private java.util.List<S>
boundaries
List of boundaries for the region.
-
Constructor Summary
Constructors Modifier Constructor Description protected
AbstractConvexHyperplaneBoundedRegion(java.util.List<S> boundaries)
Simple constructor.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description RegionLocation
classify(P pt)
Classify the given point with respect to the region.private SplitLocation
determineRegionPlusMinusLocation(Hyperplane<P> splitter)
Determine whether the region lies on the plus or minus side of the given splitter.java.util.List<S>
getBoundaries()
Get the boundaries of the convex region.double
getBoundarySize()
Get the size of the boundary of the region.boolean
isEmpty()
Return true if the region is completely empty, ie all points in the space are classified asoutside
.boolean
isFull()
Return true if the region spans the entire space.P
project(P pt)
Project a point onto the boundary of the region.private void
splitBoundaries(Hyperplane<P> splitter, java.lang.Class<S> boundaryType, java.util.List<S> minusBoundaries, java.util.List<S> plusBoundaries)
Split the boundaries of the region by the given hyperplane, adding the split parts into the corresponding lists.protected <R extends AbstractConvexHyperplaneBoundedRegion<P,S>>
Split<R>splitInternal(Hyperplane<P> splitter, R thisInstance, java.lang.Class<S> boundaryType, java.util.function.Function<java.util.List<S>,R> factory)
Generic, internal split method.private <R extends AbstractConvexHyperplaneBoundedRegion<P,S>>
Split<R>splitInternalFull(Hyperplane<P> splitter, java.lang.Class<S> boundaryType, java.util.function.Function<? super java.util.List<S>,R> factory)
Internal split method for use with full regions, i.e.private <R extends AbstractConvexHyperplaneBoundedRegion<P,S>>
Split<R>splitInternalNonFull(Hyperplane<P> splitter, R thisInstance, java.lang.Class<S> boundaryType, java.util.function.Function<? super java.util.List<S>,R> factory)
Internal split method for use with non-full regions, i.e.protected boolean
swapsInsideOutside(Transform<P> transform)
Return true if the given transform swaps the inside and outside of the region.java.lang.String
toString()
protected <R extends AbstractConvexHyperplaneBoundedRegion<P,S>>
RtransformInternal(Transform<P> transform, R thisInstance, java.lang.Class<S> boundaryType, java.util.function.Function<? super java.util.List<S>,R> factory)
Generic, internal transform method.HyperplaneConvexSubset<P>
trim(HyperplaneConvexSubset<P> sub)
Trim the given hyperplane subset to the portion contained inside this instance.-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
-
Methods inherited from interface org.apache.commons.geometry.core.Region
contains, getCentroid
-
Methods inherited from interface org.apache.commons.geometry.core.Sized
getSize, isFinite, isInfinite
-
Methods inherited from interface org.apache.commons.geometry.core.partitioning.Splittable
split
-
-
-
-
Field Detail
-
boundaries
private final java.util.List<S extends HyperplaneConvexSubset<P>> boundaries
List of boundaries for the region.
-
-
Constructor Detail
-
AbstractConvexHyperplaneBoundedRegion
protected AbstractConvexHyperplaneBoundedRegion(java.util.List<S> boundaries)
Simple constructor. Callers are responsible for ensuring that the given list of boundaries define a convex region. No validation is performed.- Parameters:
boundaries
- the boundaries of the convex region
-
-
Method Detail
-
getBoundaries
public java.util.List<S> getBoundaries()
Get the boundaries of the convex region. The exact ordering of the boundaries is not guaranteed.- Returns:
- the boundaries of the convex region
-
isFull
public boolean isFull()
Return true if the region spans the entire space. In other words, a region is full if no points in the space are classified asoutside
.
-
isEmpty
public boolean isEmpty()
Return true if the region is completely empty, ie all points in the space are classified asoutside
.This method always returns false.
-
getBoundarySize
public double getBoundarySize()
Get the size of the boundary of the region. The size is a value in thed-1
dimension space. For example, in Euclidean space, this will be a length in 2D and an area in 3D.- Specified by:
getBoundarySize
in interfaceRegion<P extends Point<P>>
- Returns:
- the size of the boundary of the region
-
classify
public RegionLocation classify(P pt)
Classify the given point with respect to the region.
-
trim
public HyperplaneConvexSubset<P> trim(HyperplaneConvexSubset<P> sub)
Trim the given hyperplane subset to the portion contained inside this instance.- Parameters:
sub
- hyperplane subset to trim. Null is returned if the subset does not intersect the instance.- Returns:
- portion of the argument that lies entirely inside the region represented by this instance, or null if it does not intersect.
-
toString
public java.lang.String toString()
- Overrides:
toString
in classjava.lang.Object
-
transformInternal
protected <R extends AbstractConvexHyperplaneBoundedRegion<P,S>> R transformInternal(Transform<P> transform, R thisInstance, java.lang.Class<S> boundaryType, java.util.function.Function<? super java.util.List<S>,R> factory)
Generic, internal transform method. Subclasses should use this to implement their own transform methods.- Type Parameters:
R
- Region implementation type- Parameters:
transform
- the transform to apply to the instancethisInstance
- a reference to the current instance; this is passed as an argument in order to allow it to be a generic typeboundaryType
- the type used for the boundary hyperplane subsetsfactory
- function used to create new convex region instances- Returns:
- the result of the transform operation
-
swapsInsideOutside
protected boolean swapsInsideOutside(Transform<P> transform)
Return true if the given transform swaps the inside and outside of the region.The default behavior of this method is to return true if the transform does not preserve spatial orientation (ie,
Transform.preservesOrientation()
is false). Subclasses may need to override this method to implement the correct behavior for their space and dimension.- Parameters:
transform
- transform to check- Returns:
- true if the given transform swaps the interior and exterior of the region
-
splitInternal
protected <R extends AbstractConvexHyperplaneBoundedRegion<P,S>> Split<R> splitInternal(Hyperplane<P> splitter, R thisInstance, java.lang.Class<S> boundaryType, java.util.function.Function<java.util.List<S>,R> factory)
Generic, internal split method. Subclasses should call this from theirSplittable.split(Hyperplane)
methods.- Type Parameters:
R
- Region implementation type- Parameters:
splitter
- splitting hyperplanethisInstance
- a reference to the current instance; this is passed as an argument in order to allow it to be a generic typeboundaryType
- the type used for the boundary hyperplane subsetsfactory
- function used to create new convex region instances- Returns:
- the result of the split operation
-
splitInternalFull
private <R extends AbstractConvexHyperplaneBoundedRegion<P,S>> Split<R> splitInternalFull(Hyperplane<P> splitter, java.lang.Class<S> boundaryType, java.util.function.Function<? super java.util.List<S>,R> factory)
Internal split method for use with full regions, i.e. regions that cover the entire space.- Type Parameters:
R
- Region implementation type- Parameters:
splitter
- splitting hyperplaneboundaryType
- the type used for the boundary hyperplane subsetsfactory
- function used to create new convex region instances- Returns:
- the result of the split operation
-
splitInternalNonFull
private <R extends AbstractConvexHyperplaneBoundedRegion<P,S>> Split<R> splitInternalNonFull(Hyperplane<P> splitter, R thisInstance, java.lang.Class<S> boundaryType, java.util.function.Function<? super java.util.List<S>,R> factory)
Internal split method for use with non-full regions, i.e. regions that do not cover the entire space.- Type Parameters:
R
- Region implementation type- Parameters:
splitter
- splitting hyperplanethisInstance
- a reference to the current instance; this is passed as an argument in order to allow it to be a generic typeboundaryType
- the type used for the boundary hyperplane subsetsfactory
- function used to create new convex region instances- Returns:
- the result of the split operation
-
determineRegionPlusMinusLocation
private SplitLocation determineRegionPlusMinusLocation(Hyperplane<P> splitter)
Determine whether the region lies on the plus or minus side of the given splitter. It is assumed that (1) the region is not full, and (2) the given splitter does not pass through the region.In theory, this is a very simple operation: one need only test a single region boundary to see if it lies on the plus or minus side of the splitter. In practice, however, accumulated floating point errors can cause discrepancies between the splitting operations, causing boundaries to be classified as lying on both sides of the splitter when they should only lie on one. Therefore, this method examines as many boundaries as needed in order to determine the best response. The algorithm proceeds as follows:
- If any boundary lies completely on the minus or plus side of the splitter, then
MINUS
orPLUS
is returned, respectively. - If any boundary is coincident with the splitter (
NEITHER
), thenMINUS
is returned if the boundary hyperplane has the same orientation as the splitter, otherwisePLUS
. - If no boundaries match the above conditions, then the sizes of the split boundaries are compared. If
the sum of the sizes of the boundaries on the minus side is greater than the sum of the sizes of
the boundaries on the plus size, then
MINUS
is returned. Otherwise,PLUS
is returned.
- Parameters:
splitter
- splitter to classify the region against; the splitter is assumed to lie completely outside of the region- Returns:
SplitLocation.MINUS
if the region lies on the minus side of the splitter andSplitLocation.PLUS
if the region lies on the plus side of the splitter
- If any boundary lies completely on the minus or plus side of the splitter, then
-
splitBoundaries
private void splitBoundaries(Hyperplane<P> splitter, java.lang.Class<S> boundaryType, java.util.List<S> minusBoundaries, java.util.List<S> plusBoundaries)
Split the boundaries of the region by the given hyperplane, adding the split parts into the corresponding lists.- Parameters:
splitter
- splitting hyperplaneboundaryType
- the type used for the boundary hyperplane subsetsminusBoundaries
- list that will contain the portions of the boundaries on the minus side of the splitting hyperplaneplusBoundaries
- list that will contain the portions of the boundaries on the plus side of the splitting hyperplane
-
-