# Find Perpendicular Distance and Minimum Perpendicular Vector between a Point and a Line using GeoTools and JTS

I have a line formed by 2 lat/lon pairs, and the lat/lon of a point. I would like to find out the perpendicular distance between the line and the point on the Earth surface (can assume Earth as great sphere), and the minimum perpendicular vector (i.e. the projected "cross point" on the line).

I am trying to use Geotools 8.0 and JTS for this. Below captured my testing code:

``````    //Coordinates in lon, lat
Coordinate linePt1 = new Coordinate(-5.71472, 50.06639);
Coordinate linePt2 = new Coordinate(-3.07000, 58.64389);

//Multiply all longitudes by the cosine of latitude.
//http://gis.stackexchange.com/a/29713/10772
linePt1.x = linePt1.x * Math.cos(linePt1.y);
linePt2.x = linePt2.x * Math.cos(linePt2.y);

LineString line = createLine(new Coordinate[]{linePt1, linePt2});

Coordinate pt1 = new Coordinate(-6, 54);
pt1.x = pt1.x * Math.cos(pt1.y);
Point point = createPoint(pt1.x, pt1.y);

double distanceOp = DistanceOp.distance(line, point);
System.out.println("Distance = " + distanceOp);

//Find the minimum perpendicular vector using "closestPoints()"
for (Coordinate c : DistanceOp.closestPoints(line, point)) {
System.out.println("=== " + c);
//verify if the point is on the line
System.out.println(CGAlgorithms.isOnLine(c, new Coordinate[]{linePt1, linePt2}));
}
``````

the createPoint() and createLine() methods:

``````public static LineString createLine(Coordinate[] coordinates){
GeometryFactory factory = new GeometryFactory(new PrecisionModel(
PrecisionModel.FLOATING), WGS84_SRID);
LineString line = (LineString) factory.createLineString(coordinates);
return line;
}

public static Point createPoint(double longitude, double latitude) {
if (longitude < -180 || longitude > 180) {
throw new IllegalArgumentException(
"Longitude should be between -180 and 180");
}
if (latitude < -90 || latitude > 90) {
throw new IllegalArgumentException(
"latitude should be between -90 and 90");
}
GeometryFactory factory = new GeometryFactory(new PrecisionModel(
PrecisionModel.FLOATING), WGS84_SRID);
Point point = (Point) factory.createPoint(new Coordinate(longitude,
latitude));
return point;
}
``````

However, the result of "isOnLine()" return false. I was wondering if there is anything wrong. Is there something wrong with my verification method, or actually the way I used to find out the perpendicular distance and the "cross point" on the Earth surface is not correct? Please kindly advice

-
Have you tried using `PrecisionModel.FIXED`? I can't comment on the rest of your code, but a double precision can introduce errors. See Robustness & Precision in the JTS FAQ. – hepiladron Oct 6 '12 at 19:42
@hepiladron, Thanks for your suggestion. Tried using PrecisionModel.FIXED but still got the same result... – xlogger Oct 7 '12 at 9:13
For future readers - this is unlikely to work out for you as JTS assumes a Cartesian framework and doesn't handle spherical geometry at all. – iant Jan 2 '13 at 10:49

Finally I found a java utility that do the job right away

-

There's also a solution using Gonomonic projection presented by Charles Karnes in Algorithms for geodesics. There is an implementation in Java available with Barefoot library: https://github.com/bmwcarit/barefoot

``````SpatialOperator spatial = new Geography();

Point reykjavik = new Point(-21.933333, 64.15);
Point moskva = new Point(37.616667, 55.75);
Point berlin = new Point(13.408056, 52.518611);

double f = spatial.intercept(reykjavik, moskva, berlin);
Point interception = spatial.interpolate(reykjavik, moskva, f);
``````

For more details see the answer here: http://gis.stackexchange.com/a/184695/29490

It works for large distance point to line projections but also close distance calculations (see images).

-