Skip to main content
edited tags
Link
Ian Turton
  • 83.2k
  • 6
  • 89
  • 189
naming
Source Link
Vince
  • 20.3k
  • 16
  • 48
  • 65

I am trying to build a polygon (with long/lat coordinates) over a line between two points (long/lat as well). Basically what I used is line buffering with meters as an distance. However

However I have noticed that my polygon is not exactly created with choosen buffer offset (e.g 100000m100km as buffer gives me like ~75km range polygon on openstreetmapOpenStreetMap). How can I achieve correct precision of buffer in meters?

I am trying to build a polygon (with long/lat coordinates) over a line between two points (long/lat as well). Basically what I used is line buffering with meters as an distance. However I have noticed that my polygon is not exactly created with choosen buffer offset (e.g 100000m as buffer gives me like ~75km range polygon on openstreetmap). How can I achieve correct precision of buffer in meters?

I am trying to build a polygon (with long/lat coordinates) over a line between two points (long/lat as well). Basically what I used is line buffering with meters as an distance.

However I have noticed that my polygon is not exactly created with choosen buffer offset (e.g 100km as buffer gives me like ~75km range polygon on OpenStreetMap). How can I achieve correct precision of buffer in meters?

Source Link

Buffer line between two coordinates with meters

I am trying to build a polygon (with long/lat coordinates) over a line between two points (long/lat as well). Basically what I used is line buffering with meters as an distance. However I have noticed that my polygon is not exactly created with choosen buffer offset (e.g 100000m as buffer gives me like ~75km range polygon on openstreetmap). How can I achieve correct precision of buffer in meters?

I am using Java GeoTools.

Line builder:

public GeoLineBuilder() throws SchemaException {
    this.lineSchema = DataUtilities.createType(
            "",
            "Location",
            "locations:LineString:srid=4326," + "id:Integer"
    );
}

SimpleFeature buildLine(List<LocationPoint> points) {
    SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(lineSchema);
    GeometryFactory geometryFactory = new GeometryFactory();
    List<Coordinate> coordinates = points.stream().map(point -> new Coordinate(point.getLongtitude(), point.getLatitude())).collect(Collectors.toList());
    LineString line = geometryFactory.createLineString(coordinates.toArray(new Coordinate[] {}));
    featureBuilder.add(line);
    return featureBuilder.buildFeature(null);
}

Polygon over the line with buffer in meters:

private SimpleFeature bufferLine(SimpleFeature feature, long distance) throws Exception {
    GeometryAttribute gProp = feature.getDefaultGeometryProperty();
    CoordinateReferenceSystem origCRS = gProp.getDescriptor()
            .getCoordinateReferenceSystem();

    Geometry geom = (Geometry) feature.getDefaultGeometry();
    Geometry pGeom = geom;
    MathTransform toTransform, fromTransform = null;

    if (!(origCRS instanceof ProjectedCRS)) {

        Point c = geom.getCentroid();
        double x = c.getCoordinate().x;
        double y = c.getCoordinate().y;

        String code = "EPSG:3857";
        CoordinateReferenceSystem auto = CRS.decode(code, true);
        toTransform = CRS.findMathTransform(
                DefaultGeographicCRS.WGS84, auto);
        fromTransform = CRS.findMathTransform(auto,
                DefaultGeographicCRS.WGS84);
        pGeom = JTS.transform(geom, toTransform);
    }

    Geometry out = pGeom.buffer(distance);
    Geometry retGeom = out;

    if (!(origCRS instanceof ProjectedCRS)) {
            retGeom = JTS.transform(out, fromTransform);
    }

    SimpleFeatureType schema = feature.getFeatureType();
    SimpleFeatureTypeBuilder ftBuilder = new SimpleFeatureTypeBuilder();
    ftBuilder.setCRS(origCRS);
    ftBuilder.addAll(schema.getAttributeDescriptors());
    ftBuilder.setName(schema.getName());

    SimpleFeatureType nSchema = ftBuilder.buildFeatureType();
    SimpleFeatureBuilder builder = new SimpleFeatureBuilder(nSchema);
    List<Object> atts = feature.getAttributes();
    for (int i = 0; i < atts.size(); i++) {
        if (atts.get(i) instanceof Geometry) {
            atts.set(i, retGeom);
        }
    }
    return builder.buildFeature(null, atts.toArray());
}

Basically:

  • I am building a line in EPSG:4326 to have a line with long/lat coordinates
  • I am doing an EPSG:4326 -> EPSG:3857 transformation to be able to buffer by meters
  • Actual buffering
  • Reverse transformation to coordinates EPSG:4326 <- EPSG:3857
  • Displaying received polygon on the openstreetmap map

I saw that when I choose Poznan and Paris coordinates as a line pair - received polygon was for sure smaller than selected buffering (100000 meters), it was like ~75000 meters instead.

How to approach this problem?