Exemple #1
0
    def __init__(self):
        # register configuration settings: default camera
        from zeobuilder.gui import fields
        from zeobuilder.gui.fields_dialogs import DialogFieldInfo
        config = context.application.configuration
        config.register_setting(
            "viewer_distance",
            100.0 * angstrom,
            DialogFieldInfo(
                "Default Viewer", (1, 0),
                fields.faulty.Length(
                    label_text="Distance from origin",
                    attribute_name="viewer_distance",
                    low=0.0,
                    low_inclusive=True,
                )),
        )
        config.register_setting(
            "opening_angle",
            0.0,
            DialogFieldInfo(
                "Default Viewer", (1, 1),
                fields.faulty.MeasureEntry(
                    measure="Angle",
                    label_text="Camera opening angle",
                    attribute_name="opening_angle",
                    low=0.0,
                    low_inclusive=True,
                    high=0.5 * numpy.pi,
                    high_inclusive=False,
                    show_popup=False,
                )),
        )
        config.register_setting(
            "window_size",
            25 * angstrom,
            DialogFieldInfo(
                "Default Viewer", (1, 2),
                fields.faulty.Length(
                    label_text="Window size",
                    attribute_name="window_size",
                    low=0.0,
                    low_inclusive=False,
                )),
        )
        config.register_setting(
            "window_depth",
            200.0 * angstrom,
            DialogFieldInfo(
                "Default Viewer", (1, 3),
                fields.faulty.Length(
                    label_text="Window depth",
                    attribute_name="window_depth",
                    low=0.0,
                    low_inclusive=False,
                )),
        )

        self.reset()
Exemple #2
0
class Notes(ModelObject):
    info = ModelObjectInfo("plugins/basic/notes.svg")
    authors = [authors.toon_verstraelen]

    #
    # Properties
    #

    def set_notes(self, notes, init=False):
        self.notes = notes

    properties = [
        Property("notes", StringIO.StringIO(), lambda self: self.notes, set_notes)
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo("Basic", (0, 10), fields.edit.TextView(
            label_text="Notes",
            attribute_name="notes",
        ))
    ])
Exemple #3
0
    def __init__(self, filename):
        self.redirecting = False
        self.filename = filename
        self.dialog_fields = []
        self.settings = {}
        self.load_from_file()
        self.redirecting = True

        # register some general settings
        from zeobuilder.gui import fields
        from zeobuilder.gui.fields_dialogs import DialogFieldInfo

        # 1) Default units
        def corrector_default_units(value):
            for measure, units in units_by_measure.iteritems():
                if (measure not in value) or (value[measure] not in units):
                    value[measure] = units[0]
            return dict((measure, unit) for measure, unit in value.iteritems()
                        if measure in measures)

        self.register_setting(
            "default_units",
            dict((measure, units[0])
                 for measure, units in units_by_measure.iteritems()),
            DialogFieldInfo(
                "General", (0, 0),
                fields.composed.Units(
                    label_text="Default units",
                    attribute_name="default_units",
                )), corrector_default_units)

        # 2) history stuff
        self.register_setting("saved_representations", {})
        self.register_setting("history_representations", {})
        self.register_setting(
            "max_history_length",
            6,
            DialogFieldInfo(
                "General", (0, 1),
                fields.faulty.Int(
                    label_text="Maximum history length for dialog fields",
                    attribute_name="max_history_length",
                    minimum=1)),
        )
Exemple #4
0
class UserColorMixin(gobject.GObject):

    __metaclass__ = NodeClass

    #
    # Properties
    #

    def set_user_color(self, user_color, init=False):
        self.user_color = user_color
        if not init:
            self.invalidate_draw_list()

    properties = [
        Property("user_color",
                 Undefined(numpy.array([0.7, 0.7, 0.7, 1.0])),
                 lambda self: self.user_color,
                 set_user_color,
                 signal=True)
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo(
            "Markup", (1, 7),
            fields.optional.CheckOptional(
                fields.edit.Color(
                    label_text="User defined color",
                    attribute_name="user_color",
                ))),
    ])

    #
    # Draw
    #

    def get_color(self):
        if isinstance(self.user_color, Undefined):
            return self.default_color
        else:
            return self.user_color

    def draw(self):
        context.application.vis_backend.set_color(*self.get_color())
Exemple #5
0
class GLPeriodicContainer(GLContainerBase):

    #
    # Properties
    #

    def update_vectors(self):
        for node in self.children:
            if isinstance(node, GLReferentBase):
                node.invalidate_draw_list()
                node.invalidate_boundingbox_list()

    def set_cell(self, cell, init=False):
        self.cell = cell
        if not init:
            self.invalidate_boundingbox_list()
            self.invalidate_draw_list()
            self.update_vectors()

    #
    # Properties
    #

    properties = [
        Property("cell", default_unit_cell, lambda self: self.cell, set_cell),
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo(
            "Unit cell", (5, 0),
            fields.composed.Cell(
                label_text="Periodic cell",
                attribute_name="cell",
            )),
    ])
Exemple #6
0
class ColorMixin(gobject.GObject):

    __metaclass__ = NodeClass

    #
    # Properties
    #

    def set_color(self, color, init=False):
        self.color = color
        if not init:
            self.invalidate_draw_list()

    properties = [
        Property("color", numpy.array([0.7, 0.7, 0.7, 1.0]),
                 lambda self: self.color, set_color)
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo(
            "Markup", (1, 0),
            fields.edit.Color(
                label_text="Color",
                attribute_name="color",
            ))
    ])

    #
    # Draw
    #

    def draw(self):
        context.application.vis_backend.set_color(*self.color)
Exemple #7
0
class Plane(GLReferentBase, ColorMixin):
    info = ModelObjectInfo("plugins/basic/plane.svg")
    authors = [authors.toon_verstraelen]

    #
    # State
    #

    def set_targets(self, targets, init=False):
        self.set_children([SpatialReference("Point") for target in targets])
        GLReferentBase.set_targets(self, targets, init)

    #
    # Properties
    #

    def set_margin(self, margin, init=False):
        self.margin = margin
        if not init:
            self.invalidate_draw_list()
            self.invalidate_boundingbox_list()

    properties = [
        Property("margin", 1.0, lambda self: self.margin, set_margin),
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo(
            "Geometry", (2, 10),
            fields.faulty.Length(
                label_text="Margin",
                attribute_name="margin",
                low=0.0,
                low_inclusive=True,
            )),
    ])

    #
    # Draw
    #

    def update_normal(self):
        self.points = numpy.array([
            child.target.get_frame_relative_to(self.parent).t
            for child in self.children if child.target is not None
        ], float)

        self.center = sum(self.points) / len(self.points)
        tmp = self.points - self.center
        tensor = (tmp.ravel()**2).sum() * numpy.identity(3) - numpy.dot(
            tmp.transpose(), tmp)
        evals, evecs = numpy.linalg.eigh(tensor)
        indices = evals.argsort()
        self.x = evecs[:, indices[0]]
        self.y = evecs[:, indices[1]]
        if numpy.linalg.det(evecs) < 0:
            self.normal = evecs[:, indices[2]]
        else:
            self.normal = -evecs[:, indices[2]]
        px = numpy.dot(tmp, self.x)
        py = numpy.dot(tmp, self.y)

        px_low = px.min() - self.margin
        px_high = px.max() + self.margin
        py_low = py.min() - self.margin
        py_high = py.max() + self.margin

        self.l_l = self.x * px_low + self.y * py_low + self.center
        self.l_h = self.x * px_low + self.y * py_high + self.center
        self.h_l = self.x * px_high + self.y * py_low + self.center
        self.h_h = self.x * px_high + self.y * py_high + self.center

    def draw(self):
        GLReferentBase.draw(self)
        ColorMixin.draw(self)
        self.update_normal()
        vb = context.application.vis_backend
        vb.draw_quads((
            self.normal,
            [
                self.l_l + 0.001 * self.normal,
                self.l_h + 0.001 * self.normal,
                self.h_h + 0.001 * self.normal,
                self.h_l + 0.001 * self.normal,
            ],
        ), (
            -self.normal,
            [
                self.h_l - 0.001 * self.normal,
                self.h_h - 0.001 * self.normal,
                self.l_h - 0.001 * self.normal,
                self.l_l - 0.001 * self.normal,
            ],
        ))

    #
    # Revalidation
    #

    def revalidate_bounding_box(self):
        GLReferentBase.revalidate_bounding_box(self)
        self.update_normal()
        self.bounding_box.extend_with_point(self.l_l)
        self.bounding_box.extend_with_point(self.l_h)
        self.bounding_box.extend_with_point(self.h_l)
        self.bounding_box.extend_with_point(self.h_h)

    #
    # Vector
    #

    def define_target(self, reference, new_target):
        GLReferentBase.define_target(self, reference, new_target)
        self.invalidate_boundingbox_list()
        self.invalidate_draw_list()

    def target_moved(self, reference, target):
        GLReferentBase.target_moved(self, reference, target)
        self.invalidate_boundingbox_list()
        self.invalidate_draw_list()
