blob: 50dd742ef5422726f02d7cd0542ea6ed773570da [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.geometry.core.partitioning.bsp;
import org.apache.commons.geometry.core.Point;
import org.apache.commons.geometry.core.Transform;
import org.apache.commons.geometry.core.partitioning.BoundarySource;
import org.apache.commons.geometry.core.partitioning.ConvexSubHyperplane;
import org.apache.commons.geometry.core.partitioning.Hyperplane;
import org.apache.commons.geometry.core.partitioning.SubHyperplane;
/** Interface for Binary Space Partitioning (BSP) trees.
* @param <P> Point implementation type
* @param <N> Node implementation type
*/
public interface BSPTree<P extends Point<P>, N extends BSPTree.Node<P, N>>
extends BSPSubtree<P, N> {
/** Enum specifying possible behaviors when a point used to locate a node
* falls directly on the cut subhyperplane of an internal node.
*/
enum NodeCutRule {
/** Choose the minus child of the internal node and continue searching.
* This behavior will result in a leaf node always being returned by the
* node search.
*/
MINUS,
/** Choose the plus child of the internal node and continue searching.
* This behavior will result in a leaf node always being returned by the
* node search.
*/
PLUS,
/** Choose the internal node and stop searching. This behavior may result
* in non-leaf nodes being returned by the node search.
*/
NODE
}
/** Get the root node of the tree.
* @return the root node of the tree
*/
N getRoot();
/** Find a node in this subtree containing the given point or its interior or boundary.
* When a point lies directly on the cut of an internal node, the minus child of the
* cut is chosen. This is equivalent to {@code subtree.findNode(pt, NodeCutRule.MINUS)}
* and always returns a leaf node.
* @param pt test point used to locate a node in the tree
* @return leaf node containing the point on its interior or boundary
* @see #findNode(Point, NodeCutRule)
*/
default N findNode(P pt) {
return findNode(pt, NodeCutRule.MINUS);
}
/** Find a node in this subtree containing the given point on it interior or boundary. The
* search should always return a leaf node except in the cases where the given point lies
* exactly on the cut subhyperplane of an internal node. In this case, it is unclear whether
* the search should continue with the minus child, the plus child, or end with the internal
* node. The {@code cutRule} argument specifies what should happen in this case.
* <ul>
* <li>{@link NodeCutRule#MINUS} - continue the search in the minus subtree</li>
* <li>{@link NodeCutRule#PLUS} - continue the search in the plus subtree</li>
* <li>{@link NodeCutRule#NODE} - stop the search and return the internal node</li>
* </ul>
* @param pt test point used to locate a node in the tree
* @param cutRule value used to determine the search behavior when the test point lies
* exactly on the cut subhyperplane of an internal node
* @return node containing the point on its interior or boundary
* @see #findNode(Point)
*/
N findNode(P pt, NodeCutRule cutRule);
/** Insert a subhyperplane into the tree.
* @param sub the subhyperplane to insert into the tree
*/
void insert(SubHyperplane<P> sub);
/** Insert a convex subhyperplane into the tree.
* @param convexSub the convex subhyperplane to insert into the tree
*/
void insert(ConvexSubHyperplane<P> convexSub);
/** Insert a set of convex subhyperplanes into the tree.
* @param convexSubs iterable containing a collection of subhyperplanes
* to insert into the tree
*/
void insert(Iterable<? extends ConvexSubHyperplane<P>> convexSubs);
/** Insert all convex subhyperplanes from the given source into the tree.
* @param boundarySrc source of boundary convex subhyperplanes to insert
* into the tree
*/
void insert(BoundarySource<? extends ConvexSubHyperplane<P>> boundarySrc);
/** Make the current instance a deep copy of the argument.
* @param src the tree to copy
*/
void copy(BSPTree<P, N> src);
/** Set this instance to the region represented by the given node. The
* given node could have come from this tree or a different tree.
* @param node the node to extract
*/
void extract(N node);
/** Transform this tree. Each cut subhyperplane in the tree is transformed in place using
* the given {@link Transform}.
* @param transform the transform to apply
*/
void transform(Transform<P> transform);
/** Interface for Binary Space Partitioning (BSP) tree nodes.
* @param <P> Point type
* @param <N> BSP tree node implementation type
*/
interface Node<P extends Point<P>, N extends Node<P, N>> extends BSPSubtree<P, N> {
/** Get the {@link BSPTree} that owns the node.
* @return the owning tree
*/
BSPTree<P, N> getTree();
/** Get the depth of the node in the tree. The root node of the tree
* has a depth of 0.
* @return the depth of the node in the tree
*/
int depth();
/** Get the parent of the node. This will be null if the node is the
* root of the tree.
* @return the parent node for this instance
*/
N getParent();
/** Get the cut for the node. This is a convex subhyperplane that splits
* the region for the cell into two disjoint regions, namely the plus and
* minus regions. This will be null for leaf nodes.
* @see #getPlus()
* @see #getMinus()
* @return the cut subhyperplane for the cell
*/
ConvexSubHyperplane<P> getCut();
/** Get the hyperplane belonging to the node cut, if it exists.
* @return the hyperplane belonging to the node cut, or null if
* the node does not have a cut
* @see #getCut()
*/
Hyperplane<P> getCutHyperplane();
/** Get the node for the minus region of the cell. This will be null if the
* node has not been cut, ie if it is a leaf node.
* @return the node for the minus region of the cell
*/
N getMinus();
/** Get the node for the plus region of the cell. This will be null if the
* node has not been cut, ie if it is a leaf node.
* @return the node for the plus region of the cell
*/
N getPlus();
/** Return true if the node is a leaf node, meaning that it has no
* binary partitioner (aka "cut") and therefore no child nodes.
* @return true if the node is a leaf node
*/
boolean isLeaf();
/** Return true if the node is an internal node, meaning that is
* has a binary partitioner (aka "cut") and therefore two child nodes.
* @return true if the node is an internal node
*/
boolean isInternal();
/** Return true if the node has a parent and is the parent's minus
* child.
* @return true if the node is the minus child of its parent
*/
boolean isMinus();
/** Return true if the node has a parent and is the parent's plus
* child.
* @return true if the node is the plus child of its parent
*/
boolean isPlus();
/** Insert a cut into this node. If the given hyperplane intersects
* this node's region, then the node's cut is set to the {@link ConvexSubHyperplane}
* representing the intersection, new plus and minus child leaf nodes
* are assigned, and true is returned. If the hyperplane does not intersect
* the node's region, then the node's cut and plus and minus child references
* are all set to null (ie, it becomes a leaf node) and false is returned. In
* either case, any existing cut and/or child nodes are removed by this method.
* @param cutter the hyperplane to cut the node's region with
* @return true if the cutting hyperplane intersected the node's region, resulting
* in the creation of new child nodes
*/
boolean insertCut(Hyperplane<P> cutter);
/** Remove the cut from this node. Returns true if the node previously had a cut.
* @return true if the node had a cut before the call to this method
*/
boolean clearCut();
/** Cut this node with the given hyperplane. The same node is returned, regardless of
* the outcome of the cut operation. If the operation succeeded, then the node will
* have plus and minus child nodes.
* @param cutter the hyperplane to cut the node's region with
* @return this node
* @see #insertCut(Hyperplane)
*/
N cut(Hyperplane<P> cutter);
}
}