[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [2696] contrib/py/scripts/addons/ io_import_pdb_atomic_blender.py:

Clemens Barth barth at root-1.de
Thu Dec 1 19:46:11 CET 2011


Revision: 2696
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=2696
Author:   blendphys
Date:     2011-12-01 18:46:10 +0000 (Thu, 01 Dec 2011)
Log Message:
-----------


Dear all.

Exciting news: I also use now the dupliface technique for the sticks. As for
the atoms the loading of the sticks takes only a few time - the code is
very fast now for many-atom scenarios. Try out!

http://development.root-1.de/Atomic_Blender/dna.pdb

Small bugs
==========
During the last changes small bugs got inside the code:

- There was a tiny bug in the reading of the sticks. The bug was removed.
- The number of atoms was also wrong. Also this was corrected. 
- A slight error in the atom reading was removed.
- There was an error in the code that treats the custom data file. 
  The error was removed. 



Cheers,

Blendphys.

Modified Paths:
--------------
    contrib/py/scripts/addons/io_import_pdb_atomic_blender.py

Modified: contrib/py/scripts/addons/io_import_pdb_atomic_blender.py
===================================================================
--- contrib/py/scripts/addons/io_import_pdb_atomic_blender.py	2011-12-01 17:52:14 UTC (rev 2695)
+++ contrib/py/scripts/addons/io_import_pdb_atomic_blender.py	2011-12-01 18:46:10 UTC (rev 2696)
@@ -52,6 +52,7 @@
 import sys
 import math
 import os
+from math import pi, cos, sin
 from mathutils import Vector, Matrix
 from bpy_extras.io_utils import ImportHelper
 from bpy.props import (StringProperty,
@@ -487,7 +488,7 @@
             else:
                 if obj.type == "SURFACE" or obj.type == "MESH":
                     for element in ATOM_PDB_ELEMENTS:          
-                        if element[1] in obj.name:
+                        if element.name in obj.name:
                             obj.scale = (element.radii[0],
                                          element.radii[0],
                                          element.radii[0])
@@ -793,6 +794,59 @@
 #                                                          Some small routines
 
 
+# Routine which produces a cylinder. All is somewhat easy to undertsand. 
+def DEF_atom_pdb_build_stick(radius, length, sectors):
+        
+    vertices = []
+    faces    = []
+
+    dphi = 2.0 * pi/(float(sectors)-1)
+
+    # Vertices
+    vertices_top    = [Vector((0,0,length / 2.0))]
+    vertices_bottom = [Vector((0,0,-length / 2.0))]
+    for i in range(sectors-1):
+        x = radius * cos( dphi * i )
+        y = radius * sin( dphi * i )
+        z =  length / 2.0  
+        vertex = Vector((x,y,z))
+        vertices_top.append(vertex)
+        z = -length / 2.0
+        vertex = Vector((x,y,z))
+        vertices_bottom.append(vertex)
+    vertices = vertices_top + vertices_bottom
+
+    # Top facets
+    for i in range(sectors-1):
+        if i == sectors-2:
+            face_top = [0,sectors-1,1]
+            face_bottom = [sectors,2*sectors-1,sectors+1]
+        else:
+            face_top    = [0]
+            face_bottom = [sectors]
+            for j in range(2):
+                face_top.append(i+j+1)
+                face_bottom.append(i+j+1+sectors)
+        faces.append(face_top)
+        faces.append(face_bottom)
+
+    # Side facets   
+    for i in range(sectors-1):
+        if i == sectors-2:
+            faces.append(  [i+1, 1, 1+sectors, i+1+sectors] ) 
+        else:
+            faces.append(  [i+1, i+2, i+2+sectors, i+1+sectors] ) 
+
+    # Build the mesh
+    cylinder = bpy.data.meshes.new("Sticks_Cylinder")
+    cylinder.from_pydata(vertices, [], faces)
+    cylinder.update()
+    new_cylinder = bpy.data.objects.new("Sticks_Cylinder", cylinder)
+    bpy.context.scene.objects.link(new_cylinder)
+    
+    return new_cylinder
+
+
 # This function measures the distance between two objects (atoms), 
 # which are active.
 def DEF_atom_pdb_distance():
@@ -1065,12 +1119,17 @@
         # used for sticks. "TER? What is that?" TER indicates the end of a 
         # list of ATOM/HETATM records for a chain.
         if "TER" in line:
-            element = "TER"
+            short_name = "TER"
             name = "TER"
             radius = 0.0
             color = [0,0,0]
-            location = Vector((0,0,0))   
-            j += 1
+            location = Vector((0,0,0))  
+            # Append the TER into the list. Material remains empty so far.
+            all_atoms.append(CLASS_atom_pdb_atom(short_name, 
+                                                 name, 
+                                                 location, 
+                                                 radius, 
+                                                 color,[])) 
         # If 'ATOM or 'HETATM' appears in the line then do ...
         elif "ATOM" in line or "HETATM" in line:
 
@@ -1124,16 +1183,16 @@
             y = float(line[38:46].rsplit()[0])
             z = float(line[46:55].rsplit()[0])
            
-            location = Vector((x,y,z))     
+            location = Vector((x,y,z))   
+        
+            j += 1       
 
             # Append the atom to the list. Material remains empty so far.
             all_atoms.append(CLASS_atom_pdb_atom(short_name, 
                                              name, 
                                              location, 
                                              radius, 
-                                             color,[]))
-                          
-            j += 1        
+                                             color,[]))                  
                        
         line = ATOM_PDB_FILEPATH_p.readline()
         line = line[:-1]