Exemple #8
0
class Arrow(Vector, ColorMixin):
    info = ModelObjectInfo("plugins/basic/arrow.svg")
    authors = [authors.toon_verstraelen]

    #
    # Properties
    #

    def set_radius(self, radius, init=False):
        self.radius = radius
        if not init:
            self.invalidate_draw_list()
            self.invalidate_boundingbox_list()

    def set_quality(self, quality, init=False):
        self.quality = quality
        if not init:
            self.invalidate_draw_list()

    def set_arrow_length(self, arrow_length, init=False):
        self.arrow_length = arrow_length
        if not init:
            self.invalidate_draw_list()
            self.invalidate_boundingbox_list()

    def set_arrow_radius(self, arrow_radius, init=False):
        self.arrow_radius = arrow_radius
        if not init:
            self.invalidate_draw_list()
            self.invalidate_boundingbox_list()

    def set_arrow_position(self, arrow_position, init=False):
        self.arrow_position = arrow_position
        if not init:
            self.invalidate_draw_list()
            self.invalidate_boundingbox_list()

    properties = [
        Property("radius", 0.15, lambda self: self.radius, set_radius),
        Property("quality", 15, lambda self: self.quality, set_quality),
        Property("arrow_length", 0.6, lambda self: self.arrow_length,
                 set_arrow_length),
        Property("arrow_radius", 0.3, lambda self: self.arrow_radius,
                 set_arrow_radius),
        Property("arrow_position", 0.5, lambda self: self.arrow_position,
                 set_arrow_position)
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo(
            "Geometry", (2, 2),
            fields.faulty.Length(
                label_text="Radius",
                attribute_name="radius",
                low=0.0,
                low_inclusive=False,
            )),
        DialogFieldInfo(
            "Geometry", (2, 3),
            fields.faulty.Length(
                label_text="Arrow length",
                attribute_name="arrow_length",
                low=0.0,
            )),
        DialogFieldInfo(
            "Geometry", (2, 4),
            fields.faulty.Length(
                label_text="Arrow radius",
                attribute_name="arrow_radius",
                low=0.0,
                low_inclusive=False,
            )),
        DialogFieldInfo(
            "Geometry", (2, 5),
            fields.faulty.Float(
                label_text="Arrow position",
                attribute_name="arrow_position",
                low=0.0,
                high=1.0,
            )),
        DialogFieldInfo(
            "Markup", (1, 3),
            fields.faulty.Int(
                label_text="Quality",
                attribute_name="quality",
                minimum=3,
            )),
    ])

    #
    # Draw
    #

    def draw(self):
        Vector.draw(self)
        ColorMixin.draw(self)
        vb = context.application.vis_backend
        if self.length == 0.0: return
        # usefull variable
        if self.arrow_radius <= 0:
            arrowtop_length = self.arrow_length
        else:
            arrowtop_length = self.arrow_length / self.arrow_radius * self.radius
        # stick and bottom
        if (self.length - arrowtop_length > 0) and (self.radius > 0):
            vb.draw_cylinder(self.radius, self.length - arrowtop_length,
                             self.quality)
            vb.set_quadric_inside()
            vb.draw_disk(self.radius, self.quality)
        # arrowtop
        if (self.radius > 0):
            if (arrowtop_length > 0):
                vb.push_matrix()
                vb.translate(0.0, 0.0, self.length - arrowtop_length)
                vb.set_quadric_outside()
                vb.draw_cone(self.radius, 0, arrowtop_length, self.quality)
                vb.pop_matrix()
            else:
                vb.push_matrix()
                vb.translate(0.0, 0.0, self.length)
                vb.set_quadric_outside()
                vb.draw_disk(self.radius, self.quality)
                vb.pop_matrix()
        # arrow
        if (self.arrow_radius - self.radius >
                0) and (self.arrow_length - arrowtop_length) > 0:
            vb.push_matrix()
            vb.translate(0.0, 0.0, (self.length - self.arrow_length) *
                         (self.arrow_position))
            vb.set_quadric_outside()
            vb.draw_cone(self.arrow_radius, self.radius,
                         self.arrow_length - arrowtop_length, self.quality)
            vb.set_quadric_inside()
            vb.draw_disk(self.arrow_radius, self.quality)
            vb.pop_matrix()
        vb.set_quadric_outside()

    #
    # Revalidation
    #

    def revalidate_bounding_box(self):
        Vector.revalidate_bounding_box(self)
        if self.length > 0.0:
            self.bounding_box.extend_with_corners(
                numpy.array([[0.0, 0.0, 0.0], [0.0, 0.0, self.length]]))
            temp = {
                True: self.radius,
                False: self.arrow_radius
            }[self.radius > self.arrow_radius]
            self.bounding_box.extend_with_corners(
                numpy.array([[-temp, -temp, 0.0], [temp, temp, 0.0]]))
Exemple #9
0
class Box(GLGeometricBase, ColorMixin):
    info = ModelObjectInfo("plugins/basic/box.svg")
    authors = [authors.toon_verstraelen]

    def initnonstate(self):
        GLGeometricBase.initnonstate(self, Complete)

    #
    # Properties
    #

    def set_size(self, size, init=False):
        self.size = size
        if not init:
            self.invalidate_draw_list()
            self.invalidate_boundingbox_list()

    properties = [
        Property("size", numpy.array([1.0, 1.0, 1.0]), lambda self: self.size,
                 set_size),
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo(
            "Geometry", (2, 6),
            fields.composed.ComposedArray(
                FieldClass=fields.faulty.Length,
                array_name="%s",
                suffices=["Width", "Height", "Depth"],
                label_text="Box size",
                attribute_name="size",
            ))
    ])

    #
    # Draw
    #

    def draw(self):
        GLGeometricBase.draw(self)
        ColorMixin.draw(self)
        vb = context.application.vis_backend

        x, y, z = numpy.identity(3)
        sides = numpy.array([(x, y, z, z), (x, y, -z, -z), (y, z, x, x),
                             (y, z, -x, -x), (z, x, y, y), (z, x, -y, -y)],
                            float)
        sides[:, :3] *= 0.5 * self.size

        vb.draw_quads(*[(normal, [
            a + b + c,
            a - b + c,
            -a - b + c,
            -a + b + c,
        ]) for a, b, c, normal in sides])

    #
    # Revalidation
    #

    def revalidate_bounding_box(self):
        GLGeometricBase.revalidate_bounding_box(self)
        self.bounding_box.extend_with_corners(
            numpy.array([-0.5 * self.size, 0.5 * self.size]))
