4 Replies - 8000 Views - Last Post: 05 July 2011 - 07:49 AM Rate Topic: -----

#1 Zel2008  Icon User is offline

  • D.I.C Addict

Reputation: 14
  • View blog
  • Posts: 790
  • Joined: 06-January 09

Calculating bezier control points

Posted 29 June 2011 - 02:51 PM

Hi everybody,
I have points around a circle that I want to connect with quadratic bezier curves. For every curve I draw, it starts at (x1,y1) on the circle, gets bent by the control point (centerX,centerY), and finishes at (x2,y2) on the circle.

I currently calculate the control points for a particular curve like this:
void calculate( int x1, int x2, int y1, int y2, int centerOfCircleXCoordinate, int centerOfCircleYCoordinate ) {

	// Calculate the midpoint between the two points.
	int midX = ( x1 + x2 ) / 2;
	int midY = ( y1 + y2 ) / 2;

	// Calculate the distance between the two points, and the angle at which a perpendicular line,
	// extending toward the center of the circle, would extend from the midpoint.
	double distance = sqrt( pow( x2 - x1, 2 ) + pow( y2 - y1, 2 ) );
	double angle = atan2( midY - centerOfCircleYCoordinate, midX - centerOfCircleXCoordinate );

	// Calculate the length of the perpendicular line, and its x and y components.
	double altitude = sqrt( 0.75 * pow ( distance, 2 ) );
	int altitudeX = (int)( cos( angle ) * altitude );
	int altitudeY = (int)( sin( angle ) * altitude );

	// Calculate the control point by subtracting half of the altitude from the midpoint.
	int centerX = midX - ( altitudeX / 2 );
	int centerY = midY - ( altitudeY / 2 );

	/* More stuff follows, but isn't important here. */
}



Essentially, I calculate the control points right now so the arcs are half as tall as the distance between their end points. For the most part, this works well, but there are many instances that curves cross (from across the circle, for example) when they shouldn't. So, I came up with the idea of having the curves bend less (be more like straight lines), the closer their midpoints come to the center of the circle. Unfortunately, this is where I'm stuck.

I've tried making a proportion based on the ratio of the altitude to the radius, but that was the only idea I had, and it didn't work.

Would anyone mind pointing me in the right direction to calculate the proper control points which bend these curves, please? I'd appreciate any help.

Thanks,
Zel2008

Is This A Good Question/Topic? 0
  • +

Replies To: Calculating bezier control points

#2 jimblumberg  Icon User is offline

  • member icon


Reputation: 4232
  • View blog
  • Posts: 13,291
  • Joined: 25-December 09

Re: Calculating bezier control points

Posted 29 June 2011 - 05:14 PM

Have you Googled quadratic bezier curves? There are several sites on the first page that explain the math behind the mystery.

Jim

This post has been edited by jimblumberg: 29 June 2011 - 05:15 PM

Was This Post Helpful? 0
  • +
  • -

#3 Zel2008  Icon User is offline

  • D.I.C Addict

Reputation: 14
  • View blog
  • Posts: 790
  • Joined: 06-January 09

Re: Calculating bezier control points

Posted 05 July 2011 - 05:34 AM

Hi Jim,
Sorry it took me a little time to reply. I have Googled bezier curves; that's how I got where I am. I understand how to create a control point to bend a curve to a particular height, but bending them progressively less or more is what's causing the problem.
Thanks,
Zel2008
Was This Post Helpful? 0
  • +
  • -

#4 Coding in the name of  Icon User is offline

  • D.I.C Head

Reputation: 67
  • View blog
  • Posts: 232
  • Joined: 07-July 10

Re: Calculating bezier control points

Posted 05 July 2011 - 06:55 AM

I don't think I totally understand your problem but a few things come to mind. If you're trying to draw an arc of a circle with a Bezier curve, that seems like trying to drive a nail with a sledgehammer. Since the curve itself must be drawn with discrete line segments why not just construct a list of points in a more straightforward and specific manner i.e.

for (float a = starta; a < enda; a += step)
{
    float x = (cos(a) * radius) + centerx;
    // etc.
}


Assuming that's not appropriate then as far as I see you want to control the curviness of each curve i.e. the distance of the control point from the line connecting the two end points. Therefore everything you need to do to achieve this should be in altering the 'altitude' variable from your original code. Where and how did this fail to work for you when you tried it?

This post has been edited by Coding in the name of: 05 July 2011 - 06:57 AM

Was This Post Helpful? 0
  • +
  • -

#5 NickDMax  Icon User is offline

  • Can grep dead trees!
  • member icon

Reputation: 2250
  • View blog
  • Posts: 9,245
  • Joined: 18-February 07

Re: Calculating bezier control points

Posted 05 July 2011 - 07:49 AM

Normally I am not much of a visual thinker but I can't seem to understand what you are looking for. Its obvious that you are not trying to make a circle because your control point at the center would curve inward rather than outward like a circle would. (besides the location of control pointers to approximate conic sections is a well understood problem and you can find articles on the subject).

so it sounds like your problem is:

You have two anchor pointer P0 and P2 laying on a circle C such that P0 != P2. At the moment you have P1 at the center of C but this is causing problems because the curve is too sharp. So you would like to place P1 proportionally closer to the anchor points.

So you plan was to find the midpoint M between P0 and P2, find the line passing between this midpoint and the center of C.

This seems pretty easy (and linear so there should be no need for sqrts.

Finding the midpoint is pretty easy, you can either find the average of the components OR you can use linerar interpolation. since we will need linear interpolation to find the point between the midpoint and the center it makes sense to just use it for both applications.

(note I have not put any of this code though a compiler so if it is broken Let me know and I will help you fix).

Coordinate linearInterp(Coordinate pFrom, Coordinate pTo, double s) {
    Coordinate point;
    point.x = (pTo.x - pFrom.x)*s + pFrom.x;
    point.x = (pTo.y - pFrom.y)*s + pFrom.y;
    return point;
}
...
Coordinate midpoint = linearInterp(P0, P2, 0.5);
P1 = linearInterp(center, midpoint, weight);
// Note Weight = 0 puts P1 at the center,
//      weight = 1 put P1 at the midpoint,
//      weight between 0 and 1 puts P1
//      proportionally between the center and the midpoint
//      so for example .25 is 25% of the way, .5 50% etc.


Of course I may be way off on what you are trying to do. But I hope that this helps.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1