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 protected 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 protected 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) {
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 protected 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) {
173 return Order.PLUS_NODE_MINUS;
174 }
175 return Order.MINUS_NODE_PLUS;
176 }
177 }
178 }