SphericalPolygonsSetTransferObject.java

  1. /* Copyright 2002-2018 CS Systèmes d'Information
  2.  * Licensed to CS Systèmes d'Information (CS) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * CS 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.  *   http://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. package org.orekit.utils;

  18. import java.io.Serializable;

  19. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  20. import org.hipparchus.geometry.partitioning.BSPTree;
  21. import org.hipparchus.geometry.partitioning.BSPTreeVisitor;
  22. import org.hipparchus.geometry.spherical.twod.Circle;
  23. import org.hipparchus.geometry.spherical.twod.Sphere2D;
  24. import org.hipparchus.geometry.spherical.twod.SphericalPolygonsSet;

  25. /** Transfer object for serializing {@link SphericalPolygonsSet} instances.
  26.  * <p>
  27.  * This object is intended to be used when {@link SphericalPolygonsSet} instances
  28.  * needs to be serialized. Instead of serializing the zone, an instance of
  29.  * this class is created from the zone and serialized. Then upon de-serialization,
  30.  * the zone can be rebuilt, typically from a {@code readResolve} method.
  31.  * </p>
  32.  * @author Luc Maisonobe
  33.  * @since 7.1
  34.  */
  35. public class SphericalPolygonsSetTransferObject implements Serializable {

  36.     /** Serializable UID. */
  37.     private static final long serialVersionUID = 20150112L;

  38.     /** Tolerance for the zone. */
  39.     private final double tolerance;

  40.     /** Zone cut hyperplanes. */
  41.     private final double[] cuts;

  42.     /** Leaf nodes indices. */
  43.     private final int[] leafs;

  44.     /** Zone interior/exterior indicators. */
  45.     private final boolean[] flags;

  46.     /** Internal nodes counter. */
  47.     private transient int internalNodes;

  48.     /** Leaf nodes counter. */
  49.     private transient int leafNodes;

  50.     /** Node index. */
  51.     private transient int nodeIndex;

  52.     /** Index in cut hyperplanes array. */
  53.     private transient int cutIndex;

  54.     /** Index in interior/exterior flags array. */
  55.     private transient int flagIndex;

  56.     /** Simple constructor.
  57.      * @param zone zone to serialize
  58.      */
  59.     public SphericalPolygonsSetTransferObject(final SphericalPolygonsSet zone) {

  60.         this.tolerance = zone.getTolerance();

  61.         // count the nodes
  62.         internalNodes = 0;
  63.         leafNodes     = 0;
  64.         zone.getTree(false).visit(new BSPTreeVisitor<Sphere2D>() {

  65.             /** {@inheritDoc} */
  66.             public Order visitOrder(final BSPTree<Sphere2D> node) {
  67.                 return Order.SUB_MINUS_PLUS;
  68.             }

  69.             /** {@inheritDoc} */
  70.             public void visitInternalNode(final BSPTree<Sphere2D> node) {
  71.                 ++internalNodes;
  72.             }

  73.             /** {@inheritDoc} */
  74.             public void visitLeafNode(final BSPTree<Sphere2D> node) {
  75.                 ++leafNodes;
  76.             }

  77.         });

  78.         // allocate the arrays for flattened tree
  79.         cuts      = new double[3 * internalNodes];
  80.         leafs     = new int[leafNodes];
  81.         flags     = new boolean[leafNodes];
  82.         nodeIndex = 0;
  83.         cutIndex  = 0;
  84.         flagIndex = 0;
  85.         zone.getTree(false).visit(new BSPTreeVisitor<Sphere2D>() {

  86.             /** {@inheritDoc} */
  87.             public Order visitOrder(final BSPTree<Sphere2D> node) {
  88.                 return Order.SUB_MINUS_PLUS;
  89.             }

  90.             /** {@inheritDoc} */
  91.             public void visitInternalNode(final BSPTree<Sphere2D> node) {
  92.                 final Vector3D cutPole = ((Circle) node.getCut().getHyperplane()).getPole();
  93.                 cuts[cutIndex++] = cutPole.getX();
  94.                 cuts[cutIndex++] = cutPole.getY();
  95.                 cuts[cutIndex++] = cutPole.getZ();
  96.                 nodeIndex++;
  97.             }

  98.             /** {@inheritDoc} */
  99.             public void visitLeafNode(final BSPTree<Sphere2D> node) {
  100.                 leafs[flagIndex]   = nodeIndex++;
  101.                 flags[flagIndex++] = (Boolean) node.getAttribute();
  102.             }

  103.         });

  104.     }

  105.     /** Rebuild the zone from saved data.
  106.      * @return rebuilt zone
  107.      */
  108.     public SphericalPolygonsSet rebuildZone() {

  109.         // rebuild the tree from the flattened arrays
  110.         BSPTree<Sphere2D> node = new BSPTree<Sphere2D>();
  111.         final int nbNodes = cuts.length / 3 + leafs.length;
  112.         cutIndex  = 0;
  113.         flagIndex = 0;
  114.         for (nodeIndex = 0; nodeIndex < nbNodes; ++nodeIndex) {
  115.             if (leafs[flagIndex] == nodeIndex) {
  116.                 // this is a leaf node
  117.                 node.setAttribute(Boolean.valueOf(flags[flagIndex++]));
  118.                 while (node.getParent() != null) {
  119.                     final BSPTree<Sphere2D> parent = node.getParent();
  120.                     if (node == parent.getMinus()) {
  121.                         node = parent.getPlus();
  122.                         break;
  123.                     } else {
  124.                         node = parent;
  125.                     }
  126.                 }
  127.             } else {
  128.                 // this is an internal node
  129.                 final double x = cuts[cutIndex++];
  130.                 final double y = cuts[cutIndex++];
  131.                 final double z = cuts[cutIndex++];
  132.                 node.insertCut(new Circle(new Vector3D(x, y, z), tolerance));
  133.                 node = node.getMinus();
  134.             }
  135.         }

  136.         return new SphericalPolygonsSet(node, tolerance);

  137.     }

  138. }