Generated on Tue Jan 19 2021 06:15:49 for Gecode by doxygen 1.8.13
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 
36 namespace 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 quarterNodeWidth = halfNodeWidth / 2.0;
59  const double failedWidth = 14.0;
60  const double halfFailedWidth = failedWidth / 2.0;
61  const double quarterFailedWidthF = failedWidth / 4.0;
62  const double shadowOffset = 3.0;
63  const double hiddenDepth =
64  static_cast<double>(Layout::dist_y) + failedWidth;
65 
67  const VisualNode::NodeAllocator& na,
68  BestNode* curBest0,
69  QPainter& painter0,
70  const QRect& clippingRect0, bool showCopies)
71  : NodeCursor<VisualNode>(root,na), painter(painter0),
72  clippingRect(clippingRect0), curBest(curBest0),
73  x(0.0), y(0.0), copies(showCopies) {
74  QPen pen = painter.pen();
75  pen.setWidth(1);
76  painter.setPen(pen);
77  }
78 
79  void
81  Gist::VisualNode* n = node();
82  double parentX = x - static_cast<double>(n->getOffset());
83  double parentY = y - static_cast<double>(Layout::dist_y) + nodeWidth;
84  if (!n->isRoot() &&
85  (n->getParent(na)->getStatus() == STOP ||
86  n->getParent(na)->getStatus() == UNSTOP) )
87  parentY -= (nodeWidth-failedWidth)/2;
88 
89  double myx = x;
90  double myy = y;
91 
92  if (n->getStatus() == STOP || n->getStatus() == UNSTOP)
93  myy += (nodeWidth-failedWidth)/2;
94 
95  if (n != startNode()) {
96  if (n->isOnPath())
97  painter.setPen(Qt::red);
98  else
99  painter.setPen(Qt::black);
100  // Here we use drawPath instead of drawLine in order to
101  // workaround a strange redraw artefact on Windows
102  QPainterPath path;
103  path.moveTo(myx,myy);
104  path.lineTo(parentX,parentY);
105  painter.drawPath(path);
106 
107  QFontMetrics fm = painter.fontMetrics();
108  QString label = na.getLabel(n);
109  int alt = n->getAlternative(na);
110  int n_alt = n->getParent(na)->getNumberOfChildren();
111  int tw = fm.width(label);
112  int lx;
113  if (alt==0 && n_alt > 1) {
114  lx = myx-tw-4;
115  } else if (alt==n_alt-1 && n_alt > 1) {
116  lx = myx+4;
117  } else {
118  lx = myx-tw/2;
119  }
120  painter.drawText(QPointF(lx,myy-2),label);
121  }
122 
123  // draw shadow
124  if (n->isMarked()) {
125  painter.setBrush(Qt::gray);
126  painter.setPen(Qt::NoPen);
127  if (n->isHidden()) {
128  QPointF points[3] = {QPointF(myx+shadowOffset,myy+shadowOffset),
129  QPointF(myx+nodeWidth+shadowOffset,
130  myy+hiddenDepth+shadowOffset),
131  QPointF(myx-nodeWidth+shadowOffset,
132  myy+hiddenDepth+shadowOffset),
133  };
134  painter.drawConvexPolygon(points, 3);
135 
136  } else {
137  switch (n->getStatus()) {
138  case Gist::SOLVED:
139  {
140  QPointF points[4] = {QPointF(myx+shadowOffset,myy+shadowOffset),
141  QPointF(myx+halfNodeWidth+shadowOffset,
142  myy+halfNodeWidth+shadowOffset),
143  QPointF(myx+shadowOffset,
144  myy+nodeWidth+shadowOffset),
145  QPointF(myx-halfNodeWidth+shadowOffset,
146  myy+halfNodeWidth+shadowOffset)
147  };
148  painter.drawConvexPolygon(points, 4);
149  }
150  break;
151  case Gist::FAILED:
152  painter.drawRect(myx-halfFailedWidth+shadowOffset,
153  myy+shadowOffset, failedWidth, failedWidth);
154  break;
155  case Gist::UNSTOP:
156  case Gist::STOP:
157  {
158  QPointF points[8] = {QPointF(myx+shadowOffset-quarterFailedWidthF,
159  myy+shadowOffset),
160  QPointF(myx+shadowOffset+quarterFailedWidthF,
161  myy+shadowOffset),
162  QPointF(myx+shadowOffset+halfFailedWidth,
163  myy+shadowOffset
164  +quarterFailedWidthF),
165  QPointF(myx+shadowOffset+halfFailedWidth,
166  myy+shadowOffset+halfFailedWidth+
167  quarterFailedWidthF),
168  QPointF(myx+shadowOffset+quarterFailedWidthF,
169  myy+shadowOffset+failedWidth),
170  QPointF(myx+shadowOffset-quarterFailedWidthF,
171  myy+shadowOffset+failedWidth),
172  QPointF(myx+shadowOffset-halfFailedWidth,
173  myy+shadowOffset+halfFailedWidth+
174  quarterFailedWidthF),
175  QPointF(myx+shadowOffset-halfFailedWidth,
176  myy+shadowOffset
177  +quarterFailedWidthF),
178  };
179  painter.drawConvexPolygon(points, 8);
180  }
181  break;
182  case Gist::BRANCH:
183  painter.drawEllipse(myx-halfNodeWidth+shadowOffset,
184  myy+shadowOffset, nodeWidth, nodeWidth);
185  break;
186  case Gist::UNDETERMINED:
187  painter.drawEllipse(myx-halfNodeWidth+shadowOffset,
188  myy+shadowOffset, nodeWidth, nodeWidth);
189  break;
190  }
191  }
192  }
193 
194  painter.setPen(Qt::SolidLine);
195  if (n->isHidden()) {
196  if (n->hasOpenChildren()) {
197  QLinearGradient gradient(myx-nodeWidth,myy,
198  myx+nodeWidth*1.3,myy+hiddenDepth*1.3);
199  if (n->hasSolvedChildren()) {
200  gradient.setColorAt(0, white);
201  gradient.setColorAt(1, green);
202  } else if (n->hasFailedChildren()) {
203  gradient.setColorAt(0, white);
204  gradient.setColorAt(1, red);
205  } else {
206  gradient.setColorAt(0, white);
207  gradient.setColorAt(1, QColor(0,0,0));
208  }
209  painter.setBrush(gradient);
210  } else {
211  if (n->hasSolvedChildren())
212  painter.setBrush(QBrush(green));
213  else
214  painter.setBrush(QBrush(red));
215  }
216 
217  QPointF points[3] = {QPointF(myx,myy),
218  QPointF(myx+nodeWidth,myy+hiddenDepth),
219  QPointF(myx-nodeWidth,myy+hiddenDepth),
220  };
221  painter.drawConvexPolygon(points, 3);
222  } else {
223  switch (n->getStatus()) {
224  case Gist::SOLVED:
225  {
226  if (n->isCurrentBest(curBest)) {
227  painter.setBrush(QBrush(orange));
228  } else {
229  painter.setBrush(QBrush(green));
230  }
231  QPointF points[4] = {QPointF(myx,myy),
232  QPointF(myx+halfNodeWidth,myy+halfNodeWidth),
233  QPointF(myx,myy+nodeWidth),
234  QPointF(myx-halfNodeWidth,myy+halfNodeWidth)
235  };
236  painter.drawConvexPolygon(points, 4);
237  }
238  break;
239  case Gist::FAILED:
240  painter.setBrush(QBrush(red));
241  painter.drawRect(myx-halfFailedWidth, myy, failedWidth, failedWidth);
242  break;
243  case Gist::UNSTOP:
244  case Gist::STOP:
245  {
246  painter.setBrush(n->getStatus() == STOP ?
247  QBrush(red) : QBrush(green));
248  QPointF points[8] = {QPointF(myx-quarterFailedWidthF,myy),
249  QPointF(myx+quarterFailedWidthF,myy),
250  QPointF(myx+halfFailedWidth,
251  myy+quarterFailedWidthF),
252  QPointF(myx+halfFailedWidth,
253  myy+halfFailedWidth+
254  quarterFailedWidthF),
255  QPointF(myx+quarterFailedWidthF,
256  myy+failedWidth),
257  QPointF(myx-quarterFailedWidthF,
258  myy+failedWidth),
259  QPointF(myx-halfFailedWidth,
260  myy+halfFailedWidth+
261  quarterFailedWidthF),
262  QPointF(myx-halfFailedWidth,
263  myy+quarterFailedWidthF),
264  };
265  painter.drawConvexPolygon(points, 8);
266  }
267  break;
268  case Gist::BRANCH:
269  painter.setBrush(n->childrenLayoutIsDone() ? QBrush(blue) :
270  QBrush(white));
271  painter.drawEllipse(myx-halfNodeWidth, myy, nodeWidth, nodeWidth);
272  break;
273  case Gist::UNDETERMINED:
274  painter.setBrush(Qt::white);
275  painter.drawEllipse(myx-halfNodeWidth, myy, nodeWidth, nodeWidth);
276  break;
277  }
278  }
279 
280  if (copies && (n->hasCopy() && !n->hasWorkingSpace())) {
281  painter.setBrush(Qt::darkRed);
282  painter.drawEllipse(myx, myy, 10.0, 10.0);
283  }
284 
285  if (copies && n->hasWorkingSpace()) {
286  painter.setBrush(Qt::darkYellow);
287  painter.drawEllipse(myx, myy + 10.0, 10.0, 10.0);
288  }
289 
290  if (n->isBookmarked()) {
291  painter.setBrush(Qt::black);
292  painter.drawEllipse(myx-10-0, myy, 10.0, 10.0);
293  }
294 
295  }
296 
297 }}
298 
299 // STATISTICS: gist-any
bool isOnPath(void)
Return whether node is on the path.
Definition: visualnode.hpp:193
const double hiddenDepth
Node representing stop point.
Definition: spacenode.hh:49
bool hasWorkingSpace(void)
Return whether the node has a working space.
Definition: spacenode.hpp:164
const double failedWidth
NodeStatus getStatus(void) const
Return current status of the node.
Definition: spacenode.hpp:71
static const QColor lightRed
The color for expanded failed nodes.
bool isRoot(void) const
Check if this node is the root of a tree.
Definition: node.hpp:211
static const QColor white
White color.
Static reference to the currently best space.
Definition: spacenode.hh:80
Node representing a branch.
Definition: spacenode.hh:47
DrawingCursor(VisualNode *root, const VisualNode::NodeAllocator &na, BestNode *curBest0, QPainter &painter0, const QRect &clippingRect0, bool showCopies)
Constructor.
bool isHidden(void)
Return if node is hidden.
Definition: visualnode.hpp:129
void path(Home home, int offset, const IntVarArgs &x, IntVar s, IntVar e, IntPropLevel ipl)
Post propagator such that x forms a Hamiltonian path.
Definition: circuit.cpp:124
bool isCurrentBest(BestNode *curBest)
Return whether this node is the currently best solution.
Definition: spacenode.hpp:133
Node representing failure.
Definition: spacenode.hh:46
Node allocator.
Definition: node.hh:48
bool hasFailedChildren(void)
Return whether the subtree of this node has any failed children.
Definition: spacenode.hpp:144
const double quarterNodeWidth
static const QColor green
The color for solved nodes.
Node that has not been explored yet.
Definition: spacenode.hh:48
static const QColor blue
The color for choice nodes.
int n
Number of negative literals for node type.
Definition: bool-expr.cpp:234
static const QColor lightGreen
The color for expanded solved nodes.
const VisualNode ::NodeAllocator & na
The node allocator.
Definition: nodecursor.hh:53
Node representing a solution.
Definition: spacenode.hh:45
const double quarterFailedWidthF
const double shadowOffset
Gecode Interactive Search Tool
Definition: qtgist.hh:81
VisualNode * startNode(void)
Return start node.
Definition: nodecursor.hpp:58
const double halfFailedWidth
static const QColor red
The color for failed nodes.
bool hasOpenChildren(void)
Return whether the subtree of this node has any open children.
Definition: spacenode.hpp:154
static const int dist_y
Definition: visualnode.hh:46
const double nodeWidth
static const QColor orange
The color for the best solution.
void processCurrentNode(void)
Draw the node.
int getParent(void) const
Return the parent.
Definition: node.hpp:182
Post propagator for SetVar SetOpType SetVar y
Definition: set.hh:767
bool childrenLayoutIsDone(void)
Return whether the layout of the node&#39;s children has been completed.
Definition: visualnode.hpp:163
A cursor that can be run over a tree.
Definition: nodecursor.hh:43
bool isMarked(void)
Return whether node is marked.
Definition: visualnode.hpp:173
bool isBookmarked(void)
Return whether node is bookmarked.
Definition: visualnode.hpp:183
Node class that supports visual layout
Definition: visualnode.hh:125
int getOffset(void)
Return offset off this node from its parent.
Definition: visualnode.hpp:147
int getAlternative(const NodeAllocator &na) const
Return alternative number of this node.
Definition: spacenode.hpp:169
Post propagator for SetVar x
Definition: set.hh:767
VisualNode * node(void)
Return current node.
Definition: nodecursor.hpp:46
bool hasCopy(void)
Return whether the node has a copy.
Definition: spacenode.hpp:159
Gecode toplevel namespace
const double halfNodeWidth
static const QColor lightBlue
The color for expanded choice nodes.
bool hasSolvedChildren(void)
Return whether the subtree of this node has any solved children.
Definition: spacenode.hpp:149
Node representing ignored stop point.
Definition: spacenode.hh:50