BSPTreeVisitor.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. /** Interface for visiting the nodes in a {@link BSPTree} or {@link BSPSubtree}.
  20.  * @param <P> Point implementation type
  21.  * @param <N> BSP tree node implementation type
  22.  */
  23. @FunctionalInterface
  24. public interface BSPTreeVisitor<P extends Point<P>, N extends BSPTree.Node<P, N>> {

  25.     /** Enum used to specify the order in which visitors should visit the nodes
  26.      * in the tree.
  27.      */
  28.     enum Order {

  29.         /** Indicates that the visitor should first visit the plus sub-tree, then
  30.          * the minus sub-tree and then the current node.
  31.          */
  32.         PLUS_MINUS_NODE,

  33.         /** Indicates that the visitor should first visit the plus sub-tree, then
  34.          * the current node, and then the minus sub-tree.
  35.          */
  36.         PLUS_NODE_MINUS,

  37.         /** Indicates that the visitor should first visit the minus sub-tree, then
  38.          * the plus sub-tree, and then the current node.
  39.          */
  40.         MINUS_PLUS_NODE,

  41.         /** Indicates that the visitor should first visit the minus sub-tree, then the
  42.          * current node, and then the plus sub-tree.
  43.          */
  44.         MINUS_NODE_PLUS,

  45.         /** Indicates that the visitor should first visit the current node, then the
  46.          * plus sub-tree, and then the minus sub-tree.
  47.          */
  48.         NODE_PLUS_MINUS,

  49.         /** Indicates that the visitor should first visit the current node, then the
  50.          * minus sub-tree, and then the plus sub-tree.
  51.          */
  52.         NODE_MINUS_PLUS,

  53.         /** Indicates that the visitor should not visit any of the nodes in this subtree. */
  54.         NONE
  55.     }

  56.     /** Enum representing the result of a BSP tree node visit operation.
  57.      */
  58.     enum Result {

  59.         /** Indicates that the visit operation should continue with the remaining nodes in
  60.          * the BSP tree.
  61.          */
  62.         CONTINUE,

  63.         /** Indicates that the visit operation should terminate and not visit any further
  64.          * nodes in the tree.
  65.          */
  66.         TERMINATE
  67.     }

  68.     /** Visit a node in a BSP tree. This method is called for both internal nodes and
  69.      * leaf nodes.
  70.      * @param node the node being visited
  71.      * @return the result of the visit operation
  72.      */
  73.     Result visit(N node);

  74.     /** Determine the visit order for the given internal node. This is called for each
  75.      * internal node before {@link #visit(BSPTree.Node)} is called. Returning null
  76.      * or {@link Order#NONE}from this method skips the subtree rooted at the given node.
  77.      * This method is not called on leaf nodes.
  78.      * @param internalNode the internal node to determine the visit order for
  79.      * @return the order that the subtree rooted at the given node should be visited
  80.      */
  81.     default Order visitOrder(final N internalNode) {
  82.         return Order.NODE_MINUS_PLUS;
  83.     }

  84.     /** Abstract class for {@link BSPTreeVisitor} implementations that base their visit
  85.      * ordering on a target point.
  86.      * @param <P> Point implementation type
  87.      * @param <N> BSP tree node implementation type
  88.      */
  89.     abstract class TargetPointVisitor<P extends Point<P>, N extends BSPTree.Node<P, N>>
  90.         implements BSPTreeVisitor<P, N> {
  91.         /** Point serving as the target of the traversal. */
  92.         private final P target;

  93.         /** Simple constructor.
  94.          * @param target the point serving as the target for the tree traversal
  95.          */
  96.         protected TargetPointVisitor(final P target) {
  97.             this.target = target;
  98.         }

  99.         /** Get the target point for the tree traversal.
  100.          * @return the target point for the tree traversal
  101.          */
  102.         public P getTarget() {
  103.             return target;
  104.         }
  105.     }

  106.     /** {@link BSPTreeVisitor} base class that orders tree nodes so that nodes closest to the target point are
  107.      * visited first. This is done by choosing {@link Order#MINUS_NODE_PLUS}
  108.      * when the target point lies on the minus side of the node's cut hyperplane and {@link Order#PLUS_NODE_MINUS}
  109.      * when it lies on the plus side. The order {@link Order#MINUS_NODE_PLUS} order is used when
  110.      * the target point lies directly on the node's cut hyerplane and no child node is closer than the other.
  111.      * @param <P> Point implementation type
  112.      * @param <N> BSP tree node implementation type
  113.      */
  114.     abstract class ClosestFirstVisitor<P extends Point<P>, N extends BSPTree.Node<P, N>>
  115.         extends TargetPointVisitor<P, N> {
  116.         /** Simple constructor.
  117.          * @param target the point serving as the target for the traversal
  118.          */
  119.         protected ClosestFirstVisitor(final P target) {
  120.             super(target);
  121.         }

  122.         /** {@inheritDoc} */
  123.         @Override
  124.         public Order visitOrder(final N node) {
  125.             if (node.getCutHyperplane().offset(getTarget()) > 0) {
  126.                 return Order.PLUS_NODE_MINUS;
  127.             }
  128.             return Order.MINUS_NODE_PLUS;
  129.         }
  130.     }

  131.     /** {@link BSPTreeVisitor} base class that orders tree nodes so that nodes farthest from the target point
  132.      * are traversed first. This is done by choosing {@link Order#PLUS_NODE_MINUS}
  133.      * when the target point lies on the minus side of the node's cut hyperplane and {@link Order#MINUS_NODE_PLUS}
  134.      * when it lies on the plus side. The order {@link Order#MINUS_NODE_PLUS} order is used when
  135.      * the target point lies directly on the node's cut hyerplane and no child node is closer than the other.
  136.      * @param <P> Point implementation type
  137.      * @param <N> BSP tree node implementation type
  138.      */
  139.     abstract class FarthestFirstVisitor<P extends Point<P>, N extends BSPTree.Node<P, N>>
  140.         extends TargetPointVisitor<P, N> {
  141.         /** Simple constructor.
  142.          * @param target the point serving as the target for the traversal
  143.          */
  144.         protected FarthestFirstVisitor(final P target) {
  145.             super(target);
  146.         }

  147.         /** {@inheritDoc} */
  148.         @Override
  149.         public Order visitOrder(final N node) {
  150.             if (node.getCutHyperplane().offset(getTarget()) < 0) {
  151.                 return Order.PLUS_NODE_MINUS;
  152.             }
  153.             return Order.MINUS_NODE_PLUS;
  154.         }
  155.     }
  156. }