可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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...
回答1:
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);
回答2:
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.

回答3:
Here is a simple solution that I used to generate bounding box coordinates that I use with GeoNames citieJSON API to get nearby big cities from a gps decimal coordinate.
This is a Java method from my GitHub repository: FusionTableModifyJava
I had a decimal GPS location and I needed to find the biggest city/state "near" that location. I needed a relatively accurate bounding box to pass to the citiesJSON GeoNames webservice to get back the biggest city in that bounding box. I pass the location and the "radius" I am interested in (in km) and it gives back the north, south, east, west decimal coordinates needed to pass to citiesJSON.
(I found these resources useful in doing my research:
Calculate distance, bearing and more between Latitude/Longitude points.
Longitude - Wikipedia)
It is not super accurate but accurate enough for what I was using it for:
// 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; } }