11 #include <vtkContourRepresentation.h>
12 #include <vtkContourWidget.h>
13 #include <vtkOrientedGlyphContourRepresentation.h>
14 #include <vtkPolyData.h>
15 #include <vtkProperty.h>
16 #include <vtkRenderWindow.h>
17 #include <vtkRenderWindowInteractor.h>
18 #include <vtkRenderer.h>
19 #include <vtkTextActor.h>
20 #include <vtkTextProperty.h>
29 #include <QApplication>
31 #include <QLayoutItem>
32 #include <QSizePolicy>
40 int cvContourTool::s_contourIdCounter = 0;
45 m_toolId(++s_contourIdCounter),
47 setWindowTitle(tr(
"Contour Measurement Tool"));
55 for (
auto& pair : m_contours) {
58 if (
auto* rep = vtkContourRepresentation::SafeDownCast(
59 pair.second->GetRepresentation())) {
60 rep->SetVisibility(0);
64 cvConstrainedContourRepresentation::SafeDownCast(
66 if (
auto* labelActor = customRep->GetLabelActor()) {
67 labelActor->SetVisibility(0);
72 pair.second->SetInteractor(
nullptr);
91 void cvContourTool::createNewContour() {
103 newContour->SetRepresentation(rep);
106 rep->SetShowSelectedNodes(
true);
109 if (
auto* linesProp = rep->GetLinesProperty()) {
110 linesProp->SetColor(m_currentColor[0], m_currentColor[1],
113 if (
auto* nodesProp = rep->GetProperty()) {
114 nodesProp->SetColor(m_currentColor[0], m_currentColor[1],
117 if (
auto* activeNodesProp = rep->GetActiveProperty()) {
118 activeNodesProp->SetColor(m_currentColor[0], m_currentColor[1],
131 m_currentContourId++;
132 m_contours[m_currentContourId] = newContour;
135 applyFontProperties();
146 CVLog::Error(
"[cvContourTool::createUi] m_ui is null!");
156 if (m_configUi &&
m_ui->configLayout) {
159 while ((item =
m_ui->configLayout->takeAt(0)) !=
nullptr) {
160 if (item->widget()) {
161 item->widget()->setParent(
nullptr);
162 item->widget()->deleteLater();
167 m_configUi =
nullptr;
171 m_configUi =
new Ui::ContourToolDlg;
172 QWidget* configWidget =
new QWidget(
this);
176 m_configUi->setupUi(configWidget);
179 if (configWidget->layout()) {
180 configWidget->layout()->setSizeConstraint(QLayout::SetMinimumSize);
182 m_ui->configLayout->addWidget(configWidget);
183 m_ui->groupBox->setTitle(tr(
"Contour Parameters"));
189 this->setMinimumSize(0, 0);
190 this->setMaximumSize(16777215, 16777215);
195 configWidget->adjustSize();
198 this->updateGeometry();
200 QApplication::processEvents();
203 connect(m_configUi->widgetVisibilityCheckBox, &QCheckBox::toggled,
this,
204 &cvContourTool::on_widgetVisibilityCheckBox_toggled);
205 connect(m_configUi->showNodesCheckBox, &QCheckBox::toggled,
this,
206 &cvContourTool::on_showNodesCheckBox_toggled);
207 connect(m_configUi->closedLoopCheckBox, &QCheckBox::toggled,
this,
208 &cvContourTool::on_closedLoopCheckBox_toggled);
209 connect(m_configUi->lineWidthSpinBox,
210 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this,
211 &cvContourTool::on_lineWidthSpinBox_valueChanged);
218 if (m_contours.find(m_currentContourId) != m_contours.end()) {
219 auto widget = m_contours[m_currentContourId];
221 widget->Initialize(
nullptr);
229 for (
auto& pair : m_contours) {
243 m_currentColor[0] = r;
244 m_currentColor[1] = g;
245 m_currentColor[2] = b;
248 for (
auto& pair : m_contours) {
250 vtkContourRepresentation* rep =
251 vtkContourRepresentation::SafeDownCast(
252 pair.second->GetRepresentation());
254 vtkOrientedGlyphContourRepresentation* orientedRep =
255 vtkOrientedGlyphContourRepresentation::SafeDownCast(
258 if (
auto* prop = orientedRep->GetLinesProperty()) {
259 prop->SetColor(r, g, b);
261 if (
auto* activeNodeProp =
262 orientedRep->GetActiveProperty()) {
263 activeNodeProp->SetColor(r, g, b);
265 rep->BuildRepresentation();
274 r = m_currentColor[0];
275 g = m_currentColor[1];
276 b = m_currentColor[2];
282 "m_contours.size()=%2")
283 .arg((quintptr)
this, 0, 16)
284 .arg(m_contours.size()));
287 for (
auto& pair : m_contours) {
289 pair.second->SetProcessEvents(0);
295 for (
auto& pair : m_contours) {
297 vtkContourRepresentation* rep =
298 vtkContourRepresentation::SafeDownCast(
299 pair.second->GetRepresentation());
301 vtkOrientedGlyphContourRepresentation* orientedRep =
302 vtkOrientedGlyphContourRepresentation::SafeDownCast(
307 if (
auto* prop = orientedRep->GetLinesProperty()) {
308 prop->SetColor(m_currentColor[0] * 0.1,
309 m_currentColor[1] * 0.1,
310 m_currentColor[2] * 0.1);
311 prop->SetOpacity(0.5);
313 if (
auto* activeNodeProp =
314 orientedRep->GetActiveProperty()) {
315 activeNodeProp->SetColor(m_currentColor[0] * 0.1,
316 m_currentColor[1] * 0.1,
317 m_currentColor[2] * 0.1);
318 activeNodeProp->SetOpacity(0.5);
320 if (
auto* nodeProp = orientedRep->GetProperty()) {
321 nodeProp->SetOpacity(0.5);
326 cvConstrainedContourRepresentation::SafeDownCast(
331 labelActor->GetTextProperty()) {
332 textProp->SetOpacity(0.5);
340 rep->BuildRepresentation();
348 m_configUi->widgetVisibilityCheckBox->setEnabled(
false);
349 m_configUi->showNodesCheckBox->setEnabled(
false);
350 m_configUi->closedLoopCheckBox->setEnabled(
false);
351 m_configUi->lineWidthSpinBox->setEnabled(
false);
367 "m_contours.size()=%2")
368 .arg((quintptr)
this, 0, 16)
369 .arg(m_contours.size()));
372 for (
auto& pair : m_contours) {
374 pair.second->SetProcessEvents(1);
379 for (
auto& pair : m_contours) {
381 vtkContourRepresentation* rep =
382 vtkContourRepresentation::SafeDownCast(
383 pair.second->GetRepresentation());
385 vtkOrientedGlyphContourRepresentation* orientedRep =
386 vtkOrientedGlyphContourRepresentation::SafeDownCast(
390 if (
auto* prop = orientedRep->GetLinesProperty()) {
391 prop->SetColor(m_currentColor[0], m_currentColor[1],
393 prop->SetOpacity(1.0);
395 if (
auto* activeNodeProp =
396 orientedRep->GetActiveProperty()) {
397 activeNodeProp->SetColor(m_currentColor[0],
400 activeNodeProp->SetOpacity(1.0);
402 if (
auto* nodeProp = orientedRep->GetProperty()) {
403 nodeProp->SetOpacity(1.0);
408 cvConstrainedContourRepresentation::SafeDownCast(
413 labelActor->GetTextProperty()) {
422 rep->BuildRepresentation();
433 QString(
"[cvContourTool::unlockInteraction] Creating "
434 "shortcuts for tool=%1, using saved vtkWidget=%2")
435 .arg((quintptr)
this, 0, 16)
439 QString(
"[cvContourTool::unlockInteraction] After "
440 "setupShortcuts, m_pickingHelpers.size()=%1")
444 QString(
"[cvContourTool::unlockInteraction] m_vtkWidget is "
445 "null for tool=%1, cannot create shortcuts")
446 .arg((quintptr)
this, 0, 16));
451 "%1 existing shortcuts for tool=%2")
453 .arg((quintptr)
this, 0, 16));
456 helper->setEnabled(
true,
464 m_configUi->widgetVisibilityCheckBox->setEnabled(
true);
465 m_configUi->showNodesCheckBox->setEnabled(
true);
466 m_configUi->closedLoopCheckBox->setEnabled(
true);
467 m_configUi->lineWidthSpinBox->setEnabled(
true);
480 m_instanceLabel = label;
483 QString title = tr(
"Contour Measurement Tool");
484 if (!m_instanceLabel.isEmpty()) {
485 title += QString(
" %1").arg(m_instanceLabel);
487 setWindowTitle(title);
490 for (
auto& pair : m_contours) {
492 vtkContourRepresentation* rep =
493 vtkContourRepresentation::SafeDownCast(
494 pair.second->GetRepresentation());
497 cvConstrainedContourRepresentation::SafeDownCast(rep);
500 m_instanceLabel.toUtf8().constData());
512 auto it = m_contours.find(m_currentContourId);
513 if (it == m_contours.end() || !it->second) {
518 vtkContourWidget* widget = it->second;
521 if (!widget->GetEnabled()) {
522 CVLog::Warning(
"[cvContourTool] Current contour widget is not enabled");
527 vtkContourRepresentation* rep =
528 vtkContourRepresentation::SafeDownCast(widget->GetRepresentation());
530 CVLog::Warning(
"[cvContourTool] Failed to get contour representation");
535 rep->BuildRepresentation();
538 vtkPolyData* polyData = rep->GetContourRepresentationAsPolyData();
541 "[cvContourTool] Failed to get polyData from contour "
547 if (polyData->GetNumberOfPoints() == 0) {
553 bool isClosed = rep->GetClosedLoop();
554 double lineWidth = 2.0;
557 vtkOrientedGlyphContourRepresentation* orientedRep =
558 vtkOrientedGlyphContourRepresentation::SafeDownCast(rep);
560 vtkProperty* prop = orientedRep->GetLinesProperty();
562 lineWidth = prop->GetLineWidth();
569 polyDataCopy->DeepCopy(polyData);
579 if (vertices && vertices->
size() > 0) {
586 for (
unsigned i = 1; i < vertices->
size(); ++i) {
603 polyline->
setName(QString(
"Contour_%1_%2")
604 .arg(m_currentContourId)
605 .arg(m_exportCounter));
613 CVLog::Print(QString(
"[cvContourTool] Exported contour %1 with %2 "
614 "points (closed: %3, width: %4)")
616 .arg(polyData->GetNumberOfPoints())
617 .arg(isClosed ?
"true" :
"false")
625 CVLog::Error(
"[cvContourTool] Failed to convert polyData to polyline");
630 void cvContourTool::onDataChanged(vtkPolyData* pd) {
636 void cvContourTool::on_widgetVisibilityCheckBox_toggled(
bool checked) {
637 if (!m_configUi)
return;
640 for (
auto& pair : m_contours) {
653 void cvContourTool::on_showNodesCheckBox_toggled(
bool checked) {
654 if (!m_configUi)
return;
657 for (
auto& pair : m_contours) {
659 vtkContourRepresentation* rep =
660 vtkContourRepresentation::SafeDownCast(
661 pair.second->GetRepresentation());
663 vtkOrientedGlyphContourRepresentation* orientedRep =
664 vtkOrientedGlyphContourRepresentation::SafeDownCast(
667 orientedRep->SetShowSelectedNodes(checked);
676 void cvContourTool::on_closedLoopCheckBox_toggled(
bool checked) {
677 if (!m_configUi)
return;
680 for (
auto& pair : m_contours) {
682 vtkContourRepresentation* rep =
683 vtkContourRepresentation::SafeDownCast(
684 pair.second->GetRepresentation());
686 rep->SetClosedLoop(checked);
687 rep->BuildRepresentation();
695 void cvContourTool::on_lineWidthSpinBox_valueChanged(
double value) {
696 if (!m_configUi)
return;
699 for (
auto& pair : m_contours) {
701 vtkContourRepresentation* rep =
702 vtkContourRepresentation::SafeDownCast(
703 pair.second->GetRepresentation());
707 vtkOrientedGlyphContourRepresentation* orientedRep =
708 vtkOrientedGlyphContourRepresentation::SafeDownCast(
713 vtkProperty* linesProp = orientedRep->GetLinesProperty();
715 linesProp->SetLineWidth(value);
720 vtkProperty* prop = orientedRep->GetProperty();
722 prop->SetLineWidth(value);
724 vtkProperty* activeProp = orientedRep->GetActiveProperty();
726 activeProp->SetLineWidth(value);
729 rep->BuildRepresentation();
737 void cvContourTool::applyFontProperties() {
739 for (
auto& pair : m_contours) {
741 vtkContourRepresentation* rep =
742 vtkContourRepresentation::SafeDownCast(
743 pair.second->GetRepresentation());
747 cvConstrainedContourRepresentation::SafeDownCast(rep);
750 if (
auto* textProp = labelActor->GetTextProperty()) {
751 textProp->SetFontFamilyAsString(
763 textProp->SetJustificationToLeft();
765 textProp->SetJustificationToCentered();
767 textProp->SetJustificationToRight();
771 textProp->SetVerticalJustificationToTop();
773 textProp->SetVerticalJustificationToCentered();
775 textProp->SetVerticalJustificationToBottom();
778 textProp->Modified();
781 labelActor->Modified();
785 rep->BuildRepresentation();
float PointCoordinateType
Type of the coordinates of a (N-D) point.
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 Error(const char *format,...)
Display an error dialog with formatted message.
virtual void setVisible(bool state)
Sets entity visibility.
Hierarchical CLOUDVIEWER Object.
virtual QString getName() const
Returns object name.
virtual void setName(const QString &name)
Sets object name.
void set2DMode(bool state)
Defines if the polyline is considered as 2D or 3D.
void setColor(const ecvColor::Rgb &col)
Sets the polyline color.
void setWidth(PointCoordinateType width)
Sets the width of the line.
virtual unsigned size() const =0
Returns the number of points.
A generic 3D point cloud with index-based and presistent access to points.
virtual const CCVector3 * getPoint(unsigned index) const =0
Returns the ith point.
void setClosed(bool state)
Sets whether the polyline is closed or not.
virtual GenericIndexedCloudPersist * getAssociatedCloud()
Returns the associated (source) cloud.
Extended contour representation with instance label support.
vtkTextActor * GetLabelActor()
Get the label actor (for property access)
void SetLabelSuffix(const char *suffix)
Set the label suffix to identify this contour instance.
void BuildRepresentation() override
Build the representation (override to update label position)
cvPointPickingHelper is a helper class for supporting keyboard shortcut-based point picking in measur...
static ccPolyline * ConvertToPolyline(vtkPolyData *polydata, bool silent=false)
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...
bool LessThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).
constexpr Rgb green(0, MAX, 0)