Subversion Repositories wimsdev

Rev

Rev 7246 | Go to most recent revision | 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;
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
}