【问题标题】:Geotools: bounding box for a buffer in wgs84Geotools:wgs84 中缓冲区的边界框
【发布时间】:2016-04-06 15:03:04
【问题描述】:

我需要一个 Java 函数,它会在缓冲区周围生成一个边界框(矩形)。缓冲区由中心点(WGS84 坐标)和半径(以米为单位)定义。

在 JTS 中获取缓冲区的边界框似乎很简单:

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

然而,这是纯平面几何。有没有办法使用距离以米为单位的坐标参考系来做到这一点?

最适合使用 Geotools,但其他 Java 解决方案也可以工作......

【问题讨论】:

    标签: java geospatial geotools jts


    【解决方案1】:

    尽管您以另一种方式处理它,但我有另一种解决方案。结果将比您提出的解决方案更精确。

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

    这是带有结果的地图,红色为缓冲区,黑色为信封。

    【讨论】:

    • 这太棒了!在我读到这篇文章之前,我无法将我的缓冲区半径投影为一个完美的圆——它是一个椭圆。
    【解决方案2】:

    我最终使用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);
    

    【讨论】:

      【解决方案3】:

      这是我用来生成边界框坐标的简单解决方案,我使用 GeoNames citieJSON API 从 gps 十进制坐标获取附近的大城市。

      这是来自我的 GitHub 存储库的 Java 方法:FusionTableModifyJava

      我有一个十进制的 GPS 位置,我需要找到该位置“附近”的最大城市/州。我需要一个相对准确的边界框来传递给 cityJSON GeoNames 网络服务,以获取该边界框中最大的城市。我传递了我感兴趣的位置和“半径”(以公里为单位),它返回传递给 cityJSON 所需的北、南、东、西十进制坐标。

      (我发现这些资源对我的研究很有用:

      Calculate distance, bearing and more between Latitude/Longitude points.

      Longitude - Wikipedia)

      它不是超级准确,但对于我使用它的用途来说足够准确:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-07-07
        • 1970-01-01
        • 2016-09-01
        • 2021-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-23
        相关资源
        最近更新 更多