SegmentGraphUtilities { public static <T> double getValueAt(List<T> segments, ToDoubleFunction<T> segmentToXExtent, BiFunction<T, Double, Double> yValueInterpolator, double xValue) { double xValueAtBoundary = 0; for (T segment : segments) { double xExtent = segmentToXExtent.applyAsDouble(segment); double xDistanceIntoSegment = Math.max(xValue - xValueAtBoundary, 0); if (xExtent >= xDistanceIntoSegment) { return yValueInterpolator.apply(segment, xDistanceIntoSegment); } xValueAtBoundary += xExtent; } if (xValue - xValueAtBoundary < xValue * ERROR_TOLERANCE) { T lastRegion = Iterables.getLast(segments, null); return yValueInterpolator.apply(lastRegion, segmentToXExtent.applyAsDouble(lastRegion)); } throw Failer.fail("Should have found an answer in loop"); } private  SegmentGraphUtilities(); static double getValueAt(List<T> segments, ToDoubleFunction<T> segmentToXExtent, BiFunction<T, Double, Double> yValueInterpolator, double xValue); static double accumulateValueTo(List<T> segments, ToDoubleFunction<T> segmentToXExtent, ToDoubleFunction<T> segmentToYExtent, BiFunction<T, Double, Double> yValueInterpolator, double xValue);  }
@Test void getValueAt_whenXWithinRange_thenReturnsExpectedValue() { double result = SegmentGraphUtilities.getValueAt(sections, Section::xExtent, Section::extrapolateValue, 7.7); assertThat(result).isCloseTo(1.4, within(1e-6)); }
@Test void getValueAt_whenXBeyondRange_thenThrowsException() { assertThatThrownBy(() -> SegmentGraphUtilities.getValueAt(sections, Section::xExtent, Section::extrapolateValue, 100000)) .isInstanceOf(IllegalStateException.class); }