def normalizingTransformation(self, repr=None): """Returns a linear transformation that shifts the center of mass of the object to the coordinate origin and makes its principal axes of inertia parallel to the three coordinate axes. A specific representation can be chosen by setting |repr| to Ir : x y z <--> b c a IIr : x y z <--> c a b IIIr : x y z <--> a b c Il : x y z <--> c b a IIl : x y z <--> a c b IIIl : x y z <--> b a c """ from Scientific.LA import determinant cm, inertia = self.centerAndMomentOfInertia() ev, diag = inertia.diagonalization() if determinant(diag.array) < 0: diag.array[0] = -diag.array[0] if repr != None: seq = Numeric.argsort(ev) if repr == 'Ir': seq = Numeric.array([seq[1], seq[2], seq[0]]) elif repr == 'IIr': seq = Numeric.array([seq[2], seq[0], seq[1]]) elif repr == 'Il': seq = Numeric.seq[2::-1] elif repr == 'IIl': seq[1:3] = Numeric.array([seq[2], seq[1]]) elif repr == 'IIIl': seq[0:2] = Numeric.array([seq[1], seq[0]]) elif repr != 'IIIr': print 'unknown representation' diag.array = Numeric.take(diag.array, seq) return Transformation.Rotation(diag) * Transformation.Translation(-cm)
def rotateAroundAxis(self, point1, point2, angle): """Rotates the object by the given |angle| around the axis that passes through |point1| and |point2|""" tr1 = Transformation.Translation(-point1) tr2 = Transformation.Rotation(point2 - point1, angle) tr3 = tr1.inverse() self.applyTransformation(tr3 * tr2 * tr1)
def rotateAroundCenter(self, axis_direction, angle): """Rotates the object by the given |angle| around an axis that passes through its center of mass and has the given |direction|.""" cm = self.centerOfMass() t = Transformation.Translation(cm) * \ Transformation.Rotation(axis_direction, angle) * \ Transformation.Translation(-cm) self.applyTransformation(t)
def __init__(self, attr, rotation, translation, reference_point): VRMLObject.__init__(self, attr) if rotation is None: rotation = Transformation.Rotation(ez, 0.) else: rotation = apply(Transformation.Rotation, rotation) if translation is None: translation = Transformation.Translation(Vector(0., 0., 0.)) else: translation = Transformation.Translation(translation) self.transformation = translation * rotation self.reference_point = reference_point
def findTransformation(self, conf1, conf2=None): """Returns the linear transformation that, when applied to the object in configuration |conf1|, minimizes the RMS distance to the conformation in |conf2|, and the minimal RMS distance. If |conf2| is 'None', returns the transformation from the current configuration to |conf1| and the associated RMS distance. The algorithm is described in [Article:Kneller1990].""" q, cm1, cm2, rms = self.findTransformationAsQuaternion(conf1, conf2) return Transformation.Translation(cm2) * \ q.asRotation() * \ Transformation.Translation(-cm1), \ rms
def rotateAroundAxis(self, point1, point2, angle): """ Rotate the object arond an axis specified by two points :param point1: the first point :type point1: Scientific.Geometry.Vector :param point2: the second point :type point2: Scientific.Geometry.Vector :param angle: the rotation angle (in radians) :type angle: float """ tr1 = Transformation.Translation(-point1) tr2 = Transformation.Rotation(point2 - point1, angle) tr3 = tr1.inverse() self.applyTransformation(tr3 * tr2 * tr1)
def rotateAroundCenter(self, axis_direction, angle): """ Rotate the object around an axis that passes through its center of mass. :param axis_direction: the direction of the axis of rotation :type axis_direction: Scientific.Geometry.Vector :param angle: the rotation angle (in radians) :type angle: float """ cm = self.centerOfMass() t = Transformation.Translation(cm) * \ Transformation.Rotation(axis_direction, angle) * \ Transformation.Translation(-cm) self.applyTransformation(t)
def testVectorRotation(self): from Scientific.Geometry import Vector, Transformation # check regression axis_direction = Vector(0.000000, 1.000000, 1.000000) angle = 0.7 Transformation.Rotation(axis_direction, angle)
def asRotation(self): """ @returns: the corresponding rotation matrix @rtype: L{Scientific.Geometry.Transformation.Rotation} @raises ValueError: if the quaternion is not normalized """ if Numeric.fabs(self.norm() - 1.) > 1.e-5: raise ValueError('Quaternion not normalized') d = Numeric.dot(Numeric.dot(self._rot, self.array), self.array) return Transformation.Rotation(d)
def findTransformation(self, conf1, conf2=None): """ :param conf1: a configuration object :type conf1: :class:~MMTK.ParticleProperties.Configuration :param conf2: a configuration object, or None for the current configuration :type conf2: :class:~MMTK.ParticleProperties.Configuration or NoneType :returns: the linear transformation that, when applied to the object in configuration conf1, minimizes the RMS distance to the conformation in conf2, and the minimal RMS distance. If conf2 is None, returns the transformation from the current configuration to conf1 and the associated RMS distance. """ q, cm1, cm2, rms = self.findTransformationAsQuaternion(conf1, conf2) return Transformation.Translation(cm2) * \ q.asRotation() * \ Transformation.Translation(-cm1), \ rms
def rotateAroundOrigin(self, axis_direction, angle): """ Rotate the object around an axis that passes through the coordinate origin. :param axis_direction: the direction of the axis of rotation :type axis_direction: Scientific.Geometry.Vector :param angle: the rotation angle (in radians) :type angle: float """ self.applyTransformation(Transformation.Rotation(axis_direction, angle))
def dihedral(self, p1, p2, p3, p4, conf = None): """Returns the dihedral angle between the plane containing the distance vectors |p1|-|p2| and |p3|-|p2| and the plane containing the distance vectors |p2|-|p3| and |p4|-|p3|.""" v1 = self.distanceVector(p2, p1, conf) v2 = self.distanceVector(p3, p2, conf) v3 = self.distanceVector(p3, p4, conf) a = v1.cross(v2).normal() b = v3.cross(v2).normal() cos = a*b sin = b.cross(a)*v2/v2.length() return Transformation.angleFromSineAndCosine(sin, cos)
def normalizingTransformation(self, repr=None): """ Calculate a linear transformation that shifts the center of mass of the object to the coordinate origin and makes its principal axes of inertia parallel to the three coordinate axes. :param repr: the specific representation for axis alignment: Ir : x y z <--> b c a IIr : x y z <--> c a b IIIr : x y z <--> a b c Il : x y z <--> c b a IIl : x y z <--> a c b IIIl : x y z <--> b a c :returns: the normalizing transformation :rtype: Scientific.Geometry.Transformation.RigidBodyTransformation """ from Scientific.LA import determinant cm, inertia = self.centerAndMomentOfInertia() ev, diag = inertia.diagonalization() if determinant(diag.array) < 0: diag.array[0] = -diag.array[0] if repr != None: seq = N.argsort(ev) if repr == 'Ir': seq = N.array([seq[1], seq[2], seq[0]]) elif repr == 'IIr': seq = N.array([seq[2], seq[0], seq[1]]) elif repr == 'Il': seq = N.seq[2::-1] elif repr == 'IIl': seq[1:3] = N.array([seq[2], seq[1]]) elif repr == 'IIIl': seq[0:2] = N.array([seq[1], seq[0]]) elif repr != 'IIIr': print 'unknown representation' diag.array = N.take(diag.array, seq) return Transformation.Rotation(diag) * Transformation.Translation(-cm)
def __init__(self, attr, point1, point2): center = 0.5 * (point1 + point2) axis = point2 - point1 self.height = axis.length() if self.height > 0: axis = axis / self.height rot_axis = ey.cross(axis) sine = rot_axis.length() cosine = ey * axis angle = Transformation.angleFromSineAndCosine(sine, cosine) if abs(angle) < 1.e-4 or abs(angle - 2. * N.pi) < 1.e-4: rotation = None else: if abs(sine) < 1.e-4: rot_axis = ex rotation = (rot_axis, angle) else: rotation = None ShapeObject.__init__(self, attr, rotation, center, center)
def __init__(self, attr, point1, point2): center = 0.5*(point1+point2) axis = point2-point1 self.height = axis.length() if self.height > 0: axis = axis/self.height rot_axis = VectorModule.ey.cross(axis) sine = rot_axis.length() cosine = VectorModule.ey*axis angle = Transformation.angleFromSineAndCosine(sine, cosine) if abs(angle) < 1.e-4 or abs(angle-2.*Numeric.pi) < 1.e-4: rotation = None else: if abs(sine) < 1.e-4: rot_axis = VectorModule.ex rotation = (rot_axis, angle) else: rotation = None ShapeObject.__init__(self, attr, rotation, center, center)
def addImproperTerm(self, data, improper, object, global_data): if not self.arguments[2]: return a1 = improper.a1 a2 = improper.a2 a3 = improper.a3 a4 = improper.a4 i1 = a1.index i2 = a2.index i3 = a3.index i4 = a4.index t1 = global_data.atom_type[a1] t2 = global_data.atom_type[a2] t3 = global_data.atom_type[a3] t4 = global_data.atom_type[a4] terms = self.dataset.improperParameters(t1, t2, t3, t4) if terms is not None: atoms = [(t2,i2,a2), (t3,i3,a3), (t4,i4,a4)] atoms.sort(_order) i2, i3, i4 = tuple(map(lambda t: t[1], atoms)) a2, a3, a4 = tuple(map(lambda t: t[2], atoms)) v1 = a2.position()-a3.position() v2 = a3.position()-a1.position() v3 = a4.position()-a1.position() a = v1.cross(v2).normal() b = v3.cross(v2).normal() cos = a*b sin = b.cross(a)*v2/v2.length() dihedral = Transformation.angleFromSineAndCosine(sin, cos) if dihedral > Numeric.pi: dihedral = dihedral - 2.*Numeric.pi for p in terms: if p[2] != 0.: mult = p[0] phase = Numeric.fmod(Numeric.pi-mult*dihedral, 2.*Numeric.pi) if phase < 0.: phase = phase + 2.*Numeric.pi data.add('dihedrals', (i2, i3, i1, i4, p[0], phase) + p[2:])
def addDihedralTerm(self, data, dihedral, object, global_data): if not self.arguments[2]: return a1 = dihedral.a1 a2 = dihedral.a2 a3 = dihedral.a3 a4 = dihedral.a4 i1 = a1.index i2 = a2.index i3 = a3.index i4 = a4.index global_data.add('1_4_pairs', (i1, i4)) t1 = global_data.atom_type[a1] t2 = global_data.atom_type[a2] t3 = global_data.atom_type[a3] t4 = global_data.atom_type[a4] terms = self.dataset.dihedralParameters(t1, t2, t3, t4) if terms is not None: v1 = a1.position()-a2.position() v2 = a2.position()-a3.position() v3 = a4.position()-a3.position() a = v1.cross(v2).normal() b = v3.cross(v2).normal() cos = a*b sin = b.cross(a)*v2/v2.length() dihedral = Transformation.angleFromSineAndCosine(sin, cos) if dihedral > Numeric.pi: dihedral = dihedral - 2.*Numeric.pi for p in terms: if p[2] != 0.: mult = p[0] phase = Numeric.fmod(Numeric.pi-mult*dihedral, 2.*Numeric.pi) if phase < 0.: phase = phase + 2.*Numeric.pi data.add('dihedrals', (i1, i2, i3, i4, p[0], phase) + p[2:])
def rotateAroundOrigin(self, axis, angle): """Rotates the object by the given |angle| around an axis that passes through the coordinate origin and has the given |direction|.""" self.applyTransformation(Transformation.Rotation(axis, angle))