summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/graphicsscene.cpp298
-rw-r--r--src/graphicsscene.h18
-rw-r--r--src/main.cpp4
-rw-r--r--src/mainwindow.cpp265
-rw-r--r--src/mainwindow.h3
-rw-r--r--src/opticaldesign.cpp48
-rw-r--r--src/opticaldesign.h49
7 files changed, 621 insertions, 64 deletions
diff --git a/src/graphicsscene.cpp b/src/graphicsscene.cpp
index e918ccc..6850c1f 100644
--- a/src/graphicsscene.cpp
+++ b/src/graphicsscene.cpp
@@ -12,7 +12,55 @@ namespace orphex
namespace constants
{
const QLineF laserPlane{QPointF{-1000, 0}, QPointF{1000, 0}};
+
+const auto laserColor = QColor{Qt::red};
+const auto sensorColor = QColor{Qt::red};
}
+
+/*!
+ * \brief vFoVDegrees - get "vertical" (YZ projection) Field of View (degrees)
+ * \param vSensorPlane - sensor plane (YZ projection)
+ * \param vLaserRange - laser range (YZ projection)
+ * \return - Field of View angle (degrees)
+ */
+double vFoVDegrees(const QLineF& vSensorPlane, const QLineF& vLaserRange);
+
+/*!
+ * \brief lenseBodyRect - create 2d rectangle representing lense body
+ * \param diameterMm - body diameter (mm)
+ * \param lengthMm - body length (mm)
+ * \return - corresponding 2d body rect
+ */
+QRectF lenseBodyRect(const double diameterMm, const double lengthMm);
+
+/*!
+ * \brief laserBodyRect - create 2d rectangle representing laser body
+ * \param diameterMm - body diameter (mm)
+ * \param lengthMm - body length (mm)
+ * \return - corresponding 2d body rect
+ */
+QRectF laserBodyRect(const double diameterMm, const double lengthMm);
+
+/*!
+ * \brief laserBodyRect - create 2d rectangle representing laser body
+ * \param diameterMm - body diameter (mm)
+ * \param lengthMm - body length (mm)
+ * \return - corresponding 2d body rect
+ */
+
+/*!
+ * \brief scannerBodyFrontWallRect - create 2d rectangle representing front wall
+ * of scanner body
+ * \param thicknessMm - wall thickness (mm)
+ * \param offsetMm - horizontal offset from lense center (mm)
+ * \return - corresponding 2d body rect
+ */
+QRectF scannerBodyFrontWallRect(
+ const double thicknessMm,
+ const double offsetMm
+);
+
+QList<QPointF> xzLaserAreaPolygon(const double laserAngle);
} // namespace orphex
GraphicsScene::GraphicsScene(QObject* parent)
@@ -26,11 +74,13 @@ GraphicsScene::GraphicsScene(QObject* parent)
);
m_lenseItem->setTransformOriginPoint(m_lenseItem->boundingRect().center());
- m_sensorItem = new QGraphicsLineItem(QLineF{}, m_lenseItem);
- m_sensorItem->setPen(QPen{Qt::red, 0});
+ m_yzSensorItem = new QGraphicsLineItem{QLineF{}, m_lenseItem};
+ m_yzSensorItem->setPen(QPen{orphex::constants::sensorColor, 0});
+
+ m_xzSensorItem = addRect({}, QPen{orphex::constants::sensorColor, 0});
m_lineOfActionItem = new QGraphicsLineItem{
- QLineF{QPointF{0, -50}, QPointF{0, 50}},
+ QLineF{QPointF{0, -1000}, QPointF{0, 1000}},
m_lenseItem
};
m_lineOfActionItem->setPen(QPen{Qt::green, 0});
@@ -41,6 +91,31 @@ GraphicsScene::GraphicsScene(QObject* parent)
};
m_opticalAxisItem->setPen(QPen{Qt::gray, 0});
+ m_lenseVerticalPlaneItem = addLine(
+ QLineF{QPointF{0, -1000}, QPointF{0, 1000}},
+ QPen{Qt::black, 0}
+ );
+
+ m_lenseBodyItem = addRect(
+ QRectF{},
+ QPen{m_lenseItem->pen().color(), 0},
+ QBrush{m_lenseItem->pen().color(), Qt::DiagCrossPattern}
+ );
+ m_lenseBodyItem->setParentItem(m_lenseItem);
+ m_lenseBodyItem->setOpacity(0.1);
+
+ m_laserBodyItem = addRect(
+ QRectF{},
+ QPen{Qt::black, 0},
+ QBrush{Qt::black, Qt::DiagCrossPattern}
+ );
+
+ m_scannerBodyFrontWallItem = addRect(
+ QRectF{},
+ QPen{Qt::lightGray, 0},
+ QBrush{Qt::lightGray, Qt::DiagCrossPattern}
+ );
+
using namespace orphex::constants;
m_laserPlaneItem = addLine(laserPlane, QPen{Qt::black, 0});
m_laserPlaneItem->stackBefore(m_lenseItem);
@@ -55,7 +130,7 @@ GraphicsScene::GraphicsScene(QObject* parent)
m_desiredImagePlaneItem = new QGraphicsLineItem(QLineF{}, m_lenseItem);
m_desiredImagePlaneItem->setPen(QPen{Qt::yellow, 0.15});
- m_desiredImagePlaneItem->stackBefore(m_sensorItem);
+ m_desiredImagePlaneItem->stackBefore(m_yzSensorItem);
m_desiredRangeAreaItem = new QGraphicsPolygonItem{m_lenseItem};
m_desiredRangeAreaItem->setPen(
@@ -71,10 +146,18 @@ GraphicsScene::GraphicsScene(QObject* parent)
m_actualRangeItem->setOpacity(0.5);
m_actualRangeAreaItem = new QGraphicsPolygonItem{m_lenseItem};
- m_actualRangeAreaItem->setPen(QPen{m_sensorItem->pen().color(), 0});
- m_actualRangeAreaItem->setBrush(QBrush{m_sensorItem->pen().color()});
+ m_actualRangeAreaItem->setPen(QPen{m_yzSensorItem->pen().color(), 0});
+ m_actualRangeAreaItem->setBrush(QBrush{m_yzSensorItem->pen().color()});
m_actualRangeAreaItem->setOpacity(0.1);
+ m_xzActualRangeAreaItem = addPolygon(
+ {},
+ m_actualRangeItem->pen(),
+ m_actualRangeAreaItem->brush()
+ );
+ m_xzActualRangeAreaItem->setOpacity(0.1);
+ // m_xzActualRangeAreaItem->setParentItem(m_lenseItem);
+
m_sensorLenseIntersectionItem = new QGraphicsEllipseItem{
QRectF{QPointF{-1, -1}, QPointF{1, 1}},
m_lenseItem
@@ -110,6 +193,23 @@ GraphicsScene::GraphicsScene(QObject* parent)
lenseLaserTextItem->setDefaultTextColor(
m_lenseLaserIntersectionItem->pen().color()
);
+
+ m_xzHardwareLaserPlaneItem = addPolygon(
+ QPolygonF{},
+ // QPen{orphex::constants::laserColor, 0.},
+ QPen{Qt::black, 0.},
+ // QBrush{orphex::constants::laserColor, Qt::DiagCrossPattern}
+ QBrush{Qt::black, Qt::DiagCrossPattern}
+ );
+ m_xzHardwareLaserPlaneItem->setOpacity(0.2);
+ m_xzHardwareLaserPlaneItem->setParentItem(m_laserBodyItem);
+ m_xzDebugItem = addPolygon(
+ QPolygonF{},
+ QPen{Qt::green, 0.},
+ QBrush{Qt::green, Qt::DiagCrossPattern}
+ );
+ m_xzDebugItem->setOpacity(0.1);
+ m_xzDebugItem->setParentItem(m_laserBodyItem);
}
void GraphicsScene::update(OpticalDesign* design)
@@ -221,17 +321,59 @@ void GraphicsScene::update(OpticalDesign* design)
const auto offset = sensorLine.pointAt(1 + offsetRatio) - sensorLine.p2();
sensorLine.setPoints(sensorLine.p1() + offset, sensorLine.p2() + offset);
- m_sensorItem->setLine(sensorLine);
+ m_yzSensorItem->setLine(sensorLine);
+
+ const auto sensorHalfWidth = design->get_sensorWidthMm() / 2.;
+ const QRectF xzSensorRect{
+ QPointF{
+ // m_yzSensorItem->mapToScene(sensorLine.p1()).x(),
+ sensorLine.p1().x(),
+ sensorHalfWidth
+ },
+ QPointF{
+ // m_yzSensorItem->mapToScene(sensorLine.p2()).x(),
+ sensorLine.p2().x(),
+ -sensorHalfWidth
+ }
+ };
+ m_xzSensorItem->setRect(xzSensorRect);
+
+ // const auto yzFoVAngle = QLineF{m_lenseItem->pos(), }
+ // const auto axisAngleD = design->get_opticalAxisAngleDegrees();
+ // const QLineF sceneAxis{
+ // m_opticalAxisItem->mapToScene(m_opticalAxisItem->line().p1()),
+ // m_opticalAxisItem->mapToScene(m_opticalAxisItem->line().p1())
+ // };
+ // for (auto& p : xzActualRangePolygon)
+ // {
+ // // qDebug() << "AZAZA hyp:" << p.x();
+ // // p.setX(sceneAxis.x1());
+ // // qt_noop();
+ // // p.setX(std::sin(qDegreesToRadians(axisAngleD)) * p.x());
+ // // p.setX(std::cos(qDegreesToRadians(axisAngleD)) * p.x());
+ // // p.setX(p.x() / std::cos(qDegreesToRadians(axisAngleD)));
+ // // p.setX(m_lenseItem->mapFromScene(p).x());
+ // p = QPointF
+ // }
+
+ // m_xzActualRangeAreaItem->setRotation(180.);
+
+ const auto p1 = xzSensorRect.topLeft();
+ const auto p2 = xzSensorRect.bottomRight();
// find laser plane range which corresponds to sensor position
m_actualRangeItem->setLine({
- imageToObject(m_sensorItem->line().p1()),
- imageToObject(m_sensorItem->line().p2()),
+ imageToObject(m_yzSensorItem->line().p1()),
+ imageToObject(m_yzSensorItem->line().p2()),
});
- // not that object area has negative coords
+ // note that object area has negative coords
+ // const auto tmp = m_actualRangeItem->line();
+ // const auto tmp2 = m_actualRangeItem->mapToScene(tmp.p1());
+
design->set_actualZBaseMm(
- -m_actualRangeItem->mapToScene(m_actualRangeItem->line().p1()).x()
+ -m_actualRangeItem->mapToScene(m_actualRangeItem->line().p1()).x() /*+
+ design->fullBodyOffset()*/
);
design->set_actualZRangeMm(m_actualRangeItem->line().length());
@@ -256,13 +398,17 @@ void GraphicsScene::update(OpticalDesign* design)
// fill actual range area
m_actualRangeAreaItem->setPolygon(
QPolygonF{
- {m_sensorItem->line().p1(),
- m_sensorItem->line().p2(),
+ {m_yzSensorItem->line().p1(),
+ m_yzSensorItem->line().p2(),
m_actualRangeItem->line().p2(),
m_actualRangeItem->line().p1()}
}
);
+ design->set_vFoVDegrees(
+ orphex::vFoVDegrees(m_yzSensorItem->line(), m_actualRangeItem->line())
+ );
+
design->set_sensorLenseAngleDegrees(
m_desiredImagePlaneItem->line().angleTo(m_lineOfActionItem->line())
);
@@ -273,7 +419,7 @@ void GraphicsScene::update(OpticalDesign* design)
// TODO: draw lines?
QPointF sensorLenseIntersection{};
- if (m_sensorItem->line().intersects(
+ if (m_yzSensorItem->line().intersects(
m_lineOfActionItem->line(),
&sensorLenseIntersection
) == QLineF::NoIntersection)
@@ -317,7 +463,7 @@ void GraphicsScene::update(OpticalDesign* design)
ROI |= m_actualRangeAreaItem->boundingRect();
ROI |= m_desiredRangeAreaItem->boundingRect();
ROI |= m_lenseItem->boundingRect();
- ROI |= m_sensorItem->boundingRect();
+ ROI |= m_yzSensorItem->boundingRect();
ROI |= m_sensorLenseIntersectionItem->boundingRect();
ROI |= m_lenseLaserIntersectionItem->boundingRect();
@@ -332,7 +478,7 @@ void GraphicsScene::update(OpticalDesign* design)
// calculate distance between sensor and lense on optical axis
QPointF sensorAxisIntersection{};
- if (m_sensorItem->line().intersects(
+ if (m_yzSensorItem->line().intersects(
m_opticalAxisItem->line(),
&sensorAxisIntersection
) == QLineF::NoIntersection)
@@ -425,5 +571,123 @@ void GraphicsScene::update(OpticalDesign* design)
design->set_frontSharpDistanceMm(R1Mm);
design->set_backSharpDistanceMm(R2Mm);
- design->set_depthOfFieldMm((R2Mm - R1Mm));
+ const auto depthOfFieldMm = R2Mm - R1Mm;
+ design->set_depthOfFieldMm(depthOfFieldMm);
+
+ if (qFuzzyIsNull(depthOfFieldMm))
+ {
+ emit design->depthOfFieldMmChanged();
+ emit design->depthOfFieldMmChanged(depthOfFieldMm);
+ }
+
+ m_lenseBodyItem->setRect(
+ orphex::lenseBodyRect(
+ design->get_lenseBodyMaxDiameterMm(),
+ design->get_lenseBodyLengthMm()
+ )
+ );
+
+ m_laserBodyItem->setRect(
+ orphex::laserBodyRect(
+ design->get_laserBodyDiameterMm(),
+ design->get_laserBodyLengthMm()
+ )
+ );
+
+ m_scannerBodyFrontWallItem->setRect(
+ orphex::scannerBodyFrontWallRect(
+ design->get_scannerBodyWallThicknessMm(),
+ design->get_scannerBodyFrontWallOffsetMm()
+ )
+ );
+
+ {
+ m_xzHardwareLaserPlaneItem->setPolygon(
+ orphex::xzLaserAreaPolygon(design->get_laserAngleDegrees())
+ );
+ }
+
+ {
+ const auto item = m_actualRangeItem;
+ const auto line = item->line();
+ const auto x1 = item->mapToScene(line.p1()).x();
+ const auto x2 = item->mapToScene(line.p2()).x();
+ QPolygonF xzActualRangePolygon{QList<QPointF>{
+ QPointF{x1, imageToObject(m_xzSensorItem->rect().topLeft()).y()},
+ QPointF{x1, imageToObject(m_xzSensorItem->rect().bottomLeft()).y()},
+ QPointF{
+ x2,
+ imageToObject(m_xzSensorItem->rect().bottomRight()).y()
+ },
+ QPointF{x2, imageToObject(m_xzSensorItem->rect().topRight()).y()},
+ }};
+ m_xzActualRangeAreaItem->setPolygon(xzActualRangePolygon);
+
+ m_xzDebugItem->setPolygon(
+ QPolygonF{QList<QPointF>{
+ QPointF{0., 0.},
+ QPointF{
+ x1,
+ imageToObject(m_xzSensorItem->rect().topLeft()).y()
+ },
+ QPointF{
+ x1,
+ imageToObject(m_xzSensorItem->rect().bottomLeft()).y()
+ },
+ }}
+ );
+ }
+}
+
+double orphex::vFoVDegrees(
+ const QLineF& vSensorPlane,
+ const QLineF& vLaserRange
+)
+{
+ const auto sl = vSensorPlane;
+ const auto arl = vLaserRange;
+
+ const QLineF l0{sl.p1(), arl.p1()};
+ const QLineF l1{sl.p2(), arl.p2()};
+
+ return l1.angleTo(l0);
+}
+
+QRectF orphex::lenseBodyRect(const double diameterMm, const double lengthMm)
+{
+ return QRectF{
+ QPointF{-lengthMm, -diameterMm / 2.},
+ QSizeF{lengthMm, diameterMm}
+ };
+}
+
+QRectF orphex::laserBodyRect(const double diameterMm, const double lengthMm)
+{
+ return QRectF{QPointF{0., -diameterMm / 2.}, QSizeF{lengthMm, diameterMm}};
+}
+
+QRectF orphex::scannerBodyFrontWallRect(
+ const double thicknessMm,
+ const double offsetMm
+)
+{
+ return QRectF{
+ QPointF{offsetMm - thicknessMm, -1000.},
+ QPointF{offsetMm, 1000.}
+ };
+}
+
+QList<QPointF> orphex::xzLaserAreaPolygon(const double laserAngle)
+{
+ QLineF line{QPointF{0., 0.}, QPointF{-1000., 0.}};
+
+ line.setAngle(180. + laserAngle / 2.);
+
+ QList<QPointF> result{QPointF{0., 0.}, line.p2()};
+
+ line.setAngle(180. - laserAngle / 2.);
+
+ result << line.p2();
+
+ return result;
}
diff --git a/src/graphicsscene.h b/src/graphicsscene.h
index 1c50c78..1303eb2 100644
--- a/src/graphicsscene.h
+++ b/src/graphicsscene.h
@@ -21,17 +21,33 @@ public slots:
private:
QGraphicsLineItem* m_lineOfActionItem{nullptr};
QGraphicsEllipseItem* m_lenseItem{nullptr};
+ QGraphicsRectItem* m_lenseBodyItem{nullptr};
QGraphicsLineItem* m_opticalAxisItem{nullptr};
+ QGraphicsLineItem* m_lenseVerticalPlaneItem{nullptr};
+ QGraphicsRectItem* m_laserBodyItem{nullptr};
QGraphicsLineItem* m_laserPlaneItem{nullptr};
QGraphicsLineItem* m_desiredLaserPlaneItem{nullptr};
QGraphicsLineItem* m_reverseLaserPlaneItem{nullptr};
QGraphicsLineItem* m_desiredImagePlaneItem{nullptr};
- QGraphicsLineItem* m_sensorItem{nullptr};
+ QGraphicsLineItem* m_yzSensorItem{nullptr};
+ QGraphicsRectItem* m_xzSensorItem{nullptr};
+
QGraphicsLineItem* m_actualRangeItem{nullptr};
QGraphicsPolygonItem* m_desiredRangeAreaItem{nullptr};
QGraphicsPolygonItem* m_actualRangeAreaItem{nullptr};
+ QGraphicsPolygonItem* m_xzActualRangeAreaItem{nullptr};
+
+ QGraphicsRectItem* m_scannerBodyFrontWallItem{nullptr};
+
+ /*!
+ * \brief m_xzHardwareLaserPlaneItem - actual laser-illuminated area,
+ * limited by its angle
+ */
+ QGraphicsPolygonItem* m_xzHardwareLaserPlaneItem{nullptr};
+
// debug
QGraphicsEllipseItem* m_sensorLenseIntersectionItem{nullptr};
QGraphicsEllipseItem* m_lenseLaserIntersectionItem{nullptr};
+ QGraphicsPolygonItem* m_xzDebugItem{nullptr};
};
diff --git a/src/main.cpp b/src/main.cpp
index 96ec1e3..dce33fc 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2,10 +2,14 @@
#include <QApplication>
+#include "opticaldesign.h"
+
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
+ qRegisterMetaType<orphex::LenseAperture>("orphex::LenseAperture");
+
a.setApplicationName("OpticalDesign");
a.setApplicationDisplayName("Optical Design");
// TODO: move to cmake
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index e73df5a..464beb4 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -4,11 +4,13 @@
#include <QComboBox>
#include <QDoubleSpinBox>
#include <QFormLayout>
+#include <QGroupBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QOpenGLWidget>
#include <QShortcut>
#include <QStyle>
+#include <QTimer>
// optical design
#include "graphicsscene.h"
@@ -38,8 +40,9 @@ void MainWindow::initUi()
const auto mainLayout = new QHBoxLayout{mainWidget};
mainWidget->setLayout(mainLayout);
- // addLayout sets parent below
- const auto leftLayout = new QFormLayout{};
+
+ const auto leftPanel = new QWidget{mainWidget};
+ const auto leftLayout = new QFormLayout{mainWidget};
leftLayout->setLabelAlignment(Qt::AlignVCenter | Qt::AlignRight);
mainLayout->addLayout(leftLayout);
@@ -59,6 +62,22 @@ void MainWindow::initUi()
using MinValue = double;
using MaxValue = double;
using SingleStep = double;
+
+ const auto newGroup = [mainWidget, leftLayout](const QString&& title) {
+ const auto group = new QGroupBox{std::move(title), mainWidget};
+ const auto layout = new QFormLayout{group};
+ leftLayout->addRow(group);
+
+ return group;
+ };
+
+ const auto lenseGroup = newGroup(tr("Lense"));
+ const auto sensorGroup = newGroup(tr("Sensor"));
+ const auto rangeGroup = newGroup(tr("Range"));
+ const auto laserGroup = newGroup(tr("Laser"));
+ const auto scannerBodyGroup = newGroup(tr("Scanner Body"));
+ const auto resultsGroup = newGroup(tr("Results"));
+
auto addFormPair = [this, leftLayout, connectWidgetToProperty](
const QString text,
const auto propertySignal,
@@ -66,7 +85,8 @@ void MainWindow::initUi()
const auto propertySetter,
const MinValue minValue,
const MaxValue maxValue,
- const SingleStep singleStep = 0.1
+ const SingleStep singleStep = 0.1,
+ const QGroupBox* groupBox = nullptr
) {
const auto spinBox = new QDoubleSpinBox{centralWidget()};
spinBox->setRange(minValue, maxValue);
@@ -87,14 +107,25 @@ void MainWindow::initUi()
std::bind(&GraphicsScene::update, m_scene, m_design)
);
- leftLayout->addRow(text, spinBox);
+ if (groupBox)
+ {
+ const auto formLayout =
+ qobject_cast<QFormLayout*>(groupBox->layout());
+ Q_ASSERT(formLayout);
+ formLayout->addRow(text, spinBox);
+ }
+ else
+ {
+ leftLayout->addRow(text, spinBox);
+ }
};
using Decimals = int;
auto addFormLabel = [this, leftLayout](
const QString text,
const auto propertySignal,
- const Decimals decimals = 2
+ const Decimals decimals = 2,
+ const QGroupBox* groupBox = nullptr
) {
const auto label = new QLabel{centralWidget()};
@@ -102,15 +133,28 @@ void MainWindow::initUi()
m_design,
propertySignal,
label,
- [label, decimals](const auto value) {
+ [label, decimals, text](const auto value) {
+ qDebug() << "AZAZA: changed:" << text << value;
label->setText(QString::number(value, 'F', decimals));
}
);
- leftLayout->addRow(text, label);
+ if (groupBox)
+ {
+ const auto formLayout =
+ qobject_cast<QFormLayout*>(groupBox->layout());
+ Q_ASSERT(formLayout);
+ formLayout->addRow(text, label);
+ }
+ else
+ {
+ leftLayout->addRow(text, label);
+ }
};
- const auto createLenseApertureComboBox = [this, leftLayout]() {
+ const auto createLenseApertureComboBox = [this](QFormLayout* formLayout) {
+ Q_ASSERT(formLayout);
+
const auto comboBox = new QComboBox{centralWidget()};
using namespace orphex;
@@ -143,17 +187,20 @@ void MainWindow::initUi()
);
// update combobox on property change
+ const auto onApertureChanged = [this, comboBox](const auto value) {
+ comboBox->setCurrentIndex(
+ comboBox->findData(QVariant::fromValue(value))
+ );
+ };
connect(
m_design,
qOverload<LenseAperture>(&OpticalDesign::lenseApertureChanged),
comboBox,
- [comboBox](const auto value) {
- comboBox->setCurrentIndex(
- comboBox->findData(QVariant::fromValue(value))
- );
- }
+ onApertureChanged
);
+ onApertureChanged(m_design->get_lenseAperture());
+
connect(
m_design,
qOverload<>(&OpticalDesign::lenseApertureChanged),
@@ -161,7 +208,7 @@ void MainWindow::initUi()
std::bind(&GraphicsScene::update, m_scene, m_design)
);
- leftLayout->addRow(tr("Lense A&perture:"), comboBox);
+ formLayout->addRow(tr("A&perture:"), comboBox);
};
addFormPair(
@@ -170,17 +217,20 @@ void MainWindow::initUi()
&OpticalDesign::get_opticalAxisAngleDegrees,
&OpticalDesign::set_opticalAxisAngleDegrees,
MinValue{10.},
- MaxValue{85.}
+ MaxValue{85.},
+ SingleStep{0.1},
+ lenseGroup
);
addFormPair(
- tr("Lense &Y pos (mm):"),
+ tr("&Y pos (mm):"),
qOverload<double>(&OpticalDesign::lenseYPosMmChanged),
&OpticalDesign::get_lenseYPosMm,
&OpticalDesign::set_lenseYPosMm,
MinValue{10.},
MaxValue{500.},
- SingleStep{1.}
+ SingleStep{1.},
+ lenseGroup
);
addFormPair(
@@ -189,7 +239,9 @@ void MainWindow::initUi()
&OpticalDesign::get_focalDistanceMm,
&OpticalDesign::set_focalDistanceMm,
MinValue{1.},
- MaxValue{45.}
+ MaxValue{45.},
+ SingleStep{0.1},
+ lenseGroup
);
addFormPair(
tr("&Back Focal Distance (mm):"),
@@ -197,55 +249,90 @@ void MainWindow::initUi()
&OpticalDesign::get_backFocalDistanceMm,
&OpticalDesign::set_backFocalDistanceMm,
MinValue{1.},
- MaxValue{45.}
+ MaxValue{45.},
+ SingleStep{0.1},
+ lenseGroup
+ );
+
+ createLenseApertureComboBox(
+ qobject_cast<QFormLayout*>(lenseGroup->layout())
+ );
+
+ addFormPair(
+ tr("Body Max Diameter (mm):"),
+ qOverload<double>(&OpticalDesign::lenseBodyMaxDiameterMmChanged),
+ &OpticalDesign::get_lenseBodyMaxDiameterMm,
+ &OpticalDesign::set_lenseBodyMaxDiameterMm,
+ MinValue{1.},
+ MaxValue{100.},
+ SingleStep{1.},
+ lenseGroup
);
- createLenseApertureComboBox();
+ addFormPair(
+ tr("Body Length (mm):"),
+ qOverload<double>(&OpticalDesign::lenseBodyLengthMmChanged),
+ &OpticalDesign::get_lenseBodyLengthMm,
+ &OpticalDesign::set_lenseBodyLengthMm,
+ MinValue{1.},
+ MaxValue{100.},
+ SingleStep{1.},
+ lenseGroup
+ );
addFormPair(
- tr("Sensor &Width (mm):"),
+ tr("&Width (mm):"),
qOverload<double>(&OpticalDesign::sensorWidthMmChanged),
&OpticalDesign::get_sensorWidthMm,
&OpticalDesign::set_sensorWidthMm,
MinValue{1.},
- MaxValue{30.}
+ MaxValue{30.},
+ SingleStep{0.1},
+ sensorGroup
);
addFormPair(
- tr("Sensor &Height (mm):"),
+ tr("&Height (mm):"),
qOverload<double>(&OpticalDesign::sensorHeightMmChanged),
&OpticalDesign::get_sensorHeightMm,
&OpticalDesign::set_sensorHeightMm,
MinValue{1.},
- MaxValue{30.}
+ MaxValue{30.},
+ SingleStep{0.1},
+ sensorGroup
);
addFormPair(
- tr("Sensor Cell W&idth (mm):"),
+ tr("Cell W&idth (µm):"),
qOverload<double>(&OpticalDesign::sensorCellWidthUmChanged),
&OpticalDesign::get_sensorCellWidthUm,
&OpticalDesign::set_sensorCellWidthUm,
MinValue{1.},
- MaxValue{30.}
+ MaxValue{30.},
+ SingleStep{0.1},
+ sensorGroup
);
addFormPair(
- tr("Sensor Cell H&eight (mm):"),
+ tr("Cell H&eight (µm):"),
qOverload<double>(&OpticalDesign::sensorCellHeightUmChanged),
&OpticalDesign::get_sensorCellHeightUm,
&OpticalDesign::set_sensorCellHeightUm,
MinValue{1.},
- MaxValue{30.}
+ MaxValue{30.},
+ SingleStep{0.1},
+ sensorGroup
);
addFormPair(
- tr("Sensor Vertical &Offset (mm):"),
+ tr("Vertical &Offset (mm):"),
qOverload<double>(&OpticalDesign::sensorVerticalOffsetMmChanged),
&OpticalDesign::get_sensorVerticalOffsetMm,
&OpticalDesign::set_sensorVerticalOffsetMm,
MinValue{-50.},
MaxValue{50.},
- SingleStep{0.1}
+ SingleStep{0.1},
+ sensorGroup
);
addFormPair(
@@ -255,7 +342,8 @@ void MainWindow::initUi()
&OpticalDesign::set_zBaseMm,
MinValue{1.},
MaxValue{10000.},
- SingleStep{1.}
+ SingleStep{1.},
+ rangeGroup
);
addFormPair(
@@ -265,49 +353,144 @@ void MainWindow::initUi()
&OpticalDesign::set_zRangeMm,
MinValue{1.},
MaxValue{10000.},
- SingleStep{1.}
+ SingleStep{1.},
+ rangeGroup
+ );
+
+ addFormPair(
+ tr("Body Diameter (mm):"),
+ qOverload<double>(&OpticalDesign::laserBodyDiameterMmChanged),
+ &OpticalDesign::get_laserBodyDiameterMm,
+ &OpticalDesign::set_laserBodyDiameterMm,
+ MinValue{1.},
+ MaxValue{100.},
+ SingleStep{1.},
+ laserGroup
+ );
+
+ addFormPair(
+ tr("Body Length (mm):"),
+ qOverload<double>(&OpticalDesign::laserBodyLengthMmChanged),
+ &OpticalDesign::get_laserBodyLengthMm,
+ &OpticalDesign::set_laserBodyLengthMm,
+ MinValue{1.},
+ MaxValue{100.},
+ SingleStep{1.},
+ laserGroup
+ );
+
+ addFormPair(
+ tr("Angle (°):"),
+ qOverload<double>(&OpticalDesign::laserAngleDegreesChanged),
+ &OpticalDesign::get_laserAngleDegrees,
+ &OpticalDesign::set_laserAngleDegrees,
+ MinValue{1.},
+ MaxValue{180.},
+ SingleStep{1.},
+ laserGroup
+ );
+ addFormPair(
+ tr("Z Offest (mm):"),
+ qOverload<double>(&OpticalDesign::laserZOffsetMmChanged),
+ &OpticalDesign::get_laserZOffsetMm,
+ &OpticalDesign::set_laserZOffsetMm,
+ MinValue{-100.},
+ MaxValue{100.},
+ SingleStep{1.},
+ laserGroup
+ );
+
+ addFormPair(
+ tr("Wall Thickness (mm):"),
+ qOverload<double>(&OpticalDesign::scannerBodyWallThicknessMmChanged),
+ &OpticalDesign::get_scannerBodyWallThicknessMm,
+ &OpticalDesign::set_scannerBodyWallThicknessMm,
+ MinValue{1.},
+ MaxValue{30.},
+ SingleStep{1.},
+ scannerBodyGroup
+ );
+
+ addFormPair(
+ tr("Front Wall Offset (mm):"),
+ qOverload<double>(&OpticalDesign::scannerBodyFrontWallOffsetMmChanged),
+ &OpticalDesign::get_scannerBodyFrontWallOffsetMm,
+ &OpticalDesign::set_scannerBodyFrontWallOffsetMm,
+ MinValue{-50.},
+ MaxValue{50.},
+ SingleStep{1.},
+ scannerBodyGroup
);
addFormLabel(
tr("Sensor/Lense Angle (°):"),
qOverload<double>(&OpticalDesign::sensorLenseAngleDegreesChanged),
- Decimals{3}
+ Decimals{3},
+ resultsGroup
);
addFormLabel(
- tr("Actual Z Base (mm):"),
- qOverload<double>(&OpticalDesign::actualZBaseMmChanged),
- Decimals{2}
+ tr("FoV (YZ, V) (°):"),
+ qOverload<double>(&OpticalDesign::vFoVDegreesChanged),
+ Decimals{3},
+ resultsGroup
);
+ // addFormLabel(
+ // tr("Actual Z Base (mm):"),
+ // qOverload<double>(&OpticalDesign::actualZBaseMmChanged),
+ // Decimals{2},
+ // resultsGroup
+ // );
+
+ {
+ const auto actualZBaseTextLabel = new QLabel{centralWidget()};
+
+ connect(
+ m_design,
+ &OpticalDesign::actualZBaseTextChanged,
+ actualZBaseTextLabel,
+ &QLabel::setText
+ );
+
+ auto formLayout = qobject_cast<QFormLayout*>(resultsGroup->layout());
+ Q_ASSERT(formLayout);
+ formLayout->addRow(tr("Actual Z Base (mm):"), actualZBaseTextLabel);
+ }
+
addFormLabel(
tr("Actual Z Range (mm):"),
qOverload<double>(&OpticalDesign::actualZRangeMmChanged),
- Decimals{2}
+ Decimals{2},
+ resultsGroup
);
addFormLabel(
tr("Lense-Sensor Distance (mm):"),
qOverload<double>(&OpticalDesign::lenseSensorDistanceMmChanged),
- Decimals{2}
+ Decimals{2},
+ resultsGroup
);
addFormLabel(
tr("Front Sharp Distance (mm):"),
qOverload<double>(&OpticalDesign::frontSharpDistanceMmChanged),
- Decimals{2}
+ Decimals{2},
+ resultsGroup
);
addFormLabel(
tr("Back Sharp Distance (mm):"),
qOverload<double>(&OpticalDesign::backSharpDistanceMmChanged),
- Decimals{2}
+ Decimals{2},
+ resultsGroup
);
addFormLabel(
tr("Depth Of Field (mm):"),
qOverload<double>(&OpticalDesign::depthOfFieldMmChanged),
- Decimals{2}
+ Decimals{2},
+ resultsGroup
);
// graphics view
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 3b4922a..a1e613d 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -2,6 +2,7 @@
// qt
#include <QMainWindow>
+#include <QProperty>
// optical design
class GraphicsScene;
@@ -13,7 +14,7 @@ class MainWindow : public QMainWindow
Q_OBJECT
public:
- MainWindow(QWidget *parent = nullptr);
+ explicit MainWindow(QWidget* parent = nullptr);
~MainWindow();
private:
diff --git a/src/opticaldesign.cpp b/src/opticaldesign.cpp
index 01f6050..15d8001 100644
--- a/src/opticaldesign.cpp
+++ b/src/opticaldesign.cpp
@@ -3,6 +3,32 @@
// qt
#include <QSize>
+OpticalDesign::OpticalDesign(QObject* parent)
+ : goodies::G_Object{parent}
+{
+ const auto emitActualZBaseTextChanged = [this]() {
+ emit actualZBaseTextChanged(actualZBaseText());
+ };
+ connect(
+ this,
+ qOverload<>(&OpticalDesign::actualZBaseMmChanged),
+ this,
+ emitActualZBaseTextChanged
+ );
+ connect(
+ this,
+ qOverload<>(&OpticalDesign::scannerBodyFrontWallOffsetMmChanged),
+ this,
+ emitActualZBaseTextChanged
+ );
+ connect(
+ this,
+ qOverload<>(&OpticalDesign::scannerBodyWallThicknessMmChanged),
+ this,
+ emitActualZBaseTextChanged
+ );
+}
+
void OpticalDesign::calculate() const
{
const auto F = get_focalDistanceMm();
@@ -12,3 +38,25 @@ void OpticalDesign::calculate() const
const auto hMm = get_sensorHeightMm();
const auto oAngle = get_opticalAxisAngleDegrees();
}
+
+/*
+double OpticalDesign::fullBodyOffset() const
+{
+ return get_scannerBodyFrontWallOffsetMm() -
+ get_scannerBodyWallThicknessMm();
+}
+*/
+
+QString OpticalDesign::actualZBaseText() const
+{
+ constexpr int decimals{2};
+ return QStringLiteral("%1 (%2)")
+ .arg(get_actualZBaseMm(), 0, 'f', decimals)
+ .arg(
+ get_actualZBaseMm() + get_scannerBodyFrontWallOffsetMm() -
+ get_scannerBodyWallThicknessMm(),
+ 0,
+ 'f',
+ decimals
+ );
+}
diff --git a/src/opticaldesign.h b/src/opticaldesign.h
index 5a7ebac..c1ff634 100644
--- a/src/opticaldesign.h
+++ b/src/opticaldesign.h
@@ -16,6 +16,7 @@ enum class LenseAperture
F1_2 = 12,
F1_4 = 14,
F2_0 = 20,
+ F2_5 = 25,
F2_8 = 28,
F4_0 = 40,
F5_6 = 56,
@@ -34,20 +35,32 @@ enum class LenseAperture
Q_ENUM_NS(LenseAperture)
} // namespace orphex
-// Q_DECLARE_METATYPE(orphex::LenseAperture)
-
class OpticalDesign : public goodies::G_Object
{
Q_OBJECT
- DEFAULT_CONSTRUCTOR(goodies::G_Object, OpticalDesign)
DEFAULT_DESTRUCTOR(OpticalDesign);
G_OBJECT(goodies::G_Object, OpticalDesign)
+protected:
+ Q_PROPERTY(
+ QString actualZBaseText READ actualZBaseText NOTIFY
+ actualZBaseTextChanged FINAL
+ )
+
+public:
+ explicit OpticalDesign(QObject* parent = nullptr);
+
public:
void calculate() const;
-protected:
+public:
+ /*!
+ * \brief fullBodyOffset - negative offset of body border from lense center
+ */
+ // double fullBodyOffset() const;
+
+private:
INI_PROPERTY(double, opticalAxisAngleDegrees, 45.);
// the Y axis is directed from the laser to the lens
INI_PROPERTY(double, lenseYPosMm, 50.);
@@ -60,23 +73,51 @@ protected:
lenseAperture,
orphex::LenseAperture::F1_2
);
+
+ INI_PROPERTY(double, lenseBodyMaxDiameterMm, 14.);
+ INI_PROPERTY(double, lenseBodyLengthMm, 17.);
+
// default values for IMX287 sensor
INI_PROPERTY(double, sensorWidthMm, 4.98);
INI_PROPERTY(double, sensorHeightMm, 3.74);
+
INI_PROPERTY(double, sensorCellWidthUm, 6.9);
INI_PROPERTY(double, sensorCellHeightUm, 6.9);
+
// sensor vertical offset along the image plane
INI_PROPERTY(double, sensorVerticalOffsetMm, 0.);
+
INI_PROPERTY(uint16_t, sensorPixelsHeight, 720);
INI_PROPERTY(uint16_t, sensorPixelsWidth, 544);
+
INI_PROPERTY(double, zBaseMm, 90);
INI_PROPERTY(double, zRangeMm, 250);
+ INI_PROPERTY(double, laserBodyDiameterMm, 14.);
+ INI_PROPERTY(double, laserBodyLengthMm, 45.);
+ INI_PROPERTY(double, laserAngleDegrees, 45.);
+ INI_PROPERTY(double, laserZOffsetMm, 0.);
+
+ INI_PROPERTY(double, scannerBodyWallThicknessMm, 3.);
+
+ INI_PROPERTY(double, scannerBodyFrontWallOffsetMm, -20.);
+
G_PROPERTY_DEFAULT(double, sensorLenseAngleDegrees, 0.);
+ G_PROPERTY_DEFAULT(double, vFoVDegrees, 0.);
+ // takes scanner body into account
G_PROPERTY_DEFAULT(double, actualZBaseMm, 0.);
G_PROPERTY_DEFAULT(double, actualZRangeMm, 0.);
G_PROPERTY_DEFAULT(double, lenseSensorDistanceMm, 0.);
G_PROPERTY_DEFAULT(double, frontSharpDistanceMm, 0.);
G_PROPERTY_DEFAULT(double, backSharpDistanceMm, 0.);
G_PROPERTY_DEFAULT(double, depthOfFieldMm, 0.);
+
+ // manual properties
+signals:
+ void actualZBaseTextChanged(QString value);
+
+public:
+ QString actualZBaseText() const;
};
+
+Q_DECLARE_METATYPE(orphex::LenseAperture)