"""
Maestro 3D polygons.
The polygon module allows creation and drawing of polygons. Clients draw using
Group instances not through Polygon instances.
Control over the vertices, color, and transparency of a polygon are provided.
See the Polygon class for more info.
To draw any number of polygons create the Polygon instances and add them to a
Group instance (PolygonGroup can be used and is a synonym). Then invoke the
Group's draw() method.
Copyright Schrodinger, LLC. All rights reserved.
"""
from schrodinger import get_maestro
from . import common
from .common import FILL
from .common import LINE
from .common import OPACITY_DEFAULT
from .common import OPACITY_MAX
from .common import OPACITY_MIN
from .common import Group
# NOTE: PolygonGroup is deprecated; use Group class.
PolygonGroup = Group
maestro = get_maestro()
# Constants used to calculate bounding box:
BOUNDING_BOX_INIT_VALUE = 100000000.0
[docs]class MaestroPolygon(common.Primitive):
[docs]    def __init__(self,
                 vertices,
                 color=None,
                 opacity=OPACITY_DEFAULT,
                 style=FILL):
        """
        Creates polygon object in Maestro.
        Constructor requires:
        vertices: List of vertex coordinates (x, y, z).
                  Specify at least 3 vertices in consecutive order.
                  All vertices must be in the same plane.
        color:    One of:
                    Color object (Color class)
                    Color name (string)
                    Tuple of (R, G, B) (each a float in range 0.0-1.0)
        Optional arguments:
        opacity:  0.0 (invisible) through 1.0 (opaque)
                       Defaults to 1.0
        style:    LINE or FILL.  Default is FILL.
        """
        self.vertices = []
        if not vertices:
            raise ValueError("Must specify vertices to define the polygon")
        else:
            self._checkVertexArgument(vertices)
        # Assume each item is a list of 3 x, y, z ordinates
        for i in range(len(vertices)):
            self.vertices.append([float(item) for item in vertices[i]])
        self.normal = common.create_normal(self.vertices)
        if len(self.vertices) < 3:
            raise ValueError("Must specify at least 3 vertices")
        if color is None:
            raise ValueError("Must specify a color")
        self.r, self.g, self.b = common.color_arg_to_rgb(color)
        # Clamp to range of 0.0 and 1.0, inclusive
        opacity = float(opacity)
        if opacity < OPACITY_MIN:
            self.opacity = OPACITY_MIN
        elif opacity > OPACITY_MAX:
            self.opacity = OPACITY_MAX
        else:
            self.opacity = opacity
        if (style != FILL and style != LINE):
            raise ValueError(
                "Must specify a valid style: FILL or LINE (see common.py)")
        else:
            self.style = style
        self.polygon = maestro.create_polygon(vertices, self.r, self.g, self.b,
                                              opacity)
        maestro_objects = [self.polygon]
        common.Primitive.__init__(self, maestro_objects) 
    def _checkVertexArgument(self, vertices):
        """
        Private method to check if the vertices are in the coorect format
        """
        errmsg = "Specify at least 3 vertices.  You passed:\n" + \
                 
("%s.  \nPass in " % str(vertices)) + \
                 
"a list of vertex lists: " + \
                 
"[[x,y,z], [x,y,z], [x,y,z], ..., [x,y,z]]"
        # Check to make sure we have vertices specified
        # as n lists each of [x, y, z]
        if not isinstance(vertices, list):
            raise TypeError(errmsg)
        elif len(vertices) < 3:
            # Need at least 3 coordinates - 3 or more x,y,z lists
            raise TypeError(errmsg)
        elif isinstance(vertices[0], list) and len(vertices[0]) % 3 != 0:
            # Every 3 makes a coordinate.  We don't check every
            # sub-list, just the first.
            raise TypeError(errmsg)
        return
    def _calculateBoundingBox(self, mat):
        xyzmin = []
        xyzmax = []
        for k in range(6):
            xyzmin.append(BOUNDING_BOX_INIT_VALUE)
            xyzmax.append(-BOUNDING_BOX_INIT_VALUE)
        tmp = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
        for vertex in self.vertices:
            for k in range(3):
                tmp[k + 3] = vertex[k]
            tmp[0] = mat[0][0] * tmp[3] + mat[0][1] * tmp[4] + mat[0][2] * tmp[
                5] + mat[0][3]
            tmp[1] = mat[1][0] * tmp[3] + mat[1][1] * tmp[4] + mat[1][2] * tmp[
                5] + mat[1][3]
            tmp[2] = mat[2][0] * tmp[3] + mat[2][1] * tmp[4] + mat[2][2] * tmp[
                5] + mat[2][3]
            for k in range(6):
                if xyzmin[k] > tmp[k]:
                    xyzmin[k] = tmp[k]
                if xyzmax[k] < tmp[k]:
                    xyzmax[k] = tmp[k]
        return (xyzmin, xyzmax)