0

我花了一些时间寻找合适的方法来解决特定矩形放置的问题。

让我们直接进入问题。

我有两个固定大小的矩形。其中一个被锁定,不能移动,另一个可以自由移动。

我有两个放在固定宽度和高度的画布上。假设它是1000x1000。

我需要将第二个可移动的矩形与另一个锁定的矩形水平或垂直对齐,而可移动的矩形不能超出 1000x1000 画布的范围。

我在水平/垂直对齐的定义下所理解的是,如果您仅查看 X(用于水平)或 Y(用于垂直)轴,则您将锁定一个在可移动的一种或另一种方式内。

我知道我可以通过 hack 解决我的问题,但我想找到任何更聪明的解决方案。

有什么建议么?

编辑:关于两个矩形的所有信息都是已知的。角,宽度/高度。

4

1 回答 1

1

给定一个在某个 X[-inf, +inf] 轴上的坐标平面和一个标称 Y[-inf, +inf] 轴,如果两个点在水平轴上的坐标(我们选择 X)可以说是垂直对齐的是平等的。如果它们在垂直轴 (Y) 上的坐标相等,则可以说它们处于水平对齐状态。

一个矩形可以用两对坐标 (x1, y1) 和 (x2, y2) 来描述,使得 x1 <= x2,并且 y1 <= y2。(如果您的配对混合在一起,您实际上可以重新排列它们以使用这种格式 - 它会让您的生活更轻松。)

当且仅当 r1.x1 >= r2.x1、r1.y1 >= r2.y1、r1.x2 <= r2.x2 和 r1 时,可以说一个矩形 (r1) 位于另一个矩形 (r2) 内。 y2 <= r2.y2 都成立。请注意,无论您在哪个象限,或者您的轴在哪个方向运行,这都是正确的。

当且仅当 r1.x1 和 r1.x2 都在范围之外 (r2.x1, r2.x2) 并且 r1.y1 和 r1.y2 都在范围之外时,可以说一个矩形 (r1) 位于另一个矩形 (r2) 之外超出范围 (r2.y1, r2.y2)。请注意,这包括 r2 在 INSIDE r1 的情况。

一个矩形 (r1) 可以说是与另一个矩形 (r2) 分开的,当且仅当它在那个矩形之外,并且那个矩形不在它里面。(即:r1 OUTSIDE r2 && NOT r2 INSIDE r1)

一个矩形 (r1) 可以说与另一个矩形 (r2) 重叠当且仅当它既不在该矩形的内部也不在该矩形的外部。(或者,您可以选择声称完全在另一个矩形内的矩形是有效重叠,并说 OVERLAP = !SEPARATE。取决于您的应用程序。)

矩形的对齐要困难得多。SAME EXACT size 的 Rectangles 可以说是和 points 一样对齐(使用每个矩形的 (x1, y1) 作为你的参考点。对于 Rectangles of Differing size,我建议你使用中心点作为参考:如果 (r1.x1+r1.x2)/2 = (r2.x1+r2.x2)/2,则矩形垂直对齐,如果 (r1.y1+r1.y2)/2 = (r2.y1 则水平对齐+r2.y2)/2。

我会编写一个包含这些规则的类,并使用它来检查每个动作,使用三个矩形——你提到的两个,第三个是边界框。

CLASS rectangle
    x1
    x2
    y1
    y2
    
    CONSTRUCT(xx1, yy1, xx2, yy2):
        Ensure xx1 <= xx2 and yy1 <= yy2 - swap them if you like
        x1 = xx1, y1 = yy1, x2 = xx2, y2 = yy2

    IS_INSIDE(rectangle r2):
        IF r2.x1<=x1 && r2.y1<=y1 && y2 <= r2.y2 && x2 <= r2.x2:
            RETURN TRUE
        RETURN FALSE
   
    IS_OUTSIDE(rectangle r2):
        IF r2.x1 <= x1 <= r2.x2 || r2.x1 <= x2 <= r2.x2 ||  r2.y1 <= y1 <= r2.y2 || r2.y1 <= y2 <= r2.y2 :
            RETURN FALSE
         RETURN TRUE
   
    IS_SEPARATE(rectangle r2):
        IF IS_OUTSIDE(r2) && ! r2.IS_INSIDE(me):
            RETURN TRUE
        RETURN FALSE

    IS_OVERLAPPED(rectangle r2):
        IF ! IS_OUTSIDE(r2) && ! IS_INSIDE(r2):
            RETURN TRUE
        RETURN FALSE

    IS_VERTICALLY_ALIGNED(rectangle r2):
        IF (x1+x2)/2 = (r2.x1+r2.x2)/2:
            RETURN TRUE
        RETURN FALSE

    IS_HORIZONTALLY_ALIGNED(rectangle r2):
        IF (y1+y2)/2 = (r2.y1+r2.y2)/2:
            RETURN TRUE
        RETURN FALSE

然后你可以写一个非常简单的函数来查看r2是否被有效放置,假设r2是可移动的矩形,r1是固定的,box是一个未显示的矩形,代表画布的边界框:

IS_VALID_PLACEMENT(r2, r1, box):
    //In the bounding box
    IF r2.IS_OUTSIDE(box):
        RETURN FALSE
    
    //Aligned with r1
    IF ! r2.IS_VERTICALLY_ALIGNED(r1) && ! r2.IS_HORIZONTALLY_ALIGNED(r1):
        RETURN FALSE

    //Not overlapping r1
    IF ! r2.IS_SEPARATE(r1):
        RETURN FALSE

    RETURN TRUE

每次盒子移动时都运行它。如果返回 false,则撤消移动,或使用边界逻辑进行邻接。

编辑

我正在重读你的问题,我注意到你对垂直对齐的定义。完全可行:

    IS_VERTICALLY_ALIGNED(rectangle r2):
        IF x1 <= r2.x1 <= r2.x2 <= x2 || r2.x1 <= x1 <= x2 <= r2.x2:
            RETURN TRUE
        RETURN FALSE 

    IS_HORIZONTALLY_ALIGNED(rectangle r2):
        IF y1 <= r2.y1 <= r2.y2 <= y2 || r2.y1 <= y1 <= y2 <= r2.y2:
            RETURN TRUE
        RETURN FALSE
于 2013-10-02T16:34:24.353 回答