Geotools: ограничивающая рамка для буфера в wgs84

Мне нужна функция Java, которая будет генерировать ограничивающую рамку (прямоугольник) вокруг буфера. Буфер определяется центральной точкой (координата WGS84) и радиусом (в метрах).

Получение ограничивающей рамки для буфера в JTS кажется довольно простым:

Point center = ....
Geometry boundingBox = center.buffer(...).getEnvelope();

Однако это чистая планарная геометрия. Есть ли способ сделать это, используя систему отсчета координат с расстоянием, указанным в метрах?

Оптимально с Geotools, но другие Java-решения также будут работать...


person daphshez    schedule 06.04.2016    source источник


Ответы (3)


Хотя вы подошли к этому по-другому, у меня есть другое решение для этого. Результаты будут намного точнее, чем с предложенным вами решением.

GeometryFactory GEOMETRY_FACTORY = JTSFactoryFinder.getGeometryFactory();

// Remember, order is (longitude, latitude)
Coordinate center = Coordinate(2.29443, 48.85816);
Point point = GEOMETRY_FACTORY.createPoint(center);

// Buffer 50KM around the point, then get the envelope
Envelope envelopeInternal = buffer(point, 50000).getEnvelopeInternal();

// Then you can play with the envelope, e.g.,
double minX = envelopeInternal.getMinX();
double maxX = envelopeInternal.getMaxX();

// The buffer using distanceInMeters
private Geometry buffer(Geometry geometry, double distanceInMeters) throws FactoryException, TransformException {
     String code = "AUTO:42001," + geometry.getCentroid().getCoordinate().x + "," + geometry.getCentroid().getCoordinate().y;
     CoordinateReferenceSystem auto = CRS.decode(code);

     MathTransform toTransform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, auto);
     MathTransform fromTransform = CRS.findMathTransform(auto, DefaultGeographicCRS.WGS84);

     Geometry pGeom = JTS.transform(geometry, toTransform);
     Geometry pBufferedGeom = pGeom.buffer(distanceInMeters);
     return JTS.transform(pBufferedGeom, fromTransform);
}

А вот и карта с результатом, красный буфер, черный конверт.

Буфер и конверт

person Eduardo    schedule 14.11.2017
comment
Это здорово! Я просто не мог спроецировать свой радиус буфера как идеальный круг, пока не прочитал это - это был эллипс. - person Scott; 19.01.2019

В итоге я использовал GeodeticCalculator, чтобы вручную найти углы коробки. Честно говоря, результаты не очень точны, но это лучшее решение, которое я нашел до сих пор:

 GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
 CoordinateReferenceSystem wgs84 = DefaultGeographicCRS.WGS84;
 GeodeticCalculator geodeticCalculator = new GeodeticCalculator(wgs84);
 geodeticCalculator.setStartingGeographicPoint(center.getX(), center.getY());
 Coordinate[] coordinates = new Coordinate[5];
 for (int i = 0; i < 4; i++) {
    geodeticCalculator.setDirection(-180 + i * 90 + 45, bufferRadiusMeters * Math.sqrt(2));
    Point2D point2D = geodeticCalculator.getDestinationGeographicPoint();
    coordinates[i] = new Coordinate(point2D.getX(), point2D.getY());
 }
 coordinates[4] = coordinates[0];
 Polygon box = geometryFactory.createPolygon(coordinates);
person daphshez    schedule 13.04.2016

Вот простое решение, которое я использовал для создания координат ограничивающей рамки, которые я использую с GeoNames citieJSON API. чтобы получить близлежащие крупные города по десятичной координате GPS.

Это метод Java из моего репозитория GitHub: FusionTableModifyJava

У меня было десятичное местоположение GPS, и мне нужно было найти самый большой город/штат «рядом» с этим местоположением. Мне нужна была относительно точная ограничительная рамка, чтобы передать ее веб-сервису cityJSON GeoNames, чтобы вернуть самый большой город в этой ограничительной рамке. Я передаю местоположение и интересующий меня «радиус» (в км), и он возвращает десятичные координаты севера, юга, востока и запада, необходимые для перехода к городамJSON.

(Я нашел эти ресурсы полезными при проведении моего исследования:

Расчет расстояния, азимута и других параметров между точками широты/долготы.

Долгота — Википедия)

Это не супер точно, но достаточно точно для того, для чего я его использовал:

    // Compute bounding Box coordinates for use with Geonames API.
    class BoundingBox
    {
        public double north, south, east, west;
        public BoundingBox(String location, float km)
        {
             //System.out.println(location + " : "+ km);
            String[] parts = location.replaceAll("\\s","").split(","); //remove spaces and split on ,

            double lat = Double.parseDouble(parts[0]);
            double lng = Double.parseDouble(parts[1]);

            double adjust = .008983112; // 1km in degrees at equator.
            //adjust = 0.008983152770714983; // 1km in degrees at equator.

            //System.out.println("deg: "+(1.0/40075.017)*360.0);


            north = lat + ( km * adjust);
            south = lat - ( km * adjust);

            double lngRatio = 1/Math.cos(Math.toRadians(lat)); //ratio for lng size
            //System.out.println("lngRatio: "+lngRatio);

            east = lng + (km * adjust) * lngRatio;
            west = lng - (km * adjust) * lngRatio;
        }

    }
person Greg Kendall    schedule 05.06.2018