Exemple #10
0
    def __init__(self):
        GladeWrapper.__init__(self, "plugins/molecular/gui.glade", "wi_sketch",
                              "window")
        self.window.hide()
        self.init_callbacks(self.__class__)
        self.init_proxies([
            "cb_object", "cb_vector", "cb_erase_filter",
            "bu_edit_erase_filter", "la_current", "bu_set_atom", "cb_bondtype",
            "hbox_atoms", "hbox_quickpicks", "hbox_fragments", "la_fragment",
            "cb_fragment"
        ])

        self.erase_filter = Expression("True")
        #Initialize atom number - this can be changed anytime with the edit_atom_number dialog
        self.atom_number = 6

        # Initialize the GUI
        #  1) common parts of the comboboxes
        def render_icon(column, cell, model, iter):
            if model.get_value(iter, 0) == "Fragment":
                cell.set_property(
                    "pixbuf",
                    context.application.plugins.get_node("Atom").icon)
            else:
                cell.set_property(
                    "pixbuf",
                    context.application.plugins.get_node(
                        model.get_value(iter, 0)).icon)

        #  2) fill the objects combo box
        self.object_store = gtk.ListStore(str)
        self.object_store.append(["Atom"])
        self.object_store.append(["Fragment"])
        self.object_store.append(["Point"])
        self.object_store.append(["Sphere"])
        self.object_store.append(["Box"])
        self.cb_object.set_model(self.object_store)

        renderer_pixbuf = gtk.CellRendererPixbuf()
        self.cb_object.pack_start(renderer_pixbuf, expand=False)
        self.cb_object.set_cell_data_func(renderer_pixbuf, render_icon)
        renderer_text = gtk.CellRendererText()
        self.cb_object.pack_start(renderer_text, expand=True)
        self.cb_object.add_attribute(renderer_text, "text", 0)

        self.cb_object.set_active(0)

        #  3) fill the vector combo box
        self.vector_store = gtk.ListStore(str)
        self.vector_store.append(["Bond"])
        self.vector_store.append(["Arrow"])
        self.vector_store.append(["Spring"])
        self.cb_vector.set_model(self.vector_store)

        renderer_pixbuf = gtk.CellRendererPixbuf()
        self.cb_vector.pack_start(renderer_pixbuf, expand=False)
        self.cb_vector.set_cell_data_func(renderer_pixbuf, render_icon)
        renderer_text = gtk.CellRendererText()
        self.cb_vector.pack_start(renderer_text, expand=True)
        self.cb_vector.add_attribute(renderer_text, "text", 0)

        self.cb_vector.set_active(0)

        # 4) fill the bond type combo box
        self.bondtype_store = gtk.ListStore(str, int)
        self.bondtype_store.append(["Single bond", BOND_SINGLE])
        self.bondtype_store.append(["Double bond", BOND_DOUBLE])
        self.bondtype_store.append(["Triple bond", BOND_TRIPLE])
        self.bondtype_store.append(["Hybrid bond", BOND_HYBRID])
        self.bondtype_store.append(["Hydrogen bond", BOND_HYDROGEN])
        self.cb_bondtype.set_model(self.bondtype_store)

        #no icons like the others, just text here
        renderer_text = gtk.CellRendererText()
        self.cb_bondtype.pack_start(renderer_text, expand=True)
        self.cb_bondtype.add_attribute(renderer_text, "text", 0)

        self.cb_bondtype.set_active(0)

        # register quick pick config setting
        config = context.application.configuration
        config.register_setting(
            "sketch_quickpicks",
            [6, 7, 8, 9, 10, 11],
            DialogFieldInfo(
                "Sketch tool", (0, 2),
                fields.faulty.IntegerList(
                    label_text="Quick pick atoms (applies after restart)",
                    attribute_name="sketch_quickpicks",
                )),
        )

        # 5)create the "quick pick" atom buttons
        for index in xrange(len(config.sketch_quickpicks)):
            atomnumber = config.sketch_quickpicks[index]
            bu_element = gtk.Button("")
            bu_element.set_label("%s" % periodic[atomnumber].symbol)
            bu_element.connect("clicked", self.on_bu_element_clicked, index)
            # add to hbox
            self.hbox_quickpicks.pack_start(bu_element)
            bu_element.show()

        # 6)fill the fragment combo box with filenames from share/fragments
        fragment_dir = context.get_share_filename('fragments')
        self.fragment_store = gtk.ListStore(str)
        for filename in sorted(os.listdir(fragment_dir)):
            # Ignore subfolders and files with extension other than cml
            if os.path.isdir(os.path.join(fragment_dir,
                                          filename)) or filename[-3:] != 'cml':
                continue
            self.fragment_store.append([filename[:-4]])
        self.cb_fragment.set_model(self.fragment_store)

        renderer_text = gtk.CellRendererText()
        self.cb_fragment.pack_start(renderer_text, expand=True)
        self.cb_fragment.add_attribute(renderer_text, "text", 0)
        self.cb_fragment.set_active(0)
Exemple #11
0
class ModelObject(Node):
    info = ModelObjectInfo(default_action_name="EditProperties")

    #
    # State
    #

    def __init__(self, **initstate):
        # some debugging code
        #Node.count += 1
        #print " PLUS => Initializing " + str(self.__class__) + " (" + str(Node.count) + ") " + hex(id(self))
        Node.__init__(self)
        # initialisation of non state variables
        self.initnonstate()
        # further initialize the state (the properties)
        self.initstate(**initstate)

    def __del__(self):
        pass
        # some debugging code
        #Node.count -= 1
        #print " MIN  => Deleting     " + str(self.__class__) + " (" + str(Node.count) + ") " + hex(id(self))

    def __getstate__(self):
        result = {}
        for p in self.properties:
            value = p.get(self)
            equal = (value == p.default(self))
            if isinstance(equal, numpy.ndarray):
                equal = equal.all()
            if not equal:
                result[p.name] = value
        return result

    def initstate(self, **initstate):
        for p in self.properties:
            if p.name in initstate:
                p.set(self, initstate[p.name], init=True)
            else:
                p.set(self, p.default(self), init=True)

    def initnonstate(self):
        self.references = []

    #
    # Properties
    #

    @classmethod
    def class_name(cls):
        temp = str(cls)
        return temp[temp.rfind(".")+1:-2]

    def default_name(self):
        return self.class_name()

    def get_name(self):
        return self.name

    def set_name(self, name, init=False):
        self.name = name

    def set_extra(self, extra, init=False):
        self.extra = extra

    properties = [
        Property("name", default_name, get_name, set_name),
        Property("extra", {}, (lambda self: self.extra), set_extra),
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo("Basic", (0, 0), fields.faulty.Name(
            label_text="Name",
            attribute_name="name",
        )),
    ])

    #
    # Tree
    #

    def delete_referents(self):
        while len(self.references) > 0:
            primitive.Delete(self.references[0].parent)
        #for reference in copy.copy(self.references):
        #    if reference.model is not None:
        #        #print "Deleting Referent %s(%i)" % (reference.parent.get_name(), id(reference.parent))
        #        primitive.Delete(reference.parent)

    def move(self, new_parent, index=-1):
        if (index > 0) and (self.parent == new_parent) and index > self.get_index():
            index -= 1
        self.parent.remove(self)
        new_parent.add(self, index)
        self.emit("on-move")
        #print "EMIT: on-move"

    #
    # Flags
    #

    def get_fixed(self):
        return (self.model is not None) and (self.parent is None)
Exemple #12
0
class Spring(Vector, ColorMixin):
    info = ModelObjectInfo("plugins/builder/spring.svg")
    authors = [authors.toon_verstraelen]

    #
    # Properties
    #

    def set_radius(self, radius, init=False):
        self.radius = radius
        if not init:
            self.invalidate_draw_list()

    def set_quality(self, quality, init=False):
        self.quality = quality
        if not init:
            self.invalidate_draw_list()

    def set_rest_length(self, rest_length, init=False):
        self.rest_length = rest_length
        if not init:
            self.invalidate_draw_list()

    properties = [
        Property("radius", 0.5, lambda self: self.radius, set_radius),
        Property("quality", 15, lambda self: self.quality, set_quality),
        Property("rest_length", 0.0, lambda self: self.rest_length,
                 set_rest_length),
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo(
            "Geometry", (2, 2),
            fields.faulty.Length(
                label_text="Radius",
                attribute_name="radius",
                low=0.0,
                low_inclusive=False,
            )),
        DialogFieldInfo(
            "Markup", (1, 3),
            fields.faulty.Int(
                label_text="Quality",
                attribute_name="quality",
                minimum=3,
            )),
        DialogFieldInfo(
            "Basic", (0, 8),
            fields.faulty.Length(
                label_text="Rest length",
                attribute_name="rest_length",
                low=0.0,
                low_inclusive=True,
            )),
    ])

    #
    # Draw
    #

    def draw(self):
        Vector.draw(self)
        ColorMixin.draw(self)
        vb = context.application.vis_backend
        if self.length > self.rest_length:
            l_cyl = self.rest_length
            l_cone = 0.5 * (self.length - l_cyl)
            if l_cone > 0:
                vb.draw_cone(self.radius, 0.0, l_cone, self.quality)
                vb.translate(0.0, 0.0, l_cone)
            if l_cyl > 0:
                vb.draw_cone(0.5 * self.radius, 0.5 * self.radius, l_cyl,
                             self.quality)
                vb.translate(0.0, 0.0, l_cyl)
            if l_cone > 0:
                vb.draw_cone(0.0, self.radius, l_cone, self.quality)
        else:
            l_cyl = self.length
            l_cone = 0.5 * (self.rest_length - self.length)
            if l_cone > 0:
                vb.translate(0.0, 0.0, -l_cone)
                vb.draw_cone(0.0, self.radius, l_cone, self.quality)
                vb.translate(0.0, 0.0, l_cone)
            if l_cyl > 0:
                vb.draw_cylinder(0.5 * self.radius, l_cyl, self.quality)
                vb.translate(0.0, 0.0, l_cyl)
            if l_cone > 0:
                vb.draw_cone(self.radius, 0.0, l_cone, self.quality)

    #
    # Revalidation
    #

    def revalidate_bounding_box(self):
        Vector.revalidate_bounding_box(self)
        if self.length > 0:
            self.bounding_box.extend_with_point(
                numpy.array([-self.radius, -self.radius, 0]))
            self.bounding_box.extend_with_point(
                numpy.array([self.radius, self.radius, self.length]))
