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()
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", )) ])
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)), )
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())
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", )), ])
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)
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()
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]]))
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]))
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)
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)
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]))
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
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()
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]]))
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] ]))
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()
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
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()
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]]))
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