1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
//
// 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 <GraphMol/MolDraw2D/DrawAnnotation.h>
#include <GraphMol/MolDraw2D/DrawText.h>
#include <GraphMol/MolDraw2D/MolDraw2D.h>
namespace RDKit {
namespace MolDraw2D_detail {
// ****************************************************************************
DrawAnnotation::DrawAnnotation(const std::string ¬e,
const TextAlignType &align,
const std::string &cls, double relFontScale,
const Point2D &pos, const DrawColour &colour,
DrawText &textDrawer)
: text_(note),
align_(align),
class_(cls),
textDrawer_(textDrawer),
pos_(pos),
colour_(colour) {
fontScale_ = relFontScale * textDrawer_.fontScale();
extractRects();
}
// ****************************************************************************
void DrawAnnotation::findExtremes(double &xmin, double &xmax, double &ymin,
double &ymax, double padding) const {
if (text_.empty()) {
return;
}
Point2D tl, tr, br, bl, otrans;
for (auto r : rects_) {
otrans = r->trans_;
r->trans_ += pos_;
r->calcCorners(tl, tr, br, bl, padding);
// 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});
r->trans_ = otrans;
}
}
// ****************************************************************************
void DrawAnnotation::getDimensions(double &width, double &height) const {
double xMin, yMin, xMax, yMax;
xMin = yMin = std::numeric_limits<double>::max();
xMax = yMax = std::numeric_limits<double>::lowest();
findExtremes(xMin, xMax, yMin, yMax);
width = xMax - xMin;
height = yMax - yMin;
}
// ****************************************************************************
void DrawAnnotation::extractRects() {
// We don't need these for notes, which are always on 1 line and plain
// text.
std::vector<TextDrawType> drawModes;
std::vector<char> drawChars;
double ofs = textDrawer_.fontScale();
textDrawer_.setFontScale(fontScale_, true);
fontScale_ = textDrawer_.fontScale();
textDrawer_.getStringRects(text_, OrientType::C, rects_, drawModes, drawChars,
true, align_);
textDrawer_.setFontScale(ofs, true);
}
// ****************************************************************************
void DrawAnnotation::draw(MolDraw2D &molDrawer) const {
std::string o_class = molDrawer.getActiveClass();
std::string actClass = o_class;
if (!actClass.empty()) {
actClass += " ";
}
actClass += class_;
molDrawer.setActiveClass(actClass);
textDrawer_.setColour(colour_);
double ofs = textDrawer_.fontScale();
textDrawer_.setFontScale(fontScale_, true);
textDrawer_.drawString(text_, pos_, align_);
textDrawer_.setFontScale(ofs, true);
molDrawer.setActiveClass(o_class);
// drawRects(molDrawer);
}
// ****************************************************************************
void DrawAnnotation::drawRects(MolDraw2D &molDrawer) const {
auto olw = molDrawer.lineWidth();
molDrawer.setLineWidth(1);
Point2D tl, tr, br, bl, origTrans;
for (auto &rect : rects_) {
origTrans = rect->trans_;
rect->trans_ += pos_;
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;
}
molDrawer.setLineWidth(olw);
}
// ****************************************************************************
void DrawAnnotation::scale(const Point2D &scaleFactor) {
pos_.x *= scaleFactor.x;
pos_.y *= scaleFactor.y;
// arbitrarily choose x scale for fonts. It is highly unlikely that the
// x and y are different, in any case.
fontScale_ *= scaleFactor.x;
// rebuild the rectangles, because the fontScale may be different,
// and the widths etc might not scale by the same amount.
rects_.clear();
extractRects();
}
// ****************************************************************************
void DrawAnnotation::move(const Point2D &trans) {
pos_ += trans;
// the internals of the rects_ are all relative to pos_, so no need to
// do anything to them.
}
// ****************************************************************************
bool DrawAnnotation::doesRectClash(const StringRect &rect,
double padding) const {
for (auto &alrect : rects_) {
auto oldTrans = alrect->trans_;
alrect->trans_ += pos_;
bool dii = alrect->doesItIntersect(rect, padding);
alrect->trans_ = oldTrans;
if (dii) {
return true;
}
}
return false;
}
} // namespace MolDraw2D_detail
} // namespace RDKit
|