//########################################################################## //# # //# CLOUDCOMPARE # //# # //# This program is free software; you can redistribute it and/or modify # //# it under the terms of the GNU General Public License as published by # //# the Free Software Foundation; version 2 or later of the License. # //# # //# This program is distributed in the hope that it will be useful, # //# but WITHOUT ANY WARRANTY; without even the implied warranty of # //# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # //# GNU General Public License for more details. # //# # //# COPYRIGHT: EDF R&D / TELECOM ParisTech (ENST-TSI) # //# # //########################################################################## #include "ccPointPropertiesDlg.h" //Local #include "ccCommon.h" //qCC_gl #include #include //qCC_db #include #include #include #include #include //CCCoreLib #include //Qt #include //System #include ccPointPropertiesDlg::ccPointPropertiesDlg(ccPickingHub* pickingHub, QWidget* parent) : ccPointPickingGenericInterface(pickingHub, parent) , Ui::PointPropertiesDlg() , m_pickingMode(POINT_INFO) { setupUi(this); connect(closeButton, &QToolButton::clicked, this, &ccPointPropertiesDlg::onClose); connect(pointPropertiesButton, &QToolButton::clicked, this, &ccPointPropertiesDlg::activatePointPropertiesDisplay); connect(pointPointDistanceButton, &QToolButton::clicked, this, &ccPointPropertiesDlg::activateDistanceDisplay); connect(pointsAngleButton, &QToolButton::clicked, this, &ccPointPropertiesDlg::activateAngleDisplay); connect(rectZoneToolButton, &QToolButton::clicked, this, &ccPointPropertiesDlg::activate2DZonePicking); connect(saveLabelButton, &QToolButton::clicked, this, &ccPointPropertiesDlg::exportCurrentLabel); connect(razButton, &QToolButton::clicked, this, &ccPointPropertiesDlg::initializeState); //for points picking m_label = new cc2DLabel(); m_label->setSelected(true); //for 2D zone picking m_rect2DLabel = new cc2DViewportLabel(); m_rect2DLabel->setVisible(false); //=invalid m_rect2DLabel->setSelected(true); //=closed } ccPointPropertiesDlg::~ccPointPropertiesDlg() { if (m_label) delete m_label; m_label = nullptr; if (m_rect2DLabel) delete m_rect2DLabel; m_rect2DLabel = nullptr; } bool ccPointPropertiesDlg::linkWith(ccGLWindowInterface* win) { assert(m_label && m_rect2DLabel); ccGLWindowInterface* oldWin = m_associatedWin; if (!ccPointPickingGenericInterface::linkWith(win)) { return false; } //old window? if (oldWin) { oldWin->removeFromOwnDB(m_label); oldWin->removeFromOwnDB(m_rect2DLabel); oldWin->setInteractionMode(ccGLWindowInterface::MODE_TRANSFORM_CAMERA); oldWin->signalEmitter()->disconnect(this); } m_rect2DLabel->setVisible(false); //=invalid m_rect2DLabel->setSelected(true); //=closed m_label->clear(); //new window? if (m_associatedWin) { m_associatedWin->addToOwnDB(m_label); m_associatedWin->addToOwnDB(m_rect2DLabel); connect(m_associatedWin->signalEmitter(), &ccGLWindowSignalEmitter::mouseMoved, this, &ccPointPropertiesDlg::update2DZone); connect(m_associatedWin->signalEmitter(), &ccGLWindowSignalEmitter::leftButtonClicked, this, &ccPointPropertiesDlg::processClickedPoint); connect(m_associatedWin->signalEmitter(), &ccGLWindowSignalEmitter::buttonReleased, this, &ccPointPropertiesDlg::close2DZone); } return true; } bool ccPointPropertiesDlg::start() { activatePointPropertiesDisplay(); return ccPointPickingGenericInterface::start(); } void ccPointPropertiesDlg::stop(bool state) { assert(m_label && m_rect2DLabel); m_label->clear(); m_rect2DLabel->setVisible(false); //=invalid m_rect2DLabel->setSelected(true); //=closed if (m_associatedWin) m_associatedWin->setInteractionMode(ccGLWindowInterface::MODE_TRANSFORM_CAMERA); ccPointPickingGenericInterface::stop(state); } void ccPointPropertiesDlg::onClose() { stop(false); } void ccPointPropertiesDlg::activatePointPropertiesDisplay() { if (m_associatedWin) m_associatedWin->setInteractionMode(ccGLWindowInterface::MODE_TRANSFORM_CAMERA); m_pickingMode = POINT_INFO; pointPropertiesButton->setDown(true); pointPointDistanceButton->setDown(false); pointsAngleButton->setDown(false); rectZoneToolButton->setDown(false); m_label->setVisible(true); m_rect2DLabel->setVisible(false); } void ccPointPropertiesDlg::activateDistanceDisplay() { m_pickingMode = POINT_POINT_DISTANCE; pointPropertiesButton->setDown(false); pointPointDistanceButton->setDown(true); pointsAngleButton->setDown(false); rectZoneToolButton->setDown(false); m_label->setVisible(true); m_rect2DLabel->setVisible(false); if (m_associatedWin) { m_associatedWin->setInteractionMode(ccGLWindowInterface::MODE_TRANSFORM_CAMERA); m_associatedWin->redraw(false); } } void ccPointPropertiesDlg::activateAngleDisplay() { m_pickingMode = POINTS_ANGLE; pointPropertiesButton->setDown(false); pointPointDistanceButton->setDown(false); pointsAngleButton->setDown(true); rectZoneToolButton->setDown(false); m_label->setVisible(true); m_rect2DLabel->setVisible(false); if (m_associatedWin) { m_associatedWin->setInteractionMode(ccGLWindowInterface::MODE_TRANSFORM_CAMERA); m_associatedWin->redraw(false); } } void ccPointPropertiesDlg::activate2DZonePicking() { m_pickingMode = RECT_ZONE; pointPropertiesButton->setDown(false); pointPointDistanceButton->setDown(false); pointsAngleButton->setDown(false); rectZoneToolButton->setDown(true); m_label->setVisible(false); //m_rect2DLabel->setVisible(false); if (m_associatedWin) { m_associatedWin->setInteractionMode(ccGLWindowInterface::INTERACT_SEND_ALL_SIGNALS); m_associatedWin->redraw(false); } } void ccPointPropertiesDlg::initializeState() { assert(m_label && m_rect2DLabel); m_label->clear(); m_rect2DLabel->setVisible(false); //=invalid m_rect2DLabel->setSelected(true); //=closed if (m_associatedWin) m_associatedWin->redraw(false); } void ccPointPropertiesDlg::exportCurrentLabel() { ccHObject* labelObject = nullptr; if (m_pickingMode == RECT_ZONE) labelObject = (m_rect2DLabel->isSelected() && m_rect2DLabel->isVisible() ? m_rect2DLabel : nullptr); else labelObject = (m_label && m_label->size() > 0 ? m_label : nullptr); if (!labelObject) { return; } //detach current label from window if (m_associatedWin) m_associatedWin->removeFromOwnDB(labelObject); labelObject->setSelected(false); ccHObject* newLabelObject = nullptr; if (m_pickingMode == RECT_ZONE) { //if (m_associatedWin) // m_rect2DLabel->setParameters(m_associatedWin->getViewportParameters()); newLabelObject = m_rect2DLabel = new cc2DViewportLabel(); m_rect2DLabel->setVisible(false); //=invalid m_rect2DLabel->setSelected(true); //=closed } else { //attach old label to first point cloud by default m_label->getPickedPoint(0).entity()->addChild(labelObject); newLabelObject = m_label = new cc2DLabel(); m_label->setSelected(true); } Q_EMIT newLabel(labelObject); if (m_associatedWin) { m_associatedWin->addToOwnDB(newLabelObject); m_associatedWin->redraw(true, false); } } void ccPointPropertiesDlg::processPickedPoint(const PickedItem& picked) { assert(picked.entity); assert(m_label); assert(m_associatedWin); switch (m_pickingMode) { case POINT_INFO: m_label->clear(); break; case POINT_POINT_DISTANCE: if (m_label->size() >= 2) m_label->clear(); break; case POINTS_ANGLE: if (m_label->size() >= 3) m_label->clear(); break; case RECT_ZONE: return; //we don't use this slot for 2D mode } if (picked.entity->isKindOf(CC_TYPES::POINT_CLOUD)) { m_label->addPickedPoint(static_cast(picked.entity), picked.itemIndex, picked.entityCenter); } else if (picked.entity->isKindOf(CC_TYPES::MESH)) { m_label->addPickedPoint(static_cast(picked.entity), picked.itemIndex, CCVector2d(picked.uvw.x, picked.uvw.y), picked.entityCenter); } else { assert(false); return; } m_label->setVisible(true); m_label->displayPointLegend(m_label->size() == 3); //we need to display 'A', 'B' and 'C' for 3-points labels if (m_label->size() == 1 && m_associatedWin) { m_label->setPosition(static_cast(picked.clickPoint.x() + 20) / m_associatedWin->glWidth(), static_cast(picked.clickPoint.y() + 20) / m_associatedWin->glHeight()); } //output info to Console QStringList body = m_label->getLabelContent(ccGui::Parameters().displayedNumPrecision); ccLog::Print(QString("[Picked] ") + m_label->getName()); for (QString& row : body) { ccLog::Print(QString("[Picked]\t- ") + row); } if (m_associatedWin) { m_associatedWin->redraw(); } } void ccPointPropertiesDlg::processClickedPoint(int x, int y) { if (m_pickingMode != RECT_ZONE) { return; } if (!m_rect2DLabel || !m_associatedWin) { assert(false); return; } QPointF pos2D = m_associatedWin->toCenteredGLCoordinates(x, y); if (m_rect2DLabel->isSelected()) //already closed? we start a new label { cc2DViewportLabel::ROI roi{ static_cast(pos2D.x()), static_cast(pos2D.y()), 0.0f, 0.0f}; if (m_associatedWin) { m_rect2DLabel->setParameters(m_associatedWin->getViewportParameters()); } m_rect2DLabel->setVisible(false); //=invalid m_rect2DLabel->setSelected(false); //=not closed m_rect2DLabel->setRoi(roi); m_rect2DLabel->setName(QString()); //reset name before display! } else //we close the existing one { cc2DViewportLabel::ROI roi {m_rect2DLabel->roi()[0], m_rect2DLabel->roi()[1], static_cast(pos2D.x()), static_cast(pos2D.y()) }; m_rect2DLabel->setRoi(roi); m_rect2DLabel->setVisible(true); //=valid m_rect2DLabel->setSelected(true); //=closed } if (m_associatedWin) { m_associatedWin->redraw(true, false); } } void ccPointPropertiesDlg::update2DZone(int x, int y, Qt::MouseButtons buttons) { if (m_pickingMode != RECT_ZONE) { return; } if (m_rect2DLabel->isSelected()) { return; } if (!m_associatedWin) { assert(false); return; } QPointF pos2D = m_associatedWin->toCenteredGLCoordinates(x, y); cc2DViewportLabel::ROI roi {m_rect2DLabel->roi()[0], m_rect2DLabel->roi()[1], static_cast(pos2D.x()), static_cast(pos2D.y()) }; m_rect2DLabel->setRoi(roi); m_rect2DLabel->setVisible(true); m_associatedWin->redraw(true, false); } static QString s_last2DLabelComment; void ccPointPropertiesDlg::close2DZone() { if (m_pickingMode != RECT_ZONE) return; if (m_rect2DLabel->isSelected() || !m_rect2DLabel->isVisible()) return; m_rect2DLabel->setSelected(true); bool ok; QString title = QInputDialog::getText(this, "Set area label title", "Title:", QLineEdit::Normal, s_last2DLabelComment, &ok); if (!ok) { m_rect2DLabel->setVisible(false); } else { m_rect2DLabel->setName(title); s_last2DLabelComment = title; } if (m_associatedWin) m_associatedWin->redraw(true, false); }