1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.geometry.euclidean.twod;
18
19 import java.util.List;
20
21 import org.apache.commons.geometry.core.GeometryTestUtils;
22 import org.apache.commons.geometry.core.partitioning.HyperplaneLocation;
23 import org.apache.commons.geometry.core.partitioning.Split;
24 import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
25 import org.apache.commons.geometry.euclidean.oned.Interval;
26 import org.apache.commons.numbers.angle.Angle;
27 import org.apache.commons.numbers.core.Precision;
28 import org.junit.jupiter.api.Assertions;
29 import org.junit.jupiter.api.Test;
30
31 class LineConvexSubsetTest {
32
33 private static final double TEST_EPS = 1e-10;
34
35 private static final Precision.DoubleEquivalence TEST_PRECISION =
36 Precision.doubleEquivalenceOfEpsilon(TEST_EPS);
37
38 @Test
39 void testFromInterval_intervalArg_finite() {
40
41 final Precision.DoubleEquivalence intervalPrecision = Precision.doubleEquivalenceOfEpsilon(1e-2);
42 final Interval interval = Interval.of(-1, 2, intervalPrecision);
43
44 final Line line = Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION);
45
46
47 final Segment segment = (Segment) Lines.subsetFromInterval(line, interval);
48
49
50 final double side = 1.0 / Math.sqrt(2);
51 checkFinite(segment, Vector2D.of(-side, -side), Vector2D.of(2 * side, 2 * side));
52
53 Assertions.assertSame(TEST_PRECISION, segment.getPrecision());
54 }
55
56 @Test
57 void testFromInterval_intervalArg_full() {
58
59 final Line line = Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION);
60
61
62 final LineConvexSubset span = Lines.subsetFromInterval(line, Interval.full());
63
64
65 GeometryTestUtils.assertNegativeInfinity(span.getSubspaceStart());
66 GeometryTestUtils.assertPositiveInfinity(span.getSubspaceEnd());
67
68 Assertions.assertNull(span.getStartPoint());
69 Assertions.assertNull(span.getEndPoint());
70
71 Assertions.assertSame(Interval.full(), span.getInterval());
72 Assertions.assertSame(TEST_PRECISION, span.getPrecision());
73 }
74
75 @Test
76 void testFromInterval_intervalArg_positiveHalfSpace() {
77
78 final Precision.DoubleEquivalence intervalPrecision = Precision.doubleEquivalenceOfEpsilon(1e-2);
79 final Interval interval = Interval.min(-1, intervalPrecision);
80
81 final Line line = Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION);
82
83
84 final Ray ray = (Ray) Lines.subsetFromInterval(line, interval);
85
86
87 Assertions.assertEquals(-1.0, ray.getSubspaceStart(), TEST_EPS);
88 GeometryTestUtils.assertPositiveInfinity(ray.getSubspaceEnd());
89
90 final double side = 1.0 / Math.sqrt(2);
91
92 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-side, -side), ray.getStartPoint(), TEST_EPS);
93 Assertions.assertNull(ray.getEndPoint());
94
95 checkInterval(interval, ray.getInterval());
96 Assertions.assertSame(TEST_PRECISION, ray.getPrecision());
97 }
98
99 @Test
100 void testFromInterval_intervalArg_negativeHalfSpace() {
101
102 final Precision.DoubleEquivalence intervalPrecision = Precision.doubleEquivalenceOfEpsilon(1e-2);
103 final Interval interval = Interval.max(2, intervalPrecision);
104
105 final Line line = Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION);
106
107
108 final ReverseRay halfLine = (ReverseRay) Lines.subsetFromInterval(line, interval);
109
110
111 GeometryTestUtils.assertNegativeInfinity(halfLine.getSubspaceStart());
112 Assertions.assertEquals(2, halfLine.getSubspaceEnd(), TEST_EPS);
113
114 final double side = 1.0 / Math.sqrt(2);
115
116 Assertions.assertNull(halfLine.getStartPoint());
117 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(2 * side, 2 * side), halfLine.getEndPoint(), TEST_EPS);
118
119 checkInterval(interval, halfLine.getInterval());
120 Assertions.assertSame(TEST_PRECISION, halfLine.getPrecision());
121 }
122
123 @Test
124 void testFromInterval_doubleArgs_finite() {
125
126 final Line line = Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION);
127
128
129 final Segment segment = (Segment) Lines.subsetFromInterval(line, -1, 2);
130
131
132 final double side = 1.0 / Math.sqrt(2);
133 checkFinite(segment, Vector2D.of(-side, -side), Vector2D.of(2 * side, 2 * side));
134
135 Assertions.assertSame(TEST_PRECISION, segment.getPrecision());
136 }
137
138 @Test
139 void testFromInterval_doubleArgs_full() {
140
141 final Line line = Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION);
142
143
144 final LineConvexSubset span = Lines.subsetFromInterval(line, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
145
146
147 GeometryTestUtils.assertNegativeInfinity(span.getSubspaceStart());
148 GeometryTestUtils.assertPositiveInfinity(span.getSubspaceEnd());
149
150 Assertions.assertNull(span.getStartPoint());
151 Assertions.assertNull(span.getEndPoint());
152
153 Assertions.assertSame(TEST_PRECISION, span.getPrecision());
154 }
155
156 @Test
157 void testFromInterval_doubleArgs_positiveHalfSpace() {
158
159 final Line line = Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION);
160
161
162 final Ray ray = (Ray) Lines.subsetFromInterval(line, -1, Double.POSITIVE_INFINITY);
163
164
165 Assertions.assertEquals(-1.0, ray.getSubspaceStart(), TEST_EPS);
166 GeometryTestUtils.assertPositiveInfinity(ray.getSubspaceEnd());
167
168 final double side = 1.0 / Math.sqrt(2);
169
170 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-side, -side), ray.getStartPoint(), TEST_EPS);
171 Assertions.assertNull(ray.getEndPoint());
172
173 Assertions.assertSame(TEST_PRECISION, ray.getPrecision());
174 }
175
176 @Test
177 void testFromInterval_doubleArgs_negativeHalfSpace() {
178
179 final Line line = Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION);
180
181
182 final ReverseRay halfLine = (ReverseRay) Lines.subsetFromInterval(line, 2, Double.NEGATIVE_INFINITY);
183
184
185 GeometryTestUtils.assertNegativeInfinity(halfLine.getSubspaceStart());
186 Assertions.assertEquals(2, halfLine.getSubspaceEnd(), TEST_EPS);
187
188 final double side = 1.0 / Math.sqrt(2);
189
190 Assertions.assertNull(halfLine.getStartPoint());
191 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(2 * side, 2 * side), halfLine.getEndPoint(), TEST_EPS);
192
193 Assertions.assertSame(TEST_PRECISION, halfLine.getPrecision());
194 }
195
196 @Test
197 void testFromInterval_doubleArgs_invalid() {
198
199 final Line line = Lines.fromPointAndAngle(Vector2D.ZERO, 0, TEST_PRECISION);
200
201
202 GeometryTestUtils.assertThrowsWithMessage(() -> {
203 Lines.subsetFromInterval(line, 0, Double.NaN);
204 }, IllegalArgumentException.class, "Invalid line subset interval: 0.0, NaN");
205
206 GeometryTestUtils.assertThrowsWithMessage(() -> {
207 Lines.subsetFromInterval(line, Double.NaN, 0.0);
208 }, IllegalArgumentException.class, "Invalid line subset interval: NaN, 0.0");
209
210 GeometryTestUtils.assertThrowsWithMessage(() -> {
211 Lines.subsetFromInterval(line, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
212 }, IllegalArgumentException.class, "Invalid line subset interval: Infinity, Infinity");
213
214 GeometryTestUtils.assertThrowsWithMessage(() -> {
215 Lines.subsetFromInterval(line, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
216 }, IllegalArgumentException.class, "Invalid line subset interval: -Infinity, -Infinity");
217
218 GeometryTestUtils.assertThrowsWithMessage(() -> {
219 Lines.subsetFromInterval(line, Double.POSITIVE_INFINITY, Double.NaN);
220 }, IllegalArgumentException.class, "Invalid line subset interval: Infinity, NaN");
221
222 GeometryTestUtils.assertThrowsWithMessage(() -> {
223 Lines.subsetFromInterval(line, Double.NaN, Double.NEGATIVE_INFINITY);
224 }, IllegalArgumentException.class, "Invalid line subset interval: NaN, -Infinity");
225 }
226
227 @Test
228 void testToConvex() {
229
230 final Line line = Lines.fromPoints(Vector2D.of(-1, 0), Vector2D.of(4, 5), TEST_PRECISION);
231 final LineConvexSubset sub = Lines.subsetFromInterval(line, 1, 2);
232
233
234 final List<LineConvexSubset> segments = sub.toConvex();
235
236
237 Assertions.assertEquals(1, segments.size());
238 Assertions.assertSame(sub, segments.get(0));
239 }
240
241 @Test
242 void testIntersection_line() {
243
244 final Segment aSeg = Lines.segmentFromPoints(Vector2D.of(1, 0), Vector2D.of(2, 0), TEST_PRECISION);
245 final Segment bSeg = Lines.segmentFromPoints(Vector2D.of(-1, -1), Vector2D.of(1, 1), TEST_PRECISION);
246
247 final Line xAxis = Lines.fromPointAndAngle(Vector2D.ZERO, 0.0, TEST_PRECISION);
248 final Line yAxis = Lines.fromPointAndAngle(Vector2D.ZERO, Angle.PI_OVER_TWO, TEST_PRECISION);
249 final Line angledLine = Lines.fromPoints(Vector2D.of(1, 1), Vector2D.of(2, 0), TEST_PRECISION);
250
251
252 Assertions.assertNull(aSeg.intersection(xAxis));
253 Assertions.assertNull(aSeg.intersection(yAxis));
254
255 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.ZERO, bSeg.intersection(xAxis), TEST_EPS);
256 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.ZERO, bSeg.intersection(yAxis), TEST_EPS);
257
258 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 1), bSeg.intersection(angledLine), TEST_EPS);
259 }
260
261 @Test
262 void testIntersection_lineSegment() {
263
264 final Segment a = Lines.segmentFromPoints(Vector2D.of(1, 0), Vector2D.of(2, 0), TEST_PRECISION);
265 final Segment b = Lines.segmentFromPoints(Vector2D.of(-1, -1), Vector2D.of(1, 1), TEST_PRECISION);
266 final Segment c = Lines.segmentFromPoints(Vector2D.of(-1, 0), Vector2D.ZERO, TEST_PRECISION);
267 final Segment d = Lines.segmentFromPoints(Vector2D.of(0, 3), Vector2D.of(3, 0), TEST_PRECISION);
268
269
270 Assertions.assertNull(a.intersection(a));
271 Assertions.assertNull(a.intersection(c));
272 Assertions.assertNull(a.intersection(b));
273
274 EuclideanTestUtils.assertCoordinatesEqual(Vector2D.ZERO, b.intersection(c), TEST_EPS);
275
276 Assertions.assertNull(b.intersection(d));
277 Assertions.assertNull(d.intersection(b));
278 }
279
280 @Test
281 void testSplit_finite() {
282
283 final Vector2D start = Vector2D.of(1, 1);
284 final Vector2D end = Vector2D.of(3, 2);
285 final Vector2D middle = start.lerp(end, 0.5);
286
287 final Segment sub = Lines.segmentFromPoints(start, end, TEST_PRECISION);
288
289
290 final Split<LineConvexSubset> both = sub.split(Lines.fromPointAndDirection(middle, Vector2D.of(1, -2), TEST_PRECISION));
291 checkFinite(both.getMinus(), middle, end);
292 checkFinite(both.getPlus(), start, middle);
293
294 final Split<LineConvexSubset> bothReversed = sub.split(Lines.fromPointAndDirection(middle, Vector2D.of(-1, 2), TEST_PRECISION));
295 checkFinite(bothReversed.getMinus(), start, middle);
296 checkFinite(bothReversed.getPlus(), middle, end);
297
298 final Split<LineConvexSubset> minusOnlyOrthogonal = sub.split(Lines.fromPointAndDirection(start, Vector2D.of(1, -2), TEST_PRECISION));
299 Assertions.assertSame(sub, minusOnlyOrthogonal.getMinus());
300 Assertions.assertNull(minusOnlyOrthogonal.getPlus());
301
302 final Split<LineConvexSubset> minusOnlyParallel = sub.split(Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(2, 1), TEST_PRECISION));
303 Assertions.assertSame(sub, minusOnlyParallel.getMinus());
304 Assertions.assertNull(minusOnlyParallel.getPlus());
305
306 final Split<LineConvexSubset> plusOnlyOrthogonal = sub.split(Lines.fromPointAndDirection(end, Vector2D.of(1, -2), TEST_PRECISION));
307 Assertions.assertNull(plusOnlyOrthogonal.getMinus());
308 Assertions.assertSame(sub, plusOnlyOrthogonal.getPlus());
309
310 final Split<LineConvexSubset> plusOnlyParallel = sub.split(Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(-2, -1), TEST_PRECISION));
311 Assertions.assertNull(plusOnlyParallel.getMinus());
312 Assertions.assertSame(sub, plusOnlyParallel.getPlus());
313
314 final Split<LineConvexSubset> hyper = sub.split(Lines.fromPointAndDirection(start, Vector2D.of(2, 1), TEST_PRECISION));
315 Assertions.assertNull(hyper.getMinus());
316 Assertions.assertNull(hyper.getPlus());
317 }
318
319 @Test
320 void testSplit_full() {
321
322 final Vector2D p1 = Vector2D.of(1, 1);
323 final Vector2D p2 = Vector2D.of(3, 2);
324 final Vector2D middle = p1.lerp(p2, 0.5);
325
326 final Line line = Lines.fromPoints(p1, p2, TEST_PRECISION);
327
328 final LineConvexSubset seg = Lines.subsetFromInterval(line, Interval.full());
329
330
331 final Split<LineConvexSubset> both = seg.split(Lines.fromPointAndDirection(middle, Vector2D.of(1, -2), TEST_PRECISION));
332 checkInfinite(both.getMinus(), line, middle, null);
333 checkInfinite(both.getPlus(), line, null, middle);
334
335 final Split<LineConvexSubset> bothReversed = seg.split(Lines.fromPointAndDirection(middle, Vector2D.of(-1, 2), TEST_PRECISION));
336 checkInfinite(bothReversed.getMinus(), line, null, middle);
337 checkInfinite(bothReversed.getPlus(), line, middle, null);
338
339 final Split<LineConvexSubset> minusOnlyParallel = seg.split(Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(2, 1), TEST_PRECISION));
340 Assertions.assertSame(seg, minusOnlyParallel.getMinus());
341 Assertions.assertNull(minusOnlyParallel.getPlus());
342
343 final Split<LineConvexSubset> plusOnlyParallel = seg.split(Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(-2, -1), TEST_PRECISION));
344 Assertions.assertNull(plusOnlyParallel.getMinus());
345 Assertions.assertSame(seg, plusOnlyParallel.getPlus());
346
347 final Split<LineConvexSubset> hyper = seg.split(Lines.fromPointAndDirection(p1, Vector2D.of(2, 1), TEST_PRECISION));
348 Assertions.assertNull(hyper.getMinus());
349 Assertions.assertNull(hyper.getPlus());
350 }
351
352 @Test
353 void testSplit_positiveHalfSpace() {
354
355 final Vector2D p1 = Vector2D.of(1, 1);
356 final Vector2D p2 = Vector2D.of(3, 2);
357 final Vector2D middle = p1.lerp(p2, 0.5);
358
359 final Line line = Lines.fromPoints(p1, p2, TEST_PRECISION);
360
361 final LineConvexSubset sub = Lines.subsetFromInterval(line, Interval.min(line.toSubspace(p1).getX(), TEST_PRECISION));
362
363
364 final Split<LineConvexSubset> both = sub.split(Lines.fromPointAndDirection(middle, Vector2D.of(1, -2), TEST_PRECISION));
365 checkInfinite(both.getMinus(), line, middle, null);
366 checkFinite(both.getPlus(), p1, middle);
367
368 final Split<LineConvexSubset> bothReversed = sub.split(Lines.fromPointAndDirection(middle, Vector2D.of(-1, 2), TEST_PRECISION));
369 checkFinite(bothReversed.getMinus(), p1, middle);
370 checkInfinite(bothReversed.getPlus(), line, middle, null);
371
372 final Split<LineConvexSubset> minusOnlyParallel = sub.split(Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(2, 1), TEST_PRECISION));
373 Assertions.assertSame(sub, minusOnlyParallel.getMinus());
374 Assertions.assertNull(minusOnlyParallel.getPlus());
375
376 final Split<LineConvexSubset> minusOnlyOrthogonal = sub.split(Lines.fromPointAndDirection(p1, Vector2D.of(1, -2), TEST_PRECISION));
377 Assertions.assertSame(sub, minusOnlyOrthogonal.getMinus());
378 Assertions.assertNull(minusOnlyOrthogonal.getPlus());
379
380 final Split<LineConvexSubset> plusOnlyParallel = sub.split(Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(-2, -1), TEST_PRECISION));
381 Assertions.assertNull(plusOnlyParallel.getMinus());
382 Assertions.assertSame(sub, plusOnlyParallel.getPlus());
383
384 final Split<LineConvexSubset> hyper = sub.split(Lines.fromPointAndDirection(p1, Vector2D.of(2, 1), TEST_PRECISION));
385 Assertions.assertNull(hyper.getMinus());
386 Assertions.assertNull(hyper.getPlus());
387 }
388
389 @Test
390 void testSplit_negativeHalfSpace() {
391
392 final Vector2D p1 = Vector2D.of(1, 1);
393 final Vector2D p2 = Vector2D.of(3, 2);
394 final Vector2D middle = p1.lerp(p2, 0.5);
395
396 final Line line = Lines.fromPoints(p1, p2, TEST_PRECISION);
397
398 final LineConvexSubset seg = Lines.subsetFromInterval(line, Interval.max(line.toSubspace(p2).getX(), TEST_PRECISION));
399
400
401 final Split<LineConvexSubset> both = seg.split(Lines.fromPointAndDirection(middle, Vector2D.of(1, -2), TEST_PRECISION));
402 checkFinite(both.getMinus(), middle, p2);
403 checkInfinite(both.getPlus(), line, null, middle);
404
405 final Split<LineConvexSubset> bothReversed = seg.split(Lines.fromPointAndDirection(middle, Vector2D.of(-1, 2), TEST_PRECISION));
406 checkInfinite(bothReversed.getMinus(), line, null, middle);
407 checkFinite(bothReversed.getPlus(), middle, p2);
408
409 final Split<LineConvexSubset> minusOnlyParallel = seg.split(Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(2, 1), TEST_PRECISION));
410 Assertions.assertSame(seg, minusOnlyParallel.getMinus());
411 Assertions.assertNull(minusOnlyParallel.getPlus());
412
413 final Split<LineConvexSubset> plusOnlyParallel = seg.split(Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(-2, -1), TEST_PRECISION));
414 Assertions.assertNull(plusOnlyParallel.getMinus());
415 Assertions.assertSame(seg, plusOnlyParallel.getPlus());
416
417 final Split<LineConvexSubset> plusOnlyOrthogonal = seg.split(Lines.fromPointAndDirection(p2, Vector2D.of(1, -2), TEST_PRECISION));
418 Assertions.assertNull(plusOnlyOrthogonal.getMinus());
419 Assertions.assertSame(seg, plusOnlyOrthogonal.getPlus());
420
421 final Split<LineConvexSubset> hyper = seg.split(Lines.fromPointAndDirection(p1, Vector2D.of(2, 1), TEST_PRECISION));
422 Assertions.assertNull(hyper.getMinus());
423 Assertions.assertNull(hyper.getPlus());
424 }
425
426 private static void checkInterval(final Interval expected, final Interval actual) {
427 Assertions.assertEquals(expected.getMin(), actual.getMin(), TEST_EPS);
428 Assertions.assertEquals(expected.getMax(), actual.getMax(), TEST_EPS);
429 }
430
431 private static void checkFinite(final LineConvexSubset segment, final Vector2D start, final Vector2D end) {
432 checkFinite(segment, start, end, TEST_PRECISION);
433 }
434
435 private static void checkFinite(final LineConvexSubset segment, final Vector2D start, final Vector2D end, final Precision.DoubleEquivalence precision) {
436 Assertions.assertFalse(segment.isInfinite());
437
438 EuclideanTestUtils.assertCoordinatesEqual(start, segment.getStartPoint(), TEST_EPS);
439 EuclideanTestUtils.assertCoordinatesEqual(end, segment.getEndPoint(), TEST_EPS);
440
441 final Line line = segment.getLine();
442 Assertions.assertEquals(HyperplaneLocation.ON, line.classify(segment.getStartPoint()));
443 Assertions.assertEquals(HyperplaneLocation.ON, line.classify(segment.getEndPoint()));
444
445 Assertions.assertEquals(line.toSubspace(segment.getStartPoint()).getX(), segment.getSubspaceStart(), TEST_EPS);
446 Assertions.assertEquals(line.toSubspace(segment.getEndPoint()).getX(), segment.getSubspaceEnd(), TEST_EPS);
447
448 Assertions.assertSame(precision, segment.getPrecision());
449 Assertions.assertSame(precision, line.getPrecision());
450 }
451
452 private static void checkInfinite(final LineConvexSubset segment, final Line line, final Vector2D start, final Vector2D end) {
453 checkInfinite(segment, line, start, end, TEST_PRECISION);
454 }
455
456 private static void checkInfinite(final LineConvexSubset segment, final Line line, final Vector2D start, final Vector2D end,
457 final Precision.DoubleEquivalence precision) {
458
459 Assertions.assertTrue(segment.isInfinite());
460
461 Assertions.assertEquals(line, segment.getLine());
462
463 if (start == null) {
464 Assertions.assertNull(segment.getStartPoint());
465 } else {
466 EuclideanTestUtils.assertCoordinatesEqual(start, segment.getStartPoint(), TEST_EPS);
467 Assertions.assertEquals(line.toSubspace(segment.getStartPoint()).getX(), segment.getSubspaceStart(), TEST_EPS);
468 }
469
470 if (end == null) {
471 Assertions.assertNull(segment.getEndPoint());
472 } else {
473 EuclideanTestUtils.assertCoordinatesEqual(end, segment.getEndPoint(), TEST_EPS);
474 Assertions.assertEquals(line.toSubspace(segment.getEndPoint()).getX(), segment.getSubspaceEnd(), TEST_EPS);
475 }
476
477 Assertions.assertSame(precision, segment.getPrecision());
478 Assertions.assertSame(precision, line.getPrecision());
479 }
480 }