Exemple #1
0
 def centrality(self, offset):
     # return 0.0
     offset = Point(
         abs(offset.x),
         offset.y + self.size.y - golden_ratio * 2.0 * self.size.y)
     if offset.y < 0.0:
         y_length = golden_ratio * 2.0 * self.size.y
         if offset.x < golden_ratio * self.size.x:
             return max(((self.size - abs(offset)) / self.size).lower(),
                        0.0)
             return max((y_length + offset.y) / y_length, 0.0)
         else:
             offset = Point(offset.x - golden_ratio * self.size.x,
                            -offset.y)
             x_length = (1.0 - golden_ratio) * self.size.x
             linear = min(
                 max(offset.y - offset.x + x_length, 0.0) /
                 (x_length + y_length), 1.0)
             size = Point((1.0 - linear) * x_length, linear * y_length)
             return max(((size - offset) / size).lower(), 0.0)
     else:
         y_length = (1.0 - golden_ratio) * 2.0 * self.size.y
         linear = min(
             max(offset.y - offset.x + self.size.x, 0.0) /
             (self.size.x + y_length), 1.0)
         size = Point((1.0 - linear) * self.size.x, linear * y_length)
         return max(((size - offset) / size).lower(), 0.0)
Exemple #2
0
 def polygon(self):
     x_size = golden_ratio * self.size.x
     y_size = golden_ratio * 2.0 * self.size.y - self.size.y
     return (Point(-x_size, -self.size.y), Point(x_size, -self.size.y),
             Point(self.size.x,
                   y_size), Point(0.0,
                                  self.size.y), Point(-self.size.x, y_size))
Exemple #3
0
 def centrality(self, offset):
     if offset.y < -self.size.y:
         return 0.0
     else:
         x = abs(offset.x) / ((1.0 - (offset.y + self.size.y) /
                               (2.0 * self.size.y)) * self.size.x)
         if offset.y < -self.size.y / 3.0:
             offset = Point(abs(offset.x), -offset.y - self.size.y / 3.0)
             frac_x = max(offset.x / self.size.x, 2.0 / 3.0)
             # x = abs(offset.x) / ((1.0 - (offset.y + self.size.y) / (2.0 * self.size.y)) * self.size.x)
             y = min(offset.y / (frac_x * 2.0 * self.size.y / 3.0), 1.0)
             linear = offset.y / (self.size.y * 2.0 / 3.0)
             linear **= 2
             # linear = 1.0 - (1.0 - linear) ** 2
             # linear = 1.0
         else:
             offset = Point(abs(offset.x), offset.y + self.size.y / 3.0)
             frac_x = (offset.x / self.size.x) * 3.0 / 2.0
             assert 1.0 - frac_x >= offset.y / (4.0 * self.size.y / 3.0)
             y = offset.y / ((1.0 - frac_x) * 4.0 * self.size.y / 3.0)
             linear = offset.y / (self.size.y * 4.0 / 3.0)
             linear = 1.0 - (1.0 - linear)**2
         linear = 1.0 - (1.0 - linear)**2
         assert 0.0 <= x <= 1.0, x
         assert 0.0 <= y <= 1.0, y
         assert 0.0 <= linear <= 1.0, linear
         # return ((1.0 - y) + (1.0 - x)) / 2.0
         return linear * (1.0 - y) + (1.0 - linear) * (1.0 - x)
Exemple #4
0
 def distance(self, offset):
     offset = abs(offset)
     if offset.x > offset.y:
         size = Point(self.size.x, self.size.y / 3.0)
     else:
         size = Point(self.size.x / 3.0, self.size.y)
     return (offset - size).positive().length()
