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    *      http://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  package org.apache.commons.geometry.euclidean.twod;
18  
19  import org.apache.commons.geometry.core.GeometryTestUtils;
20  import org.apache.commons.geometry.core.RegionLocation;
21  import org.apache.commons.geometry.core.partitioning.Split;
22  import org.apache.commons.geometry.core.partitioning.SplitLocation;
23  import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
24  import org.apache.commons.geometry.euclidean.oned.Interval;
25  import org.apache.commons.numbers.core.Precision;
26  import org.junit.jupiter.api.Assertions;
27  import org.junit.jupiter.api.Test;
28  
29  class SegmentTest {
30  
31      private static final double TEST_EPS = 1e-10;
32  
33      private static final Precision.DoubleEquivalence TEST_PRECISION =
34              Precision.doubleEquivalenceOfEpsilon(TEST_EPS);
35  
36      @Test
37      void testFromPoints() {
38          // arrange
39          final Vector2D p1 = Vector2D.of(1, 2);
40          final Vector2D p2 = Vector2D.of(3, 2);
41  
42          // act
43          final Segment seg = Lines.segmentFromPoints(p1, p2, TEST_PRECISION);
44  
45          // assert
46          Assertions.assertFalse(seg.isFull());
47          Assertions.assertFalse(seg.isEmpty());
48          Assertions.assertFalse(seg.isInfinite());
49          Assertions.assertTrue(seg.isFinite());
50  
51          EuclideanTestUtils.assertCoordinatesEqual(p1, seg.getStartPoint(), TEST_EPS);
52          EuclideanTestUtils.assertCoordinatesEqual(p2, seg.getEndPoint(), TEST_EPS);
53          EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(2, 2), seg.getCentroid(), TEST_EPS);
54  
55          Assertions.assertEquals(1, seg.getSubspaceStart(), TEST_EPS);
56          Assertions.assertEquals(3, seg.getSubspaceEnd(), TEST_EPS);
57  
58          Assertions.assertEquals(2, seg.getSize(), TEST_EPS);
59      }
60  
61      @Test
62      void testFromPoints_invalidArgs() {
63          // arrange
64          final Vector2D p1 = Vector2D.of(0, 2);
65          final Vector2D p2 = Vector2D.of(1e-17, 2);
66  
67          // act/assert
68          GeometryTestUtils.assertThrowsWithMessage(() -> {
69              Lines.segmentFromPoints(p1, p1, TEST_PRECISION);
70          }, IllegalArgumentException.class, "Line direction cannot be zero");
71  
72          GeometryTestUtils.assertThrowsWithMessage(() -> {
73              Lines.segmentFromPoints(p1, p2, TEST_PRECISION);
74          }, IllegalArgumentException.class, "Line direction cannot be zero");
75      }
76  
77      @Test
78      void testFromPoints_givenLine() {
79          // arrange
80          final Vector2D p1 = Vector2D.of(-1, 2);
81          final Vector2D p2 = Vector2D.of(3, 3);
82  
83          final Line line = Lines.fromPointAndDirection(Vector2D.of(1, 0), Vector2D.Unit.PLUS_Y, TEST_PRECISION);
84  
85          // act
86          final Segment seg = Lines.segmentFromPoints(line, p2, p1); // reverse location order
87  
88          // assert
89          Assertions.assertFalse(seg.isFull());
90          Assertions.assertFalse(seg.isEmpty());
91          Assertions.assertFalse(seg.isInfinite());
92          Assertions.assertTrue(seg.isFinite());
93  
94          EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 2), seg.getStartPoint(), TEST_EPS);
95          EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 3), seg.getEndPoint(), TEST_EPS);
96          EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 2.5), seg.getCentroid(), TEST_EPS);
97  
98          Assertions.assertEquals(2, seg.getSubspaceStart(), TEST_EPS);
99          Assertions.assertEquals(3, seg.getSubspaceEnd(), TEST_EPS);
100 
101         Assertions.assertEquals(1, seg.getSize(), TEST_EPS);
102     }
103 
104     @Test
105     void testFromPoints_givenLine_singlePoint() {
106         // arrange
107         final Vector2D p1 = Vector2D.of(-1, 2);
108 
109         final Line line = Lines.fromPointAndDirection(Vector2D.of(1, 0), Vector2D.Unit.PLUS_Y, TEST_PRECISION);
110 
111         // act
112         final Segment seg = Lines.segmentFromPoints(line, p1, p1);
113 
114         // assert
115         Assertions.assertFalse(seg.isFull());
116         Assertions.assertFalse(seg.isEmpty());
117         Assertions.assertFalse(seg.isInfinite());
118         Assertions.assertTrue(seg.isFinite());
119 
120         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 2), seg.getStartPoint(), TEST_EPS);
121         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 2), seg.getEndPoint(), TEST_EPS);
122         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 2), seg.getCentroid(), TEST_EPS);
123 
124         Assertions.assertEquals(2, seg.getSubspaceStart(), TEST_EPS);
125         Assertions.assertEquals(2, seg.getSubspaceEnd(), TEST_EPS);
126 
127         Assertions.assertEquals(0, seg.getSize(), TEST_EPS);
128     }
129 
130     @Test
131     void testFromPoints_givenLine_invalidArgs() {
132         // arrange
133         final Vector2D p0 = Vector2D.of(1, 0);
134         final Vector2D p1 = Vector2D.of(2, 0);
135 
136         final Line line = Lines.fromPointAndAngle(Vector2D.ZERO, 0, TEST_PRECISION);
137 
138         // act/assert
139         GeometryTestUtils.assertThrowsWithMessage(() -> {
140             Lines.segmentFromPoints(line, Vector2D.NaN, p1);
141         }, IllegalArgumentException.class, "Invalid line segment locations: NaN, 2.0");
142 
143         GeometryTestUtils.assertThrowsWithMessage(() -> {
144             Lines.segmentFromPoints(line, p0, Vector2D.NaN);
145         }, IllegalArgumentException.class, "Invalid line segment locations: 1.0, NaN");
146 
147         GeometryTestUtils.assertThrowsWithMessage(() -> {
148             Lines.segmentFromPoints(line, Vector2D.NEGATIVE_INFINITY, p1);
149         }, IllegalArgumentException.class, "Invalid line segment locations: NaN, 2.0");
150 
151         GeometryTestUtils.assertThrowsWithMessage(() -> {
152             Lines.segmentFromPoints(line, p0, Vector2D.POSITIVE_INFINITY);
153         }, IllegalArgumentException.class, "Invalid line segment locations: 1.0, NaN");
154     }
155 
156     @Test
157     void testFromLocations() {
158         // arrange
159         final Line line = Lines.fromPointAndDirection(Vector2D.of(-1, 0), Vector2D.Unit.PLUS_Y, TEST_PRECISION);
160 
161         // act
162         final Segment seg = Lines.segmentFromLocations(line, -1, 2);
163 
164         // assert
165         Assertions.assertFalse(seg.isFull());
166         Assertions.assertFalse(seg.isEmpty());
167         Assertions.assertFalse(seg.isInfinite());
168         Assertions.assertTrue(seg.isFinite());
169 
170         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-1, -1), seg.getStartPoint(), TEST_EPS);
171         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-1, 2), seg.getEndPoint(), TEST_EPS);
172         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-1, 0.5), seg.getCentroid(), TEST_EPS);
173 
174         Assertions.assertEquals(-1, seg.getSubspaceStart(), TEST_EPS);
175         Assertions.assertEquals(2, seg.getSubspaceEnd(), TEST_EPS);
176 
177         Assertions.assertEquals(3, seg.getSize(), TEST_EPS);
178     }
179 
180     @Test
181     void testFromLocations_reversedLocationOrder() {
182         // arrange
183         final Line line = Lines.fromPointAndDirection(Vector2D.of(-1, 0), Vector2D.Unit.PLUS_Y, TEST_PRECISION);
184 
185         // act
186         final Segment seg = Lines.segmentFromLocations(line, 2, -1);
187 
188         // assert
189         Assertions.assertFalse(seg.isFull());
190         Assertions.assertFalse(seg.isEmpty());
191         Assertions.assertFalse(seg.isInfinite());
192         Assertions.assertTrue(seg.isFinite());
193 
194         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-1, -1), seg.getStartPoint(), TEST_EPS);
195         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-1, 2), seg.getEndPoint(), TEST_EPS);
196         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-1, 0.5), seg.getCentroid(), TEST_EPS);
197 
198         Assertions.assertEquals(-1, seg.getSubspaceStart(), TEST_EPS);
199         Assertions.assertEquals(2, seg.getSubspaceEnd(), TEST_EPS);
200 
201         Assertions.assertEquals(3, seg.getSize(), TEST_EPS);
202     }
203 
204     @Test
205     void testFromLocations_singlePoint() {
206         // arrange
207         final Line line = Lines.fromPointAndDirection(Vector2D.of(-1, 0), Vector2D.Unit.PLUS_Y, TEST_PRECISION);
208 
209         // act
210         final Segment seg = Lines.segmentFromLocations(line, 1, 1);
211 
212         // assert
213         Assertions.assertFalse(seg.isFull());
214         Assertions.assertFalse(seg.isEmpty());
215         Assertions.assertFalse(seg.isInfinite());
216         Assertions.assertTrue(seg.isFinite());
217 
218         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-1, 1), seg.getStartPoint(), TEST_EPS);
219         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-1, 1), seg.getEndPoint(), TEST_EPS);
220         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-1, 1), seg.getCentroid(), TEST_EPS);
221 
222         Assertions.assertEquals(1, seg.getSubspaceStart(), TEST_EPS);
223         Assertions.assertEquals(1, seg.getSubspaceEnd(), TEST_EPS);
224 
225         Assertions.assertEquals(0, seg.getSize(), TEST_EPS);
226     }
227 
228     @Test
229     void testFromLocations_invalidArgs() {
230         // arrange
231         final Line line = Lines.fromPointAndAngle(Vector2D.ZERO, 0, TEST_PRECISION);
232 
233         // act/assert
234         GeometryTestUtils.assertThrowsWithMessage(() -> {
235             Lines.segmentFromLocations(line, Double.NaN, 2);
236         }, IllegalArgumentException.class, "Invalid line segment locations: NaN, 2.0");
237 
238         GeometryTestUtils.assertThrowsWithMessage(() -> {
239             Lines.segmentFromLocations(line, 1, Double.NaN);
240         }, IllegalArgumentException.class, "Invalid line segment locations: 1.0, NaN");
241 
242         GeometryTestUtils.assertThrowsWithMessage(() -> {
243             Lines.segmentFromLocations(line, Double.NEGATIVE_INFINITY, 2);
244         }, IllegalArgumentException.class, "Invalid line segment locations: -Infinity, 2.0");
245 
246         GeometryTestUtils.assertThrowsWithMessage(() -> {
247             Lines.segmentFromLocations(line, 1, Double.POSITIVE_INFINITY);
248         }, IllegalArgumentException.class, "Invalid line segment locations: 1.0, Infinity");
249     }
250 
251     @Test
252     void testGetBounds() {
253         // arrange
254         final Segment seg = Lines.segmentFromPoints(Vector2D.of(-1, 4), Vector2D.of(2, -2), TEST_PRECISION);
255 
256         // act
257         final Bounds2D bounds = seg.getBounds();
258 
259         // assert
260         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(-1, -2), bounds.getMin(), TEST_EPS);
261         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(2, 4), bounds.getMax(), TEST_EPS);
262     }
263 
264     @Test
265     void testTransform() {
266         // arrange
267         final AffineTransformMatrix2D t = AffineTransformMatrix2D.createRotation(0.5 * Math.PI)
268                 .translate(Vector2D.Unit.PLUS_X);
269 
270         final Segment seg = Lines.segmentFromPoints(Vector2D.ZERO, Vector2D.of(1, 0), TEST_PRECISION);
271 
272         // act
273         final Segment result = seg.transform(t);
274 
275         // assert
276         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 0), result.getStartPoint(), TEST_EPS);
277         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 1), result.getEndPoint(), TEST_EPS);
278     }
279 
280     @Test
281     void testTransform_reflection() {
282         // arrange
283         final AffineTransformMatrix2D t = AffineTransformMatrix2D.createRotation(0.5 * Math.PI)
284                 .translate(Vector2D.Unit.PLUS_X)
285                 .scale(1, -1);
286 
287         final Segment seg = Lines.segmentFromPoints(Vector2D.ZERO, Vector2D.of(1, 0), TEST_PRECISION);
288 
289         // act
290         final Segment result = seg.transform(t);
291 
292         // assert
293         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, 0), result.getStartPoint(), TEST_EPS);
294         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(1, -1), result.getEndPoint(), TEST_EPS);
295     }
296 
297     @Test
298     void testReverse() {
299         // arrange
300         final Vector2D start = Vector2D.of(1, 2);
301 
302         EuclideanTestUtils.permuteSkipZero(-4, 4, 1, (x, y) -> {
303             final Vector2D end = Vector2D.of(x, y).add(start);
304 
305             final Segment seg = Lines.segmentFromPoints(start, end, TEST_PRECISION);
306 
307             // act
308             final Segment rev = seg.reverse();
309 
310             // assert
311             Assertions.assertEquals(seg.getSize(), rev.getSize(), TEST_EPS);
312 
313             EuclideanTestUtils.assertCoordinatesEqual(seg.getLine().getOrigin(), rev.getLine().getOrigin(), TEST_EPS);
314             Assertions.assertEquals(-1, seg.getLine().getDirection().dot(rev.getLine().getDirection()), TEST_EPS);
315 
316             EuclideanTestUtils.assertCoordinatesEqual(seg.getEndPoint(), rev.getStartPoint(), TEST_EPS);
317             EuclideanTestUtils.assertCoordinatesEqual(seg.getStartPoint(), rev.getEndPoint(), TEST_EPS);
318         });
319     }
320 
321     @Test
322     void testClosest() {
323         // arrange
324         final Vector2D p1 = Vector2D.of(0, -1);
325         final Vector2D p2 = Vector2D.of(0, 1);
326         final Segment seg = Lines.segmentFromPoints(p1, p2, TEST_PRECISION);
327 
328         // act/assert
329         EuclideanTestUtils.assertCoordinatesEqual(p1, seg.closest(p1), TEST_EPS);
330         EuclideanTestUtils.assertCoordinatesEqual(p1, seg.closest(Vector2D.of(0, -2)), TEST_EPS);
331         EuclideanTestUtils.assertCoordinatesEqual(p1, seg.closest(Vector2D.of(2, -2)), TEST_EPS);
332         EuclideanTestUtils.assertCoordinatesEqual(p1, seg.closest(Vector2D.of(-1, -1)), TEST_EPS);
333 
334         EuclideanTestUtils.assertCoordinatesEqual(p2, seg.closest(p2), TEST_EPS);
335         EuclideanTestUtils.assertCoordinatesEqual(p2, seg.closest(Vector2D.of(0, 2)), TEST_EPS);
336         EuclideanTestUtils.assertCoordinatesEqual(p2, seg.closest(Vector2D.of(-2, 2)), TEST_EPS);
337         EuclideanTestUtils.assertCoordinatesEqual(p2, seg.closest(Vector2D.of(-1, 1)), TEST_EPS);
338 
339         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.ZERO, seg.closest(Vector2D.ZERO), TEST_EPS);
340         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, 0.5), seg.closest(Vector2D.of(1, 0.5)), TEST_EPS);
341         EuclideanTestUtils.assertCoordinatesEqual(Vector2D.of(0, -0.5), seg.closest(Vector2D.of(-2, -0.5)), TEST_EPS);
342     }
343 
344     @Test
345     void testClassify() {
346         // arrange
347         final Segment seg = Lines.segmentFromPoints(Vector2D.of(1, 1), Vector2D.of(3, 1), TEST_PRECISION);
348 
349         // act/assert
350         EuclideanTestUtils.assertRegionLocation(seg, RegionLocation.OUTSIDE,
351                 Vector2D.of(2, 2), Vector2D.of(2, 0),
352                 Vector2D.of(0, 1), Vector2D.of(4, 1));
353 
354         EuclideanTestUtils.assertRegionLocation(seg, RegionLocation.BOUNDARY,
355                 Vector2D.of(1, 1), Vector2D.of(3, 1),
356                 Vector2D.of(1 + 1e-16, 1), Vector2D.of(3, 1 - 1e-12));
357 
358         EuclideanTestUtils.assertRegionLocation(seg, RegionLocation.INSIDE, Vector2D.of(2, 1));
359     }
360 
361     @Test
362     void testSplit() {
363         // --- arrange
364         final Vector2D p0 = Vector2D.of(1, 1);
365         final Vector2D p1 = Vector2D.of(3, 1);
366         final Vector2D mid = p0.lerp(p1, 0.5);
367         final Vector2D low = Vector2D.of(0, 1);
368         final Vector2D high = Vector2D.of(3, 1);
369 
370         final Vector2D delta = Vector2D.of(1e-11, 1e-11);
371 
372         final Segment seg = Lines.segmentFromPoints(Vector2D.of(1, 1), Vector2D.of(3, 1), TEST_PRECISION);
373 
374         // --- act
375 
376         // parallel
377         checkSplit(seg.split(Lines.fromPointAndAngle(Vector2D.of(2, 2), 0, TEST_PRECISION)),
378                 null, null,
379                 p0, p1);
380         checkSplit(seg.split(Lines.fromPointAndAngle(Vector2D.of(2, 2), Math.PI, TEST_PRECISION)),
381                 p0, p1,
382                 null, null);
383 
384         // coincident
385         checkSplit(seg.split(Lines.fromPointAndAngle(p0.add(delta), 1e-20, TEST_PRECISION)),
386                 null, null,
387                 null, null);
388 
389         // through mid point
390         checkSplit(seg.split(Lines.fromPointAndAngle(mid, 1, TEST_PRECISION)),
391                 p0, mid,
392                 mid, p1);
393         checkSplit(seg.split(Lines.fromPointAndAngle(mid, -1, TEST_PRECISION)),
394                 mid, p1,
395                 p0, mid);
396 
397         // through start point
398         checkSplit(seg.split(Lines.fromPointAndAngle(p0.subtract(delta), 1, TEST_PRECISION)),
399                 null, null,
400                 p0, p1);
401         checkSplit(seg.split(Lines.fromPointAndAngle(p0.add(delta), -1, TEST_PRECISION)),
402                 p0, p1,
403                 null, null);
404 
405         // through end point
406         checkSplit(seg.split(Lines.fromPointAndAngle(p1.subtract(delta), 1, TEST_PRECISION)),
407                 p0, p1,
408                 null, null);
409         checkSplit(seg.split(Lines.fromPointAndAngle(p1.add(delta), -1, TEST_PRECISION)),
410                 null, null,
411                 p0, p1);
412 
413         // intersection below minus
414         checkSplit(seg.split(Lines.fromPointAndAngle(low, 1, TEST_PRECISION)),
415                 null, null,
416                 p0, p1);
417         checkSplit(seg.split(Lines.fromPointAndAngle(low, -1, TEST_PRECISION)),
418                 p0, p1,
419                 null, null);
420 
421         // intersection above minus
422         checkSplit(seg.split(Lines.fromPointAndAngle(high, 1, TEST_PRECISION)),
423                 p0, p1,
424                 null, null);
425         checkSplit(seg.split(Lines.fromPointAndAngle(high, -1, TEST_PRECISION)),
426                 null, null,
427                 p0, p1);
428     }
429 
430     @Test
431     void testSplit_pointsOnSplitterWithLineIntersection() {
432         // arrange
433         // Create a segment with both of its points lying on the splitter but with the intersection
434         // of the lines lying far enough away from the segment start point along the line to be
435         // considered a valid 1D distance for a split. In this case, no split should be performed since
436         // both points still lie on the splitter.
437         final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-5);
438 
439         final Segment seg = Lines.segmentFromPoints(Vector2D.of(1, 1e-8), Vector2D.of(1.01, 1e-6), precision);
440 
441         final Line splitter = Lines.fromPointAndAngle(Vector2D.ZERO, 0, precision);
442 
443         // act
444         final Split<LineConvexSubset> split = seg.split(splitter);
445 
446         // assert
447         Assertions.assertEquals(SplitLocation.NEITHER, split.getLocation());
448 
449         Assertions.assertNull(split.getMinus());
450         Assertions.assertNull(split.getPlus());
451     }
452 
453     @Test
454     void testGetInterval() {
455         // arrange
456         final Segment seg = Lines.segmentFromPoints(Vector2D.of(2, -1), Vector2D.of(2, 2), TEST_PRECISION);
457 
458         // act
459         final Interval interval = seg.getInterval();
460 
461         // assert
462         Assertions.assertEquals(-1, interval.getMin(), TEST_EPS);
463         Assertions.assertEquals(2, interval.getMax(), TEST_EPS);
464 
465         Assertions.assertSame(seg.getLine().getPrecision(), interval.getMinBoundary().getPrecision());
466     }
467 
468     @Test
469     void testGetInterval_singlePoint() {
470         // arrange
471         final Line line = Lines.fromPointAndAngle(Vector2D.ZERO, 0, TEST_PRECISION);
472         final Segment seg = Lines.segmentFromLocations(line, 1, 1);
473 
474         // act
475         final Interval interval = seg.getInterval();
476 
477         // assert
478         Assertions.assertEquals(1, interval.getMin(), TEST_EPS);
479         Assertions.assertEquals(1, interval.getMax(), TEST_EPS);
480         Assertions.assertEquals(0, interval.getSize(), TEST_EPS);
481 
482         Assertions.assertSame(seg.getLine().getPrecision(), interval.getMinBoundary().getPrecision());
483     }
484 
485     @Test
486     void testToString() {
487         // arrange
488         final Segment seg = Lines.segmentFromPoints(Vector2D.ZERO, Vector2D.of(1, 0), TEST_PRECISION);
489 
490         // act
491         final String str = seg.toString();
492 
493         // assert
494         GeometryTestUtils.assertContains("Segment[startPoint= (0", str);
495         GeometryTestUtils.assertContains(", endPoint= (1", str);
496     }
497 
498     private static void checkSplit(final Split<LineConvexSubset> split, final Vector2D minusStart, final Vector2D minusEnd,
499                                    final Vector2D plusStart, final Vector2D plusEnd) {
500 
501         final Segment minus = (Segment) split.getMinus();
502         if (minusStart != null) {
503             EuclideanTestUtils.assertCoordinatesEqual(minusStart, minus.getStartPoint(), TEST_EPS);
504             EuclideanTestUtils.assertCoordinatesEqual(minusEnd, minus.getEndPoint(), TEST_EPS);
505         } else {
506             Assertions.assertNull(minus);
507         }
508 
509         final Segment plus = (Segment) split.getPlus();
510         if (plusStart != null) {
511             EuclideanTestUtils.assertCoordinatesEqual(plusStart, plus.getStartPoint(), TEST_EPS);
512             EuclideanTestUtils.assertCoordinatesEqual(plusEnd, plus.getEndPoint(), TEST_EPS);
513         } else {
514             Assertions.assertNull(plus);
515         }
516     }
517 }