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.euclidean.threed;
23  
24  import java.util.ArrayList;
25  import java.util.Arrays;
26  import java.util.List;
27  
28  import org.hipparchus.geometry.enclosing.EnclosingBall;
29  import org.hipparchus.random.RandomGenerator;
30  import org.hipparchus.random.UnitSphereRandomVectorGenerator;
31  import org.hipparchus.random.Well1024a;
32  import org.hipparchus.util.FastMath;
33  import org.junit.Assert;
34  import org.junit.Test;
35  
36  
37  public class SphereGeneratorTest {
38  
39      @Test
40      public void testSupport0Point() {
41          List<Vector3D> support = Arrays.asList(new Vector3D[0]);
42          EnclosingBall<Euclidean3D, Vector3D> sphere = new SphereGenerator().ballOnSupport(support);
43          Assert.assertTrue(sphere.getRadius() < 0);
44          Assert.assertEquals(0, sphere.getSupportSize());
45          Assert.assertEquals(0, sphere.getSupport().length);
46      }
47  
48      @Test
49      public void testSupport1Point() {
50          List<Vector3D> support = Arrays.asList(new Vector3D(1, 2, 3));
51          EnclosingBall<Euclidean3D, Vector3D> sphere = new SphereGenerator().ballOnSupport(support);
52          Assert.assertEquals(0.0, sphere.getRadius(), 1.0e-10);
53          Assert.assertTrue(sphere.contains(support.get(0)));
54          Assert.assertTrue(sphere.contains(support.get(0), 0.5));
55          Assert.assertFalse(sphere.contains(new Vector3D(support.get(0).getX() + 0.1,
56                                                          support.get(0).getY() + 0.1,
57                                                          support.get(0).getZ() + 0.1),
58                                             0.001));
59          Assert.assertTrue(sphere.contains(new Vector3D(support.get(0).getX() + 0.1,
60                                                         support.get(0).getY() + 0.1,
61                                                         support.get(0).getZ() + 0.1),
62                                            0.5));
63          Assert.assertEquals(0, support.get(0).distance(sphere.getCenter()), 1.0e-10);
64          Assert.assertEquals(1, sphere.getSupportSize());
65          Assert.assertTrue(support.get(0) == sphere.getSupport()[0]);
66      }
67  
68      @Test
69      public void testSupport2Points() {
70          List<Vector3D> support = Arrays.asList(new Vector3D(1, 0, 0),
71                                                 new Vector3D(3, 0, 0));
72          EnclosingBall<Euclidean3D, Vector3D> sphere = new SphereGenerator().ballOnSupport(support);
73          Assert.assertEquals(1.0, sphere.getRadius(), 1.0e-10);
74          int i = 0;
75          for (Vector3D v : support) {
76              Assert.assertTrue(sphere.contains(v));
77              Assert.assertEquals(1.0, v.distance(sphere.getCenter()), 1.0e-10);
78              Assert.assertTrue(v == sphere.getSupport()[i++]);
79          }
80          Assert.assertTrue(sphere.contains(new Vector3D(2, 0.9, 0)));
81          Assert.assertFalse(sphere.contains(Vector3D.ZERO));
82          Assert.assertEquals(0.0, new Vector3D(2, 0, 0).distance(sphere.getCenter()), 1.0e-10);
83          Assert.assertEquals(2, sphere.getSupportSize());
84      }
85  
86      @Test
87      public void testSupport3Points() {
88          List<Vector3D> support = Arrays.asList(new Vector3D(1, 0, 0),
89                                                 new Vector3D(3, 0, 0),
90                                                 new Vector3D(2, 2, 0));
91          EnclosingBall<Euclidean3D, Vector3D> sphere = new SphereGenerator().ballOnSupport(support);
92          Assert.assertEquals(5.0 / 4.0, sphere.getRadius(), 1.0e-10);
93          int i = 0;
94          for (Vector3D v : support) {
95              Assert.assertTrue(sphere.contains(v));
96              Assert.assertEquals(5.0 / 4.0, v.distance(sphere.getCenter()), 1.0e-10);
97              Assert.assertTrue(v == sphere.getSupport()[i++]);
98          }
99          Assert.assertTrue(sphere.contains(new Vector3D(2, 0.9, 0)));
100         Assert.assertFalse(sphere.contains(new Vector3D(0.9,  0, 0)));
101         Assert.assertFalse(sphere.contains(new Vector3D(3.1,  0, 0)));
102         Assert.assertTrue(sphere.contains(new Vector3D(2.0, -0.499, 0)));
103         Assert.assertFalse(sphere.contains(new Vector3D(2.0, -0.501, 0)));
104         Assert.assertTrue(sphere.contains(new Vector3D(2.0, 3.0 / 4.0, -1.249)));
105         Assert.assertFalse(sphere.contains(new Vector3D(2.0, 3.0 / 4.0, -1.251)));
106         Assert.assertEquals(0.0, new Vector3D(2.0, 3.0 / 4.0, 0).distance(sphere.getCenter()), 1.0e-10);
107         Assert.assertEquals(3, sphere.getSupportSize());
108     }
109 
110     @Test
111     public void testSupport4Points() {
112         List<Vector3D> support = Arrays.asList(new Vector3D(17, 14,  18),
113                                                new Vector3D(11, 14,  22),
114                                                new Vector3D( 2, 22,  17),
115                                                new Vector3D(22, 11, -10));
116         EnclosingBall<Euclidean3D, Vector3D> sphere = new SphereGenerator().ballOnSupport(support);
117         Assert.assertEquals(25.0, sphere.getRadius(), 1.0e-10);
118         int i = 0;
119         for (Vector3D v : support) {
120             Assert.assertTrue(sphere.contains(v));
121             Assert.assertEquals(25.0, v.distance(sphere.getCenter()), 1.0e-10);
122             Assert.assertTrue(v == sphere.getSupport()[i++]);
123         }
124         Assert.assertTrue(sphere.contains (new Vector3D(-22.999, 2, 2)));
125         Assert.assertFalse(sphere.contains(new Vector3D(-23.001, 2, 2)));
126         Assert.assertTrue(sphere.contains (new Vector3D( 26.999, 2, 2)));
127         Assert.assertFalse(sphere.contains(new Vector3D( 27.001, 2, 2)));
128         Assert.assertTrue(sphere.contains (new Vector3D(2, -22.999, 2)));
129         Assert.assertFalse(sphere.contains(new Vector3D(2, -23.001, 2)));
130         Assert.assertTrue(sphere.contains (new Vector3D(2,  26.999, 2)));
131         Assert.assertFalse(sphere.contains(new Vector3D(2,  27.001, 2)));
132         Assert.assertTrue(sphere.contains (new Vector3D(2, 2, -22.999)));
133         Assert.assertFalse(sphere.contains(new Vector3D(2, 2, -23.001)));
134         Assert.assertTrue(sphere.contains (new Vector3D(2, 2,  26.999)));
135         Assert.assertFalse(sphere.contains(new Vector3D(2, 2,  27.001)));
136         Assert.assertEquals(0.0, new Vector3D(2.0, 2.0, 2.0).distance(sphere.getCenter()), 1.0e-10);
137         Assert.assertEquals(4, sphere.getSupportSize());
138     }
139 
140     @Test
141     public void testRandom() {
142         final RandomGenerator random = new Well1024a(0xd015982e9f31ee04l);
143         final UnitSphereRandomVectorGenerator sr = new UnitSphereRandomVectorGenerator(3, random);
144         for (int i = 0; i < 100; ++i) {
145             double d = 25 * random.nextDouble();
146             double refRadius = 10 * random.nextDouble();
147             Vector3D refCenter = new Vector3D(d, new Vector3D(sr.nextVector()));
148             List<Vector3D> support = new ArrayList<Vector3D>();
149             for (int j = 0; j < 5; ++j) {
150                 support.add(new Vector3D(1.0, refCenter, refRadius, new Vector3D(sr.nextVector())));
151             }
152             EnclosingBall<Euclidean3D, Vector3D> sphere = new SphereGenerator().ballOnSupport(support);
153             Assert.assertEquals(0.0, refCenter.distance(sphere.getCenter()), 4e-7 * refRadius);
154             Assert.assertEquals(refRadius, sphere.getRadius(), 1e-7 * refRadius);
155         }
156 
157     }
158 
159     @Test
160     public void testDegeneratedCase() {
161        final List<Vector3D> support =
162                Arrays.asList(new Vector3D(FastMath.scalb(-8039905610797991.0, -50),   //   -7.140870659936730
163                                           FastMath.scalb(-4663475464714142.0, -48),   //  -16.567993074240455
164                                           FastMath.scalb( 6592658872616184.0, -49)),  //   11.710914678204503
165                              new Vector3D(FastMath.scalb(-8036658568968473.0, -50),   //   -7.137986707455888
166                                           FastMath.scalb(-4664256346424880.0, -48),   //  -16.570767323375720
167                                           FastMath.scalb( 6591357011730307.0, -49)),  //  11.708602108715928)
168                              new Vector3D(FastMath.scalb(-8037820142977230.0, -50),   //   -7.139018392423351
169                                           FastMath.scalb(-4665280434237813.0, -48),   //  -16.574405614157020
170                                           FastMath.scalb( 6592435966112099.0, -49)),  //   11.710518716711425
171                              new Vector3D(FastMath.scalb(-8038007803611611.0, -50),   //   -7.139185068549035
172                                           FastMath.scalb(-4664291215918380.0, -48),   //  -16.570891204702250
173                                           FastMath.scalb( 6595270610894208.0, -49))); //   11.715554057357394
174         EnclosingBall<Euclidean3D, Vector3D> sphere = new SphereGenerator().ballOnSupport(support);
175 
176         // the following values have been computed using Emacs calc with exact arithmetic from the
177         // rational representation corresponding to the scalb calls (i.e. -8039905610797991/2^50, ...)
178         // The results were converted to decimal representation rounded to 1.0e-30 when writing the reference
179         // values in this test
180         Assert.assertEquals( -7.139325643360503322823511839511, sphere.getCenter().getX(), 1.0e-20);
181         Assert.assertEquals(-16.571096474251747245361467833760, sphere.getCenter().getY(), 1.0e-20);
182         Assert.assertEquals( 11.711945804096960876521111630800, sphere.getCenter().getZ(), 1.0e-20);
183         Assert.assertEquals(  0.003616820213530053297575846168, sphere.getRadius(),        2.0e-15);
184 
185         for (Vector3D v : support) {
186             Assert.assertTrue(sphere.contains(v, 1.0e-14));
187         }
188 
189     }
190 
191 }