Fréchet View  1.6.0
A Tool for Exploring Fréchet Distance Algorithms
frechetviewapplication.cpp
Go to the documentation of this file.
1 
3 #include <concurrency.h>
4 #include <input/datapath.h>
5 #include <poly_path.h>
6 #include <poly/jobs.h>
7 
8 #include <QFileDialog>
9 #include <QErrorMessage>
10 #include <QMessageBox>
11 #include <QStandardPaths>
12 #include <QDesktopServices>
13 #include <QDebug>
14 
15 #include <QJsonDocument>
16 #include <QJsonObject>
17 #include <QJsonArray>
18 
19 #include "ui_mainwindow.h"
20 
21 using namespace frechet;
22 using namespace poly;
23 using namespace app;
24 using namespace view;
25 using namespace input;
26 
27 FrechetViewApplication* FrechetViewApplication::frechetViewApp = nullptr;
28 
29 FrechetViewApplication::FrechetViewApplication(QString exec_path, bool withGui)
30  : history(), currentId(0),
31  reader(),
32  path(""),
33  fileWatch(nullptr),
34  P(), Q(),
35  grid(NULL),
36  freeSpace(NULL),
37  fspath(NULL),
38  kAlgorithm(NULL),
39  polyAlgorithm(NULL),
40  epsMax(0.0),
41  window(NULL),
42  bgJob(),
43  _currentAlgorithm(ALGORITHM_CURVE)
44 {
45  execPath = exec_path;
46  if (withGui) {
47  fileWatch = new QFileSystemWatcher;
48  }
49  Q_ASSERT(frechetViewApp==nullptr);
50  frechetViewApp = this;
51 }
52 
54 {
55  bgJob.shutDown();
56  delete fileWatch;
57  frechetViewApp = nullptr;
58 }
59 
60 void FrechetViewApplication::init(QString file)
61 {
62  history.init("file.history");
63 
64  Q_ASSERT(P.empty() && Q.empty());
66  freeSpace.reset();
67  fspath.reset();
68  kAlgorithm.reset();
69  polyAlgorithm.reset();
70 
71  window = new MainWindow;
72 
73  QSettings settings;
74  history.restore(settings);
76 
77  window->getControlPanel()->blockSignals(true); // do not trigger free-space calculation, yet
78  // signals will be enabled at the end of open()
79  window->restoreSettings(settings);
80 
81  // read command line args
82  if (file.isEmpty())
83  file = history.lastFile();
84 
85  open(file);
86 
87  connect(window->actionOpen(), SIGNAL(triggered()),
88  this, SLOT(open()));
89  connect(window->actionQuit(), SIGNAL(triggered()),
90  this, SLOT(quit()));
91 
92  connect(&history, SIGNAL(open(QString)), this, SLOT(open(QString)));
93 
94  if (fileWatch) {
95  connect(fileWatch, SIGNAL(fileChanged(QString)),
96  this, SLOT(open(QString)),
97  Qt::QueuedConnection);
98  }
99 
100  // populate Bookmarks
101  bool presentation_mode = populateBookmarks();
102  presentation_mode = true;
103  if (!presentation_mode) {
104  window->ui->menuExperimental->setEnabled(false);
105  window->ui->menuView->removeAction(window->ui->menuExperimental->menuAction());
106  window->ui->actionShow_Animation->setEnabled(false);
107  window->ui->actionShow_XAnimation->setEnabled(false);
108  window->ui->actionStart_Animation->setEnabled(false);
109  window->ui->actionStart_FSAnimation->setEnabled(false);
110  window->ui->actionStart_CVAnimation->setEnabled(false);
111  window->ui->actionStart_ProjectionAnimation->setEnabled(false);
112  }
113 
114  // Desktop Integration
115 #ifdef Q_OS_LINUX
116  settings.beginGroup("desktop");
117  //QString execPath = arguments().first();
118 
119  QString installPath = settings.value("exec.path").toString();
120  bool iconsInstalled = settings.value("icons.installed").toBool();
121 
122  if (execPath != installPath) {
123  installLinuxDesktopEntries(settings);
124  settings.setValue("exec.path",execPath);
125  }
126  if (!iconsInstalled) {
127  installLinuxDesktopIcons(settings);
128  settings.setValue("icons.installed",true);
129  }
130  settings.endGroup();
131 #endif
132 
133  if (file.isEmpty() && showFirstTimeHint())
134  open(true);
135 }
142 {
143  bool modified = (_currentAlgorithm != alg);
144  _currentAlgorithm = alg;
145  // update FSPath
146  if (freeSpace) {
147  switch (_currentAlgorithm) {
148  case ALGORITHM_CURVE:
149  if (modified || !fspath)
151  break;
152  case ALGORITHM_POLYGON:
153  if (modified || !fspath)
155  break;
156  case ALGORITHM_K_FRECHET:
157  fspath.reset();
158  break;
159  }
160  } else {
161  fspath.reset();
162  }
163 
164  if (modified)
166 }
167 
169 {
171  polyAlgorithm->resetStatus();
173  // TODO shouldn't this be done through a signal?
174 }
175 
176 void FrechetViewApplication::open(bool firstTime) {
177 
178  QSettings settings;
179  QFileDialog fdlg;
180 
181  fdlg.restoreState(settings.value("filedialog.open").toByteArray());
182  fdlg.setAcceptMode(QFileDialog::AcceptOpen);
183  fdlg.setFileMode(QFileDialog::ExistingFile);
184  fdlg.setNameFilters(DataPath::INPUT_FILTERS);
185 
186  QString dir;
187  if (firstTime)
188  dir = "../../..";
189  else
190  dir = settings.value("filedialog.open.dir").toString();
191  fdlg.setDirectory(dir);
192 
193 // fdlg.setHistory(history);
194  QStringList fileNames;
195  if (fdlg.exec()) {
196  fileNames = fdlg.selectedFiles();
197  if (!fileNames.isEmpty())
198  open(fileNames.first());
199  }
200 
201  settings.setValue("filedialog.open",fdlg.saveState());
202  settings.setValue("filedialog.open.dir",fdlg.directory().absolutePath());
203 }
204 
205 void FrechetViewApplication::open(QString filePath)
206 {
207  QSettings settings;
208  if (currentId)
209  saveFileSettings(settings,currentId);
210 
211  QString oldPath = path.getFile().absoluteFilePath();
212  path = filePath;
213  QString newPath = path.getFile().absoluteFilePath();
214 
215  if (fileWatch) {
216  if (!oldPath.isEmpty())
217  fileWatch->removePath(oldPath);
218  fileWatch->addPath(newPath);
219  }
220 
221  reader.clear();
222  freeSpace.reset();
223  fspath.reset();
224  kAlgorithm.reset();
225  polyAlgorithm.reset();
226 
227  if (!filePath.isEmpty()) {
229 
230  if (reader.getResults().size() < 2) {
231  // something is missing
232  QErrorMessage* msg = new QErrorMessage();
233  msg->showMessage(reader.errorMessage());
234  }
235  }
236 
237  if (reader.getResults().size() >= 2) {
238  QVector<Path> paths = reader.getResults();
239 
240  /* Note: for scripted files,
241  * coordinates are rounded to 8 decimal places
242  * to avoid nasty geometrical problems (especially
243  * with convex decomposition, etc.).
244  * */
245  int precision = 0; //der.isScript() ? 8:0;
246 
247  P = paths[0].toCurve(precision);
248  Q = paths[1].toCurve(precision);
249 
250  bool p_is_primary = setupCurves();
251 
252  grid->setCurves(P,Q);
253  grid->hor().setLineStyles(
254  paths[p_is_primary?0:1].getLineStyles(),
255  paths[p_is_primary?0:1].getDefaultLineStyle());
256  grid->vert().setLineStyles(
257  paths[p_is_primary?1:0].getLineStyles(),
258  paths[p_is_primary?1:0].getDefaultLineStyle());
259  }
260  else {
261  P = frechet::Curve();
262  Q = frechet::Curve();
263 
264  setupCurves();
265 
266  grid->setCurves(P,Q);
267  grid->hor().setLineStyles(LineStyleVector(),SOLID);
268  grid->vert().setLineStyles(LineStyleVector(),SOLID);
269  }
270 
271  // calculate Free-Space Diagram
273  //fspath = frechet::reach::FSPath::ptr(new frechet::reach::FSPath(freeSpace));
275 
276  Q_ASSERT(freeSpace->P==P);
277  Q_ASSERT(freeSpace->Q==Q);
278  Q_ASSERT(freeSpace->n==P.size());
279  Q_ASSERT(freeSpace->m==Q.size());
280 
281  //
282  connect(polyAlgorithm.get(), SIGNAL(statusChanged()),
283  window->getControlPanel(), SLOT(updateResults()), Qt::QueuedConnection);
284 
285 // connect(polyAlgorithm.get(), SIGNAL(optimisationResult(double)),
286 // window->getFreeSpaceView(), SLOT(calculateFreeSpace(double)));
287  connect(polyAlgorithm.get(), SIGNAL(optimisationResult(double)),
288  window->getControlPanel(), SLOT(setEpsilonWithoutNotify(double)));
289  connect(polyAlgorithm.get(), SIGNAL(optimisationResult(double)),
290  window->getFreeSpaceView(), SLOT(calculateFreeSpace(double)));
291 
292  connect(polyAlgorithm.get(), SIGNAL(pathUpdated(bool)),
293  window->getFreeSpaceView(), SLOT(showPath(bool)));
294 
295  connect(this, SIGNAL(algorithmChanged(int)),
296  this, SLOT(resetAlgorithms()));
297  connect(window->getControlPanel(), SIGNAL(epsilonChanged(double)),
298  this, SLOT(resetAlgorithms()));
299 
300  connect(kAlgorithm.get(), SIGNAL(greedyFinished()),
301  window->getControlPanel(), SLOT(updateResults()), Qt::QueuedConnection);
302 
303  connect(kAlgorithm.get(), SIGNAL(bruteForceFinished()),
304  window->getControlPanel(), SLOT(updateResults()), Qt::QueuedConnection);
305  connect(kAlgorithm.get(), SIGNAL(bruteForceIteration(int)),
306  window->getControlPanel(), SLOT(updateResults()), Qt::QueuedConnection);
307 // connect(kAlgorithm.get(), SIGNAL(bruteForceCancelled()),
308 // window->getControlPanel(), SLOT(updateResults()));//, Qt::QueuedConnection);
309 // connect(kAlgorithm.get(), SIGNAL(bruteForceFinished()),
310 // window->getFreeSpaceView(), SLOT(showOptimalResult(true)), Qt::QueuedConnection);
311 // connect(kAlgorithm.get(), SIGNAL(bruteForceCancelled()),
312 // window->getFreeSpaceView(), SLOT(showOptimalResult(false)), Qt::QueuedConnection);
313 
314  //QRectF boundingRect = P.boundingRect().united(Q.boundingRect());
316 
317  // view
318  window->setWindowTitle(path.getFile().fileName());
322  window->show();
323 
324  // restore file settings
325  if (!filePath.isEmpty()) {
326  currentId = history.insert(filePath);
327  window->ui->actionEdit_Curve->setEnabled(true);
328  }
329  else {
330  currentId = 0;
331  window->ui->actionEdit_Curve->setEnabled(false);
332  }
333 
334  // set eps, but don't trigger redraw until parameters are complete
335  // (note: calculateFreeSpace will be called directly, below)
336  window->getControlPanel()->blockSignals(true);
339 
340 // window->show();
341  if (currentId)
342  restoreFileSettings(settings,currentId);
343 
346 
347  if (currentId)
348  restoreFileSettings(settings,currentId); // zoom,scroll
349  // Note: scroll settings need to be restored after the scene is constructed.
350  // That's why restoreFileSettings is called *twice*.
351  window->getControlPanel()->blockSignals(false);
352 
353  emit fileOpened(filePath);
354 }
355 
357 {
358  QMessageBox msg(window);
359  msg.setText(qApp->applicationDisplayName()+" "
360  + qApp->applicationVersion()+ "\n\n"
361  + "Build: "+__DATE__+" "+__TIME__);
362  msg.setIconPixmap(window->windowIcon().pixmap(64,64));
363  msg.exec();
364 }
365 
367 {
368  QDir desktopDir = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
369  QDir appDir = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation);
370 #ifdef Q_OS_LINUX
371  // cp :/frechet-view.desktop ~/Desktop/frechet-view.desktop
372  QString target = desktopDir.filePath("frechet-view.desktop");
373 
374  copyContents(linuxDesktopFile().toLocal8Bit(), target);
375  // chmod a+x
376  QFile::setPermissions(target,
377  QFile::ReadUser|QFile::ReadGroup|QFile::ReadOther|
378  QFile::WriteUser|
379  QFile::ExeGroup|QFile::ExeUser|QFile::ExeOther);
380 #endif
381 #ifdef Q_OS_MAC
382  // create symbolic link on desktop
383  // point to "Fréchet View.app" instead of app/Contents/MacOS/executable
384  QDir dir = QFileInfo(this->execPath).dir();
385  dir.cdUp();
386  dir.cdUp();
387  bool created = QFile::link( dir.absolutePath(),
388  desktopDir.absoluteFilePath("Fréchet View"));
389  Q_ASSERT(created);
390 #endif
391 #ifdef Q_OS_WIN
392  // create symbolic link on desktop
393  bool created = QFile::link( this->execPath, desktopDir.absoluteFilePath("Fréchet View.lnk"));
394  Q_ASSERT(created);
395  // and Start menu entry!
396  created = QFile::link( this->execPath, appDir.absoluteFilePath("Fréchet View.lnk"));
397 #endif
398 }
399 
401 {
402  if (path.getFile().exists()) {
403  QDesktopServices::openUrl(
404  QUrl::fromLocalFile(
405  path.getFile().absoluteFilePath()));
406  }
407 }
408 
410 {
411  double epsilon = window->getControlPanel()->getEpsilon();
412  startStopDecidePolygon(epsilon);
413 }
414 
416 {
418  //Q_ASSERT(polyAlgorithm->canDecidePoly());
419  if(polyAlgorithm->canDecidePoly())
420  {
423  freeSpace, fspath,
424  epsilon);
425  bgJob.startJob(job);
426  }
427 }
428 
430 {
432 }
433 
435 {
436  double approx = epsMax * 1e-5;
437  startStopOptimisePolygon(approx);
438 }
439 
441 {
443  // Q_ASSERT(polyAlgorithm->canOptimisePoly());
444  if(polyAlgorithm->canOptimisePoly()) // SET_UP, YES,NO
445  {
447  bgJob.startJob(job);
448  }
449 }
450 
452 {
454 }
455 
457 {
458  double approx = epsMax * 1e-5;
459  startStopOptimiseCurve(approx);
460 }
461 
463 {
465 
466  //Q_ASSERT(polyAlgorithm->canOptimiseCurve());
467  if(polyAlgorithm->canOptimiseCurve()) // SET_UP, YES,NO,P_CONVEX,Q_CONVEX
468  {
470  bgJob.startJob(job);
471  }
472 }
473 
475 {
478  bgJob.startJob(job);
479 }
480 
482 {
483  bgJob.cancelJob();
484 }
485 
486 
488 {
489  // cp :/frechet-view.svg ~/.local/share/icons/default/scalable/frechet-view.svg
490  QString iconDir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
491  if (iconDir==nullptr || iconDir.isEmpty()) return;
492 
493  iconDir += "/.local/share/icons";
494 
495  QStringList themes = { "default","hicolor" };
496  QStringList sizes = { "16","32","48","64","96","128","256"};
497 
498  foreach(QString theme, themes)
499  {
500  copyFile(":/frechet-view.svg",
501  iconDir+"/"+theme+"/scalable/apps/frechet-view.svg");
502 
503  foreach(QString size, sizes)
504  copyFile(":/frechet-view-"+size+".png",
505  iconDir+"/"+theme+"/"+size+"x"+size+"/apps/frechet-view.png");
506  }
507 }
508 
510 {
511  // cp :/frechet-view.desktop ~/.local/share/applications/frechet-view.desktop
512  QString applDir = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation);
513  if (applDir.isEmpty()) return;
514 
515  QString desktop = linuxDesktopFile();
516  if (desktop.isEmpty()) return;
517 
518  copyContents(desktop.toLocal8Bit(),
519  applDir+"/frechet-view.desktop");
520 }
521 
523 {
524  Q_ASSERT(!execPath.isEmpty());
525  //QString execEntry = "Exec="+execPath;
526  QByteArray execName = "frechet-view.sh";
527  QString iconPath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
528  if (iconPath.isEmpty()) return "";
529 
530  iconPath += "/.local/share/icons/hicolor/scalable/apps/frechet-view.svg";
531  QString iconEntry = "Icon="+iconPath;
532 
533  QFile desktopFile (":/frechet-view.desktop");
534  if (!desktopFile.open(QFile::ReadOnly)) return "";
535 
536  QByteArray desktopContentsArray = desktopFile.readAll();
537  if (desktopContentsArray.isEmpty()) return "";
538 
539  QString desktopContents = desktopContentsArray;
540 
541  int i1 = desktopContents.indexOf("Exec=");
542  i1 = desktopContents.indexOf(execName,i1);
543 
544  desktopContents.replace(
545  i1, execName.length(),
546  execPath);
547 
548  desktopContents.replace(
549  "Icon=frechet-view",
550  iconEntry);
551  return desktopContents;
552 }
553 
555 {
556  /* Bookmarks are stored in a json file, bookmarks.json
557  * in the preferences directory
558  * */
559  QString bookmarkPath = QStandardPaths::locate(
560  QStandardPaths::AppConfigLocation,
561  "bookmarks.json",QStandardPaths::LocateFile);
562  //QStringList configDirectories = QStandardPaths::standardLocations(QStandardPaths::AppConfigLocation);
563  if (bookmarkPath==nullptr || bookmarkPath.isEmpty())
564  return false;
565 
566  // read json data
567  QFile bookmarkFile(bookmarkPath);
568  if (!bookmarkFile.open(QFile::ReadOnly))
569  return false;
570 
571  QByteArray jsonData = bookmarkFile.readAll();
572  QJsonParseError parseError;
573  QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData,&parseError);
574  if (parseError.error != QJsonParseError::NoError) {
575  std::cerr << parseError.errorString().toStdString() << std::endl;
576  return false;
577  }
578 
579  QToolBar* toolBar = window->ui->mainToolBar;
580  bool any=false;
581  QIcon fileIcon(":awesome/file-regular.svg");
582 
583  QJsonObject root = jsonDoc.object();
584  QString baseDirectory = root["base-directory"].toString();
585 
586  QJsonArray bookmarks = root["bookmarks"].toArray();
587  foreach(QJsonValue bookmark, bookmarks) {
588  QString file = bookmark["file"].toString();
589  QString label = bookmark["label"].toString();
590  QString shortCut = bookmark["short-cut"].toString();
591 
592  if (!any) toolBar->addSeparator();
593  any = true;
594 
595  QAction* action = toolBar->addAction(fileIcon, label, [=]{ this->open(baseDirectory+QDir::separator()+file); });
596  action->setShortcut(QKeySequence::fromString(shortCut));
597  action->setToolTip(file+" "+shortCut);
598  }
599 
600  toolBar->setIconSize(QSize(14,14));
601  return true;
602 }
603 
604 void FrechetViewApplication::copyContents(QByteArray contents, QString dst)
605 {
606  QFileInfo dinfo(dst);
607  QDir("/").mkpath(dinfo.absolutePath());
608  QFile dfile(dst);
609  dfile.open(QFile::WriteOnly);
610  dfile.write(contents.constData());
611 }
612 
613 void FrechetViewApplication::copyFile(QString src, QString dst)
614 {
615  QFileInfo dinfo(dst);
616  QDir("/").mkpath(dinfo.absolutePath());
617  QFile::copy(src,dst);
618 }
619 
620 
621 void FrechetViewApplication::saveFileSettings(QSettings& settings, size_t histId)
622 {
623  history.beginFile(settings,histId);
624 
625  window->getCurveView()->saveSettings(settings,"view.curve");
626  window->getFreeSpaceView()->saveSettings(settings,"view.freespace");
627  window->getControlPanel()->saveSettings(settings,"controls");
628 
629  history.endFile(settings);
630 }
631 
632 void FrechetViewApplication::restoreFileSettings(QSettings& settings, size_t histId)
633 {
634  history.beginFile(settings,histId,true);
635 
636  window->getCurveView()->restoreSettings(settings,"view.curve");
637  window->getFreeSpaceView()->restoreSettings(settings,"view.freespace");
638  window->getControlPanel()->restoreSettings(settings,"controls");
639 
642 
643  history.endFile(settings);
644 }
645 
647 {
648  polyAlgorithm = frechet::poly::newPolyAlgorithm(topo); // topological sorting is only applicable in command-line-version
650 
651  if (stat <= frechet::poly::Algorithm::Status::RUNNING) {
652  Q_ASSERT(false); // not supposed to happen
653  }
654 
655  switch(stat)
656  {
657  case frechet::poly::Algorithm::Status::SET_UP:
658  // OK
659  break;
660  case frechet::poly::Algorithm::Status::RUNNING:
661  case frechet::poly::Algorithm::Status::YES:
662  case frechet::poly::Algorithm::Status::NO:
663  case frechet::poly::Algorithm::Status::NOT_SET_UP:
664  Q_ASSERT(false);
665  break;
666 
667  case frechet::poly::Algorithm::Status::P_EMPTY:
668  case frechet::poly::Algorithm::Status::Q_EMPTY:
669 
670  case frechet::poly::Algorithm::Status::P_NOT_SIMPLE:
671  case frechet::poly::Algorithm::Status::Q_NOT_SIMPLE:
672  // nothing to do
673  return true;
674 
675  case frechet::poly::Algorithm::Status::P_NOT_CLOSED:
676  case frechet::poly::Algorithm::Status::Q_NOT_CLOSED:
677  if (P.isClosed()) {
678  return true;
679  }
680  else {
681  // prefer closed curve first
682  polyAlgorithm->swap();
683  std::swap(P,Q);
684  return false;
685  }
686 
687  case frechet::poly::Algorithm::Status::P_NOT_COUNTER_CLOCKWISE:
688  case frechet::poly::Algorithm::Status::Q_NOT_COUNTER_CLOCKWISE:
689  // fix orientation
690  stat = polyAlgorithm->setup(P,Q, true);
691  break;
692  }
693 
694  switch(stat)
695  {
696  case frechet::poly::Algorithm::Status::P_NOT_COUNTER_CLOCKWISE:
697  case frechet::poly::Algorithm::Status::Q_NOT_COUNTER_CLOCKWISE:
698  // already fixed ! if not fixable, the curve is not a proper polygon
699  //Q_ASSERT(false);
700  return true;
701 
702  case frechet::poly::Algorithm::Status::P_CONVEX:
703  case frechet::poly::Algorithm::Status::Q_CONVEX:
704  // convex allows for easier calculation.
705  // We do not care (but may show a hint to the user!?)
706  return true;
707  }
708 
709  /*
710  * Calculate decomposition, choose the smaller one.
711  * We do this VERY early, so that we can swap P and Q.
712  *
713  * (would create lots of dependencies later)
714  * */
715  //bool exact = std::max(P.size(),Q.size()) <= 30;
716  // Note: the exact algorithm is not only expensive O(n^4),
717  // but -so it seems- bug ridden. Better not use it.
718  bool p_is_primary = polyAlgorithm->decompose(false);
719  if (!p_is_primary) {
720  // swap P and Q !!
721  polyAlgorithm->swap();
722  std::swap(P,Q);
723  }
724  Q_ASSERT(polyAlgorithm->Pcurve()==P);
725  Q_ASSERT(polyAlgorithm->Qcurve()==Q);
726 
727  // calculate Triangulations for P an Q
728  polyAlgorithm->triangulate();
729 
730  return p_is_primary;
731 }
732 
734 {
735  QString message = "Please open an input file. \n"
736  "Accepted files are:\n\n"
737  "- Vector graphics (SVG, IPE)\n\t containing two paths\n"
738  "- Script files (*.js); see examples";
739 
740  return QMessageBox::information(window, "Welcome", message,
741  QMessageBox::Open | QMessageBox::Cancel,
742  QMessageBox::Open) == QMessageBox::Open;
743 }
744 
745 
worker job for executing the optimisation variant, or approximation variant, on curves (not on simple...
Definition: jobs.h:140
void installLinuxDesktopEntries(QSettings &)
create a desktop file on a Linux system (or try at least..)
The k-Frechet algorithm.
Definition: kalgorithm.h:113
void swap(gpuword **A, gpuword **B)
size_t currentId
reference to current File
QString linuxDesktopFile()
find location of desktpo file
bool setupCurves(bool topo=false)
set up geometric data structures, like triangulations etc.
void startStopApproximateCurve()
starts, or stops the approximation algorithm for curves
void fileOpened(QString file)
raised when a new file is opened. Triggers changes in all parts of the GUI.
InputReader reader
reads files from disk
void startStopOptimiseCurve()
starts, or stops the optimisation algorithm for curves
void restore(QSettings &settings)
read settings from application preferences
Definition: filehistory.cpp:53
void setCurrentAlgorithm(Algorithm alg)
change current algorithm
void showAboutDialog()
opens the "About" dialog
bool separateCurves() const
Definition: curveview.h:56
void installLinuxDesktopIcons(QSettings &)
create a desktop icon on a Linux system (or try at least..)
QString execPath
path to executable file
void attachMenu(QAction *recent)
attach sub-menu
global definitions for all algorithms.
Algorithm::ptr newPolyAlgorithm(bool topo)
factory method for creating a new algorithm object. Choose the appropriate implementation based on av...
Definition: parallel.cpp:11
Status
indicates the current status of the algorithm. Negative values indicate that the algorithm is current...
Definition: algorithm.h:76
The single application window.
Definition: mainwindow.h:33
void readAll(const DataPath &path)
read polygonal curves from a file
Definition: inputreader.cpp:26
CurveView * getCurveView()
Definition: mainwindow.h:49
Ui::MainWindow * ui
widgets (auto-generated by Qt)
Definition: mainwindow.h:105
ControlPanel * getControlPanel()
Definition: mainwindow.h:47
std::vector< LineStyle > LineStyleVector
Definition: grid.h:26
void restoreSettings(QSettings &settings)
load settings from application preferences
Definition: mainwindow.cpp:168
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
double epsMax
maximum value for epsilon
Grid::ptr grid
manages the free-space grid
void cancelJob()
request the job to be cancelled
poly::Algorithm::ptr polyAlgorithm
the algorithm for simple polygons and curves (if available)
void populateScene()
create the grid lines and an array of CellView objects
virtual void restoreSettings(QSettings &settings, QString group)
load settings from application preferences
Definition: curveview.cpp:189
void createDesktopEntry()
creates an application icon on the users desktop
Algorithm
we have three Fréchet Distance algorithms
Abstract base class for executing the algorithm for simple polygons in a background thread....
Definition: jobs.h:13
compute Fréchet distance between simple polygons
void algorithmChanged(int algo)
raised when another algorithm is selected. Triggers changes in all parts of the GUI.
bool showFirstTimeHint()
show a short hint when the application is opened for the very first time
static const QStringList INPUT_FILTERS
name filters for file input dialogs
Definition: datapath.h:44
void beginFile(QSettings &settings, size_t id, bool forWrite=false)
begin reading or updating file specific settings
FSPath::ptr fspath
the feasible path (if available)
draw a solid line
Definition: grid.h:19
void editInputFile()
opens the input file in an editor
FileHistory history
Open Recent file history.
void restoreFileSettings(QSettings &settings, size_t histId)
read file specific settings from preferences
void cancelBackgroundJob()
stops long-running algorithm (if necessary)
QFileInfo getFile() const
Definition: datapath.h:47
virtual void saveSettings(QSettings &settings, QString group)
store settings to application preferences
Definition: curveview.cpp:180
QVector< Path > & getResults()
Definition: inputreader.h:46
void flipVertical(bool flip)
flip graphics scene vertically
Definition: baseview.cpp:322
void startKBruteForce()
starts the brute-force k-Frechet algorithm
performs mappings to and from the free-space grid
Definition: grid.h:118
void saveSettings(QSettings &settings, QString group)
store settings to application preferences
void startStopOptimisePolygon()
starts, or stops the optimisation algorithm for simple polygons
QString lastFile() const
Definition: filehistory.cpp:94
QPolygonF Curve
a polygonal curve in the plane; with double floating point precision. This type is heavily used throu...
Definition: types.h:20
void shutDown()
cancel all remaining tasks and shut down the global QThreaPool
void startStopApproximatePolygon()
starts, or stops the approximation algorithm for simple polygons
worker job for executing the decision variant of the algorithm for simple polygons.
Definition: jobs.h:73
static FrechetViewApplication * frechetViewApp
singleton instance
void restoreSettings(QSettings &settings, QString group)
load settings from application preferences
void startJob(WorkerJob *new_job)
start a new job
virtual void restoreSettings(QSettings &settings, QString group)
load settings from application preferences
static void copyContents(QByteArray contents, QString path)
copy data to a file on disk
void clearResults()
reset the k-Frechet panel
void endFile(QSettings &settings)
end updating file specific settings
boost::shared_ptr< Grid > ptr
smart pointer to a Grid object
Definition: grid.h:128
worker job for executing the optimisation variant, or approximation variant, of the algorithm for sim...
Definition: jobs.h:105
void open(bool firstTime=false)
initialises the GUI
virtual void saveSettings(QSettings &settings, QString group)
store settings to application preferences
void saveFileSettings(QSettings &settings, size_t histId)
save file specific settings to preferences
void init(QString file)
initialise the GUI application and open a file (optional)
void setSeparateCurves(bool separate)
called when the user clicks the "Separate Curves" button
Definition: mainwindow.cpp:191
The FreeSpace class models the Free-Space Diagram calculated from two curves.
Definition: freespace.h:83
background worker job for running the k-Frechet brute-force algorithm.
Definition: kalgorithm.h:390
void setShowBounds(bool show)
called when the user clicks the "Show Bounds" button
Definition: mainwindow.cpp:186
~FrechetViewApplication()
desctructor; closes all resources and windows
static void copyFile(QString src, QString dest)
copy files on disk
a feasible-path for simple polygons.
Definition: poly_path.h:24
void quit()
quit the application, closing all resources and windows
void resetAlgorithms()
stops running algorithm(s)
FreeSpace::ptr freeSpace
the free-space diagram
size_t insert(QString path, QDateTime date=QDateTime::currentDateTime())
insert a new file into the list
Definition: filehistory.cpp:23
DataPath path
pointer to input data within an xml file
FreeSpaceView * getFreeSpaceView()
Definition: mainwindow.h:51
boost::shared_ptr< kAlgorithm > ptr
smart pointer to an kAlgorithm object
Definition: kalgorithm.h:320
double max_euclidean_distance(const Curve &P, const Curve &Q)
compute the maximum distance between two polygons This value serves as an upper bound for the Frechet...
Definition: numeric.h:318
bool populateBookmarks()
for presentation mode only
void init(QString agroup)
initialize file list and menu
Definition: filehistory.cpp:47
boost::shared_ptr< FreeSpace > ptr
smart pointer to FreeSpace object
Definition: freespace.h:92
void startStopDecidePolygon()
starts, or stops the decision algorithm for simple polygons
void updateResults()
update the k-Frechet panel to show the latest results of the k-Frechet algorithm
void setEpsilonMax(double eps_max)
update the maximum value of epsilon; adjusts the slider control
void clear()
clear results
Definition: inputreader.cpp:20
Calculates a feasible path in the Free-Space given a start point (0,0) and an end point (n-1,...
Definition: fs_path.h:44
compute k-Fréchet distance between two curves
Algorithm _currentAlgorithm
selects current Algorithm
void calculateFreeSpace(double epsilon)
update free-space diagram when epsilon changes. If the curve algorithm is selected,...