现在,在我修复了错误之后,这个程序的主要问题是速度。我的意思是它能工作,但是慢得可怕。
我有一个点的数组,我需要在这里找到正方形,所以为了做到这一点,我需要检查所有可能的4个点的组合,所以我使用了三个嵌套循环,一般来说,它需要n^4次操作,如果我有一个数组的100个元素,这或多或少是正常的,但是我有500个元素,所以500^4是很大的一个数,有没有更快的方法?
/*j, o, k, l are numbers of each point. This loop will check all possible combinations
(except 2 or more points have the same number(it means also the same coordinades) or they already are part of some figure*/
for (int j=0; j < i-1; j++)
{
if (Point[j].p != true)
{
for (int o = 1; o < i - 2; o++)
{
if ((o != j) && (Point[o].p != true))
{
for (int k = 2; k < i - 3; k++)
{
if ((k!= j) && (k != o) && (Point[k].p != true))
{
for (int l = 3; l < i - 4; l++)
{
if ((l != k) && (Point[l].p != true) && (l != o) && (l!=j))
{
vx1 = abs(Point[o].x - Point[j].x); //vectors coordinates
vx2 = abs(Point[k].x - Point[o].x);
vy1 = abs(Point[o].y - Point[j].y);
vy2 = abs(Point[k].y - Point[o].y);
vx3 = abs(Point[l].x - Point[k].x);
vy3 = abs(Point[l].y - Point[k].y);
vx4 = abs(Point[j].x - Point[l].x);
vy4 = abs(Point[j].y - Point[l].y);
dx1 = abs(Point[k].x - Point[j].x); //diagonals coordinates
dy1 = abs(Point[k].y - Point[j].y);
dx2 = abs(Point[o].x - Point[l].x);
dy2 = abs(Point[o].y - Point[l].y);
v1 = sqrt(vx1 * vx1 + vy1 * vy1); // sides length
v2 = sqrt(vx2 * vx2 + vy2 * vy2);
v3 = sqrt(vx3 * vx3 + vy3 * vy3);
v4 = sqrt(vx4 * vx4 + vy4 * vy4);
d1 = sqrt(dx1 *dx1 + dy1 * dy1); //diagonals length
d2 = sqrt(dx2 * dx2 + dy2 * dy2);
if (
((abs(v1-v2)<=0.5) && (abs(v3-v4)<=0.5) && (abs(v3-v2)<=0.5) && (v1<d1)) /*cheks all sides are equal and if the diagonal is bigger than side*/
&& (Point[k].p != true && Point[o].p != true && Point[j].p != true)/*checks if the points aren`t the part of any figure yet*/
&&(abs(d1 - d2)<=0.5)/*checks if the diagonals are equal*/)
{
q++;
Point[j].p = true; // it means that point with this number is already a part of some figure, so it will be skipped in next operations
Point[o].p = true;
Point[k].p = true;
Point[l].p = true;
// the output
out << "Figure " << q << ":" << "x1=" << Point[j].x << " y1=" << Point[j].y << " x2="
<< Point[o].x << " y2=" << Point[o].y <<
" x3=" << Point[k].x << " y3=" << Point[k].y <<
" x4=" << Point[l].x << " y4=" << Point[l].y << endl;
}
}
}
}
}
}
}
}
2条答案
按热度按时间hujrc8aj1#
既然你提到它是一个 “计算机图形坐标系(没有负坐标)",我也假设整数值,这使得它相当直接。
Point
的std::unordered_set
A
和B
的每个组合,计算第三个点C
的位置,第三个点C
相对于前两个点A -> B
旋转90°。D
相对于B -> C
的位置。示例:
首先是
Point
类模板:这样我们就可以通过
B - A
得到x
和y
的不同之处,并且专用的std::hash
可以让我们把它存储在像std::unordered_set
这样的容器中,std::unordered_set
要求 Key 是可哈希的。接下来,使用一个函数模板,通过将
Point<>
相对于其他两个Point<>
旋转90°来获得Point<>
:然后,实际的匹配过程可能如下所示:
Demo
注:
对于某些点的组合,您可能会找到比预期更少的方块。例如,上述算法(以及您的原始算法)可能会在此处找到1 * 或 * 2个方块:
那是因为
也形成了一个(第三个)正方形,由于您删除了已经使用的点,如果上面的点先找到,其他两个点将不会显示。如果您希望显示所有三个点,您可以将它们收集到另一个集合中。首先是
Square
类模板:匹配变得更加直接:
Demo
我对上面的
FindSquares
函数做了一些测量,在随机位置放置点,持续时间只是为了显示它的缩放方式:| 尺寸|点数|找到的方块|持续时间|
| - ------|- ------|- ------|- ------|
| 590x591|一千五百|1-6| 0.04s |
| 590x591|一万五千|小行星35| 5.65s |
| 590x591|三万|小行星565800| 31.00s |
| 小行星1777 x1057|一千五百|无| 0.04s |
| 小行星1777 x1057|一万五千|一千| 5.40s |
| 小行星1777 x1057|三万|小行星157| 27.70s |
x1c 0d1x的数据
vmdwslir2#
你必须测试两个初始点的任意组合。我们称之为A和B。但是由于你只需要每个可能的正方形一次,你可以要求第三个点,我们称之为C,以验证(AC)在三角学意义上是(AB)旋转90°。如果一个可能的候选者可以通过旋转相反的方向获得,你将从不同的初始对中找到最终的正方形。
但这里的条件非常简单:
当你有一个可能的候选点C,点D将必须验证(CD)=(AB)的意思是:
但是如果你使用浮点值作为坐标,你可能会遇到精度问题。我们都知道浮点运算是不精确的。所以你应该定义一个 epsilon 值(通常10-6是一个可接受的值),并用接近以下代码替换所有的相等性测试:
我目前无法编写和测试代码(无法访问可接受的编译器),但此算法应该可以稍微缩短时间:操作简单得多,并且由于如果你已经找到可接受的第三个点,则你仅搜索第四个点,因此复杂度应当接近n3。