@Test public void testLineIntersections() { final Vector2 start = Vector2.fromXY(1, 5); final Vector2 end = Vector2.fromXY(-2, 5); ITube tube = Tube.create(start, end, 10); assertThat(tube.lineIntersections(Lines.segmentFromPoints(start, Vector2.fromXY(12, 5)))) .containsExactlyInAnyOrder(Vector2.fromXY(11, 5)); assertThat(tube.lineIntersections(Lines.segmentFromPoints(start, Vector2.fromXY(-13, 5)))) .containsExactlyInAnyOrder(Vector2.fromXY(-12, 5)); assertThat(tube.lineIntersections(Lines.segmentFromPoints(start, Vector2.fromXY(1, 16)))) .containsExactlyInAnyOrder(Vector2.fromXY(1, 15)); assertThat(tube.lineIntersections(Lines.segmentFromPoints(start, Vector2.fromXY(1, -6)))) .containsExactlyInAnyOrder(Vector2.fromXY(1, -5)); assertThat(tube.lineIntersections(Lines.segmentFromPoints(end, Vector2.fromXY(-13, 5)))) .containsExactlyInAnyOrder(Vector2.fromXY(-12, 5)); assertThat(tube.lineIntersections(Lines.segmentFromPoints(end, Vector2.fromXY(12, 5)))) .containsExactlyInAnyOrder(Vector2.fromXY(11, 5)); assertThat(tube.lineIntersections(Lines.segmentFromPoints(end, Vector2.fromXY(-2, 16)))) .containsExactlyInAnyOrder(Vector2.fromXY(-2, 15)); assertThat(tube.lineIntersections(Lines.segmentFromPoints(end, Vector2.fromXY(-2, -6)))) .containsExactlyInAnyOrder(Vector2.fromXY(-2, -5)); assertThat(tube.lineIntersections(Lines.segmentFromPoints(Vector2.fromXY(1, 5), Vector2.fromXY(-1, 25)))) .containsExactlyInAnyOrder(Vector2.fromXY(0, 15)); assertThat(tube.lineIntersections(Lines.segmentFromPoints(Vector2.fromXY(1, 5), Vector2.fromXY(-1, -15)))) .containsExactlyInAnyOrder(Vector2.fromXY(0, -5)); assertThat(tube.lineIntersections(Lines.segmentFromPoints(Vector2.fromXY(0, -100), Vector2.fromXY(0, 100)))) .containsExactlyInAnyOrder(Vector2.fromXY(0, -5), Vector2.fromXY(0, 15)); assertThat(tube.lineIntersections(Lines.segmentFromPoints(Vector2.fromXY(1, -100), Vector2.fromXY(1, 100)))) .containsExactlyInAnyOrder(Vector2.fromXY(1, -5), Vector2.fromXY(1, 15)); assertThat(tube.lineIntersections(Lines.segmentFromPoints(Vector2.fromXY(-2, -100), Vector2.fromXY(-2, 100)))) .containsExactlyInAnyOrder(Vector2.fromXY(-2, -5), Vector2.fromXY(-2, 15)); assertThat(tube.lineIntersections(Lines.segmentFromPoints(Vector2.fromXY(-100, 5), Vector2.fromXY(100, 5)))) .containsExactlyInAnyOrder(Vector2.fromXY(11, 5), Vector2.fromXY(-12, 5)); assertThat(tube.lineIntersections(Lines.segmentFromPoints(Vector2.fromXY(-2, -100), Vector2.fromXY(-2, 5)))) .containsExactlyInAnyOrder(Vector2.fromXY(-2, -5)); assertThat(tube.lineIntersections(Lines.segmentFromPoints(Vector2.fromXY(-2, 5), Vector2.fromXY(-2, 100)))) .containsExactlyInAnyOrder(Vector2.fromXY(-2, 15)); assertThat(tube.lineIntersections(Lines.lineFromPoints(Vector2.fromXY(-2, -100), Vector2.fromXY(-2, 5)))) .containsExactlyInAnyOrder(Vector2.fromXY(-2, -5), Vector2.fromXY(-2, 15)); assertThat(tube.lineIntersections(Lines.lineFromPoints(Vector2.fromXY(-2, 5), Vector2.fromXY(-2, 100)))) .containsExactlyInAnyOrder(Vector2.fromXY(-2, -5), Vector2.fromXY(-2, 15)); }
@Override public List<IVector2> lineIntersections(final ILine line) { if (startCenter.equals(endCenter)) { return Circle.createCircle(startCenter, radius).lineIntersections(line); } ICircle startCircle = Circle.createCircle(startCenter, radius); ICircle endCircle = Circle.createCircle(endCenter, radius); ILineSegment tubeLineSeg = Lines.segmentFromPoints(startCenter, endCenter); List<IVector2> intersections = startCircle.lineIntersections(line).stream() .filter(v -> tubeLineSeg.closestPointOnLine(v).equals(startCenter)) .collect(Collectors.toList()); List<IVector2> intersectsAtEnd = endCircle.lineIntersections(line); for (IVector2 v : intersectsAtEnd) { if (tubeLineSeg.closestPointOnLine(v).equals(endCenter)) { intersections.add(v); } } IVector2 start1 = startCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(radius)); IVector2 end1 = endCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(radius)); Lines.segmentFromPoints(start1, end1).intersectLine(line.v2()).ifPresent(intersections::add); IVector2 start2 = startCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(-radius)); IVector2 end2 = endCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(-radius)); Lines.segmentFromPoints(start2, end2).intersectLine(line.v2()).ifPresent(intersections::add); return intersections.stream().distinct().collect(Collectors.toList()); }
Tube implements ITube { @Override public List<IVector2> lineIntersections(final ILine line) { if (startCenter.equals(endCenter)) { return Circle.createCircle(startCenter, radius).lineIntersections(line); } ICircle startCircle = Circle.createCircle(startCenter, radius); ICircle endCircle = Circle.createCircle(endCenter, radius); ILineSegment tubeLineSeg = Lines.segmentFromPoints(startCenter, endCenter); List<IVector2> intersections = startCircle.lineIntersections(line).stream() .filter(v -> tubeLineSeg.closestPointOnLine(v).equals(startCenter)) .collect(Collectors.toList()); List<IVector2> intersectsAtEnd = endCircle.lineIntersections(line); for (IVector2 v : intersectsAtEnd) { if (tubeLineSeg.closestPointOnLine(v).equals(endCenter)) { intersections.add(v); } } IVector2 start1 = startCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(radius)); IVector2 end1 = endCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(radius)); Lines.segmentFromPoints(start1, end1).intersectLine(line.v2()).ifPresent(intersections::add); IVector2 start2 = startCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(-radius)); IVector2 end2 = endCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(-radius)); Lines.segmentFromPoints(start2, end2).intersectLine(line.v2()).ifPresent(intersections::add); return intersections.stream().distinct().collect(Collectors.toList()); } }
Tube implements ITube { @Override public List<IVector2> lineIntersections(final ILine line) { if (startCenter.equals(endCenter)) { return Circle.createCircle(startCenter, radius).lineIntersections(line); } ICircle startCircle = Circle.createCircle(startCenter, radius); ICircle endCircle = Circle.createCircle(endCenter, radius); ILineSegment tubeLineSeg = Lines.segmentFromPoints(startCenter, endCenter); List<IVector2> intersections = startCircle.lineIntersections(line).stream() .filter(v -> tubeLineSeg.closestPointOnLine(v).equals(startCenter)) .collect(Collectors.toList()); List<IVector2> intersectsAtEnd = endCircle.lineIntersections(line); for (IVector2 v : intersectsAtEnd) { if (tubeLineSeg.closestPointOnLine(v).equals(endCenter)) { intersections.add(v); } } IVector2 start1 = startCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(radius)); IVector2 end1 = endCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(radius)); Lines.segmentFromPoints(start1, end1).intersectLine(line.v2()).ifPresent(intersections::add); IVector2 start2 = startCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(-radius)); IVector2 end2 = endCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(-radius)); Lines.segmentFromPoints(start2, end2).intersectLine(line.v2()).ifPresent(intersections::add); return intersections.stream().distinct().collect(Collectors.toList()); } @SuppressWarnings("unused") private  Tube(); private  Tube(final IVector2 startCenter, final IVector2 endCenter, final double radius); }
Tube implements ITube { @Override public List<IVector2> lineIntersections(final ILine line) { if (startCenter.equals(endCenter)) { return Circle.createCircle(startCenter, radius).lineIntersections(line); } ICircle startCircle = Circle.createCircle(startCenter, radius); ICircle endCircle = Circle.createCircle(endCenter, radius); ILineSegment tubeLineSeg = Lines.segmentFromPoints(startCenter, endCenter); List<IVector2> intersections = startCircle.lineIntersections(line).stream() .filter(v -> tubeLineSeg.closestPointOnLine(v).equals(startCenter)) .collect(Collectors.toList()); List<IVector2> intersectsAtEnd = endCircle.lineIntersections(line); for (IVector2 v : intersectsAtEnd) { if (tubeLineSeg.closestPointOnLine(v).equals(endCenter)) { intersections.add(v); } } IVector2 start1 = startCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(radius)); IVector2 end1 = endCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(radius)); Lines.segmentFromPoints(start1, end1).intersectLine(line.v2()).ifPresent(intersections::add); IVector2 start2 = startCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(-radius)); IVector2 end2 = endCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(-radius)); Lines.segmentFromPoints(start2, end2).intersectLine(line.v2()).ifPresent(intersections::add); return intersections.stream().distinct().collect(Collectors.toList()); } @SuppressWarnings("unused") private  Tube(); private  Tube(final IVector2 startCenter, final IVector2 endCenter, final double radius); static Tube create(final IVector2 startCenter, final IVector2 endCenter, final double radius); static Tube fromLineSegment(final ILineSegment lineSegment, final double radius); @Override double radius(); @Override IVector2 startCenter(); @Override IVector2 endCenter(); @Override IVector2 center(); @Override boolean isPointInShape(final IVector2 point); @Override boolean isPointInShape(final IVector2 point, final double margin); @Override IVector2 nearestPointOutside(final IVector2 point); @Override IVector2 nearestPointInside(final IVector2 point); @Override List<IVector2> lineIntersections(final ILine line); @Override ITube withMargin(final double margin); }
Tube implements ITube { @Override public List<IVector2> lineIntersections(final ILine line) { if (startCenter.equals(endCenter)) { return Circle.createCircle(startCenter, radius).lineIntersections(line); } ICircle startCircle = Circle.createCircle(startCenter, radius); ICircle endCircle = Circle.createCircle(endCenter, radius); ILineSegment tubeLineSeg = Lines.segmentFromPoints(startCenter, endCenter); List<IVector2> intersections = startCircle.lineIntersections(line).stream() .filter(v -> tubeLineSeg.closestPointOnLine(v).equals(startCenter)) .collect(Collectors.toList()); List<IVector2> intersectsAtEnd = endCircle.lineIntersections(line); for (IVector2 v : intersectsAtEnd) { if (tubeLineSeg.closestPointOnLine(v).equals(endCenter)) { intersections.add(v); } } IVector2 start1 = startCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(radius)); IVector2 end1 = endCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(radius)); Lines.segmentFromPoints(start1, end1).intersectLine(line.v2()).ifPresent(intersections::add); IVector2 start2 = startCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(-radius)); IVector2 end2 = endCenter.addNew(tubeLineSeg.directionVector().getNormalVector().scaleTo(-radius)); Lines.segmentFromPoints(start2, end2).intersectLine(line.v2()).ifPresent(intersections::add); return intersections.stream().distinct().collect(Collectors.toList()); } @SuppressWarnings("unused") private  Tube(); private  Tube(final IVector2 startCenter, final IVector2 endCenter, final double radius); static Tube create(final IVector2 startCenter, final IVector2 endCenter, final double radius); static Tube fromLineSegment(final ILineSegment lineSegment, final double radius); @Override double radius(); @Override IVector2 startCenter(); @Override IVector2 endCenter(); @Override IVector2 center(); @Override boolean isPointInShape(final IVector2 point); @Override boolean isPointInShape(final IVector2 point, final double margin); @Override IVector2 nearestPointOutside(final IVector2 point); @Override IVector2 nearestPointInside(final IVector2 point); @Override List<IVector2> lineIntersections(final ILine line); @Override ITube withMargin(final double margin);  }