Generated on Thu Jan 16 2025 00:00:00 for Gecode by doxygen 1.14.0
drawingcursor.cpp
Go to the documentation of this file.
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Guido Tack <tack@gecode.org>
5 *
6 * Copyright:
7 * Guido Tack, 2006
8 *
9 * This file is part of Gecode, the generic constraint
10 * development environment:
11 * http://www.gecode.org
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining
14 * a copy of this software and associated documentation files (the
15 * "Software"), to deal in the Software without restriction, including
16 * without limitation the rights to use, copy, modify, merge, publish,
17 * distribute, sublicense, and/or sell copies of the Software, and to
18 * permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be
22 * included in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 *
32 */
33
35
36namespace Gecode { namespace Gist {
37
39 const QColor DrawingCursor::red(218, 37, 29);
41 const QColor DrawingCursor::green(11, 118, 70);
43 const QColor DrawingCursor::blue(0, 92, 161);
45 const QColor DrawingCursor::orange(235, 137, 27);
47 const QColor DrawingCursor::white(255,255,255);
48
50 const QColor DrawingCursor::lightRed(218, 37, 29, 120);
52 const QColor DrawingCursor::lightGreen(11, 118, 70, 120);
54 const QColor DrawingCursor::lightBlue(0, 92, 161, 120);
55
56 const double nodeWidth = 20.0;
57 const double halfNodeWidth = nodeWidth / 2.0;
58 const double failedWidth = 14.0;
59 const double halfFailedWidth = failedWidth / 2.0;
60 const double quarterFailedWidthF = failedWidth / 4.0;
61 const double shadowOffset = 3.0;
62 const double hiddenDepth =
63 static_cast<double>(Layout::dist_y) + failedWidth;
64
67 BestNode* curBest0,
68 QPainter& painter0,
69 const QRect& clippingRect0, bool showCopies)
70 : NodeCursor<VisualNode>(root,na), painter(painter0),
71 clippingRect(clippingRect0), curBest(curBest0),
72 x(0.0), y(0.0), copies(showCopies) {
73 QPen pen = painter.pen();
74 pen.setWidth(1);
75 painter.setPen(pen);
76 }
77
78 void
81 double parentX = x - static_cast<double>(n->getOffset());
82 double parentY = y - static_cast<double>(Layout::dist_y) + nodeWidth;
83 if (!n->isRoot() &&
84 (n->getParent(na)->getStatus() == STOP ||
85 n->getParent(na)->getStatus() == UNSTOP) )
86 parentY -= (nodeWidth-failedWidth)/2;
87
88 double myx = x;
89 double myy = y;
90
91 if (n->getStatus() == STOP || n->getStatus() == UNSTOP)
92 myy += (nodeWidth-failedWidth)/2;
93
94 if (n != startNode()) {
95 if (n->isOnPath())
96 painter.setPen(Qt::red);
97 else
98 painter.setPen(Qt::black);
99 // Here we use drawPath instead of drawLine in order to
100 // workaround a strange redraw artefact on Windows
101 QPainterPath path;
102 path.moveTo(myx,myy);
103 path.lineTo(parentX,parentY);
104 painter.drawPath(path);
105
106 QFontMetrics fm = painter.fontMetrics();
107 QString label = na.getLabel(n);
108 int alt = n->getAlternative(na);
109 int n_alt = n->getParent(na)->getNumberOfChildren();
110 int tw = fm.width(label);
111 int lx;
112 if (alt==0 && n_alt > 1) {
113 lx = myx-tw-4;
114 } else if (alt==n_alt-1 && n_alt > 1) {
115 lx = myx+4;
116 } else {
117 lx = myx-tw/2;
118 }
119 painter.drawText(QPointF(lx,myy-2),label);
120 }
121
122 // draw shadow
123 if (n->isMarked()) {
124 painter.setBrush(Qt::gray);
125 painter.setPen(Qt::NoPen);
126 if (n->isHidden()) {
127 QPointF points[3] = {QPointF(myx+shadowOffset,myy+shadowOffset),
128 QPointF(myx+nodeWidth+shadowOffset,
130 QPointF(myx-nodeWidth+shadowOffset,
132 };
133 painter.drawConvexPolygon(points, 3);
134
135 } else {
136 switch (n->getStatus()) {
137 case Gist::SOLVED:
138 {
139 QPointF points[4] = {QPointF(myx+shadowOffset,myy+shadowOffset),
140 QPointF(myx+halfNodeWidth+shadowOffset,
142 QPointF(myx+shadowOffset,
144 QPointF(myx-halfNodeWidth+shadowOffset,
146 };
147 painter.drawConvexPolygon(points, 4);
148 }
149 break;
150 case Gist::FAILED:
151 painter.drawRect(myx-halfFailedWidth+shadowOffset,
153 break;
154 case Gist::UNSTOP:
155 case Gist::STOP:
156 {
157 QPointF points[8] = {QPointF(myx+shadowOffset-quarterFailedWidthF,
158 myy+shadowOffset),
160 myy+shadowOffset),
161 QPointF(myx+shadowOffset+halfFailedWidth,
162 myy+shadowOffset
164 QPointF(myx+shadowOffset+halfFailedWidth,
171 QPointF(myx+shadowOffset-halfFailedWidth,
174 QPointF(myx+shadowOffset-halfFailedWidth,
175 myy+shadowOffset
177 };
178 painter.drawConvexPolygon(points, 8);
179 }
180 break;
181 case Gist::BRANCH:
182 painter.drawEllipse(myx-halfNodeWidth+shadowOffset,
184 break;
186 painter.drawEllipse(myx-halfNodeWidth+shadowOffset,
188 break;
189 }
190 }
191 }
192
193 painter.setPen(Qt::SolidLine);
194 if (n->isHidden()) {
195 if (n->hasOpenChildren()) {
196 QLinearGradient gradient(myx-nodeWidth,myy,
197 myx+nodeWidth*1.3,myy+hiddenDepth*1.3);
198 if (n->hasSolvedChildren()) {
199 gradient.setColorAt(0, white);
200 gradient.setColorAt(1, green);
201 } else if (n->hasFailedChildren()) {
202 gradient.setColorAt(0, white);
203 gradient.setColorAt(1, red);
204 } else {
205 gradient.setColorAt(0, white);
206 gradient.setColorAt(1, QColor(0,0,0));
207 }
208 painter.setBrush(gradient);
209 } else {
210 if (n->hasSolvedChildren())
211 painter.setBrush(QBrush(green));
212 else
213 painter.setBrush(QBrush(red));
214 }
215
216 QPointF points[3] = {QPointF(myx,myy),
217 QPointF(myx+nodeWidth,myy+hiddenDepth),
218 QPointF(myx-nodeWidth,myy+hiddenDepth),
219 };
220 painter.drawConvexPolygon(points, 3);
221 } else {
222 switch (n->getStatus()) {
223 case Gist::SOLVED:
224 {
225 if (n->isCurrentBest(curBest)) {
226 painter.setBrush(QBrush(orange));
227 } else {
228 painter.setBrush(QBrush(green));
229 }
230 QPointF points[4] = {QPointF(myx,myy),
231 QPointF(myx+halfNodeWidth,myy+halfNodeWidth),
232 QPointF(myx,myy+nodeWidth),
233 QPointF(myx-halfNodeWidth,myy+halfNodeWidth)
234 };
235 painter.drawConvexPolygon(points, 4);
236 }
237 break;
238 case Gist::FAILED:
239 painter.setBrush(QBrush(red));
240 painter.drawRect(myx-halfFailedWidth, myy, failedWidth, failedWidth);
241 break;
242 case Gist::UNSTOP:
243 case Gist::STOP:
244 {
245 painter.setBrush(n->getStatus() == STOP ?
246 QBrush(red) : QBrush(green));
247 QPointF points[8] = {QPointF(myx-quarterFailedWidthF,myy),
248 QPointF(myx+quarterFailedWidthF,myy),
249 QPointF(myx+halfFailedWidth,
251 QPointF(myx+halfFailedWidth,
252 myy+halfFailedWidth+
254 QPointF(myx+quarterFailedWidthF,
255 myy+failedWidth),
256 QPointF(myx-quarterFailedWidthF,
257 myy+failedWidth),
258 QPointF(myx-halfFailedWidth,
259 myy+halfFailedWidth+
261 QPointF(myx-halfFailedWidth,
263 };
264 painter.drawConvexPolygon(points, 8);
265 }
266 break;
267 case Gist::BRANCH:
268 painter.setBrush(n->childrenLayoutIsDone() ? QBrush(blue) :
269 QBrush(white));
270 painter.drawEllipse(myx-halfNodeWidth, myy, nodeWidth, nodeWidth);
271 break;
273 painter.setBrush(Qt::white);
274 painter.drawEllipse(myx-halfNodeWidth, myy, nodeWidth, nodeWidth);
275 break;
276 }
277 }
278
279 if (copies && (n->hasCopy() && !n->hasWorkingSpace())) {
280 painter.setBrush(Qt::darkRed);
281 painter.drawEllipse(myx, myy, 10.0, 10.0);
282 }
283
284 if (copies && n->hasWorkingSpace()) {
285 painter.setBrush(Qt::darkYellow);
286 painter.drawEllipse(myx, myy + 10.0, 10.0, 10.0);
287 }
288
289 if (n->isBookmarked()) {
290 painter.setBrush(Qt::black);
291 painter.drawEllipse(myx-10-0, myy, 10.0, 10.0);
292 }
293
294 }
295
296}}
297
298// STATISTICS: gist-any
Static reference to the currently best space.
Definition spacenode.hh:80
static const QColor red
The color for failed nodes.
void processCurrentNode(void)
Draw the node.
static const QColor blue
The color for choice nodes.
static const QColor green
The color for solved nodes.
static const QColor white
White color.
static const QColor lightBlue
The color for expanded choice nodes.
DrawingCursor(VisualNode *root, const VisualNode::NodeAllocator &na, BestNode *curBest0, QPainter &painter0, const QRect &clippingRect0, bool showCopies)
Constructor.
static const QColor lightRed
The color for expanded failed nodes.
static const QColor lightGreen
The color for expanded solved nodes.
static const QColor orange
The color for the best solution.
static const int dist_y
Definition visualnode.hh:46
const VisualNode::NodeAllocator & na
Definition nodecursor.hh:53
NodeCursor(VisualNode *theNode, const typename VisualNode::NodeAllocator &na)
NodeAllocatorBase< VisualNode > NodeAllocator
Definition node.hh:143
int getParent(void) const
Return the parent.
Definition node.hpp:182
bool isRoot(void) const
Check if this node is the root of a tree.
Definition node.hpp:211
bool hasCopy(void)
Return whether the node has a copy.
bool hasWorkingSpace(void)
Return whether the node has a working space.
bool isCurrentBest(BestNode *curBest)
Return whether this node is the currently best solution.
bool hasFailedChildren(void)
Return whether the subtree of this node has any failed children.
bool hasSolvedChildren(void)
Return whether the subtree of this node has any solved children.
int getAlternative(const NodeAllocator &na) const
Return alternative number of this node.
NodeStatus getStatus(void) const
Return current status of the node.
Definition spacenode.hpp:71
bool hasOpenChildren(void)
Return whether the subtree of this node has any open children.
Node class that supports visual layout
int getOffset(void)
Return offset off this node from its parent.
bool isBookmarked(void)
Return whether node is bookmarked.
bool isHidden(void)
Return if node is hidden.
bool isMarked(void)
Return whether node is marked.
bool childrenLayoutIsDone(void)
Return whether the layout of the node's children has been completed.
bool isOnPath(void)
Return whether node is on the path.
The Gecode Interactive Search Tool.
const double shadowOffset
const double failedWidth
const double halfNodeWidth
@ UNDETERMINED
Node that has not been explored yet.
Definition spacenode.hh:48
@ UNSTOP
Node representing ignored stop point.
Definition spacenode.hh:50
@ FAILED
Node representing failure.
Definition spacenode.hh:46
@ STOP
Node representing stop point.
Definition spacenode.hh:49
@ SOLVED
Node representing a solution.
Definition spacenode.hh:45
@ BRANCH
Node representing a branch.
Definition spacenode.hh:47
const double hiddenDepth
const double nodeWidth
const double halfFailedWidth
const double quarterFailedWidthF
Gecode toplevel namespace
void path(Home home, const IntVarArgs &x, IntVar s, IntVar e, IntPropLevel ipl=IPL_DEF)
Post propagator such that x forms a Hamiltonian path.
Definition circuit.cpp:169