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.test; 18 19 import org.apache.commons.geometry.core.Point; 20 import org.apache.commons.geometry.core.partitioning.Hyperplane; 21 import org.apache.commons.geometry.core.partitioning.bsp.AbstractBSPTree; 22 23 /** Simple {@link org.apache.commons.geometry.core.partitioning.bsp.BSPTree} implementation allowing arbitrary values to be 24 * associated with each node. 25 * @param <P> Point implementation type 26 * @param <T> Tree node attribute type 27 */ 28 public class AttributeBSPTree<P extends Point<P>, T> 29 extends AbstractBSPTree<P, AttributeBSPTree.AttributeNode<P, T>> { 30 /** The initial attribute value to use for newly created nodes. */ 31 private final T initialNodeAttribute; 32 33 /** Create a new tree instance. New nodes in the tree are given an attribute 34 * of null. 35 */ 36 public AttributeBSPTree() { 37 this(null); 38 } 39 40 /** Create a new tree instance. New nodes in the tree are assigned the given 41 * initial attribute value. 42 * @param initialNodeAttribute The attribute value to assign to newly created nodes. 43 */ 44 public AttributeBSPTree(final T initialNodeAttribute) { 45 this.initialNodeAttribute = initialNodeAttribute; 46 47 this.getRoot().setAttribute(initialNodeAttribute); 48 } 49 50 /** {@inheritDoc} */ 51 @Override 52 protected AttributeNode<P, T> createNode() { 53 return new AttributeNode<>(this); 54 } 55 56 /** {@inheritDoc} */ 57 @Override 58 protected void copyNodeProperties(final AttributeNode<P, T> src, final AttributeNode<P, T> dst) { 59 dst.setAttribute(src.getAttribute()); 60 } 61 62 /** {@link org.apache.commons.geometry.core.partitioning.bsp.BSPTree.Node} implementation for use with {@link AttributeBSPTree}s. 63 * @param <P> Point implementation type 64 * @param <T> Tree node attribute type 65 */ 66 public static class AttributeNode<P extends Point<P>, T> 67 extends AbstractBSPTree.AbstractNode<P, AttributeNode<P, T>> { 68 /** The node attribute. */ 69 private T attribute; 70 71 /** Simple constructor. 72 * @param tree the owning tree; this must be an instance of {@link AttributeBSPTree} 73 */ 74 protected AttributeNode(final AbstractBSPTree<P, AttributeNode<P, T>> tree) { 75 super(tree); 76 } 77 78 /** {@inheritDoc} */ 79 @Override 80 public AttributeBSPTree<P, T> getTree() { 81 // cast to our parent tree type 82 return (AttributeBSPTree<P, T>) super.getTree(); 83 } 84 85 /** Cut this node with the given hyperplane. If the hyperplane intersects the node's region, 86 * then the node becomes an internal node with two child leaf node. If the hyperplane does 87 * not intersect the node's region, then the node is made a leaf node. The same node is 88 * returned, regardless of the outcome of the cut operation. 89 * @param cutter hyperplane to cut the node with 90 * @return this node 91 */ 92 public AttributeNode<P, T> cut(final Hyperplane<P> cutter) { 93 final AttributeBSPTree<P, T> tree = getTree(); 94 95 tree.cutNode(getSelf(), cutter, root -> { 96 root.getMinus().setAttribute(tree.initialNodeAttribute); 97 root.getPlus().setAttribute(tree.initialNodeAttribute); 98 }); 99 100 return this; 101 } 102 103 /** Get the attribute associated with this node. 104 * @return the attribute associated with this node 105 */ 106 public T getAttribute() { 107 return attribute; 108 } 109 110 /** Set the attribute associated with this node. 111 * @param attribute the attribute to associate with this node 112 */ 113 public void setAttribute(final T attribute) { 114 this.attribute = attribute; 115 } 116 117 /** Set the attribute for this node. The node is returned. 118 * @param attributeValue attribute to set for the node 119 * @return the node instance 120 */ 121 public AttributeNode<P, T> attr(final T attributeValue) { 122 setAttribute(attributeValue); 123 124 return this; 125 } 126 127 /** {@inheritDoc} */ 128 @Override 129 public String toString() { 130 final StringBuilder sb = new StringBuilder(); 131 sb.append(this.getClass().getSimpleName()) 132 .append("[cut= ") 133 .append(getCut()) 134 .append(", attribute= ") 135 .append(attribute) 136 .append("]"); 137 138 return sb.toString(); 139 } 140 141 /** {@inheritDoc} */ 142 @Override 143 protected AttributeNode<P, T> getSelf() { 144 return this; 145 } 146 } 147 }