Intersection and difference of two rectangles

前端 未结 3 1030
梦如初夏
梦如初夏 2020-12-06 14:49

Searching the internet has not given a satisfactory solution for the following problem. Given a class Rectangle defined as the following:

class          


        
3条回答
  •  刺人心
    刺人心 (楼主)
    2020-12-06 15:14

    Oleh Prypin was extremely helpful with the provided code. The following is a refactored version of the same.

    from itertools import product, tee
    
    def test():
        print('Example 1:')
        a = Rectangle(1, 1, 5, 5)
        b = Rectangle(3, 3, 7, 7)
        print(a & b)
        print(list(a - b))
        ##########################
        print('Example 2:')
        b = Rectangle(3, 2, 7, 4)
        print(a & b)
        print(list(a - b))
        ##########################
        print('Example 3:')
        b = Rectangle(2, 2, 4, 4)
        print(a & b)
        print(list(a - b))
        ##########################
        print('Example 4:')
        b = Rectangle(6, 2, 10, 6)
        print(a & b)
        print(list(a - b))
        ##########################
        print('Example 5:')
        b = Rectangle(0, 0, 6, 6)
        print(a & b)
        print(list(a - b))
        ##########################
        print('Example 6:')
        b = Rectangle(2, 0, 4, 6)
        print(a & b)
        print(list(a - b))
    
    def pairwise(iterable):
        "s -> (s0, s1), (s1, s2), (s2, s3), ..."
        a, b = tee(iterable)
        next(b, None)
        return zip(a, b)
    
    class Rectangle:
    
        __slots__ = '__x1', '__y1', '__x2', '__y2'
    
        def __init__(self, x1, y1, x2, y2):
            self.__setstate__((min(x1, x2), min(y1, y2), max(x1, x2), max(y1, y2)))
    
        def __repr__(self):
            return '{}({})'.format(type(self).__name__, ', '.join(map(repr, self)))
    
        def __eq__(self, other):
            return self.data == other.data
    
        def __ne__(self, other):
            return self.data != other.data
    
        def __hash__(self):
            return hash(self.data)
    
        def __len__(self):
            return 4
    
        def __getitem__(self, key):
            return self.data[key]
    
        def __iter__(self):
            return iter(self.data)
    
        def __and__(self, other):
            x1, y1, x2, y2 = max(self.x1, other.x1), max(self.y1, other.y1), \
                             min(self.x2, other.x2), min(self.y2, other.y2)
            if x1 < x2 and y1 < y2:
                return type(self)(x1, y1, x2, y2)
    
        def __sub__(self, other):
            intersection = self & other
            if intersection is None:
                yield self
            else:
                x, y = {self.x1, self.x2}, {self.y1, self.y2}
                if self.x1 < other.x1 < self.x2:
                    x.add(other.x1)
                if self.y1 < other.y1 < self.y2:
                    y.add(other.y1)
                if self.x1 < other.x2 < self.x2:
                    x.add(other.x2)
                if self.y1 < other.y2 < self.y2:
                    y.add(other.y2)
                for (x1, x2), (y1, y2) in product(pairwise(sorted(x)),
                                                  pairwise(sorted(y))):
                    instance = type(self)(x1, y1, x2, y2)
                    if instance != intersection:
                        yield instance
    
        def __getstate__(self):
            return self.x1, self.y1, self.x2, self.y2
    
        def __setstate__(self, state):
            self.__x1, self.__y1, self.__x2, self.__y2 = state
    
        @property
        def x1(self):
            return self.__x1
    
        @property
        def y1(self):
            return self.__y1
    
        @property
        def x2(self):
            return self.__x2
    
        @property
        def y2(self):
            return self.__y2
    
        @property
        def width(self):
            return self.x2 - self.x1
    
        @property
        def height(self):
            return self.y2 - self.y1
    
        intersection = __and__
    
        difference = __sub__
    
        data = property(__getstate__)
    
    if __name__ == '__main__':
        test()
    

提交回复
热议问题