d3 / d3-shape

Graphical primitives for visualization, such as lines and areas.
https://d3js.org/d3-shape
ISC License
2.48k stars 310 forks source link

arc command adds an extra slice of .5 Pi radians when generating paths #130

Closed ialarmedalien closed 5 years ago

ialarmedalien commented 6 years ago

I've written some code to generate different styles of link in node-link diagrams (dogleg, right angle, direct lines, etc.) and came across an odd bug when using d3.pointRadial, context.lineTo, and context.arc.

Given an set of points, x0,y0, x1,y1, x2,y2, etc., representing angle and radius, I assumed I would be able to do something like this:

  step = d3.pointRadial(x0,y0);
  context.moveTo(step[0], step[1]);
  // straight line to the next point
  step = d3.pointRadial(x1,y1);
  context.lineTo(step[0], step[1]);
  // arc to the next point
  context.arc(0, 0, y2, x1, x2, x2 > x1 ? 0 : 1);
  // now a straight line
  step = d3.pointRadial(x3,y3);
  context.lineTo(step[0], step[1]);

etc.

However, the arc command puts in an extra .5 Pi radians somewhere, so if I want the lines to join nicely, I have to use these arguments:

context.arc(0, 0, y2, x1 - Math.PI*0.5, x2 - Math.PI*0.5, x2 > x1 ? 0 : 1);

I couldn't see anything in the docs about it. Is this how the arc function is supposed to work?

I've created an example block to demonstrate the problem.

On a related note, it would be very useful to have a publicly-exported link function to allow the easy creation of custom links with the same interface as linkHorizontal, linkVertical, and linkRadial. I'm using a slightly edited version of d3-shape that exposes the link constructor, but it would be great to have something official.

mbostock commented 5 years ago

This is the expected behavior; context.arc defines angles by measuring clockwise from the positive x-axis (3 o’clock), whereas d3-shape measures clockwise from the negative y-axis (12 o’clock). This is documented in the definition of d3.pointRadial. (It’s also more convenient for pie charts and such.)