I'd be inclined to approach it like this. The first thing is to create a Circle class
class Circle
{
public:
friend std::ostream &operator<<(std::ostream &out, const Circle &c)
{ return out << '(' << c.x << ", " << c.y << ", " << c.r << ')'; };
friend std::istream &operator>>(std::istream &in, Circle &c)
{ return in >> c.x >> c.y >> c.r; };
bool intersects(const Circle &c2) const;
private:
float x, y, r;
};
bool Circle::intersects(const Circle &c2) const
{
float dist_squared = (x-c2.x)*(x-c2.x)+(y-c2.y)*(y-c2.y);
if ((r-c2.r)*(r-c2.r) > dist_squared)
return false;
return (r+c2.r)*(r+c2.r) >= dist_squared;
}
Note that this class includes its own stream inserter and extractor and a member function intersects
which tells whether any two Circle
class instances intersect. Obviously, all error checking is omitted here, but it gives the essence of the technique.
I show how to use it in a complete program below. This program uses C++ 2011 features which make it quite compact, but they're not essential to using the Circle
class.
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
#include <algorithm>
// the above Circle code would go here...
int main()
{
std::ifstream in("circles.txt");
std::vector<Circle> circles;
std::copy(std::istream_iterator<Circle>(in),
std::istream_iterator<Circle>(),
std::back_inserter(circles));
for (auto i : circles)
for (auto j : circles)
if (i.intersects(j))
std::cout << i << " intersects " << j << std::endl;
return 0;
}
If the file circles.txt
is a text file containing exactly the input given:
0 0 1
0 0 2
0 2 1.5
the output is:
(0, 0, 1) intersects (0, 0, 1)
(0, 0, 1) intersects (0, 2, 1.5)
(0, 0, 2) intersects (0, 0, 2)
(0, 0, 2) intersects (0, 2, 1.5)
(0, 2, 1.5) intersects (0, 0, 1)
(0, 2, 1.5) intersects (0, 0, 2)
(0, 2, 1.5) intersects (0, 2, 1.5)
Note that this version reports that each circle intersects with itself. Technically true, but probably not very useful! The driver code could, of course, be rewritten without C++11 features and to give some alternate form of output. One way to do that would be to substitute this code for the nested for
loops in the code above:
for (int i = 0; i < circles.size(); ++i)
for (int j = i+1; j < circles.size(); ++j)
if (circles[i].intersects(circles[j]))
std::cout << i+1 << " " << j+1 << std::endl;
Doing so yields the following output:
1 3
2 3