Encontrando distância perpendicular e vetor perpendicular mínimo entre ponto e linha usando GeoTools e JTS?


8

Eu tenho uma linha formada por 2 pares lat / lon e lat / lon de um ponto. Gostaria de descobrir a distância perpendicular entre a linha e o ponto na superfície da Terra (pode assumir a Terra como grande esfera) e o vetor perpendicular mínimo (ou seja, o "ponto cruzado" projetado na linha).

Estou tentando usar o Geotools 8.0 e o JTS para isso. Abaixo capturou meu código de teste:

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

os métodos createPoint () e 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;
}

No entanto, o resultado de "isOnLine ()" retorna falso. Eu queria saber se há algo errado.

Existe algo errado com o meu método de verificação ou, na verdade, a maneira como eu costumava descobrir a distância perpendicular e o "ponto de cruzamento" na superfície da Terra não está correta?


Você já tentou usar PrecisionModel.FIXED? Não posso comentar o restante do seu código, mas uma precisão dupla pode introduzir erros. Consulte Robustez e precisão nas perguntas frequentes do JTS.
hepiladron

@ Hepiladron, Obrigado pela sua sugestão. Tentei usar o PrecisionModel.FIXED, mas ainda assim obtive o mesmo resultado ...
xlogger 7/10/12

Para futuros leitores - é improvável que isso funcione para você, pois o JTS assume uma estrutura cartesiana e não lida com geometria esférica.
Ian Turton

Respostas:



3

Há também uma solução usando projeção Gonomonic apresentada por Charles Karnes em Algoritmos para geodésica. Existe uma implementação em Java disponível na biblioteca 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);

Para obter mais detalhes, consulte a resposta aqui: https://gis.stackexchange.com/a/184695/29490

Ele funciona para projeções de grandes distâncias ponto a linha, mas também cálculos de distâncias próximas (veja imagens).

insira a descrição do link aqui

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.