[GIS] Create dynamic circle/polygon from specific lat/long using GeoTools

geotools

I have a dataset of lat/long that I would like to match on dynamically generated circle/polygon from specific point with different radius.

I have already completed how to match lat/long with custom defined boundaries in a shapefile using GeoTools.

Now, instead of using boundaries defined in a custom shapefile, I would like to do following steps

  1. Find centroid of the boundary (polygon)

  2. Using centroid lat/long, create multiple circles/polygon with radius 5, 10 and 15 miles like 5 miles = Polygon1, 10 miles = Polygon2 15 miles = Polygon3

  3. Match dataset of lat/long to see how many points lie in
    Polygon1, Polygon2 and Polygon3.

Best Answer

To buffer the point the best way is to transform your feature to a projected crs and then use the JTS buffer operation. To create a 10 mile length use Quantity<Length> dist = Quantities.getQuantity(10.0, USCustomary.MILE);

  public Geometry bufferPoint(Quantity<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(origCRS, auto);
        fromTransform = CRS.findMathTransform(auto, origCRS);
        pGeom = JTS.transform(geom, toTransform);
        unit = SI.METRE;
      } catch (MismatchedDimensionException | TransformException | FactoryException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

    } else {
      unit = (Unit<Length>) origCRS.getCoordinateSystem().getAxis(0).getUnit();

    }
    UnitConverter converter = distance.getUnit().getConverterTo(unit);
    // buffer
    Geometry out = pGeom.buffer(converter.convert(distance.getValue()).doubleValue());
    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;
  }

For a quick and dirty buffer you can use the GeodeticCalculator to fudge the X/Y distortion and hope for the best.

  public Geometry simpleBuffer(Quantity<Length> distance,Point point) {
    GeodeticCalculator calc = new  GeodeticCalculator(DefaultGeographicCRS.WGS84);
    calc.setStartingGeographicPoint(point.getX(), point.getY());
    UnitConverter converter = distance.getUnit().getConverterTo(SI.METRE);
    double d = converter.convert(distance.getValue()).doubleValue();
    calc.setDirection(0.0, d);
    Point2D p2 = calc.getDestinationGeographicPoint();
    calc.setDirection(90.0, d);
    Point2D p3 = calc.getDestinationGeographicPoint();

    double dy = p2.getY() - point.getY();
    double dx = p3.getX() - point.getX();
    double dist = (dy + dx) / 2.0;
    Polygon p1 = (Polygon) point.buffer(dist);
    return p1;
  }

Here's the results the stripy polygon is the "correct" buffer, the orange one is the simple one using lat/lon.

enter image description here