-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathParseMol.py
executable file
·128 lines (100 loc) · 3.61 KB
/
ParseMol.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/usr/bin/python
from GeneratePolyhedronStl import Point
import sys
import math
class Bond:
def __init__(self, atom1, atom2, count):
self.atom1 = atom1
self.atom2 = atom2
self.count = count
def __str__(self):
return "({}, {}, {})".format(atom1, atom2, count)
def toScad(self, resolution, totalScale, radiusScale):
difference = self.atom2.pos - self.atom1.pos
# Compute rotation of cylinder from one pointed upward to one pointed at
# DIFFERENCE to be [0, b, c].
# Taken from bit.ly/1ziiWyc
length = difference.norm()
b = math.degrees(math.acos(difference.z/length))
if difference.x == 0:
c = 90
elif difference.x > 0:
c = math.degrees(math.atan(difference.y/difference.x))
else:
c = math.degrees(math.atan(difference.y/difference.x)) + 180
radius = radiusScale * self.count
return (("translate ([{x}, {y}, {z}])"
"{{rotate ([0, {b}, {c}])"
"{{cylinder (h={length}, r={radius});}}}}")
.format(x=self.atom1.pos.x*totalScale,
y=self.atom1.pos.y*totalScale,
z=self.atom1.pos.z*totalScale,
b=b, c=c,
length=length*totalScale,
radius=radius))
class Atom:
def __init__(self, pos, element):
self.pos = pos
self.element = element
def __str__(self):
return "{}, position: {}".format(self.element, self.pos)
def toScad(self, resolution, totalScale, size):
"""Returns SCAD representation of atom."""
scaledPosition = self.pos.mult(totalScale)
return (("translate ([{x}, {y}, {z}])"
"{{sphere (r={radius}, $fn={resolution});}}")
.format(x=scaledPosition.x, y=scaledPosition.y,
z=scaledPosition.z, radius=size,
resolution=resolution))
class Molecule:
def __init__(self, atoms, bonds, name):
self.atoms = atoms
self.bonds = bonds
self.name = name
def __str__(self):
return ("{}: Atoms ({}), Bonds ({})"
.format(self.name, self.atoms, self.bonds))
# def toScad(self):
def parseCountLine(line):
words = line.split()
atoms = int(words[0])
bonds = int(words[1])
return (atoms, bonds)
def parseAtomLine(line):
words = line.split()
assert (words[3].isalpha())
return Atom(Point(float(words[0]),
float(words[1]),
float(words[2])),
words[3])
def parseBondLine(line, atoms):
words = line.split()
return Bond(atoms[int(words[0])-1],
atoms[int(words[1])-1],
int(words[2]))
def parseFile(f):
name = f.readline()
atoms = []
bonds = []
line = ""
while (not line.endswith("V2000")):
line = f.readline().strip("\n\r")
atomCount, bondCount = parseCountLine(line)
for i in range(atomCount):
atoms.append(parseAtomLine(f.readline()))
for i in range(bondCount):
bonds.append(parseBondLine(f.readline(), atoms))
assert (f.readline().strip("\n\r") == "M END")
return Molecule(atoms, bonds, name)
if __name__=="__main__":
filename = sys.argv[1]
scale = 2
resolution = 10
with open(filename, "r") as file:
mol = parseFile(file)
print "union () {"
for atom in mol.atoms:
print atom.toScad(resolution, scale, 1)
for bond in mol.bonds:
print bond.toScad(resolution, scale, 0.3)
print "}"