From 1bafadf7cd5beb8c65ebbd2b3e70d4baa3b794b9 Mon Sep 17 00:00:00 2001
From: Clemens Barth <barth@root-1.de>
Date: Fri, 23 Mar 2012 20:34:45 +0000
Subject: [PATCH] - Option 'smooth' permits now a better 'polishing' of the
 sticks.

- The default value for the precision of the sticks (unit length)
  has been put from 0.2 onto 0.05. If the sticks are shown, they do not
  overlapp anymore.

- Code cleaning

- Due to the recent large changes of the code the addon has been tested
  with even more PDB files.


Blendphys

PS: see recent comment here: http://blenderartists.org/forum/showthread.php?235003-Atomic-Blender-for-loading-PDB-files-into-Blender-2.5&p=2079416&viewfull=1#post2079416
---
 io_mesh_pdb/__init__.py   |  36 +++---------
 io_mesh_pdb/export_pdb.py |   7 +--
 io_mesh_pdb/import_pdb.py | 114 +++++++++++++++++---------------------
 3 files changed, 61 insertions(+), 96 deletions(-)

diff --git a/io_mesh_pdb/__init__.py b/io_mesh_pdb/__init__.py
index 14b556f5e..3a479dbd1 100644
--- a/io_mesh_pdb/__init__.py
+++ b/io_mesh_pdb/__init__.py
@@ -42,12 +42,9 @@ from bpy.props import (StringProperty,
                        IntProperty,
                        FloatProperty)
 
-
-# TODO, allow reload
 from . import import_pdb
 from . import export_pdb
 
-
 ATOM_PDB_ERROR = ""
 ATOM_PDB_PANEL = ""
 
@@ -230,7 +227,7 @@ class CLASS_atom_pdb_Properties(bpy.types.PropertyGroup):
         name = "Radius", default=0.1, min=0.0001,
         description ="Radius of a stick")
     sticks_unit_length = FloatProperty(
-        name = "Unit", default=0.2, min=0.0001,
+        name = "Unit", default=0.05, min=0.0001,
         description = "Length of the unit of a stick in Angstrom")        
     use_sticks_color = BoolProperty(
         name="Color", default=True,
@@ -303,22 +300,6 @@ class CLASS_atom_pdb_datafile_apply(Operator):
 
         import_pdb.DEF_atom_pdb_custom_datafile(scn.datafile)
 
-        # TODO, move this into 'import_pdb' and call the function
-        for obj in bpy.context.selected_objects:
-            if len(obj.children) != 0:
-                child = obj.children[0]
-                if child.type == "SURFACE" or child.type  == "MESH":
-                    for element in import_pdb.ATOM_PDB_ELEMENTS:
-                        if element.name in obj.name:
-                            child.scale = (element.radii[0],) * 3
-                            child.active_material.diffuse_color = element.color
-            else:
-                if obj.type == "SURFACE" or obj.type == "MESH":
-                    for element in import_pdb.ATOM_PDB_ELEMENTS:
-                        if element.name in obj.name:
-                            obj.scale = (element.radii[0],) * 3
-                            obj.active_material.diffuse_color = element.color
-
         return {'FINISHED'}
 
 
@@ -350,7 +331,7 @@ class CLASS_atom_pdb_separate_atom(Operator):
         # ... delete the new mesh including the separated vertex
         bpy.ops.object.select_all(action='DESELECT')
         new_object.select = True
-        bpy.ops.object.delete()  # TODO, use scene.objects.unlink()
+        bpy.ops.object.delete()  
 
         # Create a new atom/vacancy at the position of the old atom
         current_layers=bpy.context.scene.layers
@@ -426,8 +407,7 @@ class CLASS_atom_pdb_radius_all_bigger_button(Operator):
         scn = bpy.context.scene.atom_pdb[0]
         import_pdb.DEF_atom_pdb_radius_all(
                 scn.radius_all,
-                scn.radius_how,
-                )
+                scn.radius_how,)
         return {'FINISHED'}
 
 
@@ -441,8 +421,7 @@ class CLASS_atom_pdb_radius_all_smaller_button(Operator):
         scn = bpy.context.scene.atom_pdb[0]
         import_pdb.DEF_atom_pdb_radius_all(
                 1.0/scn.radius_all,
-                scn.radius_how,
-                )
+                scn.radius_how,)
         return {'FINISHED'}
 
 