@@ -1190,7 +1249,7 @@
                 # However, before we check, if it is a vacancy, because then it
                 # gets some additional preparation. The vacancy is represented
                 # by a transparent cube.
-                if name == "Vacancy":
+                if atom.name == "Vacancy":
                     material.transparency_method = 'Z_TRANSPARENCY'
                     material.alpha = 1.3
                     material.raytrace_transparency.fresnel = 1.6
@@ -1270,9 +1329,9 @@
             # couple of times. (Only god knows why ...) 
             # So, does a stick between the considered atoms already exist?
             FLAG_BAR = False
-            for k in range(j):
+            for k in range(Number_of_sticks):
                 if ((all_sticks[k].atom1 == atom1 and all_sticks[k].atom2 == atom2) or 
-                    (all_sticks[k].atom2 == atom2 and all_sticks[k].atom1 == atom1)):
+                    (all_sticks[k].atom2 == atom1 and all_sticks[k].atom1 == atom2)):
                     sticks_double += 1
                     # If yes, then FLAG on 'True'.
                     FLAG_BAR       = True
@@ -1577,57 +1636,63 @@
         stick_material = bpy.data.materials.new(ATOM_PDB_ELEMENTS[-1].name)  
         stick_material.diffuse_color = ATOM_PDB_ELEMENTS[-1].color
  
-        # This is the unit vector of the z axis
-        z_axis_vec = Vector((0.0, 0.0, 1.0))
- 
-        stick_group_list = []
+        vertices = []
+        faces    = []
+        dl = 0.2
+
+        i = 0
         # For all sticks, do ...
         for stick in all_sticks:
-            # Print on the terminal the actual number of the stick that is 
-            # build
-            sys.stdout.write("Stick No. %d has been built\r" % (i+1) )
-            sys.stdout.flush()
-            # Sum and difference of both atoms
-            vv_vec = (all_atoms[stick.atom2-1].location 
-                   + all_atoms[stick.atom1-1].location)
-            dv_vec = (all_atoms[stick.atom2-1].location 
-                   - all_atoms[stick.atom1-1].location)
-            # Angle with respect to the z-axis
-            angle = dv_vec.angle(z_axis_vec, 0)
-            # Cross-product between dv_vec and the z-axis vector. It is the 
-            # vector of rotation.
-            axis_vec = z_axis_vec.cross(dv_vec)
-            # Calculate Euler angles
-            euler = Matrix.Rotation(angle, 4, axis_vec).to_euler()
-            # Create stick
-            current_layers = bpy.context.scene.layers
-            bpy.ops.mesh.primitive_cylinder_add(vertices=Stick_sectors, 
-                                  radius=Stick_diameter, depth= dv_vec.length, 
-                                  cap_ends=True, view_align=False, 
-                                  enter_editmode=False, location= (vv_vec*0.5), 
-                                  rotation=(0,0,0), layers=current_layers)
-            # Put the stick into the scene ...
-            stick = bpy.context.scene.objects.active
-            # ... and rotate the stick.
-            stick.rotation_euler  = euler
-            stick.active_material = stick_material
-            stick.name = ATOM_PDB_ELEMENTS[-1].name
-            stick_group_list.append(stick)
-            
-        # 'Group' the stuff   
-        bpy.ops.object.select_all(action='DESELECT')   
-        stick_parent = stick_group_list[0]
-        inv_mat = stick_parent.matrix_world.inverted()
-        for stick in stick_group_list[1:]: 
-            stick.matrix_parent_inverse = inv_mat
-            stick.parent = stick_parent    
-        bpy.ops.object.select_all(action='DESELECT')   
-        sticks_grouped = bpy.context.scene.objects[0]
-        sticks_grouped.name = "Sticks"
-        LOADED_STRUCTURE.append(sticks_grouped)
+        
+            # What follows is school mathematics! :-)
+            v1 = all_atoms[stick.atom2-1].location
+            v2 = all_atoms[stick.atom1-1].location
+        
+            dv = (v1 - v2)
+           
+            n  = dv / dv.length
+            m  = v1 - dv / 2.0
+  
+            gamma = -n * v1
+            b     = v1 + gamma * n
+            n_b   = b / b.length
+ 
+            loops = int(dv.length / dl)
+       
+            for j in range(loops):
+        
+                g = v1 - n * dl / 2.0 - n * dl * j
+        
+                p1 = g + n_b * Stick_diameter
+                p2 = g - n_b * Stick_diameter
+                p3 = g - n_b.cross(n) * Stick_diameter
+                p4 = g + n_b.cross(n) * Stick_diameter
 
+                vertices.append(p1)
+                vertices.append(p2)
+                vertices.append(p3)
+                vertices.append(p4)
+                faces.append((i*4+0,i*4+2,i*4+1,i*4+3))
+                i += 1        
+              
+        mesh = bpy.data.meshes.new("Sticks")
+        mesh.from_pydata(vertices, [], faces)
+        mesh.update()
+        new_mesh = bpy.data.objects.new("Sticks", mesh)
+        bpy.context.scene.objects.link(new_mesh)  
+              
+        current_layers = bpy.context.scene.layers
+        stick_cylinder = DEF_atom_pdb_build_stick(Stick_diameter, dl, Stick_sectors)
+        
 
+        stick_cylinder.active_material = stick_material
+        stick_cylinder.parent = new_mesh
+        new_mesh.dupli_type = 'FACES'
+        LOADED_STRUCTURE.append(new_mesh)
+        
+
     print("\n\nAll atoms (%d) and sticks (%d) have been drawn - finished.\n\n" 
            % (Number_of_total_atoms,Number_of_sticks))
+      
 
     return Number_of_total_atoms



More information about the Bf-extensions-cvs mailing list