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