Exemple #13
0
class Vector(GLReferentBase):

    #
    # State
    #

    def initnonstate(self):
        GLReferentBase.initnonstate(self)
        self.orientation = Complete.identity()
        self.set_children(
            [SpatialReference(prefix="Begin"),
             SpatialReference(prefix="End")])

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo("Basic", (0, 2),
                        fields.read.VectorLength(label_text="Vector length")),
    ])

    #
    # Draw
    #

    def draw(self):
        self.calc_vector_dimensions()
        context.application.vis_backend.transform(self.orientation)

    #
    # Revalidation
    #

    def revalidate_total_list(self):
        if self.gl_active:
            vb = context.application.vis_backend
            vb.begin_list(self.total_list)
            if self.visible:
                vb.push_name(self.draw_list)
                vb.push_matrix()
                self.draw_selection()
                vb.call_list(self.draw_list)
                vb.pop_matrix()
                vb.pop_name()
            vb.end_list()
            self.total_list_valid = True

    def revalidate_draw_list(self):
        if self.gl_active:
            GLReferentBase.revalidate_draw_list(self)

    def revalidate_boundingbox_list(self):
        if self.gl_active:
            vb = context.application.vis_backend
            #print "Compiling selection list (" + str(self.boundingbox_list) + "): " + str(self.name)
            vb.begin_list(self.boundingbox_list)
            vb.push_matrix()
            vb.transform(self.orientation)
            self.revalidate_bounding_box()
            self.bounding_box.draw()
            vb.pop_matrix()
            vb.end_list()
            self.boundingbox_list_valid = True

    #
    # Frame
    #

    def get_bounding_box_in_parent_frame(self):
        return self.bounding_box.transformed(self.orientation)

    #
    # Vector
    #

    def shortest_vector_relative_to(self, other):
        b = self.children[0].translation_relative_to(other)
        e = self.children[1].translation_relative_to(other)
        if (b is None) or (e is None):
            return None
        else:
            return self.parent.shortest_vector(e - b)

    def calc_vector_dimensions(self):
        relative_translation = self.shortest_vector_relative_to(self.parent)
        if relative_translation is None:
            self.length = 0
        else:
            self.length = numpy.sqrt(
                numpy.dot(relative_translation, relative_translation))
            if self.length > 0:
                t = self.children[0].translation_relative_to(self.parent)
                c = relative_translation[2] / self.length
                if c >= 1.0:
                    self.orientation = Translation(t)
                elif c <= -1.0:
                    alpha = numpy.pi
                    axis = numpy.array([1.0, 0.0, 0.0])
                    self.orientation = Complete.from_properties(
                        alpha, axis, False, t)
                else:
                    x, y = relative_translation[0], relative_translation[1]
                    if abs(x) < abs(y):
                        signy = {True: 1, False: -1}[y >= 0]
                        a = -signy
                        b = signy * x / y
                    else:
                        signx = {True: 1, False: -1}[x >= 0]
                        a = -signx * y / x
                        b = signx
                    alpha = numpy.arccos(c)
                    axis = numpy.array([a, b, 0.0])
                    self.orientation = Complete.from_properties(
                        alpha, axis, False, t)

    def define_target(self, reference, new_target):
        GLReferentBase.define_target(self, reference, new_target)
        self.invalidate_boundingbox_list()
        self.invalidate_draw_list()

    def target_moved(self, reference, target):
        GLReferentBase.target_moved(self, reference, target)
        self.invalidate_boundingbox_list()
        self.invalidate_draw_list()

    def get_neighbor(self, one_target):
        if self.children[0].target == one_target:
            return self.children[1].target
        else:
            return self.children[0].target
Exemple #14
0
class GLMixin(gobject.GObject):

    __metaclass__ = NodeClass
    double_sided = False

    #
    # State
    #

    def initnonstate(self):
        self.gl_active = False
        self.connect("on-selected", self.on_select_changed)
        self.connect("on-deselected", self.on_select_changed)

    #
    # Properties
    #

    def set_visible(self, visible, init=False):
        if init:
            self.visible = visible
        elif self.visible != visible:
            self.visible = visible
            self.invalidate_total_list()

    properties = [
        Property("visible", True, lambda self: self.visible, set_visible)
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo(
            "Markup", (1, 2),
            fields.edit.CheckButton(
                label_text="Visible (also hides children)",
                attribute_name="visible",
            )),
        DialogFieldInfo(
            "Basic", (0, 3),
            fields.read.BBox(
                label_text="Bounding box",
                attribute_name="bounding_box",
            )),
    ])

    #
    # OpenGL
    #

    def initialize_gl(self):
        assert not self.gl_active
        vb = context.application.vis_backend
        self.gl_active = True
        self.bounding_box = BoundingBox()
        self.draw_list = vb.create_list(self)
        self.boundingbox_list = vb.create_list()
        self.total_list = vb.create_list()
        ##print "Created lists (%i, %i, %i): %s" % (self.draw_list, self.boundingbox_list, self.total_list, self.get_name())
        self.draw_list_valid = True
        self.boundingbox_list_valid = True
        self.total_list_valid = True
        self.invalidate_all_lists()
        if isinstance(self.parent, GLMixin):
            self.parent.invalidate_all_lists()

    def cleanup_gl(self):
        assert self.gl_active
        self.gl_active = False
        vb = context.application.vis_backend
        ##print "Deleting lists (%i, %i, %i): %s" % (self.draw_list, self.boundingbox_list, self.total_list, self.get_name())
        vb.delete_list(self.draw_list)
        vb.delete_list(self.boundingbox_list)
        vb.delete_list(self.total_list)
        del self.bounding_box
        del self.draw_list
        del self.boundingbox_list
        del self.total_list
        del self.draw_list_valid
        del self.boundingbox_list_valid
        del self.total_list_valid
        if isinstance(self.parent, GLMixin):
            self.parent.invalidate_all_lists()

    #
    # Invalidation
    #

    def invalidate_draw_list(self):
        if self.gl_active and self.draw_list_valid:
            self.draw_list_valid = False
            context.application.main.drawing_area.queue_draw()
            context.application.scene.add_revalidation(
                self.revalidate_draw_list)
            self.emit("on-draw-list-invalidated")
            ##print "EMIT %s: on-draw-list-invalidated" % self.get_name()
            if isinstance(self.parent, GLMixin):
                self.parent.invalidate_boundingbox_list()

    def invalidate_boundingbox_list(self):
        ##print "TRY: %s: on-boundingbox-list-invalidated"  % self.get_name()
        if self.gl_active and self.boundingbox_list_valid:
            self.boundingbox_list_valid = False
            context.application.main.drawing_area.queue_draw()
            context.application.scene.add_revalidation(
                self.revalidate_boundingbox_list)
            self.emit("on-boundingbox-list-invalidated")
            ##print "EMIT %s: on-boundingbox-list-invalidated"  % self.get_name()
            if isinstance(self.parent, GLMixin):
                self.parent.invalidate_boundingbox_list()

    def invalidate_total_list(self):
        if self.gl_active and self.total_list_valid:
            self.total_list_valid = False
            context.application.main.drawing_area.queue_draw()
            context.application.scene.add_revalidation(
                self.revalidate_total_list)
            self.emit("on-total-list-invalidated")
            ##print "EMIT %s: on-total-list-invalidated" % self.get_name()
            if isinstance(self.parent, GLMixin):
                self.parent.invalidate_boundingbox_list()

    def invalidate_all_lists(self):
        self.invalidate_total_list()
        self.invalidate_boundingbox_list()
        self.invalidate_draw_list()

    #
    # Revalidation
    #

    def revalidate_draw_list(self):
        if self.gl_active:
            vb = context.application.vis_backend
            ##print "Compiling draw list (%i): %s" % (self.draw_list, self.get_name())
            vb.begin_list(self.draw_list)
            self.prepare_draw()
            self.draw()
            self.finish_draw()
            vb.end_list()
            self.draw_list_valid = True

    def revalidate_boundingbox_list(self):
        if self.gl_active:
            vb = context.application.vis_backend
            ##print "Compiling selection list (%i): %s" % (self.boundingbox_list, self.get_name())
            vb.begin_list(self.boundingbox_list)
            self.revalidate_bounding_box()
            self.bounding_box.draw()
            vb.end_list()
            self.boundingbox_list_valid = True

    def revalidate_bounding_box(self):
        self.bounding_box.clear()

    def revalidate_total_list(self):
        if self.gl_active:
            vb = context.application.vis_backend
            ##print "Compiling total list (%i): %s" % (self.total_list, self.get_name())
            vb.begin_list(self.total_list)
            if self.visible:
                vb.push_name(self.draw_list)
                self.draw_selection()
                vb.call_list(self.draw_list)
                vb.pop_name()
            vb.end_list()
            self.total_list_valid = True

    #
    # Draw
    #

    def draw_selection(self):
        vb = context.application.vis_backend
        if self.selected:
            vb.set_bright(True)
        else:
            vb.set_bright(False)

    def call_list(self):
        ##print "Executing total list (%i): %s" % (self.total_list, self.get_name())
        context.application.vis_backend.call_list(self.total_list)

    def prepare_draw(self):
        pass

    def draw(self):
        pass

    def finish_draw(self):
        pass

    #
    # Frame
    #

    def get_bounding_box_in_parent_frame(self):
        return self.bounding_box

    def get_absolute_frame(self):
        return self.get_absolute_parentframe()

    def get_absolute_parentframe(self):
        if not isinstance(self.parent, GLMixin):
            return Complete.identity()
        else:
            return self.parent.get_absolute_frame()

    def get_frame_up_to(self, upper_parent):
        if (upper_parent == self) or (self.parent == upper_parent):
            return Complete.identity()
        else:
            return self.get_parentframe_up_to(upper_parent)

    def get_parentframe_up_to(self, upper_parent):
        if not isinstance(self.parent, GLMixin):
            assert upper_parent is None, "upper_parent must be (an indirect) parent of self."
            return Complete.identity()
        elif self.parent == upper_parent:
            return Complete.identity()
        else:
            return self.parent.get_frame_up_to(upper_parent)

    def get_frame_relative_to(self, other):
        common = common_parent([self, other])
        return other.get_frame_up_to(common).inv * self.get_frame_up_to(common)

    #
    # Signal handlers
    #

    def on_select_changed(self, foo):
        self.invalidate_total_list()
Exemple #15
0
class Point(GLGeometricBase, ColorMixin):
    info = ModelObjectInfo("plugins/basic/point.svg")
    authors = [authors.toon_verstraelen]

    def initnonstate(self):
        GLGeometricBase.initnonstate(self, Translation)

    #
    # Properties
    #

    def set_spike_length(self, spike_length, init=False):
        self.spike_length = spike_length
        if not init:
            self.invalidate_draw_list()
            self.invalidate_boundingbox_list()

    def set_spike_thickness(self, spike_thickness, init=False):
        self.spike_thickness = spike_thickness
        if not init:
            self.invalidate_draw_list()
            self.invalidate_boundingbox_list()

    properties = [
        Property("spike_length", 0.3, lambda self: self.spike_length,
                 set_spike_length),
        Property("spike_thickness", 0.1, lambda self: self.spike_thickness,
                 set_spike_thickness),
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo(
            "Geometry", (2, 7),
            fields.faulty.Length(label_text="Spike length",
                                 attribute_name="spike_length",
                                 low=0.0,
                                 low_inclusive=False)),
        DialogFieldInfo(
            "Geometry", (2, 8),
            fields.faulty.Length(label_text="Spike thickness",
                                 attribute_name="spike_thickness",
                                 low=0.0,
                                 low_inclusive=False))
    ])

    #
    # Draw
    #

    def draw_spike(self):
        ColorMixin.draw(self)
        vb = context.application.vis_backend
        vb.draw_quad_strip(
            (numpy.array([0.5773502692, -0.5773502692, -0.5773502692]), [
                numpy.array(
                    [self.spike_length, self.spike_length, self.spike_length])
            ]), (numpy.array([1, 0, 0
                              ]), [numpy.array([self.spike_thickness, 0, 0])]),
            (numpy.array([-0.5773502692, 0.5773502692, -0.5773502692]), [
                numpy.array(
                    [self.spike_length, self.spike_length, self.spike_length])
            ]), (numpy.array([0, 1, 0
                              ]), [numpy.array([0, self.spike_thickness, 0])]),
            (numpy.array([-0.5773502692, -0.5773502692, 0.5773502692]), [
                numpy.array(
                    [self.spike_length, self.spike_length, self.spike_length])
            ]), (numpy.array([0, 0, 1
                              ]), [numpy.array([0, 0, self.spike_thickness])]),
            (numpy.array([0.5773502692, -0.5773502692, -0.5773502692]), [
                numpy.array(
                    [self.spike_length, self.spike_length, self.spike_length])
            ]), (numpy.array([1, 0, 0
                              ]), [numpy.array([self.spike_thickness, 0, 0])]))

    def draw(self):
        GLGeometricBase.draw(self)
        vb = context.application.vis_backend
        vb.push_matrix()
        for i in range(2):
            for i in range(4):
                self.draw_spike()
                vb.rotate(90, 1.0, 0.0, 0.0)
            vb.rotate(180, 0.0, 1.0, 0.0)
        vb.pop_matrix()

    #
    # Revalidation
    #

    def revalidate_bounding_box(self):
        GLGeometricBase.revalidate_bounding_box(self)
        self.bounding_box.extend_with_corners(
            numpy.array(
                [[-self.spike_length, -self.spike_length, -self.spike_length],
                 [self.spike_length, self.spike_length, self.spike_length]]))
Exemple #16
0
class Sphere(GLGeometricBase, ColorMixin):
    info = ModelObjectInfo("plugins/basic/sphere.svg")
    authors = [authors.toon_verstraelen]

    def initnonstate(self):
        GLGeometricBase.initnonstate(self, Translation)

    #
    # Properties
    #

    def set_radius(self, radius, init=False):
        self.radius = radius
        if not init:
            self.invalidate_draw_list()
            self.invalidate_boundingbox_list()

    def set_quality(self, quality, init=False):
        self.quality = quality
        if not init:
            self.invalidate_draw_list()

    properties = [
        Property("radius", 0.5, lambda self: self.radius, set_radius),
        Property("quality", 15, lambda self: self.quality, set_quality),
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo("Geometry", (2, 2), fields.faulty.Length(
            label_text="Radius",
            attribute_name="radius",
            low=0.0,
            low_inclusive=False,
        )),
        DialogFieldInfo("Markup", (1, 3), fields.faulty.Int(
            label_text="Quality",
            attribute_name="quality",
            minimum=3,
        ))
    ])

    #
    # Draw
    #

    def draw(self):
        GLGeometricBase.draw(self)
        ColorMixin.draw(self)
        vb = context.application.vis_backend
        vb.draw_sphere(self.radius, self.quality)

    #
    # Revalidation
    #

    def revalidate_bounding_box(self):
        GLGeometricBase.revalidate_bounding_box(self)
        self.bounding_box.extend_with_corners(numpy.array([
            [-self.radius, -self.radius, -self.radius],
            [ self.radius,  self.radius,  self.radius]
        ]))
Exemple #17
0
class Bond(Vector):
    info = ModelObjectInfo("plugins/molecular/bond.svg")
    authors = [authors.toon_verstraelen]

    #
    # State
    #

    def initnonstate(self):
        Vector.initnonstate(self)
        self.handlers = {}

    #
    # Properties
    #

    def set_quality(self, quality, init=False):
        self.quality = quality
        if not init:
            self.invalidate_draw_list()

    def set_bond_type(self, bond_type, init=False):
        self.bond_type = bond_type
        if not init:
            self.invalidate_draw_list()

    properties = [
        Property("quality", 15, lambda self: self.quality, set_quality),
        Property("bond_type", BOND_SINGLE, lambda self: self.bond_type, set_bond_type)
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo("Markup", (1, 3), fields.faulty.Int(
            label_text="Quality",
            attribute_name="quality",
            minimum=3,
        )),
        DialogFieldInfo("Molecular", (6, 1), fields.edit.ComboBox(
            choices=[
                (BOND_SINGLE, "Single bond"),
                (BOND_DOUBLE, "Double bond"),
                (BOND_TRIPLE, "Triple bond"),
                (BOND_HYBRID, "Hybrid bond"),
                (BOND_HYDROGEN, "Hydrogen bond"),
            ],
            label_text="Bond type",
            attribute_name="bond_type",
        )),
    ])

    #
    # References
    #

    def define_target(self, reference, new_target):
        Vector.define_target(self, reference, new_target)
        self.handlers[new_target] = [
            new_target.connect("on_number_changed", self.atom_property_changed),
            new_target.connect("on_user_radius_changed", self.atom_property_changed),
            new_target.connect("on_user_color_changed", self.atom_property_changed),
        ]

    def undefine_target(self, reference, old_target):
        Vector.undefine_target(self, reference, old_target)
        for handler in self.handlers[old_target]:
            old_target.disconnect(handler)

    def check_target(self, reference, target):
        return isinstance(target, context.application.plugins.get_node("Atom"))

    def atom_property_changed(self, atom):
        self.invalidate_boundingbox_list()
        self.invalidate_draw_list()

    #
    # Draw
    #

    def draw(self):
        Vector.draw(self)
        if self.length <= 0: return
        half_length = 0.5 * (self.end_position - self.begin_position)
        if half_length <= 0: return
        half_radius = 0.5 * (self.begin_radius + self.end_radius)

        begin = self.children[0].target
        end = self.children[1].target

        vb = context.application.vis_backend
        vb.set_color(*begin.get_color())
        vb.translate(0.0, 0.0, self.begin_position)
        vb.draw_cone(self.begin_radius, half_radius, half_length, self.quality)
        vb.translate(0.0, 0.0, half_length)
        vb.set_color(*end.get_color())
        vb.draw_cone(half_radius, self.end_radius, half_length, self.quality)

    #
    # Revalidation
    #

    def revalidate_bounding_box(self):
        Vector.revalidate_bounding_box(self)
        if self.length > 0:
            temp = {True: self.begin_radius, False: self.end_radius}[self.begin_radius > self.end_radius]
            self.bounding_box.extend_with_point(numpy.array([-temp, -temp, self.begin_position]))
            self.bounding_box.extend_with_point(numpy.array([temp, temp, self.end_position]))

    def calc_vector_dimensions(self):
        Vector.calc_vector_dimensions(self)
        begin = self.children[0].target
        end = self.children[1].target
        if self.length <= 0.0: return
        c = (begin.get_radius() - end.get_radius()) / self.length
        if abs(c) > 1:
            self.begin_radius = 0
            self.end_radius = 0
            self.begin_position = 0
            self.end_position = 0
        else:
            scale = 0.4
            s = numpy.sqrt(1 - c**2)
            self.begin_radius = scale * begin.get_radius() * s
            self.end_radius = scale * end.get_radius() * s
            self.begin_position = scale * c * begin.get_radius()
            self.end_position = self.length + scale * c * end.get_radius()
Exemple #18
0
class GLTransformationMixin(GLMixin):

    #
    # State
    #

    def initnonstate(self, Transformation):
        GLMixin.initnonstate(self)
        self.Transformation = Transformation

    #
    # Properties
    #

    def default_transformation(self):
        return self.Transformation.identity()

    def set_transformation(self, transformation, init=False):
        if not transformation.__class__ == self.Transformation:
            # create an object of the proper type and take only the attributes
            # of interest.
            if isinstance(transformation, Translation):
                t = transformation.t
            else:
                t = None
            if isinstance(transformation, Rotation):
                r = transformation.r
            else:
                r = None
            if self.Transformation == Translation:
                if t is None:
                    transformation = Translation.identity()
                else:
                    transformation = Translation(t)
            elif self.Transformation == Rotation:
                if r is None:
                    transformation = Rotation.identity()
                else:
                    transformation = Rotation(r)
            else:  # self.Transformation == Complete:
                if r is None:
                    r = numpy.identity(3, float)
                if t is None:
                    t = numpy.zeros(3, float)
                transformation = Complete(r, t)
        self.transformation = transformation
        if not init:
            self.invalidate_transformation_list()

    properties = [
        Property("transformation", default_transformation,
                 lambda self: self.transformation, set_transformation)
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo(
            "Transformation", (3, 0),
            fields.composed.Translation(
                label_text="Translation with vector t",
                attribute_name="transformation",
            )),
        DialogFieldInfo(
            "Transformation", (3, 1),
            fields.composed.Rotation(
                label_text="Rotation around axis n",
                attribute_name="transformation",
            )),
        DialogFieldInfo(
            "Transformation", (3, 2),
            fields.composed.Complete(
                label_text=
                "The transformation is a rotation followed by a translation.",
                attribute_name="transformation",
            )),
        DialogFieldInfo("Transformation", (3, 3), fields.read.Handedness()),
    ])

    #
    # OpenGL
    #

    def initialize_gl(self):
        vb = context.application.vis_backend
        self.transformation_list = vb.create_list()
        ##print "Created transformation list (%i): %s" % (self.transformation_list, self.get_name())
        self.transformation_list_valid = True
        GLMixin.initialize_gl(self)

    def cleanup_gl(self):
        GLMixin.cleanup_gl(self)
        vb = context.application.vis_backend
        ##print "Deleting transformation list (%i): %s" % (self.transformation_list, self.get_name())
        vb.delete_list(self.transformation_list)
        del self.transformation_list
        del self.transformation_list_valid

    #
    # Invalidation
    #

    def invalidate_transformation_list(self):
        ##print "CALL %s: on-transformation-list-invalidated" % self.get_name()
        if self.gl_active and self.transformation_list_valid:
            self.transformation_list_valid = False
            context.application.main.drawing_area.queue_draw()
            context.application.scene.add_revalidation(
                self.revalidate_transformation_list)
            self.emit("on-transformation-list-invalidated")
            ##print "EMIT %s: on-transformation-list-invalidated" % self.get_name()
            if isinstance(self.parent, GLMixin):
                self.parent.invalidate_boundingbox_list()

    def invalidate_all_lists(self):
        self.invalidate_transformation_list()
        GLMixin.invalidate_all_lists(self)

    #
    # Revalidation
    #

    def revalidate_transformation_list(self):
        if self.gl_active:
            vb = context.application.vis_backend
            ##print "Compiling transformation list (%i): %s" % (self.transformation_list,  self.get_name())
            vb.begin_list(self.transformation_list)
            vb.transform(self.transformation)
            vb.end_list()
            self.transformation_list_valid = True

    def revalidate_total_list(self):
        if self.gl_active:
            vb = context.application.vis_backend
            ##print "Compiling total list (%i): %s" % (self.total_list, self.get_name())
            vb.begin_list(self.total_list)
            if self.visible:
                vb.push_name(self.draw_list)
                vb.push_matrix()
                vb.call_list(self.transformation_list)
                self.draw_selection()
                vb.call_list(self.draw_list)
                vb.pop_matrix()
                vb.pop_name()
            vb.end_list()
            self.total_list_valid = True

    #
    # Frame
    #

    def get_bounding_box_in_parent_frame(self):
        return self.bounding_box.transformed(self.transformation)

    def get_absolute_frame(self):
        if not isinstance(self.parent, GLMixin):
            return self.transformation
        else:
            return self.get_absolute_parentframe() * self.transformation

    def get_frame_up_to(self, upper_parent):
        if (upper_parent == self):
            return Complete.identity()
        elif (self.parent == upper_parent):
            return self.transformation
        else:
            return self.get_parentframe_up_to(
                upper_parent) * self.transformation
