Search code examples
javageolocationgeometrygistopology

How to determine area based on shape bounded by latitude and longitude?


Given an approximate "rectangle" bounded by certain values of latitudes and longitudes expressed in degrees, what would be the best way using a common Java Geometry/Topology library such as JTS(https://github.com/locationtech/jts), to find the approximate area of the rectangle expressed in meters/feet squared?

Assumptions:

  • The rectangle's area will have an upper bound of ~300-500 kilometers^2
  • Assuming a tolerance of error of ~ +/- 500-1500 meters^2
  • Must use Java (Currently on Java11)
  • Any common Java Geo/GIS/Topology library is acceptable
  • Assume coordinates will be constrained to areas within the Continental USA

Example

Below is an example shape which is an approximate rectangle covering the area occupied by a park: Example Shape


Solution

  • You need to make use of a library that can handle reprojection from spherical degrees to a locally planar reference system so you can use JTS to do the calculations.

    This question on gis.stackexchange.com gives a longer general example of how to do this using the GeoTools library.

    Since you are constraining your question to the continental USA you have an easier problem and can use a fixed projection such as US National Atlas Equal Area (EPSG:2163) so a method like:

      private Measure<Double, Area> calcArea(Polygon p) {
        try {
          String code = "EPSG:2163";
          CoordinateReferenceSystem auto = CRS.decode(code);
    
          MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, auto);
    
          Polygon projed = (Polygon) JTS.transform(p, transform);
          return Measure.valueOf(projed.getArea(), SI.SQUARE_METRE);
        } catch (MismatchedDimensionException | TransformException | FactoryException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
        return Measure.valueOf(0.0, SI.SQUARE_METRE);
      }
    

    You can then call it with something like where polygon is a JTS Polygon in lat/lon:

    Unit<Area> sq_mile = USCustomary.MILE.multiply(USCustomary.MILE).asType(Area.class);
    Unit<Area> sq_km = MetricPrefix.KILO(SI.METRE).multiply(MetricPrefix.KILO(SI.METRE)).asType(Area.class);
    
    javax.measure.Quantity<Area> a = me.calcArea(polygon);
    System.out.println(a);
    System.out.println(a.to(sq_km));
    System.out.println(a.to(sq_mile));