Exemple #5
0
 def from_model(model):
     if model['name'] in Shape.shapes:
         return Shape.shapes[model['name']](
             size=Point.from_model(model['size']))
     else:
         return Shape.shapes.get(model['name'], CustomRectangle)(
             size=Point.from_model(model['size']), init_name=model['name'])
 def distance(self, offset):
     if offset.y < -self.size.y:
         return (abs(offset) - self.size).positive().length()
     else:
         offset = Point(abs(offset.x), offset.y + self.size.y)
         linear = min(max(offset.y - offset.x + self.size.x, 0.0) / (self.size.x + 2.0 * self.size.y), 1.0)
         size = Point((1.0 - linear) * self.size.x, linear * 2.0 * self.size.y)
         return (offset - size).positive().length()
Exemple #7
0
 def centrality(self, offset):
     offset = abs(offset)
     if offset.x > self.size.x / 3.0:
         size = Point(self.size.x, self.size.y / 3.0)
     elif offset.y > self.size.y / 3.0:
         size = Point(self.size.x / 3.0, self.size.y)
     elif offset.x > offset.y:
         size = Point(self.size.x / 3.0 * 4.0, self.size.y / 3.0)
     else:
         size = Point(self.size.x / 3.0, self.size.y / 3.0 * 4.0)
     return max(((size - offset) / size).lower(), 0.0)
Exemple #8
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
 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
 def random_location(self, provoke_collision=False, min_distance=0.75):
     if isinstance(provoke_collision, Entity):
         entity = provoke_collision
         provoke_collision = True
     elif provoke_collision and len(self.entities) > 0:
         entity = choice(self.entities)
     else:
         provoke_collision = False
     if provoke_collision:
         angle = Point.from_angle(angle=random())
         return entity.center + angle * entity.shape.size * (min_distance + random())
     else:
         return Point.random_instance(Point.zero, Point.one)
    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
Exemple #12
0
 def polygon(self):
     curve_size = (1.0 - cos45) * self.size.x
     return (Point(-self.size.x,
                   -curve_size), Point(-curve_size, -self.size.y),
             Point(curve_size, -self.size.y), Point(self.size.x,
                                                    -curve_size),
             Point(self.size.x, curve_size), Point(curve_size, self.size.y),
             Point(-curve_size, self.size.y), Point(-self.size.x,
                                                    curve_size))
 def polygon(self):
     return (Point(-self.size.x, -self.size.y / 3.0),
             Point(-self.size.x / 3.0, -self.size.y),
             Point(self.size.x / 3.0, -self.size.y),
             Point(self.size.x, -self.size.y / 3.0),
             Point(self.size.x, self.size.y / 3.0),
             Point(self.size.x / 3.0, self.size.y),
             Point(-self.size.x / 3.0, self.size.y),
             Point(-self.size.x, self.size.y / 3.0))
Exemple #14
0
 def from_model(model):
     entity = Entity(shape=Shape.from_model(model['shape']),
                     color=Color.from_model(model['color']),
                     texture=Texture.from_model(model['texture']),
                     center=Point.from_model(model['center']),
                     rotation=model['rotation'])
     entity.id = model['id']
     return entity
 def distance(self, offset):
     offset = Point(abs(offset.x), offset.y + self.size.y - golden_ratio * 2.0 * self.size.y)
     if offset.y < 0.0:
         y_length = golden_ratio * 2.0 * self.size.y
         if offset.x < golden_ratio * self.size.x:
             return max(-offset.y - y_length, 0.0)
         else:
             offset = Point(offset.x - golden_ratio * self.size.x, -offset.y)
             x_length = (1.0 - golden_ratio) * self.size.x
             linear = min(max(offset.y - offset.x + x_length, 0.0) / (x_length + y_length), 1.0)
             size = Point((1.0 - linear) * x_length, linear * y_length)
             return (offset - size).positive().length()
     else:
         y_length = (1.0 - golden_ratio) * 2.0 * self.size.y
         linear = min(max(offset.y - offset.x + self.size.x, 0.0) / (self.size.x + y_length), 1.0)
         size = Point((1.0 - linear) * self.size.x, linear * y_length)
         return (offset - size).positive().length()
 def random_instance(size_range, distortion_range):
     distortion = uniform(*distortion_range)
     if distortion_range[0] < distortion_range[1]:
         distortion_ratio = (distortion - distortion_range[0]) / (distortion_range[1] - distortion_range[0])
         min_size = size_range[0] + (size_range[1] - size_range[0]) * distortion_ratio * 0.5
         size = quadratic_uniform(min_size, size_range[1])
     else:
         size = quadratic_uniform(*size_range)
     return Ellipse(Point(size, size / distortion))
 def __init__(self, size, color):
     assert isinstance(size, int) and size > 0
     assert isinstance(color, str) and color in Color.colors
     super(World, self).__init__(WorldShape(), Color(color, Color.get_rgb(color), 0.0), Texture.get_texture('solid')(), Point.half, 0.0)
     self.relative_topleft = -Point.half
     self.relative_bottomright = Point.half
     self.topleft = Point.zero
     self.bottomright = Point.one
     self.size = Point(size, size)
     self.entities = []
     self.meta = dict()
