запуск примера draw_polygon в пакете CGAl в приложении qt виджета - PullRequest
0 голосов
/ 14 ноября 2018

Я пытаюсь следовать примеру CGAL в приложении виджета Qt: пример

main.ccp:

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
     MainWindow w;
 w.show();

        return a.exec();
}

mainwindow.ccp:

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/draw_polyhedron.h>
#include <fstream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel  Kernel;
typedef CGAL::Polyhedron_3<Kernel>                       Polyhedron;

void MainWindow::on_pushButton_clicked()
{
   QString fileName = QFileDialog::getOpenFileName(this,tr("Open .off model"), "/home", tr("*.off"));

draw_poly(fileName);
 }

void MainWindow::draw_poly(QString fileName)
{
    QByteArray inBytes;
    const char *c;
     inBytes = fileName.toUtf8();
     c = inBytes.constData();
          std::ifstream input(c);

          if (!input || !(input >> mesh) || mesh.is_empty()) {
            std::cerr << "Not a valid off file." << std::endl;
         //   return 1;
          }

          input >> mesh;

          CGAL::draw(mesh);
}

когда я его запустил, он открывает диалоговый файл для выбора файла .off, затем он показывает следующую ошибку:

QCoreApplication::exec: The event loop is already running

любая помощь, пожалуйста

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

CGAL :: draw () уже обрабатывает материал Qt.Вы пытаетесь открыть главное окно в другом.Просто вызовите CGAL :: draw (mesh) в вашей функции main () без чего-либо еще, и это сработает.

РЕДАКТИРОВАТЬ: Это именно то, что Шефф объяснил гораздо более подробно.

0 голосов
/ 14 ноября 2018

Я использую Qt5 в повседневной работе и однажды рассматривал CGAL в качестве возможной прикладной базы (не углубляясь в этом направлении - пока нет).Следовательно, этот вопрос вызвал у меня любопытство.

Я покопался в исходном коде CGAL на github и выяснил, почему появляется сообщение об ошибке

QCoreApplication::exec: The event loop is already running

.

Для этогоЯ скопировал соответствующие строки из CGAL на github: Многогранник / include / CGAL / draw_polyhedron.h :

template<class Polyhedron, class ColorFunctor>
void draw(const Polyhedron& apoly,
          const char* title,
          bool nofill,
          const ColorFunctor& fcolor)
{  
#if defined(CGAL_TEST_SUITE)
  bool cgal_test_suite=true;
#else
  bool cgal_test_suite=false;
#endif

  if (!cgal_test_suite)
  {
    int argc=1;
    const char* argv[2]={"polyhedron_viewer","\0"};
    QApplication app(argc,const_cast<char**>(argv));
    SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>
      mainwindow(app.activeWindow(), apoly, title, nofill, fcolor);
    mainwindow.show();
    app.exec();
  }
}

Глядя на этот исходный код, становится очевидным, что CGAL::draw()небольшое полнофункциональное приложение Qt, которое создает собственный экземпляр QApplication.ОП, в свою очередь, попытался вставить CGAL::draw() в ее / его собственное приложение Qt.Не допускается создавать экземпляры любых производных QCoreApplication более одного раза (в соответствии с документом Qt QApplication):

Для любого приложения с графическим интерфейсом, использующего Qt, существуетэто точно один объект QApplication, независимо от того, имеет ли приложение 0, 1, 2 или более окон в любой момент времени.

(Подчеркивая не мой.)

Документ CGAL.предоставляет (еще более короткий) пример в Polyhedron / draw_polyhedron.cpp , чтобы сделать это правильно:

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/draw_polyhedron.h>
#include <fstream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel  Kernel;
typedef CGAL::Polyhedron_3<Kernel>                       Polyhedron;
int main(int argc, char* argv[])
{
  Polyhedron P;
  std::ifstream in1((argc>1)?argv[1]:"data/cross.off");
  in1 >> P;
  CGAL::draw(P);
  return EXIT_SUCCESS;
}

, но нет места для вставки QFileDialog в нужной точке.

Следовательно, CGAL::draw() - это неправильный инструмент для того, что OP (вероятно) намеревается сделать - внедрить рендеринг многогранника CGAL в приложение Qt.Для этого необходимо напрямую использовать вещи, которые называются где-то внутри CGAL::draw().

Итак, вот что мне кажется подходящим:создание SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> (основного или дочернего) виджета в OP-приложении Qt.

Затем я немного прошелся по репозиторию github, чтобы выяснить, из какого виджета Qt на самом деле CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> происходит, и нашел следующее наследование.:

CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>
                           |
                           V
                 CGAL::Basic_viewer_qt
                           |
                           V
                   CGAL::QGLViewer
                           |
            +--------------+--------------+
            |                             |
            V                             V
      QOpenGLWidget               QOpenGLFunctions

Итак, CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> можно использовать как любой QWidget (что подразумевает превращение его в главное окно).Он также может стать центральным виджетом QMainWindow, который получает строку меню / панель инструментов с QAction, чтобы открыть QFileDialog, запросить путь к файлу, открыть поток файлов с этим путем к файлу и загрузитьсетка из этого файлового потока.

Есть еще одна небольшая деталь, на которую я наткнулся: CGAL::Polyhedron должен быть передан CGAL::SimplePolyhedronViewerQt в конструкторе и по константной ссылке.Чтобы учесть это, ИМХО необходимо (после успешной загрузки сетки) создать экземпляр CGAL::SimplePolyhedronViewerQt с помощью new и впоследствии установить / добавить его в родительский виджет.Если это неприемлемо, вероятно, нужно пойти еще глубже и заменить CGAL::SimplePolyhedronViewerQt собственной реализацией, используя исходный код первого в качестве «шпаргалки».

Вот как такое приложение могло бывыглядит так:

#include <fstream>

#include <QtWidgets>

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/draw_polyhedron.h>

typedef CGAL::Exact_predicates_inexact_constructions_kernel  Kernel;
typedef CGAL::Polyhedron_3<Kernel>                       Polyhedron;

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  CGAL::DefaultColorFunctorPolyhedron fColor;
  Polyhedron mesh;
  // setup UI
  QMainWindow qWin;
  QToolBar qToolbar;
  QAction qCmdLoad(QString::fromUtf8("Load File..."));
  qToolbar.addAction(&qCmdLoad);
  qWin.addToolBar(&qToolbar);
  qWin.show();
  // install signal handlers
  QObject::connect(&qCmdLoad, &QAction::triggered,
    [&qWin, &mesh, &fColor]() {
      const QString filePath = QFileDialog::getOpenFileName(
        &qWin,
        QString::fromUtf8("Open .off model"),
        QString::fromUtf8("/home"),
        QString::fromUtf8("*.off"));
      if (filePath.isEmpty()) return;
      std::ifstream fIn(filePath.toUtf8().data());
      if (!(fIn >> mesh) || mesh.is_empty()) {
        qDebug() << "Loading of" << filePath << "failed!";
        return;
      }
      qWin.setCentralWidget(
        new CGAL::SimplePolyhedronViewerQt<Polyhedron, CGAL::DefaultColorFunctorPolyhedron>(
          &qWin, mesh, "Basic Polyhedron Viewer", false, fColor));
      qWin.centralWidget()->show();
    });
  // runtime loop
  return app.exec();
}

Пожалуйста, возьмите это с «зерном соли» - у меня нет CGAL под рукой, и я не смог скомпилировать / протестировать приведенный выше код.

...