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 | } |