Reputation: 109
I need help with this portion
side note: I have two circles.
Intersect (Circle c),
tangentOut (Circle c),
tangentIn (Circle),
disjoint (Circle ),
and contained (Circle ),
(Basically, I need to decide if another circle c intersects this circle, is tangent to this circle from outside, is inside this circle but intersects at a point, is outside of this circle without any touch, or is totally inside this circle.)
To find if it intersects the other circle I made this code:
public bool intersect(Circle c)
{
Point p = new Point(), myCenter = new Point();
p.setPoint(c.x, c.y);
myCenter.setPoint(x, y);
return myCenter.dist(p) < radius + c.radius;
}
but when I make the two circle (0,0,1) and (0,0,5). It shows that the circle intersect. Shouldn't it show that it does not intersect?
I also need help on the other methods as well.
Thanks in advance!
Here is my code:
public static void Main(string[] args)
{
Circle c1 = new Circle(0, 0, 1), c2 = new Circle(1, 0, 1);
Point p1 = new Point();
p1.setPoint(0, 1);
p1.print();
Console.Write(", ");
c1.print();
Console.WriteLine();
if (c1.onCircle(p1))
{
// Console.Write(" Point ");
p1.print();
Console.Write (" on ");
c1.print();
Console.WriteLine();
}
else
Console.WriteLine("Point NOT on circle");
if (c1.intersect(c2))
{
// Console.WriteLine("Two circles intersect");
c1.print();
Console.Write(" intersects ");
c2.print();
Console.WriteLine();
}
else
Console.WriteLine("Two circles do NOT intersect");
}
My Class:
class Circle : Point
{
private double radius;
public Circle(double xV, double yV, double r)
{
this.x = xV;
this.y = yV;
this.radius = r;
}
public void setRadius(double r)
{
radius = r > 0 ? radius : 0;
}
public bool onCircle(Point p)
{
return dist(p) == radius;
}
public bool intersect (Circle c)
{
Point p = new Point (), myCenter = new Point();
p.setPoint (c.x, c.y);
myCenter.setPoint (x, y);
return myCenter.dist(p) < radius + c.radius;
}
public void print()
{
Console.Write("Circle: ({0}, {1}, {2})", x, y, radius);
}
}
Class for point:
public class Point
{
protected double x; // x coordiate of Point
protected double y; // y coordinate of Point
public void setPoint (double xCoor, double yCoor) {
x = xCoor;
y = yCoor;
}
public double dist(Point p) // compute the distance of point p to the current point
{
double distance;
distance = Math.Sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
return distance;
}
public void print()
{
Console.Write("Point: ({0}, {1})", x, y);
}
}
Upvotes: 1
Views: 946
Reputation: 16564
Your intersect
method looks like it should produce an accurate result, but since Circle
derives from Point
it could be greatly simplified:
public bool intersect(Circle c)
{
return dist(c) < radius + c.radius;
}
All of the other operations are similar:
public bool tangentOut(Circle c)
{
return dist(c) == radius + c.radius;
}
public bool tangentIn(Circle c)
{
return dist(c) == Math.Abs(c.radius - radius);
}
public bool disjoint(Circle c)
{
return dist(c) > radius + c.radius;
}
public bool contains(Circle c)
{
return dist(c) <= radius - c.radius
}
Ramblings on Epsilon values follows...
The comparison in the tangentIn
and tangentOut
requires a slight change to account for accuracy problems. It's tempting to use a static epsilon figure (as in your comment exchange with willywonka) is asking for trouble when working with larger values. Instead you can scale the epsilon based on the numbers being compared.
The base for epsilon is the difference between 1 and the next possible number, by setting the lowest bit in the binary representation of the value. According to the Wikipedia entry for double-precision floating-point format (which I confirmed by testing it), that's approximately 2E-16. Which is fine for numbers between 0 and 2-E but doesn't work when you get outside that range. Similarly using larger values will give you larger range, but will at some point stop working.
So instead of using a static figure, scale the maximum value down by a useful amount - say one part in 10^9 - and use that as your epsilon. An example extension method:
public static class Extensions
{
public static bool EpsilonEqual(this double l, double r, double eScale = 1e+9)
{
double d = Math.Abs(l - r);
double e = Math.Abs(Math.Max(l, r)) / 1e+9;
return d <= e;
}
}
Adjust the scale factor to suit your accuracy requirements. Then you can do this:
public bool tangentOut(Circle c)
{
return dist(c).EpsilonEquals(radius + c.radius);
}
public bool tangentIn(Circle c)
{
return dist(c).EpsilonEquals(Math.Abs(c.radius - radius));
}
Upvotes: 0
Reputation:
Your coding style looks iffy - I'll just help you on the math.
Take two circles, A (center c1
, radius r1
) and B (center c2
, radius r2
). Let d = c1.dist(c2)
.
tangentOut
: condition is that d = r1 + r2
tangentIn
: d = abs(r2 - r1)
disjoint
: d > r1 + r2
contained
: d < abs(r2 - r1)
Also, taking into account numerical precision, change any equalities to delta-epsilon comparisons. E.g. a = b
becomes abs(a - b) < e
where e
is some maximum threshold.
Upvotes: 1
Reputation: 1800
You should reexamine your logic for intersection. What you have now is a method that only works for circles that do not intersect when one does not fully enclose the other. The situation you choose to test, concentric circles, shows this as the distance between the centers is 0 and that is in fact less than the sum of the radiuses. Another situation that would probably not be caught is that of a single degenerate intersection point.
I would suggest reading the Wolfram Alpha article on Circle-Circle Intersection to come up with a better test method.
Upvotes: 0