Module moog.observers.polygon_modifiers

Polygon modifier classes.

These classes are used to modify polygons (sprite vertex arrays, colors, and opacities), typically before rendering. They can be used to adjust polygon positions to render first-person, duplicate sprites when simulating torus geometry, etc.

Expand source code
"""Polygon modifier classes.

These classes are used to modify polygons (sprite vertex arrays, colors, and
opacities), typically before rendering. They can be used to adjust polygon
positions to render first-person, duplicate sprites when simulating torus
geometry, etc.
"""

import abc
import numpy as np


class AbstractPolygonModifier(abc.ABC):
    """Abstract polygon modifier class.
    
    All polygon modifiers must inherit from this class.
    """
    
    @abc.abstractmethod
    def __call__(self, state):
        """Get polygon modifier.
        
        Args:
            state: Environment state.

        Returns:
            Function taking in list of polygons and returning list of polygons.
        """
        pass


class DoNothing(AbstractPolygonModifier):
    """Does not modify polygons."""
    
    def __call__(self, state):
        def _do_nothing(_, sprite):
            return [(sprite.vertices, sprite.color, sprite.opacity)]
        return _do_nothing


class FirstPersonAgent(AbstractPolygonModifier):
    """Modifies polygon positions to put an agent sprite at [0.5, 0.5]."""

    def __init__(self, agent_layer):
        """Constructor.

        Args:
            first_person_agent: String. Will apply a translation such that the
                agent sprite (first sprite in this layer) is at position
                [0.5, 0.5].
        """
        self._agent_layer = agent_layer

    def __call__(self, state):
        """Get polygon modifier that translates lists of polygons."""
        agents = state[self._agent_layer]
        agent_position = agents[0].position
        delta_position = np.array([0.5, 0.5]) - agent_position
        def _sprite_to_polygons(layer, sprite):
            outs = [
                (sprite.vertices + delta_position, sprite.color, sprite.opacity)
            ]
            return outs
        return _sprite_to_polygons


class TorusGeometry(AbstractPolygonModifier):
    """Duplicates polygons at a grid of positions.
    
    Specifically, duplicates polygons at a 3x3 grid of positions centered around
    [0, 0] + polygon_position. This is used in torus environments to make a
    sprite appear to smoothly and incrementally disappear off one edge of the
    arena and reappear on the opposite edge.
    """

    def __init__(self, wrap_layers):
        """Constructor.

        Args:
            wrap_layers: String or iterable of strings. All sprites in these
                layers will be rendered as if the arena is a torus.
        """
        if not isinstance(wrap_layers, (list, tuple)):
            wrap_layers = [wrap_layers]
        self._wrap_layers = wrap_layers

    def __call__(self, state):
        """Get polygon modifier rendering sprites as if the arena is a torus."""
        del state
        def _sprite_to_polygons(layer, sprite):
            squared_polygons = [
                (sprite.vertices + np.array([i, j]), sprite.color,
                 sprite.opacity)
                for i in [-1., 0., 1.]
                for j in [-1., 0., 1.]
            ]
            return squared_polygons
        return _sprite_to_polygons

Classes

class AbstractPolygonModifier

Abstract polygon modifier class.

All polygon modifiers must inherit from this class.

Expand source code
class AbstractPolygonModifier(abc.ABC):
    """Abstract polygon modifier class.
    
    All polygon modifiers must inherit from this class.
    """
    
    @abc.abstractmethod
    def __call__(self, state):
        """Get polygon modifier.
        
        Args:
            state: Environment state.

        Returns:
            Function taking in list of polygons and returning list of polygons.
        """
        pass

Ancestors

  • abc.ABC

Subclasses

class DoNothing

Does not modify polygons.

Expand source code
class DoNothing(AbstractPolygonModifier):
    """Does not modify polygons."""
    
    def __call__(self, state):
        def _do_nothing(_, sprite):
            return [(sprite.vertices, sprite.color, sprite.opacity)]
        return _do_nothing

Ancestors

class FirstPersonAgent (agent_layer)

Modifies polygon positions to put an agent sprite at [0.5, 0.5].

Constructor.

Args

first_person_agent
String. Will apply a translation such that the agent sprite (first sprite in this layer) is at position [0.5, 0.5].
Expand source code
class FirstPersonAgent(AbstractPolygonModifier):
    """Modifies polygon positions to put an agent sprite at [0.5, 0.5]."""

    def __init__(self, agent_layer):
        """Constructor.

        Args:
            first_person_agent: String. Will apply a translation such that the
                agent sprite (first sprite in this layer) is at position
                [0.5, 0.5].
        """
        self._agent_layer = agent_layer

    def __call__(self, state):
        """Get polygon modifier that translates lists of polygons."""
        agents = state[self._agent_layer]
        agent_position = agents[0].position
        delta_position = np.array([0.5, 0.5]) - agent_position
        def _sprite_to_polygons(layer, sprite):
            outs = [
                (sprite.vertices + delta_position, sprite.color, sprite.opacity)
            ]
            return outs
        return _sprite_to_polygons

Ancestors

class TorusGeometry (wrap_layers)

Duplicates polygons at a grid of positions.

Specifically, duplicates polygons at a 3x3 grid of positions centered around [0, 0] + polygon_position. This is used in torus environments to make a sprite appear to smoothly and incrementally disappear off one edge of the arena and reappear on the opposite edge.

Constructor.

Args

wrap_layers
String or iterable of strings. All sprites in these layers will be rendered as if the arena is a torus.
Expand source code
class TorusGeometry(AbstractPolygonModifier):
    """Duplicates polygons at a grid of positions.
    
    Specifically, duplicates polygons at a 3x3 grid of positions centered around
    [0, 0] + polygon_position. This is used in torus environments to make a
    sprite appear to smoothly and incrementally disappear off one edge of the
    arena and reappear on the opposite edge.
    """

    def __init__(self, wrap_layers):
        """Constructor.

        Args:
            wrap_layers: String or iterable of strings. All sprites in these
                layers will be rendered as if the arena is a torus.
        """
        if not isinstance(wrap_layers, (list, tuple)):
            wrap_layers = [wrap_layers]
        self._wrap_layers = wrap_layers

    def __call__(self, state):
        """Get polygon modifier rendering sprites as if the arena is a torus."""
        del state
        def _sprite_to_polygons(layer, sprite):
            squared_polygons = [
                (sprite.vertices + np.array([i, j]), sprite.color,
                 sprite.opacity)
                for i in [-1., 0., 1.]
                for j in [-1., 0., 1.]
            ]
            return squared_polygons
        return _sprite_to_polygons

Ancestors