def _axisDistance(self, axis, infinite=False):
     from chimera import angle, cross, Plane
     # shortest distance between lines is perpendicular to both...
     sDir = self.xformDirection()
     aDir = axis.xformDirection()
     if angle(sDir, aDir) in [0.0, 180.0]:
         # parallel
         return self._axisEndsDist(axis)
     shortDir = cross(sDir, aDir)
     # can use analytically shortest dist only if each axis
     # penetrates the plane formed by the other axis and the
     # perpendicular
     if not infinite:
         for a1, a2 in [(axis, self), (self, axis)]:
             normal = cross(a1.xformDirection(), shortDir)
             plane = Plane(a1.xformCenter(), normal)
             d1 = plane.distance(a2.xformCenter() +
                                 a2.xformDirection() * a2.extents[0])
             d2 = plane.distance(a2.xformCenter() +
                                 a2.xformDirection() * a2.extents[1])
             if cmp(d1, 0.0) == cmp(d2, 0.0):
                 # both ends on same side of plane
                 return self._axisEndsDist(axis)
     # D is perpendicular distance to origin
     d1 = Plane(self.xformCenter(), shortDir).equation()[3]
     d2 = Plane(axis.xformCenter(), shortDir).equation()[3]
     return abs(d1 - d2)
Beispiel #2
0
def tetraPos(bondee,
             bonded,
             bondLen,
             toward=None,
             away=None,
             toward2=None,
             away2=None):
    newBonded = []
    curBonded = bonded[:]
    if len(curBonded) == 0:
        pos = singlePos(bondee, bondLen, toward, away)
        toward = toward2
        away = away2
        newBonded.append(pos)
        curBonded.append(pos)

    if len(curBonded) == 1:
        # add at 109.5 degree angle
        coplanar = toward or away
        if coplanar:
            coplanar = [coplanar]
        else:
            coplanar = None
        pos = anglePos(bondee, curBonded[0], bondLen, 109.5, coplanar=coplanar)
        if toward or away:
            # find the other 109.5 position in the toward/away
            # plane and the closer/farther position as appropriate
            old = bondee - curBonded[0]
            old.normalize()
            new = pos - bondee
            midpoint = bondee + old * new.length * cos705
            otherPos = pos + (midpoint - pos) * 2
            d1 = (pos - (toward or away)).sqlength()
            d2 = (otherPos - (toward or away)).sqlength()
            if toward:
                if d2 < d1:
                    pos = otherPos
            elif away and d2 > d1:
                pos = otherPos

        newBonded.append(pos)
        curBonded.append(pos)

    if len(curBonded) == 2:
        # add along anti-bisector of current bonds and raised up
        # 54.75 degrees from plane of those bonds (half of 109.5)
        v1 = curBonded[0] - bondee
        v2 = curBonded[1] - bondee
        v1.normalize()
        v2.normalize()
        antiBi = v1 + v2
        antiBi.negate()
        antiBi.normalize()
        # in order to stabilize the third and fourth tetrahedral
        # positions, cross the longer vector by the shorter
        if v1.sqlength() > v2.sqlength():
            crossV = cross(v1, v2)
        else:
            crossV = cross(v2, v1)
        crossV.normalize()

        antiBi = antiBi * cos5475 * bondLen
        crossV = crossV * sin5475 * bondLen

        pos = bondee + antiBi + crossV
        if toward or away:
            otherPos = bondee + antiBi - crossV
            d1 = (pos - (toward or away)).sqlength()
            d2 = (otherPos - (toward or away)).sqlength()
            if toward:
                if d2 < d1:
                    pos = otherPos
            elif away and d2 > d1:
                pos = otherPos
        newBonded.append(pos)
        curBonded.append(pos)

    if len(curBonded) == 3:
        unitized = []
        for cb in curBonded:
            v = cb - bondee
            v.normalize()
            unitized.append(bondee + v)
        pl = Plane(unitized)
        norm = pl.normal
        # if normal on other side of plane from bondee, we need to
        # invert the normal;  the (signed) distance from bondee
        # to the plane indicates if it is on the same side
        # (positive == same side)
        d = pl.distance(bondee)
        if d < 0.0:
            norm.negate()
        newBonded.append(bondee + norm * bondLen)
    return newBonded
Beispiel #3
0
def tetraPos(bondee, bonded, bondLen, toward=None, away=None,
						toward2=None, away2=None):
	newBonded = []
	curBonded = bonded[:]
	if len(curBonded) == 0:
		pos = singlePos(bondee, bondLen, toward, away)
		toward = toward2
		away = away2
		newBonded.append(pos)
		curBonded.append(pos)
	
	if len(curBonded) == 1:
		# add at 109.5 degree angle
		coplanar = toward or away
		if coplanar:
			coplanar = [coplanar]
		else:
			coplanar = None
		pos = anglePos(bondee, curBonded[0], bondLen, 109.5,
							coplanar=coplanar)
		if toward or away:
			# find the other 109.5 position in the toward/away
			# plane and the closer/farther position as appropriate
			old = bondee - curBonded[0]
			old.normalize()
			new = pos - bondee
			midpoint = bondee + old * new.length * cos705
			otherPos = pos + (midpoint - pos) * 2
			d1 = (pos - (toward or away)).sqlength()
			d2 = (otherPos - (toward or away)).sqlength()
			if toward:
				if d2 < d1:
					pos = otherPos
			elif away and d2 > d1:
				pos = otherPos

		newBonded.append(pos)
		curBonded.append(pos)
	
	if len(curBonded) == 2:
		# add along anti-bisector of current bonds and raised up
		# 54.75 degrees from plane of those bonds (half of 109.5)
		v1 = curBonded[0] - bondee
		v2 = curBonded[1] - bondee
		v1.normalize()
		v2.normalize()
		antiBi = v1 + v2
		antiBi.negate()
		antiBi.normalize()
		# in order to stabilize the third and fourth tetrahedral
		# positions, cross the longer vector by the shorter
		if v1.sqlength() > v2.sqlength():
			crossV = cross(v1, v2)
		else:
			crossV = cross(v2, v1)
		crossV.normalize()

		antiBi = antiBi * cos5475 * bondLen
		crossV = crossV * sin5475 * bondLen

		pos = bondee + antiBi + crossV
		if toward or away:
			otherPos = bondee + antiBi - crossV
			d1 = (pos - (toward or away)).sqlength()
			d2 = (otherPos - (toward or away)).sqlength()
			if toward:
				if d2 < d1:
					pos = otherPos
			elif away and d2 > d1:
				pos = otherPos
		newBonded.append(pos)
		curBonded.append(pos)
	
	if len(curBonded) == 3:
		unitized = []
		for cb in curBonded:
			v = cb - bondee
			v.normalize()
			unitized.append(bondee + v)
		pl = Plane(unitized)
		norm = pl.normal
		# if normal on other side of plane from bondee, we need to
		# invert the normal;  the (signed) distance from bondee
		# to the plane indicates if it is on the same side
		# (positive == same side)
		d = pl.distance(bondee)
		if d < 0.0:
			norm.negate()
		newBonded.append(bondee + norm * bondLen)
	return newBonded