Geometry 两个矩形之间的差(XOR),作为矩形?

Geometry 两个矩形之间的差(XOR),作为矩形?,geometry,rectangles,Geometry,Rectangles,我正在寻找一种简单的方法来计算两个矩形之间的差。我指的是属于其中一个矩形的所有点,但不是同时属于这两个矩形(所以它类似于XOR) 在这种情况下,矩形与轴对齐,因此只有直角。我相信差异区域可以用0-4个矩形表示(如果两个矩形相同,则为0,如果只有一条边不同,则为1,在一般情况下为4),我希望将差异区域作为矩形列表 您还可以将其视为在移动实心矩形/调整其大小时必须更新的屏幕区域 示例:将矩形“a”的宽度加倍-我想要添加的区域(R) 相交矩形(a和b)-我想要T、L、R和b在矩形中给出的面积(其他分区

我正在寻找一种简单的方法来计算两个矩形之间的差。我指的是属于其中一个矩形的所有点,但不是同时属于这两个矩形(所以它类似于XOR)

在这种情况下,矩形与轴对齐,因此只有直角。我相信差异区域可以用0-4个矩形表示(如果两个矩形相同,则为0,如果只有一条边不同,则为1,在一般情况下为4),我希望将差异区域作为矩形列表

您还可以将其视为在移动实心矩形/调整其大小时必须更新的屏幕区域

示例:将矩形“a”的宽度加倍-我想要添加的区域(R)

相交矩形(a和b)-我想要T、L、R和b在矩形中给出的面积(其他分区可能),但不包括X:

+------------+  a
|      T     |
|·····+------+-----+  b
|  L  | X    |  R  |
|     |      |     |
+-----+------+·····|
      |    B       |
      +------------+

我更喜欢python解决方案/库,但任何健壮的算法都会有帮助。

我会想象找到相交矩形(即X)的面积,然后从矩形a+矩形b的组合面积中减去该面积将给出您的解决方案

我在寻找快速答案时发现:


将问题分解到每个轴上。可以根据每个轴上的跨距定义矩形-在每个轴上找到矩形开始或结束的有趣点,然后用这些术语定义结果。这将为您提供6个不同区域的矩形,您可以轻松地将它们合并为您所演示的四个,或者根据需要消除退化的零区域矩形

下面是一个Java实现:

public class Rect
{
    private float minX, maxX, minY, maxY;

    public Rect( float minX, float maxX, float minY, float maxY )
    {
        this.minX = minX;
        this.maxX = maxX;
        this.minY = minY;
        this.maxY = maxY;
    }

    /**
     * Finds the difference between two intersecting rectangles
     * 
     * @param r
     * @param s
     * @return An array of rectangle areas that are covered by either r or s, but
     *         not both
     */
    public static Rect[] diff( Rect r, Rect s )
    {
        float a = Math.min( r.minX, s.minX );
        float b = Math.max( r.minX, s.minX );
        float c = Math.min( r.maxX, s.maxX );
        float d = Math.max( r.maxX, s.maxX );

        float e = Math.min( r.minY, s.minY );
        float f = Math.max( r.minY, s.minY );
        float g = Math.min( r.maxY, s.maxY );
        float h = Math.max( r.maxY, s.maxY );

        // X = intersection, 0-7 = possible difference areas
        // h +-+-+-+
        // . |5|6|7|
        // g +-+-+-+
        // . |3|X|4|
        // f +-+-+-+
        // . |0|1|2|
        // e +-+-+-+
        // . a b c d

        Rect[] result = new Rect[ 6 ];

        // we'll always have rectangles 1, 3, 4 and 6
        result[ 0 ] = new Rect( b, c, e, f );
        result[ 1 ] = new Rect( a, b, f, g );
        result[ 2 ] = new Rect( c, d, f, g );
        result[ 3 ] = new Rect( b, c, g, h );

        // decide which corners
        if( r.minX == a && r.minY == e || s.minX == a && s.minY == e )
        { // corners 0 and 7
            result[ 4 ] = new Rect( a, b, e, f );
            result[ 5 ] = new Rect( c, d, g, h );
        }
        else
        { // corners 2 and 5
            result[ 4 ] = new Rect( c, d, e, f );
            result[ 5 ] = new Rect( a, b, g, h );
        }

        return result;
    }
}

此链接中有一个算法:

它被称为“四区矩形差”

它基本上计算了从一个矩形减去另一个矩形后可能保留的四个矩形

在这种情况下,算法必须运行两次

public class Rect
{
    private float minX, maxX, minY, maxY;

    public Rect( float minX, float maxX, float minY, float maxY )
    {
        this.minX = minX;
        this.maxX = maxX;
        this.minY = minY;
        this.maxY = maxY;
    }

    /**
     * Finds the difference between two intersecting rectangles
     * 
     * @param r
     * @param s
     * @return An array of rectangle areas that are covered by either r or s, but
     *         not both
     */
    public static Rect[] diff( Rect r, Rect s )
    {
        float a = Math.min( r.minX, s.minX );
        float b = Math.max( r.minX, s.minX );
        float c = Math.min( r.maxX, s.maxX );
        float d = Math.max( r.maxX, s.maxX );

        float e = Math.min( r.minY, s.minY );
        float f = Math.max( r.minY, s.minY );
        float g = Math.min( r.maxY, s.maxY );
        float h = Math.max( r.maxY, s.maxY );

        // X = intersection, 0-7 = possible difference areas
        // h +-+-+-+
        // . |5|6|7|
        // g +-+-+-+
        // . |3|X|4|
        // f +-+-+-+
        // . |0|1|2|
        // e +-+-+-+
        // . a b c d

        Rect[] result = new Rect[ 6 ];

        // we'll always have rectangles 1, 3, 4 and 6
        result[ 0 ] = new Rect( b, c, e, f );
        result[ 1 ] = new Rect( a, b, f, g );
        result[ 2 ] = new Rect( c, d, f, g );
        result[ 3 ] = new Rect( b, c, g, h );

        // decide which corners
        if( r.minX == a && r.minY == e || s.minX == a && s.minY == e )
        { // corners 0 and 7
            result[ 4 ] = new Rect( a, b, e, f );
            result[ 5 ] = new Rect( c, d, g, h );
        }
        else
        { // corners 2 and 5
            result[ 4 ] = new Rect( c, d, e, f );
            result[ 5 ] = new Rect( a, b, g, h );
        }

        return result;
    }
}