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.spherical.oned;
23  
24  import org.hipparchus.exception.MathIllegalArgumentException;
25  import org.hipparchus.geometry.partitioning.BSPTree;
26  import org.hipparchus.geometry.partitioning.Region;
27  import org.hipparchus.geometry.partitioning.Region.Location;
28  import org.hipparchus.geometry.partitioning.RegionFactory;
29  import org.hipparchus.geometry.partitioning.Side;
30  import org.hipparchus.util.FastMath;
31  import org.hipparchus.util.MathUtils;
32  import org.hipparchus.util.Precision;
33  import org.junit.jupiter.api.Test;
34  
35  import java.util.ArrayList;
36  import java.util.Iterator;
37  import java.util.List;
38  import java.util.NoSuchElementException;
39  
40  import static org.junit.jupiter.api.Assertions.assertEquals;
41  import static org.junit.jupiter.api.Assertions.assertFalse;
42  import static org.junit.jupiter.api.Assertions.assertNotNull;
43  import static org.junit.jupiter.api.Assertions.assertNull;
44  import static org.junit.jupiter.api.Assertions.assertThrows;
45  import static org.junit.jupiter.api.Assertions.assertTrue;
46  import static org.junit.jupiter.api.Assertions.fail;
47  
48  class ArcsSetTest {
49  
50      @Test
51      void testArc() {
52          ArcsSet set = new ArcsSet(2.3, 5.7, 1.0e-10);
53          assertEquals(3.4, set.getSize(), 1.0e-10);
54          assertEquals(1.0e-10, set.getTolerance(), 1.0e-20);
55          assertEquals(Region.Location.BOUNDARY, set.checkPoint(new S1Point(2.3)));
56          assertEquals(Region.Location.BOUNDARY, set.checkPoint(new S1Point(5.7)));
57          assertEquals(Region.Location.OUTSIDE,  set.checkPoint(new S1Point(1.2)));
58          assertEquals(Region.Location.OUTSIDE,  set.checkPoint(new S1Point(8.5)));
59          assertEquals(Region.Location.INSIDE,   set.checkPoint(new S1Point(8.7)));
60          assertEquals(Region.Location.INSIDE,   set.checkPoint(new S1Point(3.0)));
61          assertEquals(1, set.asList().size());
62          assertEquals(2.3, set.asList().get(0).getInf(), 1.0e-10);
63          assertEquals(5.7, set.asList().get(0).getSup(), 1.0e-10);
64          assertEquals(Location.INSIDE, set.checkPoint(set.getInteriorPoint()));
65      }
66  
67      @Test
68      void testWrapAround2PiArc() {
69          ArcsSet set = new ArcsSet(5.7 - MathUtils.TWO_PI, 2.3, 1.0e-10);
70          assertEquals(MathUtils.TWO_PI - 3.4, set.getSize(), 1.0e-10);
71          assertEquals(1.0e-10, set.getTolerance(), 1.0e-20);
72          assertEquals(Region.Location.BOUNDARY, set.checkPoint(new S1Point(2.3)));
73          assertEquals(Region.Location.BOUNDARY, set.checkPoint(new S1Point(5.7)));
74          assertEquals(Region.Location.INSIDE,   set.checkPoint(new S1Point(1.2)));
75          assertEquals(Region.Location.INSIDE,   set.checkPoint(new S1Point(8.5)));
76          assertEquals(Region.Location.OUTSIDE,  set.checkPoint(new S1Point(8.7)));
77          assertEquals(Region.Location.OUTSIDE,  set.checkPoint(new S1Point(3.0)));
78          assertEquals(1, set.asList().size());
79          assertEquals(5.7, set.asList().get(0).getInf(), 1.0e-10);
80          assertEquals(2.3 + MathUtils.TWO_PI, set.asList().get(0).getSup(), 1.0e-10);
81          assertEquals(Location.INSIDE, set.checkPoint(set.getInteriorPoint()));
82      }
83  
84      @Test
85      void testSplitOver2Pi() {
86          ArcsSet set = new ArcsSet(1.0e-10);
87          Arc     arc = new Arc(1.5 * FastMath.PI, 2.5 * FastMath.PI, 1.0e-10);
88          ArcsSet.Split split = set.split(arc);
89          for (double alpha = 0.0; alpha <= MathUtils.TWO_PI; alpha += 0.01) {
90              S1Point p = new S1Point(alpha);
91              if (alpha < MathUtils.SEMI_PI || alpha > 1.5 * FastMath.PI) {
92                  assertEquals(Location.OUTSIDE, split.getPlus().checkPoint(p));
93                  assertEquals(Location.INSIDE,  split.getMinus().checkPoint(p));
94              } else {
95                  assertEquals(Location.INSIDE,  split.getPlus().checkPoint(p));
96                  assertEquals(Location.OUTSIDE, split.getMinus().checkPoint(p));
97              }
98          }
99          assertEquals(Location.INSIDE, set.checkPoint(set.getInteriorPoint()));
100     }
101 
102     @Test
103     void testSplitAtEnd() {
104         ArcsSet set = new ArcsSet(1.0e-10);
105         Arc     arc = new Arc(FastMath.PI, MathUtils.TWO_PI, 1.0e-10);
106         ArcsSet.Split split = set.split(arc);
107         for (double alpha = 0.01; alpha < MathUtils.TWO_PI; alpha += 0.01) {
108             S1Point p = new S1Point(alpha);
109             if (alpha > FastMath.PI) {
110                 assertEquals(Location.OUTSIDE, split.getPlus().checkPoint(p));
111                 assertEquals(Location.INSIDE,  split.getMinus().checkPoint(p));
112             } else {
113                 assertEquals(Location.INSIDE,  split.getPlus().checkPoint(p));
114                 assertEquals(Location.OUTSIDE, split.getMinus().checkPoint(p));
115             }
116         }
117 
118         S1Point zero = new S1Point(0.0);
119         assertEquals(Location.BOUNDARY,  split.getPlus().checkPoint(zero));
120         assertEquals(Location.BOUNDARY,  split.getMinus().checkPoint(zero));
121 
122         S1Point pi = new S1Point(FastMath.PI);
123         assertEquals(Location.BOUNDARY,  split.getPlus().checkPoint(pi));
124         assertEquals(Location.BOUNDARY,  split.getMinus().checkPoint(pi));
125 
126     }
127 
128     @Test
129     void testWrongInterval() {
130         assertThrows(MathIllegalArgumentException.class, () -> new ArcsSet(1.2, 0.0, 1.0e-10));
131     }
132 
133     @Test
134     void testTooSmallTolerance() {
135         assertThrows(MathIllegalArgumentException.class, () -> new ArcsSet(0.0, 1.0, 0.9 * Sphere1D.SMALLEST_TOLERANCE));
136     }
137 
138     @Test
139     void testFullEqualEndPoints() {
140         ArcsSet set = new ArcsSet(1.0, 1.0, 1.0e-10);
141         assertEquals(1.0e-10, set.getTolerance(), 1.0e-20);
142         assertEquals(Region.Location.INSIDE, set.checkPoint(new S1Point(9.0)));
143         for (double alpha = -20.0; alpha <= 20.0; alpha += 0.1) {
144             assertEquals(Region.Location.INSIDE, set.checkPoint(new S1Point(alpha)));
145         }
146         assertEquals(1, set.asList().size());
147         assertEquals(0.0, set.asList().get(0).getInf(), 1.0e-10);
148         assertEquals(2 * FastMath.PI, set.asList().get(0).getSup(), 1.0e-10);
149         assertEquals(2 * FastMath.PI, set.getSize(), 1.0e-10);
150         assertEquals(Location.INSIDE, set.checkPoint(set.getInteriorPoint()));
151     }
152 
153     @Test
154     void testFullCircle() {
155         ArcsSet set = new ArcsSet(1.0e-10);
156         assertEquals(1.0e-10, set.getTolerance(), 1.0e-20);
157         assertEquals(Region.Location.INSIDE, set.checkPoint(new S1Point(9.0)));
158         for (double alpha = -20.0; alpha <= 20.0; alpha += 0.1) {
159             assertEquals(Region.Location.INSIDE, set.checkPoint(new S1Point(alpha)));
160         }
161         assertEquals(1, set.asList().size());
162         assertEquals(0.0, set.asList().get(0).getInf(), 1.0e-10);
163         assertEquals(2 * FastMath.PI, set.asList().get(0).getSup(), 1.0e-10);
164         assertEquals(2 * FastMath.PI, set.getSize(), 1.0e-10);
165         assertEquals(Location.INSIDE, set.checkPoint(set.getInteriorPoint()));
166     }
167 
168     @Test
169     void testEmpty() {
170         ArcsSet empty = (ArcsSet) new RegionFactory<Sphere1D, S1Point, LimitAngle, SubLimitAngle>().getComplement(new ArcsSet(1.0e-10));
171         assertEquals(1.0e-10, empty.getTolerance(), 1.0e-20);
172         assertEquals(0.0, empty.getSize(), 1.0e-10);
173         assertTrue(empty.asList().isEmpty());
174         assertNull(empty.getInteriorPoint());
175     }
176 
177     @Test
178     void testTiny() {
179         ArcsSet tiny = new ArcsSet(0.0, Precision.SAFE_MIN / 2, 1.0e-10);
180         assertEquals(1.0e-10, tiny.getTolerance(), 1.0e-20);
181         assertEquals(Precision.SAFE_MIN / 2, tiny.getSize(), 1.0e-10);
182         assertEquals(1, tiny.asList().size());
183         assertEquals(0.0, tiny.asList().get(0).getInf(), 1.0e-10);
184         assertEquals(Precision.SAFE_MIN / 2, tiny.asList().get(0).getSup(), 1.0e-10);
185         assertEquals(Location.BOUNDARY, tiny.checkPoint(tiny.getInteriorPoint()));
186     }
187 
188     @Test
189     void testSpecialConstruction() {
190         List<SubLimitAngle> boundary = new ArrayList<>();
191         boundary.add(new LimitAngle(new S1Point(0.0), false, 1.0e-10).wholeHyperplane());
192         boundary.add(new LimitAngle(new S1Point(MathUtils.TWO_PI - 1.0e-11), true, 1.0e-10).wholeHyperplane());
193         ArcsSet set = new ArcsSet(boundary, 1.0e-10);
194         assertEquals(MathUtils.TWO_PI, set.getSize(), 1.0e-10);
195         assertEquals(1.0e-10, set.getTolerance(), 1.0e-20);
196         assertEquals(1, set.asList().size());
197         assertEquals(0.0, set.asList().get(0).getInf(), 1.0e-10);
198         assertEquals(MathUtils.TWO_PI, set.asList().get(0).getSup(), 1.0e-10);
199         assertEquals(Location.INSIDE, set.checkPoint(set.getInteriorPoint()));
200     }
201 
202     @Test
203     void testDifference() {
204 
205         ArcsSet a   = new ArcsSet(1.0, 6.0, 1.0e-10);
206         List<Arc> aList = a.asList();
207         assertEquals(1,   aList.size());
208         assertEquals(1.0, aList.get(0).getInf(), 1.0e-10);
209         assertEquals(6.0, aList.get(0).getSup(), 1.0e-10);
210 
211         ArcsSet b   = new ArcsSet(3.0, 5.0, 1.0e-10);
212         List<Arc> bList = b.asList();
213         assertEquals(1,   bList.size());
214         assertEquals(3.0, bList.get(0).getInf(), 1.0e-10);
215         assertEquals(5.0, bList.get(0).getSup(), 1.0e-10);
216 
217         ArcsSet aMb = (ArcsSet) new RegionFactory<Sphere1D, S1Point, LimitAngle, SubLimitAngle>().difference(a, b);
218         for (int k = -2; k < 3; ++k) {
219             assertEquals(Location.OUTSIDE,  aMb.checkPoint(new S1Point(0.0 + k * MathUtils.TWO_PI)));
220             assertEquals(Location.OUTSIDE,  aMb.checkPoint(new S1Point(0.9 + k * MathUtils.TWO_PI)));
221             assertEquals(Location.BOUNDARY, aMb.checkPoint(new S1Point(1.0 + k * MathUtils.TWO_PI)));
222             assertEquals(Location.INSIDE,   aMb.checkPoint(new S1Point(1.1 + k * MathUtils.TWO_PI)));
223             assertEquals(Location.INSIDE,   aMb.checkPoint(new S1Point(2.9 + k * MathUtils.TWO_PI)));
224             assertEquals(Location.BOUNDARY, aMb.checkPoint(new S1Point(3.0 + k * MathUtils.TWO_PI)));
225             assertEquals(Location.OUTSIDE,  aMb.checkPoint(new S1Point(3.1 + k * MathUtils.TWO_PI)));
226             assertEquals(Location.OUTSIDE,  aMb.checkPoint(new S1Point(4.9 + k * MathUtils.TWO_PI)));
227             assertEquals(Location.BOUNDARY, aMb.checkPoint(new S1Point(5.0 + k * MathUtils.TWO_PI)));
228             assertEquals(Location.INSIDE,   aMb.checkPoint(new S1Point(5.1 + k * MathUtils.TWO_PI)));
229             assertEquals(Location.INSIDE,   aMb.checkPoint(new S1Point(5.9 + k * MathUtils.TWO_PI)));
230             assertEquals(Location.BOUNDARY, aMb.checkPoint(new S1Point(6.0 + k * MathUtils.TWO_PI)));
231             assertEquals(Location.OUTSIDE,  aMb.checkPoint(new S1Point(6.1 + k * MathUtils.TWO_PI)));
232             assertEquals(Location.OUTSIDE,  aMb.checkPoint(new S1Point(6.2 + k * MathUtils.TWO_PI)));
233         }
234 
235         List<Arc> aMbList = aMb.asList();
236         assertEquals(2,   aMbList.size());
237         assertEquals(1.0, aMbList.get(0).getInf(), 1.0e-10);
238         assertEquals(3.0, aMbList.get(0).getSup(), 1.0e-10);
239         assertEquals(5.0, aMbList.get(1).getInf(), 1.0e-10);
240         assertEquals(6.0, aMbList.get(1).getSup(), 1.0e-10);
241         assertEquals(Location.INSIDE, aMb.checkPoint(aMb.getInteriorPoint()));
242 
243 
244     }
245 
246     @Test
247     void testIntersection() {
248 
249         ArcsSet a   = (ArcsSet) new RegionFactory<Sphere1D, S1Point, LimitAngle, SubLimitAngle>().
250                        union(new ArcsSet(1.0, 3.0, 1.0e-10), new ArcsSet(5.0, 6.0, 1.0e-10));
251         List<Arc> aList = a.asList();
252         assertEquals(2,   aList.size());
253         assertEquals(1.0, aList.get(0).getInf(), 1.0e-10);
254         assertEquals(3.0, aList.get(0).getSup(), 1.0e-10);
255         assertEquals(5.0, aList.get(1).getInf(), 1.0e-10);
256         assertEquals(6.0, aList.get(1).getSup(), 1.0e-10);
257 
258         ArcsSet b   = new ArcsSet(0.0, 5.5, 1.0e-10);
259         List<Arc> bList = b.asList();
260         assertEquals(1,   bList.size());
261         assertEquals(0.0, bList.get(0).getInf(), 1.0e-10);
262         assertEquals(5.5, bList.get(0).getSup(), 1.0e-10);
263 
264         ArcsSet aMb = (ArcsSet) new RegionFactory<Sphere1D, S1Point, LimitAngle, SubLimitAngle>().
265                 intersection(a, b);
266         for (int k = -2; k < 3; ++k) {
267             assertEquals(Location.OUTSIDE,  aMb.checkPoint(new S1Point(0.0 + k * MathUtils.TWO_PI)));
268             assertEquals(Location.BOUNDARY, aMb.checkPoint(new S1Point(1.0 + k * MathUtils.TWO_PI)));
269             assertEquals(Location.INSIDE,   aMb.checkPoint(new S1Point(1.1 + k * MathUtils.TWO_PI)));
270             assertEquals(Location.INSIDE,   aMb.checkPoint(new S1Point(2.9 + k * MathUtils.TWO_PI)));
271             assertEquals(Location.BOUNDARY, aMb.checkPoint(new S1Point(3.0 + k * MathUtils.TWO_PI)));
272             assertEquals(Location.OUTSIDE,  aMb.checkPoint(new S1Point(3.1 + k * MathUtils.TWO_PI)));
273             assertEquals(Location.OUTSIDE,  aMb.checkPoint(new S1Point(4.9 + k * MathUtils.TWO_PI)));
274             assertEquals(Location.BOUNDARY, aMb.checkPoint(new S1Point(5.0 + k * MathUtils.TWO_PI)));
275             assertEquals(Location.INSIDE,   aMb.checkPoint(new S1Point(5.1 + k * MathUtils.TWO_PI)));
276             assertEquals(Location.INSIDE,   aMb.checkPoint(new S1Point(5.4 + k * MathUtils.TWO_PI)));
277             assertEquals(Location.BOUNDARY, aMb.checkPoint(new S1Point(5.5 + k * MathUtils.TWO_PI)));
278             assertEquals(Location.OUTSIDE,  aMb.checkPoint(new S1Point(5.6 + k * MathUtils.TWO_PI)));
279             assertEquals(Location.OUTSIDE,  aMb.checkPoint(new S1Point(6.2 + k * MathUtils.TWO_PI)));
280         }
281 
282         List<Arc> aMbList = aMb.asList();
283         assertEquals(2,   aMbList.size());
284         assertEquals(1.0, aMbList.get(0).getInf(), 1.0e-10);
285         assertEquals(3.0, aMbList.get(0).getSup(), 1.0e-10);
286         assertEquals(5.0, aMbList.get(1).getInf(), 1.0e-10);
287         assertEquals(5.5, aMbList.get(1).getSup(), 1.0e-10);
288         assertEquals(Location.INSIDE, aMb.checkPoint(aMb.getInteriorPoint()));
289 
290     }
291 
292     @Test
293     void testMultiple() {
294         RegionFactory<Sphere1D, S1Point, LimitAngle, SubLimitAngle> factory = new RegionFactory<>();
295         ArcsSet set = (ArcsSet)
296         factory.intersection(factory.union(factory.difference(new ArcsSet(1.0, 6.0, 1.0e-10),
297                                                               new ArcsSet(3.0, 5.0, 1.0e-10)),
298                                                               new ArcsSet(0.5, 2.0, 1.0e-10)),
299                                                               new ArcsSet(0.0, 5.5, 1.0e-10));
300         assertEquals(3.0, set.getSize(), 1.0e-10);
301         assertEquals(Region.Location.OUTSIDE,  set.checkPoint(new S1Point(0.0)));
302         assertEquals(Region.Location.OUTSIDE,  set.checkPoint(new S1Point(4.0)));
303         assertEquals(Region.Location.OUTSIDE,  set.checkPoint(new S1Point(6.0)));
304         assertEquals(Region.Location.INSIDE,   set.checkPoint(new S1Point(1.2)));
305         assertEquals(Region.Location.INSIDE,   set.checkPoint(new S1Point(5.25)));
306         assertEquals(Region.Location.BOUNDARY, set.checkPoint(new S1Point(0.5)));
307         assertEquals(Region.Location.BOUNDARY, set.checkPoint(new S1Point(3.0)));
308         assertEquals(Region.Location.BOUNDARY, set.checkPoint(new S1Point(5.0)));
309         assertEquals(Region.Location.BOUNDARY, set.checkPoint(new S1Point(5.5)));
310 
311         List<Arc> list = set.asList();
312         assertEquals(2, list.size());
313         assertEquals( 0.5, list.get(0).getInf(), 1.0e-10);
314         assertEquals( 3.0, list.get(0).getSup(), 1.0e-10);
315         assertEquals( 5.0, list.get(1).getInf(), 1.0e-10);
316         assertEquals( 5.5, list.get(1).getSup(), 1.0e-10);
317         assertEquals(Location.INSIDE, set.checkPoint(set.getInteriorPoint()));
318 
319     }
320 
321     @Test
322     void testSinglePoint() {
323         ArcsSet set = new ArcsSet(1.0, FastMath.nextAfter(1.0, Double.POSITIVE_INFINITY), 1.0e-10);
324         assertEquals(2 * Precision.EPSILON, set.getSize(), Precision.SAFE_MIN);
325     }
326 
327     @Test
328     void testIteration() {
329         ArcsSet set = (ArcsSet) new RegionFactory<Sphere1D, S1Point, LimitAngle, SubLimitAngle>().
330                 difference(new ArcsSet(1.0, 6.0, 1.0e-10), new ArcsSet(3.0, 5.0, 1.0e-10));
331         Iterator<double[]> iterator = set.iterator();
332         try {
333             iterator.remove();
334             fail("an exception should have been thrown");
335         } catch (UnsupportedOperationException uoe) {
336             // expected
337         }
338 
339         assertTrue(iterator.hasNext());
340         double[] a0 = iterator.next();
341         assertEquals(2, a0.length);
342         assertEquals(1.0, a0[0], 1.0e-10);
343         assertEquals(3.0, a0[1], 1.0e-10);
344 
345         assertTrue(iterator.hasNext());
346         double[] a1 = iterator.next();
347         assertEquals(2, a1.length);
348         assertEquals(5.0, a1[0], 1.0e-10);
349         assertEquals(6.0, a1[1], 1.0e-10);
350 
351         assertFalse(iterator.hasNext());
352         try {
353             iterator.next();
354             fail("an exception should have been thrown");
355         } catch (NoSuchElementException nsee) {
356             // expected
357         }
358 
359     }
360 
361     @Test
362     void testEmptyTree() {
363         assertEquals(MathUtils.TWO_PI,
364                      new ArcsSet(new BSPTree<>(Boolean.TRUE), 1.0e-10).getSize(),
365                      1.0e-10);
366     }
367 
368     @Test
369     void testShiftedAngles() {
370         for (int k = -2; k < 3; ++k) {
371             SubLimitAngle l1  = new LimitAngle(new S1Point(1.0 + k * MathUtils.TWO_PI), false, 1.0e-10).wholeHyperplane();
372             SubLimitAngle l2  = new LimitAngle(new S1Point(1.5 + k * MathUtils.TWO_PI), true,  1.0e-10).wholeHyperplane();
373             ArcsSet set = new ArcsSet(new BSPTree<>(l1,
374                                                     new BSPTree<>(Boolean.FALSE),
375                                                     new BSPTree<>(l2,
376                                                                   new BSPTree<>(Boolean.FALSE),
377                                                                   new BSPTree<>(Boolean.TRUE),
378                                                                   null),
379                                                     null),
380                                       1.0e-10);
381             for (double alpha = 1.0e-6; alpha < MathUtils.TWO_PI; alpha += 0.001) {
382                 if (alpha < 1 || alpha > 1.5) {
383                     assertEquals(Location.OUTSIDE, set.checkPoint(new S1Point(alpha)));
384                 } else {
385                     assertEquals(Location.INSIDE,  set.checkPoint(new S1Point(alpha)));
386                 }
387             }
388         }
389 
390     }
391 
392     @Test
393     void testInconsistentState() {
394         assertThrows(ArcsSet.InconsistentStateAt2PiWrapping.class, () -> {
395             SubLimitAngle l1 = new LimitAngle(new S1Point(1.0), false, 1.0e-10).wholeHyperplane();
396             SubLimitAngle l2 = new LimitAngle(new S1Point(2.0), true, 1.0e-10).wholeHyperplane();
397             SubLimitAngle l3 = new LimitAngle(new S1Point(3.0), false, 1.0e-10).wholeHyperplane();
398             new ArcsSet(new BSPTree<>(l1,
399                                       new BSPTree<>(Boolean.FALSE),
400                                       new BSPTree<>(l2,
401                                                     new BSPTree<>(l3, new BSPTree<>(Boolean.FALSE), new BSPTree<>(Boolean.TRUE), null),
402                                                     new BSPTree<>(Boolean.TRUE),
403                                                     null),
404                                       null),
405                         1.0e-10);
406         });
407     }
408 
409     @Test
410     void testSide() {
411         ArcsSet set = (ArcsSet) new RegionFactory<Sphere1D, S1Point, LimitAngle, SubLimitAngle>().
412                 difference(new ArcsSet(1.0, 6.0, 1.0e-10), new ArcsSet(3.0, 5.0, 1.0e-10));
413         for (int k = -2; k < 3; ++k) {
414             assertEquals(Side.MINUS, set.split(new Arc(0.5 + k * MathUtils.TWO_PI,
415                                                               6.1 + k * MathUtils.TWO_PI,
416                                                               set.getTolerance())).getSide());
417             assertEquals(Side.PLUS,  set.split(new Arc(0.5 + k * MathUtils.TWO_PI,
418                                                               0.8 + k * MathUtils.TWO_PI,
419                                                               set.getTolerance())).getSide());
420             assertEquals(Side.PLUS,  set.split(new Arc(6.2 + k * MathUtils.TWO_PI,
421                                                               6.3 + k * MathUtils.TWO_PI,
422                                                               set.getTolerance())).getSide());
423             assertEquals(Side.PLUS,  set.split(new Arc(3.5 + k * MathUtils.TWO_PI,
424                                                               4.5 + k * MathUtils.TWO_PI,
425                                                               set.getTolerance())).getSide());
426             assertEquals(Side.BOTH,  set.split(new Arc(2.9 + k * MathUtils.TWO_PI,
427                                                               4.5 + k * MathUtils.TWO_PI,
428                                                               set.getTolerance())).getSide());
429             assertEquals(Side.BOTH,  set.split(new Arc(0.5 + k * MathUtils.TWO_PI,
430                                                               1.2 + k * MathUtils.TWO_PI,
431                                                               set.getTolerance())).getSide());
432             assertEquals(Side.BOTH,  set.split(new Arc(0.5 + k * MathUtils.TWO_PI,
433                                                               5.9 + k * MathUtils.TWO_PI,
434                                                               set.getTolerance())).getSide());
435         }
436     }
437 
438     @Test
439     void testSideEmbedded() {
440 
441         ArcsSet s35 = new ArcsSet(3.0, 5.0, 1.0e-10);
442         ArcsSet s16 = new ArcsSet(1.0, 6.0, 1.0e-10);
443 
444         assertEquals(Side.BOTH,  s16.split(new Arc(3.0, 5.0, 1.0e-10)).getSide());
445         assertEquals(Side.BOTH,  s16.split(new Arc(5.0, 3.0 + MathUtils.TWO_PI, 1.0e-10)).getSide());
446         assertEquals(Side.MINUS, s35.split(new Arc(1.0, 6.0, 1.0e-10)).getSide());
447         assertEquals(Side.PLUS,  s35.split(new Arc(6.0, 1.0 + MathUtils.TWO_PI, 1.0e-10)).getSide());
448 
449     }
450 
451     @Test
452     void testSideOverlapping() {
453         ArcsSet s35 = new ArcsSet(3.0, 5.0, 1.0e-10);
454         ArcsSet s46 = new ArcsSet(4.0, 6.0, 1.0e-10);
455 
456         assertEquals(Side.BOTH,  s46.split(new Arc(3.0, 5.0, 1.0e-10)).getSide());
457         assertEquals(Side.BOTH,  s46.split(new Arc(5.0, 3.0 + MathUtils.TWO_PI, 1.0e-10)).getSide());
458         assertEquals(Side.BOTH, s35.split(new Arc(4.0, 6.0, 1.0e-10)).getSide());
459         assertEquals(Side.BOTH,  s35.split(new Arc(6.0, 4.0 + MathUtils.TWO_PI, 1.0e-10)).getSide());
460     }
461 
462     @Test
463     void testSideHyper() {
464         ArcsSet sub = (ArcsSet) new RegionFactory<Sphere1D, S1Point, LimitAngle, SubLimitAngle>().
465                 getComplement(new ArcsSet(1.0e-10));
466         assertTrue(sub.isEmpty());
467         assertEquals(Side.HYPER,  sub.split(new Arc(2.0, 3.0, 1.0e-10)).getSide());
468     }
469 
470     @Test
471     void testSplitEmbedded() {
472 
473         ArcsSet s35 = new ArcsSet(3.0, 5.0, 1.0e-10);
474         ArcsSet s16 = new ArcsSet(1.0, 6.0, 1.0e-10);
475 
476         ArcsSet.Split split1 = s16.split(new Arc(3.0, 5.0, 1.0e-10));
477         ArcsSet split1Plus  = split1.getPlus();
478         ArcsSet split1Minus = split1.getMinus();
479         assertEquals(3.0, split1Plus.getSize(), 1.0e-10);
480         assertEquals(2,   split1Plus.asList().size());
481         assertEquals(1.0, split1Plus.asList().get(0).getInf(), 1.0e-10);
482         assertEquals(3.0, split1Plus.asList().get(0).getSup(), 1.0e-10);
483         assertEquals(5.0, split1Plus.asList().get(1).getInf(), 1.0e-10);
484         assertEquals(6.0, split1Plus.asList().get(1).getSup(), 1.0e-10);
485         assertEquals(2.0, split1Minus.getSize(), 1.0e-10);
486         assertEquals(1,   split1Minus.asList().size());
487         assertEquals(3.0, split1Minus.asList().get(0).getInf(), 1.0e-10);
488         assertEquals(5.0, split1Minus.asList().get(0).getSup(), 1.0e-10);
489 
490         ArcsSet.Split split2 = s16.split(new Arc(5.0, 3.0 + MathUtils.TWO_PI, 1.0e-10));
491         ArcsSet split2Plus  = split2.getPlus();
492         ArcsSet split2Minus = split2.getMinus();
493         assertEquals(2.0, split2Plus.getSize(), 1.0e-10);
494         assertEquals(1,   split2Plus.asList().size());
495         assertEquals(3.0, split2Plus.asList().get(0).getInf(), 1.0e-10);
496         assertEquals(5.0, split2Plus.asList().get(0).getSup(), 1.0e-10);
497         assertEquals(3.0, split2Minus.getSize(), 1.0e-10);
498         assertEquals(2,   split2Minus.asList().size());
499         assertEquals(1.0, split2Minus.asList().get(0).getInf(), 1.0e-10);
500         assertEquals(3.0, split2Minus.asList().get(0).getSup(), 1.0e-10);
501         assertEquals(5.0, split2Minus.asList().get(1).getInf(), 1.0e-10);
502         assertEquals(6.0, split2Minus.asList().get(1).getSup(), 1.0e-10);
503 
504         ArcsSet.Split split3 = s35.split(new Arc(1.0, 6.0, 1.0e-10));
505         ArcsSet split3Plus  = split3.getPlus();
506         ArcsSet split3Minus = split3.getMinus();
507         assertNull(split3Plus);
508         assertEquals(2.0, split3Minus.getSize(), 1.0e-10);
509         assertEquals(1,   split3Minus.asList().size());
510         assertEquals(3.0, split3Minus.asList().get(0).getInf(), 1.0e-10);
511         assertEquals(5.0, split3Minus.asList().get(0).getSup(), 1.0e-10);
512 
513         ArcsSet.Split split4 = s35.split(new Arc(6.0, 1.0 + MathUtils.TWO_PI, 1.0e-10));
514         ArcsSet split4Plus  = split4.getPlus();
515         ArcsSet split4Minus = split4.getMinus();
516         assertEquals(2.0, split4Plus.getSize(), 1.0e-10);
517         assertEquals(1,   split4Plus.asList().size());
518         assertEquals(3.0, split4Plus.asList().get(0).getInf(), 1.0e-10);
519         assertEquals(5.0, split4Plus.asList().get(0).getSup(), 1.0e-10);
520         assertNull(split4Minus);
521 
522     }
523 
524     @Test
525     void testSplitOverlapping() {
526 
527         ArcsSet s35 = new ArcsSet(3.0, 5.0, 1.0e-10);
528         ArcsSet s46 = new ArcsSet(4.0, 6.0, 1.0e-10);
529 
530         ArcsSet.Split split1 = s46.split(new Arc(3.0, 5.0, 1.0e-10));
531         ArcsSet split1Plus  = split1.getPlus();
532         ArcsSet split1Minus = split1.getMinus();
533         assertEquals(1.0, split1Plus.getSize(), 1.0e-10);
534         assertEquals(1,   split1Plus.asList().size());
535         assertEquals(5.0, split1Plus.asList().get(0).getInf(), 1.0e-10);
536         assertEquals(6.0, split1Plus.asList().get(0).getSup(), 1.0e-10);
537         assertEquals(1.0, split1Minus.getSize(), 1.0e-10);
538         assertEquals(1,   split1Minus.asList().size());
539         assertEquals(4.0, split1Minus.asList().get(0).getInf(), 1.0e-10);
540         assertEquals(5.0, split1Minus.asList().get(0).getSup(), 1.0e-10);
541 
542         ArcsSet.Split split2 = s46.split(new Arc(5.0, 3.0 + MathUtils.TWO_PI, 1.0e-10));
543         ArcsSet split2Plus  = split2.getPlus();
544         ArcsSet split2Minus = split2.getMinus();
545         assertEquals(1.0, split2Plus.getSize(), 1.0e-10);
546         assertEquals(1,   split2Plus.asList().size());
547         assertEquals(4.0, split2Plus.asList().get(0).getInf(), 1.0e-10);
548         assertEquals(5.0, split2Plus.asList().get(0).getSup(), 1.0e-10);
549         assertEquals(1.0, split2Minus.getSize(), 1.0e-10);
550         assertEquals(1,   split2Minus.asList().size());
551         assertEquals(5.0, split2Minus.asList().get(0).getInf(), 1.0e-10);
552         assertEquals(6.0, split2Minus.asList().get(0).getSup(), 1.0e-10);
553 
554         ArcsSet.Split split3 = s35.split(new Arc(4.0, 6.0, 1.0e-10));
555         ArcsSet split3Plus  = split3.getPlus();
556         ArcsSet split3Minus = split3.getMinus();
557         assertEquals(1.0, split3Plus.getSize(), 1.0e-10);
558         assertEquals(1,   split3Plus.asList().size());
559         assertEquals(3.0, split3Plus.asList().get(0).getInf(), 1.0e-10);
560         assertEquals(4.0, split3Plus.asList().get(0).getSup(), 1.0e-10);
561         assertEquals(1.0, split3Minus.getSize(), 1.0e-10);
562         assertEquals(1,   split3Minus.asList().size());
563         assertEquals(4.0, split3Minus.asList().get(0).getInf(), 1.0e-10);
564         assertEquals(5.0, split3Minus.asList().get(0).getSup(), 1.0e-10);
565 
566         ArcsSet.Split split4 = s35.split(new Arc(6.0, 4.0 + MathUtils.TWO_PI, 1.0e-10));
567         ArcsSet split4Plus  = split4.getPlus();
568         ArcsSet split4Minus = split4.getMinus();
569         assertEquals(1.0, split4Plus.getSize(), 1.0e-10);
570         assertEquals(1,   split4Plus.asList().size());
571         assertEquals(4.0, split4Plus.asList().get(0).getInf(), 1.0e-10);
572         assertEquals(5.0, split4Plus.asList().get(0).getSup(), 1.0e-10);
573         assertEquals(1.0, split4Minus.getSize(), 1.0e-10);
574         assertEquals(1,   split4Minus.asList().size());
575         assertEquals(3.0, split4Minus.asList().get(0).getInf(), 1.0e-10);
576         assertEquals(4.0, split4Minus.asList().get(0).getSup(), 1.0e-10);
577 
578     }
579 
580     @Test
581     void testFarSplit() {
582         ArcsSet set = new ArcsSet(FastMath.PI, 2.5 * FastMath.PI, 1.0e-10);
583         ArcsSet.Split split = set.split(new Arc(MathUtils.SEMI_PI, 1.5 * FastMath.PI, 1.0e-10));
584         ArcsSet splitPlus  = split.getPlus();
585         ArcsSet splitMinus = split.getMinus();
586         assertEquals(1,   splitMinus.asList().size());
587         assertEquals(      FastMath.PI, splitMinus.asList().get(0).getInf(), 1.0e-10);
588         assertEquals(1.5 * FastMath.PI, splitMinus.asList().get(0).getSup(), 1.0e-10);
589         assertEquals(MathUtils.SEMI_PI, splitMinus.getSize(), 1.0e-10);
590         assertEquals(1,   splitPlus.asList().size());
591         assertEquals(1.5 * FastMath.PI, splitPlus.asList().get(0).getInf(), 1.0e-10);
592         assertEquals(2.5 * FastMath.PI, splitPlus.asList().get(0).getSup(), 1.0e-10);
593         assertEquals(      FastMath.PI, splitPlus.getSize(), 1.0e-10);
594 
595     }
596 
597     @Test
598     void testSplitWithinEpsilon() {
599         double epsilon = 1.0e-10;
600         double a = 6.25;
601         double b = a - 0.5 * epsilon;
602         ArcsSet set = new ArcsSet(a - 1, a, epsilon);
603         Arc arc = new Arc(b, b + FastMath.PI, epsilon);
604         ArcsSet.Split split = set.split(arc);
605         assertEquals(set.getSize(), split.getPlus().getSize(),  epsilon);
606         assertNull(split.getMinus());
607     }
608 
609     @Test
610     void testSideSplitConsistency() {
611         double  epsilon = 1.0e-6;
612         double  a       = 4.725;
613         ArcsSet set     = new ArcsSet(a, a + 0.5, epsilon);
614         Arc     arc     = new Arc(a + 0.5 * epsilon, a + 1, epsilon);
615         ArcsSet.Split split = set.split(arc);
616         assertNotNull(split.getMinus());
617         assertNull(split.getPlus());
618         assertEquals(Side.MINUS, set.split(arc).getSide());
619     }
620 
621     @Test
622     void testShuffledTreeNonRepresentable() {
623         doTestShuffledTree(FastMath.toRadians( 85.0), FastMath.toRadians( 95.0),
624                            FastMath.toRadians(265.0), FastMath.toRadians(275.0),
625                            1.0e-10);
626     }
627 
628     @Test
629     void testShuffledTreeRepresentable() {
630         doTestShuffledTree(1.0, 2.0,
631                            4.0, 5.0,
632                            1.0e-10);
633     }
634 
635     private void doTestShuffledTree(final double a0, final double a1,
636                                     final double a2, final double a3,
637                                     final double tol) {
638 
639 
640         // intervals set [ a0 ; a1 ] U [ a2 ; a3 ]
641         final ArcsSet setA =
642                         new ArcsSet(new BSPTree<>(new LimitAngle(new S1Point(a0), false, tol).wholeHyperplane(),
643                                                        new BSPTree<>(Boolean.FALSE),
644                                                        new BSPTree<>(new LimitAngle(new S1Point(a1), true, tol).wholeHyperplane(),
645                                                                      new BSPTree<>(new LimitAngle(new S1Point(a2), false, tol).wholeHyperplane(),
646                                                                                    new BSPTree<>(Boolean.FALSE),
647                                                                                    new BSPTree<>(new LimitAngle(new S1Point(a3), true, tol).wholeHyperplane(),
648                                                                                                  new BSPTree<>(Boolean.FALSE),
649                                                                                                  new BSPTree<>(Boolean.TRUE),
650                                                                                                  null),
651                                                                                    null),
652                                                                      new BSPTree<>(Boolean.TRUE),
653                                                                      null),
654                                                        null),
655                                          1.0e-10);
656         assertEquals((a1 - a0) + (a3 - a2), setA.getSize(), 1.0e-10);
657         assertEquals(2, setA.asList().size());
658         assertEquals(a0, setA.asList().get(0).getInf(), 1.0e-15);
659         assertEquals(a1, setA.asList().get(0).getSup(), 1.0e-15);
660         assertEquals(a2, setA.asList().get(1).getInf(), 1.0e-15);
661         assertEquals(a3, setA.asList().get(1).getSup(), 1.0e-15);
662 
663         // same intervals set [ a0 ; a1 ] U [ a2 ; a3 ], but with a different tree organization
664         final ArcsSet setB =
665                         new ArcsSet(new BSPTree<>(new LimitAngle(new S1Point(a2), false, tol).wholeHyperplane(),
666                                                        new BSPTree<>(new LimitAngle(new S1Point(a0), false, tol).wholeHyperplane(),
667                                                                      new BSPTree<>(Boolean.FALSE),
668                                                                      new BSPTree<>(new LimitAngle(new S1Point(a1), true, tol).wholeHyperplane(),
669                                                                                    new BSPTree<>(Boolean.FALSE),
670                                                                                    new BSPTree<>(Boolean.TRUE),
671                                                                                    null),
672                                                                      null),
673                                                        new BSPTree<>(new LimitAngle(new S1Point(a3), true, tol).wholeHyperplane(),
674                                                                      new BSPTree<>(Boolean.FALSE),
675                                                                      new BSPTree<>(Boolean.TRUE),
676                                                                      null),
677                                                        null),
678                                          1.0e-10);
679         assertEquals((a1 - a0) + (a3 - a2), setB.getSize(), 1.0e-10);
680         assertEquals(2, setB.asList().size());
681         assertEquals(a0, setB.asList().get(0).getInf(), 1.0e-15);
682         assertEquals(a1, setB.asList().get(0).getSup(), 1.0e-15);
683         assertEquals(a2, setB.asList().get(1).getInf(), 1.0e-15);
684         assertEquals(a3, setB.asList().get(1).getSup(), 1.0e-15);
685 
686         final ArcsSet intersection = (ArcsSet) new RegionFactory<Sphere1D, S1Point, LimitAngle, SubLimitAngle>().
687                 intersection(setA, setB);
688         assertEquals((a1 - a0) + (a3 - a2), intersection.getSize(), 1.0e-10);
689         assertEquals(2, intersection.asList().size());
690         assertEquals(a0, intersection.asList().get(0).getInf(), 1.0e-15);
691         assertEquals(a1, intersection.asList().get(0).getSup(), 1.0e-15);
692         assertEquals(a2, intersection.asList().get(1).getInf(), 1.0e-15);
693         assertEquals(a3, intersection.asList().get(1).getSup(), 1.0e-15);
694 
695     }
696 
697 }