Finden des senkrechten Abstands und des minimalen senkrechten Vektors zwischen Punkt und Linie mit GeoTools und JTS?

8

Ich habe eine Linie, die aus 2 Lat / Lon-Paaren und dem Lat / Lon eines Punktes besteht. Ich möchte den senkrechten Abstand zwischen der Linie und dem Punkt auf der Erdoberfläche (kann die Erde als große Kugel annehmen) und den minimalen senkrechten Vektor (dh den projizierten "Kreuzungspunkt" auf der Linie) herausfinden.

Ich versuche dafür Geotools 8.0 und JTS zu verwenden. Unten habe ich meinen Testcode erfasst:

    //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}));
    }

die Methoden createPoint () und 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;
}

Das Ergebnis von "isOnLine ()" gibt jedoch false zurück. Ich habe mich gefragt, ob etwas nicht stimmt.

Stimmt etwas mit meiner Überprüfungsmethode nicht oder stimmt die Art und Weise, wie ich den senkrechten Abstand und den "Kreuzungspunkt" auf der Erdoberfläche ermittelt habe, nicht?

xlogger
quelle
Haben Sie versucht, zu verwenden PrecisionModel.FIXED? Ich kann den Rest Ihres Codes nicht kommentieren, aber eine doppelte Genauigkeit kann zu Fehlern führen. Siehe Robustheit und Präzision in den JTS-FAQ.
Hepiladron
@hepiladron, Danke für deinen Vorschlag. Versucht mit PrecisionModel.FIXED, aber immer noch das gleiche Ergebnis ...
xlogger
Für zukünftige Leser ist es unwahrscheinlich, dass dies für Sie funktioniert, da JTS ein kartesisches Framework annimmt und die sphärische Geometrie überhaupt nicht verarbeitet.
Ian Turton

Antworten:

3

Es gibt auch eine Lösung mit der von Charles Karnes in Algorithmen für Geodäten vorgestellten gonomonischen Projektion. In der Barefoot-Bibliothek ist eine Implementierung in Java verfügbar: 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);

Weitere Informationen finden Sie in der Antwort hier: https://gis.stackexchange.com/a/184695/29490

Es funktioniert für Projektionen von Punkt zu Linie mit großer Entfernung, aber auch für Nahentfernungsberechnungen (siehe Bilder).

Geben Sie hier die Linkbeschreibung ein

sema
quelle