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
20 *permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34 
35 #ifndef _RD_DRAWING_TO_SVG_H_
36 #define _RD_DRAWING_TO_SVG_H_
37 
39 
40 namespace RDKit {
41 namespace Drawing {
42 namespace {
43 std::string getColor(int atNum) {
44  std::string res = "#000000";
45  switch (atNum) {
46  case 7:
47  res = "#0000FF";
48  break;
49  case 8:
50  res = "#FF0000";
51  break;
52  case 9:
53  res = "#33CCCC";
54  break;
55  case 15:
56  res = "#FF7F00";
57  break;
58  case 16:
59  res = "#CCCC00";
60  break;
61  case 17:
62  res = "#00CC00";
63  break;
64  case 35:
65  res = "#7F4C19";
66  break;
67  case 0:
68  res = "#7F7F7F";
69  break;
70  default:
71  res = "#000000";
72  }
73  return res;
74 }
75 void drawLine(std::vector<int>::const_iterator &pos, std::ostringstream &sstr,
76  unsigned int lineWidthMult) {
77  int width = *pos++;
78  width *= lineWidthMult;
79 
80  int dashed = *pos++;
81  std::string dashString = "";
82  switch (dashed) {
83  case 0:
84  break;
85  case 2:
86  dashString = ";stroke-dasharray:2, 6";
87  break;
88  default:
89  dashString = ";stroke-dasharray:6, 6";
90  }
91  int an1 = *pos++;
92  int an2 = *pos++;
93  std::string c1 = getColor(an1);
94  std::string c2 = getColor(an2);
95  if (c1 == c2) {
96  sstr << "<svg:path ";
97  sstr << "d='M " << *pos << "," << *(pos + 1) << " " << *(pos + 2) << ","
98  << *(pos + 3) << "' ";
99  pos += 4;
100  sstr << "style='fill:none;fill-rule:evenodd;stroke:" << c1
101  << ";stroke-width:" << width
102  << "px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
103  << dashString << "'";
104  sstr << " />\n";
105  } else {
106  int xp1 = *pos++;
107  int yp1 = *pos++;
108  int xp2 = *pos++;
109  int yp2 = *pos++;
110  int mx = xp1 + (xp2 - xp1) / 2;
111  int my = yp1 + (yp2 - yp1) / 2;
112  sstr << "<svg:path ";
113  sstr << "d='M " << xp1 << "," << yp1 << " " << mx << "," << my << "' ";
114  sstr << "style='fill:none;fill-rule:evenodd;stroke:" << c1
115  << ";stroke-width:" << width
116  << "px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
117  << dashString << "'";
118  sstr << " />\n";
119  sstr << "<svg:path ";
120  sstr << "d='M " << mx << "," << my << " " << xp2 << "," << yp2 << "' ";
121  sstr << "style='fill:none;fill-rule:evenodd;stroke:" << c2
122  << ";stroke-width:" << width
123  << "px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
124  << dashString << "'";
125  sstr << " />\n";
126  }
127 }
128 
129 void drawAtom(std::vector<int>::const_iterator &pos, std::ostringstream &sstr,
130  unsigned int fontSz, bool includeAtomCircles = false) {
131  int atNum = *pos++;
132  int xp = *pos++;
133  int yp = *pos++;
134  int slen = *pos++;
135  std::string label = "";
136  for (unsigned int i = 0; i < slen; ++i) {
137  label += (char)*pos++;
138  }
139  int orient = *pos++;
140  if (label.length()) {
141  int width = fontSz * label.length();
142  int height = fontSz;
143  sstr << "<svg:g transform='translate(" << xp << "," << yp
144  << ")'><svg:rect ";
145  sstr << "style='opacity:1.0;fill:#FFFFFF;stroke:none'";
146  sstr << " width='" << width << "' height='" << height << "'";
147  sstr << " x='-" << width / 2 << "' y='-" << height / 2 << "'";
148  sstr << "> </svg:rect>\n";
149  sstr << "<svg:text";
150  sstr << " style='font-size:" << fontSz
151  << "px;font-style:normal;font-weight:normal;line-height:125%;letter-"
152  "spacing:0px;word-spacing:0px;fill-opacity:1;stroke:none;font-"
153  "family:sans-serif;text-anchor:middle"
154  << ";fill:" << getColor(atNum) << "'";
155  sstr << " y='" << .75 * fontSz / 2 << "'>";
156  sstr << "<svg:tspan>";
157  sstr << label << "</svg:tspan>";
158  sstr << "</svg:text>";
159  sstr << "</svg:g>\n";
160  }
161  if (includeAtomCircles) {
162 #if 0
163  sstr<<"<svg:circle cx='"<<xp<<"' cy='"<<yp<<"' r='5' />\n";
164 #else
165  sstr << "<svg:circle cx='" << xp << "' cy='" << yp
166  << "' r='0' style='fill:none;stroke:none' />\n";
167 #endif
168  }
169 }
170 } // end of anonymous namespace
171 
172 std::string DrawingToSVG(const std::vector<int> &drawing,
173  unsigned int lineWidthMult = 2,
174  unsigned int fontSize = 50,
175  bool includeAtomCircles = false) {
176  std::vector<int>::const_iterator pos = drawing.begin() + 2;
177  if (*pos != RDKit::Drawing::BOUNDS) {
178  std::cerr << "no bounds token found" << std::endl;
179  return "";
180  }
181  pos += 3;
182  unsigned int width, height;
183  width = *pos++;
184  height = *pos++;
185  std::ostringstream sstr;
186  sstr << "<?xml version='1.0' encoding='iso-8859-1'?>\n";
187  sstr << "<svg:svg version='1.1' baseProfile='full'\n \
188  xmlns:svg='http://www.w3.org/2000/svg'\n \
189  xmlns:xlink='http://www.w3.org/1999/xlink'\n \
190  xml:space='preserve'\n";
191  sstr << "width='" << width << "px' height='" << height << "px' >\n";
192  sstr << "<svg:rect ";
193  sstr << "style='opacity:1.0;fill:#FFFFFF;stroke:none'";
194  sstr << " width='" << width << "' height='" << height << "'";
195  sstr << " x='0' y='0'";
196  sstr << "> </svg:rect>\n";
197  sstr << "<svg:g transform='translate(" << width * .05 << "," << height * .05
198  << ") scale(.85,.85)'>";
199  while (pos != drawing.end()) {
200  int token = *pos++;
201  switch (token) {
203  drawLine(pos, sstr, lineWidthMult);
204  break;
206  drawAtom(pos, sstr, fontSize, includeAtomCircles);
207  break;
208  default:
209  std::cerr << "unrecognized token: " << token << std::endl;
210  }
211  }
212  sstr << "</svg:g></svg:svg>";
213  return sstr.str();
214 }
215 } // end of namespace Drawing
216 } // end of namespace RDKit
217 #endif
std::string DrawingToSVG(const std::vector< int > &drawing, unsigned int lineWidthMult=2, unsigned int fontSize=50, bool includeAtomCircles=false)
Definition: DrawingToSVG.h:172
Includes a bunch of functionality for handling Atom and Bond queries.
Definition: Atom.h:29
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:45