Characterization.java

  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.  *      https://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. /*
  18.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */
  21. package org.hipparchus.geometry.partitioning;

  22. import java.util.ArrayList;
  23. import java.util.List;

  24. import org.hipparchus.exception.MathRuntimeException;
  25. import org.hipparchus.geometry.Point;
  26. import org.hipparchus.geometry.Space;

  27. /** Cut sub-hyperplanes characterization with respect to inside/outside cells.
  28.  * @see BoundaryBuilder
  29.  * @param <S> Type of the space.
  30.  * @param <P> Type of the points in space.
  31.  * @param <H> Type of the hyperplane.
  32.  * @param <I> Type of the sub-hyperplane.
  33.  */
  34. class Characterization<S extends Space,
  35.                        P extends Point<S, P>,
  36.                        H extends Hyperplane<S, P, H, I>,
  37.                        I extends SubHyperplane<S, P, H, I>> {

  38.     /** Part of the cut sub-hyperplane that touch outside cells. */
  39.     private I outsideTouching;

  40.     /** Part of the cut sub-hyperplane that touch inside cells. */
  41.     private I insideTouching;

  42.     /** Nodes that were used to split the outside touching part. */
  43.     private final NodesSet<S, P, H, I> outsideSplitters;

  44.     /** Nodes that were used to split the inside touching part. */
  45.     private final NodesSet<S, P, H, I> insideSplitters;

  46.     /** Simple constructor.
  47.      * <p>Characterization consists in splitting the specified
  48.      * sub-hyperplane into several parts lying in inside and outside
  49.      * cells of the tree. The principle is to compute characterization
  50.      * twice for each cut sub-hyperplane in the tree, once on the plus
  51.      * node and once on the minus node. The parts that have the same flag
  52.      * (inside/inside or outside/outside) do not belong to the boundary
  53.      * while parts that have different flags (inside/outside or
  54.      * outside/inside) do belong to the boundary.</p>
  55.      * @param node current BSP tree node
  56.      * @param sub sub-hyperplane to characterize
  57.      */
  58.     Characterization(final BSPTree<S, P, H, I> node, final I sub) {
  59.         outsideTouching  = null;
  60.         insideTouching   = null;
  61.         outsideSplitters = new NodesSet<>();
  62.         insideSplitters  = new NodesSet<>();
  63.         characterize(node, sub, new ArrayList<>());
  64.     }

  65.     /** Filter the parts of an hyperplane belonging to the boundary.
  66.      * <p>The filtering consist in splitting the specified
  67.      * sub-hyperplane into several parts lying in inside and outside
  68.      * cells of the tree. The principle is to call this method twice for
  69.      * each cut sub-hyperplane in the tree, once on the plus node and
  70.      * once on the minus node. The parts that have the same flag
  71.      * (inside/inside or outside/outside) do not belong to the boundary
  72.      * while parts that have different flags (inside/outside or
  73.      * outside/inside) do belong to the boundary.</p>
  74.      * @param node current BSP tree node
  75.      * @param sub sub-hyperplane to characterize
  76.      * @param splitters nodes that did split the current one
  77.      */
  78.     private void characterize(final BSPTree<S, P, H, I> node, final I sub,
  79.                               final List<BSPTree<S, P, H, I>> splitters) {
  80.         if (node.getCut() == null) {
  81.             // we have reached a leaf node
  82.             final boolean inside = (Boolean) node.getAttribute();
  83.             if (inside) {
  84.                 addInsideTouching(sub, splitters);
  85.             } else {
  86.                 addOutsideTouching(sub, splitters);
  87.             }
  88.         } else {
  89.             final H hyperplane = node.getCut().getHyperplane();
  90.             final SubHyperplane.SplitSubHyperplane<S, P, H, I> split = sub.split(hyperplane);
  91.             switch (split.getSide()) {
  92.             case PLUS:
  93.                 characterize(node.getPlus(),  sub, splitters);
  94.                 break;
  95.             case MINUS:
  96.                 characterize(node.getMinus(), sub, splitters);
  97.                 break;
  98.             case BOTH:
  99.                 splitters.add(node);
  100.                 characterize(node.getPlus(),  split.getPlus(),  splitters);
  101.                 characterize(node.getMinus(), split.getMinus(), splitters);
  102.                 splitters.remove(splitters.size() - 1);
  103.                 break;
  104.             default:
  105.                 // this should not happen
  106.                 throw MathRuntimeException.createInternalError();
  107.             }
  108.         }
  109.     }

  110.     /** Add a part of the cut sub-hyperplane known to touch an outside cell.
  111.      * @param sub part of the cut sub-hyperplane known to touch an outside cell
  112.      * @param splitters sub-hyperplanes that did split the current one
  113.      */
  114.     private void addOutsideTouching(final I sub, final List<BSPTree<S, P, H, I>> splitters) {
  115.         if (outsideTouching == null) {
  116.             outsideTouching = sub;
  117.         } else {
  118.             outsideTouching = outsideTouching.reunite(sub);
  119.         }
  120.         outsideSplitters.addAll(splitters);
  121.     }

  122.     /** Add a part of the cut sub-hyperplane known to touch an inside cell.
  123.      * @param sub part of the cut sub-hyperplane known to touch an inside cell
  124.      * @param splitters sub-hyperplanes that did split the current one
  125.      */
  126.     private void addInsideTouching(final I sub, final List<BSPTree<S, P, H, I>> splitters) {
  127.         if (insideTouching == null) {
  128.             insideTouching = sub;
  129.         } else {
  130.             insideTouching = insideTouching.reunite(sub);
  131.         }
  132.         insideSplitters.addAll(splitters);
  133.     }

  134.     /** Check if the cut sub-hyperplane touches outside cells.
  135.      * @return true if the cut sub-hyperplane touches outside cells
  136.      */
  137.     public boolean touchOutside() {
  138.         return outsideTouching != null && !outsideTouching.isEmpty();
  139.     }

  140.     /** Get all the parts of the cut sub-hyperplane known to touch outside cells.
  141.      * @return parts of the cut sub-hyperplane known to touch outside cells
  142.      * (may be null or empty)
  143.      */
  144.     public I outsideTouching() {
  145.         return outsideTouching;
  146.     }

  147.     /** Get the nodes that were used to split the outside touching part.
  148.      * <p>
  149.      * Splitting nodes are internal nodes (i.e. they have a non-null
  150.      * cut sub-hyperplane).
  151.      * </p>
  152.      * @return nodes that were used to split the outside touching part
  153.      */
  154.     public NodesSet<S, P, H, I> getOutsideSplitters() {
  155.         return outsideSplitters;
  156.     }

  157.     /** Check if the cut sub-hyperplane touches inside cells.
  158.      * @return true if the cut sub-hyperplane touches inside cells
  159.      */
  160.     public boolean touchInside() {
  161.         return insideTouching != null && !insideTouching.isEmpty();
  162.     }

  163.     /** Get all the parts of the cut sub-hyperplane known to touch inside cells.
  164.      * @return parts of the cut sub-hyperplane known to touch inside cells
  165.      * (may be null or empty)
  166.      */
  167.     public I insideTouching() {
  168.         return insideTouching;
  169.     }

  170.     /** Get the nodes that were used to split the inside touching part.
  171.      * <p>
  172.      * Splitting nodes are internal nodes (i.e. they have a non-null
  173.      * cut sub-hyperplane).
  174.      * </p>
  175.      * @return nodes that were used to split the inside touching part
  176.      */
  177.     public NodesSet<S, P, H, I> getInsideSplitters() {
  178.         return insideSplitters;
  179.     }

  180. }