예제 #1
0
    def not_collides(self,
                     other,
                     ratio=False,
                     symmetric=False,
                     resolution=None):
        if resolution is None:
            resolution = default_resolution
        topleft1 = self.topleft
        bottomright1 = self.bottomright
        topleft2 = other.topleft
        bottomright2 = other.bottomright
        if topleft1.x < topleft2.x and topleft1.y < topleft2.y and bottomright1.x > bottomright2.x and bottomright1.y > bottomright2.y:
            if not ratio:
                return False
            elif symmetric:
                return 0.0
            else:
                return (0.0, 0.0)
        elif bottomright1.distance(topleft1) < bottomright2.distance(topleft2):
            topleft, bottomright = topleft1, bottomright1
        else:
            topleft, bottomright = topleft2, bottomright2

        topleft *= resolution
        bottomright *= resolution
        average_resolution = 0.5 * (resolution.x + resolution.y)
        if ratio:
            granularity = 1.0 / resolution.x / resolution.y
            collision = 0.0
            for _, point in Point.range(topleft, bottomright, resolution):
                distance1 = min(
                    average_resolution * self.distance(point - self.center),
                    1.0)
                distance2 = max(
                    1.0 -
                    average_resolution * other.distance(point - other.center),
                    0.0)
                average_distance = 0.5 * (distance1 + distance2)
                if average_distance > 0.95:
                    collision += granularity * average_distance
            if symmetric:
                return min(collision / self.shape.area,
                           collision / other.shape.area)
            else:
                return (collision / self.shape.area,
                        collision / other.shape.area)
        else:
            min_distance = 1.0 / average_resolution
            for c, point in Point.range(topleft, bottomright, resolution):
                if (self.distance(point - self.center) > min_distance) and (
                        other.distance(point - other.center) <= min_distance):
                    return True
예제 #2
0
    def draw(self, world_array, world_size, draw_fn=None):
        shift = Point(2.0 / world_size.x, 2.0 / world_size.y)
        scale = 1.0 + 2.0 * shift
        topleft = (((self.topleft) / scale) * world_size).max(Point.izero)  # + 0.5 * shift
        bottomright = (((self.bottomright + 2.0 * shift) / scale) * world_size).min(world_size)

        if draw_fn is None:
            color = self.color.get_color()
            world_length = min(*world_size)
            for (x, y), point in Point.range(topleft, bottomright, world_size):
                point = point * scale - shift
                offset = point - self.center
                distance = self.distance(offset)
                if distance == 0.0:
                    # assert offset in self
                    world_array[y, x] = self.texture.get_color(color, offset)
                else:
                    # assert offset not in self
                    distance = max(1.0 - distance * world_length, 0.0)
                    world_array[y, x] = distance * self.texture.get_color(color, offset) + (1.0 - distance) * world_array[y, x]
                # if distance == 0.0:
                #     centrality = self.centrality(offset)
                #     world_array[y, x] = (centrality, centrality, centrality) + (1.0 - centrality) * self.texture.get_color(color, offset)
                # else:
                #     assert self.centrality(offset) == 0.0

        else:
            for (x, y), point in Point.range(topleft, bottomright, world_size):
                point = point * scale - shift
                offset = point - self.center
                world_array[y, x] = draw_fn(value=world_array[y, x], entity=self, offset=offset)

        bounding_box = False
        if bounding_box:  # draw bounding box
            assert draw_fn is None
            x1 = world_size + 1
            x2 = -1
            y1 = world_size + 1
            y2 = -1
            for (x, y), point in Point.range(topleft, bottomright, world_size):
                if x < x1:
                    x1 = x
                if x > x2:
                    x2 = x
                if y < y1:
                    y1 = y
                if y > y2:
                    y2 = y
            for (x, y), point in Point.range(topleft, bottomright, world_size):
                if x == x1 or x == x2 or y == y1 or y == y2:
                    world_array[y, x] = color
예제 #3
0
 def test():
     for shape in Shape.get_shapes():
         shape_cls = Shape.get_shape(name=shape)
         shape_obj = shape_cls.random_instance(size_range=(1.0, 1.0), distortion_range=(2.0, 2.0))
         contains = 0
         for point in Point.range(start=Point(-50, -50), end=Point(50, 50)):
             if point / 100 in shape_obj:
                 contains += 1
         estimated_area = contains / 10000
         assert shape_obj.area <= 1.0, (shape, shape_obj.area)
         assert shape_obj.area == shape_cls.relative_area() or shape_obj.area == shape_cls.relative_area() / empirical_distortion_multiplier, (shape, shape_obj.area, shape_cls.relative_area())
         assert abs(shape_obj.area - estimated_area) < 0.011, (shape, abs(shape_obj.area - estimated_area))
     return True
예제 #4
0
    def collides(self, other, ratio=False, symmetric=False, resolution=None):
        if other.id == self.id:
            if not ratio:
                return True
            elif symmetric:
                return 1.0
            else:
                return (1.0, 1.0)

        if other.id in self.collisions and self.id in other.collisions:
            if not ratio:
                return min(self.collisions[other.id], other.collisions[self.id]) > 0.0
            elif symmetric:
                return min(self.collisions[other.id], other.collisions[self.id])
            else:
                return (self.collisions[other.id], other.collisions[self.id])

        topleft1 = self.topleft
        bottomright1 = self.bottomright
        topleft2 = other.topleft
        bottomright2 = other.bottomright
        if bottomright1.x < topleft2.x or topleft1.x > bottomright2.x or bottomright1.y < topleft2.y or topleft1.y > bottomright2.y:
            if other.id is not None:
                self.collisions[other.id] = 0.0
            if self.id is not None:
                other.collisions[self.id] = 0.0
            if not ratio:
                return False
            elif symmetric:
                return 0.0
            else:
                return (0.0, 0.0)
        else:
            topleft, bottomright = topleft1.max(topleft2), bottomright1.min(bottomright2)

        if resolution is None:
            resolution = default_resolution
        topleft *= resolution
        bottomright *= resolution
        average_resolution = 0.5 * (resolution.x + resolution.y)
        if ratio:
            granularity = 1.0 / resolution.x / resolution.y
            collision = 0.0
            for _, point in Point.range(topleft, bottomright, resolution):
                distance1 = max(1.0 - average_resolution * self.distance(point - self.center), 0.0)
                distance2 = max(1.0 - average_resolution * other.distance(point - other.center), 0.0)
                average_distance = 0.5 * (distance1 + distance2)
                if average_distance > 0.95:
                    collision += granularity * average_distance
            collision1 = collision / self.shape.area
            collision2 = collision / other.shape.area
            if other.id is not None:
                self.collisions[other.id] = collision1
            if self.id is not None:
                other.collisions[self.id] = collision2
            if symmetric:
                return min(collision1, collision2)
            else:
                return (collision1, collision2)
        else:
            min_distance = 1.0 / average_resolution
            for _, point in Point.range(topleft, bottomright, resolution):
                if (self.distance(point - self.center) <= min_distance) and (other.distance(point - other.center) <= min_distance):
                    return True