public static Geometry snapAndFixPolygon(Geometry geom, PrecisionModel tilePrecision, Stats stats, String stage)
    throws GeometryException {
    try {
      if (!geom.isValid()) {
        geom = fixPolygon(geom);
        stats.dataError(stage + "_snap_fix_input");
      }
      return GeometryPrecisionReducer.reduce(geom, tilePrecision);
    } catch (TopologyException | IllegalArgumentException e) {
      // precision reduction fails if geometry is invalid, so attempt
      // to fix it then try again
      geom = GeometryFixer.fix(geom);
      stats.dataError(stage + "_snap_fix_input2");
      try {
        return GeometryPrecisionReducer.reduce(geom, tilePrecision);
      } catch (TopologyException | IllegalArgumentException e2) {
        // give it one last try but with more aggressive fixing, just in case (see issue #511)
        geom = fixPolygon(geom, tilePrecision.gridSize() / 2);
        stats.dataError(stage + "_snap_fix_input3");
        try {
          return GeometryPrecisionReducer.reduce(geom, tilePrecision);
        } catch (TopologyException | IllegalArgumentException e3) {
          stats.dataError(stage + "_snap_fix_input3_failed");
          throw new GeometryException("snap_third_time_failed", "Error reducing precision");
        }
      }
    }
  }
Returns a copy of {@code geom} with coordinates rounded to {@code #tilePrecision} and fixes any polygon
self-intersections or overlaps that may have caused.

@throws GeometryException if an unrecoverable robustness exception prevents us from fixing the geometry
planetiler-core/src/main/java/com/onthegomap/planetiler/geo/GeoUtils.java