View Javadoc
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  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.geometry.partitioning;
23  
24  import java.util.Formatter;
25  import java.util.Locale;
26  
27  import org.hipparchus.geometry.Point;
28  import org.hipparchus.geometry.Space;
29  import org.hipparchus.geometry.euclidean.oned.Euclidean1D;
30  import org.hipparchus.geometry.euclidean.oned.IntervalsSet;
31  import org.hipparchus.geometry.euclidean.oned.OrientedPoint;
32  import org.hipparchus.geometry.euclidean.oned.SubOrientedPoint;
33  import org.hipparchus.geometry.euclidean.oned.Vector1D;
34  import org.hipparchus.geometry.euclidean.threed.Euclidean3D;
35  import org.hipparchus.geometry.euclidean.threed.Plane;
36  import org.hipparchus.geometry.euclidean.threed.PolyhedronsSet;
37  import org.hipparchus.geometry.euclidean.threed.SubPlane;
38  import org.hipparchus.geometry.euclidean.threed.Vector3D;
39  import org.hipparchus.geometry.euclidean.twod.Euclidean2D;
40  import org.hipparchus.geometry.euclidean.twod.Line;
41  import org.hipparchus.geometry.euclidean.twod.PolygonsSet;
42  import org.hipparchus.geometry.euclidean.twod.SubLine;
43  import org.hipparchus.geometry.euclidean.twod.Vector2D;
44  import org.hipparchus.geometry.spherical.oned.ArcsSet;
45  import org.hipparchus.geometry.spherical.oned.LimitAngle;
46  import org.hipparchus.geometry.spherical.oned.S1Point;
47  import org.hipparchus.geometry.spherical.oned.Sphere1D;
48  import org.hipparchus.geometry.spherical.oned.SubLimitAngle;
49  import org.hipparchus.geometry.spherical.twod.Circle;
50  import org.hipparchus.geometry.spherical.twod.S2Point;
51  import org.hipparchus.geometry.spherical.twod.Sphere2D;
52  import org.hipparchus.geometry.spherical.twod.SphericalPolygonsSet;
53  import org.hipparchus.geometry.spherical.twod.SubCircle;
54  
55  /** Class dumping a string representation of an {@link AbstractRegion}.
56   * <p>
57   * This class is intended for tests and debug purposes only.
58   * </p>
59   * @see RegionParser
60   */
61  public class RegionDumper {
62  
63      /** Private constructor for a utility class
64       */
65      private RegionDumper() {
66      }
67  
68      /** Get a string representation of an {@link ArcsSet}.
69       * @param arcsSet region to dump
70       * @return string representation of the region
71       */
72      public static String dump(final ArcsSet arcsSet) {
73          final TreeDumper<Sphere1D, S1Point, LimitAngle, SubLimitAngle> visitor =
74                  new TreeDumper<Sphere1D, S1Point, LimitAngle, SubLimitAngle>("ArcsSet", arcsSet.getTolerance()) {
75  
76              /** {@inheritDoc} */
77              @Override
78              protected void formatHyperplane(final LimitAngle hyperplane) {
79                  getFormatter().format("%22.15e %b %22.15e",
80                                        hyperplane.getLocation().getAlpha(),
81                                        hyperplane.isDirect(),
82                                        hyperplane.getTolerance());
83              }
84  
85          };
86          arcsSet.getTree(false).visit(visitor);
87          return visitor.getDump();
88      }
89  
90      /** Get a string representation of a {@link SphericalPolygonsSet}.
91       * @param sphericalPolygonsSet region to dump
92       * @return string representation of the region
93       */
94      public static String dump(final SphericalPolygonsSet sphericalPolygonsSet) {
95          final TreeDumper<Sphere2D, S2Point, Circle, SubCircle> visitor =
96                  new TreeDumper<Sphere2D, S2Point, Circle, SubCircle>("SphericalPolygonsSet", sphericalPolygonsSet.getTolerance()) {
97  
98              /** {@inheritDoc} */
99              @Override
100             protected void formatHyperplane(final Circle hyperplane) {
101                 getFormatter().format("%22.15e %22.15e %22.15e %22.15e",
102                                       hyperplane.getPole().getX(), hyperplane.getPole().getY(), hyperplane.getPole().getZ(),
103                                       hyperplane.getTolerance());
104             }
105 
106         };
107         sphericalPolygonsSet.getTree(false).visit(visitor);
108         return visitor.getDump();
109     }
110 
111     /** Get a string representation of an {@link IntervalsSet}.
112      * @param intervalsSet region to dump
113      * @return string representation of the region
114      */
115     public static String dump(final IntervalsSet intervalsSet) {
116         final TreeDumper<Euclidean1D, Vector1D, OrientedPoint, SubOrientedPoint> visitor =
117                 new TreeDumper<Euclidean1D, Vector1D, OrientedPoint, SubOrientedPoint>("IntervalsSet", intervalsSet.getTolerance()) {
118 
119             /** {@inheritDoc} */
120             @Override
121             protected void formatHyperplane(final OrientedPoint hyperplane) {
122                 getFormatter().format("%22.15e %b %22.15e",
123                                       hyperplane.getLocation().getX(),
124                                       hyperplane.isDirect(),
125                                       hyperplane.getTolerance());
126             }
127 
128         };
129         intervalsSet.getTree(false).visit(visitor);
130         return visitor.getDump();
131     }
132 
133     /** Get a string representation of a {@link PolygonsSet}.
134      * @param polygonsSet region to dump
135      * @return string representation of the region
136      */
137     public static String dump(final PolygonsSet polygonsSet) {
138         final TreeDumper<Euclidean2D, Vector2D, Line, SubLine> visitor =
139                 new TreeDumper<Euclidean2D, Vector2D, Line, SubLine>("PolygonsSet", polygonsSet.getTolerance()) {
140 
141             /** {@inheritDoc} */
142             @Override
143             protected void formatHyperplane(final Line hyperplane) {
144                 final Vector2D p = hyperplane.toSpace(Vector1D.ZERO);
145                 getFormatter().format("%22.15e %22.15e %22.15e %22.15e",
146                                       p.getX(), p.getY(), hyperplane.getAngle(), hyperplane.getTolerance());
147             }
148 
149         };
150         polygonsSet.getTree(false).visit(visitor);
151         return visitor.getDump();
152     }
153 
154     /** Get a string representation of a {@link PolyhedronsSet}.
155      * @param polyhedronsSet region to dump
156      * @return string representation of the region
157      */
158     public static String dump(final PolyhedronsSet polyhedronsSet) {
159         final TreeDumper<Euclidean3D, Vector3D, Plane, SubPlane> visitor =
160                 new TreeDumper<Euclidean3D, Vector3D, Plane, SubPlane>("PolyhedronsSet", polyhedronsSet.getTolerance()) {
161 
162             /** {@inheritDoc} */
163             @Override
164             protected void formatHyperplane(final Plane hyperplane) {
165                 final Vector3D p = hyperplane.toSpace(Vector2D.ZERO);
166                 getFormatter().format("%22.15e %22.15e %22.15e %22.15e %22.15e %22.15e %22.15e",
167                                       p.getX(), p.getY(), p.getZ(),
168                                       hyperplane.getNormal().getX(), hyperplane.getNormal().getY(), hyperplane.getNormal().getZ(),
169                                       hyperplane.getTolerance());
170             }
171 
172         };
173         polyhedronsSet.getTree(false).visit(visitor);
174         return visitor.getDump();
175     }
176 
177     /** Dumping visitor.
178      * @param <S> Type of the space.
179      * @param <P> Type of the points in space.
180      * @param <H> Type of the hyperplane.
181      * @param <I> Type of the sub-hyperplane.
182      */
183     private abstract static class TreeDumper<S extends Space,
184                                              P extends Point<S, P>,
185                                              H extends Hyperplane<S, P, H, I>,
186                                              I extends SubHyperplane<S, P, H, I>>
187         implements BSPTreeVisitor<S, P, H, I> {
188 
189         /** Builder for the string representation of the dumped tree. */
190         private final StringBuilder dump;
191 
192         /** Formatter for strings. */
193         private final Formatter formatter;
194 
195         /** Current indentation prefix. */
196         private String prefix;
197 
198         /** Simple constructor.
199          * @param type type of the region to dump
200          * @param tolerance tolerance of the region
201          */
202         public TreeDumper(final String type, final double tolerance) {
203             this.dump      = new StringBuilder();
204             this.formatter = new Formatter(dump, Locale.US);
205             this.prefix    = "";
206             formatter.format("%s%n", type);
207             formatter.format("tolerance %22.15e%n", tolerance);
208         }
209 
210         /** Get the string representation of the tree.
211          * @return string representation of the tree.
212          */
213         public String getDump() {
214             return dump.toString();
215         }
216 
217         /** Get the formatter to use.
218          * @return formatter to use
219          */
220         protected Formatter getFormatter() {
221             return formatter;
222         }
223 
224         /** Format a string representation of the hyperplane underlying a cut sub-hyperplane.
225          * @param hyperplane hyperplane to format
226          */
227         protected abstract void formatHyperplane(H hyperplane);
228 
229         /** {@inheritDoc} */
230         @Override
231         public Order visitOrder(final BSPTree<S, P, H, I> node) {
232             return Order.SUB_MINUS_PLUS;
233         }
234 
235         /** {@inheritDoc} */
236         @Override
237         public void visitInternalNode(final BSPTree<S, P, H, I> node) {
238             formatter.format("%s %s internal ", prefix, type(node));
239             formatHyperplane(node.getCut().getHyperplane());
240             formatter.format("%n");
241             prefix = prefix + "  ";
242         }
243 
244         /** {@inheritDoc} */
245         @Override
246         public void visitLeafNode(final BSPTree<S, P, H, I> node) {
247             formatter.format("%s %s leaf %s%n",
248                              prefix, type(node), node.getAttribute());
249             for (BSPTree<S, P, H, I> n = node;
250                  n.getParent() != null && n == n.getParent().getPlus();
251                  n = n.getParent()) {
252                 prefix = prefix.substring(0, prefix.length() - 2);
253             }
254         }
255 
256         /** Get the type of the node.
257          * @param node node to check
258          * @return "plus " or "minus" depending on the node being the plus or minus
259          * child of its parent ("plus " is arbitrarily returned for the root node)
260          */
261         private String type(final BSPTree<S, P, H, I> node) {
262             return (node.getParent() != null && node == node.getParent().getMinus()) ? "minus" : "plus ";
263         }
264 
265     }
266 
267 }