All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.commons.geometry.core.partitioning.bsp.AbstractBSPTreeMergeOperator Maven / Gradle / Ivy

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

import org.apache.commons.geometry.core.Point;
import org.apache.commons.geometry.core.partitioning.bsp.AbstractBSPTree.AbstractNode;

/** Class containing the basic algorithm for merging two {@link AbstractBSPTree}
 * instances. Subclasses must override the
 * {@link #mergeLeaf(AbstractBSPTree.AbstractNode, AbstractBSPTree.AbstractNode)} method
 * to implement the merging logic for their particular use case. The remainder of the
 * algorithm is independent of the use case.
 *
 * 

This class does not expose any public methods so that subclasses can present their own * public API, tailored to the specific types being worked with. In particular, most subclasses * will want to restrict the tree types used with the algorithm, which is difficult to implement * cleanly at this level.

* *

This class maintains state during the merging process and is therefore * not thread-safe.

* @param

Point implementation type * @param BSP tree node implementation type */ public abstract class AbstractBSPTreeMergeOperator

, N extends AbstractNode> { /** The tree that the merge operation output will be written to. All existing content * in this tree is overwritten. */ private AbstractBSPTree outputTree; /** Set the tree used as output for this instance. * @param outputTree the tree used as output for this instance */ protected void setOutputTree(final AbstractBSPTree outputTree) { this.outputTree = outputTree; } /** Get the tree used as output for this instance. * @return the tree used as output for this instance */ protected AbstractBSPTree getOutputTree() { return outputTree; } /** Perform a merge operation with the two input trees and store the result in the output tree. The * output tree may be one of the input trees, in which case, the tree is modified in place. * @param input1 first input tree * @param input2 second input tree * @param output output tree all previous content in this tree is overwritten */ protected void performMerge(final AbstractBSPTree input1, final AbstractBSPTree input2, final AbstractBSPTree output) { setOutputTree(output); final N root1 = input1.getRoot(); final N root2 = input2.getRoot(); final N outputRoot = performMergeRecursive(root1, root2); getOutputTree().setRoot(outputRoot); } /** Recursively merge two nodes. * @param node1 node from the first input tree * @param node2 node from the second input tree * @return a merged node */ private N performMergeRecursive(final N node1, final N node2) { if (node1.isLeaf() || node2.isLeaf()) { // delegate to the mergeLeaf method if we can no longer continue // merging recursively final N merged = mergeLeaf(node1, node2); // copy the merged node to the output if needed (in case mergeLeaf // returned one of the input nodes directly) return outputTree.importSubtree(merged); } else { final N partitioned = outputTree.splitSubtree(node2, node1.getCut()); final N minus = performMergeRecursive(node1.getMinus(), partitioned.getMinus()); final N plus = performMergeRecursive(node1.getPlus(), partitioned.getPlus()); final N outputNode = outputTree.copyNode(node1); outputNode.setSubtree(node1.getCut(), minus, plus); return outputNode; } } /** Create a new node in the output tree. The node is associated with the output tree but * is not attached to a parent node. * @return a new node associated with the output tree but not yet attached to a parent */ protected N outputNode() { return outputTree.createNode(); } /** Place the subtree rooted at the given input node into the output tree. The subtree * is copied if needed. * @param node the root of the subtree to copy * @return a subtree in the output tree */ protected N outputSubtree(final N node) { return outputTree.importSubtree(node); } /** Merge a leaf node from one input with a subtree from another. *

When this method is called, one or both of the given nodes will be a leaf node. * This method is expected to return a node representing the merger of the two given * nodes. The way that the returned node is determined defines the overall behavior of * the merge operation. *

*

The return value can be one of the two input nodes or a completely different one.

* @param node1 node from the first input tree * @param node2 node from the second input tree * @return node representing the merger of the two input nodes */ protected abstract N mergeLeaf(N node1, N node2); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy