Advertisement

Bezier curve control point

Started by August 15, 2022 02:47 PM
36 comments, last by JoeJ 2 years, 4 months ago

JoeJ said:
Then we calculate the intersection for those two transported lines, giving us the middle CP we want.

so did I understand right, those two calculations are needed to calculate the middle CP?

also i'm confused if you have counted two angles how do you do intersection with those?

and why two black and white lines and not just one?

double post

Advertisement

so did I understand right, those two calculations are needed to calculate the middle CP?

Yes. The proper way to think about it:

To get a smooth curve, the curve tangent at point X must be the same no matter if we point towards the next point X+1, or if we point towards the previous point X-1.

It follows that the only way to get a middle control poitns which agrees with that is the intersection of the two tangents adjacent to it.

Thus, we have no control over the position of this point and the actual lengths of the resulting tangents. (Notice: a curve with continuous velocity needs to have both tangents at the same length too, not just at the same direction.)
We could however play with the inital tangent directions to avoid problems, indirectly moving the middle CP somewhere else. We could do this to deal with parallel tangents for example.

You will see related problems if you continue with quadritc bezier, and after you understood the limitations you'll likely prefer alternatives as mentioned.
But it's good to continue to see this yourself.

In practice, Cubic Bezier or Catmull Rom have more complex math (slightly), but they are much easier to use for satisfying results.

also i'm confused if you have counted two angles how do you do intersection with those?

No angles are needed to calculate the intersaction of two lines - that's ofc. just liner math.

My favourite resurce to look up intersection problems: https://github.com/davideberly/GeometricTools/tree/master/GTE/Mathematics

Look for IntrLine2Line2.h


@joej

Ok this is what i got so far, pretty curves but not the correct ones so far:

		
		Vertex v1 = getBP(res.Result, index);
                Vertex v2 = getBP(res.Result, index + 1);
                Vertex v3 = getBP(res.Result, index + 2);
                Vertex v4 = getBP(res.Result, index + 3);



                Vector2 pv1 = toBPoint(v1);
                Vector2 pv2 = toBPoint(v2);
                Vector2 pv3 = toBPoint(v3);
                Vector2 pv4 = toBPoint(v4);

          

                double firstAngle = getAngle(pv1, pv3);
                double secondAngle = getAngle(pv4, pv2);

                Vector2 fp = getVector(firstAngle, 1000, pv2); // Create first line end point
                Vector2 sp = getVector(secondAngle, 1000, pv3); // Second line

                Vector2 iv = intersect(pv2, fp, pv3, sp);



                Bezier bez = new Bezier(pv1, iv, pv2);

produces:

That's what i mean with ‘causing sharp, not smooth spikes in the curve at control points’.

But it should not happen. For your data you should get a pretty good result.

First i must replace the use of angles…. ?

		
		Vertex v1 = getBP(res.Result, index);
                Vertex v2 = getBP(res.Result, index + 1);
                Vertex v3 = getBP(res.Result, index + 2);
                Vertex v4 = getBP(res.Result, index + 3);



                Vector2 pv1 = toBPoint(v1);
                Vector2 pv2 = toBPoint(v2);
                Vector2 pv3 = toBPoint(v3);
                Vector2 pv4 = toBPoint(v4);

          

                //double firstAngle = getAngle(pv1, pv3);
                //double secondAngle = getAngle(pv4, pv2);

                //Vector2 fp = getVector(firstAngle, 1000, pv2); // Create first line end point
                //Vector2 sp = getVector(secondAngle, 1000, pv3); // Second line

                //Vector2 iv = intersect(pv2, fp, pv3, sp);
                
                Vector2 line0 = pv3 - pv1;
                vector2 line1 = pv4 - pv2;
                
                Vector2 tangentEndPoint0 = pv2 + line0; // 'transport' the line to the control point
                Vector2 tangentEndPoint1 = pv3 + line1; // 'transport' the line to the control point
                
                Vector2 iv = intersect(pv2, tangentEndPoint0, pv3, tangentEndPoint1); 
                // assuming the function works like IntersectInfiniteLines(line1point1, line1point2, line2point1, line2point2) 
                
				Bezier bez = new Bezier(pv1, iv, pv2);
                
                
                // this would be a way to do it with cubic bezier, just to show it's easier to set up:
                
                tangentEndPoint0 = pv2 + line0 / 2.f * 0.333f; // 0.333 means tension at the control point. Higher values make the curve smoother at this point, smaller values make it sharper
                tangentEndPoint1 = pv3 - line1 / 2.f * 0.333f; // EDIT: initially forgot division by 2
                
                CubicBezier bez4 = new Bezier(pv1, tangentEndPoint0, tangentEndPoint1, pv2);

                
                

@JoeJ Hmm getting this now, with the new code:

intersect fn:

        private Vector2 intersect(Vector2 line1V1, Vector2 line1V2, Vector2 line2V1, Vector2 line2V2)
        {

            //Line1
            float A1 = line1V2.Y - line1V1.Y;
            float B1 = line1V1.X - line1V2.X;
            float C1 = A1 * line1V1.X + B1 * line1V1.Y;

            //Line2
            float A2 = line2V2.Y - line2V1.Y;
            float B2 = line2V1.X - line2V2.X;
            float C2 = A2 * line2V1.X + B2 * line2V1.Y;


            float delta = A1 * B2 - A2 * B1;

            if (delta == 0)
                throw new ArgumentException("Lines are parallel");

            float x = (B2 * C1 - B1 * C2) / delta;
            float y = (A1 * C2 - A2 * C1) / delta;

            return new Vector2(x,y);
        }

Advertisement

Hmm, still buggy.

You should visualize the new control point. Maybe that's a hint on what's wrong…

JoeJ said:

Hmm, still buggy.

You should visualize the new control point. Maybe that's a hint on what's wrong…

well you can kinda see it the way the line gets pulled…

@joej

Here's how it looks with dots showing the calculated middle CP:

Well i managed to get it working now but the quality isn't the best. partially because the curves are missing something from start and end

this is how it looks now:

I think leaving part of those ends missing could be bug in the Bezier library.

I tried also cubic bezier and it's much better (still ends not fully rendered)

This topic is closed to new replies.

Advertisement