How to use GeometricShapeFactory in geoTools to create a Circle on map

前端 未结 2 885
既然无缘
既然无缘 2021-01-16 10:20

I am currently using the below code to create a GeoJson Polygon. this gives me a bad circle which is not valid...

in this case RADIUS = 1609.34 , which

相关标签:
2条回答
  • 2021-01-16 10:42

    Your output circle is valid, it just happens to exceed the diameter of the Earth's surface so your GIS may have issues drawing it! The problem is that you are mixing degrees and meters indiscriminately and GeoTools has no clue what you want it to do.

    You need to add some information about the coordinate reference system of the point to the program, and if that projection is geographic (i.e. in degrees), transform the problem to a projection that is in meters.

    public Geometry bufferPoint(Measure<Double, Length> distance, CoordinateReferenceSystem origCRS, Geometry geom) {
        Geometry pGeom = geom;
        MathTransform toTransform, fromTransform = null;
        // reproject the geometry to a local projection
        Unit<Length> unit = distance.getUnit();
        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);
            unit = SI.METER;
          } catch (MismatchedDimensionException | TransformException | FactoryException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
    
        } else {
          unit = (Unit<Length>) origCRS.getCoordinateSystem().getAxis(0).getUnit();
    
        }
    
    
        // buffer
        Geometry out = pGeom.buffer(distance.doubleValue(unit));
        Geometry retGeom = out;
        // reproject the geometry to the original projection
        if (!(origCRS instanceof ProjectedCRS)) {
          try {
            retGeom = JTS.transform(out, fromTransform);
    
          } catch (MismatchedDimensionException | TransformException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        }
        return retGeom;
      }
    

    AUTO:42001,x,y is a special projection centred on the point x,y in meters that allows us to use the JTS buffer method which is easier than the circle operation you are using.

    For your inputs this gives me an ellipse over New York, note this is expected and is due to the distorting effects of using unprojected Lat/Lon coordinates on a curved Earth.

    You can call it using:

    //Measure<Double, Length> dist = Measure.valueOf(50.0, SI.KILOMETER);
    Measure<Double, Length> dist = Measure.valueOf(1.0, NonSI.MILE);
    GeometryFactory gf = new GeometryFactory();
    Point p = gf.createPoint(new Coordinate(-73.87,40.84));
    buf.bufferPoint(dist, DefaultGeographicCRS.WGS84, p);
    

    0 讨论(0)
  • 2021-01-16 10:46
        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();
    

    result

    0 讨论(0)
提交回复
热议问题