GeoPolyLine extends GeoObject { @Nonnull public GeoPoint getPointAtOffset(final double offsetInMeters) { final List<GeoLine> lines = asLines(); assert !lines.isEmpty(); int index = 0; GeoLine line; double nextOffset; if (offsetInMeters < 0.0) { nextOffset = Math.max(0.0, getLengthMeters() + offsetInMeters); } else { nextOffset = Math.min(getLengthMeters(), offsetInMeters); } double offset; do { offset = nextOffset; line = lines.get(index); nextOffset = offset - line.getLengthMeters(); ++index; } while ((nextOffset > 0.0) && (index < lines.size())); assert (0.0 <= offset) && (offset <= line.getLengthMeters()); final double ratio = offset / line.getLengthMeters(); final double northing = line.getNorthing() * ratio; final double easting = line.getEasting() * ratio; final GeoPoint point = line.getOrigin().translate(new GeoVector(northing, easting)); return point; } GeoPolyLine(@Nonnull final List<GeoPoint> points); @SuppressWarnings({"ConstantConditions", "UnusedDeclaration"}) @Deprecated private  GeoPolyLine(); @Nonnull @Override GeoPoint getOrigin(); @Nonnull @Override GeoPoint getCenter(); @Nonnull GeoPoint getPointAtOffset(final double offsetInMeters); int size(); @Nonnull GeoPoint get(final int i); @Nonnull List<GeoLine> asLines(); @Nonnull GeoLine getLine(final int i); @Nonnull @Override GeoPolyLine translate(@Nonnull final GeoVector vector); @Nonnull @Override GeoPolyLine moveTo(@Nonnull final GeoPoint origin); double getLengthMeters(); @Override boolean canEqual(@Nonnull final Object obj); @Override boolean equals(@Nullable final Object obj); @Override int hashCode();  }
@Test public void testGetPointAtOffset() { LOG.info("testGetPointAtOffset"); final double delta = 1.0e-4; final GeoPoint x1 = new GeoPoint(-1.0, 0.0); final GeoPoint x2 = new GeoPoint(0.0, 0.0); final GeoPoint x2half = new GeoPoint(-0.5, 0.0); final GeoPoint x3 = new GeoPoint(0.0, 1.0); final GeoPoint x3half = new GeoPoint(0.0, 0.5); final GeoPoint x4 = new GeoPoint(1.0, 3.0); final GeoPoint x4half = new GeoPoint(0.5, 2.0); final List<GeoPoint> list = Lists.asList(x1, new GeoPoint[]{x2, x3, x4}); final GeoPolyLine poly = new GeoPolyLine(list); Assert.assertEquals(x1, poly.getPointAtOffset(0.0)); Assert.assertEquals(x4, poly.getPointAtOffset(100.0 * Geo.METERS_PER_DEGREE_LON_EQUATOR)); Assert.assertEquals(x2half, poly.getPointAtOffset(Geo.METERS_PER_DEGREE_LAT / 2.0)); Assert.assertEquals(x2, poly.getPointAtOffset(Geo.METERS_PER_DEGREE_LAT)); Assert.assertEquals(x3half, poly.getPointAtOffset(Geo.METERS_PER_DEGREE_LAT + (Geo.METERS_PER_DEGREE_LON_EQUATOR / 2.0))); Assert.assertEquals(x3, poly.getPointAtOffset(Geo.METERS_PER_DEGREE_LAT + Geo.METERS_PER_DEGREE_LON_EQUATOR)); final GeoPoint p1 = poly.getPointAtOffset(Geo.METERS_PER_DEGREE_LAT + Geo.METERS_PER_DEGREE_LON_EQUATOR + (Math.sqrt((Geo.METERS_PER_DEGREE_LAT * Geo.METERS_PER_DEGREE_LAT) + (4 * Geo.METERS_PER_DEGREE_LON_EQUATOR * Geo.METERS_PER_DEGREE_LON_EQUATOR)) / 2.0)); Assert.assertEquals(x4half.getLat(), p1.getLat(), delta); Assert.assertEquals(x4half.getLon(), p1.getLon(), delta); Assert.assertEquals(x4, poly.getPointAtOffset(Geo.METERS_PER_DEGREE_LAT + Geo.METERS_PER_DEGREE_LON_EQUATOR + Math.sqrt((Geo.METERS_PER_DEGREE_LAT * Geo.METERS_PER_DEGREE_LAT) + (4 * Geo.METERS_PER_DEGREE_LON_EQUATOR * Geo.METERS_PER_DEGREE_LON_EQUATOR)))); Assert.assertEquals(x1, poly.getPointAtOffset(-100.0 * Geo.METERS_PER_DEGREE_LON_EQUATOR)); final GeoPoint p2 = poly.getPointAtOffset(-1.0e-8); Assert.assertEquals(x4.getLat(), p2.getLat(), delta); Assert.assertEquals(x4.getLon(), p2.getLon(), delta); final GeoPoint p3 = poly.getPointAtOffset(-Math.sqrt((Geo.METERS_PER_DEGREE_LAT * Geo.METERS_PER_DEGREE_LAT) + (4 * Geo.METERS_PER_DEGREE_LON_EQUATOR * Geo.METERS_PER_DEGREE_LON_EQUATOR))); Assert.assertEquals(x3.getLat(), p3.getLat(), delta); Assert.assertEquals(x3.getLon(), p3.getLon(), delta); final GeoPoint p4 = poly.getPointAtOffset(-Math.sqrt((Geo.METERS_PER_DEGREE_LAT * Geo.METERS_PER_DEGREE_LAT) + (4 * Geo.METERS_PER_DEGREE_LON_EQUATOR * Geo.METERS_PER_DEGREE_LON_EQUATOR)) - Geo.METERS_PER_DEGREE_LON_EQUATOR); Assert.assertEquals(x2.getLat(), p4.getLat(), delta); Assert.assertEquals(x2.getLon(), p4.getLon(), delta); final GeoPoint p5 = poly.getPointAtOffset(-Math.sqrt((Geo.METERS_PER_DEGREE_LAT * Geo.METERS_PER_DEGREE_LAT) + (4 * Geo.METERS_PER_DEGREE_LON_EQUATOR * Geo.METERS_PER_DEGREE_LON_EQUATOR)) - Geo.METERS_PER_DEGREE_LON_EQUATOR - (Geo.METERS_PER_DEGREE_LAT / 2.0)); Assert.assertEquals(x2half.getLat(), p5.getLat(), delta); Assert.assertEquals(x2half.getLon(), p5.getLon(), delta); }