source: ThirdParty/mpqc_open/src/lib/chemistry/molecule/molrender.cc@ 7516f6

Action_Thermostats Adding_MD_integration_tests Adding_StructOpt_integration_tests AutomationFragmentation_failures Candidate_v1.6.1 ChemicalSpaceEvaluator Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Exclude_Hydrogens_annealWithBondGraph Fix_Verbose_Codepatterns ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion Gui_displays_atomic_force_velocity JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool PythonUI_with_named_parameters Recreated_GuiChecks StoppableMakroAction TremoloParser_IncreasedPrecision
Last change on this file since 7516f6 was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100644
File size: 12.2 KB
Line 
1//
2// molrender.cc
3//
4// Copyright (C) 1996 Limit Point Systems, Inc.
5//
6// Author: Curtis Janssen <cljanss@limitpt.com>
7// Maintainer: LPS
8//
9// This file is part of the SC Toolkit.
10//
11// The SC Toolkit is free software; you can redistribute it and/or modify
12// it under the terms of the GNU Library General Public License as published by
13// the Free Software Foundation; either version 2, or (at your option)
14// any later version.
15//
16// The SC Toolkit is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Library General Public License for more details.
20//
21// You should have received a copy of the GNU Library General Public License
22// along with the SC Toolkit; see the file COPYING.LIB. If not, write to
23// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24//
25// The U.S. Government is granted a limited license as per AL 91-7.
26//
27
28#ifdef __GNUC__
29#pragma implementation
30#endif
31
32#include <math.h>
33
34#include <util/class/scexception.h>
35#include <util/misc/formio.h>
36#include <util/render/sphere.h>
37#include <util/render/polygons.h>
38#include <util/render/polylines.h>
39#include <util/render/color.h>
40#include <chemistry/molecule/molrender.h>
41#include <math/scmat/vector3.h>
42
43using namespace sc;
44
45////////////////////////////////////////////////////////////////
46// RenderedMolecule
47
48static ClassDesc RenderedMolecule_cd(
49 typeid(RenderedMolecule),"RenderedMolecule",1,"public RenderedObject",
50 0, 0, 0);
51
52RenderedMolecule::RenderedMolecule(const Ref<KeyVal>& keyval):
53 RenderedObject(keyval)
54{
55 mol_ << keyval->describedclassvalue("molecule");
56 atominfo_ << keyval->describedclassvalue("atominfo");
57 if (atominfo_.null()) {
58 atominfo_ = new AtomInfo();
59 }
60
61 if (mol_.null()) {
62 throw InputError("missing required input of type Molecule",
63 __FILE__, __LINE__, "molecule", 0,
64 class_desc());
65 }
66}
67
68RenderedMolecule::~RenderedMolecule()
69{
70}
71
72void
73RenderedMolecule::render(const Ref<Render>& render)
74{
75 object_->render(render);
76}
77
78////////////////////////////////////////////////////////////////
79// RenderedBallMolecule
80
81static ClassDesc RenderedBallMolecule_cd(
82 typeid(RenderedBallMolecule),"RenderedBallMolecule",1,"public RenderedMolecule",
83 0, create<RenderedBallMolecule>, 0);
84
85RenderedBallMolecule::RenderedBallMolecule(const Ref<KeyVal>& keyval):
86 RenderedMolecule(keyval)
87{
88 init();
89}
90
91RenderedBallMolecule::~RenderedBallMolecule()
92{
93}
94
95void
96RenderedBallMolecule::init()
97{
98 Ref<RenderedObjectSet> set = new RenderedObjectSet;
99
100 for (int i=0; i<mol_->natom(); i++) {
101 Ref<RenderedObject> atom = new RenderedSphere;
102
103 int Z = mol_->Z(i);
104
105 Ref<Material> material = new Material;
106 Color color(atominfo_->red(Z),
107 atominfo_->green(Z),
108 atominfo_->blue(Z));
109 material->diffuse().set(color);
110 material->ambient().set(color);
111
112 Ref<Transform> transform = new Transform;
113 transform->scale(atominfo_->vdw_radius(Z));
114 transform->translate(mol_->r(i,0), mol_->r(i,1), mol_->r(i,2));
115
116 atom->material(material);
117 atom->transform(transform);
118
119 set->add(atom);
120 }
121
122 object_ = set.pointer();
123}
124
125////////////////////////////////////////////////////////////////
126// RenderedStickMolecule
127
128static ClassDesc RenderedStickMolecule_cd(
129 typeid(RenderedStickMolecule),"RenderedStickMolecule",1,"public RenderedMolecule",
130 0, create<RenderedStickMolecule>, 0);
131
132RenderedStickMolecule::RenderedStickMolecule(const Ref<KeyVal>& keyval):
133 RenderedMolecule(keyval)
134{
135 use_color_ = keyval->booleanvalue("color");
136 if (keyval->error() != KeyVal::OK) use_color_ = 1;
137 init();
138}
139
140RenderedStickMolecule::~RenderedStickMolecule()
141{
142}
143
144static int
145bonding(const Ref<Molecule>& m, const Ref<AtomInfo>& a, int i, int j)
146{
147 SCVector3 ri(m->r(i));
148 SCVector3 rj(m->r(j));
149 double maxbonddist = 1.1*(m->atominfo()->atomic_radius(m->Z(i))
150 +m->atominfo()->atomic_radius(m->Z(j)));
151 SCVector3 r(ri-rj);
152 if (r.dot(r) <= maxbonddist*maxbonddist) return 1;
153 return 0;
154}
155
156void
157RenderedStickMolecule::init()
158{
159 int i,j;
160 int nbonds;
161 int natoms = mol_->natom();
162
163 Ref<RenderedPolylines> o = new RenderedPolylines;
164
165 // count the number of bonds
166 nbonds = 0;
167 for (i=0; i<natoms; i++) {
168 for (j=0; j<i; j++) {
169 if (bonding(mol_, atominfo_, i, j)) nbonds++;
170 }
171 }
172
173 int nvertex = natoms;
174 if (use_color_) nvertex += 2*nbonds;
175
176 // initialize the polylines
177 o->initialize(nvertex, nbonds, RenderedPolylines::Vertex);
178
179 // put the atoms in the vertex list
180 for (i=0; i<natoms; i++) {
181 o->set_vertex(i,
182 mol_->r(i,0),
183 mol_->r(i,1),
184 mol_->r(i,2));
185 if (use_color_) {
186 int Z = mol_->Z(i);
187 o->set_vertex_rgb(i,
188 atominfo_->red(Z),
189 atominfo_->green(Z),
190 atominfo_->blue(Z));
191 }
192 else {
193 o->set_vertex_rgb(i, 0.0, 0.0, 0.0);
194 }
195 }
196
197 // put the bonds in the line list
198 nbonds = 0;
199 int ibonds2 = natoms;
200 for (i=0; i<natoms; i++) {
201 SCVector3 ri(mol_->r(i));
202 int Zi = mol_->Z(i);
203 for (j=0; j<i; j++) {
204 if (bonding(mol_, atominfo_, i, j)) {
205 if (use_color_) {
206 SCVector3 rj(mol_->r(j));
207 int Zj = mol_->Z(j);
208 SCVector3 v = 0.5*(ri+rj);
209 o->set_vertex(ibonds2, v.x(), v.y(), v.z());
210 o->set_vertex_rgb(ibonds2,
211 atominfo_->red(Zi),
212 atominfo_->green(Zi),
213 atominfo_->blue(Zi));
214 o->set_vertex(ibonds2+1, v.x(), v.y(), v.z());
215 o->set_vertex_rgb(ibonds2+1,
216 atominfo_->red(Zj),
217 atominfo_->green(Zj),
218 atominfo_->blue(Zj));
219 o->set_polyline(nbonds, i, ibonds2, ibonds2+1, j);
220 ibonds2 += 2;
221 }
222 else {
223 o->set_polyline(nbonds, i, j);
224 }
225 nbonds++;
226 }
227 }
228 }
229
230 object_ = o.pointer();
231}
232
233////////////////////////////////////////////////////////////////
234// RenderedMolecularSurface
235
236static ClassDesc RenderedMolecularSurface_cd(
237 typeid(RenderedMolecularSurface),"RenderedMolecularSurface",1,"public RenderedMolecule",
238 0, create<RenderedMolecularSurface>, 0);
239
240RenderedMolecularSurface::RenderedMolecularSurface(const Ref<KeyVal>& keyval):
241 RenderedMolecule(keyval)
242{
243 surf_ << keyval->describedclassvalue("surface");
244 colorizer_ << keyval->describedclassvalue("colorizer");
245 if (colorizer_.null())
246 colorizer_ = new AtomProximityColorizer(mol_,atominfo_);
247 init(0);
248}
249
250RenderedMolecularSurface::~RenderedMolecularSurface()
251{
252}
253
254void
255RenderedMolecularSurface::init()
256{
257 init(1);
258}
259
260void
261RenderedMolecularSurface::init(int reinit_surf)
262{
263 int i, ij, j;
264 if (reinit_surf || !surf_->inited()) surf_->init();
265 int nvertex = surf_->nvertex();
266 int ntriangle = surf_->ntriangle();
267 int natom = mol_->natom();
268
269 Ref<RenderedPolygons> o = new RenderedPolygons;
270
271 o->initialize(nvertex, ntriangle, RenderedPolygons::Vertex);
272
273 // extract the atomic positions and colors into an array for rapid access
274 double *axyz = new double[3*natom];
275 double *argb = new double[3*natom];
276 double *arad = new double[natom];
277 ij = 0;
278 for (i=0; i<natom; i++) {
279 int Z = mol_->Z(i);
280 arad[i] = atominfo_->vdw_radius(Z);
281 for (j=0; j<3; j++,ij++) {
282 axyz[ij] = mol_->r(i,j);
283 argb[ij] = atominfo_->rgb(Z, j);
284 }
285 }
286
287 for (i=0; i<nvertex; i++) {
288 const SCVector3& v = surf_->vertex(i)->point();
289 double x = v[0];
290 double y = v[1];
291 double z = v[2];
292 o->set_vertex(i, x, y, z);
293 }
294 colorizer_->colorize(o);
295
296 delete[] axyz;
297 delete[] argb;
298 delete[] arad;
299
300 for (i=0; i<ntriangle; i++) {
301 o->set_face(i,
302 surf_->triangle_vertex(i,0),
303 surf_->triangle_vertex(i,1),
304 surf_->triangle_vertex(i,2));
305 }
306
307 object_ = o.pointer();
308}
309
310/////////////////////////////////////////////////////////////////////////////
311// MoleculeColorizer
312
313static ClassDesc MoleculeColorizer_cd(
314 typeid(MoleculeColorizer),"MoleculeColorizer",1,"public DescribedClass",
315 0, 0, 0);
316
317MoleculeColorizer::MoleculeColorizer(const Ref<Molecule>&mol)
318{
319 mol_ = mol;
320}
321
322MoleculeColorizer::MoleculeColorizer(const Ref<KeyVal>&keyval)
323{
324 mol_ << keyval->describedclassvalue("molecule");
325}
326
327MoleculeColorizer::~MoleculeColorizer()
328{
329}
330
331/////////////////////////////////////////////////////////////////////////////
332// AtomProximityColorizer
333
334static ClassDesc AtomProximityColorizer_cd(
335 typeid(AtomProximityColorizer),"AtomProximityColorizer",1,"public MoleculeColorizer",
336 0, create<AtomProximityColorizer>, 0);
337
338AtomProximityColorizer::AtomProximityColorizer(const Ref<Molecule> &mol,
339 const Ref<AtomInfo> &ai):
340 MoleculeColorizer(mol)
341{
342 atominfo_ = ai;
343}
344
345AtomProximityColorizer::AtomProximityColorizer(const Ref<KeyVal>&keyval):
346 MoleculeColorizer(keyval)
347{
348 atominfo_ << keyval->describedclassvalue("atominfo");
349 if (atominfo_.null()) {
350 atominfo_ = new AtomInfo();
351 }
352}
353
354AtomProximityColorizer::~AtomProximityColorizer()
355{
356}
357
358static void
359compute_color(int n, double* axyz, double* argb, double* arad,
360 double x, double y, double z, Color& c)
361{
362 int i, j;
363 const int maxclosest = 10;
364 int closest[maxclosest];
365 double distance2[maxclosest]; // the distance squared - radius squared
366 int nclosest;
367
368 if (n == 0) {
369 c.set_rgb(1.0, 1.0, 1.0);
370 return;
371 }
372
373 // find the closest atoms
374 nclosest = 0;
375 for (i=0; i<n; i++) {
376 SCVector3 r(axyz[0] - x, axyz[1] - y, axyz[2] - z);
377 double tmpdist2 = r.dot(r) - arad[i]*arad[i];
378// if (tmpdist2 < 1.e-6) {
379// c.set_rgb(argb[3*i], argb[3*i+1], argb[3*i+2]);
380// return;
381// }
382 if (tmpdist2 < 0.0) tmpdist2 = 0.0;
383 for (j=nclosest-1; j>=0; j--) {
384 if (distance2[j] <= tmpdist2) break;
385 if (j+1 < maxclosest) {
386 distance2[j+1] = distance2[j];
387 closest[j+1] = closest[j];
388 }
389 }
390 if (j+1 < maxclosest) {
391 distance2[j+1] = tmpdist2;
392 closest[j+1] = i;
393 if (maxclosest > nclosest) nclosest++;
394 }
395 axyz += 3;
396 }
397
398 if (nclosest == 1) {
399 c.set_rgb(argb[3*closest[0]],argb[3*closest[0]]+1,argb[3*closest[0]]+2);
400 return;
401 }
402
403 // average the colors of the closest atoms
404 for (i=0; i<nclosest; i++) distance2[i] = sqrt(distance2[i]);
405 for (i=1; i<nclosest; i++) distance2[i] -= distance2[0];
406 distance2[0] = 0.0;
407 for (i=0; i<nclosest; i++) distance2[i] = 2.0*exp(-distance2[i]);
408 double sum = 0.0;
409 for (i=0; i<nclosest; i++) sum += distance2[i];
410 sum = 1.0/sum;
411 for (i=0; i<nclosest; i++) distance2[i] *= sum;
412
413 double rgb[3] = {0.0, 0.0, 0.0};
414 for (i=0; i<nclosest; i++) {
415 for (j=0; j<3; j++) {
416 rgb[j] += distance2[i]*argb[3*closest[i] + j];
417 }
418 }
419 c.set_rgb(rgb[0], rgb[1], rgb[2]);
420}
421
422void
423AtomProximityColorizer::colorize(const Ref<RenderedPolygons> &poly)
424{
425 int natom = mol_->natom();
426 int nvertex = poly->nvertex();
427
428 int i,j,ij;
429 // extract the atomic positions and colors into an array for rapid access
430 double *axyz = new double[3*natom];
431 double *argb = new double[3*natom];
432 double *arad = new double[natom];
433 ij = 0;
434 for (i=0; i<natom; i++) {
435 int Z = mol_->Z(i);
436 arad[i] = atominfo_->vdw_radius(Z);
437 for (j=0; j<3; j++,ij++) {
438 axyz[ij] = mol_->r(i,j);
439 argb[ij] = atominfo_->rgb(Z, j);
440 }
441 }
442
443 for (i=0; i<nvertex; i++) {
444 const double *v = poly->vertex(i);
445 double x = v[0];
446 double y = v[1];
447 double z = v[2];
448 Color c;
449 compute_color(natom, axyz, argb, arad, x, y, z, c);
450 poly->set_vertex_color(i, c);
451 }
452
453 delete[] axyz;
454 delete[] argb;
455 delete[] arad;
456}
457
458/////////////////////////////////////////////////////////////////////////////
459
460// Local Variables:
461// mode: c++
462// c-file-style: "CLJ"
463// End:
Note: See TracBrowser for help on using the repository browser.