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.path;
18  
19  import java.util.ArrayList;
20  import java.util.Arrays;
21  import java.util.Collections;
22  import java.util.List;
23  import java.util.Random;
24  
25  import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
26  import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext;
27  import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
28  import org.apache.commons.geometry.euclidean.twod.Line;
29  import org.apache.commons.geometry.euclidean.twod.LineConvexSubset;
30  import org.apache.commons.geometry.euclidean.twod.Lines;
31  import org.apache.commons.geometry.euclidean.twod.Segment;
32  import org.apache.commons.geometry.euclidean.twod.Vector2D;
33  import org.apache.commons.geometry.euclidean.twod.path.AbstractLinePathConnector.ConnectableLineSubset;
34  import org.apache.commons.numbers.angle.PlaneAngleRadians;
35  import org.junit.Assert;
36  import org.junit.Test;
37  
38  public class AbstractLinePathConnectorTest {
39  
40      private static final double TEST_EPS = 1e-10;
41  
42      private static final DoublePrecisionContext TEST_PRECISION =
43              new EpsilonDoublePrecisionContext(TEST_EPS);
44  
45      private static final Line Y_AXIS = Lines.fromPointAndAngle(Vector2D.ZERO, PlaneAngleRadians.PI_OVER_TWO,
46              TEST_PRECISION);
47  
48      private final TestConnector connector = new TestConnector();
49  
50      @Test
51      public void testConnectAll_emptyCollection() {
52          // act
53          final List<LinePath> paths = connector.connectAll(Collections.emptyList());
54  
55          // assert
56          Assert.assertEquals(0, paths.size());
57      }
58  
59      @Test
60      public void testConnectAll_singleInfiniteLine() {
61          // arrange
62          final LineConvexSubset segment = Y_AXIS.span();
63  
64          // act
65          final List<LinePath> paths = connector.connectAll(Collections.singletonList(segment));
66  
67          // assert
68          Assert.assertEquals(1, paths.size());
69  
70          final LinePath path = paths.get(0);
71          Assert.assertEquals(1, path.getElements().size());
72          Assert.assertSame(segment, path.getStart());
73      }
74  
75      @Test
76      public void testConnectAll_singleHalfInfiniteLine_noEndPoint() {
77          // arrange
78          final LineConvexSubset segment = Y_AXIS.rayFrom(Vector2D.ZERO);
79  
80          // act
81          final List<LinePath> paths = connector.connectAll(Collections.singletonList(segment));
82  
83          // assert
84          Assert.assertEquals(1, paths.size());
85  
86          final LinePath path = paths.get(0);
87          Assert.assertEquals(1, path.getElements().size());
88          Assert.assertSame(segment, path.getStart());
89      }
90  
91      @Test
92      public void testConnectAll_singleHalfInfiniteLine_noStartPoint() {
93          // arrange
94          final LineConvexSubset segment = Y_AXIS.reverseRayTo(Vector2D.ZERO);
95  
96          // act
97          final List<LinePath> paths = connector.connectAll(Collections.singletonList(segment));
98  
99          // assert
100         Assert.assertEquals(1, paths.size());
101 
102         final LinePath path = paths.get(0);
103         Assert.assertEquals(1, path.getElements().size());
104         Assert.assertSame(segment, path.getStart());
105     }
106 
107     @Test
108     public void testConnectAll_disjointSegments() {
109         // arrange
110         final LineConvexSubset a = Y_AXIS.segment(Vector2D.of(0, 1), Vector2D.of(0, 2));
111         final LineConvexSubset b = Y_AXIS.segment(Vector2D.of(0, -1), Vector2D.ZERO);
112 
113         final List<LineConvexSubset> segments = Arrays.asList(a, b);
114 
115         // act
116         final List<LinePath> paths = connector.connectAll(segments);
117 
118         // assert
119         Assert.assertEquals(2, paths.size());
120 
121         assertFinitePath(paths.get(0), Vector2D.of(0, -1), Vector2D.ZERO);
122         assertFinitePath(paths.get(1), Vector2D.of(0, 1), Vector2D.of(0, 2));
123     }
124 
125     @Test
126     public void testConnectAll_singleClosedPath() {
127         // arrange
128         final LinePath input = LinePath.builder(TEST_PRECISION)
129                 .appendVertices(Vector2D.of(1, 1), Vector2D.ZERO, Vector2D.of(1, 0))
130                 .close();
131 
132         final List<LineConvexSubset> segments = new ArrayList<>(input.getElements());
133         shuffle(segments);
134 
135         // act
136         final List<LinePath> paths = connector.connectAll(segments);
137 
138         // assert
139         Assert.assertEquals(1, paths.size());
140 
141         assertFinitePath(paths.get(0),
142                 Vector2D.ZERO, Vector2D.of(1, 0), Vector2D.of(1, 1), Vector2D.ZERO);
143     }
144 
145     @Test
146     public void testConnectAll_multipleClosedPaths() {
147         // arrange
148         final LinePath a = LinePath.builder(TEST_PRECISION)
149                 .appendVertices(Vector2D.of(1, 1), Vector2D.ZERO, Vector2D.of(1, 0))
150                 .close();
151 
152         final LinePath b = LinePath.builder(TEST_PRECISION)
153                 .appendVertices(Vector2D.of(0, 1), Vector2D.of(-1, 0), Vector2D.of(-0.5, 0))
154                 .close();
155 
156         final LinePath c = LinePath.builder(TEST_PRECISION)
157                 .appendVertices(Vector2D.of(1, 3), Vector2D.of(0, 2), Vector2D.of(1, 2))
158                 .close();
159 
160         final List<LineConvexSubset> segments = new ArrayList<>();
161         segments.addAll(a.getElements());
162         segments.addAll(b.getElements());
163         segments.addAll(c.getElements());
164 
165         shuffle(segments);
166 
167         // act
168         final List<LinePath> paths = connector.connectAll(segments);
169 
170         // assert
171         Assert.assertEquals(3, paths.size());
172 
173         assertFinitePath(paths.get(0),
174                 Vector2D.of(-1, 0), Vector2D.of(-0.5, 0), Vector2D.of(0, 1), Vector2D.of(-1, 0));
175 
176         assertFinitePath(paths.get(1),
177                 Vector2D.ZERO, Vector2D.of(1, 0), Vector2D.of(1, 1), Vector2D.ZERO);
178 
179         assertFinitePath(paths.get(2),
180                 Vector2D.of(0, 2), Vector2D.of(1, 2), Vector2D.of(1, 3), Vector2D.of(0, 2));
181     }
182 
183     @Test
184     public void testConnectAll_singleOpenPath() {
185         // arrange
186         final LinePath input = LinePath.builder(TEST_PRECISION)
187                 .appendVertices(Vector2D.of(1, 1), Vector2D.ZERO, Vector2D.of(1, 0))
188                 .build();
189 
190         final List<LineConvexSubset> segments = new ArrayList<>(input.getElements());
191         shuffle(segments);
192 
193         // act
194         final List<LinePath> paths = connector.connectAll(segments);
195 
196         // assert
197         Assert.assertEquals(1, paths.size());
198 
199         assertFinitePath(paths.get(0),
200                 Vector2D.of(1, 1), Vector2D.ZERO, Vector2D.of(1, 0));
201     }
202 
203     @Test
204     public void testConnectAll_mixOfOpenConnectedAndInfinite() {
205         // arrange
206         final LineConvexSubset inputYInf = Y_AXIS.reverseRayTo(Vector2D.ZERO);
207         final LineConvexSubset inputXInf = Lines.fromPoints(Vector2D.ZERO, Vector2D.Unit.MINUS_X, TEST_PRECISION)
208                 .rayFrom(Vector2D.ZERO);
209 
210         final LinePath closedPath = LinePath.builder(TEST_PRECISION)
211                 .appendVertices(Vector2D.of(0, 2), Vector2D.of(1, 2), Vector2D.of(1, 3))
212                 .close();
213 
214         final LinePath openPath = LinePath.builder(TEST_PRECISION)
215                 .appendVertices(Vector2D.of(-1, 3), Vector2D.of(0, 1), Vector2D.of(1, 1))
216                 .build();
217 
218         final List<LineConvexSubset> segments = new ArrayList<>();
219         segments.add(inputYInf);
220         segments.add(inputXInf);
221         segments.addAll(closedPath.getElements());
222         segments.addAll(openPath.getElements());
223 
224         shuffle(segments);
225 
226         // act
227         final List<LinePath> paths = connector.connectAll(segments);
228 
229         // assert
230         Assert.assertEquals(3, paths.size());
231 
232         assertFinitePath(paths.get(0),
233                 Vector2D.of(-1, 3), Vector2D.of(0, 1), Vector2D.of(1, 1));
234 
235         final LinePath infPath = paths.get(1);
236         Assert.assertTrue(infPath.isInfinite());
237         Assert.assertEquals(2, infPath.getElements().size());
238         Assert.assertSame(inputYInf, infPath.getElements().get(0));
239         Assert.assertSame(inputXInf, infPath.getElements().get(1));
240 
241         assertFinitePath(paths.get(2),
242                 Vector2D.of(0, 2), Vector2D.of(1, 2), Vector2D.of(1, 3), Vector2D.of(0, 2));
243     }
244 
245     @Test
246     public void testConnectAll_pathWithSinglePoint() {
247         // arrange
248         final Vector2D p0 = Vector2D.ZERO;
249 
250         final List<LineConvexSubset> segments = Collections.singletonList(Lines.fromPointAndAngle(p0, 0, TEST_PRECISION).segment(p0, p0));
251 
252         // act
253         final List<LinePath> paths = connector.connectAll(segments);
254 
255         // assert
256         Assert.assertEquals(1, paths.size());
257 
258         assertFinitePath(paths.get(0), p0, p0);
259     }
260 
261     @Test
262     public void testConnectAll_pathWithPointLikeConnectedSegments() {
263         // arrange
264         final Vector2D p0 = Vector2D.ZERO;
265         final Vector2D p1 = Vector2D.of(1, 0);
266         final Vector2D p2 = Vector2D.of(1, 1);
267 
268         final Vector2D almostP0 = Vector2D.of(-1e-20, -1e-20);
269         final Vector2D almostP1 = Vector2D.of(1 - 1e-15, 0);
270 
271         final LinePath input = LinePath.builder(TEST_PRECISION)
272                 .appendVertices(p0, p1)
273                 .append(Lines.fromPointAndAngle(p1, 0.25 * PlaneAngleRadians.PI, TEST_PRECISION).segment(p1, p1))
274                 .append(Lines.fromPointAndAngle(p1, -0.25 * PlaneAngleRadians.PI, TEST_PRECISION).segment(almostP1, almostP1))
275                 .append(p2)
276                 .append(p0)
277                 .append(Lines.fromPointAndAngle(Vector2D.ZERO, -PlaneAngleRadians.PI_OVER_TWO, TEST_PRECISION)
278                         .segment(almostP0, almostP0))
279                 .build();
280 
281         final List<LineConvexSubset> segments = new ArrayList<>(input.getElements());
282         shuffle(segments);
283 
284         // act
285         final List<LinePath> paths = connector.connectAll(segments);
286 
287         // assert
288         Assert.assertEquals(1, paths.size());
289 
290         assertFinitePath(paths.get(0), p0, p1, almostP1, p1, p2, p0, almostP0);
291     }
292 
293     @Test
294     public void testConnectAll_flatLineRegion() {
295         // arrange
296         final Vector2D p0 = Vector2D.ZERO;
297         final Vector2D p1 = Vector2D.of(1, 0);
298 
299         final Segment seg0 = Lines.segmentFromPoints(p0, p1, TEST_PRECISION);
300         final Segment seg1 = Lines.segmentFromPoints(p1, p0, TEST_PRECISION);
301         final LineConvexSubset seg2 = Lines.fromPointAndAngle(p1, PlaneAngleRadians.PI_OVER_TWO, TEST_PRECISION).segment(p1, p1);
302         final LineConvexSubset seg3 = Lines.fromPointAndAngle(p0, -PlaneAngleRadians.PI_OVER_TWO, TEST_PRECISION).segment(p0, p0);
303 
304         final List<LineConvexSubset> segments = new ArrayList<>(Arrays.asList(seg0, seg1, seg2, seg3));
305         shuffle(segments);
306 
307         // act
308         final List<LinePath> paths = connector.connectAll(segments);
309 
310         // assert
311         Assert.assertEquals(1, paths.size());
312 
313         final LinePath path = paths.get(0);
314         Assert.assertSame(seg0, path.getElements().get(0));
315         Assert.assertSame(seg2, path.getElements().get(1));
316         Assert.assertSame(seg1, path.getElements().get(2));
317         Assert.assertSame(seg3, path.getElements().get(3));
318     }
319 
320     @Test
321     public void testConnectAll_singlePointRegion() {
322         // arrange
323         final Vector2D p0 = Vector2D.of(1, 0);
324 
325         final LineConvexSubset seg0 = Lines.fromPointAndAngle(p0, 0.0, TEST_PRECISION).segment(p0, p0);
326         final LineConvexSubset seg1 = Lines.fromPointAndAngle(p0, PlaneAngleRadians.PI_OVER_TWO, TEST_PRECISION).segment(p0, p0);
327         final LineConvexSubset seg2 = Lines.fromPointAndAngle(p0, PlaneAngleRadians.PI, TEST_PRECISION).segment(p0, p0);
328         final LineConvexSubset seg3 = Lines.fromPointAndAngle(p0, -PlaneAngleRadians.PI_OVER_TWO, TEST_PRECISION).segment(p0, p0);
329 
330         final List<LineConvexSubset> segments = new ArrayList<>(Arrays.asList(seg0, seg1, seg2, seg3));
331         shuffle(segments);
332 
333         // act
334         final List<LinePath> paths = connector.connectAll(segments);
335 
336         // assert
337         Assert.assertEquals(1, paths.size());
338 
339         final LinePath path = paths.get(0);
340         Assert.assertSame(seg2, path.getElements().get(0));
341         Assert.assertSame(seg3, path.getElements().get(1));
342         Assert.assertSame(seg0, path.getElements().get(2));
343         Assert.assertSame(seg1, path.getElements().get(3));
344     }
345 
346     @Test
347     public void testConnectAll_pathWithPointLikeUnconnectedSegments() {
348         // arrange
349         final Vector2D p0 = Vector2D.ZERO;
350         final Vector2D p1 = Vector2D.of(1, 0);
351 
352         final LineConvexSubset seg0 = Lines.fromPointAndAngle(p1, 0.0, TEST_PRECISION).segment(p1, p1);
353         final LineConvexSubset seg1 = Lines.fromPointAndAngle(p1, 0.25 * PlaneAngleRadians.PI, TEST_PRECISION).segment(p1, p1);
354         final LineConvexSubset seg2 = Lines.fromPointAndAngle(p0, 0, TEST_PRECISION).segment(p0, p0);
355 
356         final List<LineConvexSubset> segments = new ArrayList<>(Arrays.asList(seg0, seg1, seg2));
357 
358         shuffle(segments);
359 
360         // act
361         final List<LinePath> paths = connector.connectAll(segments);
362 
363         // assert
364         Assert.assertEquals(2, paths.size());
365 
366         final LinePath path0 = paths.get(0);
367         Assert.assertEquals(1, path0.getElements().size());
368         Assert.assertSame(seg2, path0.getElements().get(0));
369 
370         final LinePath path1 = paths.get(1);
371         Assert.assertEquals(2, path1.getElements().size());
372         Assert.assertSame(seg0, path1.getElements().get(0));
373         Assert.assertSame(seg1, path1.getElements().get(1));
374     }
375 
376     @Test
377     public void testConnectAll_pathStartingWithPoint() {
378         // arrange
379         final Vector2D p0 = Vector2D.ZERO;
380         final Vector2D p1 = Vector2D.of(1, 0);
381         final Vector2D p2 = Vector2D.of(1, 1);
382 
383         final LineConvexSubset seg0 = Lines.fromPointAndAngle(p0, PlaneAngleRadians.PI, TEST_PRECISION).segment(p0, p0);
384         final LineConvexSubset seg1 = Lines.segmentFromPoints(p0, p1, TEST_PRECISION);
385         final LineConvexSubset seg2 = Lines.segmentFromPoints(p1, p2, TEST_PRECISION);
386 
387         final List<LineConvexSubset> segments = new ArrayList<>(Arrays.asList(seg0, seg1, seg2));
388 
389         shuffle(segments);
390 
391         // act
392         final List<LinePath> paths = connector.connectAll(segments);
393 
394         // assert
395         Assert.assertEquals(1, paths.size());
396 
397         final LinePath path = paths.get(0);
398         Assert.assertSame(seg0, path.getElements().get(0));
399         Assert.assertSame(seg1, path.getElements().get(1));
400         Assert.assertSame(seg2, path.getElements().get(2));
401     }
402 
403     @Test
404     public void testConnectAll_intersectingPaths() {
405         // arrange
406         final LinePath a = LinePath.builder(TEST_PRECISION)
407                 .appendVertices(Vector2D.of(-1, 1), Vector2D.of(0.5, 0), Vector2D.of(-1, -1))
408                 .build();
409 
410         final LinePath b = LinePath.builder(TEST_PRECISION)
411                 .appendVertices(Vector2D.of(1, 1), Vector2D.of(-0.5, 0), Vector2D.of(1, -1))
412                 .build();
413 
414         final List<LineConvexSubset> segments = new ArrayList<>();
415         segments.addAll(a.getElements());
416         segments.addAll(b.getElements());
417 
418         shuffle(segments);
419 
420         // act
421         final List<LinePath> paths = connector.connectAll(segments);
422 
423         // assert
424         Assert.assertEquals(2, paths.size());
425 
426         assertFinitePath(paths.get(0),
427                 Vector2D.of(-1, 1), Vector2D.of(0.5, 0), Vector2D.of(-1, -1));
428 
429         assertFinitePath(paths.get(1),
430                 Vector2D.of(1, 1), Vector2D.of(-0.5, 0), Vector2D.of(1, -1));
431     }
432 
433     @Test
434     public void testInstancesCanBeReused() {
435         // arrange
436         final LineConvexSubset a = Lines.segmentFromPoints(Vector2D.ZERO, Vector2D.Unit.PLUS_X, TEST_PRECISION);
437         final LineConvexSubset b = Lines.segmentFromPoints(Vector2D.Unit.PLUS_X, Vector2D.Unit.PLUS_Y, TEST_PRECISION);
438 
439         // act
440         final List<LinePath> firstPaths = connector.connectAll(Collections.singletonList(a));
441         final List<LinePath> secondPaths = connector.connectAll(Collections.singletonList(b));
442 
443         // assert
444         Assert.assertEquals(1, firstPaths.size());
445         Assert.assertEquals(1, secondPaths.size());
446 
447         Assert.assertSame(a, firstPaths.get(0).getElements().get(0));
448         Assert.assertSame(b, secondPaths.get(0).getElements().get(0));
449     }
450 
451     @Test
452     public void testAdd() {
453         // arrange
454         final LineConvexSubset a = Lines.segmentFromPoints(Vector2D.ZERO, Vector2D.Unit.PLUS_X, TEST_PRECISION);
455         final LineConvexSubset b = Lines.segmentFromPoints(Vector2D.Unit.PLUS_X, Vector2D.of(1, 1), TEST_PRECISION);
456         final LineConvexSubset c = Lines.segmentFromPoints(Vector2D.Unit.PLUS_X, Vector2D.of(2, 0), TEST_PRECISION);
457 
458         // act
459         connector.add(Arrays.asList(a, b));
460         connector.add(Collections.singletonList(c));
461 
462         final List<LinePath> paths = connector.connectAll();
463 
464         // assert
465         Assert.assertEquals(2, paths.size());
466 
467         assertFinitePath(paths.get(0), Vector2D.ZERO, Vector2D.Unit.PLUS_X, Vector2D.of(2, 0));
468         assertFinitePath(paths.get(1), Vector2D.Unit.PLUS_X, Vector2D.of(1, 1));
469     }
470 
471     @Test
472     public void testConnect() {
473         // arrange
474         final LineConvexSubset a = Lines.segmentFromPoints(Vector2D.ZERO, Vector2D.Unit.PLUS_X, TEST_PRECISION);
475         final LineConvexSubset b = Lines.segmentFromPoints(Vector2D.Unit.PLUS_X, Vector2D.of(1, 1), TEST_PRECISION);
476         final LineConvexSubset c = Lines.segmentFromPoints(Vector2D.Unit.PLUS_X, Vector2D.of(2, 0), TEST_PRECISION);
477 
478         // act
479         connector.connect(Arrays.asList(a, b));
480         connector.connect(Collections.singletonList(c));
481 
482         final List<LinePath> paths = connector.connectAll();
483 
484         // assert
485         Assert.assertEquals(2, paths.size());
486 
487         assertFinitePath(paths.get(0), Vector2D.ZERO, Vector2D.Unit.PLUS_X, Vector2D.of(1, 1));
488         assertFinitePath(paths.get(1), Vector2D.Unit.PLUS_X, Vector2D.of(2, 0));
489     }
490 
491     @Test
492     public void testConnectableSegment_hashCode() {
493         // arrange
494         final LineConvexSubset segA = Lines.segmentFromPoints(Vector2D.ZERO, Vector2D.Unit.PLUS_X, TEST_PRECISION);
495         final LineConvexSubset segB = Lines.segmentFromPoints(Vector2D.Unit.PLUS_X, Vector2D.of(1, 1), TEST_PRECISION);
496 
497         final ConnectableLineSubset a = new ConnectableLineSubset(segA);
498 
499         // act
500         final int hash = a.hashCode();
501 
502         // assert
503         Assert.assertEquals(hash, a.hashCode());
504 
505         Assert.assertNotEquals(hash, new ConnectableLineSubset(segB).hashCode());
506         Assert.assertNotEquals(hash, new ConnectableLineSubset(Vector2D.Unit.PLUS_X).hashCode());
507 
508         Assert.assertEquals(hash, new ConnectableLineSubset(segA).hashCode());
509     }
510 
511     @Test
512     public void testConnectableSegment_equals() {
513         // arrange
514         final LineConvexSubset segA = Lines.segmentFromPoints(Vector2D.ZERO, Vector2D.Unit.PLUS_X, TEST_PRECISION);
515         final LineConvexSubset segB = Lines.segmentFromPoints(Vector2D.Unit.PLUS_X, Vector2D.of(1, 1), TEST_PRECISION);
516 
517         final ConnectableLineSubset a = new ConnectableLineSubset(segA);
518 
519         // act/assert
520         Assert.assertEquals(a, a);
521 
522         Assert.assertFalse(a.equals(null));
523         Assert.assertFalse(a.equals(new Object()));
524 
525         Assert.assertNotEquals(a, new ConnectableLineSubset(segB));
526         Assert.assertNotEquals(a, new ConnectableLineSubset(Vector2D.Unit.PLUS_X));
527 
528         Assert.assertEquals(a, new ConnectableLineSubset(segA));
529     }
530 
531     private static List<LineConvexSubset> shuffle(final List<LineConvexSubset> segments) {
532         return shuffle(segments, 1);
533     }
534 
535     private static List<LineConvexSubset> shuffle(final List<LineConvexSubset> segments, final int seed) {
536         Collections.shuffle(segments, new Random(seed));
537 
538         return segments;
539     }
540 
541     private static void assertFinitePath(final LinePath path, final Vector2D... vertices) {
542         Assert.assertFalse(path.isInfinite());
543         Assert.assertTrue(path.isFinite());
544 
545         assertPathVertices(path, vertices);
546     }
547 
548     private static void assertPathVertices(final LinePath path, final Vector2D... vertices) {
549         final List<Vector2D> expectedVertices = Arrays.asList(vertices);
550         final List<Vector2D> actualVertices = path.getVertexSequence();
551 
552         final String msg = "Expected path vertices to equal " + expectedVertices + " but was " + actualVertices;
553         Assert.assertEquals(msg, expectedVertices.size(), actualVertices.size());
554 
555         for (int i = 0; i < expectedVertices.size(); ++i) {
556             EuclideanTestUtils.assertCoordinatesEqual(expectedVertices.get(i), actualVertices.get(i), TEST_EPS);
557         }
558     }
559 
560     private static class TestConnector extends AbstractLinePathConnector {
561 
562         @Override
563         protected ConnectableLineSubset selectConnection(final ConnectableLineSubset incoming, final List<ConnectableLineSubset> outgoing) {
564             // just choose the first element
565             return outgoing.get(0);
566         }
567     }
568 }