/*
 * 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 java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.function.Function;

import org.apache.commons.geometry.core.Point;
import org.apache.commons.geometry.core.RegionLocation;
import org.apache.commons.geometry.core.internal.IteratorTransform;
import org.apache.commons.geometry.core.partitioning.ConvexSubHyperplane;
import org.apache.commons.geometry.core.partitioning.Hyperplane;
import org.apache.commons.geometry.core.partitioning.HyperplaneBoundedRegion;
import org.apache.commons.geometry.core.partitioning.HyperplaneLocation;
import org.apache.commons.geometry.core.partitioning.Split;
import org.apache.commons.geometry.core.partitioning.SplitLocation;
import org.apache.commons.geometry.core.partitioning.SubHyperplane;
import org.apache.commons.geometry.core.partitioning.bsp.BSPTreeVisitor.ClosestFirstVisitor;

/** {@link BSPTree} specialized for representing regions of space. For example, this
 * class can be used to represent polygons in Euclidean 2D space and polyhedrons
 * in Euclidean 3D space.
 * @param <P> Point implementation type
 * @param <N> BSP tree node implementation type
 */
public abstract class AbstractRegionBSPTree<
        P extends Point<P>,
        N extends AbstractRegionBSPTree.AbstractRegionNode<P, N>>
    extends AbstractBSPTree<P, N> implements HyperplaneBoundedRegion<P> {
    /** Value used to indicate an unknown size. */
    private static final double UNKNOWN_SIZE = -1.0;

    /** The region boundary size; this is computed when requested and then cached. */
    private double boundarySize = UNKNOWN_SIZE;

    /** The current size properties for the region. */
    private RegionSizeProperties<P> regionSizeProperties;

    /** Construct a new region will the given boolean determining whether or not the
     * region will be full (including the entire space) or empty (excluding the entire
     * space).
     * @param full if true, the region will cover the entire space, otherwise it will
     *      be empty
     */
    protected AbstractRegionBSPTree(final boolean full) {
        getRoot().setLocation(full ? RegionLocation.INSIDE : RegionLocation.OUTSIDE);
    }

    /** {@inheritDoc} */
    @Override
    public boolean isEmpty() {
        return !hasNodeWithLocationRecursive(getRoot(), RegionLocation.INSIDE);
    }

    /** {@inheritDoc} */
    @Override
    public boolean isFull() {
        return !hasNodeWithLocationRecursive(getRoot(), RegionLocation.OUTSIDE);
    }

    /** Return true if any node in the subtree rooted at the given node has a location with the
     * given value.
     * @param node the node at the root of the subtree to search
     * @param location the location to find
     * @return true if any node in the subtree has the given location
     */
    private boolean hasNodeWithLocationRecursive(final AbstractRegionNode<P, N> node, final RegionLocation location) {
        if (node == null) {
            return false;
        }

        return node.getLocation() == location ||
                hasNodeWithLocationRecursive(node.getMinus(), location) ||
                hasNodeWithLocationRecursive(node.getPlus(), location);
    }

    /** Modify this instance so that it contains the entire space.
     * @see #isFull()
     */
    public void setFull() {
        final N root = getRoot();

        root.clearCut();
        root.setLocation(RegionLocation.INSIDE);
    }

    /** Modify this instance so that is is completely empty.
     * @see #isEmpty()
     */
    public void setEmpty() {
        final N root = getRoot();

        root.clearCut();
        root.setLocation(RegionLocation.OUTSIDE);
    }

    /** {@inheritDoc} */
    @Override
    public double getSize() {
        return getRegionSizeProperties().getSize();
    }

    /** {@inheritDoc} */
    @Override
    public double getBoundarySize() {
        if (boundarySize < 0.0) {
            double sum = 0.0;

            RegionCutBoundary<P> boundary;
            for (final AbstractRegionNode<P, N> node : this) {
                boundary = node.getCutBoundary();
                if (boundary != null) {
                    sum += boundary.getInsideFacing().getSize();
                    sum += boundary.getOutsideFacing().getSize();
                }
            }

            boundarySize = sum;
        }

        return boundarySize;
    }

    /** Return an {@link Iterable} for iterating over the boundaries of the region.
     * Each boundary is oriented such that its plus side points to the outside of the
     * region. The exact ordering of the boundaries is determined by the internal structure
     * of the tree.
     * @return an {@link Iterable} for iterating over the boundaries of the region
     * @see #getBoundaries()
     */
    public Iterable<? extends ConvexSubHyperplane<P>> boundaries() {
        return createBoundaryIterable(Function.identity());
    }

    /** Internal method for creating the iterable instances used to iterate the region boundaries.
     * @param typeConverter function to convert the generic convex subhyperplane type into
     *      the type specific for this tree
     * @param <C> ConvexSubhyperplane implementation type
     * @return an iterable to iterating the region boundaries
     */
    protected <C extends ConvexSubHyperplane<P>> Iterable<C> createBoundaryIterable(
            final Function<ConvexSubHyperplane<P>, C> typeConverter) {

        return new Iterable<C>() {

            @Override
            public Iterator<C> iterator() {
                final NodeIterator<P, N> nodeIterator = new NodeIterator<>(getRoot());
                return new RegionBoundaryIterator<>(nodeIterator, typeConverter);
            }
        };
    }

    /** Return a list containing the boundaries of the region. Each boundary is oriented such
     * that its plus side points to the outside of the region. The exact ordering of
     * the boundaries is determined by the internal structure of the tree.
     * @return a list of the boundaries of the region
     */
    public List<? extends ConvexSubHyperplane<P>> getBoundaries() {
        return createBoundaryList(Function.identity());
    }

    /** Iternal method for creating a list of the region boundaries.
     * @param typeConverter function to convert the generic convex subhyperplane type into
     *      the type specific for this tree
     * @param <C> ConvexSubhyperplane implementation type
     * @return a list of the region boundaries
     */
    protected <C extends ConvexSubHyperplane<P>> List<C> createBoundaryList(
            final Function<ConvexSubHyperplane<P>, C> typeConverter) {

        final List<C> result = new ArrayList<>();

        final RegionBoundaryIterator<P, C, N> it = new RegionBoundaryIterator<>(iterator(), typeConverter);
        it.forEachRemaining(result::add);

        return result;
    }

    /** {@inheritDoc} */
    @Override
    public P project(P pt) {
        final BoundaryProjector<P, N> projector = new BoundaryProjector<>(pt);
        accept(projector);

        return projector.getProjected();
    }

    /** {@inheritDoc} */
    @Override
    public P getBarycenter() {
        return getRegionSizeProperties().getBarycenter();
    }

    /** Helper method implementing the algorithm for splitting a tree by a hyperplane. Subclasses
     * should call this method with two instantiated trees of the correct type.
     * @param splitter splitting hyperplane
     * @param minus tree that will contain the minus side of the split result
     * @param plus tree that will contain the plus side of the split result
     * @param <T> Tree implementation type
     * @return result of splitting this tree with the given hyperplane
     */
    protected <T extends AbstractRegionBSPTree<P, N>> Split<T> split(final Hyperplane<P> splitter,
            final T minus, final T plus) {

        splitIntoTrees(splitter, minus, plus);

        T splitMinus = null;
        T splitPlus = null;

        if (minus != null) {
            minus.getRoot().getPlus().setLocation(RegionLocation.OUTSIDE);
            minus.condense();

            splitMinus = minus.isEmpty() ? null : minus;
        }
        if (plus != null) {
            plus.getRoot().getMinus().setLocation(RegionLocation.OUTSIDE);
            plus.condense();

            splitPlus = plus.isEmpty() ? null : plus;
        }

        return new Split<>(splitMinus, splitPlus);
    }

    /** Get the size-related properties for the region. The value is computed
     * lazily and cached.
     * @return the size-related properties for the region
     */
    protected RegionSizeProperties<P> getRegionSizeProperties() {
        if (regionSizeProperties == null) {
            regionSizeProperties = computeRegionSizeProperties();
        }

        return regionSizeProperties;
    }

    /** Compute the size-related properties of the region.
     * @return object containing size properties for the region
     */
    protected abstract RegionSizeProperties<P> computeRegionSizeProperties();

    /** {@inheritDoc}
     *
     * <p>If the point is {@link org.apache.commons.geometry.core.Spatial#isNaN() NaN}, then
     * {@link RegionLocation#OUTSIDE} is returned.</p>
     */
    @Override
    public RegionLocation classify(final P point) {
        if (point.isNaN()) {
            return RegionLocation.OUTSIDE;
        }

        return classifyRecursive(getRoot(), point);
    }

    /** Recursively classify a point with respect to the region.
     * @param node the node to classify against
     * @param point the point to classify
     * @return the classification of the point with respect to the region rooted
     *      at the given node
     */
    private RegionLocation classifyRecursive(final AbstractRegionNode<P, N> node, final P point) {
        if (node.isLeaf()) {
            // the point is in a leaf, so the classification is just the leaf location
            return node.getLocation();
        } else {
            final HyperplaneLocation cutLoc = node.getCutHyperplane().classify(point);

            if (cutLoc == HyperplaneLocation.MINUS) {
                return classifyRecursive(node.getMinus(), point);
            } else if (cutLoc == HyperplaneLocation.PLUS) {
                return classifyRecursive(node.getPlus(), point);
            } else {
                // the point is on the cut boundary; classify against both child
                // subtrees and see if we end up with the same result or not
                RegionLocation minusLoc = classifyRecursive(node.getMinus(), point);
                RegionLocation plusLoc = classifyRecursive(node.getPlus(), point);

                if (minusLoc == plusLoc) {
                    return minusLoc;
                }
                return RegionLocation.BOUNDARY;
            }
        }
    }

    /** Change this region into its complement. All inside nodes become outside
     * nodes and vice versa. The orientation of the cut subhyperplanes is not modified.
     */
    public void complement() {
        complementRecursive(getRoot());
    }

    /** Set this instance to be the complement of the given tree. The argument
     * is not modified.
     * @param tree the tree to become the complement of
     */
    public void complement(final AbstractRegionBSPTree<P, N> tree) {
        copySubtree(tree.getRoot(), getRoot());
        complementRecursive(getRoot());
    }

    /** Recursively switch all inside nodes to outside nodes and vice versa.
     * @param node the node at the root of the subtree to switch
     */
    private void complementRecursive(final AbstractRegionNode<P, N> node) {
        if (node != null) {
            final RegionLocation newLoc = (node.getLocationValue() == RegionLocation.INSIDE) ?
                    RegionLocation.OUTSIDE :
                    RegionLocation.INSIDE;

            node.setLocation(newLoc);

            complementRecursive(node.getMinus());
            complementRecursive(node.getPlus());
        }
    }

    /** Compute the union of this instance and the given region, storing the result back in
     * this instance. The argument is not modified.
     * @param other the tree to compute the union with
     */
    public void union(final AbstractRegionBSPTree<P, N> other) {
        new UnionOperator<P, N>().apply(this, other, this);
    }

    /** Compute the union of the two regions passed as arguments and store the result in
     * this instance. Any nodes currently existing in this instance are removed.
     * @param a first argument to the union operation
     * @param b second argument to the union operation
     */
    public void union(final AbstractRegionBSPTree<P, N> a, final AbstractRegionBSPTree<P, N> b) {
        new UnionOperator<P, N>().apply(a, b, this);
    }

    /** Compute the intersection of this instance and the given region, storing the result back in
     * this instance. The argument is not modified.
     * @param other the tree to compute the intersection with
     */
    public void intersection(final AbstractRegionBSPTree<P, N> other) {
        new IntersectionOperator<P, N>().apply(this, other, this);
    }

    /** Compute the intersection of the two regions passed as arguments and store the result in
     * this instance. Any nodes currently existing in this instance are removed.
     * @param a first argument to the intersection operation
     * @param b second argument to the intersection operation
     */
    public void intersection(final AbstractRegionBSPTree<P, N> a, final AbstractRegionBSPTree<P, N> b) {
        new IntersectionOperator<P, N>().apply(a, b, this);
    }

    /** Compute the difference of this instance and the given region, storing the result back in
     * this instance. The argument is not modified.
     * @param other the tree to compute the difference with
     */
    public void difference(final AbstractRegionBSPTree<P, N> other) {
        new DifferenceOperator<P, N>().apply(this, other, this);
    }

    /** Compute the difference of the two regions passed as arguments and store the result in
     * this instance. Any nodes currently existing in this instance are removed.
     * @param a first argument to the difference operation
     * @param b second argument to the difference operation
     */
    public void difference(final AbstractRegionBSPTree<P, N> a, final AbstractRegionBSPTree<P, N> b) {
        new DifferenceOperator<P, N>().apply(a, b, this);
    }

    /** Compute the symmetric difference (xor) of this instance and the given region, storing the result back in
     * this instance. The argument is not modified.
     * @param other the tree to compute the symmetric difference with
     */
    public void xor(final AbstractRegionBSPTree<P, N> other) {
        new XorOperator<P, N>().apply(this, other, this);
    }

    /** Compute the symmetric difference (xor) of the two regions passed as arguments and store the result in
     * this instance. Any nodes currently existing in this instance are removed.
     * @param a first argument to the symmetric difference operation
     * @param b second argument to the symmetric difference operation
     */
    public void xor(final AbstractRegionBSPTree<P, N> a, final AbstractRegionBSPTree<P, N> b) {
        new XorOperator<P, N>().apply(a, b, this);
    }

    /** Condense this tree by removing redundant subtrees.
     *
     * <p>This operation can be used to reduce the total number of nodes in the
     * tree after performing node manipulations. For example, if two sibling leaf
     * nodes both represent the same {@link RegionLocation}, then there is no reason
     * from the perspective of the geometric region to retain both nodes. They are
     * therefore both merged into their parent node. This method performs this
     * simplification process.
     * </p>
     */
    protected void condense() {
        condenseRecursive(getRoot());
    }

    /** Recursively condense nodes that have children with homogenous location attributes
     * (eg, both inside, both outside) into single nodes.
     * @param node the root of the subtree to condense
     * @return the location of the successfully condensed subtree or null if no condensing was
     *      able to be performed
     */
    private RegionLocation condenseRecursive(final N node) {
        if (node.isLeaf()) {
            return node.getLocation();
        }

        final RegionLocation minusLocation = condenseRecursive(node.getMinus());
        final RegionLocation plusLocation = condenseRecursive(node.getPlus());

        if (minusLocation != null && plusLocation != null && minusLocation == plusLocation) {
            node.setLocation(minusLocation);
            node.clearCut();

            return minusLocation;
        }

        return null;
    }

    /** {@inheritDoc} */
    @Override
    protected void copyNodeProperties(final N src, final N dst) {
        dst.setLocation(src.getLocationValue());
    }

    /** Compute the portion of the node's cut subhyperplane that lies on the boundary of
     * the region.
     * @param node the node to compute the cut subhyperplane boundary of
     * @return object representing the portions of the node's cut subhyperplane that lie
     *      on the region's boundary
     */
    private RegionCutBoundary<P> computeBoundary(final N node) {
        if (node.isLeaf()) {
            // no boundary for leaf nodes; they are either entirely in or
            // entirely out
            return null;
        }

        ConvexSubHyperplane<P> sub = node.getCut();

        // find the portions of the node cut sub-hyperplane that touch inside and
        // outside cells in the minus sub-tree
        SubHyperplane.Builder<P> minusInBuilder = sub.builder();
        SubHyperplane.Builder<P> minusOutBuilder = sub.builder();

        characterizeSubHyperplane(sub, node.getMinus(), minusInBuilder, minusOutBuilder);

        List<? extends ConvexSubHyperplane<P>> minusIn = minusInBuilder.build().toConvex();
        List<? extends ConvexSubHyperplane<P>> minusOut = minusOutBuilder.build().toConvex();

        // create the result boundary builders
        SubHyperplane.Builder<P> insideFacing = sub.builder();
        SubHyperplane.Builder<P> outsideFacing = sub.builder();

        if (!minusIn.isEmpty()) {
            // Add to the boundary anything that touches an inside cell in the minus sub-tree
            // and an outside cell in the plus sub-tree. These portions are oriented with their
            // plus side pointing to the outside of the region.
            for (ConvexSubHyperplane<P> minusInFragment : minusIn) {
                characterizeSubHyperplane(minusInFragment, node.getPlus(), null, outsideFacing);
            }
        }

        if (!minusOut.isEmpty()) {
            // Add to the boundary anything that touches an outside cell in the minus sub-tree
            // and an inside cell in the plus sub-tree. These portions are oriented with their
            // plus side pointing to the inside of the region.
            for (ConvexSubHyperplane<P> minusOutFragment : minusOut) {
                characterizeSubHyperplane(minusOutFragment, node.getPlus(), insideFacing, null);
            }
        }

        return new RegionCutBoundary<>(insideFacing.build(), outsideFacing.build());
    }

    /** Recursive method to characterize a convex subhyperplane with respect to the region's
     * boundaries.
     * @param sub the subhyperplane to characterize
     * @param node the node to characterize the subhyperplane against
     * @param in the builder that will receive the portions of the subhyperplane that lie in the inside
     *      of the region; may be null
     * @param out the builder that will receive the portions of the subhyperplane that lie on the outside
     *      of the region; may be null
     */
    private void characterizeSubHyperplane(final ConvexSubHyperplane<P> sub, final AbstractRegionNode<P, N> node,
            final SubHyperplane.Builder<P> in, final SubHyperplane.Builder<P> out) {

        if (sub != null) {
            if (node.isLeaf()) {
                if (node.isInside() && in != null) {
                    in.add(sub);
                } else if (node.isOutside() && out != null) {
                    out.add(sub);
                }
            } else {
                final Split<? extends ConvexSubHyperplane<P>> split = sub.split(node.getCutHyperplane());

                // Continue further on down the subtree with the same subhyperplane if the
                // subhyperplane lies directly on the current node's cut
                if (split.getLocation() == SplitLocation.NEITHER) {
                    characterizeSubHyperplane(sub, node.getPlus(), in, out);
                    characterizeSubHyperplane(sub, node.getMinus(), in, out);
                } else {
                    characterizeSubHyperplane(split.getPlus(), node.getPlus(), in, out);
                    characterizeSubHyperplane(split.getMinus(), node.getMinus(), in, out);
                }
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    protected void initChildNode(final N parent, final N child, final boolean isPlus) {
        super.initChildNode(parent, child, isPlus);

        child.setLocation(isPlus ? RegionLocation.OUTSIDE : RegionLocation.INSIDE);
    }

    /** {@inheritDoc} */
    @Override
    protected void invalidate() {
        super.invalidate();

        // clear cached region properties
        boundarySize = UNKNOWN_SIZE;
        regionSizeProperties = null;
    }

    /** {@link BSPTree.Node} implementation for use with {@link AbstractRegionBSPTree}s.
     * @param <P> Point implementation type
     * @param <N> BSP tree node implementation type
     */
    public abstract static class AbstractRegionNode<P extends Point<P>, N extends AbstractRegionNode<P, N>>
        extends AbstractBSPTree.AbstractNode<P, N> {
        /** The location for the node. This will only be set on leaf nodes. */
        private RegionLocation location;

        /** Object representing the part of the node cut subhyperplane that lies on the
         * region boundary. This is calculated lazily and is only present on internal nodes.
         */
        private RegionCutBoundary<P> cutBoundary;

        /** Simple constructor.
         * @param tree owning tree instance
         */
        protected AbstractRegionNode(AbstractBSPTree<P, N> tree) {
            super(tree);
        }

        /** {@inheritDoc} */
        @Override
        public AbstractRegionBSPTree<P, N> getTree() {
            // cast to our parent tree type
            return (AbstractRegionBSPTree<P, N>) super.getTree();
        }

        /** Get the location of the node. This value will only be non-null for
         * leaf nodes.
         * @return the location of the node; will be null for internal nodes
         */
        public RegionLocation getLocation() {
            return isLeaf() ? location : null;
        }

        /** True if the node is a leaf node and has a location of {@link RegionLocation#INSIDE}.
         * @return true if the node is a leaf node and has a location of
         *      {@link RegionLocation#INSIDE}
         */
        public boolean isInside() {
            return getLocation() == RegionLocation.INSIDE;
        }

        /** True if the node is a leaf node and has a location of {@link RegionLocation#OUTSIDE}.
         * @return true if the node is a leaf node and has a location of
         *      {@link RegionLocation#OUTSIDE}
         */
        public boolean isOutside() {
            return getLocation() == RegionLocation.OUTSIDE;
        }

        /** Get the portion of the node's cut subhyperplane that lies on the boundary of the
         * region.
         * @return the portion of the node's cut subhyperplane that lies on the boundary of
         *      the region
         */
        public RegionCutBoundary<P> getCutBoundary() {
            if (!isLeaf()) {
                checkValid();

                if (cutBoundary == null) {
                    cutBoundary = getTree().computeBoundary(getSelf());
                }
            }

            return cutBoundary;
        }

        /** {@inheritDoc} */
        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder();
            sb.append(this.getClass().getSimpleName())
                .append("[cut= ")
                .append(getCut())
                .append(", location= ")
                .append(getLocation())
                .append("]");

            return sb.toString();
        }

        /** {@inheritDoc} */
        @Override
        protected void nodeInvalidated() {
            super.nodeInvalidated();

            // null any computed boundary value since it is no longer valid
            cutBoundary = null;
        }

        /** Set the location attribute for the node.
         * @param location the location attribute for the node
         */
        protected void setLocation(final RegionLocation location) {
            this.location = location;
        }

        /** Get the value of the location property, unmodified based on the
         * node's leaf state.
         * @return the value of the location property
         */
        protected RegionLocation getLocationValue() {
            return location;
        }
    }

    /** Class containing the basic algorithm for merging region BSP trees.
     * @param <P> Point implementation type
     * @param <N> BSP tree node implementation type
     */
    public abstract static class RegionMergeOperator<P extends Point<P>, N extends AbstractRegionNode<P, N>>
        extends AbstractBSPTreeMergeOperator<P, N> {

        /** Merge two input trees, storing the output in the third. The output tree can be one of the
         * input trees. The output tree is condensed before the method returns.
         * @param inputTree1 first input tree
         * @param inputTree2 second input tree
         * @param outputTree the tree that will contain the result of the merge; may be one
         *      of the input trees
         */
        public void apply(final AbstractRegionBSPTree<P, N> inputTree1, final AbstractRegionBSPTree<P, N> inputTree2,
                final AbstractRegionBSPTree<P, N> outputTree) {

            this.performMerge(inputTree1, inputTree2, outputTree);

            outputTree.condense();
        }
    }

    /** Class for performing boolean union operations on region trees.
     * @param <P> Point implementation type
     * @param <N> BSP tree node implementation type
     */
    public static class UnionOperator<P extends Point<P>, N extends AbstractRegionNode<P, N>>
        extends RegionMergeOperator<P, N> {

        /** {@inheritDoc} */
        @Override
        protected N mergeLeaf(final N node1, final N node2) {
            if (node1.isLeaf()) {
                return node1.isInside() ? node1 : node2;
            }

            // call again with flipped arguments
            return mergeLeaf(node2, node1);
        }
    }

    /** Class for performing boolean intersection operations on region trees.
     * @param <P> Point implementation type
     * @param <N> BSP tree node implementation type
     */
    public static class IntersectionOperator<P extends Point<P>, N extends AbstractRegionNode<P, N>>
        extends RegionMergeOperator<P, N> {

        /** {@inheritDoc} */
        @Override
        protected N mergeLeaf(final N node1, final N node2) {
            if (node1.isLeaf()) {
                return node1.isInside() ? node2 : node1;
            }

            // call again with flipped arguments
            return mergeLeaf(node2, node1);
        }
    }

    /** Class for performing boolean difference operations on region trees.
     * @param <P> Point implementation type
     * @param <N> BSP tree node implementation type
     */
    public static class DifferenceOperator<P extends Point<P>, N extends AbstractRegionNode<P, N>>
        extends RegionMergeOperator<P, N> {

        /** {@inheritDoc} */
        @Override
        protected N mergeLeaf(final N node1, final N node2) {
            // a region is included if it belongs in tree1 and is not in tree2

            if (node1.isInside()) {
                // this region is inside of tree1, so only include subregions that are
                // not in tree2, ie include everything in node2's complement
                final N output = outputSubtree(node2);
                output.getTree().complementRecursive(output);

                return output;
            } else if (node2.isInside()) {
                // this region is inside of tree2 and so cannot be in the result region
                final N output = outputNode();
                output.setLocation(RegionLocation.OUTSIDE);

                return output;
            }

            // this region is not in tree2, so we can include everything in tree1
            return node1;
        }
    }

    /** Class for performing boolean symmetric difference (xor) operations on region trees.
     * @param <P> Point implementation type
     * @param <N> BSP tree node implementation type
     */
    public static class XorOperator<P extends Point<P>, N extends AbstractRegionNode<P, N>>
        extends RegionMergeOperator<P, N> {

        /** {@inheritDoc} */
        @Override
        protected N mergeLeaf(final N node1, final N node2) {
            // a region is included if it belongs in tree1 and is not in tree2 OR
            // it belongs in tree2 and is not in tree1

            if (node1.isLeaf()) {
                if (node1.isInside()) {
                    // this region is inside node1, so only include subregions that are
                    // not in node2, ie include everything in node2's complement
                    final N output = outputSubtree(node2);
                    output.getTree().complementRecursive(output);

                    return output;
                } else {
                    // this region is not in node1, so only include subregions that
                    // in node2
                    return node2;
                }
            }

            // the operation is symmetric, so perform the same operation but with the
            // nodes flipped
            return mergeLeaf(node2, node1);
        }
    }

    /** Class used to compute the point on the region's boundary that is closest to a target point.
     * @param <P> Point implementation type
     * @param <N> BSP tree node implementation type
     */
    protected static class BoundaryProjector<P extends Point<P>, N extends AbstractRegionNode<P, N>>
        extends ClosestFirstVisitor<P, N> {
        /** The projected point. */
        private P projected;

        /** The current closest distance to the boundary found. */
        private double minDist = -1.0;

        /** Simple constructor.
         * @param point the point to project onto the region's boundary
         */
        public BoundaryProjector(final P point) {
            super(point);
        }

        /** {@inheritDoc} */
        @Override
        public VisitResult visit(final N node) {
            final P point = getTarget();

            if (node.isInternal() && (minDist < 0.0 || isPossibleClosestCut(node.getCut(), point, minDist))) {
                final RegionCutBoundary<P> boundary = node.getCutBoundary();
                final P boundaryPt = boundary.closest(point);

                final double dist = boundaryPt.distance(point);
                final int cmp = Double.compare(dist, minDist);

                if (minDist < 0.0 || cmp < 0) {
                    projected = boundaryPt;
                    minDist = dist;
                } else if (cmp == 0) {
                    // the two points are the _exact_ same distance from the reference point, so use
                    // a separate method to disambiguate them
                    projected = disambiguateClosestPoint(point, projected, boundaryPt);
                }
            }

            return VisitResult.CONTINUE;
        }

        /** Return true if the given node cut subhyperplane is a possible candidate for containing the
         * closest region boundary point to the target.
         * @param cut the node cut subhyperplane to test
         * @param target the target point being projected
         * @param currentMinDist the smallest distance found so far to a region boundary; this value is guaranteed
         *      to be non-negative
         * @return true if the subhyperplane is a possible candidate for containing the closest region
         *      boundary point to the target
         */
        protected boolean isPossibleClosestCut(final SubHyperplane<P> cut, final P target,
                final double currentMinDist) {
            return Math.abs(cut.getHyperplane().offset(target)) <= currentMinDist;
        }

        /** Method used to determine which of points {@code a} and {@code b} should be considered
         * as the "closest" point to {@code target} when the points are exactly equidistant.
         * @param target the target point
         * @param a first point to consider
         * @param b second point to consider
         * @return which of {@code a} or {@code b} should be considered as the one closest to
         *      {@code target}
         */
        protected P disambiguateClosestPoint(final P target, final P a, final P b) {
            return a;
        }

        /** Get the projected point on the region's boundary, or null if no point could be found.
         * @return the projected point on the region's boundary
         */
        public P getProjected() {
            return projected;
        }
    }

    /** Class containing the primary size-related properties of a region. These properties
     * are typically computed at the same time, so this class serves to encapsulate the result
     * of the combined computation.
     * @param <P> Point implementation type
     */
    protected static class RegionSizeProperties<P extends Point<P>> {
        /** The size of the region. */
        private final double size;

        /** The barycenter of the region. */
        private final P barycenter;

        /** Simple constructor.
         * @param size the region size
         * @param barycenter the region barycenter
         */
        public RegionSizeProperties(final double size, final P barycenter) {
            this.size = size;
            this.barycenter = barycenter;
        }

        /** Get the size of the region.
         * @return the size of the region
         */
        public double getSize() {
            return size;
        }

        /** Get the barycenter of the region.
         * @return the barycenter of the region
         */
        public P getBarycenter() {
            return barycenter;
        }
    }

    /** Class that iterates over the boundary convex subhyperplanes from a set of region nodes.
     * @param <P> Point implementation type
     * @param <C> Boundary convex subhyperplane implementation type
     * @param <N> BSP tree node implementation type
     */
    protected static final class RegionBoundaryIterator<
            P extends Point<P>,
            C extends ConvexSubHyperplane<P>,
            N extends AbstractRegionNode<P, N>>
        extends IteratorTransform<N, C> {

        /** Function that converts from the convex subhyperplane type to the output type. */
        private final Function<ConvexSubHyperplane<P>, C> typeConverter;

        /** Simple constructor.
         * @param inputIterator iterator that will provide all nodes in the tree
         * @param typeConverter function that converts from the convex subhyperplane type to the output type
         */
        private RegionBoundaryIterator(final Iterator<N> inputIterator,
                final Function<ConvexSubHyperplane<P>, C> typeConverter) {
            super(inputIterator);

            this.typeConverter = typeConverter;
        }

        /** {@inheritDoc} */
        @Override
        protected void acceptInput(final N input) {
            if (input.isInternal()) {
                final RegionCutBoundary<P> cutBoundary = input.getCutBoundary();

                final SubHyperplane<P> outsideFacing = cutBoundary.getOutsideFacing();
                final SubHyperplane<P> insideFacing = cutBoundary.getInsideFacing();

                if (outsideFacing != null && !outsideFacing.isEmpty()) {
                    for (ConvexSubHyperplane<P> boundary : outsideFacing.toConvex()) {

                        addOutput(typeConverter.apply(boundary));
                    }
                }
                if (insideFacing != null && !insideFacing.isEmpty()) {
                    for (ConvexSubHyperplane<P> boundary : insideFacing.toConvex()) {
                        ConvexSubHyperplane<P> reversed = boundary.reverse();

                        addOutput(typeConverter.apply(reversed));
                    }
                }
            }
        }
    }
}
