View Javadoc

    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
    19  import org.apache.commons.geometry.core.Point;
    20
    21  /** Interface for visiting the nodes in a {@link BSPTree} or {@link BSPSubtree}.
    22   * @param <P> Point implementation type
    23   * @param <N> BSP tree node implementation type
    24   */
    25  @FunctionalInterface
    26  public interface BSPTreeVisitor<P extends Point<P>, N extends BSPTree.Node<P, N>> {
    27
    28      /** Enum used to specify the order in which visitors should visit the nodes
    29       * in the tree.
    30       */
    31      enum Order {
    32
    33          /** Indicates that the visitor should first visit the plus sub-tree, then
    34           * the minus sub-tree and then the current node.
    35           */
    36          PLUS_MINUS_NODE,
    37
    38          /** Indicates that the visitor should first visit the plus sub-tree, then
    39           * the current node, and then the minus sub-tree.
    40           */
    41          PLUS_NODE_MINUS,
    42
    43          /** Indicates that the visitor should first visit the minus sub-tree, then
    44           * the plus sub-tree, and then the current node.
    45           */
    46          MINUS_PLUS_NODE,
    47
    48          /** Indicates that the visitor should first visit the minus sub-tree, then the
    49           * current node, and then the plus sub-tree.
    50           */
    51          MINUS_NODE_PLUS,
    52
    53          /** Indicates that the visitor should first visit the current node, then the
    54           * plus sub-tree, and then the minus sub-tree.
    55           */
    56          NODE_PLUS_MINUS,
    57
    58          /** Indicates that the visitor should first visit the current node, then the
    59           * minus sub-tree, and then the plus sub-tree.
    60           */
    61          NODE_MINUS_PLUS,
    62
    63          /** Indicates that the visitor should not visit any of the nodes in this subtree. */
    64          NONE
    65      }
    66
    67      /** Enum representing the result of a BSP tree node visit operation.
    68       */
    69      enum Result {
    70
    71          /** Indicates that the visit operation should continue with the remaining nodes in
    72           * the BSP tree.
    73           */
    74          CONTINUE,
    75
    76          /** Indicates that the visit operation should terminate and not visit any further
    77           * nodes in the tree.
    78           */
    79          TERMINATE
    80      }
    81
    82      /** Visit a node in a BSP tree. This method is called for both internal nodes and
    83       * leaf nodes.
    84       * @param node the node being visited
    85       * @return the result of the visit operation
    86       */
    87      Result visit(N node);
    88
    89      /** Determine the visit order for the given internal node. This is called for each
    90       * internal node before {@link #visit(BSPTree.Node)} is called. Returning null
    91       * or {@link Order#NONE}from this method skips the subtree rooted at the given node.
    92       * This method is not called on leaf nodes.
    93       * @param internalNode the internal node to determine the visit order for
    94       * @return the order that the subtree rooted at the given node should be visited
    95       */
    96      default Order visitOrder(final N internalNode) {
    97          return Order.NODE_MINUS_PLUS;
    98      }
    99
    100     /** Abstract class for {@link BSPTreeVisitor} implementations that base their visit
    101      * ordering on a target point.
    102      * @param <P> Point implementation type
    103      * @param <N> BSP tree node implementation type
    104      */
    105     abstract class TargetPointVisitor<P extends Point<P>, N extends BSPTree.Node<P, N>>
    106         implements BSPTreeVisitor<P, N> {
    107         /** Point serving as the target of the traversal. */
    108         private final P target;
    109
    110         /** Simple constructor.
    111          * @param target the point serving as the target for the tree traversal
    112          */
    113         public TargetPointVisitor(final P target) {
    114             this.target = target;
    115         }
    116
    117         /** Get the target point for the tree traversal.
    118          * @return the target point for the tree traversal
    119          */
    120         public P getTarget() {
    121             return target;
    122         }
    123     }
    124
    125     /** {@link BSPTreeVisitor} base class that orders tree nodes so that nodes closest to the target point are
    126      * visited first. This is done by choosing {@link Order#MINUS_NODE_PLUS}
    127      * when the target point lies on the minus side of the node's cut hyperplane and {@link Order#PLUS_NODE_MINUS}
    128      * when it lies on the plus side. The order {@link Order#MINUS_NODE_PLUS} order is used when
    129      * the target point lies directly on the node's cut hyerplane and no child node is closer than the other.
    130      * @param <P> Point implementation type
    131      * @param <N> BSP tree node implementation type
    132      */
    133     abstract class ClosestFirstVisitor<P extends Point<P>, N extends BSPTree.Node<P, N>>
    134         extends TargetPointVisitor<P, N> {
    135         /** Simple constructor.
    136          * @param target the point serving as the target for the traversal
    137          */
    138         public ClosestFirstVisitor(final P target) {
    139             super(target);
    140         }
    141
    142         /** {@inheritDoc} */
    143         @Override
    144         public Order visitOrder(final N node) {
    145             if (node.getCutHyperplane().offset(getTarget()) > 0.0) {
    146                 return Order.PLUS_NODE_MINUS;
    147             }
    148             return Order.MINUS_NODE_PLUS;
    149         }
    150     }
    151
    152     /** {@link BSPTreeVisitor} base class that orders tree nodes so that nodes farthest from the target point
    153      * are traversed first. This is done by choosing {@link Order#PLUS_NODE_MINUS}
    154      * when the target point lies on the minus side of the node's cut hyperplane and {@link Order#MINUS_NODE_PLUS}
    155      * when it lies on the plus side. The order {@link Order#MINUS_NODE_PLUS} order is used when
    156      * the target point lies directly on the node's cut hyerplane and no child node is closer than the other.
    157      * @param <P> Point implementation type
    158      * @param <N> BSP tree node implementation type
    159      */
    160     abstract class FarthestFirstVisitor<P extends Point<P>, N extends BSPTree.Node<P, N>>
    161         extends TargetPointVisitor<P, N> {
    162         /** Simple constructor.
    163          * @param target the point serving as the target for the traversal
    164          */
    165         public FarthestFirstVisitor(final P target) {
    166             super(target);
    167         }
    168
    169         /** {@inheritDoc} */
    170         @Override
    171         public Order visitOrder(final N node) {
    172             if (node.getCutHyperplane().offset(getTarget()) < 0.0) {
    173                 return Order.PLUS_NODE_MINUS;
    174             }
    175             return Order.MINUS_NODE_PLUS;
    176         }
    177     }
    178 }