简体   繁体   中英

create a bezier curve from arc in javascript

I want to create a quadratic bezier curve from the two end points on a arc (x1, y1, x2, y2) and either the center point (cx,cy) or radius.

At one point, I thought that I could set the two control points to the intersection of the tangents, but that does not seem to work.

While an exact answer would be nice, I can live with a reasonable approximation if required. I have limited math skills but would appreciate simple pseudo code. I have done a google search and some of the suggestions are too complex for me to follow.

The problem seems simple but I know it is not.

For a good approximation of a circle place the Bezier Quadratic control points at

var cp = (r * 4 * (Math.sqrt( 2 ) - 1)) / 3; 

Where r is the radius of the circle at point (x,y) . cp is the distance along the tangent to put the control point.

ctx.moveTo(x-r,y)
ctx.quadCurve(x - r, y - pc, x + r, y - pc, x + r, y); 

Will create a nice half a circle. Do the same for the bottom to get a full circle.

There is no perfect mapping between arcs and Bezier curves due to the fact that a circle has parametric function:

fx(t) = cos(t)
fy(t) = sin(t)

which can only be represented in polynomial form as infinite sequences:

fx(t) = ∑(k=0,inf) x^(2k)   * (-1)^k / (2k)!
fy(t) = ∑(k=0,inf) x^(2k+1) * (-1)^k / (2k+1)!

Obviously, any finite degree Bezier curve will always be "off", although the higher the order, the less "off" we'll be. For a cubic curve we can approximate a quarter circle arc quite reasonably, although anything more than that and it'll look pretty obviously wrong: there's a detailed writeup on what a curve looks like given an arc of angle φ over on http://pomax.github.io/bezierinfo/#circles_cubic , and it's worth reading over that section and then implementing its explanation (or "borrowing" the code from github, it's public domain code), as well as playing with the graphic to see exactly how wrong things get once you try to model more than a quarter circle.

Quadratic Bezier curve has equation

B(t) = P0 * (1-t)^2+ 2 * P1 * t * (1-t) + P2 * t^2

For your case

P0 = (x1,y1)
P2 = (x2,y2)

To approximate an arc with Bezier, we can declare that middle point of curve must coincide with middle point of arc.

To find middle point of arc:
We have chord vector

V = (x2-x1, y2-y1)

perpendicular vector (not y sign change)

P = (y1-y2, x2-x1)

It's length

LenP = Sqrt((y1-y2)^2 + (x2-x1)^2)

unit perpendicular vector

uP = P/LenP = ( (y1-y2) / LenP, (x2-x1) / LenP)

Middle arc point

M = C + R * uP = (cx + R * (y1-y2) / LenP, cy + R * (x2-x1) / LenP)

Middle point of Bezier

B(1/2) = P0/4 + P1/2 + P2/4 = (x1/4 + px/2 + x2/4, y1/4 + py/2 + y2/4)

Now we can write equations

cx + R * (y1-y2) / LenP = x1/4 + px/2 + x2/4
cy + R * (x2-x1) / LenP = y1/4 + py/2 + y2/4

and find px and py - coordinates of control point.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM