diff options
| author | Nikita Kostovsky <nikita@kostovsky.me> | 2025-09-20 17:34:39 +0200 |
|---|---|---|
| committer | Nikita Kostovsky <nikita@kostovsky.me> | 2025-09-20 17:34:39 +0200 |
| commit | b724e714d24b7623718016af921e1d9aab8d02ea (patch) | |
| tree | 3d4efb61e43d8e6196c7eda061181897b27a9eee /src/graphicsscene.cpp | |
| parent | ad001563fda4a9061909bd09dcf51238138014d6 (diff) | |
Diffstat (limited to 'src/graphicsscene.cpp')
| -rw-r--r-- | src/graphicsscene.cpp | 199 |
1 files changed, 198 insertions, 1 deletions
diff --git a/src/graphicsscene.cpp b/src/graphicsscene.cpp index 52416d5..e918ccc 100644 --- a/src/graphicsscene.cpp +++ b/src/graphicsscene.cpp @@ -4,6 +4,8 @@ #include <QGraphicsEllipseItem> #include <QGraphicsLineItem> #include <QGraphicsPolygonItem> +#include <QGraphicsTextItem> +#include <QGraphicsView> namespace orphex { @@ -31,7 +33,7 @@ GraphicsScene::GraphicsScene(QObject* parent) QLineF{QPointF{0, -50}, QPointF{0, 50}}, m_lenseItem }; - m_lineOfActionItem->setPen(QPen{Qt::gray, 0}); + m_lineOfActionItem->setPen(QPen{Qt::green, 0}); m_opticalAxisItem = new QGraphicsLineItem{ QLineF{QPointF{-1000, 0}, QPointF{1000, 0}}, @@ -72,10 +74,47 @@ GraphicsScene::GraphicsScene(QObject* parent) m_actualRangeAreaItem->setPen(QPen{m_sensorItem->pen().color(), 0}); m_actualRangeAreaItem->setBrush(QBrush{m_sensorItem->pen().color()}); m_actualRangeAreaItem->setOpacity(0.1); + + m_sensorLenseIntersectionItem = new QGraphicsEllipseItem{ + QRectF{QPointF{-1, -1}, QPointF{1, 1}}, + m_lenseItem + }; + m_sensorLenseIntersectionItem->setPen(QPen{Qt::red, 0.1}); + + const auto sensorLenseTextItem = new QGraphicsTextItem{ + tr("Scheimpflug: sensor/lense"), + m_sensorLenseIntersectionItem + }; + + sensorLenseTextItem->setPos(QPointF{-6, -8}); + auto font = sensorLenseTextItem->font(); + font.setPixelSize(2); + sensorLenseTextItem->setFont(font); + sensorLenseTextItem->setDefaultTextColor( + m_sensorLenseIntersectionItem->pen().color() + ); + + m_lenseLaserIntersectionItem = new QGraphicsEllipseItem{ + QRectF{QPointF{-1, -1}, QPointF{1, 1}}, + m_lenseItem + }; + m_lenseLaserIntersectionItem->setPen(QPen{Qt::blue, 0}); + + const auto lenseLaserTextItem = new QGraphicsTextItem{ + tr("Scheimpflug: lense/laser"), + m_lenseLaserIntersectionItem + }; + + lenseLaserTextItem->setPos(QPointF{-6, -2}); + lenseLaserTextItem->setFont(font); + lenseLaserTextItem->setDefaultTextColor( + m_lenseLaserIntersectionItem->pen().color() + ); } void GraphicsScene::update(OpticalDesign* design) { + qDebug() << "update"; if (!design) { qCritical() << Q_FUNC_INFO << "design is nullptr"; @@ -229,4 +268,162 @@ void GraphicsScene::update(OpticalDesign* design) ); // TODO: take back focal length into account + + // check Scheimpflug principle + // TODO: draw lines? + QPointF sensorLenseIntersection{}; + + if (m_sensorItem->line().intersects( + m_lineOfActionItem->line(), + &sensorLenseIntersection + ) == QLineF::NoIntersection) + { + qWarning() << "no intersection between sensor plane and lense plane"; + return; + } + + m_sensorLenseIntersectionItem->setPos(sensorLenseIntersection); + + QPointF lenseLaserIntersection{}; + + if (m_lineOfActionItem->line().intersects( + m_actualRangeItem->line(), + &lenseLaserIntersection + ) == QLineF::NoIntersection) + { + qWarning() << "no intersection between laser plane and lense plane"; + return; + } + + m_lenseLaserIntersectionItem->setPos(lenseLaserIntersection); + + if (!qFuzzyCompare(sensorLenseIntersection, lenseLaserIntersection)) + { + qWarning() << "The Scheimpflug principle is not observed:" << Qt::endl + << "sensor/lense intersection:" << sensorLenseIntersection + << Qt::endl + << "lense/laser intersection:" << lenseLaserIntersection; + } + + // TODO: move to settings + // doesn't work (doesn't zoom) + constexpr bool autoScale{false}; + + if (autoScale) + { + // region of interest + QRectF ROI{}; + + ROI |= m_actualRangeAreaItem->boundingRect(); + ROI |= m_desiredRangeAreaItem->boundingRect(); + ROI |= m_lenseItem->boundingRect(); + ROI |= m_sensorItem->boundingRect(); + ROI |= m_sensorLenseIntersectionItem->boundingRect(); + ROI |= m_lenseLaserIntersectionItem->boundingRect(); + + for (const auto& view : views()) + { + // TODO: move to settings + constexpr double margin{5.}; + view->setSceneRect(ROI); + } + } + + // calculate distance between sensor and lense on optical axis + QPointF sensorAxisIntersection{}; + + if (m_sensorItem->line().intersects( + m_opticalAxisItem->line(), + &sensorAxisIntersection + ) == QLineF::NoIntersection) + { + qCritical() << "no intersection between sensor and optical axis"; + return; + } + + design->set_lenseSensorDistanceMm( + QLineF{QPointF{0, 0}, sensorAxisIntersection}.length() + ); + + // calculate depth of field + QPointF axisLaserIntersection{}; + + if (m_opticalAxisItem->line().intersects( + m_actualRangeItem->line(), + &axisLaserIntersection + ) == QLineF::NoIntersection) + { + qCritical() << "no intersection between laser and optical axis"; + return; + } + + // const auto zM = std::min( + // design->get_sensorPixelsHeight(), + // design->get_sensorPixelsWidth() + // ) / + // 1000. / 1000.; + + // try z based on sensor cell size + // const auto zMm = std::min( + // design->get_sensorCellHeightUm(), + // design->get_sensorCellHeightUm() + // ) / + // 1000.; + // try z based on 1/16 sensor cell size (calibration step) + const auto zMm = std::min( + design->get_sensorCellHeightUm(), + design->get_sensorCellWidthUm() + ) / + 1000. / 16.; + + // try z based on E. Goldovsky method - 0.2% of sensor height + // const auto zMm = design->get_sensorHeightMm() * 0.2 / 100.; + // const auto RM = + // QLineF{QPointF{0., 0.}, axisLaserIntersection}.length() * 1000.; + const auto RMidMm = QLineF{QPointF{0., 0.}, axisLaserIntersection}.length(); + // const auto RFrontMm = QLineF{QPointF{0., 0.}, + // axisLaserIntersection}.length(); const auto fM = + // design->get_backFocalDistanceMm() * 1000.; + + // Gordijchuk & Pell, 1979, say to use focal distance. + // Wikipedia, based on the same book, says to use back focal distance. WTF? + // const auto fMm = design->get_backFocalDistanceMm(); + const auto fMm = design->get_focalDistanceMm(); + + const auto K = static_cast<int>(design->get_lenseAperture()) / 10.; + + using FromSharpDistMm = double; + using BackSharpDistMm = double; + using DofResult = std::tuple<FromSharpDistMm, BackSharpDistMm>; + const auto calculateDof = [zMm, fMm, K](const auto RMm) -> DofResult { + const auto ff = fMm * fMm; + const auto Rff = RMm * ff; + const auto Kfz = K * fMm * zMm; + const auto KRz = K * RMm * zMm; + + const auto R1Mm = Rff / (ff - Kfz + KRz); + const auto R2Mm = Rff / (ff + Kfz - KRz); + + return {R1Mm, R2Mm}; + }; + + const auto ff = fMm * fMm; + const auto Rff = RMidMm * ff; + const auto Kfz = K * fMm * zMm; + const auto KRz = K * RMidMm * zMm; + + // const auto R1M = Rff / (ff - Kfz + KRz); + // const auto R2M = Rff / (ff + Kfz - KRz); + + // const auto R1Mm = Rff / (ff - Kfz + KRz); + // const auto R2Mm = Rff / (ff + Kfz - KRz); + + const auto [R1Mm, R2Mm] = calculateDof(RMidMm); + + qDebug() << "AAAAA: update" << R1Mm << R2Mm + << design->get_sensorCellHeightUm(); + + design->set_frontSharpDistanceMm(R1Mm); + design->set_backSharpDistanceMm(R2Mm); + design->set_depthOfFieldMm((R2Mm - R1Mm)); } |
