Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get an array of points from D3 line()

d3.line(data) returns a path data string. But, If I understand correctly, d3.line(data).context(context) draws directly the line on the canvas. How can I get the array of points used to draw the line on the canvas?

And, is it possible to change the preciseness of the line resulting from d3.line().curve() by passing the number of desired points?

Here is what I want to achieve:

makeACurvedLine([p1, p2, p3], 6)

And get the array of coordinates of the 6 points from the smoothed line.

What is the best way to achieve it?

like image 875
Zamadhi Eturu Avatar asked Oct 16 '22 15:10

Zamadhi Eturu


1 Answers

When you use d3.line().context(context)(data) with a canvas context, it uses canvas's built-in functions to draw arcs, curves, and other non-linear elements. This means d3 by itself doesn't really reduce your path to a bunch of points it connects with straight lines.

However, the browser itself has built-in functions to get points along an SVG path. One approach is to create an invisible svg path and use those functions to calculate path points. For the following snippet, I'll use uniformly spaced points, though you might want something more refined if there are some parts that are more curvy than others.

var svg = d3.select('body')
  .append('svg')
  .style('display', 'none');

var lineGenerator = d3.line().x(d=>d[0]).y(d=>d[1]).curve(d3.curveNatural);
var path = svg.append('path');

function getLinePoints(curvePoints, numPoints){
  path.attr('d', lineGenerator(curvePoints));
  var svgLine = path.node();
  var lineLength = svgLine.getTotalLength();
  var interval;
  if (numPoints === 1) {
    interval = 0;
  } else {
    interval = lineLength / (numPoints - 1);
  }
  return d3.range(numPoints).map(function (d) {
    var point = svgLine.getPointAtLength(d * interval);
    return [ point.x, point.y ];
  });
};


console.log(getLinePoints([[0,0],[0,10],[20,30]], 6));
<script src="https://d3js.org/d3.v5.min.js"></script>
like image 175
Steve Avatar answered Oct 20 '22 07:10

Steve