circle mathematics

Official forum for the Chipmunk2D Physics Library.
Post Reply
bollu
Posts: 37
Joined: Tue Sep 14, 2010 4:33 am
Contact:

circle mathematics

Post by bollu »

Hi all!

This is a question that has nothing to do with Chipmunk, but I don't know any forums related to math, so I thought I'd ask here :)

My problem is tat I have a circle at position p and with radius r. when the mouse hovers inside the circle, I want a line to be drawn from the center of the circle, through the mouse's position and touch the circumference. I've tried for DAYS, and I've been unable to find a solution :( . Help badly needed :).

Thanks all!

P.S my (unsuccesful) code right now:

Code: Select all

if(this->mouseHovering == true){
		
		int nudge = this->hovering->getSize()/2;
		cpVect hPos = this->hovering->getPosition();
		int hX = hPos.x;
		int hY = hPos.y;
		int r = this->hovering->getRadius();
		
		int angle = acos(cpvdot (cpvnormalize(hPos),cpvnormalize(this->hoveringPos)));
		cpVect otherPoint = PolarProjection(hPos,r,angle);
		printf("\n\t\tradius = %d",r);
		aalineColor(this->window, otherPoint.x + nudge ,600 -  otherPoint.y + nudge, hPos.x  + nudge, 600 -  hPos.y  + nudge,
			SDL_MapRGB(this->window->format,255,255,255));
	};
bollu
Posts: 37
Joined: Tue Sep 14, 2010 4:33 am
Contact:

Re: circle mathematics

Post by bollu »

Bump. :)
aisman
Posts: 145
Joined: Tue Mar 04, 2008 2:21 am
Contact:

Re: circle mathematics

Post by aisman »

bollu wrote:Bump. :)
Bump...di...bump..di bump bump di bump... nice song...but we are no song writer. You have no ticket to get an answer. Be patient and hope.
Chipmunk4PB: The fastest way to write games together with PureBasic and the Chipmunk physics engine.
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: circle mathematics

Post by slembcke »

Holiday weekend here in the US, so I haven't been around much.

Basically what you need to do is this: Get the delta from the circle's center to the mouse. Now to get the offset from the center, divide the delta vector by it's length to make it length one, then multiply it by the circle's radius. center + (mouse - center)*(radius/length) Without any Chipmunk or vector stuff, getting the point on the circumference would look like this:

Code: Select all

float deltaX = mouseX - centerX;
float deltaY = mouseY - centerY;

float length = sqrt(deltaX*deltaX + deltaY*deltaY);
float coef = radius/length;

float pointX = centerX + deltaX*coef;
float pointY = centerY + deltaY*coef;
With Chipmunk functions like this:

Code: Select all

cpVect delta = cpvsub(mouse, center);
cpVect point = cpvadd(center, cpvmult(delta, radius/cpvlength(delta)));
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: circle mathematics

Post by slembcke »

Oh, I suppose I should comment on what went wrong with your code in case you wanted to know why it wasn't working. You were sort of close at least.

First of all, the dot product of two unit length vectors is equal to the cosine of the angle between them. So you can get the angle using acos(dot(v1, v2)), but it will always give you a value between 0 and pi radians (0 and 180 degrees). Not really what you want in this case. Also, you were comparing the angle of the vector that pointed from the origin to the center of the circle, and the vector from the origin to the mouse point. Also not really what you wanted.

If you wanted to do it using trig functions you can use atan2(). atan() converts a slope (y/x) into an angle, again between 0 and pi. With atan2() you pass it both the x and the y and it gives you the full angle (0 to 2*pi). It also doesn't break down when you try to get the angle of a vertical direction which would have an infinite slope. Using atan2() you could have done something like this:

Code: Select all

float angle = atan2(mouseY - centerY, mouseX - centerY);
float pointX = cos(angle)*radius;
float pointY = sin(angle)*radius;
While this works, it's usually best to avoid trig functions when possible. The biggest reason is that you often run into issues with ranges. An example from your code above:

Code: Select all

acos(cpvdot(cpvnormalize(v1), cpvnormalize(v2)));
Somewhat surprisingly, this can break catastrophically if v1 equals v2. The problem is that acos() only works on values strictly between 0 and 1. Because you are working with floating point numbers cpvnormalize() is going to return a vector with a length that is very close to 1 (like 0.999999999 or 1.000000001), but rarely exactly 1.0. This means that the result of cpvdot() might be > 1.0 and acos will break. The correct thing to do is to take the minimum of the dot product and 1.0.

Code: Select all

float dot = cpvdot(cpvnormalize(v1), cpvnormalize(v2));
acos(cpfmin(dot, 1.0))
I've ran into this issue before and it took a long time to find the problem. :-\ Another reason to avoid trig functions is that they are sloooooooooooow, really really slow. Don't avoid them simply because they are slow, but don't build an algorithm around performing tens of thousands of sines and cosines every frame.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
bollu
Posts: 37
Joined: Tue Sep 14, 2010 4:33 am
Contact:

Re: circle mathematics

Post by bollu »

Thanks a bunch Slembcke :) . I've seriously got to read Trigonometry again :/ . I've forgotten some of it :D
Thanks again!
Post Reply

Who is online

Users browsing this forum: No registered users and 26 guests