mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-06 22:39:55 +08:00
* Started on ACS 1996 drawing mode. Significant change (not by itself, sadly) is that MolDrawOptions::lineWidth has changed from int to double to allow for ACS requirement of 0.6px bond widths. * Wavy lines and dashed wedges. * Better dashed wedges. * Rounder wavy bonds, same as SVG. * Added FreeSans font for ACS1996 mode. * Add help functions to write enum classes to ostream. * Dashed wedge separation now 2.5px between line edges rather than line middles. Therefore wider gap between lines. * Increase offset for wavy bond. Get classes for atoms and bonds in wavy bond correct. * For SMILES input, option to force wavy and crossed bonds for unspecified stereochem. * Tidy debugging. * Extra space round atom labels. * Extra space between chars in freetype string. * Reformats. * Change double bond offset. * Improve ring double bonds. * Simple non-ring double bonds all working. * Tidy. * All double bonds seem good. * Remove redundant function. Move calcTripleBondLines into DrawMol for consistency with calcDoubleBondLines. Use doubleBondOffset for wavy lines. * Correct spacing between FT chars. * Tidying. * Use MolBlock wedging if there is any. Needs to be made an option. * If dashed wedge thick end has bonds of it, stop one dash short. * Adjust solid wedge ends to line with attached bonds. * Width of wedge ends now based on double bond separation. * Change catch_tests.cpp * Rounder waves in wavy lines. * Dashed wedges same width even if one dash less.. * Embedded Roboto-Regular font in code. * Fix docstrings. * doubleBondTerminal swapped ends. Deal with O2 - 2 terminal atoms of degree 1. * Fix terminal double bonds. * Slightly fatter truncated wedge bonds. * Fix crash on complicated double bonds. * Control more assert tests with DO_TEST_ASSERT. * Fix 2 colour solid wedges. Fix slanted wedge for morphine (test1_5). * Change definittion of multipleBondOffset to fraction of mean bond length. * Don't slant end of solid wedge to atom symbol. * Fix wiggle separation. * Fix 2-colour terminal double bonds. * Fix colours on triple bonds. * Don't attempt to draw non-existent points in triangle.. * Symmetric bond for P=O and like. * Fix query bonds. * Reformatting. * Tidy up use of font. * Add FreeSans font and license to $RDBASE/Data/Fonts. * Draw unspecified stereo as unknown. * Add check_file_hash. * Tidying. * Tidying. * Start Python wrappers. * Fix solid wedges for 3-connected atoms. * Docstrings. * Tidying. * Alter width of bond highlights in ACS 1996 mode. * Expose setACS1996Options and mean BondLength in Python. * Expose drawMolACS1996Cairo in Python. Docstrings. * Extra padding between legend and picture in flexicanvas. * Python tests. * Tidy catch tests. * Tidying. * Fix catch tests. * Fix no Freetype tests. * Draw solid wedge more sensibly.. * Fix bond end at solid wedge. * Tidy. * Fix Python Cairo build issues. * Fix wedge end shape for terminal double bonds. * Hide the joins at the bond ends. * Fix gcc pickiness. * Extra test for no atom labels. * Change where it looks for FreeSans.ttf for ACS1996 drawings. * Same number of waves for wavy bonds in SVG and Cairo. * Same number of waves for wavy bonds in SVG and Cairo. * rename unspecifiedStereoIsUnknown to markUnspecifiedStereoAsUnknown and move to MolFileStereochem.h * refactor use of iterators * py docs update * undo a bunch of bad formatting changes * remove FreeSans * get windows builds working * Fix problem with Windows build. * Changes in response to review. * Align description of unspecifiedStereoIsUnknown in C++ to match Python. * Still working on file open modes. * Took out extraneous functions for drawing in ACS1996 mode, including the one that was breaking the windows build. * Add RDKIT_MOLDRAW2D_EXPORT. * Fix expected test results. * Clarified warning. * RDKIT_MOLDRAW2D_EXPORT missing. * Windows! * Update Code/GraphMol/MolDraw2D/rxn_test1.cpp Co-authored-by: David Cosgrove <david@cozchemix.co.uk> Co-authored-by: greg landrum <greg.landrum@gmail.com>
160 lines
5.4 KiB
C++
160 lines
5.4 KiB
C++
//
|
|
// Copyright (C) 2021-2022 David Cosgrove and other RDKit contributors
|
|
//
|
|
// @@ All Rights Reserved @@
|
|
// This file is part of the RDKit.
|
|
// The contents are covered by the terms of the BSD license
|
|
// which is included in the file license.txt, found at the root
|
|
// of the RDKit source tree.
|
|
//
|
|
// Original author: David Cosgrove (CozChemIx Limited)
|
|
//
|
|
|
|
#include <boost/format.hpp>
|
|
#include <boost/algorithm/string.hpp>
|
|
|
|
#include <GraphMol/MolDraw2D/AtomSymbol.h>
|
|
#include <GraphMol/MolDraw2D/DrawText.h>
|
|
#include <GraphMol/MolDraw2D/MolDraw2D.h>
|
|
|
|
namespace RDKit {
|
|
namespace MolDraw2D_detail {
|
|
|
|
// ****************************************************************************
|
|
AtomSymbol::AtomSymbol(const std::string &symbol, int atIdx, OrientType orient,
|
|
const Point2D &cds, const DrawColour &colour,
|
|
DrawText &textDrawer)
|
|
: symbol_(symbol),
|
|
atIdx_(atIdx),
|
|
orient_(orient),
|
|
cds_(cds),
|
|
colour_(colour),
|
|
textDrawer_(textDrawer) {
|
|
if (symbol_.empty()) {
|
|
return;
|
|
}
|
|
textDrawer_.getStringRects(symbol_, orient_, rects_, drawModes_, drawChars_,
|
|
false, TextAlignType::MIDDLE);
|
|
adjustColons();
|
|
}
|
|
|
|
// ****************************************************************************
|
|
void AtomSymbol::findExtremes(double &xmin, double &xmax, double &ymin,
|
|
double &ymax) const {
|
|
Point2D bl, br, tl, tr, origTrans;
|
|
for (auto rect : rects_) {
|
|
origTrans = rect->trans_;
|
|
rect->trans_ += cds_;
|
|
rect->calcCorners(tl, tr, br, bl, 0.0);
|
|
// sometimes the rect is in a coordinate frame where +ve y is down,
|
|
// sometimes it's up. For these purposes, we don't care so long as
|
|
// the ymax is larger than the ymin. We probably don't need to do
|
|
// all the tests for xmin and xmax.
|
|
xmin = std::min({tr.x, bl.x, xmin});
|
|
ymin = std::min({tr.y, bl.y, ymin});
|
|
xmax = std::max({tr.x, bl.x, xmax});
|
|
ymax = std::max({tr.y, bl.y, ymax});
|
|
rect->trans_ = origTrans;
|
|
}
|
|
}
|
|
|
|
// ****************************************************************************
|
|
void AtomSymbol::scale(const Point2D &scaleFactor) {
|
|
cds_.x *= scaleFactor.x;
|
|
cds_.y *= scaleFactor.y;
|
|
|
|
// rebuild the rectangles, because the fontScale may be different,
|
|
// and the widths etc might not scale by the same amount.
|
|
rects_.clear();
|
|
drawModes_.clear();
|
|
drawChars_.clear();
|
|
textDrawer_.getStringRects(symbol_, orient_, rects_, drawModes_, drawChars_,
|
|
false, TextAlignType::MIDDLE);
|
|
}
|
|
|
|
// ****************************************************************************
|
|
void AtomSymbol::move(const Point2D &trans) { cds_ += trans; }
|
|
|
|
// ****************************************************************************
|
|
void AtomSymbol::draw(MolDraw2D &molDrawer) const {
|
|
std::string o_class = molDrawer.getActiveClass();
|
|
std::string actClass = o_class;
|
|
if (!actClass.empty()) {
|
|
actClass += " ";
|
|
}
|
|
actClass += (boost::format("atom-%d") % atIdx_).str();
|
|
molDrawer.setActiveClass(actClass);
|
|
textDrawer_.setColour(colour_);
|
|
textDrawer_.drawString(symbol_, cds_, orient_);
|
|
molDrawer.setActiveClass(o_class);
|
|
// drawRects(molDrawer);
|
|
}
|
|
|
|
// ****************************************************************************
|
|
bool AtomSymbol::doesRectClash(const StringRect &rect, double padding) const {
|
|
for (auto &alrect : rects_) {
|
|
auto oldTrans = alrect->trans_;
|
|
alrect->trans_ += cds_;
|
|
bool dii = alrect->doesItIntersect(rect, padding);
|
|
alrect->trans_ = oldTrans;
|
|
if (dii) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// ****************************************************************************
|
|
void AtomSymbol::adjustColons() {
|
|
if (symbol_.empty()) {
|
|
return; // but probably it's always got something in it.
|
|
}
|
|
size_t colonPos = symbol_.find(':');
|
|
if (colonPos == std::string::npos) {
|
|
return;
|
|
}
|
|
// we need to allow for markup in the symbol, such as <lit>[CH2;X2:4]</lit>
|
|
// and the easiest way to do that is to use the fact that atomLabelToPieces
|
|
// strips it out.
|
|
std::string tmpSym = symbol_;
|
|
while (true) {
|
|
size_t ltPos = tmpSym.find('<');
|
|
if (ltPos == std::string::npos) {
|
|
break;
|
|
}
|
|
size_t gtPos = tmpSym.find('>');
|
|
tmpSym = tmpSym.substr(0, ltPos) + tmpSym.substr(gtPos + 1);
|
|
}
|
|
colonPos = tmpSym.find(':');
|
|
if (colonPos == std::string::npos) {
|
|
return;
|
|
}
|
|
CHECK_INVARIANT(colonPos <= rects_.size(), "bad rects_ size");
|
|
double leftHeight = colonPos ? rects_[colonPos - 1]->height_ : 0;
|
|
double rightHeight =
|
|
colonPos < symbol_.size() - 1 ? rects_[colonPos + 1]->height_ : 0;
|
|
rects_[colonPos]->height_ = std::min(leftHeight, rightHeight);
|
|
}
|
|
|
|
// ****************************************************************************
|
|
void AtomSymbol::drawRects(MolDraw2D &molDrawer) const {
|
|
Point2D tl, tr, br, bl, origTrans;
|
|
for (auto &rect : rects_) {
|
|
origTrans = rect->trans_;
|
|
rect->trans_ += cds_;
|
|
rect->calcCorners(tl, tr, br, bl, 0.0);
|
|
molDrawer.setColour(DrawColour(1.0, 0.0, 0.0));
|
|
molDrawer.drawLine(tl, tr, true);
|
|
molDrawer.setColour(DrawColour(0.0, 1.0, 0.0));
|
|
molDrawer.drawLine(tr, br, true);
|
|
molDrawer.setColour(DrawColour(0.0, 0.0, 1.0));
|
|
molDrawer.drawLine(br, bl, true);
|
|
molDrawer.setColour(DrawColour(0.0, 0.95, 0.95));
|
|
molDrawer.drawLine(bl, tl, true);
|
|
rect->trans_ = origTrans;
|
|
}
|
|
}
|
|
|
|
} // namespace MolDraw2D_detail
|
|
} // namespace RDKit
|