BSPTree.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.geometry.core.partitioning.bsp;

  18. import org.apache.commons.geometry.core.Point;
  19. import org.apache.commons.geometry.core.Transform;
  20. import org.apache.commons.geometry.core.partitioning.Hyperplane;
  21. import org.apache.commons.geometry.core.partitioning.HyperplaneConvexSubset;

  22. /** Interface for Binary Space Partitioning (BSP) trees. BSP trees are spatial data
  23.  * structures that recursively subdivide a space using hyperplanes. They can be used
  24.  * for a wide variety of purposes, such as representing arbitrary polytopes, storing
  25.  * data for fast spatial lookups, determining the correct rendering order for objects
  26.  * in a 3D scene, and so on.
  27.  *
  28.  * <p>This interface contains a number of methods for extracting information from existing
  29.  * trees, but it does not include methods for constructing trees or modifying tree structure.
  30.  * This is due to the large number of possible use cases for BSP trees. Each use case is likely
  31.  * to have its own specific methods and rules for tree construction, making it difficult to define
  32.  * a single API at this level. Thus, it is left to implementation classes to define their own
  33.  * API for tree construction and modification.</p>
  34.  *
  35.  * @param <P> Point implementation type
  36.  * @param <N> Node implementation type
  37.  * @see <a href="https://en.wikipedia.org/wiki/Binary_space_partitioning">Binary space partitioning</a>
  38.  */
  39. public interface BSPTree<P extends Point<P>, N extends BSPTree.Node<P, N>>
  40.     extends BSPSubtree<P, N> {

  41.     /** Enum specifying possible behaviors when a point used to locate a node
  42.      * falls directly on the cut of an internal node.
  43.      */
  44.     enum FindNodeCutRule {

  45.         /** Choose the minus child of the internal node and continue searching.
  46.          * This behavior will result in a leaf node always being returned by the
  47.          * node search.
  48.          */
  49.         MINUS,

  50.         /** Choose the plus child of the internal node and continue searching.
  51.          * This behavior will result in a leaf node always being returned by the
  52.          * node search.
  53.          */
  54.         PLUS,

  55.         /** Choose the internal node and stop searching. This behavior may result
  56.          * in non-leaf nodes being returned by the node search.
  57.          */
  58.         NODE
  59.     }

  60.     /** Get the root node of the tree.
  61.      * @return the root node of the tree
  62.      */
  63.     N getRoot();

  64.     /** Find a node in this subtree containing the given point or its interior or boundary.
  65.      * When a point lies directly on the cut of an internal node, the minus child of the
  66.      * cut is chosen. This is equivalent to {@code subtree.findNode(pt, FindNodeCutRule.MINUS)}
  67.      * and always returns a leaf node.
  68.      * @param pt test point used to locate a node in the tree
  69.      * @return leaf node containing the point on its interior or boundary
  70.      * @see #findNode(Point, FindNodeCutRule)
  71.      */
  72.     default N findNode(final P pt) {
  73.         return findNode(pt, FindNodeCutRule.MINUS);
  74.     }

  75.     /** Find a node in this subtree containing the given point on its interior or boundary. The
  76.      * search should always return a leaf node except in the cases where the given point lies
  77.      * exactly on the cut of an internal node. In this case, it is unclear whether
  78.      * the search should continue with the minus child, the plus child, or end with the internal
  79.      * node. The {@code cutRule} argument specifies what should happen in this case.
  80.      * <ul>
  81.      *      <li>{@link FindNodeCutRule#MINUS} - continue the search in the minus subtree</li>
  82.      *      <li>{@link FindNodeCutRule#PLUS} - continue the search in the plus subtree</li>
  83.      *      <li>{@link FindNodeCutRule#NODE} - stop the search and return the internal node</li>
  84.      * </ul>
  85.      * @param pt test point used to locate a node in the tree
  86.      * @param cutRule value used to determine the search behavior when the test point lies
  87.      *      exactly on the cut of an internal node
  88.      * @return node containing the point on its interior or boundary
  89.      * @see #findNode(Point)
  90.      */
  91.     N findNode(P pt, FindNodeCutRule cutRule);

  92.     /** Make the current instance a deep copy of the argument.
  93.      * @param src the tree to copy
  94.      */
  95.     void copy(BSPTree<P, N> src);

  96.     /** Set this instance to the region represented by the given node. The
  97.      * given node could have come from this tree or a different tree.
  98.      * @param node the node to extract
  99.      */
  100.     void extract(N node);

  101.     /** Transform this tree. Each cut in the tree is transformed in place using
  102.      * the given {@link Transform}.
  103.      * @param transform the transform to apply
  104.      */
  105.     void transform(Transform<P> transform);

  106.     /** Interface for Binary Space Partitioning (BSP) tree nodes.
  107.      * @param <P> Point type
  108.      * @param <N> BSP tree node implementation type
  109.      */
  110.     interface Node<P extends Point<P>, N extends Node<P, N>> extends BSPSubtree<P, N> {

  111.         /** Get the {@link BSPTree} that owns the node.
  112.          * @return the owning tree
  113.          */
  114.         BSPTree<P, N> getTree();

  115.         /** Get the depth of the node in the tree. The root node of the tree
  116.          * has a depth of 0.
  117.          * @return the depth of the node in the tree
  118.          */
  119.         int depth();

  120.         /** Get the parent of the node. This will be null if the node is the
  121.          * root of the tree.
  122.          * @return the parent node for this instance
  123.          */
  124.         N getParent();

  125.         /** Get the cut for the node. This is a hyperplane convex subset that splits
  126.          * the region for the cell into two disjoint regions, namely the plus and
  127.          * minus regions. This will be null for leaf nodes.
  128.          * @see #getPlus()
  129.          * @see #getMinus()
  130.          * @return the cut for the cell
  131.          * @see #getCutHyperplane()
  132.          */
  133.         HyperplaneConvexSubset<P> getCut();

  134.         /** Get the hyperplane containing the node cut, if it exists.
  135.          * @return the hyperplane containing the node cut, or null if
  136.          *      the node does not have a cut
  137.          * @see #getCut()
  138.          */
  139.         Hyperplane<P> getCutHyperplane();

  140.         /** Get the node for the minus region of the cell. This will be null if the
  141.          * node has not been cut, ie if it is a leaf node.
  142.          * @return the node for the minus region of the cell
  143.          */
  144.         N getMinus();

  145.         /** Get the node for the plus region of the cell. This will be null if the
  146.          * node has not been cut, ie if it is a leaf node.
  147.          * @return the node for the plus region of the cell
  148.          */
  149.         N getPlus();

  150.         /** Return true if the node is a leaf node, meaning that it has no
  151.          * binary partitioner (aka "cut") and therefore no child nodes.
  152.          * @return true if the node is a leaf node
  153.          */
  154.         boolean isLeaf();

  155.         /** Return true if the node is an internal node, meaning that is
  156.          * has a binary partitioner (aka "cut") and therefore two child nodes.
  157.          * @return true if the node is an internal node
  158.          */
  159.         boolean isInternal();

  160.         /** Return true if the node has a parent and is the parent's minus
  161.          * child.
  162.          * @return true if the node is the minus child of its parent
  163.          */
  164.         boolean isMinus();

  165.         /** Return true if the node has a parent and is the parent's plus
  166.          * child.
  167.          * @return true if the node is the plus child of its parent
  168.          */
  169.         boolean isPlus();

  170.         /** Trim the given hyperplane subset to the region defined by this node by cutting
  171.          * the argument with the cut hyperplanes (binary partitioners) of all parent nodes
  172.          * up to the root. Null is returned if the hyperplane subset lies outside of the region
  173.          * defined by the node.
  174.          * @param sub the hyperplane subset to trim
  175.          * @return the trimmed hyperplane subset or null if no part of the argument lies
  176.          *      within the node's region
  177.          */
  178.         HyperplaneConvexSubset<P> trim(HyperplaneConvexSubset<P> sub);
  179.     }
  180. }