I've been spending some days trying to find the best way to do a "rigid translate" of a polygon in a certain direction and distance, without much luck. To provide an example, consider translate like moving a polygon on 30 degrees south, for 500 meters.

Is there any API in Java GeoTools that you have used successfully to do such moving of a polygon?

If not for the polygon as a whole in one operation, I can do a single point translation for each point of the polygon, if no better solution can be found. I don't need to do this real time, so I have processing time to spend to do this.

The approach I'm following so far is of calculating the shifting on the single point as for this link to the geodetic calculator

In the specific the part called:

Generate location away from a point

    `GeodeticCalculator calc = new GeodeticCalculator();
    // mind, this is lon/lat
    calc.setStartingGeographicPoint(45.4644, 9.1908);
    calc.setDirection(90 /* azimuth */, 200 /* distance */);
    Point2D dest = calc.getDestinationGeographicPoint();
    System.out.println("Longitude: " + dest.getX() + " Latitude: " + dest.getY());`
  • 2
    Assuming a Cartesian coordinate system, you need only calculate dx and dy values from bearing and distance, to be applied to all vertices. – Vince Apr 21 at 23:54
  • JTS affine transformation translate - locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/… – Ian Turton Apr 22 at 7:46
  • @IanTurton the affine transform I need to compare with the geodetic calculator to see if it works with a geometry, as if I have to calculate for each point of the polygon, it may be too much calculation. – caramelleas Apr 22 at 15:53

You can use the JTS affine transformation if (and only if) you are working in a cartesian coordinate system, so if you are using a geographic coordinate system (i.e lat,lon) you will first need to reproject to a local crs. Then you can apply a translate in metres and finally reproject back to geographic coordinates.

Polygon p = GenerateRandomData.createRandomPolygon(5);
Point c = p.getCentroid();
double x = c.getCoordinate().x;
double y = c.getCoordinate().y;
String code = "AUTO:42001," + y + "," + x;
// System.out.println(code);
CoordinateReferenceSystem auto = CRS.decode(code);
// System.out.println(auto);
MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, auto);
MathTransform inverseTransform = CRS.findMathTransform(auto, DefaultGeographicCRS.WGS84);
Geometry cp = JTS.transform(p, transform);
// System.out.println(cp);
AffineTransformation affine = new AffineTransformation();
affine = affine.translate(5000, 0);
Geometry tp = affine.transform(cp);
// System.out.println(tp);
Geometry np = JTS.transform(tp, inverseTransform);

Will produce the following (moving the polygon 5km East):


If you are working with a distance and bearing then you need to calculate the X, Y offset (here I'm doing the whole circle to check my code):

 double distance = 20000; // 20km
    for (int i = 45; i <= 360; i += 45) {
      double bearing = 360 * (i / 360.0);
      double rBearing = Math.toRadians(bearing);
      double dx = distance * Math.cos(rBearing);
      double dy = distance * Math.sin(rBearing);
      AffineTransformation affine = new AffineTransformation();
      affine = affine.translate(dx, dy);
      Geometry tp = affine.transform(cp);
      Geometry np = JTS.transform(tp, inverseTransform);

enter image description here

  • Thanks @Ian Turton, so far by points I get similar result, but it is by points transform that is far less elegant and optimized by your approach. I'm going to test the same. Thanks, I will update once I have tested. – caramelleas Apr 22 at 22:32
  • Sorry @Ian Turton, but the 5000 is a distance, while zero is not the bearing in degrees, is a distance as well on the other coordinate, am I right ? – caramelleas Apr 22 at 22:55
  • that is an X and Y distance – Ian Turton Apr 23 at 8:49
  • see the answer I posted to myself :). – caramelleas Apr 23 at 8:53

quick update on this: at the end I came up writing the method below. I'm still investigating on applying the affine transform to have a better and more elegant solution, but in the meanwhile this code does the job.

 * Translate a source geometry by distance and bearing
 * @param source is the source geometry
 * @param bearing is the bearing in degrees
 * @param distance is the distance in meters
 * @return a geometry that is the translation of the passed in geometry
private Geometry translateGeometry(Geometry source, long distance, int bearing) throws Exception{
    Geometry translatedPolygon = null;

      GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();

      Coordinate[] translatedPolygonCoordinates  = new Coordinate[unionGeometry.getCoordinates().length];
      GeodeticCalculator geodeticCalculator = new GeodeticCalculator();
      Point2D aDestination = null;
      Coordinate aCoordinate = null;

       for(int i=0; i < unionGeometry.getCoordinates().length; i++){           
              // mind, this is lon/lat
              //Lon = x
              //Lat = y
              geodeticCalculator.setStartingGeographicPoint(unionGeometry.getCoordinates()[i] .getX(), unionGeometry.getCoordinates()[i] .getY()); 
              geodeticCalculator.setDirection(bearing /* azimuth */, distance /* distance */);
              aDestination = geodeticCalculator.getDestinationGeographicPoint();
              aCoordinate = new Coordinate(aDestination.getX(), aDestination.getY());
              translatedPolygonCoordinates[i] = aCoordinate;               

      LinearRing ring = geometryFactory.createLinearRing(translatedPolygonCoordinates);
      LinearRing holes[] = null; // use LinearRing[] to represent holes
      Polygon polygon = geometryFactory.createPolygon(ring, holes);
      translatedPolygon = polygon;

     return translatedPolygon;      
  • 1
    This will probably give the wrong answer for large polygons or large offsets as you aren't accounting for the curved nature of the Earth – Ian Turton Apr 23 at 9:08
  • Yes, I agree, in fact I'm still looking on a better way to do this, unfortunately I presume I will still have to stay on single points loop but accounting for transformation somehow, as I need bearing degrees and I cannot find any other solution so far. Not sure if converting y into radiants or something like that may help. By now I know my polygons will not have holes (although I could handle them) and they will always be small enough to not care about curved earth. – caramelleas Apr 23 at 9:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.