RDKit
Open-source cheminformatics and machine learning.
DrawingToSVG.h
Go to the documentation of this file.
1 // $Id$
2 /*
3 *
4 * Copyright (c) 2011, Novartis Institutes for BioMedical Research Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of Novartis Institutes for BioMedical Research Inc.
18 * nor the names of its contributors may be used to endorse or promote
19 * products derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 
34 #ifndef _RD_DRAWING_TO_SVG_H_
35 #define _RD_DRAWING_TO_SVG_H_
36 
38 
39 namespace RDKit {
40  namespace Drawing {
41  namespace {
42  std::string getColor(int atNum){
43  std::string res="#000000";
44  switch(atNum){
45  case 7: res="#0000FF";break;
46  case 8: res="#FF0000";break;
47  case 9: res="#33CCCC";break;
48  case 15: res="#FF7F00";break;
49  case 16: res="#CCCC00";break;
50  case 17: res="#00CC00";break;
51  case 35: res="#7F4C19";break;
52  case 0: res="#7F7F7F";break;
53  default: res="#000000";
54  }
55  return res;
56  }
57  void drawLine(std::vector<int>::const_iterator &pos,std::ostringstream &sstr,
58  unsigned int lineWidthMult){
59  int width=*pos++;
60  width*=lineWidthMult;
61 
62  int dashed=*pos++;
63  std::string dashString="";
64  switch(dashed){
65  case 0:
66  break;
67  case 2:
68  dashString=";stroke-dasharray:2, 6";
69  break;
70  default:
71  dashString=";stroke-dasharray:6, 6";
72  }
73  int an1=*pos++;
74  int an2=*pos++;
75  std::string c1=getColor(an1);
76  std::string c2=getColor(an2);
77  if(c1==c2){
78  sstr<<"<svg:path ";
79  sstr<<"d='M "<<*pos<<","<<*(pos+1)<<" "<<*(pos+2)<<","<<*(pos+3)<<"' ";
80  pos+=4;
81  sstr<<"style='fill:none;fill-rule:evenodd;stroke:"<<c1<<";stroke-width:"<<width<<"px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"<<dashString<<"'";
82  sstr<<" />\n";
83  } else {
84  int xp1 = *pos++;
85  int yp1 = *pos++;
86  int xp2 = *pos++;
87  int yp2 = *pos++;
88  int mx = xp1+(xp2-xp1)/2;
89  int my = yp1+(yp2-yp1)/2;
90  sstr<<"<svg:path ";
91  sstr<<"d='M "<<xp1<<","<<yp1<<" "<<mx<<","<<my<<"' ";
92  sstr<<"style='fill:none;fill-rule:evenodd;stroke:"<<c1<<";stroke-width:"<<width<<"px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"<<dashString<<"'";
93  sstr<<" />\n";
94  sstr<<"<svg:path ";
95  sstr<<"d='M "<<mx<<","<<my<<" "<<xp2<<","<<yp2<<"' ";
96  sstr<<"style='fill:none;fill-rule:evenodd;stroke:"<<c2<<";stroke-width:"<<width<<"px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"<<dashString<<"'";
97  sstr<<" />\n";
98  }
99  }
100 
101  void drawAtom(std::vector<int>::const_iterator &pos,std::ostringstream &sstr,unsigned int fontSz,
102  bool includeAtomCircles=false){
103  int atNum=*pos++;
104  int xp=*pos++;
105  int yp=*pos++;
106  int slen=*pos++;
107  std::string label="";
108  for(unsigned int i=0;i<slen;++i){
109  label+=(char)*pos++;
110  }
111  int orient=*pos++;
112  if(label.length()){
113  int width=fontSz*label.length();
114  int height=fontSz;
115  sstr<<"<svg:g transform='translate("<<xp<<","<<yp<<")'><svg:rect ";
116  sstr<<"style='opacity:1.0;fill:#FFFFFF;stroke:none'";
117  sstr<<" width='"<<width<<"' height='"<<height<<"'";
118  sstr<<" x='-"<<width/2<<"' y='-"<<height/2<<"'";
119  sstr<<"> </svg:rect>\n";
120  sstr<<"<svg:text";
121  sstr<<" style='font-size:"<<fontSz<<"px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill-opacity:1;stroke:none;font-family:sans-serif;text-anchor:middle"<<";fill:"<<getColor(atNum)<<"'";
122  sstr<<" y='"<<.75*fontSz/2<<"'>";
123  sstr<<"<svg:tspan>";
124  sstr<<label<<"</svg:tspan>";
125  sstr<<"</svg:text>";
126  sstr<<"</svg:g>\n";
127  }
128  if(includeAtomCircles){
129 #if 0
130  sstr<<"<svg:circle cx='"<<xp<<"' cy='"<<yp<<"' r='5' />\n";
131 #else
132  sstr<<"<svg:circle cx='"<<xp<<"' cy='"<<yp<<"' r='0' style='fill:none;stroke:none' />\n";
133 #endif
134  }
135  }
136  } // end of anonymous namespace
137 
138  std::string DrawingToSVG(const std::vector<int> &drawing,
139  unsigned int lineWidthMult=2,unsigned int fontSize=50,
140  bool includeAtomCircles=false){
141  std::vector<int>::const_iterator pos=drawing.begin()+2;
142  if(*pos!= RDKit::Drawing::BOUNDS){
143  std::cerr<<"no bounds token found"<<std::endl;
144  return "";
145  }
146  pos+=3;
147  unsigned int width,height;
148  width = *pos++;
149  height = *pos++;
150  std::ostringstream sstr;
151  sstr<<"<?xml version='1.0' encoding='iso-8859-1'?>\n";
152  sstr << "<svg:svg version='1.1' baseProfile='full'\n \
153  xmlns:svg='http://www.w3.org/2000/svg'\n \
154  xmlns:xlink='http://www.w3.org/1999/xlink'\n \
155  xml:space='preserve'\n";
156  sstr<<"width='"<<width<<"px' height='"<<height<<"px' >\n";
157  sstr<<"<svg:rect ";
158  sstr<<"style='opacity:1.0;fill:#FFFFFF;stroke:none'";
159  sstr<<" width='"<<width<<"' height='"<<height<<"'";
160  sstr<<" x='0' y='0'";
161  sstr<<"> </svg:rect>\n";
162  sstr<<"<svg:g transform='translate("<<width*.05<<","<<height*.05<<") scale(.85,.85)'>";
163  while(pos!=drawing.end()){
164  int token=*pos++;
165  switch(token){
167  drawLine(pos,sstr,lineWidthMult);
168  break;
170  drawAtom(pos,sstr,fontSize,includeAtomCircles);
171  break;
172  default:
173  std::cerr<<"unrecognized token: "<<token<<std::endl;
174  }
175  }
176  sstr<<"</svg:g></svg:svg>";
177  return sstr.str();
178  }
179  } // end of namespace Drawing
180 } // end of namespace RDKit
181 #endif
std::string DrawingToSVG(const std::vector< int > &drawing, unsigned int lineWidthMult=2, unsigned int fontSize=50, bool includeAtomCircles=false)
Definition: DrawingToSVG.h:138
Includes a bunch of functionality for handling Atom and Bond queries.
Definition: Atom.h:28
void drawLine(std::vector< ElementType > &res, int atnum1, int atnum2, int lineWidth, int dashed, double x1, double y1, double x2, double y2)
Definition: MolDrawing.h:57