### Question:
HalfLine extends AUnboundedLine implements IHalfLine { @Override public IVector2 closestPointOnLine(final IVector2 point) { if (!isValid()) { return supportVector(); } return LineMath.closestPointOnHalfLine(this, point); } private  HalfLine(final IVector2 supportVector, final IVector2 directionVector); static IHalfLine fromDirection(final IVector2 supportVector, final IVector2 directionVector); @Override boolean equals(final Object other); @Override int hashCode(); @Override IVector2 closestPointOnLine(final IVector2 point); @Override ILine toLine(); @Override IHalfLine copy(); @Override Optional<IVector2> intersectLine(final ILine line); @Override Optional<IVector2> intersectHalfLine(final IHalfLine other); @Override Optional<IVector2> intersectSegment(final ILineSegment segment); @Override boolean isPointInFront(final IVector2 point); @Override String toString();  }### Answer:
@Test public void testClosestPointOnLine() { IVector2 point = Vector2f.fromXY(0, 0); IVector2 lineSV = Vector2f.fromXY(1, 0); for (int degAngle = 0; degAngle <= 360; degAngle++) { double radAngle = Math.toRadians(degAngle); IVector2 lineDV = Vector2.fromAngle(radAngle); IHalfLine halfLine = HalfLine.fromDirection(lineSV, lineDV); IHalfLine invalidLine = HalfLine.fromDirection(lineSV, Vector2f.ZERO_VECTOR); IVector2 expectedClosestPoint; double expectedDistance; if (degAngle <= 90 || degAngle >= 270) { expectedClosestPoint = lineSV; expectedDistance = point.distanceTo(lineSV); } else { double radAngleAtOrigin = radAngle - Math.PI / 2; double distanceLinePoint = SumatraMath.cos(radAngleAtOrigin); expectedClosestPoint = Vector2f.X_AXIS.turnNew(radAngleAtOrigin).scaleTo(distanceLinePoint); expectedDistance = Math.abs(distanceLinePoint); } IVector2 actualClosestPoint = halfLine.closestPointOnLine(point); double actualDistance = halfLine.distanceTo(point); assertThat(actualClosestPoint, is(expectedClosestPoint)); assertThat(actualDistance, closeTo(expectedDistance, ACCURACY)); assertThat(invalidLine.closestPointOnLine(point), is(lineSV)); } }