如何确保给定的一组点位于可能的正方形的边界上?

时间:2014-02-24 16:32:12

标签: c++ algorithm geometry computational-geometry

给定一组积分坐标,检查给定的所有点是否位于可能的正方形的一侧,使得如此形成的正方形的轴平行于X轴和Y轴。如果这样的正方形可以给出正方形的最小可能边。

假设点数为(0,0)(1,1)(2,2) 答:方块是不可能的。

假设点数为(0,0)(0,2)(0,5)(0,7),`(3,0)。
答案:方块是可能的,边的最小长度是7。

我尝试了它并提出了许多角落案件,似乎不可能单独处理它们。我想知道是否有人可以对这类问题采取更一般化的方法,以及如何思考正确的方向。 提前致谢。 坐标范围:-1000 <= x ,y <= 1000

点数是&lt; = 50

新编辑: 还有一个角落案例: (2,0),(0,4),(1,5),(5,3) 答案:长度为5的正方形。正方形的角点是(0,0),(0,5),(5,5),(5,0)

4 个答案:

答案 0 :(得分:4)

如果您通过xminxmaxyminymax定义方格,那么所有点都必须位于其中一个坐标上。即如果适用于所有顶点v

,则方形有效
v.x == xmin || v.x == xmax || v.y == ymin || v.y == ymax

边界的候选者是点的边界矩形的边界。如果计算这些边界,请维护每个边的顶点列表。

如果无法将每个顶点分配给边,则无法创建方形。

现在矩形很可能不是正方形。所以我们需要扩大其最短的一面。如果我们选择了侧面,我们需要选择是否移动最小或最大边缘。这就是关联顶点列表发挥作用的地方。要移动边缘,请检查所有关联的顶点是否也与另一条边相关联。然后移动这个边缘是安全的。如果我们既不能移动最小边缘也不能移动最大边缘,则无法创建正方形。

得到的最小边长是边的距离。

答案 1 :(得分:1)

轴的要求有助于我们进行以下观察

  1. 每个这样的正方形都由两条平行垂直线限定,并且该垂直线上的每个点都具有相同的X坐标。我们称之为坐标maxXminX。 (其中一个比其他小)
  2. 每个这样的正方形都由两条平行的水平线界定,并且该垂直线上的每个点都具有相同的Y坐标。我们称之为坐标maxYminY
  3. 这一点至关重要:输入列表中的每个点必须具有匹配maxXminX的X坐标或匹配maxYminY的Y坐标。 (注意OR。如果有一个点都不匹配,比如前面例子中的(1, 1),你有一个反例)。
  4. 这是一个类似c ++的伪代码来计算这些数量。假设您有一个合适的Point结构。

    bool isSquare(vector<Point> points) { 
       double maxX = points[0].X;
       double minX = points[0].X;
       double maxY = points[0].Y;
       double minY = points[0].Y;
    
       // set maxX, minX, maxY, minY
       for(int i = 0; i < points.size(); i++) {
          maxX = max(points[i].X, maxX);
          minX = min(points[i].X, minX);
          maxY = max(points[i].Y, maxY);
          minY = min(points[i].Y, minY);
       }
    
       // Finally, find a point which matches neither {maxX, minX, maxY, minY}
       for(int i = 0; i < points.size(); i++) {
          if (points[i].X != maxX && points[i].X != minX && points[i].Y != maxY && points[i].Y != minY) return false;
        }
    
        // We are not done yet!
     }
    

    现在通过此代码中的检查确保点至少形成一个矩形,内部矩形没有点。确保矩形是square是更难的部分。对于那部分,您必须检查:

    1. 一个点在矩形的角上。,即它的X坐标匹配{maxX, minX}并且它的Y坐标匹配{maxY, minY}。如果找到,则需要找到相应边缘上任何其他点的最大距离。
    2. 如果没有这样的角落,你会好多了!在这种情况下,正方形的长度只是max(maxX-minX, maxY-minY)
    3. 在为这个角落寻找部分编写伪代码时需要小心,并考虑所有情况。但我认为一旦完成,这最终会给出答案。

答案 2 :(得分:1)

我想在一次通过中想办法做到这一点,但是在这里已经很晚了,我很累,所以......

  • 运行所有元素一次,并记录整个集合的最小和最大xy值。正方形的边长(如果存在)将为max(xmax-xmin, ymax-ymin)

  • 再次通过积分。要描述与轴平行的方形,每个点必须

    x == xmin || x == xmax || y == ymin || y == ymax

    即,至少一个坐标必须位于正方形的一侧。如果任何一点失败,那么你没有一个正方形。

我很确定这已经足够了,但是分两步完成它似乎不太理想。这是一个有趣的问题,祝你好运。

答案 3 :(得分:0)

您可以使用Axis Aligned Bounding Box(ABB)的常见概念解决这个问题。给定一组点,计算ABB: 循环遍历所有点并找到最小x,最小y,最大x和最大y。然后,需要针对所有点检查由两个角,左下角(min_x,min_y)和右上角(max,max y)定义的框,以查看它们是否位于其周边。由于坐标是积分的(没有浮点误差),因此很容易做到:对于每个点,x坐标或y坐标必须与AAB的相应坐标匹配,而另一个坐标必须在其他坐标。希望这是有道理的。