RDKit
Open-source cheminformatics and machine learning.
DrawMol.h
Go to the documentation of this file.
1//
2// Copyright (C) 2021-2022 David Cosgrove and other RDKit contributors
3//
4// @@ All Rights Reserved @@
5// This file is part of the RDKit.
6// The contents are covered by the terms of the BSD license
7// which is included in the file license.txt, found at the root
8// of the RDKit source tree.
9//
10// Original author: David Cosgrove (CozChemIx Limited)
11//
12// This class is a helper class used by MolDraw2D to draw an ROMol.
13// It is not part of the public API and is not intended to be used except
14// by MolDraw2D.
15
16#ifndef RDKIT_DRAWMOL_H
17#define RDKIT_DRAWMOL_H
18
19#include <map>
20#include <string>
21#include <vector>
22
23#include <Geometry/point.h>
28
29namespace RDKit {
30
31class Atom;
32class Bond;
33class ROMol;
34class RWMol;
35class DrawText;
36
37namespace MolDraw2D_detail {
38
39class DrawMol {
40 public:
41 virtual ~DrawMol() = default;
42
43 // Make the object, scaled to a given pixel size.
44 /*!
45 \param mol : the molecule to draw
46 \param legend : the legend (to be drawn under the molecule)
47 \param width : width (in pixels) of the rendering
48 set this to -1 to have the canvas size set automatically
49 \param height : height (in pixels) of the rendering
50 set this to -1 to have the canvas size set automatically
51 \param drawOptions : a MolDrawOptions object from the owning MolDraw2D
52 \param textDrawer : a DrawText object from the owning MolDraw2D
53 \param highlightAtoms : (optional) vector of atom ids to highlight
54 \param highlightBonds : (optional) vector of bond ids to highlight
55 \param highlightAtomMap : (optional) map from atomId -> DrawColour
56 providing the highlight colors. If not provided the default highlight colour
57 from \c drawOptions() will be used.
58 \param highlightBondMap : (optional) map from bondId -> DrawColour
59 providing the highlight colors. If not provided the default highlight colour
60 from \c drawOptions() will be used.
61 \param highlightRadii : (optional) map from atomId -> radius (in molecule
62 coordinates) for the radii of atomic highlights. If not provided the default
63 value from \c drawOptions() will be used.
64 \param confId : (optional) conformer ID to be used for atomic
65 coordinates
66 */
67 DrawMol(const ROMol &mol, const std::string &legend, int width, int height,
68 const MolDrawOptions &drawOptions, DrawText &textDrawer,
69 const std::vector<int> *highlightAtoms = nullptr,
70 const std::vector<int> *highlightBonds = nullptr,
71 const std::map<int, DrawColour> *highlightAtomMap = nullptr,
72 const std::map<int, DrawColour> *highlightBondMap = nullptr,
73 const std::vector<std::pair<DrawColour, DrawColour>> *bondColours =
74 nullptr,
75 const std::map<int, double> *highlight_radii = nullptr,
76 bool includeAnnotations = true, int confId = -1,
77 bool isReactionMol = false);
78 /*!
79 Make a DrawMol when there's no molecule to draw, but we still want
80 a DrawMol in the MolDraw2D for scale, conversion of atom coords to
81 draw coords etc. And so DrawMol starts sounding like a poor name for
82 the class.
83 \param width : width (in pixels) of the rendering
84 \param height : height (in pixels) of the rendering
85 \param drawOptions : a MolDrawOptions object from the owning MolDraw2D
86 \param textDrawer : a DrawText object from the owning MolDraw2D
87 \param xmin : minimum value expected in X
88 \param xmax : miaximum value expected in X
89 \param ymin : minimum value expected in Y
90 \param ymax : maximum value expected in Y
91 \param scale : scale to use
92 \param fontscale : font scale to use
93 */
94 DrawMol(int width, int height, const MolDrawOptions &drawOptions,
95 DrawText &textDrawer, double xmin, double xmax, double ymin,
96 double ymax, double scale, double fontscale);
97 DrawMol(const DrawMol &) = delete;
98 DrawMol(DrawMol &&) = delete;
99 DrawMol &operator=(const DrawMol &) = delete;
100 DrawMol &operator=(DrawMol &&) = delete;
101
102 // this must be called before a drawing can be done.
104 // common bits used by createDrawObjects and setScale.
106 void initDrawMolecule(const ROMol &mol);
111 virtual void extractHighlights();
122 // extractCloseContacts is to show where 2 atoms are drawn too close together
123 // and so needs the final drawing coords. It is therefore called at the end
124 // of changeToDrawCoords() and any necessary DrawShapePolyLines added to
125 // postShapes_ in drawCoords.
130 void draw(MolDraw2D &drawer) const;
131 void drawRadicals(MolDraw2D &drawer) const;
133 // reduce width_ and height_ to just accomodate the Xrange_ and YRange_
134 // at the current scale. Recentres everything. So the DrawMol takes up
135 // no more screen real estate than it needs.
136 void shrinkToFit(bool withPadding = true);
137
138 // adds LaTeX-like annotation for super- and sub-script.
139 std::pair<std::string, OrientType> getAtomSymbolAndOrientation(
140 const Atom &atom) const;
141 std::string getAtomSymbol(const Atom &atom, OrientType orientation) const;
143
144 // if there's a legend, partition the height_ to accommodate it
146 // extractLegend is different from all the other extract... functions
147 // in that it needs to be called once the final scale has been found
148 // by calculateScale.
150
152 void makeStandardBond(Bond *bond, double doubleBondOffset);
153 void makeQueryBond(Bond *bond, double doubleBondOffset);
154 void makeDoubleBondLines(Bond *bond, double doubleBondOffset,
155 const std::pair<DrawColour, DrawColour> &cols);
156 void makeTripleBondLines(Bond *bond, double doubleBondOffset,
157 const std::pair<DrawColour, DrawColour> &cols);
159 const std::pair<DrawColour, DrawColour> &cols);
160 void makeWavyBond(Bond *bond, const std::pair<DrawColour, DrawColour> &cols);
162 const std::pair<DrawColour, DrawColour> &cols);
163 void makeZeroBond(Bond *bond, const std::pair<DrawColour, DrawColour> &cols,
164 const DashPattern &dashPattern);
165 void adjustBondEndsForLabels(int begAtIdx, int endAtIdx, Point2D &begCds,
166 Point2D &endCds);
167 void newBondLine(const Point2D &pt1, const Point2D &pt2,
168 const DrawColour &col1, const DrawColour &col2, int atom1Idx,
169 int atom2Idx, int bondIdx, const DashPattern &dashPattern);
170 std::pair<DrawColour, DrawColour> getBondColours(Bond *bond);
173 void makeAtomEllipseHighlights(int lineWidth);
174 void makeBondHighlightLines(int lineWidth);
175 void calcAnnotationPosition(const Atom *atom,
176 DrawAnnotation &annot) const;
177 void calcAnnotationPosition(const Bond *bond,
178 DrawAnnotation &annot) const;
179 double getNoteStartAngle(const Atom *atom) const;
180 void calcMolNotePosition(const std::vector<Point2D> atCds,
181 DrawAnnotation &annot) const;
182 // see if the note will clash with anything else drawn on the molecule.
183 // Returns 0 if no clash, 1-4 if there is a clash, denoting what clashed.
184 int doesNoteClash(const DrawAnnotation &annot) const;
185 int doesRectClash(const StringRect &rect, double padding) const;
186 OrientType calcRadicalRect(const Atom *atom, StringRect &rad_rect) const;
188 Point2D &toCentre) const;
189 // Given some coords in molecule space (angstrom, probably) return the
190 // screen coords.
191 Point2D getDrawCoords(const Point2D &atCds, const Point2D &trans,
192 const Point2D &scaleFactor,
193 const Point2D &toCentre) const;
194 Point2D getDrawCoords(const Point2D &atCds) const;
195 Point2D getDrawCoords(int atnum) const;
196 // and the other way.
197 Point2D getAtomCoords(const Point2D &screenCds) const;
198 Point2D getAtomCoords(int atnum) const;
199 double getScale() const { return scale_; }
200 double getFontScale() const { return fontScale_; }
201 // More often than not, newScale and newFontScale will be the same,
202 // but not if minFontScale of maxFontScale have become involved.
203 // The newFontScale will be used without checking the min and max.
204 void setScale(double newScale, double newFontScale,
205 bool ignoreFontLimits = true);
206 // Set all the transformation details from the incoming DrawMol to this
207 // one, so they can be overlaid properly. Doesn't change the offsets.
208 void setTransformation(const DrawMol &sourceMol);
209
210 // For drawing into a grid, for example. Must be set before
211 // changeToDrawCoords is called for it to have effect.
212 void setOffsets(double xOffset, double yOffset);
213 // So we can add metadata later. Most likely used after changeToDrawCoords
214 // has been called.
216 // Apply the transformations to everything. trans and toCentre are added,
217 // scale is multiplied.
218 void transformAll(const Point2D *trans = nullptr, Point2D *scale = nullptr,
219 const Point2D *toCentre = nullptr);
220 // Apply the transformations to the given point and return a new one.
221 Point2D transformPoint(const Point2D &pt, const Point2D *trans = nullptr,
222 Point2D *scale = nullptr,
223 const Point2D *toCentre = nullptr) const;
224
227 std::vector<int> highlightAtoms_;
228 std::vector<int> highlightBonds_;
229 std::map<int, DrawColour> highlightAtomMap_;
230 std::map<int, DrawColour> highlightBondMap_;
231 std::vector<std::pair<DrawColour, DrawColour>> bondColours_;
232 std::map<int, double> highlightRadii_;
235 std::string legend_;
236
237 std::unique_ptr<RWMol> drawMol_;
239 // atCds_ are as extracted from the molecule, except that the y is
240 // inverted and drawOptions_.rotate is applied.
241 std::vector<Point2D> atCds_;
242 std::vector<std::unique_ptr<DrawShape>> bonds_;
243 std::vector<std::unique_ptr<DrawShape>> preShapes_;
244 std::vector<std::unique_ptr<DrawShape>> postShapes_;
245 std::vector<int> atomicNums_;
246 std::vector<std::pair<std::string, OrientType>> atomSyms_;
247 std::vector<std::unique_ptr<AtomSymbol>> atomLabels_;
248 std::vector<std::unique_ptr<DrawShape>> highlights_;
249 std::vector<std::unique_ptr<DrawAnnotation>> annotations_;
250 std::vector<std::unique_ptr<DrawAnnotation>> legends_;
251 std::vector<std::tuple<StringRect, OrientType, int>> radicals_;
252
254 // to allow for min and max font sizes, the font scale needs to be
255 // independent of the main scale.
258 // offsets are for drawing molecules in grids, for example.
259 double xOffset_ = 0.0, yOffset_ = 0.0;
260 double meanBondLength_ = 0.0;
261 // if there's a legend, we reserve a bit for it.
264 // when drawing the atoms and bonds in an SVG, they are given a class
265 // via MolDraw2D's activeAtmIdx[12]_ and activeBndIdx. We don't always want
266 // them to start from 0 for atom/bond 0.
268 bool flexiCanvasX_ = false;
269 bool flexiCanvasY_ = false;
270};
271
272void centerMolForDrawing(RWMol &mol, int confId = 1);
274bool isLinearAtom(const Atom &atom, const std::vector<Point2D> &atCds);
275std::string getAtomListText(const Atom &atom);
276DrawColour getColour(int atom_idx, const MolDrawOptions &drawOptions,
277 const std::vector<int> &atomicNums,
278 const std::vector<int> *highlightAtoms,
279 const std::map<int, DrawColour> *highlightMap);
281 const MolDrawOptions &drawOptions);
283 const MolDrawOptions &drawOptions, int bond_idx,
284 const std::map<int, int> *highlight_linewidth_multipliers);
285
286void calcDoubleBondLines(const ROMol &mol, double offset, const Bond &bond,
287 const std::vector<Point2D> &at_cds, Point2D &l1s,
288 Point2D &l1f, Point2D &l2s, Point2D &l2f);
289void calcTripleBondLines(double offset, const Bond &bond,
290 const std::vector<Point2D> &at_cds, Point2D &l1s,
291 Point2D &l1f, Point2D &l2s, Point2D &l2f);
292Point2D calcPerpendicular(const Point2D &cds1, const Point2D &cds2);
294 const Point2D &cds3);
295Point2D bondInsideRing(const ROMol &mol, const Bond &bond, const Point2D &cds1,
296 const Point2D &cds2, const std::vector<Point2D> &at_cds);
297Point2D bondInsideDoubleBond(const ROMol &mol, const Bond &bond,
298 const std::vector<Point2D> &at_cds);
299// return a point that is end1 moved so as not to clash with any of the
300// rects of a label. end1 to end2 and the coords of 2 ends of a bond.
302 const Point2D &end2, double padding,
303 const std::vector<std::shared_ptr<StringRect>> &rects, Point2D &moveEnd);
305 const std::vector<std::tuple<StringRect, OrientType, int>> &radicals,
306 double &xmin, double &xmax, double &ymin, double &ymax);
307void findRectExtremes(const StringRect &rect, const TextAlignType &align,
308 double &xmin, double &xmax, double &ymin, double &ymax);
310 const std::vector<int> &highlight_atoms,
311 std::vector<int> &highlight_bonds);
312
313} // namespace MolDraw2D_detail
314} // namespace RDKit
315
316#endif // RDKIT_DRAWMOL_H
The class for representing atoms.
Definition: Atom.h:68
class for representing a bond
Definition: Bond.h:47
std::pair< std::string, OrientType > getAtomSymbolAndOrientation(const Atom &atom) const
void newBondLine(const Point2D &pt1, const Point2D &pt2, const DrawColour &col1, const DrawColour &col2, int atom1Idx, int atom2Idx, int bondIdx, const DashPattern &dashPattern)
void makeAtomEllipseHighlights(int lineWidth)
Point2D getDrawCoords(const Point2D &atCds) const
void makeBondHighlightLines(int lineWidth)
std::pair< DrawColour, DrawColour > getBondColours(Bond *bond)
void makeWavyBond(Bond *bond, const std::pair< DrawColour, DrawColour > &cols)
DrawMol & operator=(DrawMol &&)=delete
std::unique_ptr< RWMol > drawMol_
Definition: DrawMol.h:237
std::map< int, DrawColour > highlightAtomMap_
Definition: DrawMol.h:229
void setTransformation(const DrawMol &sourceMol)
std::vector< std::unique_ptr< AtomSymbol > > atomLabels_
Definition: DrawMol.h:247
std::string getAtomSymbol(const Atom &atom, OrientType orientation) const
std::map< int, double > highlightRadii_
Definition: DrawMol.h:232
void shrinkToFit(bool withPadding=true)
std::map< int, DrawColour > highlightBondMap_
Definition: DrawMol.h:230
std::vector< std::pair< std::string, OrientType > > atomSyms_
Definition: DrawMol.h:246
void drawRadicals(MolDraw2D &drawer) const
void setScale(double newScale, double newFontScale, bool ignoreFontLimits=true)
std::vector< std::unique_ptr< DrawAnnotation > > annotations_
Definition: DrawMol.h:249
Point2D getAtomCoords(int atnum) const
std::vector< int > highlightAtoms_
Definition: DrawMol.h:227
DrawMol(const DrawMol &)=delete
Point2D transformPoint(const Point2D &pt, const Point2D *trans=nullptr, Point2D *scale=nullptr, const Point2D *toCentre=nullptr) const
void makeWedgedBond(Bond *bond, const std::pair< DrawColour, DrawColour > &cols)
std::vector< std::unique_ptr< DrawShape > > preShapes_
Definition: DrawMol.h:243
std::vector< std::pair< DrawColour, DrawColour > > bondColours_
Definition: DrawMol.h:231
void setOffsets(double xOffset, double yOffset)
std::vector< std::unique_ptr< DrawAnnotation > > legends_
Definition: DrawMol.h:250
void makeStandardBond(Bond *bond, double doubleBondOffset)
void makeTripleBondLines(Bond *bond, double doubleBondOffset, const std::pair< DrawColour, DrawColour > &cols)
Point2D getAtomCoords(const Point2D &screenCds) const
void adjustBondEndsForLabels(int begAtIdx, int endAtIdx, Point2D &begCds, Point2D &endCds)
double getNoteStartAngle(const Atom *atom) const
void makeDativeBond(Bond *bond, const std::pair< DrawColour, DrawColour > &cols)
const MolDrawOptions & drawOptions_
Definition: DrawMol.h:225
std::vector< std::tuple< StringRect, OrientType, int > > radicals_
Definition: DrawMol.h:251
void makeQueryBond(Bond *bond, double doubleBondOffset)
DrawMol(const ROMol &mol, const std::string &legend, int width, int height, const MolDrawOptions &drawOptions, DrawText &textDrawer, const std::vector< int > *highlightAtoms=nullptr, const std::vector< int > *highlightBonds=nullptr, const std::map< int, DrawColour > *highlightAtomMap=nullptr, const std::map< int, DrawColour > *highlightBondMap=nullptr, const std::vector< std::pair< DrawColour, DrawColour > > *bondColours=nullptr, const std::map< int, double > *highlight_radii=nullptr, bool includeAnnotations=true, int confId=-1, bool isReactionMol=false)
DrawMol & operator=(const DrawMol &)=delete
std::vector< std::unique_ptr< DrawShape > > postShapes_
Definition: DrawMol.h:244
std::vector< Point2D > atCds_
Definition: DrawMol.h:241
int doesRectClash(const StringRect &rect, double padding) const
std::vector< std::unique_ptr< DrawShape > > highlights_
Definition: DrawMol.h:248
std::vector< int > atomicNums_
Definition: DrawMol.h:245
std::vector< int > highlightBonds_
Definition: DrawMol.h:228
void draw(MolDraw2D &drawer) const
void transformAll(const Point2D *trans=nullptr, Point2D *scale=nullptr, const Point2D *toCentre=nullptr)
void getDrawTransformers(Point2D &trans, Point2D &scale, Point2D &toCentre) const
OrientType calcRadicalRect(const Atom *atom, StringRect &rad_rect) const
void makeZeroBond(Bond *bond, const std::pair< DrawColour, DrawColour > &cols, const DashPattern &dashPattern)
std::vector< std::unique_ptr< DrawShape > > bonds_
Definition: DrawMol.h:242
void calcMolNotePosition(const std::vector< Point2D > atCds, DrawAnnotation &annot) const
int doesNoteClash(const DrawAnnotation &annot) const
void calcAnnotationPosition(const Atom *atom, DrawAnnotation &annot) const
void calcAnnotationPosition(const Bond *bond, DrawAnnotation &annot) const
Point2D getDrawCoords(int atnum) const
OrientType getAtomOrientation(const Atom &atom) const
Point2D getDrawCoords(const Point2D &atCds, const Point2D &trans, const Point2D &scaleFactor, const Point2D &toCentre) const
void makeDoubleBondLines(Bond *bond, double doubleBondOffset, const std::pair< DrawColour, DrawColour > &cols)
void initDrawMolecule(const ROMol &mol)
DrawMol(int width, int height, const MolDrawOptions &drawOptions, DrawText &textDrawer, double xmin, double xmax, double ymin, double ymax, double scale, double fontscale)
MolDraw2D is the base class for doing 2D renderings of molecules.
Definition: MolDraw2D.h:47
RWMol is a molecule class that is intended to be edited.
Definition: RWMol.h:32
Point2D calcPerpendicular(const Point2D &cds1, const Point2D &cds2)
Point2D bondInsideRing(const ROMol &mol, const Bond &bond, const Point2D &cds1, const Point2D &cds2, const std::vector< Point2D > &at_cds)
Point2D calcInnerPerpendicular(const Point2D &cds1, const Point2D &cds2, const Point2D &cds3)
void findRectExtremes(const StringRect &rect, const TextAlignType &align, double &xmin, double &xmax, double &ymin, double &ymax)
bool isLinearAtom(const Atom &atom, const std::vector< Point2D > &atCds)
void findRadicalExtremes(const std::vector< std::tuple< StringRect, OrientType, int > > &radicals, double &xmin, double &xmax, double &ymin, double &ymax)
void prepareStereoGroups(RWMol &mol)
int getHighlightBondWidth(const MolDrawOptions &drawOptions, int bond_idx, const std::map< int, int > *highlight_linewidth_multipliers)
void centerMolForDrawing(RWMol &mol, int confId=1)
void adjustBondEndForString(const Point2D &end2, double padding, const std::vector< std::shared_ptr< StringRect > > &rects, Point2D &moveEnd)
DrawColour getColourByAtomicNum(int atomicNum, const MolDrawOptions &drawOptions)
Point2D bondInsideDoubleBond(const ROMol &mol, const Bond &bond, const std::vector< Point2D > &at_cds)
DrawColour getColour(int atom_idx, const MolDrawOptions &drawOptions, const std::vector< int > &atomicNums, const std::vector< int > *highlightAtoms, const std::map< int, DrawColour > *highlightMap)
void getBondHighlightsForAtoms(const ROMol &mol, const std::vector< int > &highlight_atoms, std::vector< int > &highlight_bonds)
void calcDoubleBondLines(const ROMol &mol, double offset, const Bond &bond, const std::vector< Point2D > &at_cds, Point2D &l1s, Point2D &l1f, Point2D &l2s, Point2D &l2f)
std::string getAtomListText(const Atom &atom)
void calcTripleBondLines(double offset, const Bond &bond, const std::vector< Point2D > &at_cds, Point2D &l1s, Point2D &l1f, Point2D &l2s, Point2D &l2f)
Std stuff.
Definition: Abbreviations.h:18
std::vector< double > DashPattern