Commit 65793b58 authored by Tobias WEBER's avatar Tobias WEBER
Browse files

started with 3d plot in structure factor tool

parent 91bc4ada
......@@ -156,8 +156,10 @@ GlPlotObj GlPlot_impl::CreateTriangleObject(const std::vector<t_vec3_gl>& verts,
{ // vertices
obj.m_pvertexbuf = std::make_shared<QOpenGLBuffer>(QOpenGLBuffer::VertexBuffer);
obj.m_pvertexbuf->create();
obj.m_pvertexbuf->bind();
if(!obj.m_pvertexbuf->create())
std::cerr << "Cannot create vertex buffer." << std::endl;
if(!obj.m_pvertexbuf->bind())
std::cerr << "Cannot bind vertex buffer." << std::endl;
BOOST_SCOPE_EXIT(&obj) { obj.m_pvertexbuf->release(); } BOOST_SCOPE_EXIT_END
auto vecVerts = to_float_array(triagverts, 1,3, false);
......@@ -296,6 +298,20 @@ void GlPlot_impl::SetObjectVisible(std::size_t idx, bool visible)
}
std::size_t GlPlot_impl::AddLinkedObject(std::size_t linkTo,
t_real_gl x, t_real_gl y, t_real_gl z)
{
GlPlotObj obj;
obj.linkedObj = linkTo;
obj.m_mat = m::hom_translation<t_mat_gl>(x, y, z);
QMutexLocker _locker{&m_mutexObj};
m_objs.emplace_back(std::move(obj));
return m_objs.size()-1; // object handle
}
std::size_t GlPlot_impl::AddSphere(t_real_gl rad, t_real_gl x, t_real_gl y, t_real_gl z,
t_real_gl r, t_real_gl g, t_real_gl b, t_real_gl a)
{
......@@ -304,6 +320,8 @@ std::size_t GlPlot_impl::AddSphere(t_real_gl rad, t_real_gl x, t_real_gl y, t_re
m::subdivide_triangles<t_vec3_gl>(
m::create_triangles<t_vec3_gl>(solid), 2), rad);
QMutexLocker _locker{&m_mutexObj};
auto obj = CreateTriangleObject(std::get<0>(solid), triagverts, norms, m::create<t_vec_gl>({r,g,b,a}), true);
obj.m_mat = m::hom_translation<t_mat_gl>(x, y, z);
m_objs.emplace_back(std::move(obj));
......@@ -319,6 +337,8 @@ std::size_t GlPlot_impl::AddCylinder(t_real_gl rad, t_real_gl h,
auto solid = m::create_cylinder<t_vec3_gl>(rad, h, true);
auto [triagverts, norms, uvs] = m::create_triangles<t_vec3_gl>(solid);
QMutexLocker _locker{&m_mutexObj};
auto obj = CreateTriangleObject(std::get<0>(solid), triagverts, norms, m::create<t_vec_gl>({r,g,b,a}), false);
obj.m_mat = m::hom_translation<t_mat_gl>(x, y, z);
m_objs.emplace_back(std::move(obj));
......@@ -334,6 +354,8 @@ std::size_t GlPlot_impl::AddCone(t_real_gl rad, t_real_gl h,
auto solid = m::create_cone<t_vec3_gl>(rad, h);
auto [triagverts, norms, uvs] = m::create_triangles<t_vec3_gl>(solid);
QMutexLocker _locker{&m_mutexObj};
auto obj = CreateTriangleObject(std::get<0>(solid), triagverts, norms, m::create<t_vec_gl>({r,g,b,a}), false);
obj.m_mat = m::hom_translation<t_mat_gl>(x, y, z);
m_objs.emplace_back(std::move(obj));
......@@ -349,6 +371,8 @@ std::size_t GlPlot_impl::AddArrow(t_real_gl rad, t_real_gl h,
auto solid = m::create_cylinder<t_vec3_gl>(rad, h, 2, 32, rad, rad*1.5);
auto [triagverts, norms, uvs] = m::create_triangles<t_vec3_gl>(solid);
QMutexLocker _locker{&m_mutexObj};
auto obj = CreateTriangleObject(std::get<0>(solid), triagverts, norms, m::create<t_vec_gl>({r,g,b,a}), false);
obj.m_mat = GetArrowMatrix(m::create<t_vec_gl>({1,0,0}), 1., m::create<t_vec_gl>({x,y,z}), m::create<t_vec_gl>({0,0,1}));
obj.m_labelPos = m::create<t_vec3_gl>({0., 0., 0.75});
......@@ -368,6 +392,8 @@ std::size_t GlPlot_impl::AddCoordinateCross(t_real_gl min, t_real_gl max)
m::create<t_vec3_gl>({0,0,min}), m::create<t_vec3_gl>({0,0,max}),
}};
QMutexLocker _locker{&m_mutexObj};
auto obj = CreateLineObject(verts, col);
m_objs.emplace_back(std::move(obj));
......@@ -605,19 +631,24 @@ void GlPlot_impl::UpdatePicker()
t_vec_gl vecClosestInters = m::create<t_vec_gl>({0,0,0,0});
std::size_t objInters = 0xffffffff;
QMutexLocker _locker{&m_mutexObj};
for(std::size_t curObj=0; curObj<m_objs.size(); ++curObj)
{
const auto& obj = m_objs[curObj];
const GlPlotObj *linkedObj = &obj;
if(obj.linkedObj)
linkedObj = &m_objs[*obj.linkedObj];
if(obj.m_type != GlPlotObjType::TRIANGLES || !obj.m_visible)
if(linkedObj->m_type != GlPlotObjType::TRIANGLES || !obj.m_visible)
continue;
obj.m_pcolorbuf->bind();
BOOST_SCOPE_EXIT(&obj) { obj.m_pcolorbuf->release(); } BOOST_SCOPE_EXIT_END
linkedObj->m_pcolorbuf->bind();
BOOST_SCOPE_EXIT(&linkedObj) { linkedObj->m_pcolorbuf->release(); } BOOST_SCOPE_EXIT_END
for(std::size_t startidx=0; startidx+2<obj.m_triangles.size(); startidx+=3)
for(std::size_t startidx=0; startidx+2<linkedObj->m_triangles.size(); startidx+=3)
{
std::vector<t_vec3_gl> poly{{ obj.m_triangles[startidx+0], obj.m_triangles[startidx+1], obj.m_triangles[startidx+2] }};
std::vector<t_vec3_gl> poly{{ linkedObj->m_triangles[startidx+0], linkedObj->m_triangles[startidx+1], linkedObj->m_triangles[startidx+2] }};
auto [vecInters, bInters, lamInters] =
m::intersect_line_poly<t_vec3_gl, t_mat_gl>(org3, dir3, poly, obj.m_mat);
......@@ -724,6 +755,8 @@ void GlPlot_impl::tick(const std::chrono::milliseconds& ms)
void GlPlot_impl::paintGL()
{
QMutexLocker _locker{&m_mutexObj};
if constexpr(!m_isthreaded)
{
auto *pContext = m_pPlot->context();
......@@ -760,15 +793,19 @@ void GlPlot_impl::paintGL()
// render triangle geometry
for(const auto& obj : m_objs)
{
const GlPlotObj *linkedObj = &obj;
if(obj.linkedObj)
linkedObj = &m_objs[*obj.linkedObj];
if(!obj.m_visible) continue;
// main vertex array object
pGl->glBindVertexArray(obj.m_vertexarr);
pGl->glBindVertexArray(linkedObj->m_vertexarr);
m_pShaders->setUniformValue(m_uniMatrixObj, obj.m_mat);
pGl->glEnableVertexAttribArray(m_attrVertex);
if(obj.m_type == GlPlotObjType::TRIANGLES)
if(linkedObj->m_type == GlPlotObjType::TRIANGLES)
pGl->glEnableVertexAttribArray(m_attrVertexNormal);
pGl->glEnableVertexAttribArray(m_attrVertexColor);
BOOST_SCOPE_EXIT(pGl, &m_attrVertex, &m_attrVertexNormal, &m_attrVertexColor)
......@@ -780,10 +817,10 @@ void GlPlot_impl::paintGL()
BOOST_SCOPE_EXIT_END
LOGGLERR(pGl);
if(obj.m_type == GlPlotObjType::TRIANGLES)
pGl->glDrawArrays(GL_TRIANGLES, 0, obj.m_triangles.size());
else if(obj.m_type == GlPlotObjType::LINES)
pGl->glDrawArrays(GL_LINES, 0, obj.m_vertices.size());
if(linkedObj->m_type == GlPlotObjType::TRIANGLES)
pGl->glDrawArrays(GL_TRIANGLES, 0, linkedObj->m_triangles.size());
else if(linkedObj->m_type == GlPlotObjType::LINES)
pGl->glDrawArrays(GL_LINES, 0, linkedObj->m_vertices.size());
else
std::cerr << "Error: Unknown plot object." << std::endl;
......@@ -914,15 +951,19 @@ void GlPlot_impl::paintGL()
// render triangle geometry
for(const auto& obj : m_objs)
{
const GlPlotObj *linkedObj = &obj;
if(obj.linkedObj)
linkedObj = &m_objs[*obj.linkedObj];
if(!obj.m_visible) continue;
// main vertex array object
pGl->glBindVertexArray(obj.m_vertexarr);
pGl->glBindVertexArray(linkedObj->m_vertexarr);
m_pShaders->setUniformValue(m_uniMatrixObj, obj.m_mat);
pGl->glEnableVertexAttribArray(m_attrVertex);
if(obj.m_type == GlPlotObjType::TRIANGLES)
if(linkedObj->m_type == GlPlotObjType::TRIANGLES)
pGl->glEnableVertexAttribArray(m_attrVertexNormal);
pGl->glEnableVertexAttribArray(m_attrVertexColor);
BOOST_SCOPE_EXIT(pGl, &m_attrVertex, &m_attrVertexNormal, &m_attrVertexColor)
......@@ -934,10 +975,10 @@ void GlPlot_impl::paintGL()
BOOST_SCOPE_EXIT_END
LOGGLERR(pGl);
if(obj.m_type == GlPlotObjType::TRIANGLES)
pGl->glDrawArrays(GL_TRIANGLES, 0, obj.m_triangles.size());
else if(obj.m_type == GlPlotObjType::LINES)
pGl->glDrawArrays(GL_LINES, 0, obj.m_vertices.size());
if(linkedObj->m_type == GlPlotObjType::TRIANGLES)
pGl->glDrawArrays(GL_TRIANGLES, 0, linkedObj->m_triangles.size());
else if(linkedObj->m_type == GlPlotObjType::LINES)
pGl->glDrawArrays(GL_LINES, 0, linkedObj->m_vertices.size());
else
std::cerr << "Error: Unknown plot object." << std::endl;
......
......@@ -87,6 +87,9 @@ enum class GlPlotObjType
struct GlPlotObj
{
// does not define a geometry itself, but just links to another object
std::optional<std::size_t> linkedObj;
GlPlotObjType m_type = GlPlotObjType::TRIANGLES;
GLuint m_vertexarr = 0;
......@@ -115,6 +118,9 @@ struct GlPlotObj
*/
class GlPlot_impl : public QObject
{ Q_OBJECT
private:
QMutex m_mutexObj{QMutex::Recursive};
protected:
GlPlot *m_pPlot = nullptr;
std::string m_strGlVer, m_strGlShaderVer, m_strGlVendor, m_strGlRenderer;
......@@ -199,6 +205,8 @@ public:
t_real_gl x=0, t_real_gl y=0, t_real_gl z=0,
t_real_gl r=0, t_real_gl g=0, t_real_gl b=0, t_real_gl a=1);
std::size_t AddCoordinateCross(t_real_gl min, t_real_gl max);
std::size_t AddLinkedObject(std::size_t linkTo,
t_real_gl x=0, t_real_gl y=0, t_real_gl z=0);
void SetObjectMatrix(std::size_t idx, const t_mat_gl& mat);
void SetObjectLabel(std::size_t idx, const std::string& label);
......@@ -261,7 +269,7 @@ protected slots:
void afterResizing();
private:
mutable QMutex m_mutex;
mutable QMutex m_mutex{QMutex::Recursive};
std::unique_ptr<GlPlot_impl> m_impl;
std::unique_ptr<QThread> m_thread_impl;
......
......@@ -19,6 +19,8 @@ add_definitions(${Boost_CXX_FLAGS})
include_directories("${PROJECT_SOURCE_DIR}" "${Boost_INCLUDE_DIRS}/.." "../..")
add_executable(structfact structfact.cpp structfact.h)
add_executable(structfact
structfact.cpp structfact.h
../glplot/glplot.cpp ../glplot/glplot.h)
target_link_libraries(structfact ${Boost_LIBRARIES})
qt5_use_modules(structfact Core Gui Widgets OpenGL)
......@@ -64,6 +64,9 @@ StructFactDlg::StructFactDlg(QWidget* pParent) : QDialog{pParent},
auto tabs = new QTabWidget(this);
{
m_nucleipanel = new QWidget(this);
m_plot = std::make_shared<GlPlot>(m_nucleipanel);
m_nuclei = new QTableWidget(m_nucleipanel);
m_nuclei->setShowGrid(true);
m_nuclei->setSortingEnabled(true);
......@@ -90,25 +93,28 @@ StructFactDlg::StructFactDlg(QWidget* pParent) : QDialog{pParent},
m_nuclei->setColumnWidth(COL_Y, 75);
m_nuclei->setColumnWidth(COL_Z, 75);
QToolButton *m_pTabBtnAdd = new QToolButton(m_nucleipanel);
QToolButton *m_pTabBtnDel = new QToolButton(m_nucleipanel);
QToolButton *m_pTabBtnUp = new QToolButton(m_nucleipanel);
QToolButton *m_pTabBtnDown = new QToolButton(m_nucleipanel);
m_pTabBtnAdd->setSizePolicy(QSizePolicy{QSizePolicy::Expanding, QSizePolicy::Fixed});
m_pTabBtnDel->setSizePolicy(QSizePolicy{QSizePolicy::Expanding, QSizePolicy::Fixed});
m_pTabBtnUp->setSizePolicy(QSizePolicy{QSizePolicy::Expanding, QSizePolicy::Fixed});
m_pTabBtnDown->setSizePolicy(QSizePolicy{QSizePolicy::Expanding, QSizePolicy::Fixed});
m_pTabBtnAdd->setText("Add Nucleus");
m_pTabBtnDel->setText("Delete Nuclei");
m_pTabBtnUp->setText("Move Nuclei Up");
m_pTabBtnDown->setText("Move Nuclei Down");
m_pTabBtnAdd->setToolTip("Add nucleus.");
m_pTabBtnDel->setToolTip("Delete selected nuclei.");
m_pTabBtnUp->setToolTip("Move selected nuclei up.");
m_pTabBtnDown->setToolTip("Move selected nuclei down.");
QToolButton *pTabBtnAdd = new QToolButton(m_nucleipanel);
QToolButton *pTabBtnDel = new QToolButton(m_nucleipanel);
QToolButton *pTabBtnUp = new QToolButton(m_nucleipanel);
QToolButton *pTabBtnDown = new QToolButton(m_nucleipanel);
QToolButton *pTabBtnLoad = new QToolButton(m_nucleipanel);
QToolButton *pTabBtnSave = new QToolButton(m_nucleipanel);
m_plot->setSizePolicy(QSizePolicy{QSizePolicy::Expanding, QSizePolicy::Expanding});
m_nuclei->setSizePolicy(QSizePolicy{QSizePolicy::Expanding, QSizePolicy::Expanding});
pTabBtnAdd->setSizePolicy(QSizePolicy{QSizePolicy::Expanding, QSizePolicy::Fixed});
pTabBtnDel->setSizePolicy(QSizePolicy{QSizePolicy::Expanding, QSizePolicy::Fixed});
pTabBtnUp->setSizePolicy(QSizePolicy{QSizePolicy::Expanding, QSizePolicy::Fixed});
pTabBtnDown->setSizePolicy(QSizePolicy{QSizePolicy::Expanding, QSizePolicy::Fixed});
pTabBtnLoad->setSizePolicy(QSizePolicy{QSizePolicy::Expanding, QSizePolicy::Fixed});
pTabBtnSave->setSizePolicy(QSizePolicy{QSizePolicy::Expanding, QSizePolicy::Fixed});
pTabBtnAdd->setText("Add Nucleus");
pTabBtnDel->setText("Delete Nuclei");
pTabBtnUp->setText("Move Nuclei Up");
pTabBtnDown->setText("Move Nuclei Down");
pTabBtnLoad->setText("Load...");
pTabBtnSave->setText("Save...");
m_editA = new QLineEdit("5", m_nucleipanel);
......@@ -119,46 +125,59 @@ StructFactDlg::StructFactDlg(QWidget* pParent) : QDialog{pParent},
m_editGamma = new QLineEdit("90", m_nucleipanel);
// table grid
auto pTabGrid = new QGridLayout(m_nucleipanel);
pTabGrid->setSpacing(2);
pTabGrid->setContentsMargins(4,4,4,4);
pTabGrid->addWidget(m_nuclei, 0,0,1,4);
pTabGrid->addWidget(m_pTabBtnAdd, 1,0,1,1);
pTabGrid->addWidget(m_pTabBtnDel, 1,1,1,1);
pTabGrid->addItem(new QSpacerItem(4, 4, QSizePolicy::Expanding, QSizePolicy::Minimum), 1,2,1,1);
pTabGrid->addWidget(m_pTabBtnUp, 1,2,1,1);
pTabGrid->addWidget(m_pTabBtnDown, 1,3,1,1);
int y=0;
pTabGrid->addWidget(m_plot.get(), y,0,1,4);
pTabGrid->addWidget(m_nuclei, ++y,0,1,4);
pTabGrid->addWidget(pTabBtnAdd, ++y,0,1,1);
pTabGrid->addWidget(pTabBtnDel, y,1,1,1);
pTabGrid->addWidget(pTabBtnUp, y,2,1,1);
pTabGrid->addWidget(pTabBtnDown, y,3,1,1);
pTabGrid->addWidget(pTabBtnLoad, ++y,0,1,1);
pTabGrid->addWidget(pTabBtnSave, y,1,1,1);
auto sep1 = new QFrame(m_nucleipanel); sep1->setFrameStyle(QFrame::HLine);
pTabGrid->addWidget(sep1, 2,0, 1,4);
pTabGrid->addWidget(sep1, ++y,0, 1,4);
pTabGrid->addWidget(new QLabel("Lattice (A):"), 3,0,1,1);
pTabGrid->addWidget(m_editA, 3,1,1,1);
pTabGrid->addWidget(m_editB, 3,2,1,1);
pTabGrid->addWidget(m_editC, 3,3,1,1);
pTabGrid->addWidget(new QLabel("Angles (deg):"), 4,0,1,1);
pTabGrid->addWidget(m_editAlpha, 4,1,1,1);
pTabGrid->addWidget(m_editBeta, 4,2,1,1);
pTabGrid->addWidget(m_editGamma, 4,3,1,1);
pTabGrid->addWidget(new QLabel("Lattice (A):"), 5,0,1,1);
pTabGrid->addWidget(m_editA, ++y,1,1,1);
pTabGrid->addWidget(m_editB, y,2,1,1);
pTabGrid->addWidget(m_editC, y,3,1,1);
pTabGrid->addWidget(new QLabel("Angles (deg):"), ++y,0,1,1);
pTabGrid->addWidget(m_editAlpha, y,1,1,1);
pTabGrid->addWidget(m_editBeta, y,2,1,1);
pTabGrid->addWidget(m_editGamma, y,3,1,1);
// table context CustomContextMenu
// table CustomContextMenu
m_pTabContextMenu = new QMenu(m_nuclei);
m_pTabContextMenu->addAction("Add Nucleus Before", this, [this]() { this->AddTabItem(-2); });
m_pTabContextMenu->addAction("Add Nucleus After", this, [this]() { this->AddTabItem(-3); });
m_pTabContextMenu->addAction("Clone Nucleus", this, [this]() { this->AddTabItem(-4); });
m_pTabContextMenu->addAction("Delete Nucleus", this, &StructFactDlg::DelTabItem);
// table CustomContextMenu in case nothing is selected
m_pTabContextMenuNoItem = new QMenu(m_nuclei);
m_pTabContextMenuNoItem->addAction("Add Nucleus", this, [this]() { this->AddTabItem(); });
m_pTabContextMenuNoItem->addAction("Delete Nucleus", this, &StructFactDlg::DelTabItem);
//m_pTabContextMenuNoItem->addSeparator();
// signals
connect(m_pTabBtnAdd, &QToolButton::clicked, this, [this]() { this->AddTabItem(-1); });
connect(m_pTabBtnDel, &QToolButton::clicked, this, &StructFactDlg::DelTabItem);
connect(m_pTabBtnUp, &QToolButton::clicked, this, &StructFactDlg::MoveTabItemUp);
connect(m_pTabBtnDown, &QToolButton::clicked, this, &StructFactDlg::MoveTabItemDown);
connect(pTabBtnAdd, &QToolButton::clicked, this, [this]() { this->AddTabItem(-1); });
connect(pTabBtnDel, &QToolButton::clicked, this, &StructFactDlg::DelTabItem);
connect(pTabBtnUp, &QToolButton::clicked, this, &StructFactDlg::MoveTabItemUp);
connect(pTabBtnDown, &QToolButton::clicked, this, &StructFactDlg::MoveTabItemDown);
connect(pTabBtnLoad, &QToolButton::clicked, this, &StructFactDlg::Load);
connect(pTabBtnSave, &QToolButton::clicked, this, &StructFactDlg::Save);
connect(m_nuclei, &QTableWidget::currentCellChanged, this, &StructFactDlg::TableCurCellChanged);
connect(m_nuclei, &QTableWidget::entered, this, &StructFactDlg::TableCellEntered);
connect(m_nuclei, &QTableWidget::itemChanged, this, &StructFactDlg::TableItemChanged);
connect(m_nuclei, &QTableWidget::customContextMenuRequested, this, &StructFactDlg::ShowTableContextMenu);
connect(m_plot.get(), &GlPlot::AfterGLInitialisation, this, &StructFactDlg::AfterGLInitialisation);
tabs->addTab(m_nucleipanel, "Nuclei");
......@@ -214,6 +233,13 @@ StructFactDlg::StructFactDlg(QWidget* pParent) : QDialog{pParent},
pGrid->setSpacing(4);
pGrid->setContentsMargins(4,4,4,4);
// table grid
for(int i=0; i<4; ++i)
{
m_labelGlInfos[i] = new QLabel("", infopanel);
m_labelGlInfos[i]->setSizePolicy(QSizePolicy::Ignored, m_labelGlInfos[i]->sizePolicy().verticalPolicy());
}
auto sep1 = new QFrame(infopanel); sep1->setFrameStyle(QFrame::HLine);
auto sep2 = new QFrame(infopanel); sep2->setFrameStyle(QFrame::HLine);
auto sep3 = new QFrame(infopanel); sep3->setFrameStyle(QFrame::HLine);
......@@ -246,6 +272,8 @@ StructFactDlg::StructFactDlg(QWidget* pParent) : QDialog{pParent},
pGrid->addWidget(new QLabel(QString("Qt Version: ") + QString(QT_VERSION_STR) + ".", infopanel), y++,0, 1,1);
pGrid->addWidget(new QLabel(QString("Boost Version: ") + strBoost.c_str() + ".", infopanel), y++,0, 1,1);
pGrid->addWidget(sep3, y++,0, 1,1);
for(int i=0; i<4; ++i)
pGrid->addWidget(m_labelGlInfos[i], y++,0, 1,1);
pGrid->addItem(new QSpacerItem(16,16, QSizePolicy::Minimum, QSizePolicy::Expanding), y++,0, 1,1);
tabs->addTab(infopanel, "Infos");
......@@ -272,6 +300,7 @@ StructFactDlg::StructFactDlg(QWidget* pParent) : QDialog{pParent},
void StructFactDlg::AddTabItem(int row)
{
bool bclone = 0;
m_ignoreChanges = 1;
if(row == -1) // append to end of table
......@@ -280,18 +309,46 @@ void StructFactDlg::AddTabItem(int row)
row = m_iCursorRow;
else if(row == -3 && m_iCursorRow >= 0) // use row from member variable +1
row = m_iCursorRow + 1;
else if(row == -4 && m_iCursorRow >= 0) // use row from member variable +1
{
row = m_iCursorRow + 1;
bclone = 1;
}
//bool sorting = m_nuclei->isSortingEnabled();
m_nuclei->setSortingEnabled(false);
m_nuclei->insertRow(row);
m_nuclei->setItem(row, COL_NAME, new QTableWidgetItem("n/a"));
m_nuclei->setItem(row, COL_SCATLEN_RE, new NumericTableWidgetItem<t_real>(0));
m_nuclei->setItem(row, COL_SCATLEN_IM, new NumericTableWidgetItem<t_real>(0));
m_nuclei->setItem(row, COL_X, new NumericTableWidgetItem<t_real>(0));
m_nuclei->setItem(row, COL_Y, new NumericTableWidgetItem<t_real>(0));
m_nuclei->setItem(row, COL_Z, new NumericTableWidgetItem<t_real>(0));
if(bclone)
{
for(int thecol=0; thecol<6; ++thecol)
m_nuclei->setItem(row, thecol, m_nuclei->item(m_iCursorRow, thecol)->clone());
}
else
{
m_nuclei->setItem(row, COL_NAME, new QTableWidgetItem("n/a"));
m_nuclei->setItem(row, COL_SCATLEN_RE, new NumericTableWidgetItem<t_real>(0));
m_nuclei->setItem(row, COL_SCATLEN_IM, new NumericTableWidgetItem<t_real>(0));
m_nuclei->setItem(row, COL_X, new NumericTableWidgetItem<t_real>(0));
m_nuclei->setItem(row, COL_Y, new NumericTableWidgetItem<t_real>(0));
m_nuclei->setItem(row, COL_Z, new NumericTableWidgetItem<t_real>(0));
}
// add 3d object
{
auto *itemx = m_nuclei->item(row, COL_X);
auto *itemy = m_nuclei->item(row, COL_Y);
auto *itemz = m_nuclei->item(row, COL_Z);
t_real_gl posx, posy, posz;
std::istringstream{itemx->text().toStdString()} >> posx;
std::istringstream{itemy->text().toStdString()} >> posy;
std::istringstream{itemz->text().toStdString()} >> posz;
auto obj = m_plot->GetImpl()->AddLinkedObject(m_sphere);
m_plot->GetImpl()->SetObjectMatrix(obj, m::hom_translation<t_mat_gl>(posx, posy, posz));
}
m_nuclei->scrollToItem(m_nuclei->item(row, 0));
m_nuclei->setCurrentCell(row, 0);
......@@ -441,17 +498,40 @@ void StructFactDlg::TableItemChanged(QTableWidgetItem *item)
void StructFactDlg::ShowTableContextMenu(const QPoint& pt)
{
const auto* item = m_nuclei->itemAt(pt);
if(!item)
return;
m_iCursorRow = item->row();
auto ptGlob = m_nuclei->mapToGlobal(pt);
ptGlob.setY(ptGlob.y() + m_pTabContextMenu->sizeHint().height()/2);
m_pTabContextMenu->popup(ptGlob);
if(const auto* item = m_nuclei->itemAt(pt); item)
{
m_iCursorRow = item->row();
ptGlob.setY(ptGlob.y() + m_pTabContextMenu->sizeHint().height()/2);
m_pTabContextMenu->popup(ptGlob);
}
else
{
ptGlob.setY(ptGlob.y() + m_pTabContextMenuNoItem->sizeHint().height()/2);
m_pTabContextMenuNoItem->popup(ptGlob);
}
}
// ----------------------------------------------------------------------------
void StructFactDlg::Load()
{
}
void StructFactDlg::Save()
{
}
// ----------------------------------------------------------------------------
/**
* reads nuclei positions from table
*/
......@@ -491,6 +571,7 @@ std::vector<NuclPos> StructFactDlg::GetNuclei() const
}
/**
* calculate structure factors
*/
......@@ -630,6 +711,22 @@ void StructFactDlg::Calc()
}
void StructFactDlg::AfterGLInitialisation()
{
m_sphere = m_plot->GetImpl()->AddSphere(0.1, 0.,0.,0., 1.,0.,0.,1.);
m_plot->GetImpl()->SetObjectVisible(m_sphere, false);
// GL device info
auto [strGlVer, strGlShaderVer, strGlVendor, strGlRenderer]
= m_plot->GetImpl()->GetGlDescr();
m_labelGlInfos[0]->setText(QString("GL Version: ") + strGlVer.c_str() + QString("."));
m_labelGlInfos[1]->setText(QString("GL Shader Version: ") + strGlShaderVer.c_str() + QString("."));
m_labelGlInfos[2]->setText(QString("GL Vendor: ") + strGlVendor.c_str() + QString("."));
m_labelGlInfos[3]->setText(QString("GL Device: ") + strGlRenderer.c_str() + QString("."));
}
void StructFactDlg::closeEvent(QCloseEvent *evt)
{
if(m_sett) m_sett->setValue("geo", saveGeometry());
......@@ -651,9 +748,10 @@ static inline void set_locales()
int main(int argc, char** argv)
{
auto app = std::make_unique<QApplication>(argc, argv);
set_gl_format(1, _GL_MAJ_VER, _GL_MIN_VER, 8);
set_locales();
auto app = std::make_unique<QApplication>(argc, argv);
auto dlg = std::make_unique<StructFactDlg>(nullptr);
dlg->show();
......
......@@ -15,12 +15,16 @@
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QSpinBox>
#include <QtWidgets/QMenu>
#include <QtWidgets/QLabel>
#include <QtCore/QSettings>
#include <vector>
#include <sstream>
#include <complex>
#include "../glplot/glplot.h"
using t_real = double;
using t_cplx = std::complex<t_real>;
......@@ -33,6 +37,9 @@ public:
: QTableWidgetItem(std::to_string(std::forward<T>(val)).c_str())
{}
NumericTableWidgetItem(const QString& val) : QTableWidgetItem(val)
{}
virtual bool operator<(const QTableWidgetItem& item) const override
{
T val1{}, val2{};
......@@ -41,6 +48,11 @@ public:
return val1 < val2;
}
virtual QTableWidgetItem* clone() const override
{
return new NumericTableWidgetItem<T>(this->text());
};
};
......@@ -61,6 +73,10 @@ public:
protected:
QSettings *m_sett = nullptr;
std::shared_ptr<GlPlot> m_plot;
std::size_t m_sphere = 0;
QLabel *m_labelGlInfos[4] = { nullptr, nullptr, nullptr, nullptr };