Exemple #19
0
class Universe(GLPeriodicContainer, FrameAxes):
    info = ModelObjectInfo("plugins/basic/universe.svg")
    authors = [authors.toon_verstraelen]
    clip_margin = 0.1

    #
    # State
    #

    def initnonstate(self):
        GLPeriodicContainer.initnonstate(self)
        self.model_center = Translation.identity()

    def update_center(self):
        self.model_center = Translation(
            0.5 *
            numpy.dot(self.cell.matrix, self.repetitions * self.cell.active))

    #
    # Properties
    #

    def set_cell(self, cell, init=False):
        GLPeriodicContainer.set_cell(self, cell, init)
        if not init:
            self.update_clip_planes()
            self.update_center()
            self.invalidate_total_list()
            self.invalidate_box_list()

    def set_repetitions(self, repetitions, init=False):
        self.repetitions = repetitions
        if not init:
            self.update_clip_planes()
            self.update_center()
            self.invalidate_box_list()
            self.invalidate_total_list()

    def set_box_visible(self, box_visible, init=False):
        self.box_visible = box_visible
        if not init:
            self.invalidate_total_list()

    def set_clipping(self, clipping, init=False):
        self.clipping = clipping
        if not init:
            self.invalidate_total_list()
            self.invalidate_box_list()
            self.update_clip_planes()

    properties = [
        Property("repetitions", numpy.array([1, 1, 1], int),
                 lambda self: self.repetitions, set_repetitions),
        Property("box_visible", True, lambda self: self.box_visible,
                 set_box_visible),
        Property("clipping", False, lambda self: self.clipping, set_clipping),
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo(
            "Unit cell", (5, 2),
            fields.composed.Repetitions(
                label_text="Repetitions",
                attribute_name="repetitions",
            )),
        DialogFieldInfo(
            "Markup", (1, 5),
            fields.edit.CheckButton(
                label_text="Show periodic box (if active)",
                attribute_name="box_visible",
            )),
        DialogFieldInfo(
            "Markup", (1, 6),
            fields.edit.CheckButton(
                label_text="Clip the unit cell contents.",
                attribute_name="clipping",
            )),
    ])

    #
    # Tree
    #

    @classmethod
    def check_add(Class, ModelObjectClass):
        if not GLPeriodicContainer.check_add(ModelObjectClass): return False
        if issubclass(ModelObjectClass, Universe): return False
        return True

    #
    # OpenGL
    #

    def initialize_gl(self):
        vb = context.application.vis_backend
        self.set_clip_planes()
        self.update_center()
        self.box_list = vb.create_list()
        ##print "Created box list (%i): %s" % (self.box_list, self.get_name())
        self.box_list_valid = True
        GLPeriodicContainer.initialize_gl(self)

    def cleanup_gl(self):
        vb = context.application.vis_backend
        GLPeriodicContainer.cleanup_gl(self)
        ##print "Deleting box list (%i): %s" % (self.box_list, self.get_name())
        vb.delete_list(self.box_list)
        del self.box_list
        del self.box_list_valid
        self.unset_clip_planes()

    #
    # Clipping
    #

    def update_clip_planes(self):
        if self.gl_active > 0:
            self.unset_clip_planes()
            self.set_clip_planes()

    def set_clip_planes(self):
        if not self.clipping:
            return
        clip_planes = context.application.scene.clip_planes
        assert len(clip_planes) == 0
        active, inactive = self.cell.active_inactive
        for index in active:
            axis = self.cell.matrix[:, index]
            ortho = self.cell.reciprocal[index] / numpy.linalg.norm(
                self.cell.reciprocal[index])
            length = abs(numpy.dot(ortho, axis))
            repetitions = self.repetitions[index]
            clip_planes.append(numpy.array(list(ortho) + [self.clip_margin]))
            clip_planes.append(
                numpy.array(
                    list(-ortho) + [repetitions * length + self.clip_margin]))
        context.application.main.drawing_area.queue_draw()

    def unset_clip_planes(self):
        context.application.scene.clip_planes = []
        context.application.main.drawing_area.queue_draw()

    def shortest_vector(self, delta):
        return self.cell.shortest_vector(delta)

    #
    # Invalidation
    #

    def invalidate_box_list(self):
        if self.gl_active > 0 and self.box_list_valid:
            self.box_list_valid = False
            context.application.main.drawing_area.queue_draw()
            context.application.scene.add_revalidation(
                self.revalidate_box_list)
            ##print "EMIT %s: on-box-list-invalidated" % self.get_name()

    def invalidate_all_lists(self):
        self.invalidate_box_list()
        GLPeriodicContainer.invalidate_all_lists(self)

    #
    # Draw
    #

    def draw_box(self):
        vb = context.application.vis_backend
        vb.set_line_width(2)
        vb.set_specular(False)

        col = {True: 4.0, False: 2.5}[self.selected]
        sat = {True: 0.0, False: 0.5}[self.selected]
        gray = {True: 4.0, False: 2.5}[self.selected]

        def draw_three(origin):
            if self.cell.active[0]:
                vb.set_color(col, sat, sat)
                vb.draw_line(origin, origin + self.cell.matrix[:, 0])
            if self.cell.active[1]:
                vb.set_color(sat, col, sat)
                vb.draw_line(origin, origin + self.cell.matrix[:, 1])
            if self.cell.active[2]:
                vb.set_color(sat, sat, col)
                vb.draw_line(origin, origin + self.cell.matrix[:, 2])

        def draw_gray(origin, axis1, axis2, n1, n2, delta, nd):
            c = context.application.configuration.periodic_box_color
            vb.set_color(gray * c[0], gray * c[1], gray * c[2], c[3])
            if n1 == 0 and n2 == 0:
                return
            for i1 in xrange(n1 + 1):
                if i1 == 0:
                    b2 = 1
                    vb.draw_line(origin + delta, origin + nd * delta)
                else:
                    b2 = 0
                for i2 in xrange(b2, n2 + 1):
                    vb.draw_line(origin + i1 * axis1 + i2 * axis2,
                                 origin + i1 * axis1 + i2 * axis2 + nd * delta)

        def draw_ortho(origin, axis1, axis2, n1, n2, delta):
            c = context.application.configuration.periodic_box_color
            vb.set_color(gray * c[0], gray * c[1], gray * c[2], c[3])
            if n1 == 0 and n2 == 0:
                return
            for i1 in xrange(n1 + 1):
                for i2 in xrange(n2 + 1):
                    vb.draw_line(
                        origin + i1 * axis1 + i2 * axis2 - 0.5 * delta,
                        origin + i1 * axis1 + i2 * axis2 + 0.5 * delta)

        origin = numpy.zeros(3, float)
        draw_three(origin)
        repetitions = self.repetitions * self.cell.active

        if self.cell.active[2]:
            draw_gray(origin, self.cell.matrix[:, 0], self.cell.matrix[:, 1],
                      repetitions[0], repetitions[1], self.cell.matrix[:, 2],
                      repetitions[2])
        else:
            draw_ortho(origin, self.cell.matrix[:, 0], self.cell.matrix[:, 1],
                       repetitions[0], repetitions[1], self.cell.matrix[:, 2])

        if self.cell.active[0]:
            draw_gray(origin, self.cell.matrix[:, 1], self.cell.matrix[:, 2],
                      repetitions[1], repetitions[2], self.cell.matrix[:, 0],
                      repetitions[0])
        else:
            draw_ortho(origin, self.cell.matrix[:, 1], self.cell.matrix[:, 2],
                       repetitions[1], repetitions[2], self.cell.matrix[:, 0])

        if self.cell.active[1]:
            draw_gray(origin, self.cell.matrix[:, 2], self.cell.matrix[:, 0],
                      repetitions[2], repetitions[0], self.cell.matrix[:, 1],
                      repetitions[1])
        else:
            draw_ortho(origin, self.cell.matrix[:, 2], self.cell.matrix[:, 0],
                       repetitions[2], repetitions[0], self.cell.matrix[:, 1])

        vb.set_specular(True)

    def draw(self):
        FrameAxes.draw(self, self.selected)
        GLPeriodicContainer.draw(self)

    #
    # Revalidation
    #

    def revalidate_box_list(self):
        if self.gl_active > 0:
            ##print "Compiling box list (%i): %s" % (self.box_list,  self.get_name())
            vb = context.application.vis_backend
            vb.begin_list(self.box_list)
            if sum(self.cell.active) > 0:
                self.draw_box()
            vb.end_list()
            self.box_list_valid = True

    def revalidate_total_list(self):
        if self.gl_active > 0:
            ##print "Compiling total list (%i): %s" % (self.total_list, self.get_name())
            vb = context.application.vis_backend
            vb.begin_list(self.total_list)
            if self.visible:
                vb.push_name(self.draw_list)
                if sum(self.cell.active) == 0:
                    if self.selected:
                        vb.call_list(self.boundingbox_list)
                else:
                    if self.selected:
                        vb.set_bright(True)
                    else:
                        vb.set_bright(False)

                if self.box_visible: vb.call_list(self.box_list)

                # repeat the draw list for all the unit cell images.
                if self.clipping:
                    repetitions = (self.repetitions +
                                   2) * self.cell.active + 1 - self.cell.active
                else:
                    repetitions = self.repetitions * self.cell.active + 1 - self.cell.active
                for position in iter_all_positions(repetitions):
                    vb.push_matrix()
                    t = numpy.dot(
                        self.cell.matrix,
                        numpy.array(position) -
                        self.cell.active * self.clipping)
                    vb.translate(*t)
                    vb.call_list(self.draw_list)
                    vb.pop_matrix()

                vb.pop_name()
            vb.end_list()
            self.total_list_valid = True

    def revalidate_bounding_box(self):
        GLPeriodicContainer.revalidate_bounding_box(self)
        FrameAxes.extend_bounding_box(self, self.bounding_box)

    #
    # Signal handlers
    #

    def on_select_chaged(self, selected):
        GLPeriodicContainer.on_select_chaged(self, selected)
        self.invalidate_box_list()
