ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/openbabel/povrayformat.cpp
Revision: 2445
Committed: Wed Nov 16 21:22:51 2005 UTC (18 years, 9 months ago) by tim
File size: 22420 byte(s)
Log Message:
adding more readers/writers

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