Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClemens Barth <barth@root-1.de>2013-04-04 21:21:55 +0400
committerClemens Barth <barth@root-1.de>2013-04-04 21:21:55 +0400
commit2e3a36f98d6e5990f822aaf4d44b2fb7f1b5d8d0 (patch)
tree326c65a1ed3a8373597f1a342d46004e9417a7c6 /io_mesh_pdb/import_pdb.py
parentb62c8e57401445f9411e0da76f1f55f252ae4d1e (diff)
1. After importing a structure, the sticks were not selected: fixed
2. Small cleanups of the code 3. New feature: The sticks can be represented as entire cylinders. One can choose either single cylinders, which are parented to an empty, or one single mesh object including all sticks. This feature is quite suitable for structures, which count more than 1000 sticks. When the sticks are represented by one single mesh object the handling in the 3D scene is much faster. Note that the layout of the preferences in the file dialog had to be also changed since there are more options for sticks now. Blendphys.
Diffstat (limited to 'io_mesh_pdb/import_pdb.py')
-rw-r--r--io_mesh_pdb/import_pdb.py485
1 files changed, 308 insertions, 177 deletions
diff --git a/io_mesh_pdb/import_pdb.py b/io_mesh_pdb/import_pdb.py
index d52a7e9f..37109cac 100644
--- a/io_mesh_pdb/import_pdb.py
+++ b/io_mesh_pdb/import_pdb.py
@@ -690,154 +690,11 @@ def draw_atoms_one_type(draw_all_atoms_type,
return new_atom_mesh
-# Function, which draws the sticks with help of the skin and subdivision
-# modifiers.
-def draw_sticks_skin(all_atoms,
- all_sticks,
- Stick_diameter,
- use_sticks_smooth,
- sticks_subdiv_view,
- sticks_subdiv_render):
-
- # These counters are for the edges, in the shape [i,i+1].
- i = 0
-
- # This is the list of vertices, containing the atom position
- # (vectors)).
- stick_vertices = []
- # This is the 'same' list, which contains not vector position of
- # the atoms but their numbers. It is used to handle the edges.
- stick_vertices_nr = []
- # This is the list of edges.
- stick_edges = []
-
- # Go through the list of all sticks. For each stick do:
- for stick in all_sticks:
-
- # Each stick has two atoms = two vertices.
-
- """
- [ 0,1 , 3,4 , 0,8 , 7,3]
- [[0,1], [2,3], [4,5], [6,7]]
-
- [ 0,1 , 3,4 , x,8 , 7,x] x:deleted
- [[0,1], [2,3], [0,5], [6,2]]
- """
-
- # Check, if the vertex (atom) is already in the vertex list.
- # edge: [s1,s2]
- FLAG_s1 = False
- s1 = 0
- for stick2 in stick_vertices_nr:
- if stick2 == stick.atom1-1:
- FLAG_s1 = True
- break
- s1 += 1
- FLAG_s2 = False
- s2 = 0
- for stick2 in stick_vertices_nr:
- if stick2 == stick.atom2-1:
- FLAG_s2 = True
- break
- s2 += 1
-
- # If the vertex (atom) is not yet in the vertex list:
- # append the number of atom and the vertex to the two lists.
- # For the first atom:
- if FLAG_s1 == False:
- atom1 = copy(all_atoms[stick.atom1-1].location)
- stick_vertices.append(atom1)
- stick_vertices_nr.append(stick.atom1-1)
- # For the second atom:
- if FLAG_s2 == False:
- atom2 = copy(all_atoms[stick.atom2-1].location)
- stick_vertices.append(atom2)
- stick_vertices_nr.append(stick.atom2-1)
-
- # Build the edges:
-
- # If both vertices (atoms) were not in the lists, then
- # the edge is simply [i,i+1]. These are two new vertices
- # (atoms), so increase i by 2.
- if FLAG_s1 == False and FLAG_s2 == False:
- stick_edges.append([i,i+1])
- i += 2
- # Both vertices (atoms) were already in the list, so then
- # use the vertices (atoms), which already exist. They are
- # at positions s1 and s2.
- if FLAG_s1 == True and FLAG_s2 == True:
- stick_edges.append([s1,s2])
- # The following two if cases describe the situation that
- # only one vertex (atom) was in the list. Since only ONE
- # new vertex was added, increase i by one.
- if FLAG_s1 == True and FLAG_s2 == False:
- stick_edges.append([s1,i])
- i += 1
- if FLAG_s1 == False and FLAG_s2 == True:
- stick_edges.append([i,s2])
- i += 1
-
- # Build the mesh of the sticks
- stick_mesh = bpy.data.meshes.new("Mesh_sticks")
- stick_mesh.from_pydata(stick_vertices, stick_edges, [])
- stick_mesh.update()
- new_stick_mesh = bpy.data.objects.new("Sticks", stick_mesh)
- bpy.context.scene.objects.link(new_stick_mesh)
-
- # Apply the skin modifier.
- new_stick_mesh.modifiers.new(name="Sticks_skin", type='SKIN')
- # Smooth the skin surface if this option has been chosen.
- new_stick_mesh.modifiers[0].use_smooth_shade = use_sticks_smooth
- # Apply the Subdivision modifier.
- new_stick_mesh.modifiers.new(name="Sticks_subsurf", type='SUBSURF')
- # Options: choose the levels
- new_stick_mesh.modifiers[1].levels = sticks_subdiv_view
- new_stick_mesh.modifiers[1].render_levels = sticks_subdiv_render
-
- bpy.ops.object.material_slot_add()
- stick_material = bpy.data.materials.new(ELEMENTS[-1].name)
- stick_material.diffuse_color = ELEMENTS[-1].color
- new_stick_mesh.active_material = stick_material
-
- # This is for putting the radiu of the sticks onto
- # the desired value 'Stick_diameter'
- bpy.context.scene.objects.active = new_stick_mesh
- # EDIT mode
- bpy.ops.object.mode_set(mode='EDIT', toggle=False)
- bm = bmesh.from_edit_mesh(new_stick_mesh.data)
- bpy.ops.mesh.select_all(action='DESELECT')
-
- # Select all vertices
- for v in bm.verts:
- v.select = True
-
- # This is somewhat a factor for the radius.
- r_f = 4.0
- # Apply operator 'skin_resize'.
- bpy.ops.transform.skin_resize(value=(Stick_diameter*r_f,
- Stick_diameter*r_f,
- Stick_diameter*r_f),
- constraint_axis=(False, False, False),
- constraint_orientation='GLOBAL',
- mirror=False,
- proportional='DISABLED',
- proportional_edit_falloff='SMOOTH',
- proportional_size=1,
- snap=False,
- snap_target='CLOSEST',
- snap_point=(0, 0, 0),
- snap_align=False,
- snap_normal=(0, 0, 0),
- texture_space=False,
- release_confirm=False)
- # Back to the OBJECT mode.
- bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
-
-
# Function, which draws the sticks with help of the dupliverts technique.
# Return: list of dupliverts structures.
def draw_sticks_dupliverts(all_atoms,
atom_all_types_list,
+ center,
all_sticks,
Stick_diameter,
Stick_sectors,
@@ -864,8 +721,8 @@ def draw_sticks_dupliverts(all_atoms,
for repeat in range(stick.number):
- atom1 = copy(all_atoms[stick.atom1-1].location)
- atom2 = copy(all_atoms[stick.atom2-1].location)
+ atom1 = copy(all_atoms[stick.atom1-1].location)-center
+ atom2 = copy(all_atoms[stick.atom2-1].location)-center
dist = Stick_diameter * Stick_dist
@@ -909,8 +766,8 @@ def draw_sticks_dupliverts(all_atoms,
for repeat in range(stick.number):
- atom1 = copy(all_atoms[stick.atom1-1].location)
- atom2 = copy(all_atoms[stick.atom2-1].location)
+ atom1 = copy(all_atoms[stick.atom1-1].location)-center
+ atom2 = copy(all_atoms[stick.atom2-1].location)-center
dist = Stick_diameter * Stick_dist
@@ -982,7 +839,6 @@ def draw_sticks_dupliverts(all_atoms,
bpy.context.scene.objects.link(new_mesh)
# Build the object.
- current_layers = bpy.context.scene.layers
# Get the cylinder from the 'build_stick' function.
object_stick = build_stick(Stick_diameter, dl, Stick_sectors)
stick_cylinder = object_stick[0]
@@ -1001,12 +857,269 @@ def draw_sticks_dupliverts(all_atoms,
stick_cylinder.parent = new_mesh
stick_cups.parent = new_mesh
new_mesh.dupli_type = 'FACES'
+ new_mesh.location = center
atom_object_list.append(new_mesh)
# Return the list of dupliverts structures.
return atom_object_list
+# Function, which draws the sticks with help of the skin and subdivision
+# modifiers.
+def draw_sticks_skin(all_atoms,
+ all_sticks,
+ Stick_diameter,
+ use_sticks_smooth,
+ sticks_subdiv_view,
+ sticks_subdiv_render):
+
+ # These counters are for the edges, in the shape [i,i+1].
+ i = 0
+
+ # This is the list of vertices, containing the atom position
+ # (vectors)).
+ stick_vertices = []
+ # This is the 'same' list, which contains not vector position of
+ # the atoms but their numbers. It is used to handle the edges.
+ stick_vertices_nr = []
+ # This is the list of edges.
+ stick_edges = []
+
+ # Go through the list of all sticks. For each stick do:
+ for stick in all_sticks:
+
+ # Each stick has two atoms = two vertices.
+
+ """
+ [ 0,1 , 3,4 , 0,8 , 7,3]
+ [[0,1], [2,3], [4,5], [6,7]]
+
+ [ 0,1 , 3,4 , x,8 , 7,x] x:deleted
+ [[0,1], [2,3], [0,5], [6,2]]
+ """
+
+ # Check, if the vertex (atom) is already in the vertex list.
+ # edge: [s1,s2]
+ FLAG_s1 = False
+ s1 = 0
+ for stick2 in stick_vertices_nr:
+ if stick2 == stick.atom1-1:
+ FLAG_s1 = True
+ break
+ s1 += 1
+ FLAG_s2 = False
+ s2 = 0
+ for stick2 in stick_vertices_nr:
+ if stick2 == stick.atom2-1:
+ FLAG_s2 = True
+ break
+ s2 += 1
+
+ # If the vertex (atom) is not yet in the vertex list:
+ # append the number of atom and the vertex to the two lists.
+ # For the first atom:
+ if FLAG_s1 == False:
+ atom1 = copy(all_atoms[stick.atom1-1].location)
+ stick_vertices.append(atom1)
+ stick_vertices_nr.append(stick.atom1-1)
+ # For the second atom:
+ if FLAG_s2 == False:
+ atom2 = copy(all_atoms[stick.atom2-1].location)
+ stick_vertices.append(atom2)
+ stick_vertices_nr.append(stick.atom2-1)
+
+ # Build the edges:
+
+ # If both vertices (atoms) were not in the lists, then
+ # the edge is simply [i,i+1]. These are two new vertices
+ # (atoms), so increase i by 2.
+ if FLAG_s1 == False and FLAG_s2 == False:
+ stick_edges.append([i,i+1])
+ i += 2
+ # Both vertices (atoms) were already in the list, so then
+ # use the vertices (atoms), which already exist. They are
+ # at positions s1 and s2.
+ if FLAG_s1 == True and FLAG_s2 == True:
+ stick_edges.append([s1,s2])
+ # The following two if cases describe the situation that
+ # only one vertex (atom) was in the list. Since only ONE
+ # new vertex was added, increase i by one.
+ if FLAG_s1 == True and FLAG_s2 == False:
+ stick_edges.append([s1,i])
+ i += 1
+ if FLAG_s1 == False and FLAG_s2 == True:
+ stick_edges.append([i,s2])
+ i += 1
+
+ # Build the mesh of the sticks
+ stick_mesh = bpy.data.meshes.new("Mesh_sticks")
+ stick_mesh.from_pydata(stick_vertices, stick_edges, [])
+ stick_mesh.update()
+ new_stick_mesh = bpy.data.objects.new("Sticks", stick_mesh)
+ bpy.context.scene.objects.link(new_stick_mesh)
+
+ # Apply the skin modifier.
+ new_stick_mesh.modifiers.new(name="Sticks_skin", type='SKIN')
+ # Smooth the skin surface if this option has been chosen.
+ new_stick_mesh.modifiers[0].use_smooth_shade = use_sticks_smooth
+ # Apply the Subdivision modifier.
+ new_stick_mesh.modifiers.new(name="Sticks_subsurf", type='SUBSURF')
+ # Options: choose the levels
+ new_stick_mesh.modifiers[1].levels = sticks_subdiv_view
+ new_stick_mesh.modifiers[1].render_levels = sticks_subdiv_render
+
+ bpy.ops.object.material_slot_add()
+ stick_material = bpy.data.materials.new(ELEMENTS[-1].name)
+ stick_material.diffuse_color = ELEMENTS[-1].color
+ new_stick_mesh.active_material = stick_material
+
+ # This is for putting the radiu of the sticks onto
+ # the desired value 'Stick_diameter'
+ bpy.context.scene.objects.active = new_stick_mesh
+ # EDIT mode
+ bpy.ops.object.mode_set(mode='EDIT', toggle=False)
+ bm = bmesh.from_edit_mesh(new_stick_mesh.data)
+ bpy.ops.mesh.select_all(action='DESELECT')
+
+ # Select all vertices
+ for v in bm.verts:
+ v.select = True
+
+ # This is somewhat a factor for the radius.
+ r_f = 4.0
+ # Apply operator 'skin_resize'.
+ bpy.ops.transform.skin_resize(value=(Stick_diameter*r_f,
+ Stick_diameter*r_f,
+ Stick_diameter*r_f),
+ constraint_axis=(False, False, False),
+ constraint_orientation='GLOBAL',
+ mirror=False,
+ proportional='DISABLED',
+ proportional_edit_falloff='SMOOTH',
+ proportional_size=1,
+ snap=False,
+ snap_target='CLOSEST',
+ snap_point=(0, 0, 0),
+ snap_align=False,
+ snap_normal=(0, 0, 0),
+ texture_space=False,
+ release_confirm=False)
+ # Back to the OBJECT mode.
+ bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+
+ return new_stick_mesh
+
+
+# Draw the sticks the normal way: connect the atoms by simple cylinders.
+# Two options: 1. single cylinders parented to an empty
+# 2. one single mesh object
+def draw_sticks_normal(all_atoms,
+ all_sticks,
+ center,
+ Stick_diameter,
+ Stick_sectors,
+ use_sticks_smooth,
+ use_sticks_one_object,
+ use_sticks_one_object_nr):
+
+ bpy.ops.object.material_slot_add()
+ stick_material = bpy.data.materials.new(ELEMENTS[-1].name)
+ stick_material.diffuse_color = ELEMENTS[-1].color
+
+ up_axis = Vector([0.0, 0.0, 1.0])
+ current_layers = bpy.context.scene.layers
+
+ # For all sticks, do ...
+ list_group = []
+ list_group_sub = []
+ counter = 0
+ for stick in all_sticks:
+
+ # The vectors of the two atoms
+ atom1 = all_atoms[stick.atom1-1].location-center
+ atom2 = all_atoms[stick.atom2-1].location-center
+ # Location
+ location = (atom1 + atom2) * 0.5
+ # The difference of both vectors
+ v = (atom2 - atom1)
+ # Angle with respect to the z-axis
+ angle = v.angle(up_axis, 0)
+ # Cross-product between v and the z-axis vector. It is the
+ # vector of rotation.
+ axis = up_axis.cross(v)
+ # Calculate Euler angles
+ euler = Matrix.Rotation(angle, 4, axis).to_euler()
+ # Create stick
+ bpy.ops.mesh.primitive_cylinder_add(vertices=Stick_sectors,
+ radius=Stick_diameter,
+ depth=v.length,
+ end_fill_type='NGON',
+ view_align=False,
+ enter_editmode=False,
+ location=location,
+ 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
+ # ... and name
+ stick.name = "Stick_Cylinder"
+ counter += 1
+
+ # Smooth the cylinder.
+ if use_sticks_smooth == True:
+ bpy.ops.object.select_all(action='DESELECT')
+ stick.select = True
+ bpy.ops.object.shade_smooth()
+
+ list_group_sub.append(stick)
+
+ if use_sticks_one_object == True:
+ if counter == use_sticks_one_object_nr:
+ bpy.ops.object.select_all(action='DESELECT')
+ for stick in list_group_sub:
+ stick.select = True
+ bpy.ops.object.join()
+ list_group.append(bpy.context.scene.objects.active)
+ bpy.ops.object.select_all(action='DESELECT')
+ list_group_sub = []
+ counter = 0
+ else:
+ # Material ...
+ stick.active_material = stick_material
+
+ if use_sticks_one_object == True:
+ bpy.ops.object.select_all(action='DESELECT')
+ for stick in list_group_sub:
+ stick.select = True
+ bpy.ops.object.join()
+ list_group.append(bpy.context.scene.objects.active)
+ bpy.ops.object.select_all(action='DESELECT')
+
+ for group in list_group:
+ group.select = True
+ bpy.ops.object.join()
+ bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY',
+ center='MEDIAN')
+ sticks = bpy.context.scene.objects.active
+ sticks.active_material = stick_material
+ else:
+ bpy.ops.object.empty_add(type='ARROWS',
+ view_align=False,
+ location=(0, 0, 0),
+ rotation=(0, 0, 0),
+ layers=current_layers)
+ sticks = bpy.context.scene.objects.active
+ for stick in list_group_sub:
+ stick.parent = sticks
+
+ sticks.name = "Sticks"
+ sticks.location += center
+
+ return sticks
+
+
# -----------------------------------------------------------------------------
# The main routine
@@ -1017,12 +1130,14 @@ def import_pdb(Ball_type,
radiustype,
Ball_distance_factor,
use_sticks,
- use_sticks_skin,
+ use_sticks_type,
sticks_subdiv_view,
sticks_subdiv_render,
use_sticks_color,
use_sticks_smooth,
- use_sticks_bonds,
+ use_sticks_bonds,
+ use_sticks_one_object,
+ use_sticks_one_object_nr,
Stick_unit, Stick_dist,
Stick_sectors,
Stick_diameter,
@@ -1156,7 +1271,6 @@ def import_pdb(Ball_type,
# taken as a measure. The size is used to place well the camera and light
# into the scene.
object_size_vec = [atom.location - object_center_vec for atom in all_atoms]
- object_size = 0.0
object_size = max(object_size_vec).length
# ------------------------------------------------------------------------
@@ -1187,9 +1301,9 @@ def import_pdb(Ball_type,
if atom.name == atom_type[0]:
# ... and append them to the list 'draw_all_atoms_type'.
draw_all_atoms_type.append([atom.name,
- atom.material,
- atom.location,
- atom.radius])
+ atom.material,
+ atom.location,
+ atom.radius])
# Now append the atom list to the list of all types of atoms
draw_all_atoms.append(draw_all_atoms_type)
@@ -1209,33 +1323,50 @@ def import_pdb(Ball_type,
atom_object_list.append(atom_mesh)
# ------------------------------------------------------------------------
+ # DRAWING THE STICKS: cylinders in a dupliverts structure
+
+ if use_sticks == True and use_sticks_type == '0' and all_sticks != []:
+
+ sticks = draw_sticks_dupliverts(all_atoms,
+ atom_all_types_list,
+ object_center_vec,
+ all_sticks,
+ Stick_diameter,
+ Stick_sectors,
+ Stick_unit,
+ Stick_dist,
+ use_sticks_smooth,
+ use_sticks_color)
+ for stick in sticks:
+ atom_object_list.append(stick)
+
+ # ------------------------------------------------------------------------
# DRAWING THE STICKS: skin and subdivision modifier
- if use_sticks == True and use_sticks_skin == True and all_sticks != []:
+ if use_sticks == True and use_sticks_type == '1' and all_sticks != []:
- draw_sticks_skin(all_atoms,
- all_sticks,
- Stick_diameter,
- use_sticks_smooth,
- sticks_subdiv_view,
- sticks_subdiv_render)
+ sticks = draw_sticks_skin(all_atoms,
+ all_sticks,
+ Stick_diameter,
+ use_sticks_smooth,
+ sticks_subdiv_view,
+ sticks_subdiv_render)
+ atom_object_list.append(sticks)
# ------------------------------------------------------------------------
- # DRAWING THE STICKS: cylinders in a dupliverts structure
-
- if use_sticks == True and all_sticks != [] and use_sticks_skin == False:
-
- stick_meshes = draw_sticks_dupliverts(all_atoms,
- atom_all_types_list,
- all_sticks,
- Stick_diameter,
- Stick_sectors,
- Stick_unit,
- Stick_dist,
- use_sticks_smooth,
- use_sticks_color)
- for stick_mesh in stick_meshes:
- atom_object_list.append(stick_mesh)
+ # DRAWING THE STICKS: normal cylinders
+
+ if use_sticks == True and use_sticks_type == '2' and all_sticks != []:
+
+ sticks = draw_sticks_normal(all_atoms,
+ all_sticks,
+ object_center_vec,
+ Stick_diameter,
+ Stick_sectors,
+ use_sticks_smooth,
+ use_sticks_one_object,
+ use_sticks_one_object_nr)
+ atom_object_list.append(sticks)
# ------------------------------------------------------------------------
# CAMERA and LIGHT SOURCES