PropertiesComputer.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.spherical.twod;

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

  24. import org.hipparchus.exception.MathRuntimeException;
  25. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  26. import org.hipparchus.geometry.partitioning.BSPTree;
  27. import org.hipparchus.geometry.partitioning.BSPTreeVisitor;
  28. import org.hipparchus.util.FastMath;
  29. import org.hipparchus.util.MathUtils;

  30. /** Visitor computing geometrical properties.
  31.  */
  32. class PropertiesComputer implements BSPTreeVisitor<Sphere2D, S2Point, Circle, SubCircle> {

  33.     /** Tolerance below which points are consider to be identical. */
  34.     private final double tolerance;

  35.     /** Summed area. */
  36.     private double summedArea;

  37.     /** Summed barycenter. */
  38.     private Vector3D summedBarycenter;

  39.     /** List of points strictly inside convex cells. */
  40.     private final List<Vector3D> convexCellsInsidePoints;

  41.     /** Simple constructor.
  42.      * @param tolerance below which points are consider to be identical
  43.      */
  44.     PropertiesComputer(final double tolerance) {
  45.         this.tolerance               = tolerance;
  46.         this.summedArea              = 0;
  47.         this.summedBarycenter        = Vector3D.ZERO;
  48.         this.convexCellsInsidePoints = new ArrayList<>();
  49.     }

  50.     /** {@inheritDoc} */
  51.     @Override
  52.     public Order visitOrder(final BSPTree<Sphere2D, S2Point, Circle, SubCircle> node) {
  53.         return Order.MINUS_SUB_PLUS;
  54.     }

  55.     /** {@inheritDoc} */
  56.     @Override
  57.     public void visitInternalNode(final BSPTree<Sphere2D, S2Point, Circle, SubCircle> node) {
  58.         // nothing to do here
  59.     }

  60.     /** {@inheritDoc} */
  61.     @Override
  62.     public void visitLeafNode(final BSPTree<Sphere2D, S2Point, Circle, SubCircle> node) {
  63.         if ((Boolean) node.getAttribute()) {

  64.             // transform this inside leaf cell into a simple convex polygon
  65.             final SphericalPolygonsSet convex =
  66.                     new SphericalPolygonsSet(node.pruneAroundConvexCell(Boolean.TRUE,
  67.                                                                         Boolean.FALSE,
  68.                                                                         null),
  69.                                              tolerance);

  70.             // extract the start of the single loop boundary of the convex cell
  71.             final List<Vertex> boundary = convex.getBoundaryLoops();
  72.             if (boundary.size() != 1) {
  73.                 // this should never happen
  74.                 throw MathRuntimeException.createInternalError();
  75.             }

  76.             // compute the geometrical properties of the convex cell
  77.             final double area  = convexCellArea(boundary.get(0));
  78.             final Vector3D barycenter = convexCellBarycenter(boundary.get(0));
  79.             convexCellsInsidePoints.add(barycenter);

  80.             // add the cell contribution to the global properties
  81.             summedArea      += area;
  82.             summedBarycenter = new Vector3D(1, summedBarycenter, area, barycenter);

  83.         }
  84.     }

  85.     /** Compute convex cell area.
  86.      * @param start start vertex of the convex cell boundary
  87.      * @return area
  88.      */
  89.     private double convexCellArea(final Vertex start) {

  90.         int n = 0;
  91.         double sum = 0;

  92.         // loop around the cell
  93.         for (Edge e = start.getOutgoing(); n == 0 || e.getStart() != start; e = e.getEnd().getOutgoing()) {

  94.             // find path interior angle at vertex
  95.             final Vector3D previousPole = e.getCircle().getPole();
  96.             final Vector3D nextPole     = e.getEnd().getOutgoing().getCircle().getPole();
  97.             final Vector3D point        = e.getEnd().getLocation().getVector();
  98.             double alpha = FastMath.atan2(Vector3D.dotProduct(nextPole, Vector3D.crossProduct(point, previousPole)),
  99.                                           -Vector3D.dotProduct(nextPole, previousPole));
  100.             if (alpha < 0) {
  101.                 alpha += MathUtils.TWO_PI;
  102.             }
  103.             sum += alpha;
  104.             n++;
  105.         }

  106.         // compute area using extended Girard theorem
  107.         // see Spherical Trigonometry: For the Use of Colleges and Schools by I. Todhunter
  108.         // article 99 in chapter VIII Area Of a Spherical Triangle. Spherical Excess.
  109.         // book available from project Gutenberg at http://www.gutenberg.org/ebooks/19770
  110.         return sum - (n - 2) * FastMath.PI;

  111.     }

  112.     /** Compute convex cell barycenter.
  113.      * @param start start vertex of the convex cell boundary
  114.      * @return barycenter
  115.      */
  116.     private Vector3D convexCellBarycenter(final Vertex start) {

  117.         int n = 0;
  118.         Vector3D sumB = Vector3D.ZERO;

  119.         // loop around the cell
  120.         for (Edge e = start.getOutgoing(); n == 0 || e.getStart() != start; e = e.getEnd().getOutgoing()) {
  121.             sumB = new Vector3D(1, sumB, e.getLength(), e.getCircle().getPole());
  122.             n++;
  123.         }

  124.         return sumB.normalize();

  125.     }

  126.     /** Get the area.
  127.      * @return area
  128.      */
  129.     public double getArea() {
  130.         return summedArea;
  131.     }

  132.     /** Get the barycenter.
  133.      * @return barycenter
  134.      */
  135.     public S2Point getBarycenter() {
  136.         if (summedBarycenter.getNormSq() == 0) {
  137.             return S2Point.NaN;
  138.         } else {
  139.             return new S2Point(summedBarycenter);
  140.         }
  141.     }

  142.     /** Get the points strictly inside convex cells.
  143.      * @return points strictly inside convex cells
  144.      */
  145.     public List<Vector3D> getConvexCellsInsidePoints() {
  146.         return convexCellsInsidePoints;
  147.     }

  148. }