Subversion Repositories wimsdev

Rev

Rev 7246 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.     Sketch Elements: Chemistry molecular diagram drawing tool.
  3.    
  4.     (c) 2008 Dr. Alex M. Clark
  5.    
  6.     Released as GNUware, under the Gnu Public License (GPL)
  7.    
  8.     See www.gnu.org for details.
  9. */
  10.  
  11. package WIMSchem;
  12.  
  13. import java.util.*;
  14. import java.text.*;
  15. import java.lang.*;
  16. import java.io.*;
  17.  
  18. /*
  19.     Controlling class for drawing a molecule in SVG format. This class performs a similar function to that of DrawMolecule, but outputs to
  20.     a text stream instead of a graphics context. Note that in this implementation of rendering, only the molecule is drawn, without
  21.     interactive effects.
  22. */
  23.  
  24. public class SVGMolecule implements ArrangeMeasurement
  25. {
  26.     private SVGBuilder svg=new SVGBuilder();
  27.    
  28.     private Molecule mol;
  29.     private double scale=20;
  30.    
  31.     private ArrangeMolecule arrmol;
  32.    
  33.     public SVGMolecule(Molecule mol)
  34.     {
  35.         this.mol=mol;
  36.        
  37.         arrmol=new ArrangeMolecule(mol,this);
  38.         arrmol.setDevRounding(false);
  39.     }
  40.    
  41.     public void draw()
  42.     {
  43.         arrmol.arrange();
  44.  
  45.         for (int n=0;n<arrmol.numLines();n++)
  46.         {
  47.             int btype=arrmol.lineType(n);
  48.             double x1=arrmol.lineX1(n),y1=arrmol.lineY1(n),x2=arrmol.lineX2(n),y2=arrmol.lineY2(n);
  49.             double dx=x2-x1,dy=y2-y1;
  50.             if (btype==ArrangeMolecule.BLINE_NORMAL)
  51.             {
  52.                 svg.drawLine(x1,y1,x2,y2,arrmol.lineCol(n),arrmol.lineSize(n));
  53.             }
  54.             else if (btype==ArrangeMolecule.BLINE_INCLINED)
  55.             {
  56.                 double norm=0.15*scale/Math.sqrt(dx*dx+dy*dy);
  57.                 double ox=norm*dy,oy=-norm*dx;
  58.                 svg.drawPoly(new double[]{x1,x2-ox,x2+ox},new double[]{y1,y2-oy,y2+oy},SVGBuilder.NOCOLOUR,0,arrmol.lineCol(n),true);
  59.             }
  60.             else if (btype==ArrangeMolecule.BLINE_DECLINED)
  61.             {
  62.                 int nsteps=(int)Math.ceil(Math.sqrt(dx*dx+dy*dy)*0.15);
  63.                 double norm=0.15*scale/Math.sqrt(dx*dx+dy*dy);
  64.                 double ox=norm*dy,oy=-norm*dx;
  65.                 for (int i=0;i<=nsteps+1;i++)
  66.                 {
  67.                     double cx=x1+i*dx/(nsteps+1),cy=y1+i*dy/(nsteps+1);
  68.                     double ix=ox*i/(nsteps+1),iy=oy*i/(nsteps+1);
  69.                     svg.drawLine(cx-ix,cy-iy,cx+ix,cy+iy,arrmol.lineCol(n),arrmol.lineSize(n));
  70.                 }
  71.             }
  72.             else if (btype==ArrangeMolecule.BLINE_UNKNOWN)
  73.             {
  74.                 int nsteps=(int)Math.ceil(Math.sqrt(dx*dx+dy*dy)*0.2);
  75.                 double norm=0.2*scale/Math.sqrt(dx*dx+dy*dy);
  76.                 double ox=norm*dy,oy=-norm*dx;
  77.                 int sz=1+3*(nsteps+1);
  78.                 double[] x=new double[sz],y=new double[sz];
  79.                 boolean[] ctrl=new boolean[sz];
  80.                 x[0]=x1; y[0]=y1; ctrl[0]=false;
  81.                 for (int i=0,j=1;i<=nsteps;i++,j+=3)
  82.                 {
  83.                     double ax=x1+i*dx/(nsteps+1),ay=y1+i*dy/(nsteps+1);
  84.                     double cx=x1+(i+1)*dx/(nsteps+1),cy=y1+(i+1)*dy/(nsteps+1);
  85.                     double bx=(ax+cx)/2,by=(ay+cy)/2;
  86.                     int sign=i%2==0 ? 1 : -1;
  87.                    
  88.                     x[j]=ax; x[j+1]=bx+sign*ox; x[j+2]=cx;
  89.                     y[j]=ay; y[j+1]=by+sign*oy; y[j+2]=cy;
  90.                     ctrl[j]=true; ctrl[j+1]=true; ctrl[j+2]=false;
  91.                 }
  92.                 svg.drawCurve(x,y,ctrl,arrmol.lineCol(n),arrmol.lineSize(n),SVGBuilder.NOCOLOUR,false);
  93.             }
  94.             else if (btype==ArrangeMolecule.BLINE_DOTTED)
  95.             {
  96.                 int nsteps=(int)Math.ceil(Math.sqrt(dx*dx+dy*dy)*0.10);
  97.                 float radius=(float)arrmol.lineSize(n);
  98.                 for (int i=0;i<=nsteps+1;i++)
  99.                 {
  100.                     double cx=x1+i*dx/(nsteps+1),cy=y1+i*dy/(nsteps+1);
  101.                     svg.drawOval(cx,cy,radius,radius,SVGBuilder.NOCOLOUR,0,arrmol.lineCol(n));
  102.                 }
  103.             }
  104.         }
  105.         for (int n=0;n<arrmol.numPoints();n++)
  106.         {
  107.             String txt=arrmol.pointText(n);
  108.             if (txt==null) continue; // is a point, so do not draw anything
  109.            
  110.             int fstyle=arrmol.pointBold(n) ? SVGBuilder.TXTSTYLE_BOLD : SVGBuilder.TXTSTYLE_NORMAL;
  111.             svg.drawText(arrmol.pointCX(n),arrmol.pointCY(n)+arrmol.pointRH(n),txt,arrmol.pointFontSize(n),
  112.                          arrmol.pointCol(n),fstyle,SVGBuilder.TXTALIGN_CENTRE);
  113.         }
  114.     }
  115.  
  116.     // construct the SVG document, and output it to the given writer    
  117.     public void build(PrintWriter out)
  118.     {
  119.         int w=(int)Math.ceil(svg.highX()-svg.lowX()),h=(int)Math.ceil(svg.highY()-svg.lowY());
  120.         svg.build(out,w,h,-svg.lowX(),-svg.lowY(),1,1);
  121.     }
  122.  
  123.     // convenient function for obtaining the SVG output as a string
  124.     public String toString()
  125.     {
  126.         StringWriter sw=new StringWriter();
  127.         build(new PrintWriter(sw));
  128.         return sw.toString();
  129.     }
  130.    
  131.     // implementation of measurement metrics
  132.    
  133.     public double scale() {return scale;}
  134.     public double angToX(double AX) {return AX*scale;}
  135.     public double angToY(double AY) {return -AY*scale;}
  136.     public double xToAng(double PX) {return PX*scale;}
  137.     public double yToAng(double PY) {return -PY*scale;}
  138.     public double[] measureText(String str,double fontSize) {return svg.measureText(str,fontSize,SVGBuilder.TXTSTYLE_NORMAL);}
  139. }
  140.