### Question:
Tube implements ITube { @Override public IVector2 nearestPointOutside(final IVector2 point) { if (startCenter.equals(endCenter)) { return Circle.createCircle(startCenter, radius).nearestPointOutside(point); } IVector2 nearestPointOutside = point; ILineSegment tubeLineSeg = Lines.segmentFromPoints(startCenter, endCenter); if (tubeLineSeg.distanceTo(point) < radius) { IVector2 leadPoint = tubeLineSeg.closestPointOnLine(point); if (leadPoint.equals(point)) { IVector2 dir = tubeLineSeg.directionVector().getNormalVector().scaleTo(radius); nearestPointOutside = point.addNew(dir); } else { nearestPointOutside = LineMath.stepAlongLine(leadPoint, point, radius); } } return nearestPointOutside; } @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);  }### Answer:
@Test public void testNearestPointOutside() { ITube tube = Tube.create(startCenter, endCenter, radius); ITube tubeZeroLength = Tube.create(startCenter, startCenter, radius); IVector2 pInside = Vector2.fromXY(0, 1); IVector2 nearestPointOutside = Vector2.fromXY(0, 10); Assert.assertEquals(tube.nearestPointOutside(pInside), nearestPointOutside); Assert.assertEquals(tube.nearestPointOutside(nearestPointOutside), nearestPointOutside); Assert.assertEquals(tubeZeroLength.nearestPointOutside(pInside), nearestPointOutside); }