简体   繁体   English

C++ 检测正方形

[英]C++ Detecting Squares

I built the following code to read 4 pairs of coordinates to calculate if it's a square or not:我构建了以下代码来读取 4 对坐标来计算它是否是正方形:

#include <iostream>
using namespace std;

struct {
    int x;
    int y;
}a[10];

int dist(int x1, int y1, int x2, int y2)
{
// function to compute the (square of the) distance between two points
    int c1, c2;
    c1 = x2-x1;
    c2 = y2-y1;
    return (c1*c1)+(c2*c2);
}

int main()
{
    int d1, d2, d3, d4;
    for (int i=1; i<=4; i++)
    {
        cout << 'X' << i << '='; cin >> a[i].x;
        cout << 'Y' << i << '='; cin >> a[i].y;
    }
    d1 = dist(a[1].x, a[1].y, a[2].x, a[2].y);
    d2 = dist(a[2].x, a[2].y, a[3].x, a[3].y);
    d3 = dist(a[3].x, a[3].y, a[4].x, a[4].y);
    d4 = dist(a[4].x, a[4].y, a[1].x, a[1].y);
    if(d1==d2 && d1==d3 && d1==d4)
        cout << "Is a square";
    else
        cout << "Is not a square";
    return 0;
}

The code works well enough, but I want to read multiple coordinates (more than four) and check every possible combination of four points to see if they make a square.该代码运行良好,但我想读取多个坐标(超过四个)并检查四个点的每个可能组合以查看它们是否构成正方形。

I can't figure out how to extend the method above to work with more than four points as input (and selecting all combination of four from that);我无法弄清楚如何扩展上述方法以使用四个以上的点作为输入(并从中选择四个的所有组合); can anyone give me a hint/hand please?任何人都可以给我一个提示/手吗?

This sounds like a complete-graph problem.这听起来像是一个完整的图问题。 Since all points are int's, one thing I can think of is doing a depth-first search, without duplicates, with the distance^2 as the weight.由于所有点都是整数,我能想到的一件事是进行深度优先搜索,没有重复,以距离 ^ 2 作为权重。 And you sorta need a dual-pseudograph to keep the angle info (a boolean suffices for right-angle vs non-right-angle).并且您需要一个双伪图来保存角度信息(布尔值对于直角和非直角就足够了)。

Start from a point 0 , step to the nearest neighbor 1, and then, start from the neighbor 1, find its neighbors 2,3,4 ..., and filter on two criteria: distance and angle.从点 0 开始,一步到最近的邻居 1,然后,从邻居 1 开始,找到它的邻居 2,3,4 ...,并根据两个条件过滤:距离和角度。 Each depth-first search needs only 4 steps max, since there are only 4 sides.每个深度优先搜索最多只需要 4 步,因为只有 4 个边。

Iterate through all points, and book-keeping visited points, you may track how many squares made during the way.遍历所有点,并记录访问点,您可以跟踪在此过程中制作了多少个正方形。

Here is some code that checks all combinations of four points to see if they are square.下面是一些检查四个点的所有组合以查看它们是否为正方形的代码。 Note that your original method for testing "square" was faulty - first, even if points were given in the correct order, a diamond shape would (wrongly) be called "square";请注意,您测试“正方形”的原始方法是错误的——首先,即使点以正确的顺序给出,菱形也会(错误地)被称为“正方形”; second, if points were given in the "wrong" order, a square might not look square.其次,如果点以“错误”的顺序给出,一个正方形可能看起来不是正方形。

I fixed both those issues.我解决了这两个问题。 Also, I created a simple nested loop that generates all possible combinations of four points and tests them;此外,我创建了一个简单的嵌套循环,它生成四个点的所有可能组合并对其进行测试; this can be made much more efficient (for example, if points 1,2 and 3 do not form a "isosceles right triangle" there is no point to test the fourth point - so you can save a lot of time by not testing for all other possible points).这可以提高效率(例如,如果点 1,2 和 3 不形成“等腰直角三角形”,则没有必要测试第四点 - 因此您可以通过不测试所有点来节省大量时间其他可能的点)。 I will leave that for another time.我会留着下一次。

I did not bother writing the "input N points" part of the code - I don't think that is what you were struggling with.我没有费心编写代码的“输入 N 点”部分——我认为这不是你所苦恼的。 Let me know if I was wrong to assume that.让我知道我的假设是否错误。

#include <iostream>

typedef struct{
  int x;
  int y;
} point;

int isSquare (point *p1, point *p2, point *p3, point *p4) {
double dx, dy;
double dd[6];
point *pp[4];

pp[0]=p1; pp[1]=p2; pp[2]=p3; pp[3]=p4;
int ii, jj, kk, nn;
kk = 0;
// loop over all combinations of first and second point
// six in all
for(ii=0; ii<3; ii++) {
  for(jj=ii+1; jj<4; jj++) {
    dx = pp[ii]->x - pp[jj]->x;
    dy = pp[ii]->y - pp[jj]->y;
    dd[kk]= dx*dx + dy*dy;
    if (dd[kk]==0) return 0; // two identical points: not a square
    if(kk>1) {
      for(nn= 0; nn < kk-1; nn++) {
        // if both are "sides", we expect their length to be the same;
        // if one is a diagonal and the other a side, their ratio is 2
        // since we are working with the square of the number
        if (!(((2*dd[nn] == dd[kk] ) || (dd[nn] == dd[kk]) || 2*dd[kk] == dd[nn] ))) return 0;
      }
    }
     kk++;
  }
}
return 1; // got here: all combinations tested OK, we have a square

}

int main(void) {
  // pick ten numbers - chosen so there are two squares
  point p[10]={{1,2},{3,2},{1,4},{7,8},{2,4},{3,4},{6,7},{8,7},{2,5},{3,5}};
  double d2[10][10];
  int ii, jj, kk, ll;
  // loop over all possible combinations: 
  // since there are just four to pick we can hard-wire the loop
  for(ii=0; ii<7; ii++) {
    for(jj = ii+1; jj<8; jj++) {
      for(kk = jj+1; kk<9; kk++) {
        for(ll = kk+1; ll<10; ll++) {
          if(isSquare(p+ii, p+jj, p+kk, p+ll)) {
            std::cout << "combination: " << ii << "," << jj << "," << kk << "," << ll << " is a square\n";
          }
        }
      }
    }
  }
}

Output:输出:

combination: 0,1,2,5 is a square
combination: 4,5,8,9 is a square

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM