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

File Contents

# User Rev Content
1 tim 2445 /**********************************************************************
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 gezelter 3057 /* ---- C includes ---- */
17     #include <math.h>
18     #include <time.h>
19     #include <stdlib.h>
20 tim 2445
21 gezelter 3057 /* ---- 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 tim 2445 using namespace std;
69     namespace OpenBabel
70     {
71    
72 gezelter 3057 class PovrayFormat : public OBFormat
73     {
74     public:
75     //Register this format type ID
76     PovrayFormat()
77     {
78     OBConversion::RegisterFormat("pov",this);
79     }
80 tim 2445
81 gezelter 3057 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 tim 2445 /* ---- 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