Circle Circle intersection help

Started by
5 comments, last by IsItSharp 8 years, 11 months ago

My current code to detect circle circle intersection looks like this:


        private List<Point> intersect(Circle c1, Circle c2)
        {
            List<Point> rLp = new List<Point>();
            double d = new Point(c1.p.X - c2.p.X, c1.p.Y - c2.p.Y).dist();

            if (d > (c1.radius + c2.radius))
                return rLp;
            else if (d == 0 && c1.radius == c2.radius)
                return rLp;
            else if ((d + Math.Min(c1.radius, c2.radius)) < Math.Max(c1.radius, c2.radius))
                return rLp;
            else
            {
                double a = (c1.radius * c1.radius - c2.radius * c2.radius + d * d) / (2 * d);
                double h = Math.Sqrt(c1.radius * c1.radius - a * a);

                Point p2 = new Point(Convert.ToInt32(c1.p.X + (a * (c2.p.X - c1.p.X)) / d), Convert.ToInt32(c1.p.Y + (a * c2.p.Y - c1.p.Y) / d));

                Point i1 = new Point(Convert.ToInt32(p2.X + (h * (c2.p.Y - c1.p.Y)) / d), Convert.ToInt32(p2.Y - (h * (c2.p.X - c1.p.X)) / d));
                Point i2 = new Point(Convert.ToInt32(p2.X - (h * (c2.p.Y - c1.p.Y)) / d), Convert.ToInt32(p2.Y + (h * (c2.p.X - c1.p.X)) / d));

                if (d == (c1.radius + c2.radius))
                    rLp.Add(i1);
                else
                {
                    rLp.Add(i1);
                    rLp.Add(i2);
                }

                return rLp;
            }
        }

The strange thing is:

the intersection is detected correctly but the y-coordinate is wrong. Any idea why that is?

Advertisement

Using float-valued points might be a good start.

Okay, i changed my code:
        private List<Vector2> intersect(Circle c1, Circle c2)
        {
            List<Vector2> rLp = new List<Vector2>();
            double d = new Vector2(c1.p.X - c2.p.X, c1.p.Y - c2.p.Y).dist();

            if (d > (c1.radius + c2.radius))
                return rLp;
            else if (d == 0 && c1.radius == c2.radius)
                return rLp;
            else if ((d + Math.Min(c1.radius, c2.radius)) < Math.Max(c1.radius, c2.radius))
                return rLp;
            else
            {
                double a = (c1.radius * c1.radius - c2.radius * c2.radius + d * d) / (2 * d);
                double h = Math.Sqrt(c1.radius * c1.radius - a * a);

                Vector2 p2 = new Vector2((float)(c1.p.X + (a * (c2.p.X - c1.p.X)) / d), (float)(c1.p.Y + (a * c2.p.Y - c1.p.Y) / d));

                Vector2 i1 = new Vector2((float)(p2.X + (h * (c2.p.Y - c1.p.Y)) / d), (float)(p2.Y - (h * (c2.p.X - c1.p.X)) / d));
                Vector2 i2 = new Vector2((float)(p2.X - (h * (c2.p.Y - c1.p.Y)) / d), (float)(p2.Y + (h * (c2.p.X - c1.p.X)) / d));

                if (d == (c1.radius + c2.radius))
                    rLp.Add(i1);
                else
                {
                    rLp.Add(i1);
                    rLp.Add(i2);
                }

                return rLp;
            }
        }
But still the same problem.

Vector2 p2 = new Vector2((float)(c1.p.X + (a * (c2.p.X - c1.p.X)) / d), (float)(c1.p.Y + (a * c2.p.Y - c1.p.Y) / d));

That line looks suspect. If you write it properly it actually reads:


Vector2 p2 = new Vector2((float)(c1.p.X + (a * (c2.p.X - c1.p.X)) / d),
                         (float)(c1.p.Y + (a * c2.p.Y - c1.p.Y) / d));

It seems like you're missing a pair of brackets, and that it should actually be:


Vector2 p2 = new Vector2((float)(c1.p.X + (a * (c2.p.X - c1.p.X)) / d),
                         (float)(c1.p.Y + (a * (c2.p.Y - c1.p.Y)) / d));

Remember, the compiler isn't human and isn't going to correct your mistakes (though a clever static analyzer might pick this up). Get into the habit of always trying to write and format your code to decrease the likelihood of such typographical errors.

Note: in this case that also means using vector types to write code that logically represents vector operations, which would have avoided this error. In other words, why does your Vector2 type not have operators that you can use to write "p2 = c1.p + a * (c2.p - c1.p) / d" instead of doing it component-wise here?

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

Another thing, is that it's totally okay to use some secondary variables to make things clearer. For example c2.p - c1.p looks like it's used enough times that you could make that a vector in the code. If you're worried about speed the compiler will usually optimize them out anyway. And if you're worried about speed you could avoid a square root in the .dist() call by checking the distance squared first.

Those Y's look correct mirrored vertically (over the X-axis) to me. What rendering API are you using? Your data is correct, but you might be interpreting the rendering side of it incorrectly. Most "draw circle/line" API's work where positive Y values move downwards instead of upwards; The top left of the screen is (0, 0) and the bottom left corner is (0, height). Try rendering those points at (x, imageHeight - y) and see if they match up to the circles.

@Bacterius

Thank you very much, now it works correctly :)

Another thing, is that it's totally okay to use some secondary variables to make things clearer. For example c2.p - c1.p looks like it's used enough times that you could make that a vector in the code. If you're worried about speed the compiler will usually optimize them out anyway. And if you're worried about speed you could avoid a square root in the .dist() call by checking the distance squared first.

Okay, i'll try that :)

This topic is closed to new replies.

Advertisement