4

I have single LineString and some Point (outside the line), I snapped it to the Line (using DistanceOp so as far as I understood the snapped point should lay on the line). How can I calculate length along the line from start vertex of the LineString up to the snapped point on the line?

    import com.vividsolutions.jts.geom.Coordinate;
    import com.vividsolutions.jts.geom.GeometryFactory;
    import com.vividsolutions.jts.geom.LineString;
    import com.vividsolutions.jts.geom.Point;
    import com.vividsolutions.jts.operation.distance.DistanceOp;

    GeometryFactory gf = JTSFactoryFinder.getGeometryFactory();
    Point outsidePoint = gf.createPoint(new Coordinate(outside.lat, outside.lon));
    Coordinate snappedPoint = DistanceOp.nearestPoints(outsidePoint, LineString)[1];

I though about this: LineString is a List of coordinates, Find the index of the vertex, closest to the snapped point, and replace it with the snapped point. Then construct a LineString from start vertex up to the index found. Then sum length calculated between each consecutive vertices of the line.

  1. First problem is situation like this: enter image description here
  2. Second problem: When some sophisticated algorithm calculates length - Does inside happening something more complex than just sum lengths between 2 consecutive points?
1
  • 1
    Doesn't my answer solve your problem? Could you explain what's missing?
    – Lars
    Commented Mar 20, 2017 at 6:27

2 Answers 2

3

1) Try this:

public static double calculateLengthAlongLineString(LineString theLine, Coordinate coordinateOnTheLine){
    GeometryFactory factory = new GeometryFactory();
    double length = 0;
    // create point to check for intersection with line
    Point pointOnTheLine = factory.createPoint(coordinateOnTheLine);
    Coordinate[] theLineCoordinates = theLine.getCoordinates();
    // iterate over linestring and create sub-lines for each coordinate pair
    for(int i = 1; i < theLineCoordinates.length; i++){
        LineString currentLine = factory.createLineString(new Coordinate[]{theLineCoordinates[i-1], theLineCoordinates[i]});
        // check if coordinateOnTheLine is on currentLine
        if(currentLine.intersects(pointOnTheLine)){
            // create new currentLine with coordinateOnTheLine as endpoint and calculate length
            currentLine = factory.createLineString(new Coordinate[]{theLineCoordinates[i-1], coordinateOnTheLine});
            length += currentLine.getLength();
            // return result length
            return length;
        }
        length += currentLine.getLength();
    }
    // coordinate was not on the line -> return length of complete linestring...
    return length;
}

This approach is similar to what you already suggested. Each LineString segment is checked for intersection with the point (coordinate) and then the length is summed up.

2)

Not to my knowledge.

2

JTS has an official solution for this:

import org.locationtech.jts.linearref.LengthLocationMap;
import org.locationtech.jts.linearref.LinearLocation;
import org.locationtech.jts.linearref.LocationIndexedLine;

public static double getLengthAloneLineString(LineString line, Point point) {
    return getLengthAloneLineString(line, point.getCoordinate());
}

public static double getLengthAloneLineString(LineString line, Coordinate coordinate) {
    LocationIndexedLine locationIndexedLine = new LocationIndexedLine(line);
    LinearLocation location = locationIndexedLine.project(coordinate);
    double length = new LengthLocationMap(line).getLength(location);

    return length;
}

For details see source code of JTS LocationIndexedLine and JTS LengthLocationMap

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.