Subversion Repositories wimsdev

Rev

Rev 7304 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7246 schaersvoo 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;
7307 schaersvoo 50
 
7246 schaersvoo 51
            if (btype==ArrangeMolecule.BLINE_NORMAL)
52
            {
53
                svg.drawLine(x1,y1,x2,y2,arrmol.lineCol(n),arrmol.lineSize(n));
54
            }
55
            else if (btype==ArrangeMolecule.BLINE_INCLINED)
56
            {
57
                double norm=0.15*scale/Math.sqrt(dx*dx+dy*dy);
58
                double ox=norm*dy,oy=-norm*dx;
59
                svg.drawPoly(new double[]{x1,x2-ox,x2+ox},new double[]{y1,y2-oy,y2+oy},SVGBuilder.NOCOLOUR,0,arrmol.lineCol(n),true);
60
            }
61
            else if (btype==ArrangeMolecule.BLINE_DECLINED)
62
            {
63
                int nsteps=(int)Math.ceil(Math.sqrt(dx*dx+dy*dy)*0.15);
64
                double norm=0.15*scale/Math.sqrt(dx*dx+dy*dy);
65
                double ox=norm*dy,oy=-norm*dx;
66
                for (int i=0;i<=nsteps+1;i++)
67
                {
68
                    double cx=x1+i*dx/(nsteps+1),cy=y1+i*dy/(nsteps+1);
69
                    double ix=ox*i/(nsteps+1),iy=oy*i/(nsteps+1);
70
                    svg.drawLine(cx-ix,cy-iy,cx+ix,cy+iy,arrmol.lineCol(n),arrmol.lineSize(n));
71
                }
72
            }
73
            else if (btype==ArrangeMolecule.BLINE_UNKNOWN)
74
            {
75
                int nsteps=(int)Math.ceil(Math.sqrt(dx*dx+dy*dy)*0.2);
76
                double norm=0.2*scale/Math.sqrt(dx*dx+dy*dy);
77
                double ox=norm*dy,oy=-norm*dx;
78
                int sz=1+3*(nsteps+1);
79
                double[] x=new double[sz],y=new double[sz];
80
                boolean[] ctrl=new boolean[sz];
81
                x[0]=x1; y[0]=y1; ctrl[0]=false;
82
                for (int i=0,j=1;i<=nsteps;i++,j+=3)
83
                {
84
                    double ax=x1+i*dx/(nsteps+1),ay=y1+i*dy/(nsteps+1);
85
                    double cx=x1+(i+1)*dx/(nsteps+1),cy=y1+(i+1)*dy/(nsteps+1);
86
                    double bx=(ax+cx)/2,by=(ay+cy)/2;
87
                    int sign=i%2==0 ? 1 : -1;
88
 
89
                    x[j]=ax; x[j+1]=bx+sign*ox; x[j+2]=cx;
90
                    y[j]=ay; y[j+1]=by+sign*oy; y[j+2]=cy;
91
                    ctrl[j]=true; ctrl[j+1]=true; ctrl[j+2]=false;
92
                }
93
                svg.drawCurve(x,y,ctrl,arrmol.lineCol(n),arrmol.lineSize(n),SVGBuilder.NOCOLOUR,false);
94
            }
95
            else if (btype==ArrangeMolecule.BLINE_DOTTED)
96
            {
97
                int nsteps=(int)Math.ceil(Math.sqrt(dx*dx+dy*dy)*0.10);
98
                float radius=(float)arrmol.lineSize(n);
99
                for (int i=0;i<=nsteps+1;i++)
100
                {
101
                    double cx=x1+i*dx/(nsteps+1),cy=y1+i*dy/(nsteps+1);
102
                    svg.drawOval(cx,cy,radius,radius,SVGBuilder.NOCOLOUR,0,arrmol.lineCol(n));
103
                }
104
            }
105
        }
106
        for (int n=0;n<arrmol.numPoints();n++)
107
        {
108
            String txt=arrmol.pointText(n);
109
            if (txt==null) continue; // is a point, so do not draw anything
110
 
111
            int fstyle=arrmol.pointBold(n) ? SVGBuilder.TXTSTYLE_BOLD : SVGBuilder.TXTSTYLE_NORMAL;
112
            svg.drawText(arrmol.pointCX(n),arrmol.pointCY(n)+arrmol.pointRH(n),txt,arrmol.pointFontSize(n),
113
                         arrmol.pointCol(n),fstyle,SVGBuilder.TXTALIGN_CENTRE);
114
        }
115
    }
116
 
117
    // construct the SVG document, and output it to the given writer    
118
    public void build(PrintWriter out)
119
    {
120
        int w=(int)Math.ceil(svg.highX()-svg.lowX()),h=(int)Math.ceil(svg.highY()-svg.lowY());
121
        svg.build(out,w,h,-svg.lowX(),-svg.lowY(),1,1);
122
    }
123
 
124
    // convenient function for obtaining the SVG output as a string
125
    public String toString()
126
    {
127
        StringWriter sw=new StringWriter();
128
        build(new PrintWriter(sw));
129
        return sw.toString();
130
    }
131
 
132
    // implementation of measurement metrics
133
 
134
    public double scale() {return scale;}
135
    public double angToX(double AX) {return AX*scale;}
136
    public double angToY(double AY) {return -AY*scale;}
137
    public double xToAng(double PX) {return PX*scale;}
138
    public double yToAng(double PY) {return -PY*scale;}
139
    public double[] measureText(String str,double fontSize) {return svg.measureText(str,fontSize,SVGBuilder.TXTSTYLE_NORMAL);}
140
}