Commit 68385eb2 authored by Tobias WEBER's avatar Tobias WEBER
Browse files

added fractional units

parent 0fcfea5c
......@@ -445,6 +445,7 @@ std::size_t GlPlot_impl::AddCoordinateCross(t_real_gl min, t_real_gl max)
QMutexLocker _locker{&m_mutexObj};
auto obj = CreateLineObject(verts, col);
obj.m_invariant = true;
m_objs.emplace_back(std::move(obj));
return m_objs.size()-1; // object handle
......@@ -479,6 +480,9 @@ in vec4 vertexcol;
out vec4 fragcol;
const float pi = ${PI};
// ----------------------------------------------------------------------------
// transformations
// ----------------------------------------------------------------------------
......@@ -486,6 +490,10 @@ uniform mat4 proj = mat4(1.);
uniform mat4 cam = mat4(1.);
uniform mat4 cam_inv = mat4(1.);
uniform mat4 obj = mat4(1.);
uniform mat4 trafoA = mat4(1.);
uniform mat4 trafoB = mat4(1.); // B = 2 pi / A
uniform int coordsys = 0; // 0: crystal system, 1: lab system
// ----------------------------------------------------------------------------
......@@ -583,8 +591,19 @@ float lighting(vec4 objVert, vec4 objNorm)
void main()
{
vec4 objPos = obj * vertex;
vec4 objNorm = obj * normal;
mat4 coordTrafo = mat4(1.);
mat4 coordTrafo_inv = mat4(1.);
if(coordsys == 1)
{
coordTrafo = trafoA;
coordTrafo_inv = trafoB / (2.*pi);
coordTrafo_inv[3][3] = 1.;
}
// coordTrafo_inv is needed so not to distort the object
vec4 objPos = coordTrafo * obj * coordTrafo_inv * vertex;
vec4 objNorm = normalize(coordTrafo * obj * coordTrafo_inv * normal);
gl_Position = proj * cam * objPos;
float I = lighting(objPos, objNorm);
......@@ -595,10 +614,14 @@ void main()
// --------------------------------------------------------------------
// set glsl version
std::string strGlsl = std::to_string(_GL_MAJ_VER*100 + _GL_MIN_VER*10);
// set glsl version and constants
const std::string strGlsl = std::to_string(_GL_MAJ_VER*100 + _GL_MIN_VER*10);
const std::string strPi = std::to_string(m::pi<t_real_gl>);
for(std::string* strSrc : { &strFragShader, &strVertexShader })
{
algo::replace_all(*strSrc, std::string("${GLSL_VERSION}"), strGlsl);
algo::replace_all(*strSrc, std::string("${PI}"), strPi);
}
// GL functions
......@@ -645,6 +668,9 @@ void main()
m_uniMatrixCamInv = m_pShaders->uniformLocation("cam_inv");
m_uniMatrixProj = m_pShaders->uniformLocation("proj");
m_uniMatrixObj = m_pShaders->uniformLocation("obj");
m_uniMatrixA = m_pShaders->uniformLocation("trafoA");
m_uniMatrixB = m_pShaders->uniformLocation("trafoB");
m_uniCoordSys = m_pShaders->uniformLocation("coordsys");
m_uniConstCol = m_pShaders->uniformLocation("constcol");
m_uniLightPos = m_pShaders->uniformLocation("lightpos");
m_uniNumActiveLights = m_pShaders->uniformLocation("activelights");
......@@ -726,6 +752,58 @@ void GlPlot_impl::resizeGL()
}
/**
* set up a (crystal) B matrix
*/
void GlPlot_impl::SetBTrafo(const t_mat_gl& matB, const t_mat_gl* matA)
{
m_matB = matB;
// if A matix is not given, calculate it
if(matA)
{
m_matA = *matA;
}
else
{
bool ok = true;
std::tie(m_matA, ok) = m::inv(m_matB);
if(!ok)
{
m_matA = m::unit<t_mat_gl>();
std::cerr << "Error: Cannot invert B matrix." << std::endl;
}
else
{
m_matA *= t_real_gl(2)*m::pi<t_real_gl>;
m_matA(3,3) = 1;
}
}
m_bBTrafoNeedsUpdate = true;
RequestPlotUpdate();
}
void GlPlot_impl::SetCoordSys(int iSys)
{
m_iCoordSys = iSys;
RequestPlotUpdate();
}
/**
* update the shader's B matrix
*/
void GlPlot_impl::UpdateBTrafo()
{
m_pShaders->setUniformValue(m_uniMatrixA, m_matA);
m_pShaders->setUniformValue(m_uniMatrixB, m_matB);
m_bBTrafoNeedsUpdate = false;
}
void GlPlot_impl::UpdateCam()
{
m_matCam = m_matCamBase;
......@@ -824,11 +902,24 @@ void GlPlot_impl::UpdatePicker()
}
// crystal or lab coordinate system?
const t_mat_gl matUnit = m::unit<t_mat_gl>();
const t_mat_gl *coordTrafo = &matUnit;
t_mat_gl coordTrafoInv = matUnit;
if(m_iCoordSys == 1)
{
coordTrafo = &m_matA;
coordTrafoInv = m_matB / (t_real_gl(2)*m::pi<t_real_gl>);
coordTrafoInv(3,3) = 1;
}
// intersection with geometry
bool hasInters = false;
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)
......@@ -841,14 +932,17 @@ void GlPlot_impl::UpdatePicker()
if(linkedObj->m_type != GlPlotObjType::TRIANGLES || !obj.m_visible || !obj.m_valid)
continue;
linkedObj->m_pcolorbuf->bind();
BOOST_SCOPE_EXIT(&linkedObj) { linkedObj->m_pcolorbuf->release(); } BOOST_SCOPE_EXIT_END
for(std::size_t startidx=0; startidx+2<linkedObj->m_triangles.size(); startidx+=3)
{
std::vector<t_vec3_gl> poly{{ linkedObj->m_triangles[startidx+0], linkedObj->m_triangles[startidx+1], linkedObj->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]
} };
// coordTrafoInv only keeps 3d objects from locally distorting
auto [vecInters, bInters, lamInters] =
m::intersect_line_poly<t_vec3_gl, t_mat_gl>(org3, dir3, poly, obj.m_mat);
m::intersect_line_poly<t_vec3_gl, t_mat_gl>(org3, dir3, poly, (*coordTrafo) * obj.m_mat * coordTrafoInv);
if(bInters)
{
......@@ -974,6 +1068,7 @@ void GlPlot_impl::DoPaintGL(qgl_funcs *pGl)
LOGGLERR(pGl);
if(m_bLightsNeedUpdate) UpdateLights();
if(m_bBTrafoNeedsUpdate) UpdateBTrafo();
// set cam matrix
m_pShaders->setUniformValue(m_uniMatrixCam, m_matCam);
......@@ -1000,10 +1095,16 @@ void GlPlot_impl::DoPaintGL(qgl_funcs *pGl)
if(!obj.m_visible || !obj.m_valid) continue;
m_pShaders->setUniformValue(m_uniMatrixObj, obj.m_mat);
// set to untransformed coordinate system if the object is invariant
m_pShaders->setUniformValue(m_uniCoordSys, linkedObj->m_invariant ? 0 : m_iCoordSys.load());
// main vertex array object
pGl->glBindVertexArray(linkedObj->m_vertexarr);
m_pShaders->setUniformValue(m_uniMatrixObj, obj.m_mat);
pGl->glEnableVertexAttribArray(m_attrVertex);
if(linkedObj->m_type == GlPlotObjType::TRIANGLES)
......@@ -1018,6 +1119,7 @@ void GlPlot_impl::DoPaintGL(qgl_funcs *pGl)
BOOST_SCOPE_EXIT_END
LOGGLERR(pGl);
if(linkedObj->m_type == GlPlotObjType::TRIANGLES)
pGl->glDrawArrays(GL_TRIANGLES, 0, linkedObj->m_triangles.size());
else if(linkedObj->m_type == GlPlotObjType::LINES)
......@@ -1037,12 +1139,15 @@ void GlPlot_impl::DoPaintGL(qgl_funcs *pGl)
*/
void GlPlot_impl::DoPaintNonGL(QPainter &painter)
{
const t_mat_gl matUnit = m::unit<t_mat_gl>();
QFont fontOrig = painter.font();
QPen penOrig = painter.pen();
QPen penLabel(Qt::black);
painter.setPen(penLabel);
// coordinate labels
painter.drawText(GlToScreenCoords(m::create<t_vec_gl>({0.,0.,0.,1.})), "0");
for(t_real_gl f=-std::floor(m_CoordMax); f<=std::floor(m_CoordMax); f+=0.5)
......@@ -1069,7 +1174,10 @@ void GlPlot_impl::DoPaintNonGL(QPainter &painter)
if(obj.m_label != "")
{
t_vec3_gl posLabel3d = obj.m_mat * obj.m_labelPos;
const t_mat_gl *coordTrafo = &matUnit;
if(m_iCoordSys == 1 && !obj.m_invariant) coordTrafo = &m_matA;
t_vec3_gl posLabel3d = (*coordTrafo) * obj.m_mat * obj.m_labelPos;
auto posLabel2d = GlToScreenCoords(m::create<t_vec_gl>({posLabel3d[0], posLabel3d[1], posLabel3d[2], 1.}));
QFont fontLabel = fontOrig;
......
......@@ -102,6 +102,7 @@ struct GlPlotObj
t_mat_gl m_mat = m::unit<t_mat_gl>();
bool m_invariant = false; // invariant to A, B matrices
bool m_visible = true; // object shown?
bool m_valid = true; // object deleted?
......@@ -138,6 +139,9 @@ protected:
GLint m_uniMatrixCam = -1;
GLint m_uniMatrixCamInv = -1;
GLint m_uniMatrixObj = -1;
GLint m_uniMatrixA = -1;
GLint m_uniMatrixB = -1;
GLint m_uniCoordSys = -1;
t_mat_gl m_matPerspective = m::unit<t_mat_gl>();
t_mat_gl m_matPerspective_inv = m::unit<t_mat_gl>();
......@@ -147,6 +151,8 @@ protected:
t_mat_gl m_matCamRot = m::unit<t_mat_gl>();
t_mat_gl m_matCam = m::unit<t_mat_gl>();
t_mat_gl m_matCam_inv = m::unit<t_mat_gl>();
t_mat_gl m_matA = m::unit<t_mat_gl>();
t_mat_gl m_matB = m::unit<t_mat_gl>();
t_vec_gl m_vecCamX = m::create<t_vec_gl>({1.,0.,0.,0.});
t_vec_gl m_vecCamY = m::create<t_vec_gl>({0.,1.,0.,0.});
t_real_gl m_phi_saved = 0, m_theta_saved = 0;
......@@ -158,6 +164,8 @@ protected:
std::atomic<bool> m_bWantsResize = false;
std::atomic<bool> m_bPickerNeedsUpdate = false;
std::atomic<bool> m_bLightsNeedUpdate = false;
std::atomic<bool> m_bBTrafoNeedsUpdate = false;
std::atomic<int> m_iCoordSys = 0;
std::atomic<int> m_iScreenDims[2] = { 800, 600 };
t_real_gl m_pickerSphereRadius = 1;
......@@ -177,6 +185,7 @@ protected:
void RequestPlotUpdate();
void UpdatePicker();
void UpdateLights();
void UpdateBTrafo();
void DoPaintGL(qgl_funcs *pGL);
void DoPaintNonGL(QPainter &painter);
......@@ -234,6 +243,9 @@ public:
void SetLight(std::size_t idx, const t_vec3_gl& pos);
void SetBTrafo(const t_mat_gl& matB, const t_mat_gl* matA = nullptr);
void SetCoordSys(int iSys);
public /*slots*/:
void paintGL();
......
......@@ -213,6 +213,18 @@ public:
using base_type::base_type;
qmatNN_adapter(const base_type& mat) : base_type{mat} {}
// convert from a different matrix type
template<class t_matOther> qmatNN_adapter(const t_matOther& matOther)
requires is_basic_mat<t_matOther>
{
const std::size_t minRows = std::min(static_cast<std::size_t>(size1()), static_cast<std::size_t>(matOther.size1()));
const std::size_t minCols = std::min(static_cast<std::size_t>(size2()), static_cast<std::size_t>(matOther.size2()));
for(std::size_t i=0; i<minRows; ++i)
for(std::size_t j=0; j<minCols; ++j)
(*this)(i,j) = value_type{matOther(i,j)};
}
size_t size1() const { return ROWS; }
size_t size2() const { return COLS; }
};
......@@ -338,7 +350,7 @@ requires is_mat<t_mat>
*/
template<class t_mat>
void unit(t_mat& mat, std::size_t rows_begin, std::size_t cols_begin, std::size_t rows_end, std::size_t cols_end)
requires is_mat<t_mat>
requires is_basic_mat<t_mat>
{
for(std::size_t i=rows_begin; i<rows_end; ++i)
for(std::size_t j=cols_begin; j<cols_end; ++j)
......@@ -351,7 +363,7 @@ requires is_mat<t_mat>
*/
template<class t_mat>
t_mat unit(std::size_t N1, std::size_t N2)
requires is_mat<t_mat>
requires is_basic_mat<t_mat>
{
t_mat mat;
if constexpr(is_dyn_mat<t_mat>)
......@@ -367,7 +379,7 @@ requires is_mat<t_mat>
*/
template<class t_mat>
t_mat unit(std::size_t N=0)
requires is_mat<t_mat>
requires is_basic_mat<t_mat>
{
return unit<t_mat>(N,N);
}
......@@ -378,7 +390,7 @@ requires is_mat<t_mat>
*/
template<class t_mat>
t_mat zero(std::size_t N1, std::size_t N2)
requires is_mat<t_mat>
requires is_basic_mat<t_mat>
{
t_mat mat;
if constexpr(is_dyn_mat<t_mat>)
......@@ -396,7 +408,7 @@ requires is_mat<t_mat>
*/
template<class t_mat>
t_mat zero(std::size_t N=0)
requires is_mat<t_mat>
requires is_basic_mat<t_mat>
{
return zero<t_mat>(N, N);
}
......
......@@ -106,7 +106,7 @@ std::vector<t_mat> get_cif_sg_ops(gemmi::cif::Block& block)
*/
template<class t_vec, class t_mat, class t_real = typename t_vec::value_type>
std::tuple<const char*, std::vector<t_vec>, std::vector<std::vector<t_vec>>, std::vector<std::string>, Lattice<t_real>>
load_cif(const std::string& filename)
load_cif(const std::string& filename, t_real eps=1e-6)
{
auto ifstr = std::ifstream(filename);
if(!ifstr)
......@@ -162,7 +162,7 @@ load_cif(const std::string& filename)
// make homogeneuous 4-vector
if(atom.size() == 3) atom.push_back(1);
std::vector<t_vec> newatoms = m::apply_ops_hom<t_vec, t_mat, t_real>(atom, ops);
std::vector<t_vec> newatoms = m::apply_ops_hom<t_vec, t_mat, t_real>(atom, ops, eps);
// if no ops are given, just output the raw atom position
if(!ops.size())
......
......@@ -41,6 +41,10 @@ namespace pt = boost::property_tree;
using namespace m_ops;
constexpr t_real g_eps = 1e-6;
constexpr int g_prec = 6;
enum : int
{
COL_NAME = 0,
......@@ -205,7 +209,7 @@ StructFactDlg::StructFactDlg(QWidget* pParent) : QDialog{pParent},
// signals
for(auto* edit : std::vector<QLineEdit*>{{ m_editA, m_editB, m_editC, m_editAlpha, m_editBeta, m_editGamma }})
connect(edit, &QLineEdit::textEdited, this, [this]() { this->Calc(); });
connect(edit, &QLineEdit::textEdited, this, [this]() { this->CalcB(); });
connect(pTabBtnAdd, &QToolButton::clicked, this, [this]() { this->AddTabItem(-1); });
connect(pTabBtnDel, &QToolButton::clicked, this, [this]() { StructFactDlg::DelTabItem(); });
......@@ -221,7 +225,7 @@ StructFactDlg::StructFactDlg(QWidget* pParent) : QDialog{pParent},
if(!m_dlgPlot)
{
m_dlgPlot = new QDialog(this);
m_dlgPlot->setWindowTitle("3D View");
m_dlgPlot->setWindowTitle("Unit Cell - 3D View");
m_plot = std::make_shared<GlPlot>(this);
m_plot->GetImpl()->SetLight(0, m::create<t_vec3_gl>({ 5, 5, 5 }));
......@@ -229,20 +233,38 @@ StructFactDlg::StructFactDlg(QWidget* pParent) : QDialog{pParent},
m_plot->GetImpl()->SetCoordMax(1.);
m_plot->GetImpl()->SetCamBase(m::create<t_mat_gl>({1,0,0,0, 0,0,1,0, 0,-1,0,-1.5, 0,0,0,1}),
m::create<t_vec_gl>({1,0,0,0}), m::create<t_vec_gl>({0,0,1,0}));
auto labCoordSys = new QLabel("Coordinate System:", /*m_dlgPlot*/ this);
auto comboCoordSys = new QComboBox(/*m_dlgPlot*/ this);
m_status3D = new QLabel(/*m_dlgPlot*/ this);
comboCoordSys->addItem("Fractional Units (rlu)");
comboCoordSys->addItem("Lab Units (A)");
m_plot->setSizePolicy(QSizePolicy{QSizePolicy::Expanding, QSizePolicy::Expanding});
labCoordSys->setSizePolicy(QSizePolicy{QSizePolicy::Fixed, QSizePolicy::Fixed});
auto grid = new QGridLayout(m_dlgPlot);
grid->setSpacing(2);
grid->setContentsMargins(4,4,4,4);
grid->addWidget(m_plot.get(), 0,0,1,2);
grid->addWidget(labCoordSys, 1,0,1,1);
grid->addWidget(comboCoordSys, 1,1,1,1);
grid->addWidget(m_status3D, 2,0,1,2);
connect(m_plot.get(), &GlPlot::AfterGLInitialisation, this, &StructFactDlg::AfterGLInitialisation);
connect(m_plot->GetImpl(), &GlPlot_impl::PickerIntersection, this, &StructFactDlg::PickerIntersection);
connect(m_plot.get(), &GlPlot::MouseDown, this, &StructFactDlg::PlotMouseDown);
connect(m_plot.get(), &GlPlot::MouseUp, this, &StructFactDlg::PlotMouseUp);
connect(comboCoordSys, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [this](int val)
{
if(this->m_plot)
this->m_plot->GetImpl()->SetCoordSys(val);
});
m_status3D = new QLabel(this);
auto grid = new QGridLayout(m_dlgPlot);
grid->setSpacing(2);
grid->setContentsMargins(4,4,4,4);
grid->addWidget(m_plot.get(), 0,0,1,1);
grid->addWidget(m_status3D, 1,0,1,1);
if(m_sett && m_sett->contains("geo_3dview"))
m_dlgPlot->restoreGeometry(m_sett->value("geo_3dview").toByteArray());
......@@ -729,32 +751,32 @@ void StructFactDlg::Load()
if(auto opt = node.get_optional<t_real>("sfact.xtal.a"); opt)
{
std::ostringstream ostr; ostr << *opt;
std::ostringstream ostr; ostr.precision(g_prec); ostr << *opt;
m_editA->setText(ostr.str().c_str());
}
if(auto opt = node.get_optional<t_real>("sfact.xtal.b"); opt)
{
std::ostringstream ostr; ostr << *opt;
std::ostringstream ostr; ostr.precision(g_prec); ostr << *opt;
m_editB->setText(ostr.str().c_str());
}
if(auto opt = node.get_optional<t_real>("sfact.xtal.c"); opt)
{
std::ostringstream ostr; ostr << *opt;
std::ostringstream ostr; ostr.precision(g_prec); ostr << *opt;
m_editC->setText(ostr.str().c_str());
}
if(auto opt = node.get_optional<t_real>("sfact.xtal.alpha"); opt)
{
std::ostringstream ostr; ostr << *opt;
std::ostringstream ostr; ostr.precision(g_prec); ostr << *opt;
m_editAlpha->setText(ostr.str().c_str());
}
if(auto opt = node.get_optional<t_real>("sfact.xtal.beta"); opt)
{
std::ostringstream ostr; ostr << *opt;
std::ostringstream ostr; ostr.precision(g_prec); ostr << *opt;
m_editBeta->setText(ostr.str().c_str());
}
if(auto opt = node.get_optional<t_real>("sfact.xtal.gamma"); opt)
{
std::ostringstream ostr; ostr << *opt;
std::ostringstream ostr; ostr.precision(g_prec); ostr << *opt;
m_editGamma->setText(ostr.str().c_str());
}
if(auto opt = node.get_optional<int>("sfact.order"); opt)
......@@ -765,6 +787,7 @@ void StructFactDlg::Load()
{
m_comboSG->setCurrentIndex(*opt);
}
CalcB(false);
// nuclei
......@@ -861,7 +884,7 @@ void StructFactDlg::ImportCIF()
return;
m_sett->setValue("dir", QFileInfo(filename).path());
auto [errstr, atoms, generatedatoms, atomnames, lattice] = load_cif<t_vec, t_mat>(filename.toStdString());
auto [errstr, atoms, generatedatoms, atomnames, lattice] = load_cif<t_vec, t_mat>(filename.toStdString(), g_eps);
if(errstr)
{
QMessageBox::critical(this, "Structure Factors", errstr);
......@@ -874,29 +897,30 @@ void StructFactDlg::ImportCIF()
// lattice
{
std::ostringstream ostr; ostr << lattice.a;
std::ostringstream ostr; ostr.precision(g_prec); ostr << lattice.a;
m_editA->setText(ostr.str().c_str());
}
{
std::ostringstream ostr; ostr << lattice.b;
std::ostringstream ostr; ostr.precision(g_prec); ostr << lattice.b;
m_editB->setText(ostr.str().c_str());
}
{
std::ostringstream ostr; ostr << lattice.c;
std::ostringstream ostr; ostr.precision(g_prec); ostr << lattice.c;
m_editC->setText(ostr.str().c_str());
}
{
std::ostringstream ostr; ostr << lattice.alpha;
std::ostringstream ostr; ostr.precision(g_prec); ostr << lattice.alpha;
m_editAlpha->setText(ostr.str().c_str());
}
{
std::ostringstream ostr; ostr << lattice.beta;
std::ostringstream ostr; ostr.precision(g_prec); ostr << lattice.beta;
m_editBeta->setText(ostr.str().c_str());
}
{
std::ostringstream ostr; ostr << lattice.gamma;
std::ostringstream ostr; ostr.precision(g_prec); ostr << lattice.gamma;
m_editGamma->setText(ostr.str().c_str());
}
CalcB(false);
// atoms
......@@ -952,7 +976,7 @@ void StructFactDlg::GenerateFromSG()
std::string col = m_nuclei->item(row, COL_COL)->text().toStdString();
t_vec nucl = m::create<t_vec>({x, y, z, 1});
auto newnuclei = m::apply_ops_hom<t_vec, t_mat, t_real>(nucl, ops);
auto newnuclei = m::apply_ops_hom<t_vec, t_mat, t_real>(nucl, ops, g_eps);
for(const auto& newnucl : newnuclei)
{
......@@ -1012,30 +1036,64 @@ std::vector<NuclPos> StructFactDlg::GetNuclei() const
}
/**
* calculate crystal B matrix
*/
void StructFactDlg::CalcB(bool bFullRecalc)
{
t_real a,b,c, alpha,beta,gamma;
std::istringstream{m_editA->text().toStdString()} >> a;
std::istringstream{m_editB->text().toStdString()} >> b;
std::istringstream{m_editC->text().toStdString()} >> c;
std::istringstream{m_editAlpha->text().toStdString()} >> alpha;
std::istringstream{m_editBeta->text().toStdString()} >> beta;
std::istringstream{m_editGamma->text().toStdString()} >> gamma;
m_crystB = m::B_matrix<t_mat>(a, b, c,
alpha/180.*m::pi<t_real>, beta/180.*m::pi<t_real>, gamma/180.*m::pi<t_real>);
bool ok = true;
std::tie(m_crystA, ok) = m::inv(m_crystB);
if(!ok)
{
m_crystA = m::unit<t_mat>();
std::cerr << "Error: Cannot invert B matrix." << std::endl;
}
else
{
m_crystA *= t_real_gl(2)*m::pi<t_real_gl>;
}
if(m_plot)
{
t_mat_gl matA{m_crystA};
m_plot->GetImpl()->SetBTrafo(m_crystB, &matA);
}
if(bFullRecalc)
Calc();
}
/**
* calculate structure factors
*/
void StructFactDlg::Calc()
{
const t_real eps = 1e-6;
const int prec = 6;
const auto maxBZ = m_maxBZ->value();
// powder lines
std::vector<PowderLine> powderlines;
auto add_powderline = [&powderlines, eps](t_real Q, t_real I,
auto add_powderline = [&powderlines](t_real Q, t_real I,
t_real h, t_real k, t_real l)
{
std::ostringstream ostrPeak;