Java 如何使用GeoTools创建具有纬度、经度和半径的圆?

Java 如何使用GeoTools创建具有纬度、经度和半径的圆?,java,geotools,Java,Geotools,现在我有: Polygon circle = geometryBuilder.circle( myLong, myLat, radiusInMeters, 10); 它创建了一个具有巨大纬度和经度的无意义多边形(lat=28.456306,long=-16.292034,radius=500),例如: POLYGON ((483.678055 28.482505000000003, 388.1865521874737 -265.4101211462366, 138.1865521874737

现在我有:

Polygon circle = geometryBuilder.circle(
myLong,
myLat, 
radiusInMeters, 10);
它创建了一个具有巨大纬度和经度的无意义多边形(lat=28.456306,long=-16.292034,radius=500),例如:

POLYGON ((483.678055 28.482505000000003, 388.1865521874737 -265.4101211462366, 138.1865521874737 -447.04575314757676, -170.8304421874737 -447.0457531475768, -420.8304421874737 -265.41012114623663, -516.321945 28.482504999999943, -420.83044218747375 322.3751311462365, -170.8304421874738 504.01076314757677, 138.18655218747358 504.0107631475768, 388.18655218747364 322.3751311462367, 483.678055 28.482505000000003))
我希望在我提供的中心点附近有十对坐标,分别是lat和long

任何帮助都会大有帮助。提前谢谢

编辑

除了@iant的答案,我还必须创建一个
作为
功能

//build the type
SimpleFeatureType TYPE = null;
try {
    TYPE = DataUtilities.createType("", "Location", "locations:Point:srid=4326," + "id:Integer" // a
            // number
            // attribute
            );
} catch (Exception e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
com.vividsolutions.jts.geom.Point point = geometryFactory.createPoint(
        new Coordinate(
                currentDevicePosition.getLongitude(), 
                currentDevicePosition.getLatitude()
                )
        );
featureBuilder.add(point);
SimpleFeature feature = featureBuilder.buildFeature( "fid.1" ); // build the 1st feature

正如在iant的要点中所解释的:这里:,哦,我还缺少一个依赖项,正如这里所解释的

有两种解决方案:

  • 将以米为单位的半径转换为度,并将问题视为平面问题

  • 将lat/lon点转换为米,计算局部平面投影中的圆,然后重新投影回lat/lon

  • 对于1,你可以做一些类似的事情,这对赤道附近的小半径很好:

    GeodeticCalculator calc = new  GeodeticCalculator(DefaultGeographicCRS.WGS84);
      calc.setStartingGeographicPoint(point.getX(), point.getY());
      calc.setDirection(0.0, 10000);
      Point2D p2 = calc.getDestinationGeographicPoint();
      calc.setDirection(90.0, 10000);
      Point2D p3 = calc.getDestinationGeographicPoint();
    
      double dy = p2.getY() - point.getY();
      double dx = p3.getX() - point.getX();
      double distance = (dy + dx) / 2.0;
      Polygon p1 = (Polygon) point.buffer(distance);
    
    我将展示第二个的一些代码,因为它更通用(即,它工作得更好,半径范围更好)

    首先,您需要找到一个局部投影,GeoTools提供了一个“伪”投影
    AUTO42001,x,y
    ,它是一个以x,y为中心的UTM投影:

    public SimpleFeature bufferFeature(SimpleFeature feature, Measure<Double, Length> distance) {
        // extract the geometry
        GeometryAttribute gProp = feature.getDefaultGeometryProperty();
        CoordinateReferenceSystem origCRS = gProp.getDescriptor().getCoordinateReferenceSystem();
    
        Geometry geom = (Geometry) feature.getDefaultGeometry();
        Geometry pGeom = geom;
        MathTransform toTransform, fromTransform = null;
        // reproject the geometry to a local projection
        if (!(origCRS instanceof ProjectedCRS)) {
    
          double x = geom.getCoordinate().x;
          double y = geom.getCoordinate().y;
    
          String code = "AUTO:42001," + x + "," + y;
          // System.out.println(code);
          CoordinateReferenceSystem auto;
          try {
            auto = CRS.decode(code);
            toTransform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, auto);
            fromTransform = CRS.findMathTransform(auto, DefaultGeographicCRS.WGS84);
            pGeom = JTS.transform(geom, toTransform);
    
          } catch (MismatchedDimensionException | TransformException | FactoryException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
    
        }
    
    然后,我们使用前面查找的反向变换投射回WGS84(lat/lon):

      retGeom = JTS.transform(out, fromTransform); 
    
    然后会有一点混乱来改变特征类型,以反映我们返回的是多边形而不是点的事实。完整的代码在这里

    当我运行它时,我得到以下输出:

    POINT (10.840378413128576 3.4152050343701745)
    POLYGON ((10.84937634426605 3.4151876838951822, 10.849200076653755 3.413423962919184, 10.84868480171117 3.4117286878605766, 10.847850322146979 3.4101670058279794, 10.846728706726902 3.4087989300555464, 10.845363057862208 3.407677033830687, 10.843805855306746 3.406844430298736, 10.84211693959797 3.406333115754347, 10.840361212705258 3.4061627400701946, 10.838606144204721 3.4063398515107184, 10.836919178768184 3.4068576449605277, 10.835365144548726 3.4076962232621035, 10.834003762019957 3.408823361646906, 10.832887348980522 3.410195745914279, 10.832058809914859 3.411760636805914, 10.831549986992338 3.4134578966399034, 10.831380436105858 3.4152223003379722, 10.831556675029052 3.416986042039048, 10.832071932633442 3.4186813409639054, 10.832906408849936 3.4202430463705085, 10.834028035422469 3.4216111414662183, 10.835393708241908 3.422733050021835, 10.836950943907517 3.4235656570147763, 10.838639896841123 3.424076965623486, 10.840395659406198 3.4242473268789406, 10.842150756595839 3.4240701947133396, 10.843837739370569 3.4235523773972796, 10.845391776937724 3.4227137757216988, 10.846753148314034 3.4215866180136185, 10.847869537398722 3.4202142214154887, 10.848698043354238 3.4186493270628633, 10.849206829051935 3.4169520731645546, 10.84937634426605 3.4151876838951822))
    

    GeometricShapeFactory shapeFactory=新的GeometricShapeFactory();shapeFactory.setNumPoints(64); 可调整形状系数设置中心(新坐标(纬度、经度));
    //长度以米为单位为1°

    从gist复制了整个函数和辅助缓冲区后,我如何将其称为具有多边形(或其GeoJSON定义)而不是特征?我想,但希望通过更改为投影,然后再次确认,能解释不同经度下米/纬度的差异吗?另外,#1会更有效吗?如果你不得不这样做100万次呢?@jonayreyes你可以在
    geom
    从featuratanks@iant中提取之前跳过这个部分,不管怎样,你能在#1上再多说一点吗?我对Geotools相当陌生,但无论如何,我如何将“米半径”更改为度?好了,a应该是一对点,或者一个震级,我不知道如何将它转换成“双半径”是经度和纬度在中心坐标中混在一起的吗?请解释一下你的答案。
    POINT (10.840378413128576 3.4152050343701745)
    POLYGON ((10.84937634426605 3.4151876838951822, 10.849200076653755 3.413423962919184, 10.84868480171117 3.4117286878605766, 10.847850322146979 3.4101670058279794, 10.846728706726902 3.4087989300555464, 10.845363057862208 3.407677033830687, 10.843805855306746 3.406844430298736, 10.84211693959797 3.406333115754347, 10.840361212705258 3.4061627400701946, 10.838606144204721 3.4063398515107184, 10.836919178768184 3.4068576449605277, 10.835365144548726 3.4076962232621035, 10.834003762019957 3.408823361646906, 10.832887348980522 3.410195745914279, 10.832058809914859 3.411760636805914, 10.831549986992338 3.4134578966399034, 10.831380436105858 3.4152223003379722, 10.831556675029052 3.416986042039048, 10.832071932633442 3.4186813409639054, 10.832906408849936 3.4202430463705085, 10.834028035422469 3.4216111414662183, 10.835393708241908 3.422733050021835, 10.836950943907517 3.4235656570147763, 10.838639896841123 3.424076965623486, 10.840395659406198 3.4242473268789406, 10.842150756595839 3.4240701947133396, 10.843837739370569 3.4235523773972796, 10.845391776937724 3.4227137757216988, 10.846753148314034 3.4215866180136185, 10.847869537398722 3.4202142214154887, 10.848698043354238 3.4186493270628633, 10.849206829051935 3.4169520731645546, 10.84937634426605 3.4151876838951822))
    
        double latitude = 40.689234d;
        double longitude = -74.044598d;
        double diameterInMeters = 2000d; //2km
    
        GeometricShapeFactory shapeFactory = new GeometricShapeFactory();
        shapeFactory.setNumPoints(64); // adjustable
        shapeFactory.setCentre(new Coordinate(latitude, longitude));
        // Length in meters of 1° of latitude = always 111.32 km
        shapeFactory.setWidth(diameterInMeters/111320d);
        // Length in meters of 1° of longitude = 40075 km * cos( latitude ) / 360
        shapeFactory.setHeight(diameterInMeters / (40075000 * Math.cos(Math.toRadians(latitude)) / 360));
    
        Polygon circle = shapeFactory.createEllipse();