圆是否相交
whether circles intersect or not
本文关键字:是否 更新时间:2023-10-16
我有一个矩阵,看起来像这样:
0 0 1
0 0 2
0 2 1.5
表示圆的(X, Y, R)(首先是圆心,其次是半径)
这个矩阵是动态创建的,所以它可以有你想要的所有大小,只要输入它的1。
我需要找出这些圆是否相交,我这样做:
for( int i = 0; i < n; i++ ) {
dis_x = fabs(*(matrix + (i+1) * 3 + 0) - *(matrix + i * 3 + 0));
dis_y = fabs(*(matrix + (i+1) * 3 + 1) - *(matrix + i * 3 + 1));
hypotenuse = sqrt( pow(dis_x,2) + pow(dis_y,2) );
radius_i = *(matrix + i * 3 + 2);
radius_i_plus_1 = *(matrix + (i+1) * 3 + 2);
sum_of_radius = radius_i_plus_1 + radius_i;
if( sum_of_radius >= hypotenuse && hypotenuse != 0) {
*(array_of_numbers_of_circles + i * 2 + 0) = i + 1;
*(array_of_numbers_of_circles + i * 2 + 1) = i + 2;
}
}
如果我用上面的例子,我将看到:2 3
但是我需要:
1 3
2 3
换句话说,我需要比较所有元素,包括第一个元素与最后一个元素(如果大小为3)和所有元素:第二个元素与第四个元素(如果大小为4+)
提前感谢!
count = 0;
for( int i = 0; i < n-1; i++ ) {
for( int j= i + 1; j < n ; j++) {
dis_x = *(matrix + j * 3 + 0) - *(matrix + i * 3 + 0); // no need for fabs
dis_y = *(matrix + j * 3 + 1) - *(matrix + i * 3 + 1);
// use squared form, use multiplication rather than pow
hypSquared = dis_x * dis_x + dis_y * dis_y;
radius_i = *(matrix + i * 3 + 2);
radius_j = *(matrix + j * 3 + 2);
sum_of_radius = radius_i + radius_j;
diff_of_radius = radius_i - radius_j;
// compare square of radius to the square of hyp. Eliminates call to sqrt()
if( sum_of_radius * sum_of_radius >= hypSquared
&& diff_of_radius * diff_of_radius < hypSquared ) {
*(array_of_numbers_of_circles + count * 2 + 0) = i + 1;
*(array_of_numbers_of_circles + count * 2 + 1) = j + 2;
++count;
}
}
这个怎么样:
struct circle
{
double x, y, r;
bool empty() { return x==0.0 && y==0.0 && r==0.0; }
};
circle matrix[] = {
{0, 0, 1},
{0, 0, 2},
{0, 2, 1.5},
{0,0,0} // end marker
};
bool intersect(circle &c1, circle &c2)
{
double dx = c2.x - c1.x;
double dy = c2.y - c1.y;
double dist = sqrt(dx*dx + dy*dy);
double sumRad = c2.r + c1.r;
bool yes = false;
if (sumRad >= dist)
{
double minR = c1.r;
double maxR = c2.r;
if (minR > maxR) std::swap(minR, maxR);
if (dist + minR >= maxR || (dist == 0.0 && minR == maxR))
yes = true;
}
return yes;
}
void test()
{
std::vector<std::pair<int, int>> result;
for (int i=0; !matrix[i].empty(); i++)
for (int j=i+1; !matrix[j].empty(); j++)
if (intersect(matrix[i], matrix[j]))
result.push_back(std::pair<int, int>(i+1,j+1));
for (int i =0; i < result.size(); i++)
printf("%d %dn", result[i].first, result[i].second);
}
执行test()的输出为:
1 3
2 3
我倾向于这样做。首先是创建一个Circle类
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;
}
注意,这个类包括它自己的流插入器和提取器,以及一个成员函数intersects
,它告诉我们是否有两个Circle
类实例相交。显然,这里省略了所有的错误检查,但它给出了该技术的本质。
我将在下面的完整程序中展示如何使用它。该程序使用c++ 2011功能,使其相当紧凑,但它们不是使用Circle
类所必需的。
#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;
}
如果文件circles.txt
是一个包含给定输入的文本文件:
0 0 1
0 0 2
0 2 1.5
输出为:
(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)
注意这个版本报告每个圆与自己相交。技术上是正确的,但可能不是很有用!当然,可以重写驱动程序代码,去掉c++ 11的特性,并提供一些替代形式的输出。一种方法是将以下代码替换为上面代码中嵌套的for
循环:
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;
这样做会产生以下输出:
1 3
2 3
相关文章:
- 在提升multi_index容器中,是否定义了"default index"?
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 检查输入是否不是整数或数字
- 是否可以初始化不可复制类型的成员变量(或基类)
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 此代码是否违反一个定义规则
- 是否需要删除包含对象的"pair"?
- 是否可以从int转换为enum类类型
- 无论条件是否为true,if总是在c++中执行
- 如何找到大小'x'数组是否完全填充,在C++?
- 检查值是否在集合p1和p2中,但不在p3中
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- 检查 std::shared_ptr<> 的当前底层类型是否为 T
- 在c++中检查长方体是否尽可能快地重叠(无迭代)
- GL_SHADERSTORAGE_BUFFER位置是否与其他着色器位置冲突
- 子目录是否继承属性,例如add_definitions,include_directories和父Cmakelist.t
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- C/C++预处理器是否可以检测一些编译器选项
- 是否可以用"iostream"包装现有的TCP/OOpenSSL会话