简体   繁体   中英

Calculate bezier curve control points with given angle

在此处输入图片说明 Lets assume we have a bezier curve with a start p0 of (0, 0) and an end p4 of (100, 0). Right now it would basically be a line with no curve yet. Now lets assume I want to calculate the two missing control points (p1 p2) based on a given angle. What is the best way to achieve this?

Lets assume I wanted something like this:

https://1.bp.blogspot.com/_W3ZUYKgeEpk/SDcAerq1xkI/AAAAAAAAAAc/W9OnovkzgPI/s400/RectanglularControlPoly.jpg

I mean depending on the position of the control points it forms a triangle of some sort, that is why I was wondering if its possible.

Controls points that go through a Bezier point with a given angle, lie on the tangent with that angle.

The resulting bending will be the softer the farther away the control point is chosen, so there are many different solutions with the same angle and different curvature..

在此处输入图片说明

To find control points with equally soft curvatures for two Bezier points simply find the crossing of the two tangents! Use the crossing as the common control point for both segments, ie have C1 = C2.

For any sort of symmetrical curve you need to keep the deviations from the crossing symmetrical, ie 50%, 10% etc..

Note that for optimizing the overall shape one also needs to look at the neighbouring points; in general the provided GDI function does a good job; so it is worth considering simply adding more Bezier points for controlling the shape; but of course using the perfect set of control points is the most economic solution.

Update: I have added an example of how well a circle (orange) gets approximated by the math in this interesting post .

Short version: An exact solution isn't really possible but the best fit for a quarter circle is to move the control point to ~0.55% of the crossing point. ( d=r*4*(sqrt(2)-1)/3 ). Sometimes instead of using a 4 segment solution an 8 segment solution is used for even closer approximation..

private void button_Click(object sender, EventArgs e)
{
    int w = Math.Abs(P2.Left - P1.Left);
    int h = Math.Abs(P2.Top - P1.Top);
    C2.Left =  (int) (P2.Left + w * 0.5523f);
    C2.Top = P2.Top;
    C1.Left = P1.Left;
    C1.Top = (int) (P1.Top + h * 0.5523f);
    C1.Parent.Invalidate();
}

The code uses Labels for the points and control points..

Btw: Adding ellipses/circles to a GraphicsPath will create bezier curves that seem to be approximated just like that.

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