def replace(self, gl_object): if not gl_object.get_fixed(): state = gl_object.__getstate__() state.pop("name", None) state.pop("transformation", None) new = self.get_new(gl_object.transformation.t) if(self.current_object == "Fragment"): #fragments are inserted at frames - have no refs target_object = new.children[1] else: target_object = new for reference in gl_object.references[::-1]: if not reference.check_target(target_object): return parent = gl_object.parent import copy primitive.Add(new, parent) if(self.current_object == "Fragment"): # rotation Bond = context.application.plugins.get_node("Bond") if len(gl_object.references) == 1 and isinstance(gl_object.references[0].parent, Bond): bond1 = gl_object.references[0].parent direction1 = bond1.shortest_vector_relative_to(parent) if bond1.children[0].target != gl_object: direction1 *= -1 bond2 = new.children[0].references[0].parent direction2 = bond2.shortest_vector_relative_to(parent) if bond2.children[0].target != target_object: direction2 *= -1 axis = numpy.cross(direction2, direction1) if numpy.linalg.norm(axis) < 1e-8: axis = random_orthonormal(direction1) angle = compute_angle(direction1, direction2) rotation = Rotation() rotation.set_rotation_properties(angle,axis,False) primitive.Transform(new, rotation) else: bond1 = None # tranlsation translation = Translation() pos_old = new.children[1].get_frame_relative_to(parent).t pos_new = gl_object.transformation.t translation.t = pos_new - pos_old primitive.Transform(new, translation) if bond1 != None: # bond length old_length = numpy.linalg.norm(direction1) new_length = bonds.get_length(new.children[1].number, bond1.get_neighbor(gl_object).number) translation = Translation() translation.t = -direction1/old_length*(new_length-old_length) primitive.Transform(new, translation) for reference in gl_object.references[::-1]: reference.set_target(target_object) primitive.Delete(gl_object) if(self.current_object == "Fragment"): primitive.Delete(new.children[0]) # get rid of frame UnframeAbsolute = context.application.plugins.get_action("UnframeAbsolute") UnframeAbsolute([new])
def __init__(self, send, geometry1, geometry2, action_radius, hit_tolerance, rotation2): Scanner.__init__(self, send, geometry1, geometry2, action_radius, hit_tolerance) if rotation2 is None: self.rotation2 = Rotation.identity() else: self.rotation2 = rotation2
def default_parameters(cls): rotation2 = Rotation() rotation2.set_rotation_properties(0.0, [1, 0, 0], False) result = Parameters() result.connect_description1 = (Expression("True"), Expression("node.get_radius()")) result.repulse_description1 = (Expression("True"), Expression("node.get_radius()")) result.connect_description2 = (Expression("True"), Expression("node.get_radius()")) result.repulse_description2 = (Expression("True"), Expression("node.get_radius()")) result.action_radius = 7*angstrom result.distance_tolerance = 0.1*angstrom result.hit_tolerance = 0.1*angstrom result.allow_inversions = True result.minimum_triangle_size = 0.1*angstrom result.rotation_tolerance = 0.05 result.rotation2 = Undefined(rotation2) return result
def reset(self): config = context.application.configuration self.rotation_center = Translation() self.rotation = Rotation() self.eye = Translation() self.eye.t[2] = config.viewer_distance self.opening_angle = config.opening_angle self.window_size = config.window_size self.window_depth = config.window_depth
def do(self): universe = context.application.cache.node # first make sure the cell is right handed if numpy.linalg.det(universe.cell) < 0 and universe.cell_active.sum() == 3: new_cell = universe.cell.copy() temp = new_cell[:,0].copy() new_cell[:,0] = new_cell[:,1] new_cell[:,1] = temp primitive.SetProperty(universe, "cell", new_cell) # then rotate the unit cell box to the normalized frame: rotation = Rotation() rotation.r = numpy.array(universe.calc_align_rotation_matrix()) new_cell = numpy.dot(rotation.r, universe.cell) old_cell_active = universe.cell_active.copy() universe.cell_active = numpy.array([False, False, False]) primitive.SetProperty(universe, "cell", new_cell) for child in context.application.cache.transformed_children: primitive.Transform(child, rotation) universe.cell_active = old_cell_active primitive.SetProperty(universe, "cell", new_cell)
def do_rotation(self, rotation_angle, rotation_axis): rotation_axis = numpy.dot(self.eye_rotation, rotation_axis) if self.rotation_axis is not None: if numpy.dot(self.rotation_axis, rotation_axis) > 0: rotation_axis = self.rotation_axis else: rotation_axis = -self.rotation_axis rotation = Rotation() rotation.set_rotation_properties(rotation_angle, rotation_axis, False) transformation = self.victim.transformation if isinstance(self.victim.transformation, Translation): transformation.t -= self.rotation_center transformation.t = numpy.dot(numpy.transpose(rotation.r), transformation.t) transformation.t += self.rotation_center if isinstance(self.victim.transformation, Rotation): transformation.r = numpy.dot(numpy.transpose(rotation.r), transformation.r) self.victim.revalidate_transformation_list() context.application.main.drawing_area.queue_draw() #self.victim.invalidate_transformation_list() self.changed = True
def do(self): cache = context.application.cache # Translate where possible, if necessary translated_nodes = cache.translated_nodes if len(translated_nodes) > 0: if isinstance(cache.last, GLTransformationMixin) and \ isinstance(cache.last.transformation, Translation): absolute_inversion_center = cache.last.get_absolute_frame().t else: absolute_inversion_center = numpy.zeros(3, float) victims_by_parent = list_by_parent(cache.transformed_nodes) for parent, victims in victims_by_parent.iteritems(): local_inversion_center = parent.get_absolute_frame().vector_apply_inverse(absolute_inversion_center) for victim in victims: translation = Translation() translation.t = 2 * (local_inversion_center - victim.transformation.t) primitive.Transform(victim, translation) # Apply an inversion rotation where possible r = Rotation() r.inversion_rotation() for victim in cache.rotated_nodes: primitive.Transform(victim, r, after=False)
def alignment_a(self): """Computes the rotation matrix that aligns the unit cell with the Cartesian axes, starting with cell vector a. * a parallel to x * b in xy-plane with b_y positive * c with c_z positive """ from molmod.transformations import Rotation new_x = self.matrix[:, 0].copy() new_x /= numpy.linalg.norm(new_x) new_z = numpy.cross(new_x, self.matrix[:, 1]) new_z /= numpy.linalg.norm(new_z) new_y = numpy.cross(new_z, new_x) new_y /= numpy.linalg.norm(new_y) return Rotation(numpy.array([new_x, new_y, new_z]))
def alignment_c(self): """Computes the rotation matrix that aligns the unit cell with the Cartesian axes, starting with cell vector c. * c parallel to z * b in zy-plane with b_y positive * a with a_x positive """ from molmod.transformations import Rotation new_z = self.matrix[:, 2].copy() new_z /= np.linalg.norm(new_z) new_x = np.cross(self.matrix[:, 1], new_z) new_x /= np.linalg.norm(new_x) new_y = np.cross(new_z, new_x) new_y /= np.linalg.norm(new_y) return Rotation(np.array([new_x, new_y, new_z]))
def do_rotation(self, drawing_area, rotation_angle, rotation_axis): camera = context.application.camera rotation = Rotation() rotation.set_rotation_properties(rotation_angle, rotation_axis, False) camera.rotation.apply_before(rotation) drawing_area.queue_draw()
def do(self): cache = context.application.cache rotation = Rotation() rotation.r = copy.deepcopy(cache.node.transformation.r) CenterAlignBase.do(self, cache.parent, cache.transformed_neighbors, rotation)
def rotate(self, center, axis, angle): self.transform(Translation(-np.array(center))) self.transform(Rotation.from_properties(angle, axis, invert=False)) self.transform(Translation(center))
def randomize(self, center): self.transform(Translation(-np.array(center))) self.transform(Rotation.random()) self.transform(Translation(center))
def add_hydrogens(atom): existing_bonds = list(atom.yield_bonds()) num_bonds = len(existing_bonds) bond_length = bonds.get_length(atom.number, 1, BOND_SINGLE) if num_bonds == 0: H = Atom(name="auto H", number=1) H.transformation.t = atom.transformation.t + numpy.array([0,bond_length,0]) primitive.Add(H, atom.parent) bond = Bond(name="aut H bond", targets=[atom, H]) primitive.Add(bond, atom.parent) existing_bonds.append(bond) num_bonds = 1 used_valence = 0 oposite_direction = numpy.zeros(3, float) for bond in existing_bonds: shortest_vector = bond.shortest_vector_relative_to(atom.parent) if bond.children[1].target == atom: shortest_vector *= -1 oposite_direction -= shortest_vector if bond.bond_type == BOND_SINGLE: used_valence += 1 elif bond.bond_type == BOND_DOUBLE: used_valence += 2 elif bond.bond_type == BOND_TRIPLE: used_valence += 3 oposite_direction /= numpy.linalg.norm(oposite_direction) num_hydrogens = valence_el(atom.number) - 2*lone_pairs(atom.number) - used_valence if num_hydrogens <= 0: return hybride_count = num_hydrogens + lone_pairs(atom.number) + num_bonds - (used_valence - num_bonds) num_sites = num_hydrogens + lone_pairs(atom.number) rotation = Rotation() rotation.set_rotation_properties(2*math.pi / float(num_sites), oposite_direction, False) opening_key = (hybride_count, num_sites) opening_angle = self.opening_angles.get(opening_key) if opening_angle is None: return if num_bonds == 1: first_bond = existing_bonds[0] other_atom = first_bond.children[0].target if other_atom == atom: other_atom = first_bond.children[1].target other_bonds = [bond for bond in other_atom.yield_bonds() if bond != first_bond] if len(other_bonds) > 0: normal = other_bonds[0].shortest_vector_relative_to(atom.parent) normal -= numpy.dot(normal, oposite_direction) * oposite_direction normal /= numpy.linalg.norm(normal) if other_bonds[0].children[0].target == other_atom: normal *= -1 else: normal = random_orthonormal(oposite_direction) elif num_bonds == 2: normal = numpy.cross(oposite_direction, existing_bonds[0].shortest_vector_relative_to(atom.parent)) normal /= numpy.linalg.norm(normal) elif num_bonds == 3: normal = random_orthonormal(oposite_direction) else: return h_pos = bond_length*(oposite_direction*math.cos(opening_angle) + normal*math.sin(opening_angle)) for i in range(num_hydrogens): H = Atom(name="auto H", number=1) H.transformation.t = atom.transformation.t + h_pos primitive.Add(H, atom.parent) bond = Bond(name="aut H bond", targets=[atom, H]) primitive.Add(bond, atom.parent) h_pos = rotation.vector_apply(h_pos)
class Camera(object): 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() def reset(self): config = context.application.configuration self.rotation_center = Translation() self.rotation = Rotation() self.eye = Translation() self.eye.t[2] = config.viewer_distance self.opening_angle = config.opening_angle self.window_size = config.window_size self.window_depth = config.window_depth def get_znear(self): if self.opening_angle > 0.0: return 0.5*self.window_size/numpy.tan(0.5*self.opening_angle) else: return 0.0 znear = property(get_znear) # coordinate transformations def eye_to_camera(self, vector_e): tmp = numpy.ones(2, float) znear = self.znear if znear > 0: return -vector_e[:2]/vector_e[2]/self.window_size*znear else: return vector_e[:2]/self.window_size def camera_window_to_eye(self, vector_c): tmp = numpy.zeros(3, float) tmp[:2] = vector_c*self.window_size znear = self.znear if znear > 0: tmp[2] = -self.znear else: tmp[2] = -self.window_size/3.0 return tmp def model_to_eye(self, vector_m): scene = context.application.scene tmp = scene.model_center.vector_apply_inverse(vector_m) tmp = self.rotation_center.vector_apply_inverse(tmp) tmp = self.rotation.vector_apply_inverse(tmp) tmp[2] -= self.znear tmp = self.eye.vector_apply_inverse(tmp) return tmp def eye_to_model(self, vector_e): scene = context.application.scene tmp = self.eye.vector_apply(vector_e) tmp[2] += self.znear tmp = self.rotation.vector_apply(tmp) tmp = self.rotation_center.vector_apply(tmp) tmp = scene.model_center.vector_apply(tmp) return tmp def model_to_camera(self, vector_m): return self.eye_to_camera(self.model_to_eye(vector_m)) def camera_window_to_model(self, vector_c): return self.eye_to_model(self.camera_window_to_eye(vector_c)) def object_to_depth(self, gl_object): result = -self.model_to_eye(gl_object.get_absolute_frame().t)[2] return result def object_to_camera(self, gl_object): return self.eye_to_camera(self.model_to_eye(gl_object.get_absolute_frame().t)) def object_to_eye(self, gl_object): return self.model_to_eye(gl_object.get_absolute_frame().t) def object_eye_rotation(self, gl_object): """ Returns a matrix that consists of the x, y and z axes of the eye frame in the coordinates of the parent frame of the given object. """ if hasattr(gl_object, "parent") and \ isinstance(gl_object.parent, GLTransformationMixin): parent_matrix = gl_object.parent.get_absolute_frame().r else: parent_matrix = numpy.identity(3, float) result = numpy.dot(self.rotation.r.transpose(), parent_matrix).transpose() return result def depth_to_scale(self, depth): """ transforms a depth into a scale (au/camcoords)""" znear = self.znear if znear > 0: return depth/znear*self.window_size else: return self.window_size def vector_in_plane(self, r, p_m): """Returns a vector at camera position r in a plane (through p, orthogonal to viewing direction) Arguments r -- a two-dimensional vector in camera coordinates p_m -- a three-dimensional vector in model coordinates Returns rp -- a three-dimensional vector in model coordinates that lies at the intersection of a plane and a line. The plane is orthogonal to the viewing direction and goes through the point p. The line connects the eye (eye_m below) with the point r (r_m below) in the camera window. """ eye_m = self.eye_to_model(numpy.zeros(3, float)) r_m = self.camera_window_to_model(r) center_m = self.camera_window_to_model(numpy.zeros(2, float)) normal = (eye_m - center_m) normal /= numpy.linalg.norm(normal) if self.znear > 0: # the line is defined as r = eye_m + d*t, where t = -infinity ... infinity d = eye_m - r_m # t at the intersection: t = -numpy.dot(eye_m - p_m, normal)/numpy.dot(d, normal) return eye_m + d*t else: # the line is defined as r = r_m + d*t, where t = -infinity ... infinity d = normal # t at the intersection: t = -numpy.dot(r_m - p_m, normal)/numpy.dot(d, normal) return r_m + d*t