@Test @SuppressWarnings("OptionalGetWithoutIsPresent") public void nextTo() { double stepSize = 3; double margin = Geometry.getBotRadius() * 2; for (ILineSegment edge : penAreaBoundary.getEdges()) { int steps = (int) ((edge.getLength() - margin) / stepSize); for (int i = 0; i < steps; i++) { final IVector2 current = edge.stepAlongLine((i + 1) * stepSize); final Optional<IVector2> next = penAreaBoundary.nextTo(current, margin, 1); assertThat(next) .as("Point exists for i=%d", i) .isPresent(); assertThat(current.distanceTo(next.get())) .as("Distance between points is equal to margin for i=%d", i) .isCloseTo(margin, within(1e-10)); } } }
public Optional<IVector2> nextTo(final IVector2 p, final double margin, final int direction) { final ILineSegment currentEdge = edges.stream().filter(l -> l.isPointOnLine(p)).findAny().orElse(null); if (currentEdge == null) { return Optional.empty(); } double baseDistance = edgeStartByDirection(currentEdge, direction).distanceTo(p); IVector2 np = stepAlongEdge(currentEdge, baseDistance + margin, direction); if (currentEdge.isPointOnLine(np)) { return Optional.of(np); } double remainingDistanceOnCurrentEdge = p.distanceTo(currentEdge.closestPointOnLine(np)); double distanceOnNextEdge = SumatraMath .sqrt(margin * margin - remainingDistanceOnCurrentEdge * remainingDistanceOnCurrentEdge); Optional<ILineSegment> nextEdge = nextEdge(currentEdge, direction); return nextEdge.map(e -> stepAlongEdge(e, distanceOnNextEdge, direction)); }
PenAreaBoundary implements Comparator<IVector2> { public Optional<IVector2> nextTo(final IVector2 p, final double margin, final int direction) { final ILineSegment currentEdge = edges.stream().filter(l -> l.isPointOnLine(p)).findAny().orElse(null); if (currentEdge == null) { return Optional.empty(); } double baseDistance = edgeStartByDirection(currentEdge, direction).distanceTo(p); IVector2 np = stepAlongEdge(currentEdge, baseDistance + margin, direction); if (currentEdge.isPointOnLine(np)) { return Optional.of(np); } double remainingDistanceOnCurrentEdge = p.distanceTo(currentEdge.closestPointOnLine(np)); double distanceOnNextEdge = SumatraMath .sqrt(margin * margin - remainingDistanceOnCurrentEdge * remainingDistanceOnCurrentEdge); Optional<ILineSegment> nextEdge = nextEdge(currentEdge, direction); return nextEdge.map(e -> stepAlongEdge(e, distanceOnNextEdge, direction)); } }
PenAreaBoundary implements Comparator<IVector2> { public Optional<IVector2> nextTo(final IVector2 p, final double margin, final int direction) { final ILineSegment currentEdge = edges.stream().filter(l -> l.isPointOnLine(p)).findAny().orElse(null); if (currentEdge == null) { return Optional.empty(); } double baseDistance = edgeStartByDirection(currentEdge, direction).distanceTo(p); IVector2 np = stepAlongEdge(currentEdge, baseDistance + margin, direction); if (currentEdge.isPointOnLine(np)) { return Optional.of(np); } double remainingDistanceOnCurrentEdge = p.distanceTo(currentEdge.closestPointOnLine(np)); double distanceOnNextEdge = SumatraMath .sqrt(margin * margin - remainingDistanceOnCurrentEdge * remainingDistanceOnCurrentEdge); Optional<ILineSegment> nextEdge = nextEdge(currentEdge, direction); return nextEdge.map(e -> stepAlongEdge(e, distanceOnNextEdge, direction)); } private  PenAreaBoundary(final double width, final double depth, final double sign); }
PenAreaBoundary implements Comparator<IVector2> { public Optional<IVector2> nextTo(final IVector2 p, final double margin, final int direction) { final ILineSegment currentEdge = edges.stream().filter(l -> l.isPointOnLine(p)).findAny().orElse(null); if (currentEdge == null) { return Optional.empty(); } double baseDistance = edgeStartByDirection(currentEdge, direction).distanceTo(p); IVector2 np = stepAlongEdge(currentEdge, baseDistance + margin, direction); if (currentEdge.isPointOnLine(np)) { return Optional.of(np); } double remainingDistanceOnCurrentEdge = p.distanceTo(currentEdge.closestPointOnLine(np)); double distanceOnNextEdge = SumatraMath .sqrt(margin * margin - remainingDistanceOnCurrentEdge * remainingDistanceOnCurrentEdge); Optional<ILineSegment> nextEdge = nextEdge(currentEdge, direction); return nextEdge.map(e -> stepAlongEdge(e, distanceOnNextEdge, direction)); } private  PenAreaBoundary(final double width, final double depth, final double sign); static PenAreaBoundary ownWithMargin(final double margin); PenAreaBoundary withMargin(final double margin); IVector2 closestPoint(final IVector2 p); IVector2 projectPoint(final IVector2 p); IVector2 projectPoint(final IVector2 p1, final IVector2 p2); Optional<IVector2> nextTo(final IVector2 p, final double margin, final int direction); Optional<IVector2> nextIntermediateCorner(final IVector2 pFrom, final IVector2 pTo); double distanceBetween(final IVector2 p1, final IVector2 p2); @Override int compare(IVector2 p1, IVector2 p2); Optional<IVector2> stepAlongBoundary(final IVector2 start, final double distance); boolean isPointInShape(IVector2 point); double getWidth(); double getDepth(); IVector2 getStart(); IVector2 getCorner1(); IVector2 getCorner2(); IVector2 getEnd(); IVector2 getCenter(); }
PenAreaBoundary implements Comparator<IVector2> { public Optional<IVector2> nextTo(final IVector2 p, final double margin, final int direction) { final ILineSegment currentEdge = edges.stream().filter(l -> l.isPointOnLine(p)).findAny().orElse(null); if (currentEdge == null) { return Optional.empty(); } double baseDistance = edgeStartByDirection(currentEdge, direction).distanceTo(p); IVector2 np = stepAlongEdge(currentEdge, baseDistance + margin, direction); if (currentEdge.isPointOnLine(np)) { return Optional.of(np); } double remainingDistanceOnCurrentEdge = p.distanceTo(currentEdge.closestPointOnLine(np)); double distanceOnNextEdge = SumatraMath .sqrt(margin * margin - remainingDistanceOnCurrentEdge * remainingDistanceOnCurrentEdge); Optional<ILineSegment> nextEdge = nextEdge(currentEdge, direction); return nextEdge.map(e -> stepAlongEdge(e, distanceOnNextEdge, direction)); } private  PenAreaBoundary(final double width, final double depth, final double sign); static PenAreaBoundary ownWithMargin(final double margin); PenAreaBoundary withMargin(final double margin); IVector2 closestPoint(final IVector2 p); IVector2 projectPoint(final IVector2 p); IVector2 projectPoint(final IVector2 p1, final IVector2 p2); Optional<IVector2> nextTo(final IVector2 p, final double margin, final int direction); Optional<IVector2> nextIntermediateCorner(final IVector2 pFrom, final IVector2 pTo); double distanceBetween(final IVector2 p1, final IVector2 p2); @Override int compare(IVector2 p1, IVector2 p2); Optional<IVector2> stepAlongBoundary(final IVector2 start, final double distance); boolean isPointInShape(IVector2 point); double getWidth(); double getDepth(); IVector2 getStart(); IVector2 getCorner1(); IVector2 getCorner2(); IVector2 getEnd(); IVector2 getCenter();  }