/** * Gets the difference in headings between firstSegment and secondSegment, returning * defaultAngle if either segments are a point. * * @param firstSegment * the first segment to compare * @param secondSegment * the second segment to compare * @param defaultAngle * the default value to return * @return the difference between firstSegment.heading() and secondSegment.heading() if neither * segment is a single point (same start and end nodes), or defaultAngle if either * segment is a single point */ private Angle getDifferenceInHeadings(final Segment firstSegment, final Segment secondSegment, final Angle defaultAngle) { return firstSegment.heading() .flatMap(first -> secondSegment.heading().map(first::difference)) .orElse(defaultAngle); }
/** * @return the initial {@link Heading} for this {@link PolyLine}, based on the {@link Heading} * of the first {@link Segment}. */ public Optional<Heading> initialHeading() { final List<Segment> segments = this.segments(); return segments.size() > 0 ? segments.get(0).heading() : Optional.empty(); }
/** * @return the final {@link Heading} for this {@link PolyLine}, based on the {@link Heading} of * the last {@link Segment}. */ public Optional<Heading> finalHeading() { final List<Segment> segments = this.segments(); return segments.size() > 0 ? segments.get(segments.size() - 1).heading() : Optional.empty(); }
public boolean isOppositeDirectionUsingSegmentHeading(final PolyLine incomingEdgePolyline, final PolyLine outgoingEdgePolyline) { boolean oppositeDirection = false; if (Math.min(incomingEdgePolyline.size(), outgoingEdgePolyline.size()) > 1) { final List<Segment> incomingSegments = incomingEdgePolyline.segments(); final Optional<Heading> incomingSegmentHeading = incomingSegments .get(incomingSegments.size() - 1).heading(); final Optional<Heading> outgoingSegmentHeading = outgoingEdgePolyline.segments().get(0) .heading(); if (incomingSegmentHeading.isPresent() && outgoingSegmentHeading.isPresent()) { oppositeDirection = isOppositeDirection(incomingSegmentHeading.get(), outgoingSegmentHeading.get()); } } return oppositeDirection; }
public boolean isSameDirectionUsingSegmentHeading(final PolyLine incomingEdgePolyline, final PolyLine outgoingEdgePolyline) { boolean sameDirection = false; if (!incomingEdgePolyline.isPoint() && !outgoingEdgePolyline.isPoint()) { final Optional<Heading> incomingSegmentHeading = incomingEdgePolyline.segments() .get(incomingEdgePolyline.segments().size() - 1).heading(); final Optional<Heading> outgoingSegmentHeading = outgoingEdgePolyline.segments().get(0) .heading(); if (incomingSegmentHeading.isPresent() && outgoingSegmentHeading.isPresent()) { sameDirection = isSameDirection(incomingSegmentHeading.get(), outgoingSegmentHeading.get()); } } return sameDirection; } }
/** * @return The location of the biggest Angle in this {@link PolyLine} */ public Optional<Location> maximumAngleLocation() { final List<Segment> segments = segments(); if (segments.isEmpty() || segments.size() == 1) { return Optional.empty(); } Angle maximum = Angle.NONE; Location maximumAngleLocation = null; for (int i = 1; i < segments.size(); i++) { final Segment first = segments.get(i - 1); final Segment second = segments.get(i); final Optional<Heading> firstHeading = first.heading(); final Optional<Heading> secondHeading = second.heading(); if (firstHeading.isPresent() && secondHeading.isPresent()) { final Angle candidate = firstHeading.get().difference(secondHeading.get()); if (candidate.isGreaterThan(maximum) || maximumAngleLocation == null) { maximum = candidate; maximumAngleLocation = first.end(); } } } return Optional.ofNullable(maximumAngleLocation); }
@Override public Location offsetFromStart(final Ratio ratio) { final Optional<Heading> heading = heading(); if (heading.isPresent()) { return this.start().shiftAlongGreatCircle(heading.get(), length().scaleBy(ratio)); } return this.start(); }