Source code: joelib/io/types/POVRay.java
1 ///////////////////////////////////////////////////////////////////////////////
2 // Filename: $RCSfile: POVRay.java,v $
3 // Purpose: Reader/Writer for SDF files.
4 // Language: Java
5 // Compiler: JDK 1.4
6 // Authors: Joerg K. Wegner
7 // Version: $Revision: 1.19 $
8 // $Date: 2003/08/22 15:56:18 $
9 // $Author: wegner $
10 //
11 // Copyright (c) Dept. Computer Architecture, University of Tuebingen, Germany
12 //
13 // This program is free software; you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation version 2 of the License.
16 //
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU General Public License for more details.
21 ///////////////////////////////////////////////////////////////////////////////
22 package joelib.io.types;
23
24 import cformat.PrintfStream;
25
26 import joelib.data.JOEElementTable;
27
28 import joelib.desc.DescResult;
29 import joelib.desc.DescriptorException;
30 import joelib.desc.DescriptorHelper;
31
32 import joelib.io.MoleculeFileType;
33
34 import joelib.math.XYZVector;
35
36 import joelib.molecule.JOEAtom;
37 import joelib.molecule.JOEBond;
38 import joelib.molecule.JOEMol;
39
40 import joelib.molecule.types.AtomProperties;
41 import joelib.molecule.types.AtomPropertyColoring;
42
43 import joelib.ring.JOERing;
44
45 import joelib.util.JHM;
46 import joelib.util.JOEHelper;
47
48 import joelib.util.iterator.AtomIterator;
49 import joelib.util.iterator.NbrAtomIterator;
50
51 import wsi.ra.tool.PropertyHolder;
52
53 /*==========================================================================*
54 * IMPORTS
55 *========================================================================== */
56 import java.awt.Color;
57
58 import java.io.IOException;
59 import java.io.InputStream;
60 import java.io.OutputStream;
61
62 import java.util.Vector;
63
64 import org.apache.log4j.Category;
65
66
67 /*==========================================================================*
68 * CLASS DECLARATION
69 *========================================================================== */
70
71 /**
72 * Reader/Writer for Persitance Of Vision Raytracer (POVRay) files.
73 *
74 * @author wegnerj
75 * @license GPL
76 * @cvsversion $Revision: 1.19 $, $Date: 2003/08/22 15:56:18 $
77 * @cite povray
78 */
79 public class POVRay implements MoleculeFileType
80 {
81 //~ Static fields/initializers /////////////////////////////////////////////
82
83 /*-------------------------------------------------------------------------*
84 * public static member variables
85 *------------------------------------------------------------------------- */
86
87 /**
88 * Description of the Field
89 */
90 public final static int BALL_AND_STICK = 0;
91 public final static String BALL_AND_STICK_S = "ball_and_stick";
92
93 /**
94 * Description of the Field
95 */
96 public final static int SPHERE = 1;
97 public final static String SPHERE_S = "sphere";
98
99 /**
100 * Description of the Field
101 */
102 public final static int STICK = 2;
103 public final static String STICK_S = "stick";
104
105 /**
106 * Description of the Field
107 */
108 public final static int DEFAULT_OUTPUT_TYPE = BALL_AND_STICK;
109
110 /*-------------------------------------------------------------------------*
111 * private static member variables
112 *------------------------------------------------------------------------- */
113
114 /**
115 * Obtain a suitable logger.
116 */
117 private static Category logger = Category.getInstance(
118 "joelib.io.types.POVRay");
119 private final static String version = "$Revision: 1.19 $";
120
121 /**
122 * Description of the Field
123 */
124 private final static String description = new String(
125 "Persistence Of Vision (POV) Ray Tracer");
126 private final static String[] extensions = new String[]{"pov"};
127
128 //~ Instance fields ////////////////////////////////////////////////////////
129
130 // variables for property coloring
131 private AtomPropertyColoring aPropColoring = new AtomPropertyColoring();
132 private JOEElementTable etab = JOEElementTable.instance();
133
134 /*-------------------------------------------------------------------------*
135 * private member variables
136 *------------------------------------------------------------------------- */
137
138 // private LineNumberReader lnr;
139 private PrintfStream ps;
140 private String atomProperty2Use = null;
141
142 // private AtomProperties data=null;
143 // private boolean dataInitialised=false;
144 // private double minDataValue;
145 // private double maxDataValue;
146 // private Color minColor = new Color(0.0f,0.0f,1.0f);
147 // private Color maxColor = new Color(1.0f,0.0f,0.0f);
148 private boolean usePropertyColoring = false;
149 private boolean writeAromaticRings = true;
150 private boolean writePorbitals = false;
151 private double atomResizeFactor = 0.25;
152 private double biggerBondRadius = 0.3;
153 private double maxX;
154 private double maxY;
155 private double maxZ;
156 private double minX;
157 private double minY;
158 private double minZ;
159 private double mx;
160 private double my;
161 private double mz;
162 private double smallerBondRadius = 0.175;
163 private int moleculeCounter = 1;
164 private int outputType = DEFAULT_OUTPUT_TYPE;
165
166 //~ Methods ////////////////////////////////////////////////////////////////
167
168 /*-------------------------------------------------------------------------*
169 * constructor
170 *------------------------------------------------------------------------- */
171 /*-------------------------------------------------------------------------*
172 * public methods
173 *------------------------------------------------------------------------- */
174
175 /**
176 * Sets the outputType attribute of the POVRay object
177 *
178 * @param _outputType The new outputType value
179 */
180 public void setOutputType(int _outputType)
181 {
182 outputType = _outputType;
183 }
184
185 /**
186 * Gets the outputType attribute of the POVRay object
187 *
188 * @return The outputType value
189 */
190 public int getOutputType()
191 {
192 return outputType;
193 }
194
195 /**
196 * Description of the Method
197 *
198 * @exception IOException Description of the Exception
199 */
200 public void closeReader() throws IOException
201 {
202 }
203
204 /**
205 * Description of the Method
206 *
207 * @exception IOException Description of the Exception
208 */
209 public void closeWriter() throws IOException
210 {
211 ps.close();
212 }
213
214 /**
215 * Description of the Method
216 *
217 * @param is Description of the Parameter
218 * @exception IOException Description of the Exception
219 */
220 public void initReader(InputStream is) throws IOException
221 {
222 // lnr = new LineNumberReader(new InputStreamReader(is));
223 }
224
225 /**
226 * Description of the Method
227 *
228 * @param os Description of the Parameter
229 * @exception IOException Description of the Exception
230 */
231 public void initWriter(OutputStream os) throws IOException
232 {
233 ps = new PrintfStream(os);
234
235 ps.println("// Creator: " + this.getClass().getName() + " " + version);
236 ps.println("// Author: Joerg K. Wegner");
237 ps.println("// Version: POV-Ray 3.1" + JHM.eol);
238
239 ps.println("#include \"shapes.inc\"");
240 ps.println("#include \"colors.inc\"");
241 ps.println("#include \"textures.inc\"" + JHM.eol);
242
243 ps.println("// brighten up colors");
244 ps.println("global_settings {assumed_gamma 1.4}");
245 ps.println("// set background color");
246 ps.println("background {colour<0.0, 0.0, 0.3>}" + JHM.eol);
247
248 initProperties();
249 }
250
251 /**
252 * Description of the Method
253 *
254 * @return Description of the Return Value
255 */
256 public String inputDescription()
257 {
258 return description;
259 }
260
261 /**
262 * Description of the Method
263 *
264 * @return Description of the Return Value
265 */
266 public String[] inputFileExtensions()
267 {
268 return extensions;
269 }
270
271 /**
272 * Description of the Method
273 *
274 * @return Description of the Return Value
275 */
276 public String outputDescription()
277 {
278 return description;
279 }
280
281 /**
282 * Description of the Method
283 *
284 * @return Description of the Return Value
285 */
286 public String[] outputFileExtensions()
287 {
288 return extensions;
289 }
290
291 /**
292 * Reads an molecule entry as (unparsed) <tt>String</tt> representation.
293 *
294 * @return <tt>null</tt> if the reader contains no more
295 * relevant data. Otherwise the <tt>String</tt> representation of the
296 * whole molecule entry is returned.
297 * @exception IOException typical IOException
298 */
299 public String read() throws IOException
300 {
301 logger.error(
302 "Reading POVRay data as String representation is not implemented yet !!!");
303
304 return null;
305 }
306
307 /**
308 * Description of the Method
309 *
310 * @param mol Description of the Parameter
311 * @return Description of the Return Value
312 * @exception IOException Description of the Exception
313 */
314 public synchronized boolean read(JOEMol mol) throws IOException
315 {
316 return read(mol, null);
317 }
318
319 /**
320 * Loads an molecule in MDL SD-MOL format and sets the title.
321 * If <tt>title</tt> is <tt>null</tt> the title line in
322 * the molecule file is used.
323 *
324 * @param mol Description of the Parameter
325 * @param title Description of the Parameter
326 * @return Description of the Return Value
327 * @exception IOException Description of the Exception
328 */
329 public synchronized boolean read(JOEMol mol, String title)
330 throws IOException
331 {
332 return false;
333 }
334
335 /**
336 * Description of the Method
337 *
338 * @return Description of the Return Value
339 */
340 public boolean readable()
341 {
342 return false;
343 }
344
345 public boolean skipReaderEntry() throws IOException
346 {
347 return true;
348 }
349
350 /**
351 * Description of the Method
352 *
353 * @param mol Description of the Parameter
354 * @return Description of the Return Value
355 * @exception IOException Description of the Exception
356 */
357 public boolean write(JOEMol mol) throws IOException
358 {
359 return write(mol, null);
360 }
361
362 /**
363 * Description of the Method
364 *
365 * @param mol Description of the Parameter
366 * @param title Description of the Parameter
367 * @return Description of the Return Value
368 * @exception IOException Description of the Exception
369 */
370 public boolean write(JOEMol mol, String title) throws IOException
371 {
372 if ((atomProperty2Use != null) && usePropertyColoring)
373 {
374 //useAtomPropertyColoring(mol, atomProperty2Use);
375 aPropColoring.useAtomPropertyColoring(mol, atomProperty2Use);
376 }
377 else
378 {
379 aPropColoring.usePlainColoring();
380 }
381
382 // useAtomPropertyColoring(mol, "A_QTOT");
383 // useAtomPropertyColoring(mol, "A_POLARIZABILITY");
384 StringBuffer povMolecule = new StringBuffer((mol.numAtoms() * 100) +
385 (mol.numBonds() * 100));
386
387 // calculate molecule centrum new everytime
388 mx = my = mz = 0.0;
389 minX = minY = minZ = Double.MAX_VALUE;
390 maxX = maxY = maxZ = -Double.MAX_VALUE;
391
392 // get molecule information
393 write2Buffer(mol, povMolecule);
394
395 // write moelcule informations
396 ps.println("// minimum values");
397 ps.println("#declare minX = " + minX + ";");
398 ps.println("#declare minY = " + minY + ";");
399 ps.println("#declare minZ = " + minZ + ";");
400 ps.println("// maximum values");
401 ps.println("#declare maxX = " + maxX + ";");
402 ps.println("#declare maxY = " + maxY + ";");
403 ps.println("#declare maxZ = " + maxZ + ";");
404 ps.println("// delta values");
405 ps.println("#declare deltaX = " + Math.abs(maxX - minX) + ";");
406 ps.println("#declare deltaY = " + Math.abs(maxY - minY) + ";");
407 ps.println("#declare deltaZ = " + Math.abs(maxZ - minZ) + ";");
408 ps.println("// average values");
409 ps.println("#declare mx = " + mx + ";");
410 ps.println("#declare my = " + my + ";");
411 ps.println("#declare mz = " + mz + ";");
412 ps.println();
413
414 if (outputType == BALL_AND_STICK)
415 {
416 ps.println("// atom resize factor");
417 ps.println("#declare atomResizeFactor = " + atomResizeFactor + ";");
418 }
419
420 // use camera and light only for the first molecule
421 String isComment = "";
422
423 if (moleculeCounter > 1)
424 {
425 isComment = "//";
426 }
427
428 ps.println("// Camera" + JHM.eol + "camera {");
429 ps.println(isComment +
430 " location <mx, my, mz-(max(deltaX,deltaY)*1.4)> // use maximum window with a resize factor of 1.4");
431 ps.println(isComment + " direction <0.0, 0.0, 1.0>");
432 ps.println(isComment + " look_at <mx, my, 1.0>" + JHM.eol + "}" +
433 JHM.eol);
434
435 ps.println("// Light");
436 ps.println(isComment + " light_source {<" + ((mx < 0.0) ? "-" : "") +
437 "mx*2, " + ((my < 0.0) ? "-" : "") +
438 "my*2, mz-max(deltaX,deltaY)>");
439 ps.println(isComment + " colour White");
440 ps.println(isComment + "}" + JHM.eol);
441
442 // define molecule in povray
443 ps.println("// Molecule " + moleculeCounter + ":" + mol.getTitle());
444 ps.println("#declare");
445 ps.println("Molecule" + moleculeCounter + " = union{");
446 ps.println(povMolecule.toString());
447 ps.println("}");
448
449 // draw molecule in povray
450 ps.println();
451 ps.println("object { Molecule" + moleculeCounter + JHM.eol);
452
453 // ps.println(" translate <-mx,-my,-mz>"+JHM.eol);
454 // ps.println(" rotate y*clock*10"+JHM.eol);
455 // ps.println(" translate <mx,my,mz>"+JHM.eol);
456 ps.println("}" + JHM.eol);
457
458 moleculeCounter++;
459
460 return (true);
461 }
462
463 /**
464 * Description of the Method
465 *
466 * @return Description of the Return Value
467 */
468 public boolean writeable()
469 {
470 return true;
471 }
472
473 //public void useAtomPropertyColoring(JOEMol mol, String property)
474 //{
475 // aPropColoring.useAtomPropertyColoring(mol, property);
476
477 /* DescResult result=null;
478 try
479 {
480 result= DescriptorHelper.instance().descFromMol(mol,property);
481 }
482 catch (DescriptorException e)
483 {
484 logger.error(e.toString());
485 usePropertyColoring=false;
486 }
487
488
489 if(result==null)logger.error("Can't get atom property "+property+" for atom coloring in "+this.getClass().getName());
490 if(JOEHelper.hasInterface(result, "AtomProperties"))
491 {
492 dataInitialised=true;
493 data = (AtomProperties)result;
494 minDataValue=Double.MAX_VALUE;
495 maxDataValue=-Double.MAX_VALUE;
496 double value;
497 for(int i=1;i<=mol.numAtoms();i++)
498 {
499 value = data.getDoubleValue(i);
500 if(value>maxDataValue)maxDataValue=value;
501 if(value<minDataValue)minDataValue=value;
502 // System.out.println(""+i+": "+value);
503 }
504
505 usePropertyColoring=true;
506 }
507 else
508 {
509 logger.error("Data for atom coloring has wrong format in "+this.getClass().getName());
510 }*/
511
512 //}
513 //private Color getAtomColor(JOEAtom atom)
514 //{
515 // return aPropColoring.getAtomColor(atom);
516
517 /* if(usePropertyColoring)
518 {
519 double delta = maxDataValue-minDataValue;
520 //System.out.println("data:"+data);
521
522 float val = (float) ((data.getDoubleValue(atom.getIdx())-minDataValue)/delta);
523 float r= ((maxColor.getRed()-minColor.getRed())*val +minColor.getRed())/255.0f;
524 float g=((maxColor.getGreen()-minColor.getGreen())*val +minColor.getGreen())/255.0f;
525 float b=((maxColor.getBlue()-minColor.getBlue())*val +minColor.getBlue())/255.0f;
526 // System.out.println(""+atom.getIdx()+": "+data.getDoubleValue(atom.getIdx())+": "+val);
527 // System.out.println("rgb:"+r+" "+g+" "+b);
528 return new Color(r,g,b);
529 }
530 else
531 {
532 int atomNum = atom.getAtomicNum();
533 return etab.getColor(atomNum);
534 }*/
535
536 //}
537
538 /**
539 * Description of the Method
540 *
541 * @exception IOException Description of the Exception
542 */
543 private void initProperties()
544 {
545 String value;
546
547 value = PropertyHolder.instance().getProperty(this, "output");
548
549 if (value == null)
550 {
551 outputType = DEFAULT_OUTPUT_TYPE;
552 }
553 else if (value.equalsIgnoreCase(STICK_S))
554 {
555 outputType = STICK;
556 }
557 else if (value.equalsIgnoreCase(SPHERE_S))
558 {
559 outputType = SPHERE;
560 }
561 else if (value.equalsIgnoreCase(BALL_AND_STICK_S))
562 {
563 outputType = BALL_AND_STICK;
564 }
565 else
566 {
567 logger.error("Use output type :" + STICK_S + ", " + SPHERE_S +
568 " and " + BALL_AND_STICK_S);
569 outputType = DEFAULT_OUTPUT_TYPE;
570 }
571
572 value = PropertyHolder.instance().getProperty(this,
573 "atomPropertyColoring");
574
575 if (((value != null) && value.equalsIgnoreCase("true")))
576 {
577 usePropertyColoring = true;
578 }
579 else
580 {
581 usePropertyColoring = false;
582 }
583
584 atomProperty2Use = null;
585 value = PropertyHolder.instance().getProperty(this, "atomProperty");
586
587 Vector atomPropDescs = DescriptorHelper.instance().getAtomPropDescs();
588 int s = atomPropDescs.size();
589
590 for (int ii = 0; ii < s; ii++)
591 {
592 if (value == null)
593 {
594 break;
595 }
596
597 if (value.equalsIgnoreCase((String) atomPropDescs.get(ii)))
598 {
599 atomProperty2Use = value;
600 }
601
602 //System.out.println(atomPropDescs.get(ii));
603 }
604
605 if ((atomProperty2Use == null) && usePropertyColoring)
606 {
607 logger.warn("atomProperty=" + value +
608 " is not a valid atom property. Setting to Gasteiger_Marsili");
609
610 StringBuffer sb = new StringBuffer();
611 sb.append("Or use:");
612
613 for (int ii = 0; ii < s; ii++)
614 {
615 sb.append(atomPropDescs.get(ii));
616 sb.append(" ");
617 }
618
619 logger.warn(sb.toString());
620 atomProperty2Use = "Gasteiger_Marsili";
621 }
622 }
623
624 /**
625 * Description of the Method
626 *
627 * @param mol Description of the Parameter
628 * @param sb Description of the Parameter
629 */
630 private void write2Buffer(JOEMol mol, StringBuffer sb)
631 {
632 // write atoms
633 writeAtoms(mol, sb);
634
635 if (outputType != SPHERE)
636 {
637 // write bonds
638 writeBonds(mol, sb);
639
640 if (writeAromaticRings)
641 {
642 // write rings
643 writeRings(mol, sb);
644 }
645 }
646 }
647
648 /**
649 * Description of the Method
650 *
651 * @param mol Description of the Parameter
652 * @param sb Description of the Parameter
653 */
654 private void writeAtoms(JOEMol mol, StringBuffer sb)
655 {
656 JOEAtom atom;
657 AtomIterator ait = mol.atomIterator();
658 double x;
659 double y;
660 double z;
661 double radius;
662 Color color;
663
664 while (ait.hasNext())
665 {
666 atom = ait.nextAtom();
667
668 int atomNum = atom.getAtomicNum();
669
670 x = atom.getX();
671 y = atom.getY();
672 z = atom.getZ();
673 mx += x;
674 my += y;
675 mz += z;
676
677 if (x > maxX)
678 {
679 maxX = x;
680 }
681
682 if (x < minX)
683 {
684 minX = x;
685 }
686
687 if (y > maxY)
688 {
689 maxY = y;
690 }
691
692 if (y < minY)
693 {
694 minY = y;
695 }
696
697 if (z > maxZ)
698 {
699 maxZ = z;
700 }
701
702 if (z < minZ)
703 {
704 minZ = z;
705 }
706
707 if (outputType != STICK)
708 {
709 radius = etab.correctedVdwRad(atomNum);
710 }
711 else
712 {
713 radius = smallerBondRadius;
714 }
715
716 sb.append(" // atom " + atom.getIdx() + ": " +
717 etab.getSymbol(atom.getAtomicNum()) + JHM.eol);
718 sb.append(" sphere {" + JHM.eol);
719
720 if (outputType != BALL_AND_STICK)
721 {
722 sb.append(" <" + x + ", " + y + ", " + z + "> " + radius +
723 JHM.eol);
724 }
725 else
726 {
727 sb.append(" <" + x + ", " + y + ", " + z + "> " + radius +
728 "*atomResizeFactor" + JHM.eol);
729 }
730
731 sb.append(" texture {" + JHM.eol);
732
733 //color = getAtomColor(atom);
734 color = aPropColoring.getAtomColor(atom);
735 sb.append(" pigment {color rgb <" + (color.getRed() / 255.0f) +
736 ", " + (color.getGreen() / 255.0f) + ", " +
737 (color.getBlue() / 255.0f) + ">}" + JHM.eol);
738 sb.append(" finish {Shiny}" + JHM.eol);
739 sb.append(" }" + JHM.eol);
740 sb.append(" }" + JHM.eol);
741 }
742
743 mx = mx / (double) mol.numAtoms();
744 my = my / (double) mol.numAtoms();
745 mz = mz / (double) mol.numAtoms();
746 }
747
748 /**
749 * Description of the Method
750 *
751 * @param mol Description of the Parameter
752 * @param sb Description of the Parameter
753 */
754 private void writeBonds(JOEMol mol, StringBuffer sb)
755 {
756 JOEBond bond;
757 double x;
758 double y;
759 double z;
760 Color color;
761 double middleX;
762 double middleY;
763 double middleZ;
764 double r1;
765 double r2;
766 double l;
767 double s;
768 JOEAtom atom1;
769 JOEAtom atom2;
770 double smallerR;
771 double biggerR;
772 double middleR;
773
774 JOEAtom nbr;
775 JOEAtom atom;
776 AtomIterator ait = mol.atomIterator();
777
778 while (ait.hasNext())
779 {
780 atom = ait.nextAtom();
781
782 NbrAtomIterator nait = atom.nbrAtomIterator();
783
784 while (nait.hasNext())
785 {
786 nbr = nait.nextNbrAtom();
787
788 if (atom.getIdx() < nbr.getIdx())
789 {
790 bond = nait.actualBond();
791
792 // while (bit.hasNext())
793 // {
794 // bond = bit.nextBond();
795 atom1 = atom;
796 atom2 = nbr;
797
798 if (atom1.getIdx() < atom2.getIdx())
799 {
800 sb.append(" // bond " + bond.getIdx() + ": " +
801 etab.getSymbol(atom1.getAtomicNum()) + "(" +
802 atom1.getIdx() + ")");
803 sb.append(bond.toString());
804 sb.append(etab.getSymbol(atom2.getAtomicNum()) + "(" +
805 atom2.getIdx() + ")" + JHM.eol);
806 sb.append(" union {" + JHM.eol);
807
808 r1 = JOEElementTable.instance().correctedVdwRad(atom1.getAtomicNum()) * atomResizeFactor;
809 r2 = JOEElementTable.instance().correctedVdwRad(atom2.getAtomicNum()) * atomResizeFactor;
810 x = atom2.getX() - atom1.getX();
811 y = atom2.getY() - atom1.getY();
812 z = atom2.getZ() - atom1.getZ();
813 l = Math.sqrt((x * x) + (y * y) + (z * z));
814
815 // if atom radius of atom to big, cones not visible !!!!
816 if (l < (r1 + r2))
817 {
818 s = 0.5;
819 }
820 else
821 {
822 s = (((l - r1 - r2) / 2) + r1) / l;
823 }
824
825 middleX = atom1.getX() + (x * s);
826 middleY = atom1.getY() + (y * s);
827 middleZ = atom1.getZ() + (z * s);
828
829 // getting bond radii
830 if ((bond.isUp() || bond.isDown()) &&
831 (outputType != STICK))
832 {
833 smallerR = smallerBondRadius;
834 biggerR = biggerBondRadius;
835 }
836 else
837 {
838 smallerR = smallerBondRadius;
839 biggerR = smallerBondRadius;
840 }
841
842 middleR = smallerR + ((biggerR - smallerR) * s);
843
844 // write bond
845 sb.append(" cone {" + JHM.eol);
846 sb.append(" <" + atom1.getX() + ", " +
847 atom1.getY() + ", " + atom1.getZ() + "> " +
848 smallerR + JHM.eol);
849 sb.append(" <" + middleX + ", " + middleY + ", " +
850 middleZ + "> " + middleR + JHM.eol);
851 sb.append(" open" + JHM.eol);
852 sb.append(" texture {" + JHM.eol);
853
854 //color = getAtomColor(atom1);
855 color = aPropColoring.getAtomColor(atom1);
856 sb.append(" pigment {color rgb <" +
857 (color.getRed() / 255.0f) + ", " +
858 (color.getGreen() / 255.0f) + ", " +
859 (color.getBlue() / 255.0f) + ">}" + JHM.eol);
860 sb.append(" finish {Shiny}" + JHM.eol);
861 sb.append(" }" + JHM.eol);
862 sb.append(" }" + JHM.eol);
863
864 sb.append(" cone {" + JHM.eol);
865 sb.append(" <" + middleX + ", " + middleY + ", " +
866 middleZ + "> " + middleR + JHM.eol);
867 sb.append(" <" + atom2.getX() + ", " +
868 atom2.getY() + ", " + atom2.getZ() + "> " +
869 biggerR + JHM.eol);
870 sb.append(" open" + JHM.eol);
871 sb.append(" texture {" + JHM.eol);
872
873 //color = getAtomColor(atom2);
874 color = aPropColoring.getAtomColor(atom2);
875 sb.append(" pigment {color rgb <" +
876 (color.getRed() / 255.0f) + ", " +
877 (color.getGreen() / 255.0f) + ", " +
878 (color.getBlue() / 255.0f) + ">}" + JHM.eol);
879 sb.append(" finish {Shiny}" + JHM.eol);
880 sb.append(" }" + JHM.eol);
881 sb.append(" }" + JHM.eol);
882
883 sb.append(" }" + JHM.eol);
884 }
885 }
886 }
887 }
888 }
889
890 /**
891 * Description of the Method
892 *
893 * @param mol Description of the Parameter
894 * @param sb Description of the Parameter
895 */
896 private void writeRings(JOEMol mol, StringBuffer sb)
897 {
898 JOEAtom atom;
899 Color color;
900 JOEAtom atom1;
901 JOEAtom atom2;
902 double l;
903 double x;
904 double y;
905 double z;
906
907 // write rings
908 Vector sssRings = mol.getSSSR();
909 JOERing ring;
910 XYZVector center = new XYZVector();
911 XYZVector r1v = new XYZVector();
912 XYZVector r2v = new XYZVector();
913 int[] itmp;
914 boolean allAromatic;
915 double rgb_r;
916 double rgb_g;
917 double rgb_b;
918
919 //sb.append(" // rings:" + JHM.eol);
920 for (int i = 0; i < sssRings.size(); i++)
921 {
922 ring = (JOERing) sssRings.get(i);
923
924 // is ring aromatic ?
925 // if yes, get the color of this ring
926 allAromatic = true;
927 itmp = ring.getAtoms();
928
929 for (int n = 0; n < itmp.length; n++)
930 {
931 atom = mol.getAtom(itmp[n]);
932
933 if (!atom.isAromatic())
934 {
935 allAromatic = false;
936
937 break;
938 }
939 }
940
941 if (!allAromatic)
942 {
943 continue;
944 }
945
946 // show ring atoms in command line
947 sb.append(" // ring " + i + ":");
948
949 for (int n = 0; n < itmp.length; n++)
950 {
951 sb.append(" " + itmp[n]);
952 }
953
954 sb.append(JHM.eol);
955
956 // calculate color and write p orbitals
957 ring.findCenterAndNormal(center, r1v, r2v);
958 r1v.normalize();
959 itmp = ring.getAtoms();
960 rgb_r = 0.0;
961 rgb_g = 0.0;
962 rgb_b = 0.0;
963
964 for (int n = 0; n < itmp.length; n++)
965 {
966 atom = mol.getAtom(itmp[n]);
967
968 //color = getAtomColor(atom);
969 color = aPropColoring.getAtomColor(atom);
970 rgb_r += (color.getRed() / 255.0f);
971 rgb_g += (color.getGreen() / 255.0f);
972 rgb_b += (color.getBlue() / 255.0f);
973
974 if (writePorbitals)
975 {
976 sb.append(" cylinder {" + JHM.eol);
977 sb.append(" <" + r1v._vx + ", " + r1v._vy + ", " +
978 r1v._vz + ">" + JHM.eol);
979 sb.append(" <" + r2v._vx + ", " + r2v._vy + ", " +
980 r2v._vz + ">, 0.05" + JHM.eol);
981 sb.append(" pigment { color rgbt<0, 0.5, 0, 0.7>}" +
982 JHM.eol);
983 sb.append(" finish { ambient 1 diffuse 0 }" + JHM.eol);
984 sb.append(" no_shadow" + JHM.eol);
985 sb.append(" translate <" + atom.getX() + ", " +
986 atom.getY() + ", " + atom.getZ() + ">" + JHM.eol);
987 sb.append(" }" + JHM.eol);
988 }
989 }
990
991 rgb_r /= itmp.length;
992 rgb_g /= itmp.length;
993 rgb_b /= itmp.length;
994
995 // calculate radius
996 atom1 = mol.getAtom(itmp[0]);
997 atom2 = mol.getAtom(itmp[0]);
998 x = ((atom1.getX() + atom2.getX()) / 2) - center._vx;
999 y = ((atom1.getY() + atom2.getY()) / 2) - center._vy;
1000 z = ((atom1.getZ() + atom2.getZ()) / 2) - center._vz;
1001 l = Math.sqrt((x * x) + (y * y) + (z * z)) * 0.45;
1002
1003 // calculate rotation vector
1004 double rrx = -XYZVector.angle(XYZVector.vX, r1v);
1005
1006 if (r1v._vz < 0.0)
1007 {
1008 rrx *= -1.0;
1009 }
1010
1011 double rry = -XYZVector.angle(XYZVector.vY, r1v);
1012
1013 // write ring
1014 sb.append(" torus {" + JHM.eol);
1015 sb.append(" " + l + ", 0.075" + JHM.eol);
1016 sb.append(" rotate z*" + rry + JHM.eol);
1017 sb.append(" rotate y*" + rrx + JHM.eol);
1018 sb.append(" translate <" + center._vx + ", " + center._vy +
1019 ", " + center._vz + ">" + JHM.eol);
1020 sb.append(" pigment {color rgb <" + rgb_r + ", " + rgb_g + ", " +
1021 rgb_b + ">}" + JHM.eol);
1022 sb.append(" finish {Shiny}" + JHM.eol);
1023 sb.append(" }" + JHM.eol);
1024 }
1025 }
1026}
1027///////////////////////////////////////////////////////////////////////////////
1028// END OF FILE.
1029///////////////////////////////////////////////////////////////////////////////