d3-shape
d3-shape copied to clipboard
add optional angle radius parameter in curbeBezier `curveStep` curves
Following #177, as suggested in https://github.com/d3/d3-shape/pull/177#issuecomment-809936541, it could be useful to have a curve similar to curveStep
but with smooth angles:
An important note is that the curve angle should be identical whatever its length. This way we don't see curves duplication on nodes with many child of various link length:
~~Those curves could be named curbeBezierX
and curbeBezierY
as suggested in this example.~~
In fact, I think those curves could be included in curveStep
, by adding an extra optional parameter allowing to define the angle radius, which is 0 by default.
This will also allow some customization. This is for instance large angle (ie curveStep(15)
) and small angle (ie curveStep(5)
) stepCurves, respectively:
Some other visuals to get the idea:
curveStep(10)
curveStepBefore(10)
curveStepAfter(10)
Edit: as pointed out by @Fil, the curve horizontal and vertical distance might be lower than twice the angle radius. In that case the radius remains the same, but angles stops before 90° in order to share the same tangential line. Example with several curves formed with curveStep(20)
, tangential line in red:
Nice! Note that you need the difference in x and the difference in y to be greater than twice the radius—the spec should also describe what to do when it's smaller.
Good point! I edited the issue.
We'll need to specify all the cases :)
pseudo code:
move to x1,y1
xa = (x1+x2)/2; // x1+r if stepBefore, x2-r if stepAfter
ya = (y1+y2)/2;
sx = Math.sign(x2-x1);
sy = Math.sign(y2-y1);
if (|x2-x1| > 2r && |y2-y1| > 2r):
line to xa - sx * r, y1
arc to xa, y1 + sy * r
line to xa, y2 - sy * r
arc to xa + sx * r, y2
line to x2, y2
else if (|x2-x1| > 2r)
… // line + bezier + line?
else if (|y2-y1| > 2r)
… // ?? smaller r?
else
... // bezier ??
Does that image cover all the cases?