line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Chemistry::File::VRML; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
$VERSION = '0.10'; |
4
|
|
|
|
|
|
|
|
5
|
1
|
|
|
1
|
|
20743
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
32
|
|
6
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
25
|
|
7
|
1
|
|
|
1
|
|
4
|
use base qw(Chemistry::File); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
1038
|
|
8
|
1
|
|
|
1
|
|
22114
|
use Chemistry::Mol; |
|
1
|
|
|
|
|
49821
|
|
|
1
|
|
|
|
|
65
|
|
9
|
1
|
|
|
1
|
|
1018
|
use POSIX qw(acos); |
|
1
|
|
|
|
|
8408
|
|
|
1
|
|
|
|
|
7
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
Chemistry::Mol->register_format(vrml => __PACKAGE__); |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
my %OPTS = ( |
14
|
|
|
|
|
|
|
center => 'centerAtoms', |
15
|
|
|
|
|
|
|
color => 'setColor', |
16
|
|
|
|
|
|
|
style => 'setStyle', |
17
|
|
|
|
|
|
|
stick_radius => 'setStickRadius', |
18
|
|
|
|
|
|
|
ball_radius => 'setBallRadius', |
19
|
|
|
|
|
|
|
compression => 'setCompression', |
20
|
|
|
|
|
|
|
); |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub write_mol { |
23
|
1
|
|
|
1
|
1
|
3614
|
my ($self, $fh, $mol, %opts) = @_; |
24
|
1
|
|
|
|
|
9
|
my $vrml = Chemistry::File::VRML::PDB2VRML->new($fh); |
25
|
1
|
|
|
|
|
4
|
$vrml->add_mol($mol); |
26
|
1
|
|
|
|
|
7
|
while (my ($key, $val) = each %opts) { |
27
|
5
|
100
|
|
|
|
22
|
if (my $method = $OPTS{$key}) { |
28
|
3
|
|
|
|
|
11
|
$vrml->$method($val); |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
} |
31
|
1
|
|
|
|
|
5
|
$vrml->printVRML; |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
package Chemistry::File::VRML::PDB2VRML; |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# Defaults variables |
37
|
|
|
|
|
|
|
my $Compression = 0; |
38
|
|
|
|
|
|
|
my $Style = 'Wireframe'; # default display style |
39
|
|
|
|
|
|
|
my $Color = 'byAtom'; # default color |
40
|
|
|
|
|
|
|
my $PI = 3.14159265; |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
my $RadiusBNS = 0.2; |
43
|
|
|
|
|
|
|
my $RadiusStick = 0.15; |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
# Some global tables |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
# color indizes per atom type |
48
|
|
|
|
|
|
|
my %AtomColors = qw( |
49
|
|
|
|
|
|
|
'' 5 H 3 HE 5 LI 5 BE 5 B 1 C 4 N 1 O 2 F 7 NE 5 NA 5 |
50
|
|
|
|
|
|
|
MG 5 AL 5 SI 5 P 6 S 0 CL 7 AR 5 K 5 CA 5 SC 5 TI 5 V 5 |
51
|
|
|
|
|
|
|
CR 5 MN 5 FE 5 CO 5 NI 5 CU 5 ZN 5 GA 5 GE 5 AS 5 SE 5 BR 7 |
52
|
|
|
|
|
|
|
KR 5 RB 5 SR 5 Y 5 ZR 5 NB 5 MO 5 TC 5 RU 5 RH 5 PD 5 AG 5 |
53
|
|
|
|
|
|
|
CD 5 IN 5 SN 5 SB 5 TE 5 I 7 XE 5 CS 5 BA 5 LA 5 CE 5 PR 5 |
54
|
|
|
|
|
|
|
ND 5 PM 5 SM 5 EU 5 GD 5 TB 5 DY 5 HO 5 ER 5 TM 5 YB 5 LU 5 |
55
|
|
|
|
|
|
|
HF 5 TA 5 W 5 RE 5 OS 5 IR 5 PT 5 AU 5 HG 5 TL 5 PB 5 BI 5 |
56
|
|
|
|
|
|
|
PO 5 AT 7 RN 5 FR 5 RA 5 AC 5 TH 5 PA 5 U 5 NP 5 PU 5 AM 5 |
57
|
|
|
|
|
|
|
CM 5 BK 5 CF 5 XX 5 FM 5 MD 5 NO 5 LW 5 |
58
|
|
|
|
|
|
|
); |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# VDW radius per atom type |
61
|
|
|
|
|
|
|
my %VDWRadius = qw( |
62
|
|
|
|
|
|
|
'' 1.00 H 1.08 HE 1.00 LI 1.00 BE 1.00 B 1.00 C 1.54 N 1.48 |
63
|
|
|
|
|
|
|
O 1.36 F 1.30 NE 1.00 NA 2.30 MG 1.00 AL 2.86 SI 2.10 P 1.75 |
64
|
|
|
|
|
|
|
S 1.70 CL 1.65 AR 1 K 1 CA 2.75 SC 1 TI 1 V 1 |
65
|
|
|
|
|
|
|
CR 1 MN 1 FE 2.27 CO 1 NI 1 CU 1.4 ZN 1.4 GA 1 |
66
|
|
|
|
|
|
|
GE 1 AS 1 SE 1 BR 1.8 KR 1 RB 1 SR 1 Y 1 |
67
|
|
|
|
|
|
|
ZR 1 NB 1 MO 1 TC 1 RU 1 RH 1 PD 1 AG 1 |
68
|
|
|
|
|
|
|
CD 1 IN 1 SN 1 SB 1 TE 1 I 1 XE 1 CS 1 |
69
|
|
|
|
|
|
|
BA 1 LA 1 CE 1 PR 1 ND 1 PM 1 SM 1 EU 1 |
70
|
|
|
|
|
|
|
GD 1 TB 1 DY 1 HO 1 ER 1 TM 1 YB 1 LU 1 |
71
|
|
|
|
|
|
|
HF 1 TA 1 W 1 RE 1 OS 1 IR 1 PT 1 AU 1 |
72
|
|
|
|
|
|
|
HG 1 TL 1 PB 1 BI 1 PO 1 AT 1 RN 1 FR 1 |
73
|
|
|
|
|
|
|
RA 1 AC 1 TH 1 PA 1 U 1 NP 1 PU 1 AM 1 |
74
|
|
|
|
|
|
|
CM 1 BK 1 CF 1 XX 1 FM 1 MD 1 NO 1 LW 1 |
75
|
|
|
|
|
|
|
); |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# atom radius per atom type |
78
|
|
|
|
|
|
|
my %AtomRadius = qw( |
79
|
|
|
|
|
|
|
'' 0.00 H 0.37 HE 0.70 LI 1.23 BE 0.89 B 0.80 C 0.77 N 0.74 |
80
|
|
|
|
|
|
|
O 0.74 F 0.72 NE 0.70 NA 1.57 MG 1.36 AL 1.25 SI 1.17 P 1.10 |
81
|
|
|
|
|
|
|
S 1.04 CL 0.99 AR 0.70 K 2.03 CA 1.74 SC 1.44 TI 1.32 V 1.22 |
82
|
|
|
|
|
|
|
CR 1.17 MN 1.16 FE 1.16 CO 1.15 NI 1.17 CU 1.25 ZN 1.25 GA 1.22 |
83
|
|
|
|
|
|
|
GE 1.21 AS 1.17 SE 0.70 BR 1.24 KR 1.91 RB 1.62 SR 1.45 Y 1.34 |
84
|
|
|
|
|
|
|
ZR 1.29 NB 1.29 MO 1.24 TC 1.25 RU 1.28 RH 1.34 PD 1.41 AG 1.50 |
85
|
|
|
|
|
|
|
CD 1.40 IN 1.41 SN 1.37 SB 1.33 TE 0.70 I 1.33 XE 1.98 CS 1.69 |
86
|
|
|
|
|
|
|
BA 1.69 LA 1.69 CE 1.69 PR 1.69 ND 1.69 PM 1.69 SM 1.69 EU 1.69 |
87
|
|
|
|
|
|
|
GD 1.69 TB 1.69 DY 1.69 HO 1.69 ER 1.69 TM 1.69 YB 1.69 LU 1.69 |
88
|
|
|
|
|
|
|
HF 1.44 TA 1.34 W 1.30 RE 1.28 OS 1.26 IR 1.29 PT 1.34 AU 1.44 |
89
|
|
|
|
|
|
|
HG 1.55 TL 1.54 PB 1.52 BI 1.52 PO 1.40 AT 0.70 RN 2.40 FR 2.00 |
90
|
|
|
|
|
|
|
RA 1.90 AC 1.90 TH 1.90 PA 1.90 U 1.90 NP 0.70 PU 0.26 AM 1.00 |
91
|
|
|
|
|
|
|
CM 1.00 BK 1.00 CF 1.00 XX 1.00 FM 1.00 MD 1.00 NO 1.00 LW 1.00 |
92
|
|
|
|
|
|
|
); |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
# S N O H |
95
|
|
|
|
|
|
|
my (@RGBColors) = |
96
|
|
|
|
|
|
|
('1 1 0', '0 0 1', '1 0 0', '1 1 1', '.5 .5 .5', '1 0 1', '1 .5 0', '0 1 0'); |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
# C rest P Hal |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
my (%ColorNames) = ( |
101
|
|
|
|
|
|
|
'yellow' => 0, |
102
|
|
|
|
|
|
|
'blue' => 1, |
103
|
|
|
|
|
|
|
'red' => 2, |
104
|
|
|
|
|
|
|
'white' => 3, |
105
|
|
|
|
|
|
|
'grey' => 4, |
106
|
|
|
|
|
|
|
'purple' => 5, |
107
|
|
|
|
|
|
|
'brown' => 6, |
108
|
|
|
|
|
|
|
'green' => 7 |
109
|
|
|
|
|
|
|
); |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
sub new { |
112
|
1
|
|
|
1
|
|
2
|
my ($class, $fh) = @_; |
113
|
1
|
50
|
|
|
|
5
|
$class = ref($class) if (ref($class)); |
114
|
|
|
|
|
|
|
|
115
|
1
|
|
|
|
|
18
|
my $this = bless { |
116
|
|
|
|
|
|
|
fh => $fh, |
117
|
|
|
|
|
|
|
atoms => [], |
118
|
|
|
|
|
|
|
bonds => [], |
119
|
|
|
|
|
|
|
points => [], |
120
|
|
|
|
|
|
|
lines => [], |
121
|
|
|
|
|
|
|
style => $Style, |
122
|
|
|
|
|
|
|
color => $Color, |
123
|
|
|
|
|
|
|
lineSets => [], |
124
|
|
|
|
|
|
|
lineColors => [], |
125
|
|
|
|
|
|
|
indent => 0, |
126
|
|
|
|
|
|
|
DefUse => {}, # stores shared instances |
127
|
|
|
|
|
|
|
BLT => {}, # bond lookup table for CONECT list |
128
|
|
|
|
|
|
|
RadiusStick => $RadiusStick, |
129
|
|
|
|
|
|
|
Compression => $Compression, |
130
|
|
|
|
|
|
|
RadiusBNS => $RadiusBNS, |
131
|
|
|
|
|
|
|
}, $class; |
132
|
|
|
|
|
|
|
|
133
|
1
|
|
|
|
|
3
|
return $this; |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub add_mol { |
137
|
1
|
|
|
1
|
|
2
|
my ($this, $mol) = @_; |
138
|
|
|
|
|
|
|
|
139
|
1
|
|
|
|
|
2
|
my %atoms; |
140
|
1
|
|
|
|
|
5
|
for my $atom ($mol->atoms) { |
141
|
9
|
|
|
|
|
30
|
my $label = uc $atom->symbol; |
142
|
9
|
|
|
|
|
65
|
my ($x, $y, $z) = $atom->coords->array; |
143
|
9
|
|
|
|
|
51
|
my $vrml_atom = { |
144
|
|
|
|
|
|
|
x => $x, |
145
|
|
|
|
|
|
|
y => $y, |
146
|
|
|
|
|
|
|
z => $z, |
147
|
9
|
|
|
|
|
435
|
nr => scalar(@{$this->{'atoms'}}), |
148
|
|
|
|
|
|
|
label => $label, |
149
|
|
|
|
|
|
|
radius => $VDWRadius{$label}, |
150
|
|
|
|
|
|
|
}; |
151
|
9
|
|
|
|
|
26
|
$atoms{$atom} = $vrml_atom; |
152
|
9
|
|
|
|
|
63
|
push(@{$this->{'atoms'}}, $vrml_atom); |
|
9
|
|
|
|
|
26
|
|
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
1
|
|
|
|
|
7
|
for my $bond ($mol->bonds) { |
156
|
0
|
|
|
|
|
0
|
my ($from, $to) = map { $atoms{$_} } $bond->atoms; |
|
0
|
|
|
|
|
0
|
|
157
|
0
|
|
|
|
|
0
|
push(@{$this->{'bonds'}}, {from => $from, to => $to}); |
|
0
|
|
|
|
|
0
|
|
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
} |
160
|
1
|
|
|
|
|
9
|
1; |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
########################################################################### |
163
|
|
|
|
|
|
|
# |
164
|
|
|
|
|
|
|
# Read PDB file |
165
|
|
|
|
|
|
|
# Old atoms and bonds won't be deleted, allowing to |
166
|
|
|
|
|
|
|
# merge several PDB file. |
167
|
|
|
|
|
|
|
# Syntax: $object->readPDB($fileName); |
168
|
|
|
|
|
|
|
# Diag: returns undef on error |
169
|
|
|
|
|
|
|
# |
170
|
|
|
|
|
|
|
# 1 2 3 4 5 6 7 |
171
|
|
|
|
|
|
|
#1234567890123456789012345678901234567890123456789012345678901234567890123456789 |
172
|
|
|
|
|
|
|
#TOM 5 O5* A A 1 -16.851 -5.543 74.981 1.00 55.62 3CRO 148 |
173
|
|
|
|
|
|
|
########################################################################### |
174
|
|
|
|
|
|
|
sub readPDB { |
175
|
0
|
|
|
0
|
|
0
|
my $this = shift; |
176
|
0
|
|
|
|
|
0
|
my $fileName = shift; |
177
|
|
|
|
|
|
|
|
178
|
0
|
0
|
|
|
|
0
|
open(FILE, "$fileName") or return undef; |
179
|
0
|
|
|
|
|
0
|
while () { |
180
|
0
|
0
|
|
|
|
0
|
if (/^ATOM /) { # only C,H,O,P,N,S allowed |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
181
|
0
|
|
|
|
|
0
|
my $label = substr($_, 12, 4); |
182
|
0
|
|
|
|
|
0
|
$label =~ s/\s//g; |
183
|
0
|
|
|
|
|
0
|
$label = substr(uc $label, 0, 1); # only the first letter |
184
|
0
|
|
|
|
|
0
|
my $x = substr($_, 30, 8); |
185
|
0
|
|
|
|
|
0
|
my $y = substr($_, 38, 8); |
186
|
0
|
|
|
|
|
0
|
my $z = substr($_, 46, 8); |
187
|
0
|
|
|
|
|
0
|
my (%atom) = ( |
188
|
|
|
|
|
|
|
'x' => $x, |
189
|
|
|
|
|
|
|
'y' => $y, |
190
|
|
|
|
|
|
|
'z' => $z, |
191
|
0
|
|
|
|
|
0
|
'nr' => scalar(@{$this->{'atoms'}}), |
192
|
|
|
|
|
|
|
'label' => $label, |
193
|
|
|
|
|
|
|
'radius' => $VDWRadius{$label} |
194
|
|
|
|
|
|
|
); |
195
|
0
|
|
|
|
|
0
|
push(@{$this->{'atoms'}}, \%atom); |
|
0
|
|
|
|
|
0
|
|
196
|
|
|
|
|
|
|
} elsif (/^HETATM/) { |
197
|
0
|
|
|
|
|
0
|
my $label = substr($_, 12, 4); |
198
|
0
|
|
|
|
|
0
|
$label =~ s/\s//g; |
199
|
0
|
|
|
|
|
0
|
$label =~ s/[^A-Za-z].*$//g; |
200
|
0
|
|
|
|
|
0
|
$label = uc $label; |
201
|
0
|
|
|
|
|
0
|
my $x = substr($_, 30, 8); |
202
|
0
|
|
|
|
|
0
|
my $y = substr($_, 38, 8); |
203
|
0
|
|
|
|
|
0
|
my $z = substr($_, 46, 8); |
204
|
0
|
|
|
|
|
0
|
my (%atom) = ( |
205
|
|
|
|
|
|
|
'x' => $x, |
206
|
|
|
|
|
|
|
'y' => $y, |
207
|
|
|
|
|
|
|
'z' => $z, |
208
|
0
|
|
|
|
|
0
|
'nr' => scalar(@{$this->{'atoms'}}), |
209
|
|
|
|
|
|
|
'label' => $label, |
210
|
|
|
|
|
|
|
'radius' => $VDWRadius{$label} |
211
|
|
|
|
|
|
|
); |
212
|
0
|
|
|
|
|
0
|
push(@{$this->{'atoms'}}, \%atom); |
|
0
|
|
|
|
|
0
|
|
213
|
|
|
|
|
|
|
} elsif (/^CONECT/) { |
214
|
0
|
|
|
|
|
0
|
my $tmp = substr($_, 0, 69); |
215
|
0
|
|
|
|
|
0
|
my ($null, $a, @b) = split(/\s+/, $tmp); |
216
|
0
|
|
|
|
|
0
|
foreach (@b) { |
217
|
0
|
|
|
|
|
0
|
my $n1 = $a - 1; |
218
|
0
|
|
|
|
|
0
|
my $n2 = $_ - 1; |
219
|
0
|
0
|
|
|
|
0
|
if ($n1 > $n2) { my $n3 = $n1; $n1 = $n2; $n2 = $n3; } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
220
|
0
|
|
|
|
|
0
|
my $label = $n1 . '_' . $n2; |
221
|
0
|
0
|
|
|
|
0
|
next if (exists($this->{'BLT'}->{$label})); |
222
|
0
|
|
|
|
|
0
|
my $from = $this->{'atoms'}->[$n1]; |
223
|
0
|
|
|
|
|
0
|
my $to = $this->{'atoms'}->[$n2]; |
224
|
0
|
|
|
|
|
0
|
my (%bond) = ('from' => $from, 'to' => $to); |
225
|
0
|
|
|
|
|
0
|
push(@{$this->{'bonds'}}, \%bond); |
|
0
|
|
|
|
|
0
|
|
226
|
0
|
|
|
|
|
0
|
$this->{'BLT'}->{$label} = 1; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
} |
230
|
0
|
|
|
|
|
0
|
CORE::close FILE; |
231
|
|
|
|
|
|
|
|
232
|
0
|
|
|
|
|
0
|
1; |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
########################################################################### |
236
|
|
|
|
|
|
|
sub setStyle { |
237
|
1
|
|
|
1
|
|
1
|
my ($this, $style) = @_; |
238
|
1
|
|
|
|
|
4
|
$style = lc $style; |
239
|
1
|
|
|
|
|
3
|
$style =~ s/[_ ]//g; |
240
|
1
|
|
|
|
|
4
|
$this->{'style'} = $style; |
241
|
|
|
|
|
|
|
} |
242
|
1
|
|
|
1
|
|
2
|
sub setColor { my $this = shift; $this->{'color'} = shift; } |
|
1
|
|
|
|
|
6
|
|
243
|
0
|
|
|
0
|
|
0
|
sub setStickRadius { my $this = shift; $this->{RadiusStick} = shift; } |
|
0
|
|
|
|
|
0
|
|
244
|
0
|
|
|
0
|
|
0
|
sub setBallRadius { my $this = shift; $this->{RadiusBNS} = shift; } |
|
0
|
|
|
|
|
0
|
|
245
|
0
|
|
|
0
|
|
0
|
sub setCompression { my $this = shift; $this->{Compression} = shift; } |
|
0
|
|
|
|
|
0
|
|
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
########################################################################### |
248
|
|
|
|
|
|
|
# |
249
|
|
|
|
|
|
|
# Center all atoms |
250
|
|
|
|
|
|
|
# Syntax: $object->centerAtoms(); |
251
|
|
|
|
|
|
|
# |
252
|
|
|
|
|
|
|
########################################################################### |
253
|
|
|
|
|
|
|
sub centerAtoms { |
254
|
1
|
|
|
1
|
|
3
|
my $this = shift; |
255
|
|
|
|
|
|
|
|
256
|
1
|
|
|
|
|
17
|
my ($cogX, $cogY, $cogZ) = (0, 0, 0); |
257
|
1
|
|
|
|
|
2
|
foreach (@{$this->{'atoms'}}) { |
|
1
|
|
|
|
|
3
|
|
258
|
9
|
|
|
|
|
15
|
$cogX += $_->{'x'}; |
259
|
9
|
|
|
|
|
16
|
$cogY += $_->{'y'}; |
260
|
9
|
|
|
|
|
17
|
$cogZ += $_->{'z'}; |
261
|
|
|
|
|
|
|
} |
262
|
1
|
|
|
|
|
4
|
my $numAtoms = @{$this->{'atoms'}}; |
|
1
|
|
|
|
|
2
|
|
263
|
1
|
|
|
|
|
3
|
$cogX /= $numAtoms; |
264
|
1
|
|
|
|
|
2
|
$cogY /= $numAtoms; |
265
|
1
|
|
|
|
|
1
|
$cogZ /= $numAtoms; |
266
|
1
|
|
|
|
|
3
|
foreach (($cogX, $cogY, $cogZ)) { $_ = sprintf("%.4f", $_); } |
|
3
|
|
|
|
|
19
|
|
267
|
1
|
|
|
|
|
2
|
foreach (@{$this->{'atoms'}}) { |
|
1
|
|
|
|
|
2
|
|
268
|
9
|
|
|
|
|
9
|
$_->{'x'} -= $cogX; |
269
|
9
|
|
|
|
|
9
|
$_->{'y'} -= $cogY; |
270
|
9
|
|
|
|
|
16
|
$_->{'z'} -= $cogZ; |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
########################################################################### |
275
|
|
|
|
|
|
|
# |
276
|
|
|
|
|
|
|
# Generate list of lines (cylinders) and points. |
277
|
|
|
|
|
|
|
# Syntax: $object->_genDisplay(); |
278
|
|
|
|
|
|
|
# |
279
|
|
|
|
|
|
|
########################################################################### |
280
|
|
|
|
|
|
|
sub _genDisplay { |
281
|
1
|
|
|
1
|
|
1
|
my $this = shift; |
282
|
1
|
|
|
|
|
3
|
my $color = $this->{'color'}; |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
# determine atom colors |
285
|
1
|
50
|
|
|
|
4
|
if ($color eq 'byAtom') { |
286
|
1
|
|
|
|
|
2
|
foreach (@{$this->{'atoms'}}) { |
|
1
|
|
|
|
|
2
|
|
287
|
9
|
|
|
|
|
20
|
$_->{'color'} = $AtomColors{$_->{'label'}}; |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
} else { |
290
|
0
|
|
|
|
|
0
|
my $c = $ColorNames{$color}; |
291
|
0
|
|
|
|
|
0
|
foreach (@{$this->{'atoms'}}) { $_->{'color'} = $c; } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
# create one point foreach atom |
295
|
1
|
|
|
|
|
2
|
@{$this->{'points'}} = (); |
|
1
|
|
|
|
|
3
|
|
296
|
1
|
|
|
|
|
2
|
foreach (@{$this->{'atoms'}}) { |
|
1
|
|
|
|
|
3
|
|
297
|
9
|
|
|
|
|
42
|
my (%point) = (%$_, 'lines' => []); |
298
|
9
|
|
|
|
|
12
|
push(@{$this->{'points'}}, \%point); |
|
9
|
|
|
|
|
16
|
|
299
|
9
|
|
|
|
|
21
|
$_->{'point'} = \%point; |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
# create one (or two) lines per bond |
303
|
1
|
|
|
|
|
2
|
@{$this->{'lines'}} = (); |
|
1
|
|
|
|
|
3
|
|
304
|
1
|
|
|
|
|
2
|
foreach (@{$this->{'bonds'}}) { |
|
1
|
|
|
|
|
2
|
|
305
|
0
|
|
|
|
|
0
|
my ($at1, $at2) = ($_->{'from'}, $_->{'to'}); |
306
|
0
|
0
|
|
|
|
0
|
if ($at1->{'color'} == $at2->{'color'}) { |
307
|
0
|
|
|
|
|
0
|
my $from = $at1->{'point'}; |
308
|
0
|
|
|
|
|
0
|
my (%line) = ( |
309
|
|
|
|
|
|
|
'from' => $from, |
310
|
|
|
|
|
|
|
'to' => $at2->{'point'}, |
311
|
|
|
|
|
|
|
'label' => $at1->{'nr'} . '_' . $at2->{'nr'} |
312
|
|
|
|
|
|
|
); |
313
|
0
|
|
|
|
|
0
|
push(@{$this->{'lines'}}, \%line); |
|
0
|
|
|
|
|
0
|
|
314
|
0
|
|
|
|
|
0
|
push(@{$from->{'lines'}}, \%line); |
|
0
|
|
|
|
|
0
|
|
315
|
0
|
|
|
|
|
0
|
next; |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
# split bond |
319
|
0
|
|
|
|
|
0
|
my $pt1 = $at1->{'point'}; |
320
|
0
|
|
|
|
|
0
|
my $pt2 = $at2->{'point'}; |
321
|
|
|
|
|
|
|
|
322
|
0
|
|
|
|
|
0
|
my $x = 0.5 * ($at1->{'x'} + $at2->{'x'}); |
323
|
0
|
|
|
|
|
0
|
my $y = 0.5 * ($at1->{'y'} + $at2->{'y'}); |
324
|
0
|
|
|
|
|
0
|
my $z = 0.5 * ($at1->{'z'} + $at2->{'z'}); |
325
|
0
|
|
|
|
|
0
|
my (%point3) = ( |
326
|
|
|
|
|
|
|
'x' => $x, |
327
|
|
|
|
|
|
|
'y' => $y, |
328
|
|
|
|
|
|
|
'z' => $z, # no label, |
329
|
|
|
|
|
|
|
'color' => $at2->{'color'}, # radius or |
330
|
0
|
|
|
|
|
0
|
'nr' => scalar(@{$this->{'points'}}) |
331
|
|
|
|
|
|
|
); # bonds needed |
332
|
0
|
|
|
|
|
0
|
my (%line1) = ( |
333
|
|
|
|
|
|
|
'from' => $pt1, |
334
|
|
|
|
|
|
|
'to' => \%point3, |
335
|
|
|
|
|
|
|
'label' => $at1->{'nr'} . '_' . $at2->{'nr'} |
336
|
|
|
|
|
|
|
); |
337
|
0
|
|
|
|
|
0
|
my (%line2) = ( |
338
|
|
|
|
|
|
|
'from' => $pt2, |
339
|
|
|
|
|
|
|
'to' => \%point3, |
340
|
|
|
|
|
|
|
'label' => $at2->{'nr'} . '_' . $at1->{'nr'} |
341
|
|
|
|
|
|
|
); |
342
|
0
|
|
|
|
|
0
|
push(@{$this->{'lines'}}, \%line1); |
|
0
|
|
|
|
|
0
|
|
343
|
0
|
|
|
|
|
0
|
push(@{$this->{'lines'}}, \%line2); |
|
0
|
|
|
|
|
0
|
|
344
|
0
|
|
|
|
|
0
|
push(@{$pt1->{'lines'}}, \%line1); |
|
0
|
|
|
|
|
0
|
|
345
|
0
|
|
|
|
|
0
|
push(@{$pt2->{'lines'}}, \%line2); |
|
0
|
|
|
|
|
0
|
|
346
|
0
|
|
|
|
|
0
|
push(@{$this->{'points'}}, \%point3); |
|
0
|
|
|
|
|
0
|
|
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
########################################################################### |
351
|
|
|
|
|
|
|
# |
352
|
|
|
|
|
|
|
# Optimize the wireframe representation. |
353
|
|
|
|
|
|
|
# Create longer line strips instead of single lines. |
354
|
|
|
|
|
|
|
# |
355
|
|
|
|
|
|
|
########################################################################### |
356
|
|
|
|
|
|
|
sub _genLineSets { |
357
|
1
|
|
|
1
|
|
2
|
my $this = shift; |
358
|
|
|
|
|
|
|
|
359
|
1
|
|
|
|
|
2
|
@{$this->{'lineSets'}} = (); |
|
1
|
|
|
|
|
2
|
|
360
|
1
|
|
|
|
|
2
|
@{$this->{'lineColors'}} = (); |
|
1
|
|
|
|
|
2
|
|
361
|
1
|
|
|
|
|
2
|
foreach (@{$this->{'lines'}}) { $_->{'used'} = 0; } |
|
1
|
|
|
|
|
2
|
|
|
0
|
|
|
|
|
0
|
|
362
|
1
|
|
|
|
|
2
|
foreach (@{$this->{'lines'}}) { |
|
1
|
|
|
|
|
7
|
|
363
|
0
|
0
|
|
|
|
0
|
next if $_->{'used'}; |
364
|
0
|
|
|
|
|
0
|
my ($from, $to) = ($_->{'from'}, $_->{'to'}); |
365
|
0
|
|
|
|
|
0
|
push(@{$this->{'lineColors'}}, $from->{'color'}); |
|
0
|
|
|
|
|
0
|
|
366
|
0
|
|
|
|
|
0
|
my $set = [$from->{'nr'}, $to->{'nr'}]; |
367
|
0
|
|
|
|
|
0
|
push(@{$this->{'lineSets'}}, $set); |
|
0
|
|
|
|
|
0
|
|
368
|
0
|
|
|
|
|
0
|
$_->{'used'} = 1; |
369
|
0
|
|
|
|
|
0
|
my $next = 1; |
370
|
0
|
|
|
|
|
0
|
my $bonds = $to->{'lines'}; |
371
|
|
|
|
|
|
|
|
372
|
0
|
|
0
|
|
|
0
|
while ($next and $bonds) { |
373
|
0
|
|
|
|
|
0
|
$next = 0; |
374
|
0
|
|
|
|
|
0
|
my $b; |
375
|
0
|
|
|
|
|
0
|
foreach $b (@$bonds) { |
376
|
0
|
0
|
|
|
|
0
|
next if $b->{'used'}; |
377
|
0
|
|
|
|
|
0
|
my $to = $b->{'to'}; |
378
|
0
|
|
|
|
|
0
|
push(@$set, $to->{'nr'}); |
379
|
0
|
|
|
|
|
0
|
$bonds = $to->{'lines'}; |
380
|
0
|
|
|
|
|
0
|
$b->{'used'} = 1; |
381
|
0
|
|
|
|
|
0
|
$next = 1; |
382
|
0
|
|
|
|
|
0
|
last; |
383
|
|
|
|
|
|
|
} |
384
|
|
|
|
|
|
|
} |
385
|
|
|
|
|
|
|
} |
386
|
|
|
|
|
|
|
} |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
########################################################################### |
389
|
|
|
|
|
|
|
# |
390
|
|
|
|
|
|
|
# print VRML SceneGraph |
391
|
|
|
|
|
|
|
# |
392
|
|
|
|
|
|
|
########################################################################### |
393
|
|
|
|
|
|
|
sub printVRML { |
394
|
1
|
|
|
1
|
|
2
|
my $this = shift; |
395
|
|
|
|
|
|
|
|
396
|
1
|
|
|
|
|
1
|
%{$this->{'DefUse'}} = (); |
|
1
|
|
|
|
|
3
|
|
397
|
1
|
|
|
|
|
2
|
$this->{'indent'} = 0; |
398
|
1
|
|
|
|
|
5
|
$this->_printHead(); |
399
|
|
|
|
|
|
|
|
400
|
1
|
|
|
|
|
9
|
$this->_genDisplay(); |
401
|
|
|
|
|
|
|
|
402
|
1
|
50
|
|
|
|
8
|
$this->_genLineSets(), $this->_printWire() |
403
|
|
|
|
|
|
|
if ($this->{'style'} =~ /wire/); |
404
|
1
|
50
|
|
|
|
11
|
$this->_printAtoms() |
405
|
|
|
|
|
|
|
if ($this->{'style'} =~ /(ball|stick|cpk)/); |
406
|
|
|
|
|
|
|
|
407
|
1
|
|
|
|
|
5
|
$this->_printTail(); |
408
|
|
|
|
|
|
|
} |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
########################################################################### |
411
|
|
|
|
|
|
|
# |
412
|
|
|
|
|
|
|
# print VRML header |
413
|
|
|
|
|
|
|
# |
414
|
|
|
|
|
|
|
########################################################################### |
415
|
|
|
|
|
|
|
sub _printHead { |
416
|
1
|
|
|
1
|
|
1
|
my $this = shift; |
417
|
1
|
|
|
|
|
2
|
my $fh = $this->{fh}; |
418
|
|
|
|
|
|
|
|
419
|
1
|
|
|
|
|
3
|
print $fh <
|
420
|
|
|
|
|
|
|
#VRML V2.0 utf8 |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
Transform { |
423
|
|
|
|
|
|
|
children [ |
424
|
|
|
|
|
|
|
NavigationInfo { type "EXAMINE" } |
425
|
|
|
|
|
|
|
EOT |
426
|
|
|
|
|
|
|
|
427
|
1
|
|
|
|
|
2
|
$this->{'indent'} = 2; |
428
|
|
|
|
|
|
|
} |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
########################################################################### |
431
|
|
|
|
|
|
|
sub _printWire { |
432
|
1
|
|
|
1
|
|
2
|
my $this = shift; |
433
|
|
|
|
|
|
|
|
434
|
1
|
|
|
|
|
4
|
$this->_printWireShape(); |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
########################################################################### |
438
|
|
|
|
|
|
|
sub _printWireShape { |
439
|
1
|
|
|
1
|
|
2
|
my $this = shift; |
440
|
|
|
|
|
|
|
|
441
|
1
|
50
|
|
|
|
4
|
if ($this->{'DefUse'}->{'WireShape'}) { |
442
|
0
|
|
|
|
|
0
|
$this->_printLine('USE WIRESHAPE'); |
443
|
0
|
|
|
|
|
0
|
return; |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
|
446
|
1
|
|
|
|
|
4
|
$this->_printLine('DEF WIRESHAPE Shape {'); |
447
|
1
|
|
|
|
|
2
|
$this->{'indent'}++; |
448
|
1
|
|
|
|
|
5
|
$this->_printWireAppearance(); |
449
|
1
|
|
|
|
|
4
|
$this->_printWireGeometry(); |
450
|
1
|
|
|
|
|
1
|
$this->{'indent'}--; |
451
|
1
|
|
|
|
|
4
|
$this->_printLine('}'); |
452
|
|
|
|
|
|
|
|
453
|
1
|
|
|
|
|
4
|
$this->{'DefUse'}->{'WireShape'} = 1; |
454
|
|
|
|
|
|
|
} |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
########################################################################### |
457
|
|
|
|
|
|
|
sub _printWireAppearance { |
458
|
1
|
|
|
1
|
|
1
|
my $this = shift; |
459
|
|
|
|
|
|
|
|
460
|
1
|
50
|
|
|
|
4
|
if ($this->{'DefUse'}->{'WireApp'}) { |
461
|
0
|
|
|
|
|
0
|
$this->_printLine('USE WIREAPP'); |
462
|
0
|
|
|
|
|
0
|
return; |
463
|
|
|
|
|
|
|
} |
464
|
|
|
|
|
|
|
|
465
|
1
|
|
|
|
|
3
|
$this->_printLine("appearance DEF WIREAPP Appearance {"); |
466
|
1
|
|
|
|
|
2
|
$this->{'indent'}++; |
467
|
1
|
|
|
|
|
3
|
$this->_printLine("material Material { diffuseColor 1 1 1 }"); # dummy |
468
|
1
|
|
|
|
|
3
|
$this->{'indent'}--; |
469
|
1
|
|
|
|
|
6
|
$this->_printLine('}'); |
470
|
|
|
|
|
|
|
|
471
|
1
|
|
|
|
|
3
|
$this->{'DefUse'}->{'WireApp'} = 1; |
472
|
|
|
|
|
|
|
} |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
########################################################################### |
475
|
|
|
|
|
|
|
sub _printWireGeometry { |
476
|
1
|
|
|
1
|
|
2
|
my $this = shift; |
477
|
|
|
|
|
|
|
|
478
|
1
|
50
|
|
|
|
6
|
if ($this->{'DefUse'}->{'WireGeo'}) { |
479
|
0
|
|
|
|
|
0
|
$this->_printLine('geometry USE WIREGEO'); |
480
|
0
|
|
|
|
|
0
|
return; |
481
|
|
|
|
|
|
|
} |
482
|
|
|
|
|
|
|
|
483
|
1
|
|
|
|
|
4
|
$this->_printLine('geometry DEF WIREGEO IndexedLineSet {'); |
484
|
1
|
|
|
|
|
1
|
$this->{'indent'}++; |
485
|
1
|
|
|
|
|
6
|
$this->_printWireColor(); |
486
|
1
|
|
|
|
|
4
|
$this->_printWireColorIndex(); |
487
|
1
|
|
|
|
|
3
|
$this->_printLine('colorPerVertex FALSE'); |
488
|
1
|
|
|
|
|
4
|
$this->_printWireCoordinate(); |
489
|
1
|
|
|
|
|
4
|
$this->_printWireCoordIndex(); |
490
|
1
|
|
|
|
|
1
|
$this->{'indent'}--; |
491
|
1
|
|
|
|
|
3
|
$this->_printLine('}'); |
492
|
|
|
|
|
|
|
|
493
|
1
|
|
|
|
|
3
|
$this->{'DefUse'}->{'WireGeo'} = 1; |
494
|
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
########################################################################### |
497
|
|
|
|
|
|
|
sub _printWireColor { |
498
|
1
|
|
|
1
|
|
3
|
my $this = shift; |
499
|
|
|
|
|
|
|
|
500
|
1
|
50
|
|
|
|
16
|
if ($this->{'DefUse'}->{'WireCol'}) { |
501
|
0
|
|
|
|
|
0
|
$this->_printLine('color USE WIRECOL'); |
502
|
0
|
|
|
|
|
0
|
return; |
503
|
|
|
|
|
|
|
} |
504
|
|
|
|
|
|
|
|
505
|
1
|
|
|
|
|
4
|
$this->_printLine('color DEF WIRECOL Color {'); |
506
|
1
|
|
|
|
|
2
|
$this->{'indent'}++; |
507
|
1
|
|
|
|
|
3
|
$this->_printLine('color ['); |
508
|
1
|
|
|
|
|
1
|
$this->{'indent'}++; |
509
|
1
|
|
|
|
|
3
|
foreach (@RGBColors) { $this->_printLine("$_,"); } |
|
8
|
|
|
|
|
22
|
|
510
|
1
|
|
|
|
|
3
|
$this->{'indent'}--; |
511
|
1
|
|
|
|
|
2
|
$this->_printLine(']'); |
512
|
1
|
|
|
|
|
2
|
$this->{'indent'}--; |
513
|
1
|
|
|
|
|
3
|
$this->_printLine('}'); |
514
|
|
|
|
|
|
|
|
515
|
1
|
|
|
|
|
2
|
$this->{'DefUse'}->{'WireCol'} = 1; |
516
|
|
|
|
|
|
|
} |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
########################################################################### |
519
|
|
|
|
|
|
|
sub _printWireColorIndex { |
520
|
1
|
|
|
1
|
|
1
|
my $this = shift; |
521
|
|
|
|
|
|
|
|
522
|
1
|
|
|
|
|
3
|
$this->_printLine('colorIndex ['); |
523
|
1
|
|
|
|
|
3
|
$this->{'indent'}++; |
524
|
1
|
|
|
|
|
3
|
my $lc = $this->{'lineColors'}; |
525
|
1
|
|
|
|
|
1
|
my $i; |
526
|
1
|
|
|
|
|
10
|
for ($i = 0 ; $i < (@$lc - 8) ; $i += 8) { |
527
|
0
|
|
|
|
|
0
|
$this->_printLine(join(', ', @$lc[$i .. ($i + 7)]) . ','); |
528
|
|
|
|
|
|
|
} |
529
|
1
|
50
|
|
|
|
4
|
$this->_printLine(join(', ', @$lc[$i .. $#$lc]) . ',') |
530
|
|
|
|
|
|
|
if ($i < @$lc); |
531
|
1
|
|
|
|
|
2
|
$this->{'indent'}--; |
532
|
1
|
|
|
|
|
3
|
$this->_printLine(']'); |
533
|
|
|
|
|
|
|
} |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
########################################################################### |
536
|
|
|
|
|
|
|
sub _printWireCoordinate { |
537
|
1
|
|
|
1
|
|
1
|
my $this = shift; |
538
|
|
|
|
|
|
|
|
539
|
1
|
50
|
|
|
|
5
|
if ($this->{'DefUse'}->{'WireCoo'}) { |
540
|
0
|
|
|
|
|
0
|
$this->_printLine('coord USE WIRECOO'); |
541
|
0
|
|
|
|
|
0
|
return; |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
|
544
|
1
|
|
|
|
|
4
|
$this->_printLine('coord DEF WIRECOO Coordinate {'); |
545
|
1
|
|
|
|
|
1
|
$this->{'indent'}++; |
546
|
1
|
|
|
|
|
3
|
$this->_printLine('point ['); |
547
|
1
|
|
|
|
|
2
|
$this->{'indent'}++; |
548
|
1
|
|
|
|
|
3
|
my ($x, $y, $z); |
549
|
1
|
|
|
|
|
2
|
foreach (@{$this->{'points'}}) { |
|
1
|
|
|
|
|
4
|
|
550
|
9
|
|
|
|
|
34
|
my $x = sprintf("%.4g", $_->{'x'}); |
551
|
9
|
|
|
|
|
20
|
my $y = sprintf("%.4g", $_->{'y'}); |
552
|
9
|
|
|
|
|
18
|
my $z = sprintf("%.4g", $_->{'z'}); |
553
|
9
|
|
|
|
|
24
|
$this->_printLine("$x $y $z,"); |
554
|
|
|
|
|
|
|
} |
555
|
1
|
|
|
|
|
3
|
$this->{'indent'}--; |
556
|
1
|
|
|
|
|
23
|
$this->_printLine(']'); |
557
|
1
|
|
|
|
|
1
|
$this->{'indent'}--; |
558
|
1
|
|
|
|
|
3
|
$this->_printLine('}'); |
559
|
|
|
|
|
|
|
|
560
|
1
|
|
|
|
|
3
|
$this->{'DefUse'}->{'WireCoo'} = 1; |
561
|
|
|
|
|
|
|
} |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
########################################################################### |
564
|
|
|
|
|
|
|
sub _printWireCoordIndex { |
565
|
1
|
|
|
1
|
|
1
|
my $this = shift; |
566
|
|
|
|
|
|
|
|
567
|
1
|
|
|
|
|
2
|
$this->_printLine('coordIndex ['); |
568
|
1
|
|
|
|
|
2
|
$this->{'indent'}++; |
569
|
1
|
|
|
|
|
2
|
my $ls = $this->{'lineSets'}; |
570
|
1
|
|
|
|
|
3
|
foreach (@$ls) { $this->_printLine(join(', ', @$_) . ', -1,'); } |
|
0
|
|
|
|
|
0
|
|
571
|
1
|
|
|
|
|
2
|
$this->{'indent'}--; |
572
|
1
|
|
|
|
|
2
|
$this->_printLine(']'); |
573
|
|
|
|
|
|
|
} |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
########################################################################### |
576
|
|
|
|
|
|
|
sub _printAtoms { |
577
|
1
|
|
|
1
|
|
2
|
my $this = shift; |
578
|
|
|
|
|
|
|
|
579
|
1
|
|
|
|
|
5
|
foreach (@{$this->{'atoms'}}) { |
|
1
|
|
|
|
|
3
|
|
580
|
9
|
50
|
|
|
|
34
|
$this->_printAtom($_) if ($_->{'label'}); |
581
|
|
|
|
|
|
|
} |
582
|
|
|
|
|
|
|
} |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
########################################################################### |
585
|
|
|
|
|
|
|
sub _printAtom { |
586
|
9
|
|
|
9
|
|
11
|
my $this = shift; |
587
|
9
|
|
|
|
|
10
|
my $atom = shift; |
588
|
|
|
|
|
|
|
|
589
|
9
|
|
|
|
|
45
|
$this->_printLine("DEF ATOM_$atom->{'nr'} Transform {"); |
590
|
9
|
|
|
|
|
15
|
$this->{'indent'}++; |
591
|
9
|
|
|
|
|
72
|
$this->_printLine("translation $atom->{'x'} $atom->{'y'} $atom->{'z'}"); |
592
|
9
|
|
|
|
|
20
|
$this->_printLine('children ['); |
593
|
9
|
|
|
|
|
11
|
$this->{'indent'}++; |
594
|
9
|
|
|
|
|
20
|
$this->_printAtomShape($atom); |
595
|
9
|
50
|
|
|
|
25
|
if ($this->{'style'} =~ /stick/) { |
596
|
0
|
|
|
|
|
0
|
my $point = $atom->{'point'}; |
597
|
0
|
|
|
|
|
0
|
foreach (@{$point->{'lines'}}) { $this->_printBond($_); } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
598
|
|
|
|
|
|
|
} |
599
|
9
|
|
|
|
|
11
|
$this->{'indent'}--; |
600
|
9
|
|
|
|
|
16
|
$this->_printLine(']'); |
601
|
9
|
|
|
|
|
10
|
$this->{'indent'}--; |
602
|
9
|
|
|
|
|
18
|
$this->_printLine('}'); |
603
|
|
|
|
|
|
|
} |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
########################################################################### |
606
|
|
|
|
|
|
|
sub _printAtomShape { |
607
|
9
|
|
|
9
|
|
14
|
my $this = shift; |
608
|
9
|
|
|
|
|
11
|
my $atom = shift; |
609
|
|
|
|
|
|
|
|
610
|
9
|
|
|
|
|
14
|
my $l = $atom->{'label'}; |
611
|
9
|
100
|
|
|
|
27
|
if ($this->{'DefUse'}->{"AtomShape$l"}) { |
612
|
6
|
|
|
|
|
17
|
$this->_printLine("USE ATOMSHAPE_$l"); |
613
|
6
|
|
|
|
|
12
|
return; |
614
|
|
|
|
|
|
|
} |
615
|
|
|
|
|
|
|
|
616
|
3
|
|
|
|
|
9
|
$this->_printLine("DEF ATOMSHAPE_$l Shape {"); |
617
|
3
|
|
|
|
|
4
|
$this->{'indent'}++; |
618
|
3
|
|
|
|
|
6
|
$this->_printAtomAppearance($atom); |
619
|
3
|
|
|
|
|
6
|
$this->_printAtomGeometry($atom); |
620
|
3
|
|
|
|
|
4
|
$this->{'indent'}--; |
621
|
3
|
|
|
|
|
5
|
$this->_printLine('}'); |
622
|
|
|
|
|
|
|
|
623
|
3
|
|
|
|
|
10
|
$this->{'DefUse'}->{"AtomShape$l"} = 1; |
624
|
|
|
|
|
|
|
} |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
########################################################################### |
627
|
|
|
|
|
|
|
sub _printAtomAppearance { |
628
|
3
|
|
|
3
|
|
4
|
my $this = shift; |
629
|
3
|
|
|
|
|
4
|
my $atom = shift; |
630
|
|
|
|
|
|
|
|
631
|
3
|
|
|
|
|
6
|
my $c = $atom->{'color'}; |
632
|
3
|
50
|
|
|
|
11
|
if ($this->{'DefUse'}->{"AtomApp$c"}) { |
633
|
0
|
|
|
|
|
0
|
$this->_printLine("appearance USE ATOMAPP_$c"); |
634
|
0
|
|
|
|
|
0
|
return; |
635
|
|
|
|
|
|
|
} |
636
|
|
|
|
|
|
|
|
637
|
3
|
|
|
|
|
9
|
$this->_printLine("appearance DEF ATOMAPP_$c Appearance {"); |
638
|
3
|
|
|
|
|
5
|
$this->{'indent'}++; |
639
|
3
|
|
|
|
|
7
|
$this->_printLine('material Material {'); |
640
|
3
|
|
|
|
|
4
|
$this->{'indent'}++; |
641
|
3
|
|
|
|
|
10
|
$this->_printLine("diffuseColor $RGBColors[$c]"); |
642
|
3
|
|
|
|
|
7
|
$this->_printLine('specularColor 1 1 1'); |
643
|
3
|
|
|
|
|
6
|
$this->_printLine('shininess 0.75'); |
644
|
3
|
|
|
|
|
5
|
$this->{'indent'}--; |
645
|
3
|
|
|
|
|
6
|
$this->_printLine('}'); |
646
|
3
|
|
|
|
|
4
|
$this->{'indent'}--; |
647
|
3
|
|
|
|
|
5
|
$this->_printLine('}'); |
648
|
|
|
|
|
|
|
|
649
|
3
|
|
|
|
|
9
|
$this->{'DefUse'}->{"AtomApp$c"} = 1; |
650
|
|
|
|
|
|
|
} |
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
########################################################################### |
653
|
|
|
|
|
|
|
sub _printAtomGeometry { |
654
|
3
|
|
|
3
|
|
4
|
my $this = shift; |
655
|
3
|
|
|
|
|
3
|
my $atom = shift; |
656
|
|
|
|
|
|
|
|
657
|
3
|
|
|
|
|
5
|
my $l = $atom->{'label'}; |
658
|
3
|
50
|
|
|
|
9
|
if ($this->{'DefUse'}->{"AtomGeo$l"}) { |
659
|
0
|
|
|
|
|
0
|
$this->_printLine("geometry USE ATOMGEO_$l"); |
660
|
0
|
|
|
|
|
0
|
return; |
661
|
|
|
|
|
|
|
} |
662
|
|
|
|
|
|
|
|
663
|
3
|
|
|
|
|
4
|
my $r = $this->{RadiusStick}; |
664
|
3
|
50
|
|
|
|
14
|
$r = $this->{RadiusBNS} * $atom->{'radius'} if ($this->{'style'} =~ /ball/); |
665
|
3
|
50
|
|
|
|
10
|
$r = $atom->{'radius'} if ($this->{'style'} =~ /cpk/); |
666
|
3
|
|
|
|
|
45
|
$this->_printLine("geometry DEF ATOMGEO_$l Sphere { radius $r }"); |
667
|
|
|
|
|
|
|
|
668
|
3
|
|
|
|
|
9
|
$this->{'DefUse'}->{"AtomGeo$l"} = 1; |
669
|
|
|
|
|
|
|
} |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
########################################################################### |
672
|
|
|
|
|
|
|
sub _printBond { |
673
|
0
|
|
|
0
|
|
0
|
my $this = shift; |
674
|
0
|
|
|
|
|
0
|
my $bond = shift; |
675
|
|
|
|
|
|
|
|
676
|
0
|
|
|
|
|
0
|
my ($from, $to) = ($bond->{'from'}, $bond->{'to'}); |
677
|
0
|
|
|
|
|
0
|
my ($tx, $ty, $tz, $s, $ax, $ay, $az, $angle) = |
678
|
|
|
|
|
|
|
$this->_calcBond($from, $to); |
679
|
|
|
|
|
|
|
|
680
|
0
|
|
|
|
|
0
|
foreach ($tx, $ty, $tz, $s, $ax, $ay, $az, $angle) { |
681
|
0
|
|
|
|
|
0
|
$_ = sprintf("%.5g", $_); |
682
|
|
|
|
|
|
|
} |
683
|
|
|
|
|
|
|
|
684
|
0
|
|
|
|
|
0
|
my $l = $bond->{'label'}; |
685
|
0
|
|
|
|
|
0
|
$this->_printLine("DEF BOND_$l Transform {"); |
686
|
0
|
|
|
|
|
0
|
$this->{'indent'}++; |
687
|
0
|
|
|
|
|
0
|
$this->_printLine("translation $tx $ty $tz"); |
688
|
0
|
|
|
|
|
0
|
$this->_printLine("scale 1 $s 1"); |
689
|
0
|
|
|
|
|
0
|
$this->_printLine("rotation $ax $ay $az $angle"); |
690
|
0
|
|
|
|
|
0
|
$this->_printLine('children ['); |
691
|
0
|
|
|
|
|
0
|
$this->{'indent'}++; |
692
|
0
|
|
|
|
|
0
|
$this->_printBondShape($from); |
693
|
0
|
|
|
|
|
0
|
$this->{'indent'}--; |
694
|
0
|
|
|
|
|
0
|
$this->_printLine(']'); |
695
|
0
|
|
|
|
|
0
|
$this->{'indent'}--; |
696
|
0
|
|
|
|
|
0
|
$this->_printLine('}'); |
697
|
|
|
|
|
|
|
} |
698
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
########################################################################### |
700
|
|
|
|
|
|
|
sub _printBondShape { |
701
|
0
|
|
|
0
|
|
0
|
my $this = shift; |
702
|
0
|
|
|
|
|
0
|
my $from = shift; |
703
|
|
|
|
|
|
|
|
704
|
0
|
|
|
|
|
0
|
my $c = $from->{'color'}; |
705
|
0
|
0
|
|
|
|
0
|
if ($this->{'DefUse'}->{"BondShape$c"}) { |
706
|
0
|
|
|
|
|
0
|
$this->_printLine("USE BONDSHAPE_$c"); |
707
|
0
|
|
|
|
|
0
|
return; |
708
|
|
|
|
|
|
|
} |
709
|
|
|
|
|
|
|
|
710
|
0
|
|
|
|
|
0
|
$this->_printLine("DEF BONDSHAPE_$c Shape {"); |
711
|
0
|
|
|
|
|
0
|
$this->{'indent'}++; |
712
|
0
|
|
|
|
|
0
|
$this->_printAtomAppearance($from); # bond color is the same as atom color |
713
|
0
|
|
|
|
|
0
|
$this->_printBondGeometry(); |
714
|
0
|
|
|
|
|
0
|
$this->{'indent'}--; |
715
|
0
|
|
|
|
|
0
|
$this->_printLine('}'); |
716
|
|
|
|
|
|
|
|
717
|
0
|
|
|
|
|
0
|
$this->{'DefUse'}->{"BondShape$c"} = 1; |
718
|
|
|
|
|
|
|
} |
719
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
########################################################################### |
721
|
|
|
|
|
|
|
sub _printBondGeometry { |
722
|
0
|
|
|
0
|
|
0
|
my $this = shift; |
723
|
|
|
|
|
|
|
|
724
|
0
|
0
|
|
|
|
0
|
if ($this->{'DefUse'}->{'BondGeo'}) { |
725
|
0
|
|
|
|
|
0
|
$this->_printLine('geometry USE BONDGEO'); |
726
|
0
|
|
|
|
|
0
|
return; |
727
|
|
|
|
|
|
|
} |
728
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
$this->_printLine( |
730
|
0
|
|
|
|
|
0
|
"geometry DEF BONDGEO Cylinder { radius $this->{RadiusStick} top FALSE bottom FALSE}" |
731
|
|
|
|
|
|
|
); |
732
|
|
|
|
|
|
|
|
733
|
0
|
|
|
|
|
0
|
$this->{'DefUse'}->{'BondGeo'} = 1; |
734
|
|
|
|
|
|
|
} |
735
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
########################################################################### |
737
|
|
|
|
|
|
|
# |
738
|
|
|
|
|
|
|
# print VRML tail |
739
|
|
|
|
|
|
|
# |
740
|
|
|
|
|
|
|
########################################################################### |
741
|
|
|
|
|
|
|
sub _printTail { |
742
|
1
|
|
|
1
|
|
3
|
my $this = shift; |
743
|
1
|
|
|
|
|
2
|
my $fh = $this->{fh}; |
744
|
1
|
|
|
|
|
47
|
print $fh <
|
745
|
|
|
|
|
|
|
] |
746
|
|
|
|
|
|
|
} |
747
|
|
|
|
|
|
|
EOT |
748
|
|
|
|
|
|
|
} |
749
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
########################################################################### |
751
|
|
|
|
|
|
|
sub _printLine { |
752
|
118
|
|
|
118
|
|
356
|
my $this = shift; |
753
|
118
|
|
|
|
|
331
|
my $str = shift; |
754
|
118
|
|
|
|
|
147
|
my $fh = $this->{fh}; |
755
|
|
|
|
|
|
|
|
756
|
118
|
50
|
|
|
|
201
|
if ($this->{Compression}) { print $fh "$str\n"; } |
|
0
|
|
|
|
|
0
|
|
757
|
|
|
|
|
|
|
else { |
758
|
118
|
|
|
|
|
175
|
my $i = "\t" x int($this->{'indent'} >> 1); |
759
|
118
|
100
|
|
|
|
254
|
$i .= ' ' if ($this->{'indent'} & 0x1); |
760
|
118
|
|
|
|
|
279
|
print $fh "$i$str\n"; |
761
|
|
|
|
|
|
|
} |
762
|
|
|
|
|
|
|
} |
763
|
|
|
|
|
|
|
|
764
|
|
|
|
|
|
|
########################################################################### |
765
|
|
|
|
|
|
|
# |
766
|
|
|
|
|
|
|
# Calculate bond transformation parameters |
767
|
|
|
|
|
|
|
# Syntax: @geometry = _calcBond(\%atom1, \%atom2); |
768
|
|
|
|
|
|
|
# |
769
|
|
|
|
|
|
|
########################################################################### |
770
|
|
|
|
|
|
|
sub _calcBond { |
771
|
0
|
|
|
0
|
|
|
my $this = shift; |
772
|
0
|
|
|
|
|
|
my $atom1 = shift; |
773
|
0
|
|
|
|
|
|
my $atom2 = shift; |
774
|
|
|
|
|
|
|
|
775
|
0
|
|
|
|
|
|
my ($x1, $y1, $z1) = ($atom1->{'x'}, $atom1->{'y'}, $atom1->{'z'}); |
776
|
0
|
|
|
|
|
|
my ($x2, $y2, $z2) = ($atom2->{'x'}, $atom2->{'y'}, $atom2->{'z'}); |
777
|
|
|
|
|
|
|
|
778
|
0
|
|
|
|
|
|
my ($dx, $dy, $dz) = ($x2 - $x1, $y2 - $y1, $z2 - $z1); |
779
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
# length |
781
|
0
|
|
|
|
|
|
my $s = sqrt($dx * $dx + $dy * $dy + $dz * $dz); |
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
# translation |
784
|
0
|
|
|
|
|
|
my ($tx, $ty, $tz) = (0.5 * $dx, 0.5 * $dy, 0.5 * $dz); |
785
|
|
|
|
|
|
|
|
786
|
0
|
|
|
|
|
|
($dx, $dy, $dz) = ($dx / $s, $dy / $s, $dz / $s); |
787
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
# rotation axis and angle |
789
|
0
|
|
|
|
|
|
my ($ax, $ay, $az, $angle); |
790
|
0
|
0
|
|
|
|
|
if ($dy > 0.9999) { ($ax, $ay, $az, $angle) = (1, 0, 0, 0); } |
|
0
|
0
|
|
|
|
|
|
791
|
0
|
|
|
|
|
|
elsif ($dy < -0.9999) { ($ax, $ay, $az, $angle) = (1, 0, 0, $PI); } |
792
|
0
|
|
|
|
|
|
else { ($ax, $ay, $az, $angle) = ($dz, 0, -$dx, acos($dy)); } |
793
|
|
|
|
|
|
|
|
794
|
0
|
|
|
|
|
|
return $tx, $ty, $tz, 0.5 * $s, $ax, $ay, $az, $angle; |
795
|
|
|
|
|
|
|
} |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
########################################################################### |
798
|
|
|
|
|
|
|
# |
799
|
|
|
|
|
|
|
# Generate connectivities |
800
|
|
|
|
|
|
|
# |
801
|
|
|
|
|
|
|
########################################################################### |
802
|
|
|
|
|
|
|
sub genBonds { |
803
|
1
|
|
|
1
|
|
7115
|
no warnings 'uninitialized'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
951
|
|
804
|
0
|
|
|
0
|
|
|
my $this = shift; |
805
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
# find largest possible distance |
807
|
0
|
|
|
|
|
|
my $maxR; |
808
|
0
|
0
|
|
|
|
|
foreach (values %AtomRadius) { $maxR = $_ if ($_ > $maxR); } |
|
0
|
|
|
|
|
|
|
809
|
0
|
|
|
|
|
|
$maxR *= 2.4; |
810
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
# find the most negative coordinates to avoid negative indizes |
812
|
0
|
|
|
|
|
|
my ($minX, $minY, $minZ); |
813
|
0
|
|
|
|
|
|
foreach (@{$this->{'atoms'}}) { |
|
0
|
|
|
|
|
|
|
814
|
0
|
0
|
|
|
|
|
$minX = $_->{'x'} if ($_->{'x'} < $minX); |
815
|
0
|
0
|
|
|
|
|
$minY = $_->{'y'} if ($_->{'y'} < $minY); |
816
|
0
|
0
|
|
|
|
|
$minZ = $_->{'z'} if ($_->{'z'} < $minZ); |
817
|
|
|
|
|
|
|
} |
818
|
0
|
|
|
|
|
|
$minX -= 2.5 * $maxR; |
819
|
0
|
|
|
|
|
|
$minY -= 2.5 * $maxR; |
820
|
0
|
|
|
|
|
|
$minZ -= 2.5 * $maxR; |
821
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
# distribute atoms in a grid with $maxR cell distance |
823
|
0
|
|
|
|
|
|
my (@grid, $maxI, $maxJ, $maxK); |
824
|
0
|
|
|
|
|
|
foreach (@{$this->{'atoms'}}) { |
|
0
|
|
|
|
|
|
|
825
|
0
|
|
|
|
|
|
my $i = int(($_->{'x'} - $minX) / $maxR); |
826
|
0
|
|
|
|
|
|
my $j = int(($_->{'y'} - $minY) / $maxR); |
827
|
0
|
|
|
|
|
|
my $k = int(($_->{'z'} - $minZ) / $maxR); |
828
|
0
|
|
|
|
|
|
push(@{$grid[$i][$j][$k]}, $_); |
|
0
|
|
|
|
|
|
|
829
|
0
|
0
|
|
|
|
|
$maxI = $i if ($i > $maxI); |
830
|
0
|
0
|
|
|
|
|
$maxJ = $j if ($j > $maxJ); |
831
|
0
|
0
|
|
|
|
|
$maxK = $k if ($k > $maxK); |
832
|
|
|
|
|
|
|
} |
833
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
# loop of grid cells and find bonds |
835
|
0
|
|
|
|
|
|
my ($i, $j, $k, $a, $b, $c); |
836
|
0
|
|
|
|
|
|
for ($i = 1 ; $i <= $maxI ; $i++) { |
837
|
0
|
|
|
|
|
|
for ($j = 1 ; $j <= $maxJ ; $j++) { |
838
|
0
|
|
|
|
|
|
for ($k = 1 ; $k <= $maxK ; $k++) { |
839
|
0
|
|
|
|
|
|
foreach (@{$grid[$i][$j][$k]}) { |
|
0
|
|
|
|
|
|
|
840
|
0
|
|
|
|
|
|
foreach $a (-1 .. 1) { |
841
|
0
|
|
|
|
|
|
foreach $b (-1 .. 1) { |
842
|
0
|
|
|
|
|
|
foreach $c (-1 .. 1) { |
843
|
0
|
|
|
|
|
|
$this->_atomToGrid($_, |
844
|
0
|
|
|
|
|
|
\@{$grid[$i + $a][$j + $b][$k + $c]}); |
845
|
|
|
|
|
|
|
} |
846
|
|
|
|
|
|
|
} |
847
|
|
|
|
|
|
|
} |
848
|
|
|
|
|
|
|
} |
849
|
|
|
|
|
|
|
} |
850
|
|
|
|
|
|
|
} |
851
|
|
|
|
|
|
|
} |
852
|
|
|
|
|
|
|
} |
853
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
########################################################################### |
855
|
|
|
|
|
|
|
sub _atomToGrid { |
856
|
0
|
|
|
0
|
|
|
my $this = shift; |
857
|
0
|
|
|
|
|
|
my $atom1 = shift; |
858
|
0
|
|
|
|
|
|
my $grid = shift; |
859
|
|
|
|
|
|
|
|
860
|
0
|
|
|
|
|
|
my $n1 = $atom1->{'nr'}; |
861
|
0
|
|
|
|
|
|
my ($x1, $y1, $z1) = ($atom1->{'x'}, $atom1->{'y'}, $atom1->{'z'}); |
862
|
0
|
|
|
|
|
|
my $ar1 = $AtomRadius{$atom1->{'label'}}; |
863
|
|
|
|
|
|
|
|
864
|
0
|
|
|
|
|
|
my $atom2; |
865
|
0
|
|
|
|
|
|
foreach $atom2 (@$grid) { |
866
|
0
|
|
|
|
|
|
my $n2 = $atom2->{'nr'}; |
867
|
0
|
0
|
|
|
|
|
next unless ($n1 < $n2); |
868
|
|
|
|
|
|
|
|
869
|
0
|
|
|
|
|
|
my $ar2 = $ar1 + $AtomRadius{$atom2->{'label'}}; |
870
|
0
|
|
|
|
|
|
$ar2 *= 1.2; |
871
|
0
|
|
|
|
|
|
$ar2 *= $ar2; |
872
|
|
|
|
|
|
|
|
873
|
0
|
|
|
|
|
|
my ($x2, $y2, $z2) = ($atom2->{'x'}, $atom2->{'y'}, $atom2->{'z'}); |
874
|
0
|
|
|
|
|
|
my ($dx, $dy, $dz) = ($x2 - $x1, $y2 - $y1, $z2 - $z1); |
875
|
0
|
|
|
|
|
|
my $dist = $dx * $dx + $dy * $dy + $dz * $dz; |
876
|
0
|
0
|
|
|
|
|
next if ($dist > $ar2); |
877
|
0
|
|
|
|
|
|
my $label = $atom1->{'nr'} . '_' . $atom2->{'nr'}; |
878
|
0
|
0
|
|
|
|
|
next if (exists($this->{'BLT'}->{$label})); |
879
|
0
|
|
|
|
|
|
my (%bond) = ('from' => $atom1, 'to' => $atom2); |
880
|
0
|
|
|
|
|
|
push(@{$this->{'bonds'}}, \%bond); |
|
0
|
|
|
|
|
|
|
881
|
|
|
|
|
|
|
} |
882
|
|
|
|
|
|
|
} |
883
|
|
|
|
|
|
|
|
884
|
|
|
|
|
|
|
########################################################################### |
885
|
|
|
|
|
|
|
|
886
|
|
|
|
|
|
|
1; |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
__END__ |