@@ -458,9 +437,8 @@ class CLASS_atom_pdb_radius_sticks_button(Operator):
         scn = bpy.context.scene.atom_pdb[0]
                 
         result = import_pdb.DEF_atom_pdb_radius_sticks(
-                     scn.sticks_radius * 0.9,
-                     scn.radius_how,)
-                     
+                     0.01,
+                     scn.radius_how,)  
         if result == False:
             ATOM_PDB_ERROR = "No sticks => no changes"
             bpy.ops.atom_pdb.error_dialog('INVOKE_DEFAULT')
@@ -606,7 +584,7 @@ class CLASS_ImportPDB(Operator, ImportHelper):
         name = "Radius", default=0.1, min=0.0001,
         description ="Radius of a stick")
     sticks_unit_length = FloatProperty(
-        name = "Unit", default=0.2, min=0.0001,
+        name = "Unit", default=0.05, min=0.0001,
         description = "Length of the unit of a stick in Angstrom")        
     use_sticks_color = BoolProperty(
         name="Color", default=True,
diff --git a/io_mesh_pdb/export_pdb.py b/io_mesh_pdb/export_pdb.py
index 5e17e0bbf..e47003610 100644
--- a/io_mesh_pdb/export_pdb.py
+++ b/io_mesh_pdb/export_pdb.py
@@ -25,7 +25,7 @@
 #
 #  Start of project              : 2011-08-31 by Clemens Barth
 #  First publication in Blender  : 2011-11-11
-#  Last modified                 : 2012-03-22
+#  Last modified                 : 2012-03-23
 #
 #  Acknowledgements: Thanks to ideasman, meta_androcto, truman, kilon,
 #  dairin0d, PKHG, Valter, etc
@@ -50,8 +50,6 @@ ATOM_PDB_PDBTEXT  = (  "REMARK This pdb file has been created with Blender "
                      + "REMARK\n")
 
 
-
-
 class CLASS_atom_pdb_atoms_export(object):  
     __slots__ = ('element', 'location')
     def __init__(self, element, location):
@@ -59,8 +57,6 @@ class CLASS_atom_pdb_atoms_export(object):
         self.location = location
 
 
-
-
 def DEF_atom_pdb_export(obj_type):
 
     list_atoms = []
@@ -117,3 +113,4 @@ def DEF_atom_pdb_export(obj_type):
     pdb_file_p.close()
 
     return True
+
diff --git a/io_mesh_pdb/import_pdb.py b/io_mesh_pdb/import_pdb.py
index fa8a92f51..b4f52af50 100644
--- a/io_mesh_pdb/import_pdb.py
+++ b/io_mesh_pdb/import_pdb.py
@@ -25,7 +25,7 @@
 #
 #  Start of project              : 2011-08-31 by Clemens Barth
 #  First publication in Blender  : 2011-11-11
-#  Last modified                 : 2012-03-22
+#  Last modified                 : 2012-03-23
 #
 #  Acknowledgements: Thanks to ideasman, meta_androcto, truman, kilon,
 #  dairin0d, PKHG, Valter, etc
@@ -216,22 +216,18 @@ class CLASS_atom_pdb_stick(object):
         self.number = number
         self.dist = dist
 
-
 # -----------------------------------------------------------------------------
 #                                                          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))]
+    vertices = []
     for i in range(sectors-1):
         x = radius * cos( dphi * i )
         y = radius * sin( dphi * i )
@@ -243,7 +239,16 @@ def DEF_atom_pdb_build_stick(radius, length, sectors):
         vertices_bottom.append(vertex)
     vertices = vertices_top + vertices_bottom
 
+    # Side facets (Cylinder)
+    faces1 = []    
+    for i in range(sectors-1):
+        if i == sectors-2:
+            faces1.append(  [i+1, 1, 1+sectors, i+1+sectors] )
+        else:
+            faces1.append(  [i+1, i+2, i+2+sectors, i+1+sectors] )
+
     # Top facets
+    faces2 = []    
     for i in range(sectors-1):
         if i == sectors-2:
             face_top = [0,sectors-1,1]
@@ -254,28 +259,27 @@ def DEF_atom_pdb_build_stick(radius, length, 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] )
+        faces2.append(face_top)
+        faces2.append(face_bottom)
 
