Extensions: change the constant for the complete status
[blender-addons-contrib.git] / add_mesh_clusters / add_mesh_cluster.py
blobc5515b7e344f47672e1df2321523d7d8469c7ea6
1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
19 import bpy
20 import io
21 import math
22 import os
23 import copy
24 from math import pi, cos, sin, tan, sqrt
25 from mathutils import Vector, Matrix
26 from copy import copy
28 # -----------------------------------------------------------------------------
29 # Atom, stick and element data
32 # This is a list that contains some data of all possible elements. The structure
33 # is as follows:
35 # 1, "Hydrogen", "H", [0.0,0.0,1.0], 0.32, 0.32, 0.32 , -1 , 1.54 means
37 # No., name, short name, color, radius (used), radius (covalent), radius (atomic),
39 # charge state 1, radius (ionic) 1, charge state 2, radius (ionic) 2, ... all
40 # charge states for any atom are listed, if existing.
41 # The list is fixed and cannot be changed ... (see below)
43 ATOM_CLUSTER_ELEMENTS_DEFAULT = (
44 ( 1, "Hydrogen", "H", ( 1.0, 1.0, 1.0, 1.0), 0.32, 0.32, 0.79 , -1 , 1.54 ),
45 ( 2, "Helium", "He", ( 0.85, 1.0, 1.0, 1.0), 0.93, 0.93, 0.49 ),
46 ( 3, "Lithium", "Li", ( 0.8, 0.50, 1.0, 1.0), 1.23, 1.23, 2.05 , 1 , 0.68 ),
47 ( 4, "Beryllium", "Be", ( 0.76, 1.0, 0.0, 1.0), 0.90, 0.90, 1.40 , 1 , 0.44 , 2 , 0.35 ),
48 ( 5, "Boron", "B", ( 1.0, 0.70, 0.70, 1.0), 0.82, 0.82, 1.17 , 1 , 0.35 , 3 , 0.23 ),
49 ( 6, "Carbon", "C", ( 0.56, 0.56, 0.56, 1.0), 0.77, 0.77, 0.91 , -4 , 2.60 , 4 , 0.16 ),
50 ( 7, "Nitrogen", "N", ( 0.18, 0.31, 0.97, 1.0), 0.75, 0.75, 0.75 , -3 , 1.71 , 1 , 0.25 , 3 , 0.16 , 5 , 0.13 ),
51 ( 8, "Oxygen", "O", ( 1.0, 0.05, 0.05, 1.0), 0.73, 0.73, 0.65 , -2 , 1.32 , -1 , 1.76 , 1 , 0.22 , 6 , 0.09 ),
52 ( 9, "Fluorine", "F", ( 0.56, 0.87, 0.31, 1.0), 0.72, 0.72, 0.57 , -1 , 1.33 , 7 , 0.08 ),
53 (10, "Neon", "Ne", ( 0.70, 0.89, 0.96, 1.0), 0.71, 0.71, 0.51 , 1 , 1.12 ),
54 (11, "Sodium", "Na", ( 0.67, 0.36, 0.94, 1.0), 1.54, 1.54, 2.23 , 1 , 0.97 ),
55 (12, "Magnesium", "Mg", ( 0.54, 1.0, 0.0, 1.0), 1.36, 1.36, 1.72 , 1 , 0.82 , 2 , 0.66 ),
56 (13, "Aluminium", "Al", ( 0.74, 0.65, 0.65, 1.0), 1.18, 1.18, 1.82 , 3 , 0.51 ),
57 (14, "Silicon", "Si", ( 0.94, 0.78, 0.62, 1.0), 1.11, 1.11, 1.46 , -4 , 2.71 , -1 , 3.84 , 1 , 0.65 , 4 , 0.42 ),
58 (15, "Phosphorus", "P", ( 1.0, 0.50, 0.0, 1.0), 1.06, 1.06, 1.23 , -3 , 2.12 , 3 , 0.44 , 5 , 0.35 ),
59 (16, "Sulfur", "S", ( 1.0, 1.0, 0.18, 1.0), 1.02, 1.02, 1.09 , -2 , 1.84 , 2 , 2.19 , 4 , 0.37 , 6 , 0.30 ),
60 (17, "Chlorine", "Cl", ( 0.12, 0.94, 0.12, 1.0), 0.99, 0.99, 0.97 , -1 , 1.81 , 5 , 0.34 , 7 , 0.27 ),
61 (18, "Argon", "Ar", ( 0.50, 0.81, 0.89, 1.0), 0.98, 0.98, 0.88 , 1 , 1.54 ),
62 (19, "Potassium", "K", ( 0.56, 0.25, 0.83, 1.0), 2.03, 2.03, 2.77 , 1 , 0.81 ),
63 (20, "Calcium", "Ca", ( 0.23, 1.0, 0.0, 1.0), 1.74, 1.74, 2.23 , 1 , 1.18 , 2 , 0.99 ),
64 (21, "Scandium", "Sc", ( 0.90, 0.90, 0.90, 1.0), 1.44, 1.44, 2.09 , 3 , 0.73 ),
65 (22, "Titanium", "Ti", ( 0.74, 0.76, 0.78, 1.0), 1.32, 1.32, 2.00 , 1 , 0.96 , 2 , 0.94 , 3 , 0.76 , 4 , 0.68 ),
66 (23, "Vanadium", "V", ( 0.65, 0.65, 0.67, 1.0), 1.22, 1.22, 1.92 , 2 , 0.88 , 3 , 0.74 , 4 , 0.63 , 5 , 0.59 ),
67 (24, "Chromium", "Cr", ( 0.54, 0.6, 0.78, 1.0), 1.18, 1.18, 1.85 , 1 , 0.81 , 2 , 0.89 , 3 , 0.63 , 6 , 0.52 ),
68 (25, "Manganese", "Mn", ( 0.61, 0.47, 0.78, 1.0), 1.17, 1.17, 1.79 , 2 , 0.80 , 3 , 0.66 , 4 , 0.60 , 7 , 0.46 ),
69 (26, "Iron", "Fe", ( 0.87, 0.4, 0.2, 1.0), 1.17, 1.17, 1.72 , 2 , 0.74 , 3 , 0.64 ),
70 (27, "Cobalt", "Co", ( 0.94, 0.56, 0.62, 1.0), 1.16, 1.16, 1.67 , 2 , 0.72 , 3 , 0.63 ),
71 (28, "Nickel", "Ni", ( 0.31, 0.81, 0.31, 1.0), 1.15, 1.15, 1.62 , 2 , 0.69 ),
72 (29, "Copper", "Cu", ( 0.78, 0.50, 0.2, 1.0), 1.17, 1.17, 1.57 , 1 , 0.96 , 2 , 0.72 ),
73 (30, "Zinc", "Zn", ( 0.49, 0.50, 0.69, 1.0), 1.25, 1.25, 1.53 , 1 , 0.88 , 2 , 0.74 ),
74 (31, "Gallium", "Ga", ( 0.76, 0.56, 0.56, 1.0), 1.26, 1.26, 1.81 , 1 , 0.81 , 3 , 0.62 ),
75 (32, "Germanium", "Ge", ( 0.4, 0.56, 0.56, 1.0), 1.22, 1.22, 1.52 , -4 , 2.72 , 2 , 0.73 , 4 , 0.53 ),
76 (33, "Arsenic", "As", ( 0.74, 0.50, 0.89, 1.0), 1.20, 1.20, 1.33 , -3 , 2.22 , 3 , 0.58 , 5 , 0.46 ),
77 (34, "Selenium", "Se", ( 1.0, 0.63, 0.0, 1.0), 1.16, 1.16, 1.22 , -2 , 1.91 , -1 , 2.32 , 1 , 0.66 , 4 , 0.50 , 6 , 0.42 ),
78 (35, "Bromine", "Br", ( 0.65, 0.16, 0.16, 1.0), 1.14, 1.14, 1.12 , -1 , 1.96 , 5 , 0.47 , 7 , 0.39 ),
79 (36, "Krypton", "Kr", ( 0.36, 0.72, 0.81, 1.0), 1.31, 1.31, 1.24 ),
80 (37, "Rubidium", "Rb", ( 0.43, 0.18, 0.69, 1.0), 2.16, 2.16, 2.98 , 1 , 1.47 ),
81 (38, "Strontium", "Sr", ( 0.0, 1.0, 0.0, 1.0), 1.91, 1.91, 2.45 , 2 , 1.12 ),
82 (39, "Yttrium", "Y", ( 0.58, 1.0, 1.0, 1.0), 1.62, 1.62, 2.27 , 3 , 0.89 ),
83 (40, "Zirconium", "Zr", ( 0.58, 0.87, 0.87, 1.0), 1.45, 1.45, 2.16 , 1 , 1.09 , 4 , 0.79 ),
84 (41, "Niobium", "Nb", ( 0.45, 0.76, 0.78, 1.0), 1.34, 1.34, 2.08 , 1 , 1.00 , 4 , 0.74 , 5 , 0.69 ),
85 (42, "Molybdenum", "Mo", ( 0.32, 0.70, 0.70, 1.0), 1.30, 1.30, 2.01 , 1 , 0.93 , 4 , 0.70 , 6 , 0.62 ),
86 (43, "Technetium", "Tc", ( 0.23, 0.61, 0.61, 1.0), 1.27, 1.27, 1.95 , 7 , 0.97 ),
87 (44, "Ruthenium", "Ru", ( 0.14, 0.56, 0.56, 1.0), 1.25, 1.25, 1.89 , 4 , 0.67 ),
88 (45, "Rhodium", "Rh", ( 0.03, 0.49, 0.54, 1.0), 1.25, 1.25, 1.83 , 3 , 0.68 ),
89 (46, "Palladium", "Pd", ( 0.0, 0.41, 0.52, 1.0), 1.28, 1.28, 1.79 , 2 , 0.80 , 4 , 0.65 ),
90 (47, "Silver", "Ag", ( 0.75, 0.75, 0.75, 1.0), 1.34, 1.34, 1.75 , 1 , 1.26 , 2 , 0.89 ),
91 (48, "Cadmium", "Cd", ( 1.0, 0.85, 0.56, 1.0), 1.48, 1.48, 1.71 , 1 , 1.14 , 2 , 0.97 ),
92 (49, "Indium", "In", ( 0.65, 0.45, 0.45, 1.0), 1.44, 1.44, 2.00 , 3 , 0.81 ),
93 (50, "Tin", "Sn", ( 0.4, 0.50, 0.50, 1.0), 1.41, 1.41, 1.72 , -4 , 2.94 , -1 , 3.70 , 2 , 0.93 , 4 , 0.71 ),
94 (51, "Antimony", "Sb", ( 0.61, 0.38, 0.70, 1.0), 1.40, 1.40, 1.53 , -3 , 2.45 , 3 , 0.76 , 5 , 0.62 ),
95 (52, "Tellurium", "Te", ( 0.83, 0.47, 0.0, 1.0), 1.36, 1.36, 1.42 , -2 , 2.11 , -1 , 2.50 , 1 , 0.82 , 4 , 0.70 , 6 , 0.56 ),
96 (53, "Iodine", "I", ( 0.58, 0.0, 0.58, 1.0), 1.33, 1.33, 1.32 , -1 , 2.20 , 5 , 0.62 , 7 , 0.50 ),
97 (54, "Xenon", "Xe", ( 0.25, 0.61, 0.69, 1.0), 1.31, 1.31, 1.24 ),
98 (55, "Caesium", "Cs", ( 0.34, 0.09, 0.56, 1.0), 2.35, 2.35, 3.35 , 1 , 1.67 ),
99 (56, "Barium", "Ba", ( 0.0, 0.78, 0.0, 1.0), 1.98, 1.98, 2.78 , 1 , 1.53 , 2 , 1.34 ),
100 (57, "Lanthanum", "La", ( 0.43, 0.83, 1.0, 1.0), 1.69, 1.69, 2.74 , 1 , 1.39 , 3 , 1.06 ),
101 (58, "Cerium", "Ce", ( 1.0, 1.0, 0.78, 1.0), 1.65, 1.65, 2.70 , 1 , 1.27 , 3 , 1.03 , 4 , 0.92 ),
102 (59, "Praseodymium", "Pr", ( 0.85, 1.0, 0.78, 1.0), 1.65, 1.65, 2.67 , 3 , 1.01 , 4 , 0.90 ),
103 (60, "Neodymium", "Nd", ( 0.78, 1.0, 0.78, 1.0), 1.64, 1.64, 2.64 , 3 , 0.99 ),
104 (61, "Promethium", "Pm", ( 0.63, 1.0, 0.78, 1.0), 1.63, 1.63, 2.62 , 3 , 0.97 ),
105 (62, "Samarium", "Sm", ( 0.56, 1.0, 0.78, 1.0), 1.62, 1.62, 2.59 , 3 , 0.96 ),
106 (63, "Europium", "Eu", ( 0.38, 1.0, 0.78, 1.0), 1.85, 1.85, 2.56 , 2 , 1.09 , 3 , 0.95 ),
107 (64, "Gadolinium", "Gd", ( 0.27, 1.0, 0.78, 1.0), 1.61, 1.61, 2.54 , 3 , 0.93 ),
108 (65, "Terbium", "Tb", ( 0.18, 1.0, 0.78, 1.0), 1.59, 1.59, 2.51 , 3 , 0.92 , 4 , 0.84 ),
109 (66, "Dysprosium", "Dy", ( 0.12, 1.0, 0.78, 1.0), 1.59, 1.59, 2.49 , 3 , 0.90 ),
110 (67, "Holmium", "Ho", ( 0.0, 1.0, 0.61, 1.0), 1.58, 1.58, 2.47 , 3 , 0.89 ),
111 (68, "Erbium", "Er", ( 0.0, 0.90, 0.45, 1.0), 1.57, 1.57, 2.45 , 3 , 0.88 ),
112 (69, "Thulium", "Tm", ( 0.0, 0.83, 0.32, 1.0), 1.56, 1.56, 2.42 , 3 , 0.87 ),
113 (70, "Ytterbium", "Yb", ( 0.0, 0.74, 0.21, 1.0), 1.74, 1.74, 2.40 , 2 , 0.93 , 3 , 0.85 ),
114 (71, "Lutetium", "Lu", ( 0.0, 0.67, 0.14, 1.0), 1.56, 1.56, 2.25 , 3 , 0.85 ),
115 (72, "Hafnium", "Hf", ( 0.30, 0.76, 1.0, 1.0), 1.44, 1.44, 2.16 , 4 , 0.78 ),
116 (73, "Tantalum", "Ta", ( 0.30, 0.65, 1.0, 1.0), 1.34, 1.34, 2.09 , 5 , 0.68 ),
117 (74, "Tungsten", "W", ( 0.12, 0.58, 0.83, 1.0), 1.30, 1.30, 2.02 , 4 , 0.70 , 6 , 0.62 ),
118 (75, "Rhenium", "Re", ( 0.14, 0.49, 0.67, 1.0), 1.28, 1.28, 1.97 , 4 , 0.72 , 7 , 0.56 ),
119 (76, "Osmium", "Os", ( 0.14, 0.4, 0.58, 1.0), 1.26, 1.26, 1.92 , 4 , 0.88 , 6 , 0.69 ),
120 (77, "Iridium", "Ir", ( 0.09, 0.32, 0.52, 1.0), 1.27, 1.27, 1.87 , 4 , 0.68 ),
121 (78, "Platinum", "Pt", ( 0.81, 0.81, 0.87, 1.0), 1.30, 1.30, 1.83 , 2 , 0.80 , 4 , 0.65 ),
122 (79, "Gold", "Au", ( 1.0, 0.81, 0.13, 1.0), 1.34, 1.34, 1.79 , 1 , 1.37 , 3 , 0.85 ),
123 (80, "Mercury", "Hg", ( 0.72, 0.72, 0.81, 1.0), 1.49, 1.49, 1.76 , 1 , 1.27 , 2 , 1.10 ),
124 (81, "Thallium", "Tl", ( 0.65, 0.32, 0.30, 1.0), 1.48, 1.48, 2.08 , 1 , 1.47 , 3 , 0.95 ),
125 (82, "Lead", "Pb", ( 0.34, 0.34, 0.38, 1.0), 1.47, 1.47, 1.81 , 2 , 1.20 , 4 , 0.84 ),
126 (83, "Bismuth", "Bi", ( 0.61, 0.30, 0.70, 1.0), 1.46, 1.46, 1.63 , 1 , 0.98 , 3 , 0.96 , 5 , 0.74 ),
127 (84, "Polonium", "Po", ( 0.67, 0.36, 0.0, 1.0), 1.46, 1.46, 1.53 , 6 , 0.67 ),
128 (85, "Astatine", "At", ( 0.45, 0.30, 0.27, 1.0), 1.45, 1.45, 1.43 , -3 , 2.22 , 3 , 0.85 , 5 , 0.46 ),
129 (86, "Radon", "Rn", ( 0.25, 0.50, 0.58, 1.0), 1.00, 1.00, 1.34 ),
130 (87, "Francium", "Fr", ( 0.25, 0.0, 0.4, 1.0), 1.00, 1.00, 1.00 , 1 , 1.80 ),
131 (88, "Radium", "Ra", ( 0.0, 0.49, 0.0, 1.0), 1.00, 1.00, 1.00 , 2 , 1.43 ),
132 (89, "Actinium", "Ac", ( 0.43, 0.67, 0.98, 1.0), 1.00, 1.00, 1.00 , 3 , 1.18 ),
133 (90, "Thorium", "Th", ( 0.0, 0.72, 1.0, 1.0), 1.65, 1.65, 1.00 , 4 , 1.02 ),
134 (91, "Protactinium", "Pa", ( 0.0, 0.63, 1.0, 1.0), 1.00, 1.00, 1.00 , 3 , 1.13 , 4 , 0.98 , 5 , 0.89 ),
135 (92, "Uranium", "U", ( 0.0, 0.56, 1.0, 1.0), 1.42, 1.42, 1.00 , 4 , 0.97 , 6 , 0.80 ),
136 (93, "Neptunium", "Np", ( 0.0, 0.50, 1.0, 1.0), 1.00, 1.00, 1.00 , 3 , 1.10 , 4 , 0.95 , 7 , 0.71 ),
137 (94, "Plutonium", "Pu", ( 0.0, 0.41, 1.0, 1.0), 1.00, 1.00, 1.00 , 3 , 1.08 , 4 , 0.93 ),
138 (95, "Americium", "Am", ( 0.32, 0.36, 0.94, 1.0), 1.00, 1.00, 1.00 , 3 , 1.07 , 4 , 0.92 ),
139 (96, "Curium", "Cm", ( 0.47, 0.36, 0.89, 1.0), 1.00, 1.00, 1.00 ),
140 (97, "Berkelium", "Bk", ( 0.54, 0.30, 0.89, 1.0), 1.00, 1.00, 1.00 ),
141 (98, "Californium", "Cf", ( 0.63, 0.21, 0.83, 1.0), 1.00, 1.00, 1.00 ),
142 (99, "Einsteinium", "Es", ( 0.70, 0.12, 0.83, 1.0), 1.00, 1.00, 1.00 ),
143 (100, "Fermium", "Fm", ( 0.70, 0.12, 0.72, 1.0), 1.00, 1.00, 1.00 ),
144 (101, "Mendelevium", "Md", ( 0.70, 0.05, 0.65, 1.0), 1.00, 1.00, 1.00 ),
145 (102, "Nobelium", "No", ( 0.74, 0.05, 0.52, 1.0), 1.00, 1.00, 1.00 ),
146 (103, "Lawrencium", "Lr", ( 0.78, 0.0, 0.4, 1.0), 1.00, 1.00, 1.00 ),
147 (104, "Vacancy", "Vac", ( 0.5, 0.5, 0.5, 1.0), 1.00, 1.00, 1.00),
148 (105, "Default", "Default", ( 1.0, 1.0, 1.0, 1.0), 1.00, 1.00, 1.00),
149 (106, "Stick", "Stick", ( 0.5, 0.5, 0.5, 1.0), 1.00, 1.00, 1.00),
152 # This list here contains all data of the elements and will be used during
153 # runtime. It is a list of classes.
154 # During executing Atomic Blender, the list will be initialized with the fixed
155 # data from above via the class structure below (CLASS_atom_pdb_Elements). We
156 # have then one fixed list (above), which will never be changed, and a list of
157 # classes with same data. The latter can be modified via loading a separate
158 # custom data file.
159 ATOM_CLUSTER_ELEMENTS = []
160 ATOM_CLUSTER_ALL_ATOMS = []
162 # This is the class, which stores the properties for one element.
163 class CLASS_atom_cluster_Elements(object):
164 __slots__ = ('number', 'name', 'short_name', 'color', 'radii', 'radii_ionic')
165 def __init__(self, number, name, short_name, color, radii, radii_ionic):
166 self.number = number
167 self.name = name
168 self.short_name = short_name
169 self.color = color
170 self.radii = radii
171 self.radii_ionic = radii_ionic
173 # This is the class, which stores the properties of one atom.
174 class CLASS_atom_cluster_atom(object):
175 __slots__ = ('location')
176 def __init__(self, location):
177 self.location = location
179 # -----------------------------------------------------------------------------
180 # Read atom data
182 def DEF_atom_read_atom_data():
184 del ATOM_CLUSTER_ELEMENTS[:]
186 for item in ATOM_CLUSTER_ELEMENTS_DEFAULT:
188 # All three radii into a list
189 radii = [item[4],item[5],item[6]]
190 # The handling of the ionic radii will be done later. So far, it is an
191 # empty list.
192 radii_ionic = []
194 li = CLASS_atom_cluster_Elements(item[0],item[1],item[2],item[3],
195 radii,radii_ionic)
196 ATOM_CLUSTER_ELEMENTS.append(li)
199 # -----------------------------------------------------------------------------
200 # Routines for shapes
202 def vec_in_sphere(atom_pos,size, skin):
204 regular = True
205 inner = True
207 if atom_pos.length > size/2.0:
208 regular = False
210 if atom_pos.length < (size/2.0)*(1-skin):
211 inner = False
213 return (regular, inner)
216 def vec_in_parabole(atom_pos, height, diameter):
218 regular = True
219 inner = True
221 px = atom_pos[0]
222 py = atom_pos[1]
223 pz = atom_pos[2] + height/2.0
225 a = diameter / sqrt(4 * height)
228 if pz < 0.0:
229 return (False, False)
230 if px == 0.0 and py == 0.0:
231 return (True, True)
233 if py == 0.0:
234 y = 0.0
235 x = a * a * pz / px
236 z = x * x / (a * a)
237 else:
238 y = pz * py * a * a / (px*px + py*py)
239 x = y * px / py
240 z = (x*x + y*y) / (a * a)
242 if( atom_pos.length > sqrt(x*x+y*y+z*z) ):
243 regular = False
245 return (regular, inner)
248 def vec_in_pyramide_square(atom_pos, size, skin):
251 Please, if possible leave all this! The code documents the
252 mathemetical way of cutting a pyramide with square base.
254 P1 = Vector((-size/2, 0.0, -size/4))
255 P2 = Vector((0.0, -size/2, -size/4))
256 P4 = Vector((size/2, 0.0, -size/4))
257 P5 = Vector((0.0, size/2, -size/4))
258 P6 = Vector((0.0, 0.0, size/4))
260 # First face
261 v11 = P1 - P2
262 v12 = P1 - P6
263 n1 = v11.cross(v12)
264 g1 = -n1 * P1
266 # Second face
267 v21 = P6 - P4
268 v22 = P6 - P5
269 n2 = v21.cross(v22)
270 g2 = -n2 * P6
272 # Third face
273 v31 = P1 - P5
274 v32 = P1 - P6
275 n3 = v32.cross(v31)
276 g3 = -n3 * P1
278 # Forth face
279 v41 = P6 - P2
280 v42 = P2 - P4
281 n4 = v41.cross(v42)
282 g4 = -n4 * P2
284 # Fith face, base
285 v51 = P2 - P1
286 v52 = P2 - P4
287 n5 = v51.cross(v52)
288 g5 = -n5 * P2
291 # A much faster way for calculation:
292 size2 = size * size
293 size3 = size2 * size
294 n1 = Vector((-1/4, -1/4, 1/4)) * size2
295 g1 = -1/16 * size3
296 n2 = Vector(( 1/4, 1/4, 1/4)) * size2
297 g2 = g1
298 n3 = Vector((-1/4, 1/4, 1/4)) * size2
299 g3 = g1
300 n4 = Vector(( 1/4, -1/4, 1/4)) * size2
301 g4 = g1
302 n5 = Vector(( 0.0, 0.0, -1/2)) * size2
303 g5 = -1/8 * size3
305 distance_plane_1 = abs((n1 @ atom_pos - g1)/n1.length)
306 on_plane_1 = (atom_pos - n1 * (distance_plane_1/n1.length)).length
307 distance_plane_2 = abs((n2 @ atom_pos - g2)/n2.length)
308 on_plane_2 = (atom_pos - n2 * (distance_plane_2/n2.length)).length
309 distance_plane_3 = abs((n3 @ atom_pos - g3)/n3.length)
310 on_plane_3 = (atom_pos - n3 * (distance_plane_3/n3.length)).length
311 distance_plane_4 = abs((n4 @ atom_pos - g4)/n4.length)
312 on_plane_4 = (atom_pos - n4 * (distance_plane_4/n4.length)).length
313 distance_plane_5 = abs((n5 @ atom_pos - g5)/n5.length)
314 on_plane_5 = (atom_pos - n5 * (distance_plane_5/n5.length)).length
316 regular = True
317 inner = True
318 if(atom_pos.length > on_plane_1):
319 regular = False
320 if(atom_pos.length > on_plane_2):
321 regular = False
322 if(atom_pos.length > on_plane_3):
323 regular = False
324 if(atom_pos.length > on_plane_4):
325 regular = False
326 if(atom_pos.length > on_plane_5):
327 regular = False
329 if skin == 1.0:
330 return (regular, inner)
332 size = size * (1.0 - skin)
334 size2 = size * size
335 size3 = size2 * size
336 n1 = Vector((-1/4, -1/4, 1/4)) * size2
337 g1 = -1/16 * size3
338 n2 = Vector(( 1/4, 1/4, 1/4)) * size2
339 g2 = g1
340 n3 = Vector((-1/4, 1/4, 1/4)) * size2
341 g3 = g1
342 n4 = Vector(( 1/4, -1/4, 1/4)) * size2
343 g4 = g1
344 n5 = Vector(( 0.0, 0.0, -1/2)) * size2
345 g5 = -1/8 * size3
347 distance_plane_1 = abs((n1 @ atom_pos - g1)/n1.length)
348 on_plane_1 = (atom_pos - n1 * (distance_plane_1/n1.length)).length
349 distance_plane_2 = abs((n2 @ atom_pos - g2)/n2.length)
350 on_plane_2 = (atom_pos - n2 * (distance_plane_2/n2.length)).length
351 distance_plane_3 = abs((n3 @ atom_pos - g3)/n3.length)
352 on_plane_3 = (atom_pos - n3 * (distance_plane_3/n3.length)).length
353 distance_plane_4 = abs((n4 @ atom_pos - g4)/n4.length)
354 on_plane_4 = (atom_pos - n4 * (distance_plane_4/n4.length)).length
355 distance_plane_5 = abs((n5 @ atom_pos - g5)/n5.length)
356 on_plane_5 = (atom_pos - n5 * (distance_plane_5/n5.length)).length
358 inner = False
359 if(atom_pos.length > on_plane_1):
360 inner = True
361 if(atom_pos.length > on_plane_2):
362 inner = True
363 if(atom_pos.length > on_plane_3):
364 inner = True
365 if(atom_pos.length > on_plane_4):
366 inner = True
367 if(atom_pos.length > on_plane_5):
368 inner = True
370 return (regular, inner)
373 def vec_in_pyramide_hex_abc(atom_pos, size, skin):
375 a = size/2.0
376 #c = size/2.0*cos((30/360)*2.0*pi)
377 c = size * 0.4330127020
378 #s = size/2.0*sin((30/360)*2.0*pi)
379 s = size * 0.25
380 #h = 2.0 * (sqrt(6.0)/3.0) * c
381 h = 1.632993162 * c
384 Please, if possible leave all this! The code documents the
385 mathemetical way of cutting a tetraeder.
387 P1 = Vector((0.0, a, 0.0))
388 P2 = Vector(( -c, -s, 0.0))
389 P3 = Vector(( c, -s, 0.0))
390 P4 = Vector((0.0, 0.0, h))
391 C = (P1+P2+P3+P4)/4.0
392 P1 = P1 - C
393 P2 = P2 - C
394 P3 = P3 - C
395 P4 = P4 - C
397 # First face
398 v11 = P1 - P2
399 v12 = P1 - P4
400 n1 = v11.cross(v12)
401 g1 = -n1 * P1
403 # Second face
404 v21 = P2 - P3
405 v22 = P2 - P4
406 n2 = v21.cross(v22)
407 g2 = -n2 * P2
409 # Third face
410 v31 = P3 - P1
411 v32 = P3 - P4
412 n3 = v31.cross(v32)
413 g3 = -n3 * P3
415 # Forth face
416 v41 = P2 - P1
417 v42 = P2 - P3
418 n4 = v41.cross(v42)
419 g4 = -n4 * P1
422 n1 = Vector(( -h*(a+s), c*h, c*a ))
423 g1 = -1/2*c*(a*h+s*h)
424 n2 = Vector(( 0, -2*c*h, 2*c*s ))
425 g2 = -1/2*c*(a*h+s*h)
426 n3 = Vector(( h*(a+s), c*h, a*c ))
427 g3 = -1/2*c*(a*h+s*h)
428 n4 = Vector(( 0, 0, -2*c*(s+a) ))
429 g4 = -1/2*h*c*(s+a)
431 distance_plane_1 = abs((n1 @ atom_pos - g1)/n1.length)
432 on_plane_1 = (atom_pos - n1 * (distance_plane_1/n1.length)).length
433 distance_plane_2 = abs((n2 @ atom_pos - g2)/n2.length)
434 on_plane_2 = (atom_pos - n2 * (distance_plane_2/n2.length)).length
435 distance_plane_3 = abs((n3 @ atom_pos - g3)/n3.length)
436 on_plane_3 = (atom_pos - n3 * (distance_plane_3/n3.length)).length
437 distance_plane_4 = abs((n4 @ atom_pos - g4)/n4.length)
438 on_plane_4 = (atom_pos - n4 * (distance_plane_4/n4.length)).length
440 regular = True
441 inner = True
442 if(atom_pos.length > on_plane_1):
443 regular = False
444 if(atom_pos.length > on_plane_2):
445 regular = False
446 if(atom_pos.length > on_plane_3):
447 regular = False
448 if(atom_pos.length > on_plane_4):
449 regular = False
451 if skin == 1.0:
452 return (regular, inner)
454 size = size * (1.0 - skin)
456 a = size/2.0
457 #c = size/2.0*cos((30/360)*2.0*pi)
458 c= size * 0.4330127020
459 #s = size/2.0*sin((30/360)*2.0*pi)
460 s = size * 0.25
461 #h = 2.0 * (sqrt(6.0)/3.0) * c
462 h = 1.632993162 * c
464 n1 = Vector(( -h*(a+s), c*h, c*a ))
465 g1 = -1/2*c*(a*h+s*h)
466 n2 = Vector(( 0, -2*c*h, 2*c*s ))
467 g2 = -1/2*c*(a*h+s*h)
468 n3 = Vector(( h*(a+s), c*h, a*c ))
469 g3 = -1/2*c*(a*h+s*h)
470 n4 = Vector(( 0, 0, -2*c*(s+a) ))
471 g4 = -1/2*h*c*(s+a)
473 distance_plane_1 = abs((n1 @ atom_pos - g1)/n1.length)
474 on_plane_1 = (atom_pos - n1 * (distance_plane_1/n1.length)).length
475 distance_plane_2 = abs((n2 @ atom_pos - g2)/n2.length)
476 on_plane_2 = (atom_pos - n2 * (distance_plane_2/n2.length)).length
477 distance_plane_3 = abs((n3 @ atom_pos - g3)/n3.length)
478 on_plane_3 = (atom_pos - n3 * (distance_plane_3/n3.length)).length
479 distance_plane_4 = abs((n4 @ atom_pos - g4)/n4.length)
480 on_plane_4 = (atom_pos - n4 * (distance_plane_4/n4.length)).length
482 inner = False
483 if(atom_pos.length > on_plane_1):
484 inner = True
485 if(atom_pos.length > on_plane_2):
486 inner = True
487 if(atom_pos.length > on_plane_3):
488 inner = True
489 if(atom_pos.length > on_plane_4):
490 inner = True
492 return (regular, inner)
496 def vec_in_octahedron(atom_pos,size, skin):
498 regular = True
499 inner = True
502 Please, if possible leave all this! The code documents the
503 mathemetical way of cutting an octahedron.
505 P1 = Vector((-size/2, 0.0, 0.0))
506 P2 = Vector((0.0, -size/2, 0.0))
507 P3 = Vector((0.0, 0.0, -size/2))
508 P4 = Vector((size/2, 0.0, 0.0))
509 P5 = Vector((0.0, size/2, 0.0))
510 P6 = Vector((0.0, 0.0, size/2))
512 # First face
513 v11 = P2 - P1
514 v12 = P2 - P3
515 n1 = v11.cross(v12)
516 g1 = -n1 * P2
518 # Second face
519 v21 = P1 - P5
520 v22 = P1 - P3
521 n2 = v21.cross(v22)
522 g2 = -n2 * P1
524 # Third face
525 v31 = P1 - P2
526 v32 = P1 - P6
527 n3 = v31.cross(v32)
528 g3 = -n3 * P1
530 # Forth face
531 v41 = P6 - P2
532 v42 = P2 - P4
533 n4 = v41.cross(v42)
534 g4 = -n4 * P2
536 # Fith face
537 v51 = P2 - P3
538 v52 = P2 - P4
539 n5 = v51.cross(v52)
540 g5 = -n5 * P2
542 # Six face
543 v61 = P6 - P4
544 v62 = P6 - P5
545 n6 = v61.cross(v62)
546 g6 = -n6 * P6
548 # Seventh face
549 v71 = P5 - P4
550 v72 = P5 - P3
551 n7 = v71.cross(v72)
552 g7 = -n7 * P5
554 # Eigth face
555 v81 = P1 - P5
556 v82 = P1 - P6
557 n8 = v82.cross(v81)
558 g8 = -n8 * P1
561 # A much faster way for calculation:
562 size2 = size * size
563 size3 = size2 * size
564 n1 = Vector((-1/4, -1/4, -1/4)) * size2
565 g1 = -1/8 * size3
566 n2 = Vector((-1/4, 1/4, -1/4)) * size2
567 g2 = g1
568 n3 = Vector((-1/4, -1/4, 1/4)) * size2
569 g3 = g1
570 n4 = Vector(( 1/4, -1/4, 1/4)) * size2
571 g4 = g1
572 n5 = Vector(( 1/4, -1/4, -1/4)) * size2
573 g5 = g1
574 n6 = Vector(( 1/4, 1/4, 1/4)) * size2
575 g6 = g1
576 n7 = Vector(( 1/4, 1/4, -1/4)) * size2
577 g7 = g1
578 n8 = Vector((-1/4, 1/4, 1/4)) * size2
579 g8 = g1
581 distance_plane_1 = abs((n1 @ atom_pos - g1)/n1.length)
582 on_plane_1 = (atom_pos - n1 * (distance_plane_1/n1.length)).length
583 distance_plane_2 = abs((n2 @ atom_pos - g2)/n2.length)
584 on_plane_2 = (atom_pos - n2 * (distance_plane_2/n2.length)).length
585 distance_plane_3 = abs((n3 @ atom_pos - g3)/n3.length)
586 on_plane_3 = (atom_pos - n3 * (distance_plane_3/n3.length)).length
587 distance_plane_4 = abs((n4 @ atom_pos - g4)/n4.length)
588 on_plane_4 = (atom_pos - n4 * (distance_plane_4/n4.length)).length
589 distance_plane_5 = abs((n5 @ atom_pos - g5)/n5.length)
590 on_plane_5 = (atom_pos - n5 * (distance_plane_5/n5.length)).length
591 distance_plane_6 = abs((n6 @ atom_pos - g6)/n6.length)
592 on_plane_6 = (atom_pos - n6 * (distance_plane_6/n6.length)).length
593 distance_plane_7 = abs((n7 @ atom_pos - g7)/n7.length)
594 on_plane_7 = (atom_pos - n7 * (distance_plane_7/n7.length)).length
595 distance_plane_8 = abs((n8 @ atom_pos - g8)/n8.length)
596 on_plane_8 = (atom_pos - n8 * (distance_plane_8/n8.length)).length
598 if(atom_pos.length > on_plane_1):
599 regular = False
600 if(atom_pos.length > on_plane_2):
601 regular = False
602 if(atom_pos.length > on_plane_3):
603 regular = False
604 if(atom_pos.length > on_plane_4):
605 regular = False
606 if(atom_pos.length > on_plane_5):
607 regular = False
608 if(atom_pos.length > on_plane_6):
609 regular = False
610 if(atom_pos.length > on_plane_7):
611 regular = False
612 if(atom_pos.length > on_plane_8):
613 regular = False
615 if skin == 1.0:
616 return (regular, inner)
618 size = size * (1.0 - skin)
620 size2 = size * size
621 size3 = size2 * size
622 n1 = Vector((-1/4, -1/4, -1/4)) * size2
623 g1 = -1/8 * size3
624 n2 = Vector((-1/4, 1/4, -1/4)) * size2
625 g2 = g1
626 n3 = Vector((-1/4, -1/4, 1/4)) * size2
627 g3 = g1
628 n4 = Vector(( 1/4, -1/4, 1/4)) * size2
629 g4 = g1
630 n5 = Vector(( 1/4, -1/4, -1/4)) * size2
631 g5 = g1
632 n6 = Vector(( 1/4, 1/4, 1/4)) * size2
633 g6 = g1
634 n7 = Vector(( 1/4, 1/4, -1/4)) * size2
635 g7 = g1
636 n8 = Vector((-1/4, 1/4, 1/4)) * size2
637 g8 = g1
639 distance_plane_1 = abs((n1 @ atom_pos - g1)/n1.length)
640 on_plane_1 = (atom_pos - n1 * (distance_plane_1/n1.length)).length
641 distance_plane_2 = abs((n2 @ atom_pos - g2)/n2.length)
642 on_plane_2 = (atom_pos - n2 * (distance_plane_2/n2.length)).length
643 distance_plane_3 = abs((n3 @ atom_pos - g3)/n3.length)
644 on_plane_3 = (atom_pos - n3 * (distance_plane_3/n3.length)).length
645 distance_plane_4 = abs((n4 @ atom_pos - g4)/n4.length)
646 on_plane_4 = (atom_pos - n4 * (distance_plane_4/n4.length)).length
647 distance_plane_5 = abs((n5 @ atom_pos - g5)/n5.length)
648 on_plane_5 = (atom_pos - n5 * (distance_plane_5/n5.length)).length
649 distance_plane_6 = abs((n6 @ atom_pos - g6)/n6.length)
650 on_plane_6 = (atom_pos - n6 * (distance_plane_6/n6.length)).length
651 distance_plane_7 = abs((n7 @ atom_pos - g7)/n7.length)
652 on_plane_7 = (atom_pos - n7 * (distance_plane_7/n7.length)).length
653 distance_plane_8 = abs((n8 @ atom_pos - g8)/n8.length)
654 on_plane_8 = (atom_pos - n8 * (distance_plane_8/n8.length)).length
656 inner = False
657 if(atom_pos.length > on_plane_1):
658 inner = True
659 if(atom_pos.length > on_plane_2):
660 inner = True
661 if(atom_pos.length > on_plane_3):
662 inner = True
663 if(atom_pos.length > on_plane_4):
664 inner = True
665 if(atom_pos.length > on_plane_5):
666 inner = True
667 if(atom_pos.length > on_plane_6):
668 inner = True
669 if(atom_pos.length > on_plane_7):
670 inner = True
671 if(atom_pos.length > on_plane_8):
672 inner = True
674 return (regular, inner)
677 def vec_in_truncated_octahedron(atom_pos,size, skin):
679 regular = True
680 inner = True
682 # The normal octahedron
683 size2 = size * size
684 size3 = size2 * size
685 n1 = Vector((-1/4, -1/4, -1/4)) * size2
686 g1 = -1/8 * size3
687 n2 = Vector((-1/4, 1/4, -1/4)) * size2
688 g2 = g1
689 n3 = Vector((-1/4, -1/4, 1/4)) * size2
690 g3 = g1
691 n4 = Vector(( 1/4, -1/4, 1/4)) * size2
692 g4 = g1
693 n5 = Vector(( 1/4, -1/4, -1/4)) * size2
694 g5 = g1
695 n6 = Vector(( 1/4, 1/4, 1/4)) * size2
696 g6 = g1
697 n7 = Vector(( 1/4, 1/4, -1/4)) * size2
698 g7 = g1
699 n8 = Vector((-1/4, 1/4, 1/4)) * size2
700 g8 = g1
702 distance_plane_1 = abs((n1 @ atom_pos - g1)/n1.length)
703 on_plane_1 = (atom_pos - n1 * (distance_plane_1/n1.length)).length
704 distance_plane_2 = abs((n2 @ atom_pos - g2)/n2.length)
705 on_plane_2 = (atom_pos - n2 * (distance_plane_2/n2.length)).length
706 distance_plane_3 = abs((n3 @ atom_pos - g3)/n3.length)
707 on_plane_3 = (atom_pos - n3 * (distance_plane_3/n3.length)).length
708 distance_plane_4 = abs((n4 @ atom_pos - g4)/n4.length)
709 on_plane_4 = (atom_pos - n4 * (distance_plane_4/n4.length)).length
710 distance_plane_5 = abs((n5 @ atom_pos - g5)/n5.length)
711 on_plane_5 = (atom_pos - n5 * (distance_plane_5/n5.length)).length
712 distance_plane_6 = abs((n6 @ atom_pos - g6)/n6.length)
713 on_plane_6 = (atom_pos - n6 * (distance_plane_6/n6.length)).length
714 distance_plane_7 = abs((n7 @ atom_pos - g7)/n7.length)
715 on_plane_7 = (atom_pos - n7 * (distance_plane_7/n7.length)).length
716 distance_plane_8 = abs((n8 @ atom_pos - g8)/n8.length)
717 on_plane_8 = (atom_pos - n8 * (distance_plane_8/n8.length)).length
719 # Here are the 6 additional faces
720 # pp = (size/2.0) - (sqrt(2.0)/2.0) * ((size/sqrt(2.0))/3.0)
721 pp = size / 3.0
723 n_1 = Vector((1.0,0.0,0.0))
724 n_2 = Vector((-1.0,0.0,0.0))
725 n_3 = Vector((0.0,1.0,0.0))
726 n_4 = Vector((0.0,-1.0,0.0))
727 n_5 = Vector((0.0,0.0,1.0))
728 n_6 = Vector((0.0,0.0,-1.0))
730 distance_plane_1b = abs((n_1 @ atom_pos + pp)/n_1.length)
731 on_plane_1b = (atom_pos - n_1 * (distance_plane_1b/n_1.length)).length
732 distance_plane_2b = abs((n_2 @ atom_pos + pp)/n_2.length)
733 on_plane_2b = (atom_pos - n_2 * (distance_plane_2b/n_2.length)).length
734 distance_plane_3b = abs((n_3 @ atom_pos + pp)/n_3.length)
735 on_plane_3b = (atom_pos - n_3 * (distance_plane_3b/n_3.length)).length
736 distance_plane_4b = abs((n_4 @ atom_pos + pp)/n_4.length)
737 on_plane_4b = (atom_pos - n_4 * (distance_plane_4b/n_4.length)).length
738 distance_plane_5b = abs((n_5 @ atom_pos + pp)/n_5.length)
739 on_plane_5b = (atom_pos - n_5 * (distance_plane_5b/n_5.length)).length
740 distance_plane_6b = abs((n_6 @ atom_pos + pp)/n_6.length)
741 on_plane_6b = (atom_pos - n_6 * (distance_plane_6b/n_6.length)).length
743 if(atom_pos.length > on_plane_1):
744 regular = False
745 if(atom_pos.length > on_plane_2):
746 regular = False
747 if(atom_pos.length > on_plane_3):
748 regular = False
749 if(atom_pos.length > on_plane_4):
750 regular = False
751 if(atom_pos.length > on_plane_5):
752 regular = False
753 if(atom_pos.length > on_plane_6):
754 regular = False
755 if(atom_pos.length > on_plane_7):
756 regular = False
757 if(atom_pos.length > on_plane_8):
758 regular = False
759 if(atom_pos.length > on_plane_1b):
760 regular = False
761 if(atom_pos.length > on_plane_2b):
762 regular = False
763 if(atom_pos.length > on_plane_3b):
764 regular = False
765 if(atom_pos.length > on_plane_4b):
766 regular = False
767 if(atom_pos.length > on_plane_5b):
768 regular = False
769 if(atom_pos.length > on_plane_6b):
770 regular = False
772 if skin == 1.0:
773 return (regular, inner)
775 size = size * (1.0 - skin)
777 # The normal octahedron
778 size2 = size * size
779 size3 = size2 * size
780 n1 = Vector((-1/4, -1/4, -1/4)) * size2
781 g1 = -1/8 * size3
782 n2 = Vector((-1/4, 1/4, -1/4)) * size2
783 g2 = g1
784 n3 = Vector((-1/4, -1/4, 1/4)) * size2
785 g3 = g1
786 n4 = Vector(( 1/4, -1/4, 1/4)) * size2
787 g4 = g1
788 n5 = Vector(( 1/4, -1/4, -1/4)) * size2
789 g5 = g1
790 n6 = Vector(( 1/4, 1/4, 1/4)) * size2
791 g6 = g1
792 n7 = Vector(( 1/4, 1/4, -1/4)) * size2
793 g7 = g1
794 n8 = Vector((-1/4, 1/4, 1/4)) * size2
795 g8 = g1
797 distance_plane_1 = abs((n1 @ atom_pos - g1)/n1.length)
798 on_plane_1 = (atom_pos - n1 * (distance_plane_1/n1.length)).length
799 distance_plane_2 = abs((n2 @ atom_pos - g2)/n2.length)
800 on_plane_2 = (atom_pos - n2 * (distance_plane_2/n2.length)).length
801 distance_plane_3 = abs((n3 @ atom_pos - g3)/n3.length)
802 on_plane_3 = (atom_pos - n3 * (distance_plane_3/n3.length)).length
803 distance_plane_4 = abs((n4 @ atom_pos - g4)/n4.length)
804 on_plane_4 = (atom_pos - n4 * (distance_plane_4/n4.length)).length
805 distance_plane_5 = abs((n5 @ atom_pos - g5)/n5.length)
806 on_plane_5 = (atom_pos - n5 * (distance_plane_5/n5.length)).length
807 distance_plane_6 = abs((n6 @ atom_pos - g6)/n6.length)
808 on_plane_6 = (atom_pos - n6 * (distance_plane_6/n6.length)).length
809 distance_plane_7 = abs((n7 @ atom_pos - g7)/n7.length)
810 on_plane_7 = (atom_pos - n7 * (distance_plane_7/n7.length)).length
811 distance_plane_8 = abs((n8 @ atom_pos - g8)/n8.length)
812 on_plane_8 = (atom_pos - n8 * (distance_plane_8/n8.length)).length
814 # Here are the 6 additional faces
815 # pp = (size/2.0) - (sqrt(2.0)/2.0) * ((size/sqrt(2.0))/3.0)
816 pp = size / 3.0
818 n_1 = Vector((1.0,0.0,0.0))
819 n_2 = Vector((-1.0,0.0,0.0))
820 n_3 = Vector((0.0,1.0,0.0))
821 n_4 = Vector((0.0,-1.0,0.0))
822 n_5 = Vector((0.0,0.0,1.0))
823 n_6 = Vector((0.0,0.0,-1.0))
825 distance_plane_1b = abs((n_1 @ atom_pos + pp)/n_1.length)
826 on_plane_1b = (atom_pos - n_1 * (distance_plane_1b/n_1.length)).length
827 distance_plane_2b = abs((n_2 @ atom_pos + pp)/n_2.length)
828 on_plane_2b = (atom_pos - n_2 * (distance_plane_2b/n_2.length)).length
829 distance_plane_3b = abs((n_3 @ atom_pos + pp)/n_3.length)
830 on_plane_3b = (atom_pos - n_3 * (distance_plane_3b/n_3.length)).length
831 distance_plane_4b = abs((n_4 @ atom_pos + pp)/n_4.length)
832 on_plane_4b = (atom_pos - n_4 * (distance_plane_4b/n_4.length)).length
833 distance_plane_5b = abs((n_5 @ atom_pos + pp)/n_5.length)
834 on_plane_5b = (atom_pos - n_5 * (distance_plane_5b/n_5.length)).length
835 distance_plane_6b = abs((n_6 @ atom_pos + pp)/n_6.length)
836 on_plane_6b = (atom_pos - n_6 * (distance_plane_6b/n_6.length)).length
838 inner = False
840 if(atom_pos.length > on_plane_1):
841 inner = True
842 if(atom_pos.length > on_plane_2):
843 inner = True
844 if(atom_pos.length > on_plane_3):
845 inner = True
846 if(atom_pos.length > on_plane_4):
847 inner = True
848 if(atom_pos.length > on_plane_5):
849 inner = True
850 if(atom_pos.length > on_plane_6):
851 inner = True
852 if(atom_pos.length > on_plane_7):
853 inner = True
854 if(atom_pos.length > on_plane_8):
855 inner = True
856 if(atom_pos.length > on_plane_1b):
857 inner = True
858 if(atom_pos.length > on_plane_2b):
859 inner = True
860 if(atom_pos.length > on_plane_3b):
861 inner = True
862 if(atom_pos.length > on_plane_4b):
863 inner = True
864 if(atom_pos.length > on_plane_5b):
865 inner = True
866 if(atom_pos.length > on_plane_6b):
867 inner = True
869 return (regular, inner)
871 # -----------------------------------------------------------------------------
872 # Routines for lattices
874 def create_hexagonal_abcabc_lattice(ctype, size, skin, lattice):
876 atom_number_total = 0
877 atom_number_drawn = 0
878 y_displ = 0
879 z_displ = 0
882 e = (1/sqrt(2.0)) * lattice
883 f = sqrt(3.0/4.0) * e
884 df1 = (e/2.0) * tan((30.0/360.0)*2.0*pi)
885 df2 = (e/2.0) / cos((30.0/360.0)*2.0*pi)
886 g = sqrt(2.0/3.0) * e
889 e = 0.7071067810 * lattice
890 f = 0.8660254038 * e
891 df1 = 0.2886751348 * e
892 df2 = 0.5773502690 * e
893 g = 0.8164965810 * e
895 if ctype == "parabolid_abc":
896 # size = height, skin = diameter
897 number_x = int(skin/(2*e))+4
898 number_y = int(skin/(2*f))+4
899 number_z = int(size/(2*g))
900 else:
901 number_x = int(size/(2*e))+4
902 number_y = int(size/(2*f))+4
903 number_z = int(size/(2*g))+1+4
906 for k in range(-number_z,number_z+1):
907 for j in range(-number_y,number_y+1):
908 for i in range(-number_x,number_x+1):
909 atom = Vector((float(i)*e,float(j)*f,float(k)*g))
911 if y_displ == 1:
912 if z_displ == 1:
913 atom[0] += e/2.0
914 else:
915 atom[0] -= e/2.0
916 if z_displ == 1:
917 atom[0] -= e/2.0
918 atom[1] += df1
919 if z_displ == 2:
920 atom[0] += 0.0
921 atom[1] += df2
923 if ctype == "sphere_hex_abc":
924 message = vec_in_sphere(atom, size, skin)
925 elif ctype == "pyramide_hex_abc":
926 # size = height, skin = diameter
927 message = vec_in_pyramide_hex_abc(atom, size, skin)
928 elif ctype == "parabolid_abc":
929 message = vec_in_parabole(atom, size, skin)
931 if message[0] == True and message[1] == True:
932 atom_add = CLASS_atom_cluster_atom(atom)
933 ATOM_CLUSTER_ALL_ATOMS.append(atom_add)
934 atom_number_total += 1
935 atom_number_drawn += 1
936 if message[0] == True and message[1] == False:
937 atom_number_total += 1
939 if y_displ == 1:
940 y_displ = 0
941 else:
942 y_displ = 1
944 y_displ = 0
945 if z_displ == 0:
946 z_displ = 1
947 elif z_displ == 1:
948 z_displ = 2
949 else:
950 z_displ = 0
952 print("Atom positions calculated")
954 return (atom_number_total, atom_number_drawn)
957 def create_hexagonal_abab_lattice(ctype, size, skin, lattice):
959 atom_number_total = 0
960 atom_number_drawn = 0
961 y_displ = "even"
962 z_displ = "even"
965 e = (1/sqrt(2.0)) * lattice
966 f = sqrt(3.0/4.0) * e
967 df = (e/2.0) * tan((30.0/360.0)*2*pi)
968 g = sqrt(2.0/3.0) * e
971 e = 0.7071067814 * lattice
972 f = 0.8660254038 * e
973 df = 0.2886751348 * e
974 g = 0.8164965810 * e
977 if ctype == "parabolid_ab":
978 # size = height, skin = diameter
979 number_x = int(skin/(2*e))+4
980 number_y = int(skin/(2*f))+4
981 number_z = int(size/(2*g))
982 else:
983 number_x = int(size/(2*e))+4
984 number_y = int(size/(2*f))+4
985 number_z = int(size/(2*g))+1+4
988 for k in range(-number_z,number_z+1):
989 for j in range(-number_y,number_y+1):
990 for i in range(-number_x,number_x+1):
992 atom = Vector((float(i)*e,float(j)*f,float(k)*g))
994 if "odd" in y_displ:
995 if "odd" in z_displ:
996 atom[0] += e/2.0
997 else:
998 atom[0] -= e/2.0
999 if "odd" in z_displ:
1000 atom[0] -= e/2.0
1001 atom[1] += df
1003 if ctype == "sphere_hex_ab":
1004 message = vec_in_sphere(atom, size, skin)
1005 elif ctype == "parabolid_ab":
1006 # size = height, skin = diameter
1007 message = vec_in_parabole(atom, size, skin)
1009 if message[0] == True and message[1] == True:
1010 atom_add = CLASS_atom_cluster_atom(atom)
1011 ATOM_CLUSTER_ALL_ATOMS.append(atom_add)
1012 atom_number_total += 1
1013 atom_number_drawn += 1
1014 if message[0] == True and message[1] == False:
1015 atom_number_total += 1
1017 if "even" in y_displ:
1018 y_displ = "odd"
1019 else:
1020 y_displ = "even"
1022 y_displ = "even"
1023 if "even" in z_displ:
1024 z_displ = "odd"
1025 else:
1026 z_displ = "even"
1028 print("Atom positions calculated")
1030 return (atom_number_total, atom_number_drawn)
1033 def create_square_lattice(ctype, size, skin, lattice):
1035 atom_number_total = 0
1036 atom_number_drawn = 0
1038 if ctype == "parabolid_square":
1039 # size = height, skin = diameter
1040 number_k = int(size/(2.0*lattice))
1041 number_j = int(skin/(2.0*lattice)) + 5
1042 number_i = int(skin/(2.0*lattice)) + 5
1043 else:
1044 number_k = int(size/(2.0*lattice))
1045 number_j = int(size/(2.0*lattice))
1046 number_i = int(size/(2.0*lattice))
1049 for k in range(-number_k,number_k+1):
1050 for j in range(-number_j,number_j+1):
1051 for i in range(-number_i,number_i+1):
1053 atom = Vector((float(i),float(j),float(k))) * lattice
1055 if ctype == "sphere_square":
1056 message = vec_in_sphere(atom, size, skin)
1057 elif ctype == "pyramide_square":
1058 message = vec_in_pyramide_square(atom, size, skin)
1059 elif ctype == "parabolid_square":
1060 # size = height, skin = diameter
1061 message = vec_in_parabole(atom, size, skin)
1062 elif ctype == "octahedron":
1063 message = vec_in_octahedron(atom, size, skin)
1064 elif ctype == "truncated_octahedron":
1065 message = vec_in_truncated_octahedron(atom,size, skin)
1067 if message[0] == True and message[1] == True:
1068 atom_add = CLASS_atom_cluster_atom(atom)
1069 ATOM_CLUSTER_ALL_ATOMS.append(atom_add)
1070 atom_number_total += 1
1071 atom_number_drawn += 1
1072 if message[0] == True and message[1] == False:
1073 atom_number_total += 1
1075 print("Atom positions calculated")
1077 return (atom_number_total, atom_number_drawn)
1081 # -----------------------------------------------------------------------------
1082 # Routine for the icosahedron
1085 # Note that the icosahedron needs a special treatment since it requires a
1086 # non-common crystal lattice. The faces are (111) facets and the geometry
1087 # is five-fold. So far, a max size of 8217 atoms can be chosen.
1088 # More details about icosahedron shaped clusters can be found in:
1090 # 1. C. Mottet, G. Tréglia, B. Legrand, Surface Science 383 (1997) L719-L727
1091 # 2. C. R. Henry, Surface Science Reports 31 (1998) 231-325
1093 # The following code is a translation from an existing Fortran code into Python.
1094 # The Fortran code has been created by Christine Mottet and translated by me
1095 # (Clemens Barth).
1097 # Although a couple of code lines are non-typical for Python, it is best to
1098 # leave the code as is.
1100 # To do:
1102 # 1. Unlimited cluster size
1103 # 2. Skin effect
1105 def create_icosahedron(size, lattice):
1107 natot = int(1 + (10*size*size+15*size+11)*size/3)
1109 x = list(range(natot+1))
1110 y = list(range(natot+1))
1111 z = list(range(natot+1))
1113 xs = list(range(12+1))
1114 ys = list(range(12+1))
1115 zs = list(range(12+1))
1117 xa = [[[ [] for i in range(12+1)] for j in range(12+1)] for k in range(20+1)]
1118 ya = [[[ [] for i in range(12+1)] for j in range(12+1)] for k in range(20+1)]
1119 za = [[[ [] for i in range(12+1)] for j in range(12+1)] for k in range(20+1)]
1121 naret = [[ [] for i in range(12+1)] for j in range(12+1)]
1122 nfacet = [[[ [] for i in range(12+1)] for j in range(12+1)] for k in range(12+1)]
1124 rac2 = sqrt(2.0)
1125 rac5 = sqrt(5.0)
1126 tdef = (rac5+1.0)/2.0
1128 rapp = sqrt(2.0*(1.0-tdef/(tdef*tdef+1.0)))
1129 nats = 2 * (5*size*size+1)
1130 nat = 13
1131 epsi = 0.01
1133 x[1] = 0.0
1134 y[1] = 0.0
1135 z[1] = 0.0
1137 for i in range(2, 5+1):
1138 z[i] = 0.0
1139 y[i+4] = 0.0
1140 x[i+8] = 0.0
1142 for i in range(2, 3+1):
1143 x[i] = tdef
1144 x[i+2] = -tdef
1145 x[i+4] = 1.0
1146 x[i+6] = -1.0
1147 y[i+8] = tdef
1148 y[i+10] = -tdef
1150 for i in range(2, 4+1, 2):
1151 y[i] = 1.0
1152 y[i+1] = -1.0
1153 z[i+4] = tdef
1154 z[i+5] = -tdef
1155 z[i+8] = 1.0
1156 z[i+9] = -1.0
1158 xdef = rac2 / sqrt(tdef * tdef + 1)
1160 for i in range(2, 13+1):
1161 x[i] = x[i] * xdef / 2.0
1162 y[i] = y[i] * xdef / 2.0
1163 z[i] = z[i] * xdef / 2.0
1165 if size > 1:
1167 for n in range (2, size+1):
1168 ifacet = 0
1169 iaret = 0
1170 inatf = 0
1171 for i in range(1, 12+1):
1172 for j in range(1, 12+1):
1173 naret[i][j] = 0
1174 for k in range (1, 12+1):
1175 nfacet[i][j][k] = 0
1177 nl1 = 6
1178 nl2 = 8
1179 nl3 = 9
1180 k1 = 0
1181 k2 = 0
1182 k3 = 0
1183 k12 = 0
1184 for i in range(1, 12+1):
1185 nat += 1
1186 xs[i] = n * x[i+1]
1187 ys[i] = n * y[i+1]
1188 zs[i] = n * z[i+1]
1189 x[nat] = xs[i]
1190 y[nat] = ys[i]
1191 z[nat] = zs[i]
1192 k1 += 1
1194 for i in range(1, 12+1):
1195 for j in range(2, 12+1):
1196 if j <= i:
1197 continue
1199 xij = xs[j] - xs[i]
1200 yij = ys[j] - ys[i]
1201 zij = zs[j] - zs[i]
1202 xij2 = xij * xij
1203 yij2 = yij * yij
1204 zij2 = zij * zij
1205 dij2 = xij2 + yij2 + zij2
1206 dssn = n * rapp / rac2
1207 dssn2 = dssn * dssn
1208 diffij = abs(dij2-dssn2)
1209 if diffij >= epsi:
1210 continue
1212 for k in range(3, 12+1):
1213 if k <= j:
1214 continue
1216 xjk = xs[k] - xs[j]
1217 yjk = ys[k] - ys[j]
1218 zjk = zs[k] - zs[j]
1219 xjk2 = xjk * xjk
1220 yjk2 = yjk * yjk
1221 zjk2 = zjk * zjk
1222 djk2 = xjk2 + yjk2 + zjk2
1223 diffjk = abs(djk2-dssn2)
1224 if diffjk >= epsi:
1225 continue
1227 xik = xs[k] - xs[i]
1228 yik = ys[k] - ys[i]
1229 zik = zs[k] - zs[i]
1230 xik2 = xik * xik
1231 yik2 = yik * yik
1232 zik2 = zik * zik
1233 dik2 = xik2 + yik2 + zik2
1234 diffik = abs(dik2-dssn2)
1235 if diffik >= epsi:
1236 continue
1238 if nfacet[i][j][k] != 0:
1239 continue
1241 ifacet += 1
1242 nfacet[i][j][k] = ifacet
1244 if naret[i][j] == 0:
1245 iaret += 1
1246 naret[i][j] = iaret
1247 for l in range(1,n-1+1):
1248 nat += 1
1249 xa[i][j][l] = xs[i]+l*(xs[j]-xs[i]) / n
1250 ya[i][j][l] = ys[i]+l*(ys[j]-ys[i]) / n
1251 za[i][j][l] = zs[i]+l*(zs[j]-zs[i]) / n
1252 x[nat] = xa[i][j][l]
1253 y[nat] = ya[i][j][l]
1254 z[nat] = za[i][j][l]
1256 if naret[i][k] == 0:
1257 iaret += 1
1258 naret[i][k] = iaret
1259 for l in range(1, n-1+1):
1260 nat += 1
1261 xa[i][k][l] = xs[i]+l*(xs[k]-xs[i]) / n
1262 ya[i][k][l] = ys[i]+l*(ys[k]-ys[i]) / n
1263 za[i][k][l] = zs[i]+l*(zs[k]-zs[i]) / n
1264 x[nat] = xa[i][k][l]
1265 y[nat] = ya[i][k][l]
1266 z[nat] = za[i][k][l]
1268 if naret[j][k] == 0:
1269 iaret += 1
1270 naret[j][k] = iaret
1271 for l in range(1, n-1+1):
1272 nat += 1
1273 xa[j][k][l] = xs[j]+l*(xs[k]-xs[j]) / n
1274 ya[j][k][l] = ys[j]+l*(ys[k]-ys[j]) / n
1275 za[j][k][l] = zs[j]+l*(zs[k]-zs[j]) / n
1276 x[nat] = xa[j][k][l]
1277 y[nat] = ya[j][k][l]
1278 z[nat] = za[j][k][l]
1280 for l in range(2, n-1+1):
1281 for ll in range(1, l-1+1):
1282 xf = xa[i][j][l]+ll*(xa[i][k][l]-xa[i][j][l]) / l
1283 yf = ya[i][j][l]+ll*(ya[i][k][l]-ya[i][j][l]) / l
1284 zf = za[i][j][l]+ll*(za[i][k][l]-za[i][j][l]) / l
1285 nat += 1
1286 inatf += 1
1287 x[nat] = xf
1288 y[nat] = yf
1289 z[nat] = zf
1290 k3 += 1
1292 atom_number_total = 0
1293 atom_number_drawn = 0
1295 for i in range (1,natot+1):
1297 atom = Vector((x[i],y[i],z[i])) * lattice
1299 atom_add = CLASS_atom_cluster_atom(atom)
1300 ATOM_CLUSTER_ALL_ATOMS.append(atom_add)
1301 atom_number_total += 1
1302 atom_number_drawn += 1
1304 return (atom_number_total, atom_number_drawn)