1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.hipparchus.geometry.partitioning;
23
24 import java.io.IOException;
25 import java.text.ParseException;
26 import java.util.StringTokenizer;
27
28 import org.hipparchus.geometry.Point;
29 import org.hipparchus.geometry.Space;
30 import org.hipparchus.geometry.euclidean.oned.Euclidean1D;
31 import org.hipparchus.geometry.euclidean.oned.IntervalsSet;
32 import org.hipparchus.geometry.euclidean.oned.OrientedPoint;
33 import org.hipparchus.geometry.euclidean.oned.SubOrientedPoint;
34 import org.hipparchus.geometry.euclidean.oned.Vector1D;
35 import org.hipparchus.geometry.euclidean.threed.Euclidean3D;
36 import org.hipparchus.geometry.euclidean.threed.Plane;
37 import org.hipparchus.geometry.euclidean.threed.PolyhedronsSet;
38 import org.hipparchus.geometry.euclidean.threed.SubPlane;
39 import org.hipparchus.geometry.euclidean.threed.Vector3D;
40 import org.hipparchus.geometry.euclidean.twod.Euclidean2D;
41 import org.hipparchus.geometry.euclidean.twod.Line;
42 import org.hipparchus.geometry.euclidean.twod.PolygonsSet;
43 import org.hipparchus.geometry.euclidean.twod.SubLine;
44 import org.hipparchus.geometry.euclidean.twod.Vector2D;
45 import org.hipparchus.geometry.spherical.oned.ArcsSet;
46 import org.hipparchus.geometry.spherical.oned.LimitAngle;
47 import org.hipparchus.geometry.spherical.oned.S1Point;
48 import org.hipparchus.geometry.spherical.oned.Sphere1D;
49 import org.hipparchus.geometry.spherical.oned.SubLimitAngle;
50 import org.hipparchus.geometry.spherical.twod.Circle;
51 import org.hipparchus.geometry.spherical.twod.S2Point;
52 import org.hipparchus.geometry.spherical.twod.Sphere2D;
53 import org.hipparchus.geometry.spherical.twod.SphericalPolygonsSet;
54 import org.hipparchus.geometry.spherical.twod.SubCircle;
55
56
57
58
59
60
61
62 public class RegionParser {
63
64
65
66 private RegionParser() {
67 }
68
69
70
71
72
73
74
75 public static ArcsSet parseArcsSet(final String s)
76 throws IOException, ParseException {
77 final TreeBuilder<Sphere1D, S1Point, LimitAngle, SubLimitAngle> builder =
78 new TreeBuilder<Sphere1D, S1Point, LimitAngle, SubLimitAngle>("ArcsSet", s) {
79
80
81 @Override
82 protected LimitAngle parseHyperplane() throws ParseException {
83 return new LimitAngle(new S1Point(getNumber()), getBoolean(), getNumber());
84 }
85
86 };
87 return new ArcsSet(builder.getTree(), builder.getTolerance());
88 }
89
90
91
92
93
94
95
96 public static SphericalPolygonsSet parseSphericalPolygonsSet(final String s)
97 throws IOException, ParseException {
98 final TreeBuilder<Sphere2D, S2Point, Circle, SubCircle> builder =
99 new TreeBuilder<Sphere2D, S2Point, Circle, SubCircle>("SphericalPolygonsSet", s) {
100
101
102 @Override
103 public Circle parseHyperplane() {
104 return new Circle(new Vector3D(getNumber(), getNumber(), getNumber()), getNumber());
105 }
106
107 };
108 return new SphericalPolygonsSet(builder.getTree(), builder.getTolerance());
109 }
110
111
112
113
114
115
116
117 public static IntervalsSet parseIntervalsSet(final String s)
118 throws IOException, ParseException {
119 final TreeBuilder<Euclidean1D, Vector1D, OrientedPoint, SubOrientedPoint> builder =
120 new TreeBuilder<Euclidean1D, Vector1D, OrientedPoint, SubOrientedPoint>("IntervalsSet", s) {
121
122
123 @Override
124 public OrientedPoint parseHyperplane() throws ParseException {
125 return new OrientedPoint(new Vector1D(getNumber()), getBoolean(), getNumber());
126 }
127
128 };
129 return new IntervalsSet(builder.getTree(), builder.getTolerance());
130 }
131
132
133
134
135
136
137
138 public static PolygonsSet parsePolygonsSet(final String s)
139 throws IOException, ParseException {
140 final TreeBuilder<Euclidean2D, Vector2D, Line, SubLine> builder =
141 new TreeBuilder<Euclidean2D, Vector2D, Line, SubLine>("PolygonsSet", s) {
142
143
144 @Override
145 public Line parseHyperplane() {
146 return new Line(new Vector2D(getNumber(), getNumber()), getNumber(), getNumber());
147 }
148
149 };
150 return new PolygonsSet(builder.getTree(), builder.getTolerance());
151 }
152
153
154
155
156
157
158
159 public static PolyhedronsSet parsePolyhedronsSet(final String s)
160 throws IOException, ParseException {
161 final TreeBuilder<Euclidean3D, Vector3D, Plane, SubPlane> builder =
162 new TreeBuilder<Euclidean3D, Vector3D, Plane, SubPlane>("PolyhedronsSet", s) {
163
164
165 @Override
166 public Plane parseHyperplane() {
167 return new Plane(new Vector3D(getNumber(), getNumber(), getNumber()),
168 new Vector3D(getNumber(), getNumber(), getNumber()),
169 getNumber());
170 }
171
172 };
173 return new PolyhedronsSet(builder.getTree(), builder.getTolerance());
174 }
175
176
177
178
179
180
181
182 private abstract static class TreeBuilder<S extends Space,
183 P extends Point<S, P>,
184 H extends Hyperplane<S, P, H, I>,
185 I extends SubHyperplane<S, P, H, I>> {
186
187
188 private static final String TOLERANCE = "tolerance";
189
190
191 private static final String INTERNAL = "internal";
192
193
194 private static final String LEAF = "leaf";
195
196
197 private static final String PLUS = "plus";
198
199
200 private static final String MINUS = "minus";
201
202
203 private static final String TRUE = "true";
204
205
206 private static final String FALSE = "false";
207
208
209 private BSPTree<S, P, H, I> root;
210
211
212 private final double tolerance;
213
214
215 private final StringTokenizer tokenizer;
216
217
218
219
220
221
222
223 public TreeBuilder(final String type, final String s)
224 throws IOException, ParseException {
225 root = null;
226 tokenizer = new StringTokenizer(s);
227 getWord(type);
228 getWord(TOLERANCE);
229 tolerance = getNumber();
230 getWord(PLUS);
231 root = new BSPTree<>();
232 parseTree(root);
233 if (tokenizer.hasMoreTokens()) {
234 throw new ParseException("unexpected " + tokenizer.nextToken(), 0);
235 }
236 }
237
238
239
240
241
242
243 private void parseTree(final BSPTree<S, P, H, I> node)
244 throws IOException, ParseException {
245 if (INTERNAL.equals(getWord(INTERNAL, LEAF))) {
246
247
248 node.insertCut(parseHyperplane());
249 getWord(MINUS);
250 parseTree(node.getMinus());
251 getWord(PLUS);
252 parseTree(node.getPlus());
253 } else {
254
255 node.setAttribute(getBoolean());
256 }
257 }
258
259
260
261
262
263
264 protected String getWord(final String ... allowed) throws ParseException {
265 final String token = tokenizer.nextToken();
266 for (final String a : allowed) {
267 if (a.equals(token)) {
268 return token;
269 }
270 }
271 throw new ParseException(token + " != " + allowed[0], 0);
272 }
273
274
275
276
277
278 protected double getNumber() throws NumberFormatException {
279 return Double.parseDouble(tokenizer.nextToken());
280 }
281
282
283
284
285
286 protected boolean getBoolean() throws ParseException {
287 return getWord(TRUE, FALSE).equals(TRUE);
288 }
289
290
291
292
293 public BSPTree<S, P, H, I> getTree() {
294 return root;
295 }
296
297
298
299
300 public double getTolerance() {
301 return tolerance;
302 }
303
304
305
306
307
308
309 protected abstract H parseHyperplane()
310 throws IOException, ParseException;
311
312 }
313
314 }