-    # Build the mesh
+    # Build the mesh, Cylinder
     cylinder = bpy.data.meshes.new("Sticks_Cylinder")
-    cylinder.from_pydata(vertices, [], faces)
+    cylinder.from_pydata(vertices, [], faces1)
     cylinder.update()
     new_cylinder = bpy.data.objects.new("Sticks_Cylinder", cylinder)
     bpy.context.scene.objects.link(new_cylinder)
 
-    return new_cylinder
+    # Build the mesh, Cups
+    cups = bpy.data.meshes.new("Sticks_Cups")
+    cups.from_pydata(vertices, [], faces2)
+    cups.update()
+    new_cups = bpy.data.objects.new("Sticks_Cups", cups)
+    bpy.context.scene.objects.link(new_cups)
 
+    return (new_cylinder, new_cups)
 
-# This function measures the distance between two objects (atoms),
-# which are active.
+
+# This function measures the distance between two active objects (atoms).
 def DEF_atom_pdb_distance():
 
     if len(bpy.context.selected_bases) > 1:
@@ -495,7 +499,6 @@ def DEF_atom_pdb_radius_sticks(radius, how):
 
     return True
 
-
 # -----------------------------------------------------------------------------
 #                                                         The custom data file
 
@@ -556,14 +559,27 @@ def DEF_atom_pdb_custom_datafile(path_datafile):
             ATOM_PDB_ELEMENTS.append(element)
 
     data_file_p.close()
-
+    
+    for obj in bpy.context.selected_objects:
+        if len(obj.children) != 0:
+            child = obj.children[0]
+            if child.type == "SURFACE" or child.type  == "MESH":
+                for element in ATOM_PDB_ELEMENTS:
+                    if element.name in obj.name:
+                        child.scale = (element.radii[0],) * 3
+                        child.active_material.diffuse_color = element.color
+        else:
+            if obj.type == "SURFACE" or obj.type == "MESH":
+                for element in ATOM_PDB_ELEMENTS:
+                    if element.name in obj.name:
+                        obj.scale = (element.radii[0],) * 3
+                        obj.active_material.diffuse_color = element.color
+                        
     return True
 
-
 # -----------------------------------------------------------------------------
 #                                                            The main routine
 
-
 def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
                Ball_radius_factor,radiustype,Ball_distance_factor,
                use_sticks,use_sticks_color,use_sticks_smooth,
@@ -602,11 +618,9 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
                                      radii,radii_ionic)
         ATOM_PDB_ELEMENTS.append(li)
 
-
     # ------------------------------------------------------------------------
     # READING DATA OF ATOMS
 
-
     if DEF_atom_pdb_custom_datafile(path_datafile):
         print("Custom data file is loaded.")
 
@@ -738,11 +752,9 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
     # From above it can be clearly seen that j is now the number of all atoms.
     Number_of_total_atoms = j
 
-
     # ------------------------------------------------------------------------
     # MATERIAL PROPERTIES FOR ATOMS
 
-
     # The list that contains info about all types of atoms is created
     # here. It is used for building the material properties for
     # instance (see below).
@@ -795,11 +807,9 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
                 # The atom gets its properties.
                 atom.material = material
 
-
     # ------------------------------------------------------------------------
     # READING DATA OF STICKS
 
-
     # Open the PDB file again such that the file pointer is in the first
     # line ... . Stupid, I know ... ;-)
     ATOM_PDB_FILEPATH_p = io.open(ATOM_PDB_FILEPATH, "r")
@@ -829,8 +839,8 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
         # The strings of the atom numbers do have a clear position in the file
         # (From 7 to 12, from 13 to 18 and so on.) and one needs to consider
         # this. One could also use the split function but then one gets into
-        # trouble if there are many atoms: For instance, it may happen that one
-        # has
+        # trouble if there are lots of atoms: For instance, it may happen that
+        # one has
         #                   CONECT 11111  22244444
         #
         # In Fact it means that atom No. 11111 has a connection with atom