Exemple #18
0
 def from_model(model):
     return Shape.shapes[model['name']](
         size=Point.from_model(model['size']))
    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
from __future__ import division
from math import cos, pi, sin
from random import choice, random
from shapeworld.world import Point, Shape, Color, Texture


default_resolution = Point(100, 100)


class Entity(object):

    __slots__ = ('id', 'shape', 'color', 'texture', 'center', 'rotation', 'rotation_sin', 'rotation_cos', 'relative_topleft', 'relative_bottomright', 'topleft', 'bottomright', 'collisions')

    def __init__(self, shape, color, texture, center, rotation):
        assert isinstance(shape, Shape)
        assert isinstance(color, Color)
        assert isinstance(texture, Texture)
        assert isinstance(center, Point)
        assert isinstance(rotation, float) and 0.0 <= rotation < 1.0
        self.id = None
        self.shape = shape
        self.color = color
        self.texture = texture
        self.rotation = rotation
        self.rotation_sin = sin(-rotation * 2.0 * pi)
        self.rotation_cos = cos(-rotation * 2.0 * pi)
        self.set_center(center=center)
        self.collisions = dict()

    def __hash__(self):
        assert self.id is not None
Exemple #21
0
 def polygon(self):
     return (Point(-self.size.x,
                   -self.size.y), Point(self.size.x, -self.size.y),
             Point(-self.size.x,
                   self.size.y), Point(self.size.x, self.size.y))
Exemple #22
0
 def centrality(self, offset):
     offset += Point(0.0, self.size.y)
     if offset.y < 0.0:
         return 0.0
     else:
         return max((self.size.x - offset.length()) / self.size.x, 0.0)
Exemple #23
0
 def distance(self, offset):
     offset += Point(0.0, self.size.y)
     if offset.y < 0.0:
         return (abs(offset) - Point(self.size.x, 0.0)).positive().length()
     else:
         return max(offset.length() - self.size.x, 0.0)
Exemple #24
0
 def __init__(self, size):
     if isinstance(size, float):
         size = Point(size, size * 0.5)
     return super(Semicircle, self).__init__(size=size)
Exemple #25
0
 def __init__(self, size):
     if isinstance(size, float):
         size = Point(size, size * sqrt34)
     return super(Triangle, self).__init__(size=size)
Exemple #26
0
 def __init__(self, size):
     if isinstance(size, float):
         size = Point(size, size)
     return super(Cross, self).__init__(size=size)
Exemple #27
0
 def __contains__(self, offset):
     offset += Point(0.0, self.size.y)
     return offset.length() <= self.size.x and offset.y >= 0.0
Exemple #28
0
 def size(self):
     return Point(0.5, 0.5)
Exemple #29
0
 def __init__(self, size):
     if isinstance(size, float):
         size = Point(size, size * cos18)
     return super(Pentagon, self).__init__(size=size)