如何使用GeoTools创建具有纬度,经度和半径的圆? [英] How do I create a circle with latitude, longitude and radius with GeoTools?

查看:247
本文介绍了如何使用GeoTools创建具有纬度,经度和半径的圆?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

现在我有:

 多边形圆= 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))

我希望在我提供的中心点附近有十对经度和纬度坐标.

任何帮助都将多于帮助.预先感谢!

编辑

除了@iant的答案外,我还必须创建一个 Point 作为 Feature

 //建立类型SimpleFeatureType TYPE = null;尝试 {TYPE = DataUtilities.createType(","Location","locations:Point:srid = 4326," +"id:Integer"//a//数字//属性);} catch(Exception e1){//TODO自动生成的catch块e1.printStackTrace();}SimpleFeatureBuilder featureBuilder =新的SimpleFeatureBuilder(TYPE);GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();com.vividsolutions.jts.geom.Point point = geometryFactory.createPoint(新坐标(currentDevicePosition.getLongitude(),currentDevicePosition.getLatitude()));featureBuilder.add(point);SimpleFeature功能= featureBuilder.buildFeature("fid.1");//建立第一个功能 

如iant的要旨中所述: https://gitlab.com/snippets/17558 和此处: http://docs.geotools.org/,哦,我也缺少依赖项,因为在 SchemaException in Java

中进行了解释

解决方案

对此有两种解决方案:

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

  2. 将纬度/经度点转换为米,在局部平面投影中计算圆,然后重新投影回纬度/经度.

对于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();dy = p2.getY()-point.getY();double dx = p3.getX()-point.getX();双倍距离=(dy + dx)/2.0;多边形p1 =(多边形)point.buffer(distance); 

由于第二个代码比较笼统,所以我将显示一些代码(即,它工作得更好,并且半径范围更广).

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

 公共SimpleFeature bufferFeature(SimpleFeature功能,度量距离){//提取几何GeometryAttribute gProp = feature.getDefaultGeometryProperty();CoordinateReferenceSystem origCRS = gProp.getDescriptor().getCoordinateReferenceSystem();几何geom =(Geometry)feature.getDefaultGeometry();几何pGeom = geom;MathTransform toTransform,fromTransform = null;//将几何重新投影为局部投影if(!(ProjectedCRS的origCRS实例)){双x = geom.getCoordinate().x;双重y = geom.getCoordinate().y;字符串代码="AUTO:42001," + x +," + y;//System.out.println(code);CoordinateReferenceSystem自动;尝试 {自动= CRS.decode(代码);toTransform = CRS.findMathTransform(DefaultGeographicCRS.WGS84,自动);fromTransform = CRS.findMathTransform(auto,DefaultGeographicCRS.WGS84);pGeom = JTS.transform(geom,toTransform);} catch(MismatchedDimensionException | TransformException | FactoryException e){//TODO自动生成的catch块e.printStackTrace();}} 

因此,现在 pGeom 是我们的米数.缓冲起来现在很容易

 几何输出= bufferFeature(pGeom,distance.doubleValue(SI.METER)); 

然后,使用我们之前查找的反向变换将其投影回WGS84(纬度/经度):

  retGeom = JTS.transform(out,fromTransform); 

然后会有一些混乱,以更改要素类型,以反映我们返回的是多边形而不是Point的事实.完整代码位于此要点中.

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

  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.42356565704734062403890897608947133396、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) 

Right now I have:

Polygon circle = geometryBuilder.circle(
myLong,
myLat, 
radiusInMeters, 10);

And it creates (with lat=28.456306, long=-16.292034 and radius=500) a nonsense polygon with huge latitudes and longitudes, such as:

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

I expected to have ten pairs of coordinates with lat's and long's nearby the center point I supplied.

Any help would be more than helpful. Thanks in advance!

EDIT

In addition to @iant 's answer, I had to create a Point as a Feature

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

as explained in iant's Gist here: https://gitlab.com/snippets/17558 and here: http://docs.geotools.org/, oh, and also I was missing a dependency as explained here SchemaException in java

解决方案

There are two solutions to this:

  1. Convert the radius in meters to degrees and treat the problem as a planar problem

  2. Convert the lat/lon point to meters, calculate the circle in a locally planar projection and reproject back to lat/lon.

For 1 you could do something like which will be fine for small radii near the equator:

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

I'll show some code for the second as it is more general (i.e. it works better and for a better range of radii).

First you need to find a local projection, GeoTools provides a "pseudo" projection AUTO42001,x,y which is a UTM projection centred at X,Y:

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

    }

So now pGeom is our point in metres. Buffering it is now easy

  Geometry out = bufferFeature(pGeom, distance.doubleValue(SI.METER)); 

then we project back to WGS84 (lat/lon) using the reverse transform we looked up earlier:

  retGeom = JTS.transform(out, fromTransform); 

There is then a little messing around to change the feature type to reflect the fact we are returning a polygon instead of a Point. The full code is in this gist.

When I run it I get the following output:

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

这篇关于如何使用GeoTools创建具有纬度,经度和半径的圆?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