1

I have a line that is drawn on a map.
I want to find 2 parallel lines with this one, one at 50m above this and one at 50m below this. Something like in the picture below

1]

In the end I want to transform the line in a rectangle of width 100m.

I have tried some implementations, but I can't get it right.

How can I achieve this, keeping in mind that the line can have a length of hundreds of kilometers?

Edit:

  function getBearing(a, b) {
    const TWOPI = 6.2831853071795865;
    const RAD2DEG = 57.2957795130823209;
    var theta = Math.atan2(b.lat - a.lat, a.lng - b.lng);
    if (theta < 0.0)
      theta += TWOPI;
    console.log(a, b);
    return RAD2DEG * theta;
  }

  function getPolygonForLine(start, end, distance) {
    var bearing = getBearing(start, end);
    distance /= 2;
    var dx = distance * Math.cos(bearing);
    var dy = distance * Math.sin(bearing);

    var delta = {
      lat: dx / (111320 * Math.cos(start.lat)),
      lng: dy / 110540
    };

    var bounds = [
      L.polygon(getBoundsForPoint(start, delta)).getBounds(),
    ];

    var points = [];
    _.forEach(bounds, function(val) {
      points.push(
        val.getNorthEast(),
        val.getNorthWest(),
        val.getSouthWest(),
        val.getSouthEast()
      );
    });
  }

  function getBoundsForPoint(point, delta) {
    var points = [
      [
        point.lat + delta.lat,
        point.lng + delta.lng
      ],
      [
        point.lat - delta.lat,
        point.lng - delta.lng
      ],
      [
        point.lat + delta.lat,
        point.lng - delta.lng
      ],
      [
        point.lat - delta.lat,
        point.lng + delta.lng
      ],
      [
        point.lat - delta.lat,
        point.lng
      ],
      [
        point.lat + delta.lat,
        point.lng
      ],
      [
        point.lat,
        point.lng - delta.lng
      ],
      [
        point.lat,
        point.lng + delta.lng
      ]
    ];
    return points;
  }

This is the code that I have at the moment(I left only the code that calculates one end of the line). The problem is that the rectangle seems to not have the desired width and it also does not form a 90 degree angle with the line (it is parallel with the edge of the screen).

2
  • What kind of implementations have you tried? What was the problem with them?
    – user30184
    Commented Sep 20, 2016 at 11:28
  • Added the code, see the edit.
    – N Alex
    Commented Sep 20, 2016 at 11:53

4 Answers 4

1

Have you tried creating a 50m buffer around the line? I believe this tool should be available on almost any kind of GIS software.

4
  • I can only add a buffer in pixels, and that does not help me because I need the new rectangle coordinates.
    – N Alex
    Commented Sep 20, 2016 at 11:53
  • May I know what software are you using for this task? Is the line in raster format?
    – FichurClas
    Commented Sep 20, 2016 at 11:56
  • I am using leaflet. It is not.
    – N Alex
    Commented Sep 20, 2016 at 11:58
  • I have never used this library. Have you tried doing this using GIS sofware such as QGIS?
    – FichurClas
    Commented Sep 20, 2016 at 12:44
1

Doing this well is difficult because...

keeping in mind that the line can have a length of hundreds of kilometers

...geodesy is hard.

One approach to solve this would be to use geographiclib to calculate the azimuth from the both points to each other (by solving an inverse geodesic problem).

Once that's done, add (or subtract) 90 degrees from the azimuth of the start endpoint, and solve a direct geodesic problem with the desired distance. Repeat with -90 degrees and the other endpoint for a total of four points, which will form two lines.

Now, these endpoints will be apart from the original endpoints by the desired distance, but the lines themselves will have a larger separation (because geodesy is hard).

Also note that if the two endpoints are exactly 180° apart, the problem will have no solution (or infinite solutions).


Another solution would be to calculate the great circle that your line is in (assuming that the earth is spherical and not a geoid; once again geodesy is hard).

Now, there is no such thing as a great circle parallel to another great circle, as illustrated in wikipedia.

So the closest that you can get in that case is calculate the plane that the great circle belongs to, then calculate a parallel plane, then calculate the intersection of that plane and the spherical surface, then reproject that back to whatever map projection you're using.

But, as the intersection is not a great circle, it cannot be reprojected as a line... but as a curve arc. Geodesy is hard.

0

You could use something like Turf.js to buffer your line. The only tricky bit is that it will try to round off the ends of the lines but it should be trivial to snip that part of the code (it may even have a flat end option but I can't tell from the docs.)

1
  • I implemented using the buffer function from Turf.js but it has a bug. Do you know any other library with the same functionality?
    – N Alex
    Commented Sep 21, 2016 at 0:05
0

I am sure you would have got your answer already but I came across this post when I am trying to figure out how to find a polygon around a line, so that I could trick javafx to send click events to leaflet (issue with javafx not being able to send events to line strokes).

Here is what I did to find the parallel line using leaflet plugins.

References: Example & Source

function getPolygonForLine(start, end, distance) {
    var linecoords = [start, end];
    var leftPolyline = L.PolylineOffset.offsetLatLngs(linecoords, distance, map);
var rightPolyline = L.PolylineOffset.offsetLatLngs(linecoords, distance, map);
var resultcoords = [];
resultcoords.push(leftPolyline[0]);
resultcoords.push(leftPolyline[1]);
resultcoords.push(rightPolyline[1]);
resultcoords.push(rightPolyline[0]);
return resultcoords;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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