/*
* 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.math3.geometry.partitioning;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.math3.exception.MathInternalError;
import org.apache.commons.math3.geometry.Space;
Cut sub-hyperplanes characterization with respect to inside/outside cells.
Type parameters: - <S> – Type of the space.
See Also: - BoundaryBuilder
Since: 3.4
/** Cut sub-hyperplanes characterization with respect to inside/outside cells.
* @see BoundaryBuilder
* @param <S> Type of the space.
* @since 3.4
*/
class Characterization<S extends Space> {
Part of the cut sub-hyperplane that touch outside cells. /** Part of the cut sub-hyperplane that touch outside cells. */
private SubHyperplane<S> outsideTouching;
Part of the cut sub-hyperplane that touch inside cells. /** Part of the cut sub-hyperplane that touch inside cells. */
private SubHyperplane<S> insideTouching;
Nodes that were used to split the outside touching part. /** Nodes that were used to split the outside touching part. */
private final NodesSet<S> outsideSplitters;
Nodes that were used to split the outside touching part. /** Nodes that were used to split the outside touching part. */
private final NodesSet<S> insideSplitters;
Simple constructor.
Characterization consists in splitting the specified
sub-hyperplane into several parts lying in inside and outside
cells of the tree. The principle is to compute characterization
twice for each cut sub-hyperplane in the tree, once on the plus
node and once on the minus node. The parts that have the same flag
(inside/inside or outside/outside) do not belong to the boundary
while parts that have different flags (inside/outside or
outside/inside) do belong to the boundary.
Params: - node – current BSP tree node
- sub – sub-hyperplane to characterize
/** Simple constructor.
* <p>Characterization consists in splitting the specified
* sub-hyperplane into several parts lying in inside and outside
* cells of the tree. The principle is to compute characterization
* twice for each cut sub-hyperplane in the tree, once on the plus
* node and once on the minus node. The parts that have the same flag
* (inside/inside or outside/outside) do not belong to the boundary
* while parts that have different flags (inside/outside or
* outside/inside) do belong to the boundary.</p>
* @param node current BSP tree node
* @param sub sub-hyperplane to characterize
*/
Characterization(final BSPTree<S> node, final SubHyperplane<S> sub) {
outsideTouching = null;
insideTouching = null;
outsideSplitters = new NodesSet<S>();
insideSplitters = new NodesSet<S>();
characterize(node, sub, new ArrayList<BSPTree<S>>());
}
Filter the parts of an hyperplane belonging to the boundary.
The filtering consist in splitting the specified
sub-hyperplane into several parts lying in inside and outside
cells of the tree. The principle is to call this method twice for
each cut sub-hyperplane in the tree, once on the plus node and
once on the minus node. The parts that have the same flag
(inside/inside or outside/outside) do not belong to the boundary
while parts that have different flags (inside/outside or
outside/inside) do belong to the boundary.
Params: - node – current BSP tree node
- sub – sub-hyperplane to characterize
- splitters – nodes that did split the current one
/** Filter the parts of an hyperplane belonging to the boundary.
* <p>The filtering consist in splitting the specified
* sub-hyperplane into several parts lying in inside and outside
* cells of the tree. The principle is to call this method twice for
* each cut sub-hyperplane in the tree, once on the plus node and
* once on the minus node. The parts that have the same flag
* (inside/inside or outside/outside) do not belong to the boundary
* while parts that have different flags (inside/outside or
* outside/inside) do belong to the boundary.</p>
* @param node current BSP tree node
* @param sub sub-hyperplane to characterize
* @param splitters nodes that did split the current one
*/
private void characterize(final BSPTree<S> node, final SubHyperplane<S> sub,
final List<BSPTree<S>> splitters) {
if (node.getCut() == null) {
// we have reached a leaf node
final boolean inside = (Boolean) node.getAttribute();
if (inside) {
addInsideTouching(sub, splitters);
} else {
addOutsideTouching(sub, splitters);
}
} else {
final Hyperplane<S> hyperplane = node.getCut().getHyperplane();
final SubHyperplane.SplitSubHyperplane<S> split = sub.split(hyperplane);
switch (split.getSide()) {
case PLUS:
characterize(node.getPlus(), sub, splitters);
break;
case MINUS:
characterize(node.getMinus(), sub, splitters);
break;
case BOTH:
splitters.add(node);
characterize(node.getPlus(), split.getPlus(), splitters);
characterize(node.getMinus(), split.getMinus(), splitters);
splitters.remove(splitters.size() - 1);
break;
default:
// this should not happen
throw new MathInternalError();
}
}
}
Add a part of the cut sub-hyperplane known to touch an outside cell.
Params: - sub – part of the cut sub-hyperplane known to touch an outside cell
- splitters – sub-hyperplanes that did split the current one
/** Add a part of the cut sub-hyperplane known to touch an outside cell.
* @param sub part of the cut sub-hyperplane known to touch an outside cell
* @param splitters sub-hyperplanes that did split the current one
*/
private void addOutsideTouching(final SubHyperplane<S> sub,
final List<BSPTree<S>> splitters) {
if (outsideTouching == null) {
outsideTouching = sub;
} else {
outsideTouching = outsideTouching.reunite(sub);
}
outsideSplitters.addAll(splitters);
}
Add a part of the cut sub-hyperplane known to touch an inside cell.
Params: - sub – part of the cut sub-hyperplane known to touch an inside cell
- splitters – sub-hyperplanes that did split the current one
/** Add a part of the cut sub-hyperplane known to touch an inside cell.
* @param sub part of the cut sub-hyperplane known to touch an inside cell
* @param splitters sub-hyperplanes that did split the current one
*/
private void addInsideTouching(final SubHyperplane<S> sub,
final List<BSPTree<S>> splitters) {
if (insideTouching == null) {
insideTouching = sub;
} else {
insideTouching = insideTouching.reunite(sub);
}
insideSplitters.addAll(splitters);
}
Check if the cut sub-hyperplane touches outside cells.
Returns: true if the cut sub-hyperplane touches outside cells
/** Check if the cut sub-hyperplane touches outside cells.
* @return true if the cut sub-hyperplane touches outside cells
*/
public boolean touchOutside() {
return outsideTouching != null && !outsideTouching.isEmpty();
}
Get all the parts of the cut sub-hyperplane known to touch outside cells.
Returns: parts of the cut sub-hyperplane known to touch outside cells
(may be null or empty)
/** Get all the parts of the cut sub-hyperplane known to touch outside cells.
* @return parts of the cut sub-hyperplane known to touch outside cells
* (may be null or empty)
*/
public SubHyperplane<S> outsideTouching() {
return outsideTouching;
}
Get the nodes that were used to split the outside touching part.
Splitting nodes are internal nodes (i.e. they have a non-null
cut sub-hyperplane).
Returns: nodes that were used to split the outside touching part
/** Get the nodes that were used to split the outside touching part.
* <p>
* Splitting nodes are internal nodes (i.e. they have a non-null
* cut sub-hyperplane).
* </p>
* @return nodes that were used to split the outside touching part
*/
public NodesSet<S> getOutsideSplitters() {
return outsideSplitters;
}
Check if the cut sub-hyperplane touches inside cells.
Returns: true if the cut sub-hyperplane touches inside cells
/** Check if the cut sub-hyperplane touches inside cells.
* @return true if the cut sub-hyperplane touches inside cells
*/
public boolean touchInside() {
return insideTouching != null && !insideTouching.isEmpty();
}
Get all the parts of the cut sub-hyperplane known to touch inside cells.
Returns: parts of the cut sub-hyperplane known to touch inside cells
(may be null or empty)
/** Get all the parts of the cut sub-hyperplane known to touch inside cells.
* @return parts of the cut sub-hyperplane known to touch inside cells
* (may be null or empty)
*/
public SubHyperplane<S> insideTouching() {
return insideTouching;
}
Get the nodes that were used to split the inside touching part.
Splitting nodes are internal nodes (i.e. they have a non-null
cut sub-hyperplane).
Returns: nodes that were used to split the inside touching part
/** Get the nodes that were used to split the inside touching part.
* <p>
* Splitting nodes are internal nodes (i.e. they have a non-null
* cut sub-hyperplane).
* </p>
* @return nodes that were used to split the inside touching part
*/
public NodesSet<S> getInsideSplitters() {
return insideSplitters;
}
}