This commit is contained in:
Ahmed Essam 2020-08-30 23:24:51 +02:00
parent bf57baf339
commit b9a08d76d6
10 changed files with 280 additions and 392 deletions

View File

@ -17,7 +17,6 @@
//
// Author(s): Saurabh Singh <ssingh@cs.iitr.ac.in>
#include <CGAL/Arr_algebraic_segment_traits_2.h>
#include <CGAL/Polynomial_traits_d.h>
#include <CGAL/polynomial_utils.h>
@ -149,8 +148,14 @@ AlgebraicCurveParser<Polynomial_d>::operator()(const std::string& expression)
// makes compilation slower
// template class
// AlgebraicCurveParser<demo_types::Alg_seg_traits::Polynomial_2>;
// AlgebraicCurveParser<demo_types::Rational_traits::Polynomial_1>;
#ifdef CGAL_USE_CORE
#include <CGAL/Arr_algebraic_segment_traits_2.h>
#include <CGAL/Algebraic_kernel_d_1.h>
template struct AlgebraicCurveParser<
CGAL::Arr_algebraic_segment_traits_2<CORE::BigInt>::Polynomial_2>;
template struct AlgebraicCurveParser<
typename CGAL::Algebraic_kernel_d_1<CORE::BigInt>::Polynomial_1>;
#endif

View File

