13 #include <vtkActor2D.h>
14 #include <vtkCallbackCommand.h>
15 #include <vtkCommand.h>
16 #include <vtkHandleRepresentation.h>
18 #include <vtkPointHandleRepresentation3D.h>
19 #include <vtkPolyLineRepresentation.h>
20 #include <vtkProperty.h>
21 #include <vtkProperty2D.h>
22 #include <vtkRenderWindow.h>
23 #include <vtkRenderWindowInteractor.h>
24 #include <vtkRenderer.h>
25 #include <vtkTextActor.h>
26 #include <vtkTextProperty.h>
28 #include <QApplication>
30 #include <QLayoutItem>
32 #include <QSizePolicy>
60 bool use3DHandles =
true) {
64 rep->SetNumberOfHandles(3);
67 if (
auto* lineProp = rep->GetLineProperty()) {
70 lineProp->SetLineWidth(2.0);
71 lineProp->SetAmbient(1.0);
75 if (
auto* handleProp = rep->GetHandleProperty()) {
79 if (
auto* selectedHandleProp = rep->GetSelectedHandleProperty()) {
85 if (
auto* labelActor = rep->GetAngleLabelActor()) {
86 if (
auto* textProp = labelActor->GetTextProperty()) {
87 textProp->SetFontSize(20);
89 textProp->SetShadow(1);
90 textProp->SetColor(1.0, 1.0, 1.0);
95 rep->SetShowAngleLabel(1);
96 rep->SetShowAngleArc(1);
97 rep->SetArcRadius(1.0);
104 setWindowTitle(tr(
"Protractor Measurement Tool"));
116 m_widget->SetEnabled(0);
121 m_rep->SetVisibility(0);
122 if (
auto* labelActor = m_rep->GetAngleLabelActor()) {
123 labelActor->SetVisibility(0);
125 if (
auto* arcActor = m_rep->GetAngleArcActor()) {
126 arcActor->SetVisibility(0);
137 m_configUi =
nullptr;
150 m_widget->SetRepresentation(m_rep);
161 configurePolyLineRepresentation(m_rep,
true);
164 if (
auto* lineProp = m_rep->GetLineProperty()) {
165 lineProp->SetColor(m_currentColor[0], m_currentColor[1],
168 if (
auto* selectedLineProp = m_rep->GetSelectedLineProperty()) {
169 selectedLineProp->SetColor(m_currentColor[0], m_currentColor[1],
175 double defaultPos1[3] = {0.0, 0.0, 0.0};
176 double defaultCenter[3] = {1.0, 0.0, 0.0};
177 double defaultPos2[3] = {1.0, 1.0, 0.0};
187 double diagLength = diag.
norm();
188 double offset = diagLength * 0.3;
198 defaultCenter[0] = center.
x;
199 defaultCenter[1] = center.
y +
offset;
200 defaultCenter[2] = center.
z +
offset;
202 defaultPos1[0] = center.
x - diag.
x * 0.25;
203 defaultPos1[1] = center.
y +
offset;
204 defaultPos1[2] = center.
z +
offset;
206 defaultPos2[0] = center.
x + diag.
x * 0.25;
207 defaultPos2[1] = center.
y +
offset;
208 defaultPos2[2] = center.
z +
offset;
211 m_rep->SetHandlePosition(0, defaultPos1);
212 m_rep->SetHandlePosition(1, defaultCenter);
213 m_rep->SetHandlePosition(2, defaultPos2);
216 m_rep->BuildRepresentation();
220 applyFontProperties();
234 m_configUi->centerXSpinBox->setValue(defaultCenter[0]);
235 m_configUi->centerYSpinBox->setValue(defaultCenter[1]);
236 m_configUi->centerZSpinBox->setValue(defaultCenter[2]);
237 m_configUi->point1XSpinBox->setValue(defaultPos1[0]);
238 m_configUi->point1YSpinBox->setValue(defaultPos1[1]);
239 m_configUi->point1ZSpinBox->setValue(defaultPos1[2]);
240 m_configUi->point2XSpinBox->setValue(defaultPos2[0]);
241 m_configUi->point2YSpinBox->setValue(defaultPos2[1]);
242 m_configUi->point2ZSpinBox->setValue(defaultPos2[2]);
245 updateAngleDisplay();
251 hookWidget(m_widget);
262 CVLog::Error(
"[cvProtractorTool::createUi] m_ui is null!");
272 if (m_configUi &&
m_ui->configLayout) {
275 while ((item =
m_ui->configLayout->takeAt(0)) !=
nullptr) {
276 if (item->widget()) {
277 item->widget()->setParent(
nullptr);
278 item->widget()->deleteLater();
283 m_configUi =
nullptr;
287 m_configUi =
new Ui::ProtractorToolDlg;
288 QWidget* configWidget =
new QWidget(
this);
292 m_configUi->setupUi(configWidget);
295 if (configWidget->layout()) {
296 configWidget->layout()->setSizeConstraint(QLayout::SetMinimumSize);
298 m_ui->configLayout->addWidget(configWidget);
299 m_ui->groupBox->setTitle(tr(
"Protractor Parameters"));
302 m_configUi->instructionLabel->setText(
303 m_configUi->instructionLabel->text().replace(
"Ctrl",
"Cmd"));
310 if (m_configUi->instructionLabel) {
318 m_configUi->instructionLabel->setMaximumHeight(
322 m_configUi->instructionLabel->setMaximumWidth(
324 m_configUi->instructionLabel->setWordWrap(
true);
327 m_configUi->instructionLabel->adjustSize();
329 m_configUi->instructionLabel->updateGeometry();
336 this->setMinimumSize(0, 0);
337 this->setMaximumSize(16777215, 16777215);
342 configWidget->adjustSize();
345 this->updateGeometry();
347 QApplication::processEvents();
349 connect(m_configUi->point1XSpinBox,
350 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this,
351 &cvProtractorTool::on_point1XSpinBox_valueChanged);
352 connect(m_configUi->point1YSpinBox,
353 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this,
354 &cvProtractorTool::on_point1YSpinBox_valueChanged);
355 connect(m_configUi->point1ZSpinBox,
356 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this,
357 &cvProtractorTool::on_point1ZSpinBox_valueChanged);
358 connect(m_configUi->centerXSpinBox,
359 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this,
360 &cvProtractorTool::on_centerXSpinBox_valueChanged);
361 connect(m_configUi->centerYSpinBox,
362 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this,
363 &cvProtractorTool::on_centerYSpinBox_valueChanged);
364 connect(m_configUi->centerZSpinBox,
365 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this,
366 &cvProtractorTool::on_centerZSpinBox_valueChanged);
367 connect(m_configUi->point2XSpinBox,
368 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this,
369 &cvProtractorTool::on_point2XSpinBox_valueChanged);
370 connect(m_configUi->point2YSpinBox,
371 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this,
372 &cvProtractorTool::on_point2YSpinBox_valueChanged);
373 connect(m_configUi->point2ZSpinBox,
374 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this,
375 &cvProtractorTool::on_point2ZSpinBox_valueChanged);
378 connect(m_configUi->pickPoint1ToolButton, &QToolButton::toggled,
this,
379 &cvProtractorTool::on_pickPoint1_toggled);
380 connect(m_configUi->pickCenterToolButton, &QToolButton::toggled,
this,
381 &cvProtractorTool::on_pickCenter_toggled);
382 connect(m_configUi->pickPoint2ToolButton, &QToolButton::toggled,
this,
383 &cvProtractorTool::on_pickPoint2_toggled);
386 connect(m_configUi->widgetVisibilityCheckBox, &QCheckBox::toggled,
this,
387 &cvProtractorTool::on_widgetVisibilityCheckBox_toggled);
388 connect(m_configUi->arcVisibilityCheckBox, &QCheckBox::toggled,
this,
389 &cvProtractorTool::on_arcVisibilityCheckBox_toggled);
402 double defaultCenter[3] = {0.0, 0.0, 0.0};
403 double defaultPos1[3] = {-0.5, 0.0, 0.0};
404 double defaultPos2[3] = {0.5, 0.0, 0.0};
414 double diagLength = diag.
norm();
415 double offset = diagLength * 0.3;
425 defaultCenter[0] = center.
x;
426 defaultCenter[1] = center.
y +
offset;
427 defaultCenter[2] = center.
z +
offset;
429 defaultPos1[0] = center.
x - diag.
x * 0.25;
430 defaultPos1[1] = center.
y +
offset;
431 defaultPos1[2] = center.
z +
offset;
433 defaultPos2[0] = center.
x + diag.
x * 0.25;
434 defaultPos2[1] = center.
y +
offset;
435 defaultPos2[2] = center.
z +
offset;
439 if (m_widget && m_widget->GetEnabled()) {
440 m_rep->SetCenterWorldPosition(defaultCenter);
441 m_rep->SetPoint1WorldPosition(defaultPos1);
442 m_rep->SetPoint2WorldPosition(defaultPos2);
443 m_rep->BuildRepresentation();
446 applyTextPropertiesToLabel();
448 m_widget->Modified();
463 m_configUi->centerXSpinBox->setValue(defaultCenter[0]);
464 m_configUi->centerYSpinBox->setValue(defaultCenter[1]);
465 m_configUi->centerZSpinBox->setValue(defaultCenter[2]);
466 m_configUi->point1XSpinBox->setValue(defaultPos1[0]);
467 m_configUi->point1YSpinBox->setValue(defaultPos1[1]);
468 m_configUi->point1ZSpinBox->setValue(defaultPos1[2]);
469 m_configUi->point2XSpinBox->setValue(defaultPos2[0]);
470 m_configUi->point2YSpinBox->setValue(defaultPos2[1]);
471 m_configUi->point2ZSpinBox->setValue(defaultPos2[2]);
479 if (!vtkWidget)
return;
488 &cvProtractorTool::pickKeyboardPoint1);
493 QKeySequence(tr(
"Ctrl+1")),
true, vtkWidget);
498 &cvProtractorTool::pickKeyboardPoint1);
508 &cvProtractorTool::pickKeyboardCenter);
513 QKeySequence(tr(
"Ctrl+C")),
true, vtkWidget);
518 &cvProtractorTool::pickKeyboardCenter);
528 &cvProtractorTool::pickKeyboardPoint2);
533 QKeySequence(tr(
"Ctrl+2")),
true, vtkWidget);
538 &cvProtractorTool::pickKeyboardPoint2);
554 m_rep->SetVisibility(state ? 1 : 0);
555 m_rep->BuildRepresentation();
559 applyTextPropertiesToLabel();
563 m_widget->Modified();
577 "[cvProtractorTool::getOutput] No entity associated with this "
583 double p1[3], center[3], p2[3];
599 if (!cloud || cloud->
size() == 0) {
601 "[cvProtractorTool::getOutput] Could not find associated point "
602 "cloud or cloud is empty");
622 unsigned nearestIndex1 = 0;
623 unsigned nearestIndexC = 0;
624 unsigned nearestIndex2 = 0;
625 double minDist1 = std::numeric_limits<double>::max();
626 double minDistC = std::numeric_limits<double>::max();
627 double minDist2 = std::numeric_limits<double>::max();
631 const double DISTANCE_THRESHOLD = 0.001;
633 for (
unsigned i = 0; i < cloud->
size(); ++i) {
637 double d1 = (*P - point1).norm();
643 double dC = (*P - pointC).norm();
649 double d2 = (*P - point2).norm();
663 unsigned pointsToAdd = 0;
664 if (minDist1 > DISTANCE_THRESHOLD) pointsToAdd++;
665 if (minDistC > DISTANCE_THRESHOLD) pointsToAdd++;
666 if (minDist2 > DISTANCE_THRESHOLD) pointsToAdd++;
669 if (pointsToAdd > 0) {
670 unsigned currentSize = pointCloud->
size();
671 if (pointCloud->
reserve(currentSize + pointsToAdd)) {
673 if (minDist1 > DISTANCE_THRESHOLD) {
675 nearestIndex1 = pointCloud->
size() - 1;
679 if (minDistC > DISTANCE_THRESHOLD) {
681 nearestIndexC = pointCloud->
size() - 1;
685 if (minDist2 > DISTANCE_THRESHOLD) {
687 nearestIndex2 = pointCloud->
size() - 1;
704 "[cvProtractorTool::getOutput] Failed to add first point (A) "
712 "[cvProtractorTool::getOutput] Failed to add center point (B) "
720 "[cvProtractorTool::getOutput] Failed to add second point (C) "
736 float labelPosX = 0.05f;
737 float labelPosY = 0.90f;
741 if (
auto* labelActor = m_rep->GetAngleLabelActor()) {
742 double* vtkPos = labelActor->GetPosition();
745 int* windowSize =
m_interactor->GetRenderWindow()->GetSize();
746 if (windowSize && windowSize[0] > 0 && windowSize[1] > 0) {
750 float normalizedX =
static_cast<float>(vtkPos[0]) /
751 static_cast<float>(windowSize[0]);
752 float normalizedY =
static_cast<float>(vtkPos[1]) /
753 static_cast<float>(windowSize[1]);
757 labelPosX = normalizedX;
758 labelPosY = 1.0f - normalizedY;
761 QString(
"[cvProtractorTool::getOutput] Retrieved "
763 "position from VTK: display=(%1, %2), "
764 "normalized=(%3, %4)")
777 CVLog::Print(QString(
"[cvProtractorTool] Exported angle measurement: %1° "
778 "at position (%2, %3)")
788 return m_configUi->angleSpinBox->value();
794 if (m_configUi && pos) {
795 pos[0] = m_configUi->point1XSpinBox->value();
796 pos[1] = m_configUi->point1YSpinBox->value();
797 pos[2] = m_configUi->point1ZSpinBox->value();
799 pos[0] = pos[1] = pos[2] = 0.0;
804 if (m_configUi && pos) {
805 pos[0] = m_configUi->point2XSpinBox->value();
806 pos[1] = m_configUi->point2YSpinBox->value();
807 pos[2] = m_configUi->point2ZSpinBox->value();
809 pos[0] = pos[1] = pos[2] = 0.0;
814 if (m_configUi && pos) {
815 pos[0] = m_configUi->centerXSpinBox->value();
816 pos[1] = m_configUi->centerYSpinBox->value();
817 pos[2] = m_configUi->centerZSpinBox->value();
819 pos[0] = pos[1] = pos[2] = 0.0;
824 if (!m_configUi || !pos)
return;
827 if (m_configUi->pickPoint1ToolButton->isChecked()) {
828 m_configUi->pickPoint1ToolButton->setChecked(
false);
835 m_configUi->point1XSpinBox->setValue(pos[0]);
836 m_configUi->point1YSpinBox->setValue(pos[1]);
837 m_configUi->point1ZSpinBox->setValue(pos[2]);
840 if (m_widget && m_widget->GetEnabled()) {
841 m_rep->SetPoint1WorldPosition(pos);
842 m_rep->BuildRepresentation();
845 applyTextPropertiesToLabel();
847 m_widget->Modified();
852 updateAngleDisplay();
857 if (!m_configUi || !pos)
return;
860 if (m_configUi->pickPoint2ToolButton->isChecked()) {
861 m_configUi->pickPoint2ToolButton->setChecked(
false);
868 m_configUi->point2XSpinBox->setValue(pos[0]);
869 m_configUi->point2YSpinBox->setValue(pos[1]);
870 m_configUi->point2ZSpinBox->setValue(pos[2]);
873 if (m_widget && m_widget->GetEnabled()) {
874 m_rep->SetPoint2WorldPosition(pos);
875 m_rep->BuildRepresentation();
878 applyTextPropertiesToLabel();
880 m_widget->Modified();
885 updateAngleDisplay();
890 if (!m_configUi || !pos)
return;
893 if (m_configUi->pickCenterToolButton->isChecked()) {
894 m_configUi->pickCenterToolButton->setChecked(
false);
901 m_configUi->centerXSpinBox->setValue(pos[0]);
902 m_configUi->centerYSpinBox->setValue(pos[1]);
903 m_configUi->centerZSpinBox->setValue(pos[2]);
906 if (m_widget && m_widget->GetEnabled()) {
907 m_rep->SetCenterWorldPosition(pos);
908 m_rep->BuildRepresentation();
911 applyTextPropertiesToLabel();
913 m_widget->Modified();
918 updateAngleDisplay();
924 m_currentColor[0] = r;
925 m_currentColor[1] = g;
926 m_currentColor[2] = b;
930 if (
auto* lineProp = m_rep->GetLineProperty()) {
931 lineProp->SetColor(r, g, b);
933 if (
auto* selectedLineProp = m_rep->GetSelectedLineProperty()) {
934 selectedLineProp->SetColor(r, g, b);
936 m_rep->BuildRepresentation();
939 applyTextPropertiesToLabel();
942 m_widget->Modified();
949 r = m_currentColor[0];
950 g = m_currentColor[1];
951 b = m_currentColor[2];
958 m_widget->SetProcessEvents(0);
966 if (
auto* lineProp = m_rep->GetLineProperty()) {
967 lineProp->SetColor(m_currentColor[0] * 0.1, m_currentColor[1] * 0.1,
968 m_currentColor[2] * 0.1);
969 lineProp->SetOpacity(0.5);
971 if (
auto* selectedLineProp = m_rep->GetSelectedLineProperty()) {
972 selectedLineProp->SetColor(m_currentColor[0] * 0.1,
973 m_currentColor[1] * 0.1,
974 m_currentColor[2] * 0.1);
975 selectedLineProp->SetOpacity(0.5);
979 if (
auto* handleProp = m_rep->GetHandleProperty()) {
980 handleProp->SetOpacity(0.5);
982 if (
auto* selectedHandleProp = m_rep->GetSelectedHandleProperty()) {
983 selectedHandleProp->SetOpacity(0.5);
987 m_rep->BuildRepresentation();
994 if (
auto* labelActor = m_rep->GetAngleLabelActor()) {
995 if (
auto* textProp = labelActor->GetTextProperty()) {
996 textProp->SetOpacity(0.5);
997 textProp->SetColor(0.5, 0.5,
999 textProp->Modified();
1001 labelActor->Modified();
1005 if (
auto* arcActor = m_rep->GetAngleArcActor()) {
1006 if (
auto* arcProp = arcActor->GetProperty()) {
1007 arcProp->SetOpacity(0.5);
1008 arcProp->SetColor(0.5, 0.5,
1010 arcProp->Modified();
1012 arcActor->Modified();
1016 m_widget->Modified();
1028 m_configUi->point1XSpinBox->setEnabled(
false);
1029 m_configUi->point1YSpinBox->setEnabled(
false);
1030 m_configUi->point1ZSpinBox->setEnabled(
false);
1031 m_configUi->centerXSpinBox->setEnabled(
false);
1032 m_configUi->centerYSpinBox->setEnabled(
false);
1033 m_configUi->centerZSpinBox->setEnabled(
false);
1034 m_configUi->point2XSpinBox->setEnabled(
false);
1035 m_configUi->point2YSpinBox->setEnabled(
false);
1036 m_configUi->point2ZSpinBox->setEnabled(
false);
1037 m_configUi->pickPoint1ToolButton->setEnabled(
false);
1038 m_configUi->pickCenterToolButton->setEnabled(
false);
1039 m_configUi->pickPoint2ToolButton->setEnabled(
false);
1040 m_configUi->widgetVisibilityCheckBox->setEnabled(
false);
1041 m_configUi->arcVisibilityCheckBox->setEnabled(
false);
1051 m_widget->SetProcessEvents(1);
1058 if (
auto* lineProp = m_rep->GetLineProperty()) {
1059 lineProp->SetColor(m_currentColor[0], m_currentColor[1],
1061 lineProp->SetOpacity(1.0);
1063 if (
auto* selectedLineProp = m_rep->GetSelectedLineProperty()) {
1064 selectedLineProp->SetColor(m_currentColor[0], m_currentColor[1],
1066 selectedLineProp->SetOpacity(1.0);
1070 if (
auto* handleProp = m_rep->GetHandleProperty()) {
1071 handleProp->SetOpacity(1.0);
1073 if (
auto* selectedHandleProp = m_rep->GetSelectedHandleProperty()) {
1074 selectedHandleProp->SetOpacity(1.0);
1078 m_rep->BuildRepresentation();
1085 if (
auto* labelActor = m_rep->GetAngleLabelActor()) {
1086 if (
auto* textProp = labelActor->GetTextProperty()) {
1090 textProp->Modified();
1092 labelActor->Modified();
1096 if (
auto* arcActor = m_rep->GetAngleArcActor()) {
1097 if (
auto* arcProp = arcActor->GetProperty()) {
1098 arcProp->SetOpacity(1.0);
1099 arcProp->SetColor(1.0, 1.0, 0.0);
1100 arcProp->Modified();
1102 arcActor->Modified();
1106 m_widget->Modified();
1118 m_configUi->point1XSpinBox->setEnabled(
true);
1119 m_configUi->point1YSpinBox->setEnabled(
true);
1120 m_configUi->point1ZSpinBox->setEnabled(
true);
1121 m_configUi->centerXSpinBox->setEnabled(
true);
1122 m_configUi->centerYSpinBox->setEnabled(
true);
1123 m_configUi->centerZSpinBox->setEnabled(
true);
1124 m_configUi->point2XSpinBox->setEnabled(
true);
1125 m_configUi->point2YSpinBox->setEnabled(
true);
1126 m_configUi->point2ZSpinBox->setEnabled(
true);
1127 m_configUi->pickPoint1ToolButton->setEnabled(
true);
1128 m_configUi->pickCenterToolButton->setEnabled(
true);
1129 m_configUi->pickPoint2ToolButton->setEnabled(
true);
1130 m_configUi->widgetVisibilityCheckBox->setEnabled(
true);
1131 m_configUi->arcVisibilityCheckBox->setEnabled(
true);
1139 QString(
"[cvProtractorTool::unlockInteraction] Creating "
1140 "shortcuts for tool=%1, using saved vtkWidget=%2")
1141 .arg((quintptr)
this, 0, 16)
1145 QString(
"[cvProtractorTool::unlockInteraction] After "
1146 "setupShortcuts, m_pickingHelpers.size()=%1")
1150 QString(
"[cvProtractorTool::unlockInteraction] m_vtkWidget "
1151 "is null for tool=%1, cannot create shortcuts")
1152 .arg((quintptr)
this, 0, 16));
1160 "Updating %1 existing shortcuts for tool=%2")
1162 .arg((quintptr)
this, 0, 16));
1184 helper->setEnabled(
true,
1193 m_instanceLabel = label;
1197 m_rep->SetLabelSuffix(m_instanceLabel.toUtf8().constData());
1201 applyFontProperties();
1205 void cvProtractorTool::on_point1XSpinBox_valueChanged(
double arg1) {
1206 if (!m_configUi)
return;
1213 if (m_widget && m_widget->GetEnabled()) {
1214 m_rep->GetPoint1WorldPosition(pos);
1217 m_rep->SetPoint1WorldPosition(newPos);
1218 m_rep->BuildRepresentation();
1219 m_widget->Modified();
1222 updateAngleDisplay();
1226 void cvProtractorTool::on_point1YSpinBox_valueChanged(
double arg1) {
1227 if (!m_configUi)
return;
1234 if (m_widget && m_widget->GetEnabled()) {
1235 m_rep->GetPoint1WorldPosition(pos);
1238 m_rep->SetPoint1WorldPosition(newPos);
1239 m_rep->BuildRepresentation();
1240 m_widget->Modified();
1243 updateAngleDisplay();
1247 void cvProtractorTool::on_point1ZSpinBox_valueChanged(
double arg1) {
1248 if (!m_configUi)
return;
1255 if (m_widget && m_widget->GetEnabled()) {
1256 m_rep->GetPoint1WorldPosition(pos);
1259 m_rep->SetPoint1WorldPosition(newPos);
1260 m_rep->BuildRepresentation();
1261 m_widget->Modified();
1264 updateAngleDisplay();
1268 void cvProtractorTool::on_centerXSpinBox_valueChanged(
double arg1) {
1269 if (!m_configUi)
return;
1276 if (m_widget && m_widget->GetEnabled()) {
1277 m_rep->GetCenterWorldPosition(pos);
1280 m_rep->SetCenterWorldPosition(newPos);
1281 m_rep->BuildRepresentation();
1282 m_widget->Modified();
1285 updateAngleDisplay();
1289 void cvProtractorTool::on_centerYSpinBox_valueChanged(
double arg1) {
1290 if (!m_configUi)
return;
1297 if (m_widget && m_widget->GetEnabled()) {
1298 m_rep->GetCenterWorldPosition(pos);
1301 m_rep->SetCenterWorldPosition(newPos);
1302 m_rep->BuildRepresentation();
1303 m_widget->Modified();
1306 updateAngleDisplay();
1310 void cvProtractorTool::on_centerZSpinBox_valueChanged(
double arg1) {
1311 if (!m_configUi)
return;
1318 if (m_widget && m_widget->GetEnabled()) {
1319 m_rep->GetCenterWorldPosition(pos);
1322 m_rep->SetCenterWorldPosition(newPos);
1323 m_rep->BuildRepresentation();
1324 m_widget->Modified();
1327 updateAngleDisplay();
1331 void cvProtractorTool::on_point2XSpinBox_valueChanged(
double arg1) {
1332 if (!m_configUi)
return;
1339 if (m_widget && m_widget->GetEnabled()) {
1340 m_rep->GetPoint2WorldPosition(pos);
1343 m_rep->SetPoint2WorldPosition(newPos);
1344 m_rep->BuildRepresentation();
1345 m_widget->Modified();
1348 updateAngleDisplay();
1352 void cvProtractorTool::on_point2YSpinBox_valueChanged(
double arg1) {
1353 if (!m_configUi)
return;
1360 if (m_widget && m_widget->GetEnabled()) {
1361 m_rep->GetPoint2WorldPosition(pos);
1364 m_rep->SetPoint2WorldPosition(newPos);
1365 m_rep->BuildRepresentation();
1366 m_widget->Modified();
1369 updateAngleDisplay();
1373 void cvProtractorTool::on_point2ZSpinBox_valueChanged(
double arg1) {
1374 if (!m_configUi)
return;
1381 if (m_widget && m_widget->GetEnabled()) {
1382 m_rep->GetPoint2WorldPosition(pos);
1385 m_rep->SetPoint2WorldPosition(newPos);
1386 m_rep->BuildRepresentation();
1387 m_widget->Modified();
1390 updateAngleDisplay();
1394 void cvProtractorTool::onAngleChanged(
double angle) {
1395 if (!m_configUi)
return;
1397 m_configUi->angleSpinBox->setValue(angle);
1401 void cvProtractorTool::onWorldPoint1Changed(
double* pos) {
1402 if (!m_configUi || !pos)
return;
1406 m_configUi->point1XSpinBox->setValue(pos[0]);
1407 m_configUi->point1YSpinBox->setValue(pos[1]);
1408 m_configUi->point1ZSpinBox->setValue(pos[2]);
1412 void cvProtractorTool::onWorldPoint2Changed(
double* pos) {
1413 if (!m_configUi || !pos)
return;
1417 m_configUi->point2XSpinBox->setValue(pos[0]);
1418 m_configUi->point2YSpinBox->setValue(pos[1]);
1419 m_configUi->point2ZSpinBox->setValue(pos[2]);
1423 void cvProtractorTool::onWorldCenterChanged(
double* pos) {
1424 if (!m_configUi || !pos)
return;
1428 m_configUi->centerXSpinBox->setValue(pos[0]);
1429 m_configUi->centerYSpinBox->setValue(pos[1]);
1430 m_configUi->centerZSpinBox->setValue(pos[2]);
1434 void cvProtractorTool::hookWidget(
1439 vtkNew<vtkCallbackCommand>
callback;
1440 callback->SetCallback([](vtkObject* caller,
unsigned long ,
1441 void* clientData,
void* ) {
1443 self->updateAngleDisplay();
1447 widget->AddObserver(vtkCommand::InteractionEvent,
callback);
1450 void cvProtractorTool::updateAngleDisplay() {
1453 "[cvProtractorTool] updateAngleDisplay: m_configUi is null!");
1458 double angleDegrees = 0.0;
1461 angleDegrees = m_rep->GetAngle();
1464 double p1[3], center[3], p2[3];
1465 m_rep->GetHandlePosition(0, p1);
1466 m_rep->GetHandlePosition(1, center);
1467 m_rep->GetHandlePosition(2, p2);
1479 m_configUi->point1XSpinBox->setValue(p1[0]);
1480 m_configUi->point1YSpinBox->setValue(p1[1]);
1481 m_configUi->point1ZSpinBox->setValue(p1[2]);
1482 m_configUi->centerXSpinBox->setValue(center[0]);
1483 m_configUi->centerYSpinBox->setValue(center[1]);
1484 m_configUi->centerZSpinBox->setValue(center[2]);
1485 m_configUi->point2XSpinBox->setValue(p2[0]);
1486 m_configUi->point2YSpinBox->setValue(p2[1]);
1487 m_configUi->point2ZSpinBox->setValue(p2[2]);
1491 m_configUi->angleSpinBox->setValue(angleDegrees);
1495 void cvProtractorTool::on_pickPoint1_toggled(
bool checked) {
1498 if (m_configUi->pickCenterToolButton->isChecked()) {
1499 m_configUi->pickCenterToolButton->setChecked(
false);
1501 if (m_configUi->pickPoint2ToolButton->isChecked()) {
1502 m_configUi->pickPoint2ToolButton->setChecked(
false);
1512 void cvProtractorTool::on_pickCenter_toggled(
bool checked) {
1515 if (m_configUi->pickPoint1ToolButton->isChecked()) {
1516 m_configUi->pickPoint1ToolButton->setChecked(
false);
1518 if (m_configUi->pickPoint2ToolButton->isChecked()) {
1519 m_configUi->pickPoint2ToolButton->setChecked(
false);
1529 void cvProtractorTool::on_pickPoint2_toggled(
bool checked) {
1532 if (m_configUi->pickPoint1ToolButton->isChecked()) {
1533 m_configUi->pickPoint1ToolButton->setChecked(
false);
1535 if (m_configUi->pickCenterToolButton->isChecked()) {
1536 m_configUi->pickCenterToolButton->setChecked(
false);
1546 void cvProtractorTool::on_widgetVisibilityCheckBox_toggled(
bool checked) {
1547 if (!m_configUi)
return;
1561 m_rep->SetVisibility(checked ? 1 : 0);
1562 m_rep->BuildRepresentation();
1566 applyTextPropertiesToLabel();
1570 m_widget->Modified();
1583 void cvProtractorTool::on_arcVisibilityCheckBox_toggled(
bool checked) {
1584 if (!m_configUi)
return;
1588 m_rep->SetShowAngleArc(checked ? 1 : 0);
1589 m_rep->BuildRepresentation();
1592 applyTextPropertiesToLabel();
1595 if (
auto* arcActor = m_rep->GetAngleArcActor()) {
1596 arcActor->SetVisibility(checked);
1600 m_widget->Modified();
1608 void cvProtractorTool::pickKeyboardPoint1(
double x,
double y,
double z) {
1609 double pos[3] = {
x,
y,
z};
1613 void cvProtractorTool::pickKeyboardCenter(
double x,
double y,
double z) {
1614 double pos[3] = {
x,
y,
z};
1618 void cvProtractorTool::pickKeyboardPoint2(
double x,
double y,
double z) {
1619 double pos[3] = {
x,
y,
z};
1623 void cvProtractorTool::applyTextPropertiesToLabel() {
1628 if (
auto* labelActor = m_rep->GetAngleLabelActor()) {
1629 if (
auto* textProp = labelActor->GetTextProperty()) {
1631 textProp->SetFontFamilyAsString(
m_fontFamily.toUtf8().constData());
1645 textProp->SetJustificationToLeft();
1647 textProp->SetJustificationToCentered();
1649 textProp->SetJustificationToRight();
1654 textProp->SetVerticalJustificationToTop();
1656 textProp->SetVerticalJustificationToCentered();
1658 textProp->SetVerticalJustificationToBottom();
1662 textProp->Modified();
1666 labelActor->Modified();
1670 void cvProtractorTool::applyFontProperties() {
1677 m_rep->BuildRepresentation();
1680 applyTextPropertiesToLabel();
1684 m_widget->Modified();
float PointCoordinateType
Type of the coordinates of a (N-D) point.
std::function< void(std::shared_ptr< core::Tensor >)> callback
static bool PrintDebug(const char *format,...)
Same as Print, but works only in Debug mode.
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
static bool Print(const char *format,...)
Prints out a formatted message in console.
static bool PrintVerbose(const char *format,...)
Prints out a verbose formatted message in console.
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Type norm() const
Returns vector norm.
2D label (typically attached to points)
bool addPickedPoint(ccGenericPointCloud *cloud, unsigned pointIndex, bool entityCenter=false)
Adds a point to this label.
void setCollapsed(bool state)
Whether to collapse label or not.
void setDisplayedIn2D(bool state)
Whether to display the label in 2D.
void setPosition(float x, float y)
Sets relative position.
void displayPointLegend(bool state)
Whether to display the point(s) legend (title only)
virtual void setVisible(bool state)
Sets entity visibility.
virtual ccGenericPointCloud * getAssociatedCloud() const =0
Returns the vertices cloud.
A 3D cloud interface with associated features (color, normals, octree, etc.)
static ccPointCloud * ToPointCloud(ccHObject *obj, bool *isLockedVertices=nullptr)
Converts current object to 'equivalent' ccPointCloud.
Hierarchical CLOUDVIEWER Object.
virtual ccBBox getBB_recursive(bool withGLFeatures=false, bool onlyEnabledChildren=true)
Returns the bounding-box of this entity and it's children.
virtual void setEnabled(bool state)
Sets the "enabled" property.
bool isKindOf(CV_CLASS_ENUM type) const
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
bool reserve(unsigned numberOfPoints) override
Reserves memory for all the active features.
Vector3Tpl< T > getDiagVec() const
Returns diagonal vector.
Vector3Tpl< T > getCenter() const
Returns center.
bool isValid() const
Returns whether bounding box is valid or not.
virtual unsigned size() const =0
Returns the number of points.
virtual const CCVector3 * getPoint(unsigned index) const =0
Returns the ith point.
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.
unsigned size() const override
Extended PolyLineRepresentation adding angle display functionality.
cvPointPickingHelper is a helper class for supporting keyboard shortcut-based point picking in measur...
void setContextWidget(QWidget *widget)
Set the context widget for the shortcut.
void setInteractor(vtkRenderWindowInteractor *interactor)
Set the VTK interactor for picking.
void setRenderer(vtkRenderer *renderer)
Set the VTK renderer for picking.
void pick(double x, double y, double z)
Emitted when a point is picked.
void vtkInitOnce(T **obj)
Tensor Minimum(const Tensor &input, const Tensor &other)
Computes the element-wise minimum of input and other. The tensors must have same data type and device...