1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.math4.examples.sofm.chineserings;
19
20 import java.util.Iterator;
21 import java.util.NoSuchElementException;
22
23 import org.apache.commons.rng.UniformRandomProvider;
24 import org.apache.commons.rng.simple.RandomSource;
25 import org.apache.commons.rng.sampling.UnitSphereSampler;
26 import org.apache.commons.rng.sampling.distribution.ContinuousUniformSampler;
27 import org.apache.commons.geometry.euclidean.threed.Vector3D;
28 import org.apache.commons.geometry.euclidean.threed.rotation.Rotation3D;
29 import org.apache.commons.geometry.euclidean.threed.rotation.QuaternionRotation;
30
31
32
33
34
35 class ChineseRings {
36
37 private final Vector3D[] points;
38
39
40
41
42
43
44
45
46
47
48
49 ChineseRings(Vector3D orientationRing1,
50 double radiusRing1,
51 double halfWidthRing1,
52 double radiusRing2,
53 double halfWidthRing2,
54 int numPointsRing1,
55 int numPointsRing2) {
56
57 final Vector3D[] firstRing = new Vector3D[numPointsRing1];
58
59 final Vector3D[] secondRing = new Vector3D[numPointsRing2];
60
61 final UniformRandomProvider rng = RandomSource.WELL_19937_C.create();
62
63
64 final UnitSphereSampler unit = UnitSphereSampler.of(rng, 2);
65
66 final ContinuousUniformSampler radius1
67 = new ContinuousUniformSampler(rng,
68 radiusRing1 - halfWidthRing1,
69 radiusRing1 + halfWidthRing1);
70 final ContinuousUniformSampler widthRing1
71 = new ContinuousUniformSampler(rng,
72 -halfWidthRing1,
73 halfWidthRing1);
74
75 for (int i = 0; i < numPointsRing1; i++) {
76 final double[] v = unit.sample();
77 final double r = radius1.sample();
78
79 firstRing[i] = Vector3D.of(v[0] * r,
80 v[1] * r,
81 widthRing1.sample());
82 }
83
84 final ContinuousUniformSampler radius2
85 = new ContinuousUniformSampler(rng,
86 radiusRing2 - halfWidthRing2,
87 radiusRing2 + halfWidthRing2);
88 final ContinuousUniformSampler widthRing2
89 = new ContinuousUniformSampler(rng,
90 -halfWidthRing2,
91 halfWidthRing2);
92
93 for (int i = 0; i < numPointsRing2; i++) {
94 final double[] v = unit.sample();
95 final double r = radius2.sample();
96
97 secondRing[i] = Vector3D.of(radiusRing1 + v[0] * r,
98 widthRing2.sample(),
99 v[1] * r);
100 }
101
102
103 final Rotation3D rot = QuaternionRotation.createVectorRotation(Vector3D.Unit.PLUS_Z,
104 orientationRing1.normalize());
105 int count = 0;
106 points = new Vector3D[numPointsRing1 + numPointsRing2];
107 for (int i = 0; i < numPointsRing1; i++) {
108 points[count++] = rot.apply(firstRing[i]);
109 }
110 for (int i = 0; i < numPointsRing2; i++) {
111 points[count++] = rot.apply(secondRing[i]);
112 }
113 }
114
115
116
117
118
119
120 public Vector3D[] getPoints() {
121 return points.clone();
122 }
123
124
125
126
127
128
129 public Iterable<double[]> createIterable() {
130 return () -> new Iterator<double[]>() {
131
132 private final Vector3D[] points = getPoints();
133
134 private int n;
135
136
137 @Override
138 public boolean hasNext() {
139 return n < points.length;
140 }
141
142
143 @Override
144 public double[] next() {
145 if (!hasNext()) {
146 throw new NoSuchElementException();
147 }
148 return points[n++].toArray();
149 }
150
151
152 @Override
153 public void remove() {
154 throw new UnsupportedOperationException();
155 }
156 };
157 }
158 }