Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Geotools: bounding box for a buffer in wgs84

I am need a Java function that will generate a bounding box (rectangle) around a buffer. The buffer is defined by the center point (WGS84 coordinate) and the radius (in meters).

Getting a bounding box for a buffer in JTS seems to be quite simple:

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

This however is pure planar geometry. Is there a way to do this using a coordinate reference system with the distance given in meters?

Optimally with Geotools but other Java solutions will also work...

like image 688
daphshez Avatar asked Apr 06 '16 15:04

daphshez


2 Answers

Although you have approached it in another way, I have another solution for that. The results will be way more precise than with your proposed solution.

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

And here is the map with the result, buffer in red, envelope in black.

Buffer and envelope

like image 95
Eduardo Avatar answered Nov 02 '22 10:11

Eduardo


I ended up using a GeodeticCalculator to manually find the corners of the box. Frankly the results aren't very precise, but that's the best solution I found till now:

 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);
like image 45
daphshez Avatar answered Nov 02 '22 12:11

daphshez