Fréchet View  1.6.0
A Tool for Exploring Fréchet Distance Algorithms
curveview.cpp
Go to the documentation of this file.
1 
2 #include <curveview.h>
4 #include <poly_path.h>
5 
6 using namespace frechet;
7 using namespace view;
8 using namespace app;
9 using namespace poly;
10 using namespace reach;
11 
12 const QPen CurveView::PEN_A(QColor(255,0,0,180), 2.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
13 const QPen CurveView::PEN_B(QColor(0,0,255,180), 2.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
14 
15 const QPen CurveView::PEN_C_DIAGS(QColor(255,255,0,180), 2.0, Qt::DashLine, Qt::RoundCap, Qt::RoundJoin);
16 const QPen CurveView::PEN_T_DIAGS(QColor(180,180,255,180), 2.0, Qt::DotLine, Qt::RoundCap, Qt::RoundJoin);
17 const QPen CurveView::PEN_PASSIVE_DIAGS(QColor(180,180,180,180), 2.0, Qt::DashLine, Qt::RoundCap, Qt::RoundJoin);
18 
19 const double CurveView::SEPARATOR = 0.06;
20 
21 CurveView::CurveView(QWidget *parent)
22  : BaseView(parent,"Curve"),
23  polygon_a(nullptr), polygon_b(nullptr),
24  diagonals_a(nullptr), diagonals_b(nullptr),
25  select_a(nullptr), select_b(nullptr),
26  _separate(false)
27 {
28  view()->setMouseTracking(true);
29  view()->viewport()->setMouseTracking(true);
30 }
31 
33  const Curve& a, const Curve& b,
35 {
36  //graphicsView->setInteractive(true); // we ant to process mouse click events
37  scene->clear();
40  // common bounding box
41  polygon_bounds = a.boundingRect().united(b.boundingRect());
42 
43  /* P: t-Diagonalen (Triangulation außer c-Diagonalen) = */
45  poly->PTriangulation().edges(),
46  poly->c_diagonals(), true,
48  /* P: nur c-Diagonalen */
50  poly->c_diagonals(),
51  false,
53  /* Q: alle Diagonalen außer äußeren Kanten */
55  poly->QTriangulation().edges(),
56  Segments(), false,
58 /*
59  * QGraphicsItemGroup* group,
60  frechet::poly::Triangulation::Edge_range d,
61  const frechet::poly::Segments& exclude,
62  bool exclude_edges,
63  QPen pen
64  */
65  polygon_a->setZValue(+2); // to front
66  polygon_b->setZValue(+2); // to front
67 
68  diagonals_a->setZValue(+1);
69  diagonals_b->setZValue(+1);
70  // Note: Z-Value has bad influence on hoverability !
71 
72  select_a = new QGraphicsPathItem();
73  select_b = new QGraphicsPathItem();
74 
75  select_a->setPen(PEN_SELECT);
76  select_b->setPen(PEN_SELECT);
77 
78  select_a->setVisible(false);
79  select_b->setVisible(false);
80 
81  select_a->setZValue(+3);
82  select_b->setZValue(+3);
83 
84  polygon_a->addToGroup(select_a);
85  polygon_b->addToGroup(select_b);
86 
87  // set pen width relative to scene size
88  double pen_width = std::max(polygon_bounds.width(),polygon_bounds.height()) * 0.005;
89  setPenWidth(polygon_a,pen_width);
90  setPenWidth(polygon_b,pen_width);
91 
92  setPenWidth(diagonals_a,pen_width);
93  setPenWidth(diagonals_b,pen_width);
94 
95  setPenWidth(select_a,3*pen_width);
96  setPenWidth(select_b,3*pen_width);
97 
99 
100  // TODO show (c- and t-) diagonals
101 
102 // scene->setSceneRect(polygon_bounds);
103 // graphicsView->setSceneRect(polygon_bounds);
104 }
105 
106 QGraphicsItemGroup* CurveView::addPolygonToScene(const Curve& poly, QPen pen, GraphicsHoverLineItem::Location hover)
107 {
108  QGraphicsItemGroup* group = new QGraphicsItemGroup();
109  group->setAcceptHoverEvents(hover);
110  group->setHandlesChildEvents(false); // Children handle their mouse events
111  for(int i=0; i+1 < poly.size(); ++i) {
112  QLineF line(poly[i],poly[i+1]);
113  createLineItem(line,pen, Segment(i,i+1), group, hover);
114  }
115  scene->addItem(group);
116  return group;
117 }
118 
119 QGraphicsItemGroup* CurveView::addSegmentsToScene(
120  QGraphicsItemGroup* group,
121  Triangulation::Edge_range dr,
122  const Segments& exclude,
123  bool with_edges,
124  QPen pen, GraphicsHoverLineItem::Location hover)
125 {
126  if (group==nullptr) {
127  group = new QGraphicsItemGroup();
128  group->setAcceptHoverEvents(hover);
129  group->setHandlesChildEvents(false); // Children handle their mouse events
130  scene->addItem(group);
131  }
132  for(auto d = dr.first; d != dr.second; ++d)
133  {
134  if (d.is_outer_edge()) continue; // always ignore
135  if (exclude.find(d.segment()) != exclude.end()) continue;
136  if (d.is_polygon_edge() && !with_edges) continue;
137 
138  QLineF line = d.line();
139  createLineItem(line,pen, d.segment(), group,hover);
140  }
141  return group;
142 }
143 
144 QGraphicsItemGroup* CurveView::addSegmentsToScene(
145  QGraphicsItemGroup* group,
146  const Segments& d,
147  bool with_edges,
148  QPen pen,
149  const Curve& P, GraphicsHoverLineItem::Location hover)
150 {
151  if (group==nullptr) {
152  group = new QGraphicsItemGroup();
153  group->setAcceptHoverEvents(hover);
154  group->setHandlesChildEvents(false); // Children handle their mouse events
155  scene->addItem(group);
156  }
157  for(const Segment& s : d)
158  {
159  if (s.is_edge(P.size()-1) && !with_edges) continue;
160 
161  QLineF line = Grid::mapToSegment(P,s.first,s.second);
162  createLineItem(line,pen, s, group,hover);
163  }
164  return group;
165 }
166 
167 QGraphicsLineItem* CurveView::createLineItem(QLineF line, QPen pen,
168  Segment seg,
169  QGraphicsItemGroup* group,
171 {
172  QGraphicsLineItem* item = new GraphicsHoverLineItem(line,hover,seg.first,seg.second,group);
173  item->setPen(pen);
174  //item->setAcceptHoverEvents(hover);
175  //group->addToGroup(item);
176  return item;
177 }
178 
179 
180 void CurveView::saveSettings(QSettings& settings, QString group)
181 {
182  settings.beginGroup(group);
183  settings.setValue("separate.curves",_separate);
184  settings.endGroup();
185 
186  BaseView::saveSettings(settings,group);
187 }
188 
189 void CurveView::restoreSettings(QSettings& settings, QString group)
190 {
191  settings.beginGroup(group);
192  _separate = settings.value("separate.curves",false).toBool();
193  settings.endGroup();
194 
195  BaseView::restoreSettings(settings,group);
196 
198 }
199 
201 {
202  _separate=on;
203 
204  if (!polygon_a || !polygon_b) return;
205 
206  QRectF ra = polygon_a->boundingRect();
207  QRectF rb = polygon_b->boundingRect();
208 
209  QPointF offseta, offsetb;
210 
211  if (_separate) {
212  // Stack vertical, or horizontal
213  // choose minimal aspect ratio
214  double sep_hor = SEPARATOR * std::max(ra.width(),rb.width());
215  double sep_vert = SEPARATOR * std::max(ra.height(),rb.height());
216 
217  double ar_hor = (ra.width()+rb.width()+sep_hor) / std::max(ra.height(),rb.height());
218  double ar_vert = (ra.height()+rb.height()+sep_vert) / std::max(ra.width(),rb.width());
219 
220  if (ar_hor < ar_vert) {
221  // stack horizontal. Move rects to...
222  offseta = QPointF(-ra.width()-sep_hor/2, -ra.height()/2) - ra.topLeft();
223  offsetb = QPointF(sep_hor/2, -rb.height()/2) - rb.topLeft();
224  }
225  else {
226  // stack vertical
227  offseta = QPointF(-ra.width()/2, -ra.height()-sep_vert/2) - ra.topLeft();
228  offsetb = QPointF(-rb.width()/2, sep_vert/2) - rb.topLeft();
229  }
230 
231  }
232 
233  QTransform ta = QTransform::fromTranslate(offseta.x(),offseta.y());
234  QTransform tb = QTransform::fromTranslate(offsetb.x(),offsetb.y());
235 
236  polygon_a->setTransform(ta);
237  polygon_b->setTransform(tb);
238 
239  diagonals_a->setTransform(ta);
240  diagonals_b->setTransform(tb);
241 
242  onAlgorithmChanged(0); // update visibility of diagonals
243 
244  // adjust scene rect
245  polygon_bounds = ra.translated(offseta.x(),offseta.y())
246  .united(rb.translated(offsetb.x(),offsetb.y()));
247  scene->setSceneRect(polygon_bounds);
248  graphicsView->setSceneRect(polygon_bounds);
249  setupMatrix();
250 }
251 
253 {
254  const reach::FSPath::ptr fspath = FrechetViewApplication::instance()->getFSPath();
255  if (!fspath || fspath->empty())
256  item = selected_item = nullptr;
257 
258  if (item) {
259  doHiliteSegment(item->loc,item->a,item->b);
260  emit hiliteSegment(item->loc, item->a,item->b);
261  }
262  else {
265  }
266 }
267 
268 void CurveView::onHiliteSegment(int loc, int a, int b)
269 {
271 }
272 
274 {
275  const FSPath::ptr fspath = FrechetViewApplication::instance()->getFSPath();
276  if (!fspath || fspath->empty())
278 
279  const poly::Algorithm::ptr polyAlgo = FrechetViewApplication::instance()->getPolyAlgorithm();
280  const Curve& P = FrechetViewApplication::instance()->getP();
281  const Curve& Q = FrechetViewApplication::instance()->getQ();
282  QLineF line;
283 
284  QPainterPath path_a, path_b;
285  Curve mapped[2];
286 
287  switch(loc) {
289  // Map from P to Q
290  line = Grid::mapToSegment(P,a,b);
291  Q_ASSERT(line.p1()!=line.p2());
292  addLine(path_a,line);
293 
294  fspath->mapFromP(poly::Segment(a,b),mapped);
295  fspath->mapToQ(mapped);
296  addPolygon(path_b,mapped[0]);
297  break;
298 
300  // Map from Q to P
301  line = Grid::mapToSegment(Q,a,b);
302  Q_ASSERT(line.p1() != line.p2());
303  addLine(path_b,line);
304 
305  fspath->mapFromQ(poly::Segment(a,b),mapped);
306  fspath->mapToP(mapped);
307  addPolygon(path_a,mapped[0]);
308  break;
309 
311  line = Grid::mapToSegment(P, a, b);
312  addLine(path_a, line);
313  // finc shortest path in Q
314  poly::PolygonFSPath *polyPath = dynamic_cast<poly::PolygonFSPath *>(fspath.get());
315  Q_ASSERT(polyPath);
316  Curve sp = polyPath->findShortestPathQ(a, b, polyAlgo->QTriangulation());
317  addPolygon(path_b, sp);
318  } break;
319 
321  line = Grid::mapToSegment(Q, a, b);
322  addLine(path_b, line);
323  // finc shortest path in P
324  poly::PolygonFSPath *polyPath = dynamic_cast<poly::PolygonFSPath *>(fspath.get());
325  Q_ASSERT(polyPath);
326  Curve sp = polyPath->findShortestPathP(a, b, polyAlgo->displayPTriangulation());
327  addPolygon(path_a, sp);
328  } break;
329 
331  Curve p = fspath->getPath(a);
332  Point p1 = p[b];
333  Point p2 = p[b+1];
334  QLineF l1 = Grid::mapToSegment(P,p1.x(),p2.x());
335  QLineF l2 = Grid::mapToSegment(Q,p1.y(),p2.y());
336  addLine(path_a,l1);
337  addLine(path_b,l2);
338  } break;
339 
341  // clear selection
342  break;
343 
344  default:
345  Q_ASSERT(false);
346  }
347 
348  select_a->setPath(path_a);
349  select_b->setPath(path_b);
350 
351  select_a->setVisible(loc != GraphicsHoverLineItem::None);
352  select_b->setVisible(loc != GraphicsHoverLineItem::None);
353 }
354 
355 void CurveView::onAlgorithmChanged(int algorithm)
356 {
357  bool poly_alg = (FrechetViewApplication::instance()->currentAlgorithm()
358  == FrechetViewApplication::ALGORITHM_POLYGON);
359 
360  if (diagonals_a)
361  diagonals_a->setVisible(poly_alg && _separate);
362  if (diagonals_b)
363  diagonals_b->setVisible(poly_alg && _separate);
364 
365  if (select_a)
366  select_a->setVisible(false);
367  if (select_b)
368  select_b->setVisible(false);
369 }
370 
371 
base class for view widgets.
Definition: baseview.h:79
Represents a polygon line segment from node i to j.
Definition: types.h:39
used for segments that are not mouse sensitive
Definition: baseview.h:243
QGraphicsItemGroup * addPolygonToScene(const Curve &poly, QPen pen, GraphicsHoverLineItem::Location hover)
add a polygon curve to the graphics scene
Definition: curveview.cpp:106
void onAlgorithmChanged(int alg)
called when the user changes the current algorithm. Update the curve display accordingly (e....
Definition: curveview.cpp:355
QGraphicsItemGroup * polygon_b
graphics items for (boundary of) curve Q
Definition: curveview.h:118
QGraphicsView * view() const
Definition: baseview.cpp:302
QGraphicsLineItem * createLineItem(QLineF line, QPen pen, frechet::poly::Segment seg, QGraphicsItemGroup *group, GraphicsHoverLineItem::Location hover)
create a line segment graphics item
Definition: curveview.cpp:167
global definitions for all algorithms.
static const QPen PEN_PASSIVE_DIAGS
Definition: curveview.h:111
std::set< Segment > Segments
a set of Segment objects
Definition: types.h:115
void hiliteSegment(int loc, int a, int b)
raised when a mouse sensitive line segment is highlighted. Parameters identify the location of the li...
void populateScene(const Curve &P, const Curve &Q, frechet::poly::Algorithm::ptr alg)
set up the graphics scene with polygonal curves
Definition: curveview.cpp:32
void setSeparateCurves(bool sep)
update the display to show curves separately, or not
Definition: curveview.cpp:200
friend class GraphicsHoverLineItem
Definition: curveview.h:178
static QLineF mapToSegment(const Curve &C, double x1, double x2)
given a polygonal curve and two offsets, compute the corresponding line segment
Definition: grid.cpp:144
boost::shared_ptr< Algorithm > ptr
(smart) pointer to an Algorithm object
Definition: algorithm.h:236
virtual void restoreSettings(QSettings &settings, QString group)
load settings from application preferences
Definition: curveview.cpp:189
a segment of the feasible paht (displayed in the free-space diagram)
Definition: baseview.h:248
static const QPen PEN_T_DIAGS
pen for drawing the t-diagonals in P
Definition: curveview.h:110
static void addPolygon(QPainterPath &ppath, const QPolygonF &poly)
add a polygon curve segment to a QPainterPath
Definition: baseview.cpp:622
Curve findShortestPathP(int qa, int qb, Triangulation &tri)
given a diagonal in Q, compute the mapped shortest-path in P.
Definition: poly_path.cpp:236
void setupMatrix()
set up transformation matrix to account for zoom,rotate,scroll
Definition: baseview.cpp:374
const Location loc
location on screen
Definition: baseview.h:251
QGraphicsItemGroup * diagonals_b
Definition: curveview.h:120
static const QPen PEN_A
pen for drawing the curve P
Definition: curveview.h:107
CurveView(QWidget *parent=0)
default constructor with parent
Definition: curveview.cpp:21
QGraphicsScene * scene
scene that is displayed by graphicsView
Definition: baseview.h:174
static const QPen PEN_SELECT
pen for drawing selected polygon segment
Definition: baseview.h:163
GraphicsHoverLineItem * selected_item
the currently selected mouse sensitve polyon segment (or nullptr)
Definition: baseview.h:189
a QGraphicsLitem that can handle mouse hover events. It is used to highlight mouse sensitve polygon s...
Definition: baseview.h:239
static const QPen PEN_C_DIAGS
pen for drawing the c-diagonals in P
Definition: curveview.h:109
QPointF Point
a point in the plane; with double floating point precision. This type is heavily used throughout all ...
Definition: types.h:14
virtual void saveSettings(QSettings &settings, QString group)
store settings to application preferences
Definition: curveview.cpp:180
static const QPen PEN_B
pen for drawing the curve Q
Definition: curveview.h:108
boost::shared_ptr< FSPath > ptr
smart pointer to an FSPath object
Definition: fs_path.h:65
QGraphicsItemGroup * addSegmentsToScene(QGraphicsItemGroup *group, frechet::poly::Triangulation::Edge_range d, const frechet::poly::Segments &exclude, bool with_edges, QPen pen, GraphicsHoverLineItem::Location hover)
add a number of line segments to the graphics scene
const int a
parameters loc,a, and b identify a segment.
Definition: baseview.h:257
static const double SEPARATOR
distance when curves are displayed separately
Definition: curveview.h:113
QPolygonF Curve
a polygonal curve in the plane; with double floating point precision. This type is heavily used throu...
Definition: types.h:20
QRectF polygon_bounds
boundary rectangle for both curves
Definition: curveview.h:122
void onHiliteSegment(int loc, int a, int b)
called when a line segment should be highlighted
Definition: curveview.cpp:268
QGraphicsItemGroup * diagonals_a
graphics items for diagonals of curve P
Definition: curveview.h:119
virtual void restoreSettings(QSettings &settings, QString group)
load view settings to application prefs
Definition: baseview.cpp:533
QGraphicsView * graphicsView
the embedded QGraphicsView
Definition: baseview.h:172
QGraphicsItemGroup * polygon_a
graphics items for (boundary of) curve P
Definition: curveview.h:117
void doHiliteSegment(GraphicsHoverLineItem::Location loc, int a, int b)
highlight a line segment
Definition: curveview.cpp:273
bool _separate
draw curves separately?
Definition: curveview.h:115
virtual void saveSettings(QSettings &settings, QString group)
store view settings to application prefs
Definition: baseview.cpp:512
QGraphicsPathItem * select_a
highlited items for curve P
Definition: curveview.h:124
a feasible-path for simple polygons.
Definition: poly_path.h:24
virtual void segmentSelected(GraphicsHoverLineItem *item) override
called when the mouse hovers over a sensitive line segment. Updates the corresponding line segments.
Definition: curveview.cpp:252
Location
location of the polygon segment
Definition: baseview.h:243
Curve findShortestPathQ(int pa, int pb, Triangulation &tri)
given a diagonal in P, compute the mapped shortest-path in Q
Definition: poly_path.cpp:248
QGraphicsPathItem * select_b
highlited items for curve Q
Definition: curveview.h:125
double max(double a, double b)
maximum function with checks for NAN
Definition: numeric.h:233
static void setPenWidth(QGraphicsItem *item, double width)
update the pen width of a graphics item
Definition: baseview.cpp:579
static void addLine(QPainterPath &ppath, const QLineF &line)
add a line segment to a QPainterPath
Definition: baseview.cpp:608