Menemukan Jarak Perpendikuler dan Vektor Perpendikuler Minimum antara Titik dan Garis menggunakan GeoTools dan JTS?

8

Saya memiliki garis yang dibentuk oleh 2 pasangan lat / lon, dan lat / lon suatu titik. Saya ingin mengetahui jarak tegak lurus antara garis dan titik pada permukaan bumi (dapat menganggap bumi sebagai bola besar), dan vektor tegak lurus minimum (yaitu "titik silang" yang diproyeksikan pada garis).

Saya mencoba menggunakan Geotools 8.0 dan JTS untuk ini. Di bawah ini diambil kode pengujian saya:

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

metode createPoint () dan 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;
}

Namun, hasil "isOnLine ()" mengembalikan false. Saya bertanya-tanya apakah ada yang salah.

Apakah ada yang salah dengan metode verifikasi saya, atau sebenarnya cara yang saya gunakan untuk mengetahui jarak tegak lurus dan "titik silang" di permukaan bumi tidak benar?

xlogger
sumber
Sudahkah Anda mencoba menggunakan PrecisionModel.FIXED? Saya tidak dapat mengomentari sisa kode Anda, tetapi presisi ganda dapat menyebabkan kesalahan. Lihat Robustness & Precision di FAQ JTS.
hepiladron
@ hepiladron, Terima kasih atas saran Anda.
Sudah
Untuk pembaca masa depan - ini tidak mungkin berhasil untuk Anda karena JTS mengasumsikan kerangka kerja Cartesian dan sama sekali tidak menangani geometri bola.
Ian Turton

Jawaban:

3

Ada juga solusi menggunakan proyeksi Gonomonic yang disajikan oleh Charles Karnes dalam Algoritma untuk geodesik. Ada implementasi di Jawa yang tersedia dengan perpustakaan Barefoot: 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);

Untuk lebih jelasnya lihat jawabannya di sini: https://gis.stackexchange.com/a/184695/29490

Ini berfungsi untuk proyeksi jarak jauh ke garis besar tetapi juga perhitungan jarak dekat (lihat gambar).

masukkan deskripsi tautan di sini

sema
sumber