@ -128,7 +128,7 @@ void ArrangementDemoPropertiesDialog::updateUi( )
{
return;
}
ArrangementDemoTabBase* currentTab = this->parent->getCurrentTab().first;
ArrangementDemoTabBase* currentTab = this->parent->getCurrentTab();
if ( currentTab == NULL )
{
return;

View File

@ -10,6 +10,7 @@
// Author(s) : Alex Tsui <alextsui05@gmail.com>
#include "ArrangementTypes.h"
#include "ArrangementTypesUtils.h"
#include "ArrangementDemoTab.h"
#include "ArrangementGraphicsItem.h"
#include "ArrangementDemoGraphicsView.h"
@ -25,6 +26,8 @@
#include "PointSnapper.h"
#include "ConstructBoundingBox.h"
#include <CGAL/Qt/GraphicsViewNavigation.h>
#include <QGridLayout>
static constexpr double MAX_WIDTH =
@ -35,14 +38,7 @@ ArrangementDemoTabBase::ArrangementDemoTabBase( QWidget* parent ) :
GraphicsSceneMixin( new QGraphicsScene() ),
graphicsView( new ArrangementDemoGraphicsView( this ) ),
layout( new QGridLayout( this ) ),
curveInputCallback( nullptr ),
deleteCurveCallback( nullptr ),
pointLocationCallback( nullptr ),
verticalRayShootCallback( nullptr ),
mergeEdgeCallback( nullptr ),
splitEdgeCallback( nullptr ),
envelopeCallback( nullptr ),
fillFaceCallback( nullptr ),
navigation( std::make_unique<CGAL::Qt::GraphicsViewNavigation>() ),
activeCallback( nullptr ),
arrangementGraphicsItem( nullptr ),
gridGraphicsItem( nullptr )
@ -65,6 +61,8 @@ void ArrangementDemoTabBase::setupUi( )
double xymin = -MAX_WIDTH / 2;
double wh = MAX_WIDTH;
scene->setSceneRect(xymin, xymin, wh, wh);
this->getView()->installEventFilter(this->navigation.get());
}
QGraphicsView* ArrangementDemoTabBase::getView() const
@ -155,6 +153,12 @@ FillFaceCallbackBase* ArrangementDemoTabBase::getFillFaceCallback( ) const
return this->fillFaceCallback.get();
}
CGAL::Qt::GraphicsViewNavigation*
ArrangementDemoTabBase::getGraphicsViewNavigation() const
{
return this->navigation.get();
}
void ArrangementDemoTabBase::activateCurveInputCallback(CGAL::Qt::CurveType type)
{
this->unhookCallbacks();
@ -262,6 +266,12 @@ ArrangementDemoTab<Arr_>::ArrangementDemoTab(
this->setupCallbacks();
}
template <class Arr_>
demo_types::TraitsType ArrangementDemoTab<Arr_>::traitsType() const
{
return demo_types::enumFromArrType<Arrangement>();
}
template <class Arr_>
ArrangementDemoTab<Arr_>::~ArrangementDemoTab()
{

View File

@ -36,10 +36,16 @@ class ArrangementGraphicsItemBase;
class Callback;
class ArrangementGraphicsItemBase;
class GraphicsViewCurveInputBase;
class GraphicsViewNavigation;
enum class CurveType;
} // namespace Qt
} // namespace CGAL
namespace demo_types
{
enum class TraitsType;
}
class ArrangementDemoTabBase : public QWidget, public GraphicsSceneMixin
{
Q_OBJECT
@ -51,9 +57,11 @@ public:
ArrangementDemoTabBase( QWidget* parent );
virtual ~ArrangementDemoTabBase( );
QGraphicsView* getView() const;
virtual CGAL::Object getArrangement() const = 0;
virtual void adjustViewport() = 0;
virtual demo_types::TraitsType traitsType() const = 0;
QGraphicsView* getView() const;
void showGrid(bool);
bool isGridVisible();
void setSnapToGrid(bool);
@ -61,16 +69,18 @@ public:
bool isSnapToGridEnabled();
bool isSnapToArrangementEnabled();
CGAL::Qt::ArrangementGraphicsItemBase* getArrangementGraphicsItem() const;
GridGraphicsItem* getGridGraphicsItem() const;
CGAL::Qt::GraphicsViewCurveInputBase* getCurveInputCallback() const;
CGAL::Qt::Callback* getDeleteCurveCallback() const;
CGAL::Qt::Callback* getPointLocationCallback() const;
VerticalRayShootCallbackBase* getVerticalRayShootCallback() const;
CGAL::Qt::Callback* getMergeEdgeCallback() const;
SplitEdgeCallbackBase* getSplitEdgeCallback() const;
EnvelopeCallbackBase* getEnvelopeCallback() const;
FillFaceCallbackBase* getFillFaceCallback() const;
auto getArrangementGraphicsItem() const
-> CGAL::Qt::ArrangementGraphicsItemBase*;
auto getGridGraphicsItem() const -> GridGraphicsItem*;
auto getCurveInputCallback() const -> CGAL::Qt::GraphicsViewCurveInputBase*;
auto getDeleteCurveCallback() const -> CGAL::Qt::Callback*;
auto getPointLocationCallback() const -> CGAL::Qt::Callback*;
auto getVerticalRayShootCallback() const -> VerticalRayShootCallbackBase*;
auto getMergeEdgeCallback() const -> CGAL::Qt::Callback*;
auto getSplitEdgeCallback() const -> SplitEdgeCallbackBase*;
auto getEnvelopeCallback() const -> EnvelopeCallbackBase*;
auto getFillFaceCallback() const -> FillFaceCallbackBase*;
auto getGraphicsViewNavigation() const -> CGAL::Qt::GraphicsViewNavigation*;
void activateCurveInputCallback(CGAL::Qt::CurveType);
void activateDeleteCurveCallback();
@ -106,6 +116,7 @@ protected:
std::unique_ptr<EnvelopeCallbackBase> envelopeCallback;
std::unique_ptr<FillFaceCallbackBase> fillFaceCallback;
std::unique_ptr<PointSnapperBase> snapper;
std::unique_ptr<CGAL::Qt::GraphicsViewNavigation> navigation;
CGAL::Qt::Callback* activeCallback;
CGAL::Qt::ArrangementGraphicsItemBase* arrangementGraphicsItem;
@ -125,6 +136,7 @@ public:
~ArrangementDemoTab();
void adjustViewport() override;
CGAL::Object getArrangement() const override;
demo_types::TraitsType traitsType() const override;
private:
void initArrangement();

View File

@ -27,6 +27,7 @@
#include "FillFaceCallback.h"
#include "GridGraphicsItem.h"
#include "ArrangementTypes.h"
#include "ArrangementTypesUtils.h"
#include "Conic_reader.h"
#include <QActionGroup>
@ -44,6 +45,7 @@
#include "ui_ArrangementDemoWindow.h"
using TraitsType = demo_types::TraitsType;
ArrangementDemoWindow::ArrangementDemoWindow(QWidget* parent) :
CGAL::Qt::DemosMainWindow(parent), ui(new Ui::ArrangementDemoWindow),
@ -59,7 +61,7 @@ ArrangementDemoWindow::ArrangementDemoWindow(QWidget* parent) :
this->envelopeGroup, SIGNAL(triggered(QAction*)), this,
SLOT(updateEnvelope(QAction*)));
this->makeTab(SEGMENT_TRAITS);
this->makeTab(TraitsType::SEGMENT_TRAITS);
// Call inherited functions
this->setupStatusBar();
@ -102,97 +104,22 @@ void ArrangementDemoWindow::setupUi()
this->inputTypeGroup->addAction(this->ui->actionBezier);
}
template <class T>
struct TypeHolder
{
using type = T;
};
template <typename T>
static constexpr ArrangementDemoWindow::TraitsType traitFromType()
{
using TraitsType = ArrangementDemoWindow::TraitsType;
using namespace std;
using namespace demo_types;
if (is_same<T, Seg_arr>::value) return TraitsType::SEGMENT_TRAITS;
else if (is_same<T, Pol_arr>::value) return TraitsType::POLYLINE_TRAITS;
else if (is_same<T, Lin_arr>::value) return TraitsType::LINEAR_TRAITS;
#ifdef CGAL_USE_CORE
else if (is_same<T, Conic_arr>::value) return TraitsType::CONIC_TRAITS;
else if (is_same<T, Alg_seg_arr>::value) return TraitsType::ALGEBRAIC_TRAITS;
else if (is_same<T, Bezier_arr>::value) return TraitsType::BEZIER_TRAITS;
else if (is_same<T, Rational_arr>::value) return TraitsType::RATIONAL_FUNCTION_TRAITS;
#endif
else return TraitsType::NONE;
}
template <class Lambda>
static void
visitArrangementType(ArrangementDemoWindow::TraitsType tt, Lambda lambda)
{
using TraitsType = ArrangementDemoWindow::TraitsType;
using namespace demo_types;
switch (tt)
{
default:
case TraitsType::SEGMENT_TRAITS:
lambda(TypeHolder<Seg_arr>{});
break;
case TraitsType::POLYLINE_TRAITS:
lambda(TypeHolder<Pol_arr>{});
break;
case TraitsType::LINEAR_TRAITS:
lambda(TypeHolder<Lin_arr>{});
break;
#ifdef CGAL_USE_CORE
case TraitsType::CONIC_TRAITS:
lambda(TypeHolder<Conic_arr>{});
break;
case TraitsType::ALGEBRAIC_TRAITS:
lambda(TypeHolder<Alg_seg_arr>{});
break;
case TraitsType::BEZIER_TRAITS:
lambda(TypeHolder<Bezier_arr>{});
break;
case TraitsType::RATIONAL_FUNCTION_TRAITS:
lambda(TypeHolder<Rational_arr>{});
break;
#endif
}
}
template <class Lambda>
static void forEachArrangementType(Lambda lambda)
{
using namespace demo_types;
lambda(TypeHolder<Seg_arr>{});
lambda(TypeHolder<Pol_arr>{});
lambda(TypeHolder<Lin_arr>{});
#ifdef CGAL_USE_CORE
lambda(TypeHolder<Conic_arr>{});
lambda(TypeHolder<Alg_seg_arr>{});
lambda(TypeHolder<Bezier_arr>{});
lambda(TypeHolder<Rational_arr>{});
#endif
}
QString ArrangementDemoWindow::makeTabLabel(TraitsType tt)
{
static const char* typeNames[] = {
"Segment", "Polyline", "Linear", "Conic", "Algebraic",
"Bezier", "Rational Functions"
};
return QString("%1 - %2").arg(this->tabLabelCounter++).arg(typeNames[tt]);
return QString("%1 - %2")
.arg(this->tabLabelCounter++)
.arg(typeNames[static_cast<int>(tt)]);
}
ArrangementDemoTabBase* ArrangementDemoWindow::makeTab(TraitsType tt)
{
ArrangementDemoTabBase* demoTab;
QString tabLabel = makeTabLabel(tt);
visitArrangementType(tt, [&](auto type_holder) {
demo_types::visitArrangementType(tt, [&](auto type_holder) {
demoTab =
new ArrangementDemoTab<typename decltype(type_holder)::type>(this);
});
@ -203,13 +130,16 @@ ArrangementDemoTabBase* ArrangementDemoWindow::makeTab(TraitsType tt)
void ArrangementDemoWindow::addTab(
ArrangementDemoTabBase* demoTab, QString tabLabel, TraitsType tt)
{
this->tabs.push_back({demoTab, tt});
this->tabs.push_back(demoTab);
this->ui->tabWidget->addTab(demoTab, tabLabel);
this->ui->tabWidget->setCurrentWidget(demoTab);
// TODO: This causes memory leak because of the existence of multiple tabs
// fix it
this->addNavigation(demoTab->getView());
// avoid using addNavigation since it will cause memory leaks when there are
// multiple tabs (no way to delete the navigation item!)
QObject::connect(
demoTab->getGraphicsViewNavigation(), SIGNAL(mouseCoordinates(QString)),
xycoord, SLOT(setText(QString)));
}
void ArrangementDemoWindow::resetActionGroups(
@ -227,12 +157,14 @@ void ArrangementDemoWindow::resetActionGroups(
this->ui->actionLowerEnvelope->setChecked(tab->isLowerEnvelopeShown());
this->ui->actionUpperEnvelope->setChecked(tab->isUpperEnvelopeShown());
if (tt != SEGMENT_TRAITS && tt != POLYLINE_TRAITS && tt != LINEAR_TRAITS)
if (
tt != TraitsType::SEGMENT_TRAITS && tt != TraitsType::POLYLINE_TRAITS &&
tt != TraitsType::LINEAR_TRAITS)
this->ui->actionArrangementSnapMode->setVisible(false);
else
this->ui->actionArrangementSnapMode->setVisible(true);
if (tt == RATIONAL_FUNCTION_TRAITS)
if (tt == TraitsType::RATIONAL_FUNCTION_TRAITS)
this->ui->actionGridSnapMode->setVisible(false);
// default action group is scrolling
@ -250,7 +182,7 @@ void ArrangementDemoWindow::resetCallbackState(ArrangementDemoTabBase* tab)
void ArrangementDemoWindow::updateEnvelope(QAction* newMode)
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (!currentTab) return;
bool show = newMode->isChecked();
@ -286,47 +218,46 @@ void ArrangementDemoWindow::hideInsertMethods()
this->ui->actionBezier->setChecked(false);
}
void ArrangementDemoWindow::showInsertMethods()
void ArrangementDemoWindow::showInsertMethods(demo_types::TraitsType tabType)
{
auto tabType = this->getCurrentTab().second;
switch(tabType)
{
case NONE:
case TraitsType::NONE:
return;
case SEGMENT_TRAITS:
case TraitsType::SEGMENT_TRAITS:
this->ui->actionSegment->setVisible(true);
this->ui->actionSegment->activate(QAction::Trigger);
break;
case POLYLINE_TRAITS:
case TraitsType::POLYLINE_TRAITS:
this->ui->actionPolyline->setVisible(true);
this->ui->actionPolyline->activate(QAction::Trigger);
break;
case LINEAR_TRAITS:
case TraitsType::LINEAR_TRAITS:
this->ui->actionSegment->setVisible(true);
this->ui->actionSegment->activate(QAction::Trigger);
this->ui->actionRay->setVisible(true);
this->ui->actionLine->setVisible(true);
break;
#ifdef CGAL_USE_CORE
case CONIC_TRAITS:
case TraitsType::CONIC_TRAITS:
this->ui->actionSegment->setVisible(true);
this->ui->actionCircle->setVisible(true);
this->ui->actionEllipse->setVisible(true);
this->ui->actionConicThreePoint->setVisible(true);
this->ui->actionConicFivePoint->setVisible(true);
break;
case ALGEBRAIC_TRAITS:
case TraitsType::ALGEBRAIC_TRAITS:
this->ui->actionCircle->setVisible(true);
this->ui->actionCircle->activate(QAction::Trigger);
this->ui->actionEllipse->setVisible(true);
this->ui->actionLine->setVisible(true);
this->ui->actionAddAlgebraicCurve->setVisible(true);
break;
case BEZIER_TRAITS:
case TraitsType::BEZIER_TRAITS:
this->ui->actionBezier->setVisible(true);
this->ui->actionBezier->activate(QAction::Trigger);
break;
case RATIONAL_FUNCTION_TRAITS:
case TraitsType::RATIONAL_FUNCTION_TRAITS:
this->ui->actionAddRationalCurve->setVisible(true);
break;
#endif
@ -337,7 +268,7 @@ void ArrangementDemoWindow::showInsertMethods()
void ArrangementDemoWindow::updateInputType(QAction* a)
{
auto tab = this->getCurrentTab().first;
auto tab = this->getCurrentTab();
if (!tab) return;
using namespace CGAL::Qt;
@ -390,7 +321,7 @@ void ArrangementDemoWindow::on_actionAddAlgebraicCurve_triggered()
return;
}
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
Alg_seg_arr* arr;
if (!CGAL::assign(arr, currentTab->getArrangement()))
CGAL_error();
@ -437,7 +368,7 @@ void ArrangementDemoWindow::on_actionAddRationalCurve_triggered()
return;
}
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
Rational_arr* arr;
if (!CGAL::assign(arr, currentTab->getArrangement()))
CGAL_error();
@ -465,18 +396,16 @@ void ArrangementDemoWindow::on_actionNewTab_triggered()
if (newTabDialog.exec() == QDialog::Accepted)
{
int id = newTabDialog.checkedId();
// this assumes that options have the same order as TraitsType
this->makeTab(static_cast<TraitsType>(id));
}
}
void ArrangementDemoWindow::on_tabWidget_currentChanged(int)
{
auto tabPair = this->getCurrentTab();
auto currentTab = tabPair.first;
auto tt = tabPair.second;
auto currentTab = this->getCurrentTab();
if (currentTab)
{
auto tt = currentTab->traitsType();
this->resetCallbackState(currentTab);
this->resetActionGroups(currentTab, tt);
this->updateFillColorSwatch(currentTab);
@ -487,11 +416,11 @@ void ArrangementDemoWindow::on_actionInsert_toggled(bool checked)
{
this->hideInsertMethods();
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (currentTab)
{
if (checked)
this->showInsertMethods();
this->showInsertMethods(currentTab->traitsType());
else
this->resetCallbackState(currentTab);
}
@ -499,7 +428,7 @@ void ArrangementDemoWindow::on_actionInsert_toggled(bool checked)
void ArrangementDemoWindow::on_actionDrag_toggled(bool checked)
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (currentTab)
{
// TODO: Move this to DemoTab
@ -513,21 +442,21 @@ void ArrangementDemoWindow::on_actionDrag_toggled(bool checked)
void ArrangementDemoWindow::on_actionDelete_toggled(bool checked)
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (currentTab && !checked)
this->resetCallbackState(currentTab);
}
void ArrangementDemoWindow::on_actionDelete_triggered()
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (currentTab)
currentTab->activateDeleteCurveCallback();
}
void ArrangementDemoWindow::on_actionPointLocation_toggled(bool checked)
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (currentTab)
{
if (!checked)
@ -539,7 +468,7 @@ void ArrangementDemoWindow::on_actionPointLocation_toggled(bool checked)
void ArrangementDemoWindow::on_actionRayShootingUp_toggled(bool checked)
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (currentTab)
{
if (!checked)
@ -551,7 +480,7 @@ void ArrangementDemoWindow::on_actionRayShootingUp_toggled(bool checked)
void ArrangementDemoWindow::on_actionRayShootingDown_toggled(bool checked)
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (currentTab)
{
if (!checked)
@ -563,7 +492,7 @@ void ArrangementDemoWindow::on_actionRayShootingDown_toggled(bool checked)
void ArrangementDemoWindow::on_actionMerge_toggled(bool checked)
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (currentTab)
{
if (!checked)
@ -575,7 +504,7 @@ void ArrangementDemoWindow::on_actionMerge_toggled(bool checked)
void ArrangementDemoWindow::on_actionSplit_toggled(bool checked)
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (currentTab)
{
if (!checked)
@ -587,7 +516,7 @@ void ArrangementDemoWindow::on_actionSplit_toggled(bool checked)
void ArrangementDemoWindow::on_actionFill_toggled(bool checked)
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (currentTab)
{
if (!checked)
@ -600,7 +529,7 @@ void ArrangementDemoWindow::on_actionFill_toggled(bool checked)
void ArrangementDemoWindow::on_actionShowGrid_toggled(bool checked)
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (currentTab)
{
currentTab->showGrid(checked);
@ -611,7 +540,7 @@ void ArrangementDemoWindow::on_actionShowGrid_toggled(bool checked)
void ArrangementDemoWindow::on_actionGridSnapMode_toggled(bool checked)
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (currentTab)
{
currentTab->setSnapToGrid(checked);
@ -622,7 +551,7 @@ void ArrangementDemoWindow::on_actionGridSnapMode_toggled(bool checked)
void ArrangementDemoWindow::on_actionArrangementSnapMode_toggled(bool checked)
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (currentTab)
{
currentTab->setSnapToArrangement(checked);
@ -631,7 +560,7 @@ void ArrangementDemoWindow::on_actionArrangementSnapMode_toggled(bool checked)
void ArrangementDemoWindow::on_actionCloseTab_triggered()
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (!currentTab) return;
// delete the tab
@ -647,7 +576,7 @@ void ArrangementDemoWindow::on_actionCloseTab_triggered()
void ArrangementDemoWindow::on_actionZoomIn_triggered()
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (currentTab)
{
QGraphicsView* view = currentTab->getView();
@ -657,7 +586,7 @@ void ArrangementDemoWindow::on_actionZoomIn_triggered()
void ArrangementDemoWindow::on_actionZoomOut_triggered()
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (currentTab)
{
QGraphicsView* view = currentTab->getView();
@ -667,14 +596,14 @@ void ArrangementDemoWindow::on_actionZoomOut_triggered()
void ArrangementDemoWindow::on_actionZoomReset_triggered()
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (currentTab)
currentTab->adjustViewport();
}
void ArrangementDemoWindow::on_actionFillColor_triggered()
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (!currentTab) return;
FillFaceCallbackBase* fillFaceCallback = currentTab->getFillFaceCallback();
@ -701,11 +630,10 @@ void ArrangementDemoWindow::updateFillColorSwatch(ArrangementDemoTabBase* tab)
this->ui->actionFillColor->setIcon(fillColorIcon);
}
auto ArrangementDemoWindow::getCurrentTab()
-> std::pair<ArrangementDemoTabBase*, TraitsType>
ArrangementDemoTabBase* ArrangementDemoWindow::getCurrentTab()
{
int tabIndex = this->ui->tabWidget->currentIndex();
if (tabIndex == -1) return {nullptr, NONE};
if (tabIndex == -1) return nullptr;
return this->tabs[tabIndex];
}
@ -721,7 +649,7 @@ std::vector<QString> ArrangementDemoWindow::getTabLabels() const
std::vector<CGAL::Object> ArrangementDemoWindow::getArrangements() const
{
std::vector<CGAL::Object> res;
for (auto& tab : this->tabs) res.push_back(tab.first->getArrangement());
for (auto& tab : this->tabs) res.push_back(tab->getArrangement());
return res;
}
@ -733,9 +661,9 @@ void ArrangementDemoWindow::on_actionOverlay_triggered()
std::vector<CGAL::Object> arrs = overlayDialog.selectedArrangements();
if (arrs.size() == 2)
{
forEachArrangementType([&](auto type_holder) {
demo_types::forEachArrangementType([&](auto type_holder) {
using Arr = typename decltype(type_holder)::type;
auto tt = traitFromType<Arr>();
auto tt = demo_types::enumFromArrType<Arr>();
Arr* arr;
Arr* arr2;
@ -796,15 +724,13 @@ struct ArrWriter
void ArrangementDemoWindow::on_actionSaveAs_triggered()
{
auto tab_tt = this->getCurrentTab();
auto currentTab = tab_tt.first;
auto tt = tab_tt.second;
auto currentTab = this->getCurrentTab();
if (!currentTab)
{
QMessageBox::information(this, "Oops", "Create a new tab first");
return;
}
auto tt = currentTab->traitsType();
QString filename = QFileDialog::getSaveFileName(
this, tr("Save file"), "", "Arrangement (*.arr)");
@ -816,7 +742,7 @@ void ArrangementDemoWindow::on_actionSaveAs_triggered()
// write type info
ofs << "# " << static_cast<int>(tt) << std::endl;
visitArrangementType(tt, [&](auto type_holder) {
demo_types::visitArrangementType(tt, [&](auto type_holder) {
using Arr = typename decltype(type_holder)::type;
Arr* typed_arr;
if (CGAL::assign(typed_arr, currentTab->getArrangement()))
@ -846,7 +772,7 @@ void ArrangementDemoWindow::on_actionOpen_triggered()
struct ArrReader
{
template <typename Arr>
auto operator()(TypeHolder<Arr>)
auto operator()(demo_types::TypeHolder<Arr>)
{
using Text_formatter = CGAL::Arr_text_formatter<Arr>;
using ArrFormatter = CGAL::Arr_with_history_text_formatter<Text_formatter>;
@ -858,7 +784,7 @@ struct ArrReader
}
#ifdef CGAL_USE_CORE
auto operator()(TypeHolder<demo_types::Conic_arr>)
auto operator()(demo_types::TypeHolder<demo_types::Conic_arr>)
{
using namespace demo_types;
@ -871,12 +797,12 @@ struct ArrReader
return arr;
}
auto operator()(TypeHolder<demo_types::Bezier_arr>)
auto operator()(demo_types::TypeHolder<demo_types::Bezier_arr>)
{
return std::make_unique<demo_types::Bezier_arr>();
}
auto operator()(TypeHolder<demo_types::Rational_arr>)
auto operator()(demo_types::TypeHolder<demo_types::Rational_arr>)
{
return std::make_unique<demo_types::Rational_arr>();
}
@ -902,7 +828,7 @@ ArrangementDemoTabBase* ArrangementDemoWindow::openArrFile(QString filename)
ArrangementDemoTabBase* createdTab = nullptr;
visitArrangementType(tt, [&](auto type_holder) {
demo_types::visitArrangementType(tt, [&](auto type_holder) {
auto arr = ArrReader{ifs}(type_holder);
createdTab = this->makeTab(std::move(arr), this->makeTabLabel(tt), tt);
});
@ -912,7 +838,7 @@ ArrangementDemoTabBase* ArrangementDemoWindow::openArrFile(QString filename)
void ArrangementDemoWindow::on_actionPreferences_triggered()
{
auto currentTab = this->getCurrentTab().first;
auto currentTab = this->getCurrentTab();
if (!currentTab) return;
auto agi = currentTab->getArrangementGraphicsItem();

View File

@ -24,6 +24,15 @@ class ArrangementDemoWindow;
namespace CGAL
{
class Object;
namespace Qt
{
class GraphicsViewNavigation;
}
}
namespace demo_types
{
enum class TraitsType;
}
class ArrangementDemoTabBase;
@ -34,24 +43,12 @@ class ArrangementDemoWindow : public CGAL::Qt::DemosMainWindow
Q_OBJECT
public:
typedef enum TraitsType
{
SEGMENT_TRAITS,
POLYLINE_TRAITS,
LINEAR_TRAITS,
CONIC_TRAITS,
ALGEBRAIC_TRAITS,
BEZIER_TRAITS,
RATIONAL_FUNCTION_TRAITS,
NONE,
} TraitsType;
ArrangementDemoWindow(QWidget* parent = nullptr);
~ArrangementDemoWindow();
std::vector<CGAL::Object> getArrangements() const;
std::vector<QString> getTabLabels() const;
std::pair<ArrangementDemoTabBase*, TraitsType> getCurrentTab();
ArrangementDemoTabBase* getCurrentTab();
public Q_SLOTS:
void updateEnvelope(QAction*);
@ -89,26 +86,26 @@ Q_SIGNALS:
protected:
void setupUi();
ArrangementDemoTabBase* makeTab(TraitsType);
void addTab(ArrangementDemoTabBase*, QString, TraitsType);
ArrangementDemoTabBase* makeTab(demo_types::TraitsType);
void addTab(ArrangementDemoTabBase*, QString, demo_types::TraitsType);
void resetCallbackState(ArrangementDemoTabBase*);
void resetActionGroups(ArrangementDemoTabBase*, TraitsType);
void resetActionGroups(ArrangementDemoTabBase*, demo_types::TraitsType);
void hideInsertMethods();
void showInsertMethods();
void showInsertMethods(demo_types::TraitsType);
void updateFillColorSwatch(ArrangementDemoTabBase*);
QString makeTabLabel(TraitsType);
QString makeTabLabel(demo_types::TraitsType);
ArrangementDemoTabBase* openArrFile(QString filename);
template <class ArrType>
ArrangementDemoTabBase*
makeTab(std::unique_ptr<ArrType> arr, QString, TraitsType);
makeTab(std::unique_ptr<ArrType> arr, QString, demo_types::TraitsType);
template <class ArrType>
void makeOverlayTab(ArrType* arr1, ArrType* arr2, TraitsType);
void makeOverlayTab(ArrType* arr1, ArrType* arr2, demo_types::TraitsType);
private:
Ui::ArrangementDemoWindow* ui;
std::vector<std::pair<ArrangementDemoTabBase*, TraitsType>> tabs;
std::vector<ArrangementDemoTabBase*> tabs;
QActionGroup* modeGroup;
QActionGroup* envelopeGroup;
QActionGroup* inputTypeGroup;

View File

@ -0,0 +1,94 @@
#ifndef ARRANGEMENT_DEMO_TYPE_UTILS
#define ARRANGEMENT_DEMO_TYPE_UTILS
#include "ArrangementTypes.h"
#include <type_traits>
namespace demo_types
{
enum class TraitsType : int
{
SEGMENT_TRAITS,
POLYLINE_TRAITS,
LINEAR_TRAITS,
#ifdef CGAL_USE_CORE
CONIC_TRAITS,
ALGEBRAIC_TRAITS,
BEZIER_TRAITS,
RATIONAL_FUNCTION_TRAITS,
#endif
NONE,
};
template <class T>
struct TypeHolder
{
using type = T;
};
template <typename T>
static constexpr TraitsType enumFromArrType()
{
using namespace std;
if (is_same<T, Seg_arr>::value) return TraitsType::SEGMENT_TRAITS;
else if (is_same<T, Pol_arr>::value) return TraitsType::POLYLINE_TRAITS;
else if (is_same<T, Lin_arr>::value) return TraitsType::LINEAR_TRAITS;
#ifdef CGAL_USE_CORE
else if (is_same<T, Conic_arr>::value) return TraitsType::CONIC_TRAITS;
else if (is_same<T, Alg_seg_arr>::value) return TraitsType::ALGEBRAIC_TRAITS;
else if (is_same<T, Bezier_arr>::value) return TraitsType::BEZIER_TRAITS;
else if (is_same<T, Rational_arr>::value) return TraitsType::RATIONAL_FUNCTION_TRAITS;
#endif
else return TraitsType::NONE;
}
template <class Lambda>
static void visitArrangementType(TraitsType tt, Lambda lambda)
{
switch (tt)
{
default:
case TraitsType::SEGMENT_TRAITS:
lambda(TypeHolder<Seg_arr>{});
break;
case TraitsType::POLYLINE_TRAITS:
lambda(TypeHolder<Pol_arr>{});
break;
case TraitsType::LINEAR_TRAITS:
lambda(TypeHolder<Lin_arr>{});
break;
#ifdef CGAL_USE_CORE
case TraitsType::CONIC_TRAITS:
lambda(TypeHolder<Conic_arr>{});
break;
case TraitsType::ALGEBRAIC_TRAITS:
lambda(TypeHolder<Alg_seg_arr>{});
break;
case TraitsType::BEZIER_TRAITS:
lambda(TypeHolder<Bezier_arr>{});
break;
case TraitsType::RATIONAL_FUNCTION_TRAITS:
lambda(TypeHolder<Rational_arr>{});
break;
#endif
}
}
template <class Lambda>
static void forEachArrangementType(Lambda lambda)
{
lambda(TypeHolder<Seg_arr>{});
lambda(TypeHolder<Pol_arr>{});
lambda(TypeHolder<Lin_arr>{});
#ifdef CGAL_USE_CORE
lambda(TypeHolder<Conic_arr>{});
lambda(TypeHolder<Alg_seg_arr>{});
lambda(TypeHolder<Bezier_arr>{});
lambda(TypeHolder<Rational_arr>{});
#endif
}
}
#endif

View File

@ -43,7 +43,6 @@ struct Arr_identified_side_tag;
template <typename T>
class Rational_traits;
} // namespace CGAL
#endif

View File

@ -11,31 +11,38 @@
#include "NewTabDialog.h"
#include "ArrangementDemoWindow.h"
#include "ArrangementTypesUtils.h"
#include "ui_NewTabDialog.h"
#include <QButtonGroup>
NewTabDialog::NewTabDialog( QWidget* parent ) :
QDialog( parent ),
ui( new Ui::NewTabDialog ),
buttonGroup( new QButtonGroup )
{
this->ui->setupUi( this );
using TraitsType = demo_types::TraitsType;
this->buttonGroup->addButton( this->ui->segmentRadioButton,
ArrangementDemoWindow::SEGMENT_TRAITS );
this->buttonGroup->addButton( this->ui->polylineRadioButton,
ArrangementDemoWindow::POLYLINE_TRAITS );
this->buttonGroup->addButton( this->ui->linearRadioButton,
ArrangementDemoWindow::LINEAR_TRAITS );
this->ui->setupUi(this);
this->buttonGroup->addButton(
this->ui->segmentRadioButton, static_cast<int>(TraitsType::SEGMENT_TRAITS));
this->buttonGroup->addButton(
this->ui->polylineRadioButton,
static_cast<int>(TraitsType::POLYLINE_TRAITS));
this->buttonGroup->addButton(
this->ui->linearRadioButton, static_cast<int>(TraitsType::LINEAR_TRAITS));
#ifdef CGAL_USE_CORE
this->buttonGroup->addButton( this->ui->conicRadioButton,
ArrangementDemoWindow::CONIC_TRAITS );
this->buttonGroup->addButton( this->ui->algebraicRadioButton,
ArrangementDemoWindow::ALGEBRAIC_TRAITS );
this->buttonGroup->addButton( this->ui->bezierRadioButton,
ArrangementDemoWindow::BEZIER_TRAITS );
this->buttonGroup->addButton( this->ui->rationalFunctionRadioButton,
ArrangementDemoWindow::RATIONAL_FUNCTION_TRAITS );
this->buttonGroup->addButton(
this->ui->conicRadioButton, static_cast<int>(TraitsType::CONIC_TRAITS));
this->buttonGroup->addButton(
this->ui->algebraicRadioButton,
static_cast<int>(TraitsType::ALGEBRAIC_TRAITS));
this->buttonGroup->addButton(
this->ui->bezierRadioButton, static_cast<int>(TraitsType::BEZIER_TRAITS));
this->buttonGroup->addButton(
this->ui->rationalFunctionRadioButton,
static_cast<int>(TraitsType::RATIONAL_FUNCTION_TRAITS));
#else
this->ui->conicRadioButton->hide();
this->ui->algebraicRadioButton->hide();

View File

@ -9,7 +9,7 @@
#include "OverlayDialog.h"
#include "ArrangementDemoWindow.h"
#include "ArrangementTypes.h"
#include "ArrangementTypesUtils.h"
#include "QtMetaTypes.h"
#include <QListWidgetItem>
@ -18,9 +18,6 @@
#include "ui_OverlayDialog.h"
// TODO: clean this up!
// TODO: Don't color the text, but set an icon for each arrangement type...
// TODO: Or maybe don't bother
OverlayDialog::OverlayDialog( ArrangementDemoWindow* parent ) :
QDialog( parent ),
ui( new Ui::OverlayDialog )
@ -46,54 +43,24 @@ OverlayDialog::OverlayDialog( ArrangementDemoWindow* parent ) :
item->setData( ARRANGEMENT, QVariant::fromValue( arrangements[ i ] ) );
QIcon icon;
Seg_arr* seg;
Pol_arr* pol;
Lin_arr* lin;
#ifdef CGAL_USE_CORE
Conic_arr* conic;
Alg_seg_arr* alg;
Bezier_arr* bezier;
Rational_arr* rat_arr;
#endif
TraitsType traitsType = TraitsType::NONE;
forEachArrangementType([&](auto type_holder) {
using Arrangement = typename decltype(type_holder)::type;
Arrangement* arr;
if (CGAL::assign(arr, arrangements[i]))
traitsType = enumFromArrType<Arrangement>();
});
if ( CGAL::assign( seg, arrangements[ i ] ) )
{
icon.addFile(QString::fromUtf8(":/icons/green_icon.xpm"), QSize(),
QIcon::Normal, QIcon::Off);
}
else if ( CGAL::assign( pol, arrangements[ i ] ) )
{
icon.addFile(QString::fromUtf8(":/icons/yellow_icon.xpm"), QSize(),
QIcon::Normal, QIcon::Off);
}
else if ( CGAL::assign( lin, arrangements[ i ] ) )
{
icon.addFile(QString::fromUtf8(":/icons/blue_icon.xpm"), QSize(),
QIcon::Normal, QIcon::Off);
}
if (traitsType == TraitsType::NONE)
CGAL_error();
#ifdef CGAL_USE_CORE
else if ( CGAL::assign( conic, arrangements[ i ] ) )
{
icon.addFile(QString::fromUtf8(":/icons/red_icon.xpm"), QSize(),
QIcon::Normal, QIcon::Off);
}
else if ( CGAL::assign( alg, arrangements[ i ] ) )
{
icon.addFile(QString::fromUtf8(":/icons/yellow_icon.xpm"), QSize(),
QIcon::Normal, QIcon::Off);
}
else if ( CGAL::assign( bezier, arrangements[ i ] ) )
{
icon.addFile(QString::fromUtf8(":/icons/pink_icon.xpm"), QSize(),
QIcon::Normal, QIcon::Off);
}
else if ( CGAL::assign( rat_arr, arrangements[ i ] ) )
{
icon.addFile(QString::fromUtf8(":/icons/yellow_icon.xpm"), QSize(),
QIcon::Normal, QIcon::Off);
}
#endif
static constexpr std::array<const char*, 5> icons = {
":/cgal/icons/green_icon.xpm", ":/cgal/icons/yellow_icon.xpm",
":/cgal/icons/blue_icon.xpm", ":/cgal/icons/red_icon.xpm",
":/cgal/icons/pink_icon.xpm"};
icon.addFile(
QString::fromUtf8(icons[static_cast<int>(traitsType) % icons.size()]));
item->setIcon( icon );
}
@ -170,153 +137,24 @@ void OverlayDialog::restrictSelection( QListWidgetItem* item )
CGAL::Object o = item->data( ARRANGEMENT ).value< CGAL::Object >( );
Seg_arr* seg;
Pol_arr* pol;
Lin_arr* lin;
#ifdef CGAL_USE_CORE
Conic_arr* conic;
Alg_seg_arr* alg;
Bezier_arr* bezier;
Rational_arr* rat_arr;
#endif
forEachArrangementType([&](auto type_holder) {
using Arrangement = typename decltype(type_holder)::type;
Arrangement* arr;
if (CGAL::assign(arr, o))
{
for (int i = 0; i < this->ui->arrangementsListWidget->count(); ++i)
{
auto* otherItem = this->ui->arrangementsListWidget->item(i);
auto o2 = otherItem->data(ARRANGEMENT).value<CGAL::Object>();
bool enabled = CGAL::assign(arr, o2);
Qt::ItemFlags flags = otherItem->flags();
if (!enabled) { flags &= ~(Qt::ItemIsEnabled); }
else { flags |= Qt::ItemIsEnabled; }
if ( CGAL::assign( seg, o ) )
{
for ( int i = 0; i < this->ui->arrangementsListWidget->count( ); ++i )
{
QListWidgetItem* otherItem = this->ui->arrangementsListWidget->item( i );
CGAL::Object o2 = otherItem->data( ARRANGEMENT ).value< CGAL::Object >( );
bool enabled = CGAL::assign( seg, o2 );
Qt::ItemFlags flags = otherItem->flags( );
if ( ! enabled )
{
flags &= ~( Qt::ItemIsEnabled );
otherItem->setFlags(flags);
}
else
{
flags |= Qt::ItemIsEnabled;
}
otherItem->setFlags( flags );
}
}
else if ( CGAL::assign( pol, o ) )
{
for ( int i = 0; i < this->ui->arrangementsListWidget->count( ); ++i )
{
QListWidgetItem* otherItem = this->ui->arrangementsListWidget->item( i );
CGAL::Object o2 = otherItem->data( ARRANGEMENT ).value< CGAL::Object >( );
bool enabled = CGAL::assign( pol, o2 );
Qt::ItemFlags flags = otherItem->flags( );
if ( ! enabled )
{
flags &= ~( Qt::ItemIsEnabled );
}
else
{
flags |= Qt::ItemIsEnabled;
}
otherItem->setFlags( flags );
}
}
else if ( CGAL::assign( lin, o ) )
{
for ( int i = 0; i < this->ui->arrangementsListWidget->count( ); ++i )
{
QListWidgetItem* otherItem = this->ui->arrangementsListWidget->item( i );
CGAL::Object o2 = otherItem->data( ARRANGEMENT ).value< CGAL::Object >( );
bool enabled = CGAL::assign( lin, o2 );
Qt::ItemFlags flags = otherItem->flags( );
if ( ! enabled )
{
flags &= ~( Qt::ItemIsEnabled );
}
else
{
flags |= Qt::ItemIsEnabled;
}
otherItem->setFlags( flags );
}
}
#ifdef CGAL_USE_CORE
else if ( CGAL::assign( conic, o ) )
{
for ( int i = 0; i < this->ui->arrangementsListWidget->count( ); ++i )
{
QListWidgetItem* otherItem = this->ui->arrangementsListWidget->item( i );
CGAL::Object o2 = otherItem->data( ARRANGEMENT ).value< CGAL::Object >( );
bool enabled = CGAL::assign( conic, o2 );
Qt::ItemFlags flags = otherItem->flags( );
if ( ! enabled )
{
flags &= ~( Qt::ItemIsEnabled );
}
else
{
flags |= Qt::ItemIsEnabled;
}
otherItem->setFlags( flags );
}
}
else if ( CGAL::assign( alg, o ) )
{
for ( int i = 0; i < this->ui->arrangementsListWidget->count( ); ++i )
{
QListWidgetItem* otherItem = this->ui->arrangementsListWidget->item( i );
CGAL::Object o2 = otherItem->data( ARRANGEMENT ).value< CGAL::Object >( );
bool enabled = CGAL::assign( alg, o2 );
Qt::ItemFlags flags = otherItem->flags( );
if ( ! enabled )
{
flags &= ~( Qt::ItemIsEnabled );
}
else
{
flags |= Qt::ItemIsEnabled;
}
otherItem->setFlags( flags );
}
}
else if ( CGAL::assign( bezier, o ) )
{
for ( int i = 0; i < this->ui->arrangementsListWidget->count( ); ++i )
{
QListWidgetItem* otherItem = this->ui->arrangementsListWidget->item( i );
CGAL::Object o2 = otherItem->data( ARRANGEMENT ).value< CGAL::Object >( );
bool enabled = CGAL::assign( bezier, o2 );
Qt::ItemFlags flags = otherItem->flags( );
if ( ! enabled )
{
flags &= ~( Qt::ItemIsEnabled );
}
else
{
flags |= Qt::ItemIsEnabled;
}
otherItem->setFlags( flags );
}
}
else if ( CGAL::assign( rat_arr, o ) )
{
for ( int i = 0; i < this->ui->arrangementsListWidget->count( ); ++i )
{
QListWidgetItem* otherItem = this->ui->arrangementsListWidget->item( i );
CGAL::Object o2 = otherItem->data( ARRANGEMENT ).value< CGAL::Object >( );
bool enabled = CGAL::assign( rat_arr, o2 );
Qt::ItemFlags flags = otherItem->flags( );
if ( ! enabled )
{
flags &= ~( Qt::ItemIsEnabled );
}
else
{
flags |= Qt::ItemIsEnabled;
}
otherItem->setFlags( flags );
}
}
#endif
});
}
void OverlayDialog::unrestrictSelection( )