@@ -914,11 +924,9 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
     ATOM_PDB_FILEPATH_p.close()
     # So far, all atoms and sticks have been registered.
 
-
     # ------------------------------------------------------------------------
     # TRANSLATION OF THE STRUCTURE TO THE ORIGIN
 
-
     # It may happen that the structure in a PDB file already has an offset
     # If chosen, the structure is first put into the center of the scene
     # (the offset is substracted).
@@ -937,20 +945,16 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
         for atom in all_atoms:
             atom.location -= sum_vec
 
-
     # ------------------------------------------------------------------------
     # SCALING
 
-
     # Take all atoms and adjust their radii and scale the distances.
     for atom in all_atoms:
         atom.location *= Ball_distance_factor
 
-
     # ------------------------------------------------------------------------
     # DETERMINATION OF SOME GEOMETRIC PROPERTIES
 
-
     # In the following, some geometric properties of the whole object are
     # determined: center, size, etc.
     sum_vec = Vector((0.0,0.0,0.0))
@@ -968,7 +972,6 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
     object_size = 0.0
     object_size = max(object_size_vec).length
 
-
     # ------------------------------------------------------------------------
     # CAMERA AND LAMP
 
@@ -1024,14 +1027,6 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
                                  snap_align=False, snap_normal=(0, 0, 0),
                                  release_confirm=False)
 
-
-        # This does not work, I don't know why.
-        #
-        #for area in bpy.context.screen.areas:
-        #    if area.type == 'VIEW_3D':
-        #        area.spaces[0].region_3d.view_perspective = 'CAMERA'
-
-
     # Here a lamp is put into the scene, if chosen.
     if use_lamp == True:
 
@@ -1063,11 +1058,9 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
         bpy.context.scene.world.light_settings.use_ambient_occlusion = True
         bpy.context.scene.world.light_settings.ao_factor = 0.2
 
-
     # ------------------------------------------------------------------------
     # SOME OUTPUT ON THE CONSOLE
 
-
     print()
     print()
     print()
@@ -1079,11 +1072,9 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
     print("Size of object (Angstrom)   : ", object_size)
     print()
 
-
     # ------------------------------------------------------------------------
     # SORTING THE ATOMS
 
-
     # Lists of atoms of one type are created. Example:
     # draw_all_atoms = [ data_hydrogen,data_carbon,data_nitrogen ]
     # data_hydrogen = [["Hydrogen", Material_Hydrogen, Vector((x,y,z)), 109], ...]
@@ -1116,11 +1107,9 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
         # Now append the atom list to the list of all types of atoms
         draw_all_atoms.append(draw_all_atoms_type)
 
-
     # ------------------------------------------------------------------------
     # DRAWING THE ATOMS
 
-
     # This is the number of all atoms which are put into the scene.
     bpy.ops.object.select_all(action='DESELECT')
 
@@ -1183,7 +1172,6 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
 
     print()
 
-
     # ------------------------------------------------------------------------
     # DRAWING THE STICKS
 
@@ -1280,7 +1268,6 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
 
             sticks_all_lists.append(sticks_list)
 
-
         # ... the sticks in the list can be drawn:
         for stick_list in sticks_all_lists:
             vertices = []
@@ -1324,19 +1311,23 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
             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)
+            object_stick = DEF_atom_pdb_build_stick(Stick_diameter, dl, Stick_sectors)
+            stick_cylinder = object_stick[0]
             stick_cylinder.active_material = stick[3]
-            
+            stick_cups = object_stick[1]
+            stick_cups.active_material = stick[3]            
+                   
             if use_sticks_smooth == True: 
-                for face in stick_cylinder.data.faces:
-                    face.use_smooth = True
+                bpy.ops.object.select_all(action='DESELECT')
+                stick_cylinder.select = True
+                stick_cups.select = True
+                bpy.ops.object.shade_smooth()
 
             stick_cylinder.parent = new_mesh
+            stick_cups.parent = new_mesh
             new_mesh.dupli_type = 'FACES'
             atom_object_list.append(new_mesh)
 
-
-
     # ------------------------------------------------------------------------
     # SELECT ALL LOADED OBJECTS
     bpy.ops.object.select_all(action='DESELECT')
@@ -1351,5 +1342,4 @@ def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
     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
-- 
GitLab