Point Circle Intersection Woes

This topic is 4667 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

All I want to do is have a circle change colour when the mouse pointer intersects it. Currently I'm doing this all in transformed space. The most likely place for my problem is probably my intersection code, so let's look at that first. All the code is C#.
                private bool MouseIntersection(int x, int y)
{

if( (((30 + x)^2) - ((30 + y)^2)) < (30^2) )
return true;
else
return false;
}

private void Investigator_MouseMove(object sender,
System.Windows.Forms.MouseEventArgs e)
{
this.textBox1.Text = e.X + "," + e.Y;
mouseInside = MouseIntersection(e.X,e.Y);
}


So my circle is at position 30,30 and is of radius 30. It's a test program :D. Each frame I create the entire circle and draw it. The mouseInside bool dictates which colour the circle will be. (Actaully as an aside I have a problem drawing a circle too :( I use a triangle fan but if I attempt to draw all the circle it dissapears, if I leave one segment out it draws fine though looks a little like pac-man). Here's my circle creation code.
                private CustomVertex.TransformedColored[] CreateCircle(
float radius, float originX, float originY,
float stepSize)
{
float x,y = 0;
float angle = 0.0f;
int i = 0;

int segmentNum = (int)Math.Ceiling((Math.PI*2 / stepSize)) + 1;

CustomVertex.TransformedColored[] verts
= new CustomVertex.TransformedColored[segmentNum];
verts[0].Position = new Vector4(originX,originY, 0,1);
verts[0].Color = Color.White.ToArgb();
i++;

while(angle < Math.PI*2)
{

x = radius * (float) Math.Cos(angle);
y =  radius * (float) Math.Sin(angle);

verts.Position =
new Vector4(x + originX, y + originY, 0, 1);
if(!mouseInside)
{
verts.Color = Color.White.ToArgb();
}
else
{
verts.Color = Color.Red.ToArgb();
}

i++;
angle += stepSize;
}

return verts;
}


And here's the code that's run every render loop
                private void Process()
{
device.Clear(ClearFlags.Target, System.Drawing.Color.Blue,
1.0f, 0);

CustomVertex.TransformedColored[] verts =
CreateCircle(30,30,30,0.1f);

VertexBuffer vb = new VertexBuffer(typeof(CustomVertex.TransformedColored),
verts.Length,
device,
0,
CustomVertex.TransformedColored.Format,
Pool.Default);
GraphicsStream stm = vb.Lock(0, 0, 0);
stm.Write(verts);
vb.Unlock();

device.RenderState.Lighting = false;
device.RenderState.PointSize = 2.0f;
device.RenderState.CullMode = Cull.None;

device.BeginScene();

device.SetStreamSource(0, vb,0);
device.VertexFormat = CustomVertex.TransformedColored.Format;
device.DrawPrimitives(PrimitiveType.TriangleFan, 0, verts.Length
-2);

device.EndScene();

device.Present();
}


Pretty standard. So when the mouse goes in the circle it should go a reddish colour (i don't colour the middle vertex red, for no particular reason, so I get a red corona). Anyhoo the intersection is a bit off the mouse can be far outside the circle and it still gets coloured. Also I think it's possible to be in the circle without any highlight. Help! :D

Share on other sites
You know your origin, your radius and your cursor position, right? Just need to think of it in terms of vectors. Measure the distance between your origin vector and your cursor vector and see if that length is less than your radius. So, for example:

Vector center;Vector cursor;Vector between;between = center - cursor;if (between.Magitutde <= radius)    change color;

obviously psuedo code ;) If you have any questions (like, you don't know how to calculate the magitude of a vector or do vector subtraction and can't find it on google), just let us know :)

Share on other sites
Quote:
 Original post by BalaamSo my circle is at position 30,30 and is of radius 30. It's a test program :D.

Then for the sake of your sanity (and ours) make that clear in your code and actually use some named constants. You make things worse by using 30 for all three params! Who's going to know whats what?

On a more practical note, the '^' operator probably doesn't do what you think it does (at least, it doesn't in C, C++ and Java, so I'm guessing its the same in C#). In C++ it's the bitwise XOR (IIRC, not one I use often).

So your separation ends up looking like:
float dx = x1 - x2;float dy = y1 - y2;float separationSquared = (dx*dx) + (dy*dy)float separation = sqrt(separationSquared);return (separation <= circleRadius);

Share on other sites
Thank you very much I have it working now.

Sorry I should take more care with variables when posting to the forums. As for myself I like to write small throw-away programs when I don't understand something too well. First I stick to constants and then when I have it working for that specific case I generalize :D In future I'll make sure not to inflict this practice on those who might help me!

Share on other sites
((30 + x)^2) - ((30 + y)^2)) < (30^2)

Why are you xoring 30 + x with 2?
30 + y with 2?
And 30 with 2?

From,
Nice coder

Share on other sites
Well I know C/C++ and not C# but unless MS has changed this (and they may well have), the ^ operator is bitwise XOR not raise-to-the-power-of.

Second,

(((30 + x)^2) - ((30 + y)^2)) < (30^2)

is not the correct equation of a circle at (30, 30). It's a hyperbola centred at (-30, -30). So I think the actual test you want is:

((x - x0)*(x - x0) + (y - y0)*(y - y0)) < rad*rad

For a circle at (x0,y0) with radius rad.