Exemple #20
0
class FrameAxes(object):

    __metaclass__ = NodeClass

    #
    # Properties
    #

    def set_axis_thickness(self, axis_thickness, init=False):
        self.axis_thickness = axis_thickness
        if not init:
            self.invalidate_draw_list()
            self.invalidate_boundingbox_list()

    def set_axis_length(self, axis_length, init=False):
        self.axis_length = axis_length
        if not init:
            self.invalidate_draw_list()
            self.invalidate_boundingbox_list()

    def set_axes_visible(self, axes_visible, init=False):
        self.axes_visible = axes_visible
        if not init:
            self.invalidate_draw_list()
            self.invalidate_boundingbox_list()

    properties = [
        Property("axis_thickness", 0.1 * angstrom,
                 lambda self: self.axis_thickness, set_axis_thickness),
        Property("axis_length", 1.0 * angstrom, lambda self: self.axis_length,
                 set_axis_length),
        Property("axes_visible", True, lambda self: self.axes_visible,
                 set_axes_visible)
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo(
            "Geometry", (2, 0),
            fields.faulty.Length(
                label_text="Axis thickness",
                attribute_name="axis_thickness",
                low=0.0,
                low_inclusive=False,
            )),
        DialogFieldInfo(
            "Geometry", (2, 1),
            fields.faulty.Length(
                label_text="Axes length",
                attribute_name="axis_length",
                low=0.0,
                low_inclusive=False,
            )),
        DialogFieldInfo(
            "Markup", (1, 4),
            fields.edit.CheckButton(
                label_text="Show frame axes",
                attribute_name="axes_visible",
            )),
    ])

    #
    # Draw
    #

    def draw(self, light):
        if self.axes_visible:
            col = {True: 2.0, False: 1.2}[light]
            sat = {True: 0.2, False: 0.1}[light]
            vb = context.application.vis_backend
            vb.push_matrix()
            # x-axis
            vb.set_color(col, sat, sat)
            draw_axis_spike(self.axis_thickness, self.axis_length)
            # y-axis
            vb.rotate(120, 1.0, 1.0, 1.0)
            vb.set_color(sat, col, sat)
            draw_axis_spike(self.axis_thickness, self.axis_length)
            # z-axis
            vb.rotate(120, 1.0, 1.0, 1.0)
            vb.set_color(sat, sat, col)
            draw_axis_spike(self.axis_thickness, self.axis_length)
            vb.pop_matrix()

    #
    # Revalidation
    #

    def extend_bounding_box(self, bounding_box):
        bounding_box.extend_with_corners(
            numpy.array([[
                -self.axis_thickness, -self.axis_thickness,
                -self.axis_thickness
            ], [self.axis_length, self.axis_length, self.axis_length]]))
Exemple #21
0
class Atom(GLGeometricBase, UserColorMixin):
    info = ModelObjectInfo("plugins/molecular/atom.svg")
    authors = [authors.toon_verstraelen]

    #
    # State
    #

    def initnonstate(self):
        GLGeometricBase.initnonstate(self, Translation)

    #
    # Properties
    #

    def set_user_radius(self, user_radius, init=False):
        self.user_radius = user_radius
        if not init:
            self.invalidate_draw_list()
            self.invalidate_boundingbox_list()

    def set_quality(self, quality, init=False):
        self.quality = quality
        if not init:
            self.invalidate_draw_list()

    def set_number(self, number, init=False):
        self.number = number
        atom_info = periodic[number]
        if atom_info.vdw_radius is not None:
            self.default_radius = atom_info.vdw_radius * 0.2
        else:
            self.default_radius = 1.0
        color = [atom_info.red, atom_info.green, atom_info.blue, 1.0]
        if None in color:
            self.default_color = numpy.array([0.7, 0.7, 0.7, 1.0], float)
        else:
            self.default_color = numpy.array(color, float)
        if not init:
            self.invalidate_draw_list()
            self.invalidate_boundingbox_list()

    properties = [
        Property("user_radius",
                 Undefined(0.5),
                 lambda self: self.user_radius,
                 set_user_radius,
                 signal=True),
        Property("quality", 15, lambda self: self.quality, set_quality),
        Property("number",
                 6,
                 lambda self: self.number,
                 set_number,
                 signal=True),
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo(
            "Geometry", (2, 9),
            fields.optional.CheckOptional(
                fields.faulty.Length(
                    label_text="User defined radius",
                    attribute_name="user_radius",
                    low=0.0,
                    low_inclusive=False,
                ))),
        DialogFieldInfo(
            "Markup", (1, 3),
            fields.faulty.Int(
                label_text="Quality",
                attribute_name="quality",
                minimum=3,
            )),
        DialogFieldInfo(
            "Molecular", (6, 0),
            fields.edit.Element(
                attribute_name="number",
                show_popup=False,
            )),
    ])

    #
    # Draw
    #

    def get_radius(self):
        if isinstance(self.user_radius, Undefined):
            return self.default_radius
        else:
            return self.user_radius

    def draw(self):
        GLGeometricBase.draw(self)
        UserColorMixin.draw(self)
        vb = context.application.vis_backend
        vb.draw_sphere(self.get_radius(), self.quality)

    #
    # Revalidation
    #

    def revalidate_bounding_box(self):
        GLGeometricBase.revalidate_bounding_box(self)
        radius = self.get_radius()
        self.bounding_box.extend_with_corners(
            numpy.array([[-radius, -radius, -radius], [radius, radius,
                                                       radius]]))

    #
    # Tools
    #

    def num_bonds(self):
        Bond = context.application.plugins.get_node("Bond")
        return sum(
            isinstance(reference.parent, Bond)
            for reference in self.references)

    def iter_bonds(self):
        Bond = context.application.plugins.get_node("Bond")
        for reference in self.references:
            referent = reference.parent
            if isinstance(referent, Bond):
                yield referent

    def iter_neighbors(self):
        for bond in self.iter_bonds():
            first = bond.children[0].target
            if first == self:
                neighbor = bond.children[1].target
            else:
                neighbor = first
            if isinstance(neighbor, Atom):
                yield neighbor