ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/openbabel/povrayformat.cpp
Revision: 1081
Committed: Thu Oct 19 20:49:05 2006 UTC (18 years, 6 months ago) by gezelter
File size: 25071 byte(s)
Log Message:
updated OpenBabel to version 2.0.2

File Contents

# Content
1 /**********************************************************************
2 Copyright (C) 2002 by Steffen Reith <streit@streit.cc>
3 Some portions Copyright (C) 2003-2005 by Geoffrey R. Hutchison
4 Some portions Copyright (C) 2004 by Chris Morley
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation version 2 of the License.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 ***********************************************************************/
15
16 /* ---- C includes ---- */
17 #include <math.h>
18 #include <time.h>
19 #include <stdlib.h>
20
21 /* ---- OpenBabel include ---- */
22 #include "config.h"
23 #include "mol.hpp"
24 #include "obconversion.hpp"
25
26 /* ---- C++ includes ---- */
27 #include <string>
28 #if defined(HAVE_SSTREAM)
29 #include <sstream>
30 #else
31 #include <strstream>
32 #endif
33
34 /* ---- Max. length of a atom-label ---- */
35 #define StrLen 32
36
37 /* ---- Define max. length of domainname ---- */
38 #define MAXDOMAINNAMELEN 256
39
40 /* ---- Maximal radius of an atom. Needed for bounding box ---- */
41 #define MAXRADIUS (double) 3.0
42
43 /* ---- Define index of first atom if needed ---- */
44 #ifndef MIN_ATOM
45 #define MIN_ATOM 1
46 #endif
47
48 /* ---- Size of time-string ---- */
49 #define TIME_STR_SIZE 64
50
51 /* ---- if x < = EPSILON then x = 0.0 ---- */
52 #define EPSILON (double) 1e-4
53
54 /* ---- Define makro for calculating x^2 ---- */
55 #ifdef SQUARE
56 #undef SQUARE
57 #endif
58 #define SQUARE(x) ((x) * (x))
59
60 /* ---- Define PI (if needed) ---- */
61 #ifndef PI
62 #define PI ((double) 3.1415926535897932384626433)
63 #endif
64
65 /* ---- Convert RAD to DEG ---- */
66 #define RAD2DEG(r) (((double) 180.0 * r) / PI)
67
68 using namespace std;
69 namespace OpenBabel
70 {
71
72 class PovrayFormat : public OBFormat
73 {
74 public:
75 //Register this format type ID
76 PovrayFormat()
77 {
78 OBConversion::RegisterFormat("pov",this);
79 }
80
81 virtual const char* Description() //required
82 {
83 return
84 "POV-Ray input format\n \
85 No comments yet\n";
86 };
87
88 virtual const char* SpecificationURL()
89 {return "http://www.povray.org/";}; //optional
90
91 //Flags() can return be any the following combined by | or be omitted if none apply
92 // NOTREADABLE READONEONLY NOTWRITABLE WRITEONEONLY
93 virtual unsigned int Flags()
94 {
95 return NOTREADABLE | WRITEONEONLY;
96 };
97
98 ////////////////////////////////////////////////////
99 /// The "API" interface functions
100 virtual bool WriteMolecule(OBBase* pOb, OBConversion* pConv);
101
102 ////////////////////////////////////////////////////
103 /// The "Convert" interface functions
104 virtual bool WriteChemObject(OBConversion* pConv)
105 {
106 //Retrieve the target OBMol
107 OBBase* pOb = pConv->GetChemObject();
108 OBMol* pmol = dynamic_cast<OBMol*> (pOb);
109 bool ret=false;
110 if(pmol)
111 ret=WriteMolecule(pmol,pConv);
112
113 std::string auditMsg = "OpenBabel::Write molecule ";
114 std::string description(Description());
115 auditMsg += description.substr( 0, description.find('\n') );
116 obErrorLog.ThrowError(__func__,
117 auditMsg,
118 obAuditMsg);
119 delete pOb;
120 return ret;
121 };
122 };
123
124 //Make an instance of the format class
125 PovrayFormat thePovrayFormat;
126
127 /* ---- Make a prefix from title of molecule ---- */
128 string MakePrefix(const char* title)
129 {
130 int pos; /* Position in prefix */
131 char *titleCpy = (char*) NULL;
132 char *str = (char*) NULL;
133 char *last = (char*) NULL;
134
135 /* ---- Copy molecule title to 'str' ---- */
136 if ((titleCpy = strdup(title)) == (char *) NULL)
137 return string("NoMemory");
138
139 /* --- Find last '/' and set 'str' to it if needed ----- */
140 last = strrchr(titleCpy, '/');
141 if (last != (char *) NULL)
142 str = (last + 1);
143 else
144 str = titleCpy;
145
146 /* ---- Check for nonempty string ---- */
147 if (strlen(str) == 0)
148 return string("InValid");
149
150 /* ---- Look for first . and replace with \0 ----- */
151 pos = 0;
152 while((str[pos] != '\0') && (str[pos] != '.'))
153 {
154
155 /* ---- Remove all tabs and spaces ---- */
156 if ((str[pos] == ' ') || (str[pos] == '\t'))
157 str[pos] = '_';
158
159 /* ---- Check next position ---- */
160 pos++;
161
162 }
163
164 /* ---- If we have found a '.' cut the string there ---- */
165 str[pos] = '\0';
166
167 /* ---- Cast to C++ string-type the above operations are a mess with C++ strings ---- */
168 string prefix(str);
169
170 /* ---- Free allocated memory ---- */
171 free(titleCpy);
172
173 /* ---- Return the prefix ---- */
174 return prefix;
175
176 }
177
178 void OutputHeader(ostream &ofs, OBMol &mol, string prefix)
179 {
180 time_t akttime; /* Systemtime */
181 char timestr[TIME_STR_SIZE + 1] = ""; /* Timestring */
182 size_t time_res; /* Result of strftime */
183
184 /* ---- Get the system-time ---- */
185 akttime = time((time_t *) NULL);
186 time_res = strftime(timestr,
187 TIME_STR_SIZE,
188 "%a %b %d %H:%M:%S %Z %Y",
189 localtime((time_t *) &akttime)
190 );
191
192 /* ---- Write some header information ---- */
193 ofs << "//Povray V3.1 code generated by Open Babel" << endl;
194 ofs << "//Author: Steffen Reith <streit@streit.cc>" << endl;
195
196 /* ---- Include timestamp in header ---- */
197 ofs << "//Date: " << timestr << endl << endl;
198
199 /* ---- Include header statement for babel ---- */
200 ofs << "//Include header for povray" << endl;
201 ofs << "#include \"babel31.inc\"" << endl << endl;
202
203 /* ---- You should do a spacefill model for molecules without bonds ---- */
204 if (mol.NumBonds() == 0)
205 {
206
207 /* ---- Check if a spacefill-model is selected ---- */
208 ofs << "#if (BAS | CST)\"" << endl;
209 ofs << "#warning \"Molecule without bonds!\"" << endl;
210 ofs << "#warning \"You should do a spacefill-model\"" << endl;
211 ofs << "#end" << endl << endl;
212
213 }
214
215 /* ---- Set version ---- */
216 ofs << "//Use PovRay3.1" << endl;
217 ofs << "#version 3.1;" << endl << endl;
218
219 /* ---- Print of name of molecule (#\b depends on size of babel.inc!) ---- */
220 ofs << "//Print name of molecule while rendering" << endl;
221 ofs << "#render \"\\b\\b " << mol.GetTitle() << "\\n\\n\"" << endl << endl;
222
223 }
224
225 void CalcBoundingBox(OBMol &mol,
226 double &min_x, double &max_x,
227 double &min_y, double &max_y,
228 double &min_z, double &max_z
229 )
230 {
231 /* ---- Init bounding-box variables ---- */
232 min_x = (double) 0.0;
233 max_x = (double) 0.0;
234 min_y = (double) 0.0;
235 max_y = (double) 0.0;
236 min_z = (double) 0.0;
237 max_z = (double) 0.0;
238
239 /* ---- Check all atoms ---- */
240 for(unsigned int i = 1; i <= mol.NumAtoms(); ++i)
241 {
242
243 /* ---- Get a pointer to ith atom ---- */
244 OBAtom *atom = mol.GetAtom(i);
245
246 /* ---- Check for minimal/maximal x-position ---- */
247 if (atom -> GetX() < min_x)
248 min_x = atom -> GetX();
249 if (atom -> GetX() > max_x)
250 max_x = atom -> GetX();
251
252 /* ---- Check for minimal/maximal y-position ---- */
253 if (atom -> GetY() < min_y)
254 min_y = atom -> GetY();
255 if (atom -> GetY() > max_y)
256 max_y = atom -> GetY();
257
258 /* ---- Check for minimal/maximal z-position ---- */
259 if (atom -> GetZ() < min_z)
260 min_z = atom -> GetZ();
261 if (atom -> GetZ() > max_z)
262 max_z = atom -> GetZ();
263
264 }
265
266 }
267
268 void OutputAtoms(ostream &ofs, OBMol &mol, string prefix)
269 {
270 /* ---- Write all coordinates ---- */
271 ofs << "//Coodinates of atoms 1 - " << mol.NumAtoms() << endl;
272 unsigned int i;
273 for(i = 1; i <= mol.NumAtoms(); ++i)
274 {
275
276 /* ---- Get a pointer to ith atom ---- */
277 OBAtom *atom = mol.GetAtom(i);
278
279 /* ---- Write position of atom i ---- */
280 ofs << "#declare " << prefix << "_pos_" << i << " = <"
281 << atom -> GetX() << ","
282 << atom -> GetY() << ","
283 << atom -> GetZ()
284 << ">;" << endl;
285
286 }
287
288 /* ---- Write povray-description of all atoms ---- */
289 ofs << endl << "//Povray-description of atoms 1 - " << mol.NumAtoms() << endl;
290 for(i = 1; i <= mol.NumAtoms(); ++i)
291 {
292
293 /* ---- Get a pointer to ith atom ---- */
294 OBAtom *atom = mol.GetAtom(i);
295
296 /* ---- Write full description of atom i ---- */
297 ofs << "#declare " << prefix << "_atom" << i << " = ";
298 ofs << "object {" << endl
299 << "\t Atom_" << etab.GetSymbol(atom->GetAtomicNum()) << endl
300 << "\t translate " << prefix << "_pos_" << i << endl << "\t }" << endl;
301
302 }
303
304 /* ---- Add empty line ---- */
305 ofs << endl;
306
307 }
308
309
310 void OutputBASBonds(ostream &ofs, OBMol &mol, string prefix)
311 {
312 /* ---- Write povray-description of all bonds---- */
313 for(unsigned int i = 0; i < mol.NumBonds(); ++i)
314 {
315
316 double x1,y1,z1,x2,y2,z2; /* Start and stop coordinates of a bond */
317 double dist; /* Distance between (x1|y1|z1) and (x2|y2|z2) */
318 double phi,theta; /* Angles between (x1|y1|z1) and (x2|y2|z2) */
319 double dy; /* Distance between (x1|0|z1) and (x2|0|z2) */
320
321 /* ---- Get a pointer to ith atom ---- */
322 OBBond *bond = mol.GetBond(i);
323
324 /* ---- Assign start of bond i ---- */
325 x1 = (bond -> GetBeginAtom()) -> GetX();
326 y1 = (bond -> GetBeginAtom()) -> GetY();
327 z1 = (bond -> GetBeginAtom()) -> GetZ();
328
329 /* ---- Assign end of bond i ---- */
330 x2 = (bond -> GetEndAtom()) -> GetX();
331 y2 = (bond -> GetEndAtom()) -> GetY();
332 z2 = (bond -> GetEndAtom()) -> GetZ();
333
334 /* ---- Calculate length of bond and (x1|0|z1) - (x2|0|z2) ---- */
335 dist = sqrt(SQUARE(x2-x1) + SQUARE(y2-y1) + SQUARE(z2-z1));
336 dy = sqrt(SQUARE(x2-x1) + SQUARE(z2-z1));
337
338 /* ---- Calculate Phi and Theta ---- */
339 phi = (double) 0.0;
340 theta = (double) 0.0;
341 if (fabs(dist) >= EPSILON)
342 phi = acos((y2-y1)/dist);
343 if (fabs(dy) >= EPSILON)
344 theta = acos((x2-x1)/dy);
345
346 /* ---- Full description of bond i ---- */
347 ofs << "#declare " << prefix << "_bond" << i
348 << " = object {" << endl << "\t bond_" << bond -> GetBondOrder() << endl;
349
350 /* ---- Scale bond if needed ---- */
351 if (fabs(dist) >= EPSILON)
352 {
353
354 /* ---- Print povray scale-statement (x-Axis) ---- */
355 ofs << "\t scale <" << dist << ",1.0000,1.0000>\n";
356
357 }
358
359 /* ---- Rotate (Phi) bond if needed ---- */
360 if (fabs(RAD2DEG(-phi) + (double) 90.0) >= EPSILON)
361 {
362
363 /* ---- Rotate along z-axis ---- */
364 ofs << "\t rotate <0.0000,0.0000,"
365 << RAD2DEG(-phi) + (double) 90.0
366 << ">" << endl;
367
368
369 }
370
371 /* ---- Check angle between (x1|0|z1) and (x2|0|z2) ---- */
372 if (theta >= EPSILON)
373 {
374
375 /* ---- Check direction ---- */
376 if ((z2 - z1) >= (double) 0.0)
377 {
378
379 /* ---- Rotate along y-Axis (negative) ---- */
380 ofs << "\t rotate <0.0000,"
381 << RAD2DEG((double) -1.0 * theta) << ",0.0000>"
382 << endl;
383
384 }
385 else
386 {
387
388 /* ---- Rotate along y-Axis (positive) ---- */
389 ofs << "\t rotate <0.0000,"
390 << RAD2DEG(theta) << ",0.0000>"
391 << endl;
392
393 }
394
395 }
396
397 /* ---- Translate bond to start ---- */
398 ofs << "\t translate " << prefix << "_pos_" << bond -> GetBeginAtomIdx()
399 << endl << "\t }" << endl;
400
401 }
402
403 }
404
405 void OutputCSTBonds(ostream &ofs, OBMol &mol, string prefix)
406 {
407 /* ---- Write povray-description of all bonds---- */
408 for(unsigned int i = 0; i < mol.NumBonds(); ++i)
409 {
410
411 double x1,y1,z1,x2,y2,z2; /* Start and stop coordinates of a bond */
412 double dist; /* Distance between (x1|y1|z1) and (x2|y2|z2) */
413 double phi,theta; /* Angles between (x1|y1|z1) and (x2|y2|z2) */
414 double dy; /* Distance between (x1|0|z1) and (x2|0|z2) */
415
416 /* ---- Get a pointer to ith atom ---- */
417 OBBond *bond = mol.GetBond(i);
418
419 /* ---- Assign start of bond i ---- */
420 x1 = (bond -> GetBeginAtom()) -> GetX();
421 y1 = (bond -> GetBeginAtom()) -> GetY();
422 z1 = (bond -> GetBeginAtom()) -> GetZ();
423
424 /* ---- Assign end of bond i ---- */
425 x2 = (bond -> GetEndAtom()) -> GetX();
426 y2 = (bond -> GetEndAtom()) -> GetY();
427 z2 = (bond -> GetEndAtom()) -> GetZ();
428
429 /* ---- Calculate length of bond and (x1|0|z1) - (x2|0|z2) ---- */
430 dist = sqrt(SQUARE(x2-x1) + SQUARE(y2-y1) + SQUARE(z2-z1));
431 dy = sqrt(SQUARE(x2-x1) + SQUARE(z2-z1));
432
433 /* ---- Calculate Phi and Theta ---- */
434 phi = (double) 0.0;
435 theta = (double) 0.0;
436 if (fabs(dist) >= EPSILON)
437 phi = acos((y2-y1)/dist);
438 if (fabs(dy) >= EPSILON)
439 theta = acos((x2-x1)/dy);
440
441 /* ---- Begin of description of bond i (for a capped sticks model) ---- */
442 ofs << "#declare " << prefix << "_bond" << i << " = object {" << endl;
443 ofs << "\t union {" << endl;
444
445 /* ---- Begin of Start-Half of Bond (i) ---- */
446 ofs << "\t object {" << endl << "\t bond_" << bond -> GetBondOrder() << "\n";
447
448 /* ---- Add a pigment - statement for start-atom of bond ---- */
449 ofs << "\t pigment{color Color_"
450 << bond -> GetBeginAtom() -> GetType()
451 << "}" << endl;
452
453 /* ---- Scale bond if needed ---- */
454 if (fabs((double) 2.0 * dist) >= EPSILON)
455 {
456
457 /* ---- Print povray scale-statement (x-Axis) ---- */
458 ofs << "\t scale <" << (double) 0.5 * dist << ",1.0000,1.0000>" << endl;
459
460 }
461
462 /* ---- Rotate (Phi) bond if needed ---- */
463 if (fabs(RAD2DEG(-phi) + (double) 90.0) >= EPSILON)
464 {
465
466 /* ---- Rotate along z-axis ---- */
467 ofs << "\t rotate <0.0000,0.0000,"
468 << RAD2DEG(-phi) + (double) 90.0
469 << ">" << endl;
470
471 }
472
473 /* ---- Check angle between (x1|0|z1) and (x2|0|z2) ---- */
474 if (theta >= EPSILON)
475 {
476
477 /* ---- Check direction ---- */
478 if ((z2 - z1) >= (double) 0.0)
479 {
480
481 /* ---- Rotate along y-Axis (negative) ---- */
482 ofs << "\t rotate <0.0000,"
483 << RAD2DEG((double) -1.0 *theta) << ",0.0000>"
484 << endl;
485
486 }
487 else
488 {
489
490 /* ---- Rotate along y-Axis (positive) ---- */
491 ofs << "\t rotate <0.0000," << RAD2DEG(theta) << ",0.0000>" << endl;
492
493 }
494
495 }
496
497 /* ---- Translate bond to start ---- */
498
499 ofs << "\t translate " << prefix << "_pos_" << bond -> GetBeginAtomIdx() << endl;
500
501 /* ---- End of description of Start-Bond ---- */
502 ofs << "\t }" << endl;
503
504 /* ---- Begin of End-Half of Bond i ---- */
505 ofs << "\t object {" << endl << "\t bond_" << bond -> GetBondOrder() << endl;
506
507 /* ---- Add a pigment - statement for end-atom of bond i ---- */
508 ofs << "\t pigment{color Color_"
509 << bond -> GetEndAtom() -> GetType()
510 << "}" << endl;
511
512 /* ---- Scale bond if needed ---- */
513 if (fabs((double) 2.0 * dist) >= EPSILON)
514 {
515
516 /* ---- Print povray scale-statement (x-Axis) ---- */
517 ofs << "\t scale <" << (double) 0.5 * dist << ",1.0000,1.0000>" << endl;
518
519 }
520
521 /* ---- Rotate (Phi) bond if needed ---- */
522 if (fabs(RAD2DEG(-phi) + (double) 270.0) >= EPSILON)
523 {
524
525 /* ---- Rotate along z-axis (oposite to start half) ---- */
526 ofs << "\t rotate <0.0000,0.0000,"
527 << (RAD2DEG(-phi) + (double) 90.0) + (double) 180.0
528 << ">" << endl;
529
530 }
531
532 /* ---- Check angle between (x1|0|z1) and (x2|0|z2) ---- */
533 if (fabs(theta) >= EPSILON)
534 {
535
536 /* ---- Check direction ---- */
537 if ((z2 - z1) >= (double) 0.0)
538 {
539
540 /* ---- Rotate along y-Axis (negative) (oposite orientation) ---- */
541 ofs << "\t rotate <0.0000,"
542 << RAD2DEG((double) -1.0 * theta)
543 << ",0.0000>"
544 << endl;
545
546 }
547 else
548 {
549
550 /* ---- Rotate along y-Axis (positive) (oposite orientation) ---- */
551 ofs << "\t rotate <0.0000," << RAD2DEG(theta) << ",0.0000>" << endl;
552
553 }
554
555 }
556
557 /* ---- Translate bond to end ---- */
558 ofs << "\t translate " << prefix << "_pos_" << bond -> GetEndAtomIdx() << endl;
559
560 /* ---- End of description of End-Bond ---- */
561 ofs << "\t }" << endl;
562
563 /* ---- End of description of bond i ---- */
564 ofs << "\t }" << endl << "\t }" << endl << endl;
565
566 }
567
568 }
569
570 void OutputUnions(ostream &ofs, OBMol &mol, string prefix)
571 {
572 /* ---- Build union of all atoms ---- */
573 ofs << endl << "//All atoms of molecule " << prefix << endl;
574 ofs << "#ifdef (TRANS)" << endl;
575 ofs << "#declare " << prefix << "_atoms = merge {" << endl;
576 ofs << "#else" << endl;
577 ofs << "#declare " << prefix << "_atoms = union {" << endl;
578 ofs << "#end //(End of TRANS)" << endl;
579
580 /* ---- Write definition of all atoms ---- */
581 for(unsigned int i = 1; i <= mol.NumAtoms(); ++i)
582 {
583
584 /* ---- Write definition of atom i ---- */
585 ofs << "\t object{" << prefix << "_atom" << i << "}" << endl;
586
587 }
588 ofs << "\t }" << endl << endl;
589
590 /* ---- Check for number of bonds ---- */
591 if(mol.NumBonds() > 0)
592 {
593
594 /* ---- Do a BAS or CST model ? ---- */
595 ofs << "//Bonds only needed for ball and sticks or capped sticks models" << endl;
596 ofs << "#if (BAS | CST)" << endl;
597 ofs << "#declare " << prefix <<"_bonds = union {" << endl;
598
599 /* ---- Description of all bonds ---- */
600 for(unsigned int i = 0; i < mol.NumBonds(); ++i)
601 {
602
603 /* ---- Write Definition of Bond i ---- */
604 ofs << "\t object{" << prefix << "_bond" << i << "}" << endl;
605
606 }
607
608 /* ---- End of povray-conditional for ball and sticks ---- */
609 ofs << "\t }" << endl << "#end" << endl << endl;
610
611 }
612
613 }
614
615 void OutputMoleculeBonds(ostream &ofs,
616 string prefix,
617 double min_x, double max_x,
618 double min_y, double max_y,
619 double min_z, double max_z
620 )
621 {
622 /* ---- Write a comment ---- */
623 ofs << endl << "//Definition of molecule " << prefix << endl;
624
625 /* ---- Check for space-fill model ---- */
626 ofs << "#if (SPF)" << endl;
627 ofs << "#declare " << prefix << " = object{"
628 << endl << "\t " << prefix << "_atoms" << endl;
629
630 /* ---- Here we do BAS oder CST models ---- */
631 ofs << "#else" << endl;
632 ofs << "#declare " << prefix << " = union {" << endl;
633
634 /* ---- Add all Atoms ---- */
635 ofs << "\t object{" << prefix << "_atoms}" << endl;
636
637 /* ---- Add difference between bonds and atoms ---- */
638 ofs << "#if (BAS | CST)//(Not really needed at moment!)" << endl;
639
640 /* ---- Use disjunct objects for transparent pics? ---- */
641 ofs << "#if (TRANS)" << endl;
642 ofs << "\t difference {" << endl;
643 ofs << "\t object{" << prefix << "_bonds}" << endl
644 << "\t object{" << prefix << "_atoms}" << endl
645 << "\t }" << endl;
646
647 /* ---- Do a solid model ? ---- */
648 ofs << "#else" << endl;
649 ofs << "\t object{" << prefix << "_bonds}" << endl;
650 ofs << "#end //(End of TRANS)" << endl;
651 ofs << "#end //(End of (BAS|CST))" << endl;
652
653 /* ---- End of CST or BAS model ---- */
654 ofs << "#end //(End of SPF)" << endl;
655
656 /* ---- Add comment (bounding box) ---- */
657 ofs << "//\t bounded_by {" << endl
658 << "//\t box {" << endl
659 << "//\t <"
660 << min_x - MAXRADIUS << ","
661 << min_y - MAXRADIUS << ","
662 << min_z - MAXRADIUS << ">" << endl;
663
664 ofs << "//\t <"
665 << max_x + MAXRADIUS << ","
666 << max_y + MAXRADIUS << ","
667 << max_z + MAXRADIUS << ">" << endl;
668
669 ofs << "\t }" << endl << endl;
670
671 }
672
673 void OutputMoleculeNoBonds(ostream &ofs, string prefix)
674 {
675 /* ---- Print description of molecule without bonds ---- */
676 ofs << endl << "//Definition of Molecule " << prefix << " (no bonds)" << endl;
677 ofs << "#declare " << prefix << " = object {" << prefix << "_atoms}" << endl << endl;
678
679 }
680
681 void OutputCenterComment(ostream &ofs,
682 string prefix,
683 double min_x, double max_x,
684 double min_y, double max_y,
685 double min_z, double max_z
686 )
687 {
688 /* ---- Print center comment (Warn: Vector is multiplied by -1.0)---- */
689 ofs << "//Center of molecule " << prefix << " (bounding box)" << endl;
690 ofs << "#declare " << prefix << "_center = <"
691 << (double) -1.0 * (min_x + max_x) / (double) 2.0 << ","
692 << (double) -1.0 * (min_y + max_y) / (double) 2.0 << ","
693 << (double) -1.0 * (min_z + max_z) / (double) 2.0 << ">" << endl << endl;
694 }
695
696 ////////////////////////////////////////////////////////////////
697
698 bool PovrayFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
699 {
700 OBMol* pmol = dynamic_cast<OBMol*>(pOb);
701 if(pmol==NULL)
702 return false;
703
704 //Define some references so we can use the old parameter names
705 ostream &ofs = *pConv->GetOutStream();
706 OBMol &mol = *pmol;
707 const char* title = pmol->GetTitle();
708
709 static long num = 0;
710 double min_x, max_x, min_y, max_y, min_z, max_z; /* Edges of bounding box */
711 string prefix;
712
713 /* ---- We use the molecule-title as our prefix ---- */
714 if(title != (const char*) NULL)
715 prefix = MakePrefix(title);
716 else if (mol.GetTitle() != (const char *) NULL)
717 prefix = MakePrefix(mol.GetTitle());
718 else
719 prefix = MakePrefix("Unknown");
720
721 /* ---- Check if we have already written a molecule to this file ---- */
722 if (num == 0)
723 {
724
725 /* ---- Print the header ---- */
726 OutputHeader(ofs, mol, prefix);
727
728 }
729 else
730 {
731
732 /* ---- Convert the unique molecule-number to a string and set the prefix ---- */
733 #if defined(HAVE_SSTREAM)
734 ostringstream numStr;
735 numStr << num << ends;
736 prefix += numStr.str().c_str();
737 #else
738
739 ostrstream numStr;
740 numStr << num << ends;
741 prefix += numStr.str();
742 #endif
743
744 }
745
746 /* ---- Print positions and descriptions of all atoms ---- */
747 OutputAtoms(ofs, mol, prefix);
748
749 /* ---- Check #bonds ---- */
750 if (mol.NumBonds() > 0)
751 {
752
753 /* ---- Write an comment ---- */
754 ofs << "//Povray-description of bonds 1 - " << mol.NumBonds() << endl;
755
756 /* ---- Do a ball and sticks model? ---- */
757 ofs << "#if (BAS)" << endl;
758
759 /* ---- Print bonds using "ball and sticks style" ---- */
760 OutputBASBonds(ofs, mol, prefix);
761
762 /* ---- End of povray-conditional for ball and sticks ---- */
763 ofs << "#end //(BAS-Bonds)" << endl << endl;
764
765 /* ---- Do a capped-sticks model? ---- */
766 ofs << "#if (CST)" << endl;
767
768 /* ---- Print bonds using "capped sticks style" ---- */
769 OutputCSTBonds(ofs, mol, prefix);
770
771 /* ---- End of povray-conditional for capped sticks ---- */
772 ofs << "#end // (CST-Bonds)" << endl << endl;
773
774 }
775
776 /* ---- Print out unions of atoms and bonds ---- */
777 OutputUnions(ofs, mol, prefix);
778
779 /* ---- Calculate bounding-box ---- */
780 CalcBoundingBox(mol, min_x, max_x, min_y, max_y, min_z, max_z);
781
782 /* ---- Check #bonds ---- */
783 if (mol.NumBonds() > 0)
784 {
785
786 /* ---- Print out description of molecule ---- */
787 OutputMoleculeBonds(ofs,
788 prefix,
789 min_x, max_x,
790 min_y, max_y,
791 min_z, max_z);
792
793 }
794 else
795 {
796
797 /* ---- Now we can define the molecule without bonds ---- */
798 OutputMoleculeNoBonds(ofs, prefix);
799
800 }
801
802 /* ---- Insert declaration for centering the molecule ---- */
803 OutputCenterComment(ofs,
804 prefix,
805 min_x, max_x,
806 min_y, max_y,
807 min_z, max_z);
808
809 /* ---- Increment the static molecule output-counter ---- */
810 num++;
811
812 /* ---- Everything is ok! ---- */
813 return(true);
814 }
815
816 } //namespace OpenBabel