Sagar Guhe
Sagar Guhe

Reputation: 1106

Draw parallel measurement notation lines using d3js

I am trying to draw parallel lines to a polyline so that they will look like this:

enter image description here

I have all the points needed to draw polyline but using those points to draw individual lines and translating them shifts line slightly on both axis and those lines are also connected to each other. I want them exactly as shown in the above image.

I am using this code:

points = [[83.5,144],[172.5,71],[281.5,133],[385.5,77],[437.5,152]];

for (let i = 0; i < points.length; i++) {        
    if (i <= this.points.length - 2) {
        g.append('line')
            .attr('class', "notationLine")
            .attr("x1", points[i][0])
            .attr("y1", points[i][1])
            .attr("x2", points[i+1][0])
            .attr("y2", points[i+1][1])
            .attr("marker-end", "url(#arrow)")
            .attr("marker-start", "url(#arrowStart)")
            .attr('stroke', '#53DBF3')
            .attr('stroke-width', 1)
            .attr("transform", "translate(-10, -20)");
    }
}

Upvotes: 1

Views: 291

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102188

All you need for this is a bit of trigonometry.

For instance, given the distance you set...

const distance = 15;

... you calculate the angle between the two points with Math.atan2 and multiply its sine or cosine by the distance you want, sine for x positions and cosine for y positions:

distance * Math.sin(Math.atan(y, x))//for x
distance * Math.cos(Math.atan(y, x))//for y

Here is the demo with your data points:

const points = [
  [83.5, 144],
  [172.5, 71],
  [281.5, 133],
  [385.5, 77],
  [437.5, 152]
];

const distance = 15;

const svg = d3.select("svg");

const polyline = svg.append("polyline")
  .attr("points", points.join(" "));

const lines = svg.selectAll(null)
  .data(d3.pairs(points))
  .enter()
  .append("line")
  .attr("x1", d => d[0][0] - (distance * Math.sin(Math.atan2(d[0][1] - d[1][1], d[0][0] - d[1][0]))))
  .attr("x2", d => d[1][0] - (distance * Math.sin(Math.atan2(d[0][1] - d[1][1], d[0][0] - d[1][0]))))
  .attr("y1", d => d[0][1] + (distance * Math.cos(Math.atan2(d[0][1] - d[1][1], d[0][0] - d[1][0]))))
  .attr("y2", d => d[1][1] + (distance * Math.cos(Math.atan2(d[0][1] - d[1][1], d[0][0] - d[1][0]))))
polyline {
  fill: none;
  stroke: blue;
  stroke-width: 2px;
}

line {
  stroke: red;
  stroke-width: 2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="500" height="200"></svg>

Upvotes: 2

Related Questions