def writepov(self, file, dispdef): if self.hidden: return if self.is_disabled(): return #bruce 050421 hw = self.width / 2.0 wo = self.image_offset eo = self.edge_offset corners_pos = [ V(-hw, hw, 0.0), V(-hw, -hw, 0.0), V(hw, -hw, 0.0), V(hw, hw, 0.0) ] povPlaneCorners = [] for v in corners_pos: povPlaneCorners += [self.quat.rot(v) + self.center] strPts = ' %s, %s, %s, %s ' % tuple(map(povpoint, povPlaneCorners)) if self.image_obj: imgName = os.path.basename(self.espimage_file) imgPath = os.path.dirname(self.espimage_file) file.write( '\n // Before you render, please set this command option: Library_Path="%s"\n\n' % (imgPath, )) file.write('esp_plane_texture(' + strPts + ', "' + imgName + '") \n') else: color = '%s %f>' % (povStrVec(self.fill_color), self.opacity) file.write('esp_plane_color(' + strPts + ', ' + color + ') \n') return
def __init__(self, command): """ Constructor for the Build DNA property manager. """ self.endPoint1 = V(0, 0, 0) self.endPoint2 = V(0, 0, 0) self._numberOfBases = 0 self._conformation = 'B-DNA' self.duplexRise = 3.18 self.basesPerTurn = 10 self.dnaModel = 'PAM3' _superclass.__init__(self, command) self.showTopRowButtons( PM_DONE_BUTTON | \ PM_CANCEL_BUTTON | \ PM_PREVIEW_BUTTON | \ PM_WHATS_THIS_BUTTON) msg = "Use resize handles to resize the segment. Drag any axis or sugar"\ " atom for translation or rotation about axis respectively. Dragging"\ " any bond will freely move the whole segment." self.updateMessage(msg)
def getParameters(self): """ Return the parameters from this property manager to be used to create the DNA duplex. @return: A tuple containing the parameters @rtype: tuple @see: L{InsertDna_EditCommand._gatherParameters} where this is used """ numberOfBases = self.numberOfBasePairsSpinBox.value() dnaForm = str(self.conformationComboBox.currentText()) basesPerTurn = self.basesPerTurnDoubleSpinBox.value() duplexRise = self.duplexRiseDoubleSpinBox.value() dnaModel = str(self.dnaModelComboBox.currentText()) # First endpoint (origin) of DNA duplex x1 = self.x1SpinBox.value() y1 = self.y1SpinBox.value() z1 = self.z1SpinBox.value() # Second endpoint (direction vector/axis) of DNA duplex. x2 = self.x2SpinBox.value() y2 = self.y2SpinBox.value() z2 = self.z2SpinBox.value() if not self.endPoint1: self.endPoint1 = V(x1, y1, z1) if not self.endPoint2: self.endPoint2 = V(x2, y2, z2) return (numberOfBases, dnaForm, dnaModel, basesPerTurn, duplexRise, self.endPoint1, self.endPoint2)
def setup_quat_center(self, atomList=None): """ Setup the plane's quat using a list of atoms. If no atom list is supplied, the plane is centered in the glpane and parallel to the screen. @param atomList: A list of atoms. @type atomList: list """ if atomList: self.atomPos = [] for a in atomList: self.atomPos += [a.posn()] planeNorm = self._getPlaneOrientation(self.atomPos) if dot(planeNorm, self.glpane.lineOfSight) < 0: planeNorm = -planeNorm self.center = add.reduce(self.atomPos) / len(self.atomPos) self.quat = Q(V(0.0, 0.0, 1.0), planeNorm) else: self.center = V(0.0, 0.0, 0.0) # Following makes sure that Plane edges are parallel to # the 3D workspace borders. Fixes bug 2448 x, y, z = self.glpane.right, self.glpane.up, self.glpane.out self.quat = Q(x, y, z) self.quat += Q(self.glpane.right, pi)
def __init__(self, win, editCommand): """ Constructor for the Build DNA property manager. """ #For model changed signal #@see: self.model_changed() and self._current_model_changed_params #for example use self._previous_model_changed_params = None #see self.connect_or_disconnect_signals for comment about this flag self.isAlreadyConnected = False self.isAlreadyDisconnected = False self.endPoint1 = V(0, 0, 0) self.endPoint2 = V(0, 0, 0) self._numberOfBases = 0 self._conformation = 'B-DNA' self.duplexRise = 3.18 self.basesPerTurn = 10 self.dnaModel = 'PAM3' _superclass.__init__(self, win, editCommand) self.showTopRowButtons( PM_DONE_BUTTON | \ PM_CANCEL_BUTTON | \ PM_PREVIEW_BUTTON | \ PM_WHATS_THIS_BUTTON) msg = "Use resize handles to resize the segment. Drag any axis or sugar"\ " atom for translation or rotation about axis respectively. Dragging"\ " any bond will freely move the whole segment." self.updateMessage(msg)
def sameAsCurrentView(self, view = None): """ Tests if self is the same as I{view}, or the current view if I{view} is None (the default). @param view: A named view to compare with self. If None (the default), self is compared to the current view (i.e. the 3D graphics area). @type view: L{NamedView} @return: True if they are the same. Otherwise, returns False. @rtype: boolean """ # Note: I'm guessing this could be rewritten to be more # efficient/concise. For example, it seems possible to implement # this using a simple conditional like this: # # if self == view: # return True # else: # return False # # It occurs to me that the GPLane class should use a NamedView attr # along with (or in place of) quat, scale, pov and zoomFactor attrs. # That would make this method (and possibly other code) easier to # write and understand. # # Ask Bruce about all this. # # BTW, this code was originally copied/borrowed from # GLPane.animateToView(). Mark 2008-02-03. # Make copies of self parameters. q1 = Q(self.quat) s1 = self.scale p1 = V(self.pov[0], self.pov[1], self.pov[2]) z1 = self.zoomFactor if view is None: # use the graphics area in which self is displayed # (usually the main 3D graphics area; code in this class # has not been reviewed for working in other GLPane_minimal instances) view = self.assy.glpane # Copy the parameters of view for comparison q2 = Q(view.quat) s2 = view.scale p2 = V(view.pov[0], view.pov[1], view.pov[2]) z2 = view.zoomFactor # Compute the deltas deltaq = q2 - q1 deltap = vlen(p2 - p1) deltas = abs(s2 - s1) deltaz = abs(z2 - z1) if deltaq.angle + deltap + deltas + deltaz == 0: return True else: return False
def __computeBBox(self): """ Compute the plane's current bounding box. """ # The move absolute method moveAbsolute() in Move_Command relies on a # 'bbox' attribute for the movables. This attribute is really useless # for Planes otherwise. Instead of modifying that method, I added the # attribute bbox here to fix BUG 2473. # -- ninad 2007-06-27. hw = self.width * 0.5 hh = self.height * 0.5 corners_pos = [ V(-hw, hh, 0.0), V(-hw, -hh, 0.0), V(hw, -hh, 0.0), V(hw, hh, 0.0) ] abs_pos = [] for pos in corners_pos: abs_pos += [self.quat.rot(pos) + self.center] return BBox(abs_pos)
def __init__(self, assy, editCommand = None, atomlist = []): """ create a blank Rotary Motor not connected to anything """ # [note (bruce 071128): future copy-code cleanup will require either # that the atomlist argument comes before the editCommand argument, # or that _um_initargs is overridden.] assert atomlist == [] # whether from default arg value or from caller -- for now Motor.__init__(self, assy, atomlist) self.torque = 0.0 # in nN * nm self.initial_speed = 0.0 # in gHz self.speed = 0.0 # in gHz self.center = V(0,0,0) self.axis = V(0,0,0) self._initial_posns = None #bruce 050518 # We need to reset _initial_posns to None whenever we recompute # self.axis from scratch or change the atom list in any way (even reordering it). # For now, we do this everywhere it's needed "by hand", # rather than in some (not yet existing) systematic and general way. # set default color of new rotary motor to gray self.color = gray # This is the "draw" color. When selected, this will become highlighted red. self.normcolor = gray # This is the normal (unselected) color. self.length = 10.0 # default length of Rotary Motor cylinder self.radius = 1.0 # default cylinder radius self.sradius = 0.2 #default spoke radius # Should self.cancelled be in RotaryMotorProp.setup? - Mark 050109 self.cancelled = True # We will assume the user will cancel self.editCommand = editCommand
def __init__(self, assy, name, scale, pov, zoomFactor, wxyz): """ @param pov: the inverse of the "center of view" in model coordinates @type pov: position vector (Numeric.array of 3 ints or floats, as made by V(x,y,z)) @param wxyz: orientation of view @type wxyz: a Quaternion (class VQT.Q), or a sequence of 4 floats which can be passed to that class to make one, e.g. Q(W, x, y, z) is the quaternion with axis vector x,y,z and sin(theta/2) = W """ self.const_pixmap = imagename_to_pixmap("modeltree/NamedView.png") if not name: name = gensym("%s" % self.sym, assy) Node.__init__(self, assy, name) self.scale = scale assert type(pov) is type(V(1, 0, 0)) self.pov = V(pov[0], pov[1], pov[2]) self.zoomFactor = zoomFactor self.quat = Q(wxyz) #bruce 050518/080303 comment: wxyz is passed as an array of 4 floats # (in same order as in mmp file's csys record), when parsing # csys mmp records, or with wxyz a quat in other places. return
def posn( self ): # stub - average posn of Ss neighbors (plus offset in case only one!) print "should use Pl_pos_from_neighbor_PAM3plus5_data for %r" % self ##### # note: average_value seems to work here res = average_value([n.posn() for n in self.neighbors()], V(0, 0, 0)) return res + V(0, 2, 0) # offset (kluge, wrong)
def __init__(self, win, editCommand): """ Constructor for the Build DNA property manager. """ #For model changed signal #@see: self.model_changed() and self._current_model_changed_params #for example use self._previous_model_changed_params = None #see self.connect_or_disconnect_signals for comment about this flag self.isAlreadyConnected = False self.isAlreadyDisconnected = False self.endPoint1 = V(0, 0, 0) self.endPoint2 = V(0, 0, 0) self._numberOfBases = 0 self._conformation = 'B-DNA' self.duplexRise = 3.18 self.basesPerTurn = 10 self.dnaModel = 'PAM3' _superclass.__init__(self, win, editCommand) DebugMenuMixin._init1(self) self.showTopRowButtons( PM_DONE_BUTTON | \ PM_WHATS_THIS_BUTTON) msg = "Use resize handles to resize the segments." self.updateMessage(msg)
def __init__(self, assy, editCommand = None, atomlist = []): """ create a blank Linear Motor not connected to anything """ # [note (bruce 071128): future copy-code cleanup will require either # that the atomlist argument comes before the editCommand argument, # or that _um_initargs is overridden.] assert atomlist == [] # whether from default arg value or from caller -- for now Motor.__init__(self, assy, atomlist) self.force = 0.0 self.stiffness = 0.0 self.center = V(0,0,0) self.axis = V(0,0,0) # set default color of new linear motor to gray self.color = gray # This is the "draw" color. When selected, this will become highlighted red. self.normcolor = gray # This is the normal (unselected) color. self.length = 10.0 # default length of Linear Motor box self.width = 2.0 # default box width self.sradius = 0.2 #default spoke radius self.cancelled = True # We will assume the user will cancel self.editCommand = editCommand
def gather_parameters(self): """ Return the parameters from the property manager UI. @return: All the parameters: - numberOfBases - dnaForm - basesPerTurn - endPoint1 - endPoint2 @rtype: tuple """ numberOfBases = self.numberOfBasesSpinBox.value() dnaForm = str(self.conformationComboBox.currentText()) basesPerTurn = self.basesPerTurnDoubleSpinBox.value() # First endpoint (origin) of DNA duplex x1 = self.x1SpinBox.value() y1 = self.y1SpinBox.value() z1 = self.z1SpinBox.value() # Second endpoint (direction vector/axis) of DNA duplex. x2 = self.x2SpinBox.value() y2 = self.y2SpinBox.value() z2 = self.z2SpinBox.value() endPoint1 = V(x1, y1, z1) endPoint2 = V(x2, y2, z2) return (numberOfBases, dnaForm, basesPerTurn, endPoint1, endPoint2)
def __init__(self, point1=None, point2=None, slab=None): # Huaicai 4/23/05: added some comments below to help understand the code. if slab: # convert from 2d (x, y) coordinates into its 3d world (x, y, 0) #coordinates(the lower-left and upper-right corner). #In another word, the 3d coordinates minus the z offset of the plane x = dot(A(point1), A(point2)) # Get the vector from upper-right point to the lower-left point dx = subtract.reduce(x) # Get the upper-left and lower right corner points oc = x[1] + V(point2[0] * dot(dx, point2[0]), point2[1] * dot(dx, point2[1])) # Get the four 3d cooridinates on the bottom crystal-cutting plane sq1 = cat(x, oc) + slab.normal * dot(slab.point, slab.normal) # transfer the above 4 3d coordinates in parallel to get that on #the top plane, put them together sq1 = cat(sq1, sq1 + slab.thickness * slab.normal) self.data = V(maximum.reduce(sq1), minimum.reduce(sq1)) elif point2: # just 2 3d points self.data = V(maximum(point1, point2), minimum(point1, point2)) elif point1: # list of points: could be 2d or 3d? +/- 1.8 to make the bounding #box enclose the vDw ball of an atom? self.data = V( maximum.reduce(point1) + BBOX_MARGIN, minimum.reduce(point1) - BBOX_MARGIN) else: # a null bbox self.data = None
def flush(self, newmotion=V(0, 0, 0)): self.delegate.move( self.use_motion + newmotion ) ###k ASSUMES ModelObject always supports move (even if it's a noop) ###IMPLEM # note, nothing wrong with modelobjects usually having one coordsys state which this affects # and storing the rest of their data relative to that, if they want to -- but only some do. ## self.motion = V(0,0,0) self.delta_stateref.value = V(0, 0, 0)
def Draw_other(self): """ Do some custom drawing (in the model's abs coordsys), as well as whatever the superclass does. """ #print "start ExampleCommand2E Draw_other" super(ExampleCommand2E_GM, self).Draw_other() drawline(red, V(1, 0, 1), V(1, 1, 1), width=2) self.command._expr_instance.draw()
def Draw(self): """ Do some custom drawing (in the model's abs coordsys) after drawing the model. """ #print "start ExampleCommand2E Draw" glpane = self.glpane super(ExampleCommand2E_GM, self).Draw() drawline(red, V(1, 0, 1), V(1, 1, 1), width=2) self.command._expr_instance.draw()
def drawsphere_worker_loop(params): (pos, radius, detailLevel) = params for x in range(100): ## 500 for y in range(100): newpos = pos + (x+x/10+x/100) * V(1, 0, 0) + \ (y+y/10+y/100) * V(0, 1, 0) drawsphere_worker((newpos, radius, detailLevel)) continue continue return
def _orient(self, cntChunk, pt1, pt2): """ Orients the CNT I{cntChunk} based on two points. I{pt1} is the first endpoint (origin) of the nanotube. The vector I{pt1}, I{pt2} defines the direction and central axis of the nanotube. @param pt1: The starting endpoint (origin) of the nanotube. @type pt1: L{V} @param pt2: The second point of a vector defining the direction and central axis of the nanotube. @type pt2: L{V} """ a = V(0.0, 0.0, -1.0) # <a> is the unit vector pointing down the center axis of the default # DNA structure which is aligned along the Z axis. bLine = pt2 - pt1 bLength = vlen(bLine) b = bLine / bLength # <b> is the unit vector parallel to the line (i.e. pt1, pt2). axis = cross(a, b) # <axis> is the axis of rotation. theta = angleBetween(a, b) # <theta> is the angle (in degress) to rotate about <axis>. scalar = bLength * 0.5 rawOffset = b * scalar if 0: # Debugging code. print "" print "uVector a = ", a print "uVector b = ", b print "cross(a,b) =", axis print "theta =", theta print "cntRise =", self.getCntRise() print "# of cells =", self.getNumberOfCells() print "scalar =", scalar print "rawOffset =", rawOffset if theta == 0.0 or theta == 180.0: axis = V(0, 1, 0) # print "Now cross(a,b) =", axis rot = (pi / 180.0) * theta # Convert to radians qrot = Q(axis, rot) # Quat for rotation delta. # Move and rotate the nanotube into final orientation. cntChunk.move( qrot.rot(cntChunk.center) - cntChunk.center + rawOffset + pt1) cntChunk.rot(qrot) # Bruce suggested I add this. It works here, but not if its # before move() and rot() above. Mark 2008-04-11 cntChunk.full_inval_and_update() return
def displayLabelsAlongPlaneEdgesLowerLeft(h, w, hh, hw, uh, uw, text_offset, text_color, font_size, glpane): """ Display labels when origin is on the lower left corner. along all the plane edges @param h: height of the plane @type h: float @param w: width of the plane @type w: float @param hh: half the height of the plane @type hh: float @param hw: half the width of the plane @type hw: float @param uh: spacing along height of the plane @type uh: float @param uw: spacing along width of the plane @type uw: float @param text_offset: offset for label @type text_offset: float @param text_color: color of the text @type: text_colot: tuple @param font_size: size of the text font @type: font_size: float @param glpane: The 3D graphics area to draw it in. @type glpane: L{GLPane} """ #Along the origin edges # Draw unit text labels for horizontal lines (nm) y1 = 0 while y1 >= -h: drawtext("%g" % (-y1 / 10.0), text_color, V(-hw - 3 * text_offset, y1 + hh, 0.0), font_size, glpane) y1 -= uh # Draw unit text labels for vertical lines (nm). x1 = 0 while x1 <= w: drawtext("%g" % (x1 / 10.0), text_color, V(x1 - hw, hh + 2 * text_offset, 0.0), font_size, glpane) x1 += uw #Along the non origin edges # Draw unit text labels for horizontal lines (nm) y1 = 0 while y1 >= -h: drawtext("%g" % (-y1 / 10.0), text_color, V(hw + 2 * text_offset, y1 + hh, 0.0), font_size, glpane) y1 -= uh # Draw unit text labels for vertical lines (nm). x1 = 0 while x1 <= w: drawtext("%g" % (x1 / 10.0), text_color, V(x1 - hw, -hh - text_offset, 0.0), font_size, glpane) x1 += uw return
def drawsphere_worker_loop(params): (pos, radius, detailLevel, n) = params pos += V(-n / 2, -n / 2, 0) # Centered on the origin. for x in range(n): for y in range(n): newpos = pos + (x+x/10+x/100) * V(1, 0, 0) + \ (y+y/10+y/100) * V(0, 1, 0) drawsphere_worker((newpos, radius, detailLevel, 1)) continue continue return
def __getattr__(self, name): # in class RectGadget if name == 'bbox': return self.__computeBBox() elif name == 'planeNorm': return self.quat.rot(V(0.0, 0.0, 1.0)) elif name == 'right': return self.quat.rot(V(1.0, 0.0, 0.0)) elif name == 'up': return self.quat.rot(V(0.0, 1.0, 0.0)) else: raise AttributeError, 'RectGadget has no "%s"' % name
def arb_non_parallel_vector(vec): """ Given a nonzero vector, return an arbitrary vector not close to being parallel to it. """ x, y, z = vec if abs(z) < abs(x) > abs(y): # x is biggest, use y return V(0, 1, 0) else: return V(1, 0, 0) pass
def _computeBBox(self): """ Construct the 3D bounding box for this volume. """ self.rad = vlen(self.ptlist[1] - self.ptlist[0]) self.cirCenter = self.project_2d(self.ptlist[0]) bbhi = self.cirCenter + V(self.rad, self.rad) bblo = self.cirCenter - V(self.rad, self.rad) x, y = self.right, self.up self.bbox = BBox(V(bblo, bbhi), V(x, y), self.slab)
def _orientRawDnaGroup(self, rawDnaGroup, pt1, pt2): """ Orients the raw DNA group based on two endpoints. @param rawDnaGroup: The raw DNA group created by make(). @type rawDnaGroup: L{Group} @param pt1: The first endpoint of the DNA strand. @type pt1: L{V} @param pt2: The second endpoint of the DNA strand. @type pt2: L{V} @attention: Only works for PAM5 models. """ a = V(0.0, 0.0, -1.0) # <a> is the unit vector pointing down the center axis of the default # rawDnaGroup structure which is aligned along the Z axis. bLine = pt2 - pt1 bLength = vlen(bLine) b = bLine/bLength # <b> is the unit vector parallel to the line (i.e. pt1, pt2). axis = cross(a, b) # <axis> is the axis of rotation. theta = angleBetween(a, b) # <theta> is the angle (in degress) to rotate about <axis>. scalar = self.dna.getBaseRise() * self.getSequenceLength() * 0.5 rawOffset = b * scalar if 0: # Debugging code. print "" print "uVector a = ", a print "uVector b = ", b print "cross(a,b) =", axis print "theta =", theta print "baserise =", self.dna.getBaseRise() print "seqLength =", self.getSequenceLength() print "scalar =", scalar print "rawOffset =", rawOffset if theta == 0.0 or theta == 180.0: axis = V(0, 1, 0) # print "Now cross(a,b) =", axis rot = (pi / 180.0) * theta # Convert to radians qrot = Q(axis, rot) # Quat for rotation delta. # Move and rotate the base chunks into final orientation. for m in rawDnaGroup.members: m.move(qrot.rot(m.center) - m.center + rawOffset + pt1) m.rot(qrot)
def gather_parameters(self): """ Return the parameters from the property manager UI. @return: All the parameters: - dnaSequence - dnaType - basesPerTurn - chunkOption @rtype: tuple """ if not basepath_ok: raise PluginBug("The cad/plugins/DNA directory is missing.") dnaModel = str(self.modelComboBox.currentText()) dnaType = str(self.conformationComboBox.currentText()) assert dnaType in ('B-DNA') # Get bases per turn. basesPerTurnString = str(self.basesPerTurnComboBox.currentText()) basesPerTurn = float(basesPerTurnString) chunkOption = str(self.createComboBox.currentText()) resolve_random = False # Later this flag may depend on a new checkbox in that case; # for now it doesn't matter, since sequence info is # discarded for reduced bases anyway. (dnaSequence, allKnown) = \ self._getSequence( resolve_random = resolve_random) x1 = self.x1SpinBox.value() y1 = self.y1SpinBox.value() z1 = self.z1SpinBox.value() x2 = self.x2SpinBox.value() y2 = self.y2SpinBox.value() z2 = self.z2SpinBox.value() endpoint1 = V(x1, y1, z1) endpoint2 = V(x2, y2, z2) return (dnaSequence, dnaModel, dnaType, basesPerTurn, chunkOption, endpoint1, endpoint2)
def animate_TCs(): # Animate TCs, rotating them slowly. # Note: as of 090223 and before, this works in DL case but not in shader # case, because coordinate updates after TCs are modified are nim in # shader case (I think). [bruce 090223 comment] slow = 10.0 # Seconds. angle = 2 * pi * fmod(time.time(), slow) / slow # Leave the first one as identity, and rotate the others in # opposite directions around the X axis. TCs[1].setRotateTranslate(Q(V(1, 0, 0), angle * 2), V(0, 0, 0)) TCs[2].setRotateTranslate(Q(V(1, 0, 0), -angle), V(0, 0, 0)) return
def viewIsometric(self): """ This sets the view to isometric. For isometric view, it needs rotation around the vertical axis by pi/4 *followed* by rotation around horizontal axis by asin(tan(pi/6) - ninad060810 """ # This is not yet called from the MainWindow. Need UI for this. # Also need code review -ninad060810 cmd = greenmsg("Isometric View: ") info = 'Current view is Isometric View' env.history.message(cmd + info) self.quatX = Q(V(1,0,0), math.asin(math.tan(math.pi/6))) self.quatY = Q(V(0,1,0), -math.pi/4) self.glpane.rotateView(self.quatY+self.quatX)
def _orient(self, chunk, pt1, pt2): """ Orients the Peptide I{chunk} based on two points. I{pt1} is the first endpoint (origin) of the Peptide. The vector I{pt1}, I{pt2} defines the direction and central axis of the Peptide. piotr 080801: I copied this method from Nanotube Builder. @param pt1: The starting endpoint (origin) of the Peptide. @type pt1: L{V} @param pt2: The second point of a vector defining the direction and central axis of the Peptide. @type pt2: L{V} """ a = V(0.0, 0.0, -1.0) # <a> is the unit vector pointing down the center axis of the default # structure which is aligned along the Z axis. bLine = pt2 - pt1 bLength = vlen(bLine) if bLength == 0: return b = bLine / bLength # <b> is the unit vector parallel to the line (i.e. pt1, pt2). axis = cross(a, b) # <axis> is the axis of rotation. theta = angleBetween(a, b) # <theta> is the angle (in degress) to rotate about <axis>. scalar = bLength * 0.5 rawOffset = b * scalar if theta == 0.0 or theta == 180.0: axis = V(0, 1, 0) # print "Now cross(a,b) =", axis rot = (pi / 180.0) * theta # Convert to radians qrot = Q(axis, rot) # Quat for rotation delta. # Move and rotate the Peptide into final orientation. chunk.move(-chunk.center) chunk.rot(qrot) # Bruce suggested I add this. It works here, but not if its # before move() and rot() above. Mark 2008-04-11 chunk.full_inval_and_update() return
def _createStructure(self): """ Build a peptide from the parameters in the Property Manager. """ # self.name needed for done message if self.create_name_from_prefix: # create a new name name = self.name = gensym(self.prefix, self.win.assy) # (in _build_struct) self._gensym_data_for_reusing_name = (self.prefix, name) else: # use externally created name self._gensym_data_for_reusing_name = None # (can't reuse name in this case -- not sure what prefix it was # made with) name = self.name self.secondary, self.phi, self.psi, aa_type = self._gatherParameters() # self.win.assy.part.ensure_toplevel_group() """ struct = self.structGenerator.make(self.win.assy, name, params, -self.win.glpane.pov) """ from geometry.VQT import V pos1 = V(self.mouseClickPoints[0][0], \ self.mouseClickPoints[0][1], \ self.mouseClickPoints[0][2]) pos2 = V(self.mouseClickPoints[1][0], \ self.mouseClickPoints[1][1], \ self.mouseClickPoints[1][2]) struct = self.structGenerator.make_aligned(self.win.assy, name, aa_type, self.phi, self.psi, pos1, pos2, fake_chain=False, secondary=self.secondary) self.win.assy.part.topnode.addmember(struct) self.win.win_update() return struct