Tengo una línea formada por 2 pares lat / lon, y el lat / lon de un punto. Me gustaría averiguar la distancia perpendicular entre la línea y el punto en la superficie de la Tierra (puede asumir la Tierra como gran esfera), y el vector perpendicular mínimo (es decir, el "punto de cruce" proyectado en la línea).
Estoy tratando de usar Geotools 8.0 y JTS para esto. A continuación capturó mi código de prueba:
//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}));
}
los métodos createPoint () y createLine ():
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;
}
Sin embargo, el resultado de "isOnLine ()" devuelve falso. Me preguntaba si hay algo mal.
¿Hay algún problema con mi método de verificación, o en realidad la forma en que solía averiguar la distancia perpendicular y el "punto de cruce" en la superficie de la Tierra no es correcta?
PrecisionModel.FIXED
? No puedo comentar sobre el resto de su código, pero una precisión doble puede introducir errores. Consulte Robustez y precisión en las preguntas frecuentes de JTS.Respuestas:
Finalmente encontré una utilidad Java que hace el trabajo de inmediato
http://biodiversityinformatics.amnh.org/open_source/pdc/documentation.php
fuente
También hay una solución que utiliza la proyección gonomónica presentada por Charles Karnes en Algoritmos para geodésicas. Hay una implementación en Java disponible con la biblioteca Barefoot: https://github.com/bmwcarit/barefoot
Para obtener más detalles, consulte la respuesta aquí: https://gis.stackexchange.com/a/184695/29490
Funciona para proyecciones de punto a línea de gran distancia, pero también para cálculos de corta distancia (ver imágenes).
fuente