ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
PCLDisplayTools.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "PCLDisplayTools.h"
9 
10 // PCLModules
11 #include <Utils/PCLConv.h>
12 #include <Utils/cc2sm.h>
13 #include <Utils/sm2cc.h>
14 
15 // CV_CORE_LIB
16 #include <CVGeom.h>
17 #include <CVTools.h>
18 #include <ecvGLMatrix.h>
19 
20 // CV_DB_LIB
21 #include <ecvBBox.h>
22 #include <ecvCameraSensor.h>
23 #include <ecvGenericMesh.h>
24 #include <ecvHObjectCaster.h>
25 #include <ecvImage.h>
26 #include <ecvMaterialSet.h>
27 #include <ecvMesh.h>
28 #include <ecvPointCloud.h>
29 #include <ecvPolyline.h>
30 #include <ecvScalarField.h>
31 #include <ecvSensor.h>
32 
33 // LOCAL
35 
36 // PCL
37 #include <pcl/io/pcd_io.h>
38 #include <pcl/point_cloud.h>
39 #include <pcl/point_types.h>
40 
41 // VTK
42 #include <vtkFieldData.h>
43 #include <vtkGenericOpenGLRenderWindow.h>
44 #include <vtkPolyData.h>
45 #include <vtkStringArray.h>
46 
47 // SYSTEM
48 #include <assert.h>
49 
50 // Qt
51 #include <QImage>
52 
53 void PCLDisplayTools::registerVisualizer(QMainWindow* win, bool stereoMode) {
54  this->m_vtkWidget = new QVTKWidgetCustom(win, this, stereoMode);
57 
58  if (!m_visualizer3D) {
59  auto renderer = vtkSmartPointer<vtkRenderer>::New();
60  auto renderWindow =
62  // CRITICAL: Disable multisampling for hardware selection to work
63  // ParaView does this in vtkPVRenderView.cxx line 453
64  // MultiSamples interferes with vtkHardwareSelector's pixel reading
65  // renderWindow->SetMultiSamples(0);
66  renderWindow->AddRenderer(renderer);
67  auto interactorStyle =
70  renderer, renderWindow, interactorStyle, "3Dviewer", false));
71  // m_visualizer3D.reset(new PclUtils::PCLVis(interactorStyle,
72  // "3Dviewer", false)); // deprecated!
73  }
74 
75  getQVtkWidget()->SetRenderWindow(m_visualizer3D->getRenderWindow());
76  m_visualizer3D->setupInteractor(getQVtkWidget()->GetInteractor(),
77  getQVtkWidget()->GetRenderWindow());
78  getQVtkWidget()->initVtk(m_visualizer3D->getRenderWindowInteractor(),
79  false);
80  m_visualizer3D->initialize();
81 
83  if (!m_visualizer2D) {
84  m_visualizer2D.reset(new PclUtils::ImageVis("2Dviewer", false));
85  }
86 
87  m_visualizer2D->setRender(getQVtkWidget()->getVtkRender());
88  m_visualizer2D->setupInteractor(getQVtkWidget()->GetInteractor(),
89  getQVtkWidget()->GetRenderWindow());
90  } else {
91  m_visualizer2D = nullptr;
92  }
93 }
94 
96  // Cleanup is now handled in PCLVis destructor
97  if (this->m_vtkWidget) {
98  delete this->m_vtkWidget;
99  this->m_vtkWidget = nullptr;
100  }
101 }
102 
103 void PCLDisplayTools::drawPointCloud(const CC_DRAW_CONTEXT& context,
104  ccPointCloud* ecvCloud) {
105  std::string viewID = CVTools::FromQString(context.viewID);
106  int viewport = context.defaultViewPort;
107  bool firstShow = !m_visualizer3D->contains(viewID);
108  bool hasRedrawn = false;
109 
110  // Create local context to pass entity's redraw state
111  // This ensures updateShadingMode() in PCLVis updates normals/colors when
112  // needed
113  CC_DRAW_CONTEXT localContext = context;
114  if (ecvCloud->isRedraw()) {
115  localContext.forceRedraw = true;
116  }
117 
118  if (ecvCloud->isRedraw() || firstShow) {
119  if (firstShow || checkEntityNeedUpdate(viewID, ecvCloud)) {
120  PCLCloud::Ptr pclCloud =
121  cc2smReader(ecvCloud, true)
122  .getAsSM(!context.drawParam.showSF);
123  if (!pclCloud) {
124  return;
125  }
126  m_visualizer3D->draw(localContext, pclCloud);
127  m_visualizer3D->updateNormals(localContext, pclCloud);
128  hasRedrawn = true;
129  } else {
130  m_visualizer3D->resetScalarColor(viewID, true, viewport);
131  if (!updateEntityColor(localContext, ecvCloud)) {
132  PCLCloud::Ptr pclCloud =
133  cc2smReader(ecvCloud, true)
134  .getAsSM(!localContext.drawParam.showSF);
135  if (!pclCloud) {
136  return;
137  }
138  m_visualizer3D->draw(localContext, pclCloud);
139  m_visualizer3D->updateNormals(localContext, pclCloud);
140  hasRedrawn = true;
141  } else {
142  if (localContext.drawParam.showNorms) {
143  PCLCloud::Ptr pointNormals =
144  cc2smReader(ecvCloud).getPointNormals();
145  m_visualizer3D->updateNormals(localContext, pointNormals);
146  } else {
147  m_visualizer3D->updateNormals(localContext, nullptr);
148  }
149  }
150  }
151  }
152 
153  if (m_visualizer3D->contains(viewID)) {
154  m_visualizer3D->setPointSize(context.defaultPointSize, viewID,
155  viewport);
156 
157  // Set the source object for direct extraction during selection
158  // operations This allows bypassing VTK→ccPointCloud conversion when
159  // extracting selections
160  if (firstShow || hasRedrawn) {
161  m_visualizer3D->setCurrentSourceObject(ecvCloud, viewID);
162  }
163 
164  // Sync ALL scalar fields to VTK on first show or force redraw
165  // This ensures all SFs are available for selection/extraction (Find
166  // Data)
167  if (firstShow || localContext.forceRedraw) {
168  unsigned numSFs = ecvCloud->getNumberOfScalarFields();
169  for (unsigned i = 0; i < numSFs; ++i) {
170  m_visualizer3D->addScalarFieldToVTK(
171  viewID, ecvCloud, static_cast<int>(i), viewport);
172  }
173 
174  // For point clouds without scalar fields, we still need to set
175  // DatasetName This ensures they appear in the Data Producer combo
176  // (ParaView style)
177  if (numSFs == 0) {
178  vtkActor* actor = m_visualizer3D->getActorById(viewID);
179  if (actor && actor->GetMapper()) {
180  vtkPolyData* polyData = vtkPolyData::SafeDownCast(
181  actor->GetMapper()->GetInput());
182  if (polyData) {
183  vtkFieldData* fieldData = polyData->GetFieldData();
184  if (fieldData) {
185  vtkStringArray* datasetNameArray =
186  vtkStringArray::SafeDownCast(
187  fieldData->GetAbstractArray(
188  "DatasetName"));
189  if (!datasetNameArray) {
190  // DatasetName not yet added, create it
191  QString cloudName = ecvCloud->getName();
192  if (!cloudName.isEmpty()) {
194  newDatasetNameArray =
196  vtkStringArray>::
197  New();
198  newDatasetNameArray->SetName("DatasetName");
199  newDatasetNameArray->SetNumberOfTuples(1);
200  newDatasetNameArray->SetValue(
201  0, cloudName.toStdString());
202  fieldData->AddArray(newDatasetNameArray);
203 
205  QString("[PCLDisplayTools] Added "
206  "DatasetName for point "
207  "cloud "
208  "without SFs: '%1'")
209  .arg(cloudName));
210  }
211  }
212  }
213  }
214  }
215  }
216  }
217  // Also ensure current SF is updated for tooltip display
218  else if (context.drawParam.showSF && ecvCloud->sfShown()) {
219  int sfIdx = ecvCloud->getCurrentDisplayedScalarFieldIndex();
220  if (sfIdx >= 0) {
221  // Add/update scalar field to VTK for tooltip display
222  // Extract values directly from ccPointCloud (not from PCL
223  // cloud) Note: addScalarFieldToVTK has internal check to avoid
224  // unnecessary updates
225  m_visualizer3D->addScalarFieldToVTK(viewID, ecvCloud, sfIdx,
226  viewport);
227  }
228  }
229 
230  if ((!context.drawParam.showColors && !context.drawParam.showSF) ||
231  ecvCloud->isColorOverridden()) {
232  ecvColor::Rgbf pointUniqueColor =
233  ecvTools::TransFormRGB(context.pointsCurrentCol);
234  m_visualizer3D->setPointCloudUniqueColor(
235  pointUniqueColor.r, pointUniqueColor.g, pointUniqueColor.b,
236  viewID, viewport);
237  }
238  }
239 }
240 
242  const ccGenericMesh* mesh) {
243  std::string viewID = CVTools::FromQString(context.viewID);
244  bool firstShow = !m_visualizer3D->contains(viewID);
245  if (firstShow) {
246  drawMesh(const_cast<CC_DRAW_CONTEXT&>(context),
247  const_cast<ccGenericMesh*>(mesh));
248  } else {
249  // materials & textures
250  bool applyMaterials = (mesh->hasMaterials() && mesh->materialsShown());
251  bool showTextures = (mesh->hasTextures() && mesh->materialsShown());
252  if (applyMaterials || showTextures) {
253  // materials
254  const ccMaterialSet* materials = mesh->getMaterialSet();
255  assert(materials);
256  if (!m_visualizer3D->updateTexture(context, materials)) {
257  CVLog::Warning(QString("Update mesh texture failed!"));
258  }
259  } else {
261  QString("Mesh texture has not been shown, please toggle it "
262  "to be shown!"));
263  }
264  }
265 }
266 
267 void PCLDisplayTools::drawMesh(CC_DRAW_CONTEXT& context, ccGenericMesh* mesh) {
268  std::string viewID = CVTools::FromQString(context.viewID);
269  int viewport = context.defaultViewPort;
270  context.visFiltering = true;
271  bool firstShow = !m_visualizer3D->contains(viewID);
272 
273  // Set forceRedraw based on entity's redraw state
274  // This ensures updateShadingMode() in PCLVis updates normals/colors when
275  // needed
276  if (mesh->isRedraw()) {
277  context.forceRedraw = true;
278  }
279 
280  if (mesh->isRedraw() || firstShow) {
282  "[PCLDisplayTools::drawMesh] Entering render block "
283  "(isRedraw=%d || firstShow=%d)",
284  mesh->isRedraw(), firstShow);
285 
287  if (!ecvCloud) {
289  "[PCLDisplayTools::drawMesh] Failed to get point cloud "
290  "from mesh!");
291  return;
292  }
293 
294  // materials & textures
295  bool applyMaterials = (mesh->hasMaterials() && mesh->materialsShown());
296  bool lodEnabled = false;
297  bool showTextures =
298  (mesh->hasTextures() && mesh->materialsShown() && !lodEnabled);
299 
301  "[PCLDisplayTools::drawMesh] applyMaterials=%d, "
302  "showTextures=%d",
303  applyMaterials, showTextures);
304 
305  if (firstShow || checkEntityNeedUpdate(viewID, ecvCloud)) {
306  if (applyMaterials || showTextures) {
307  // Use new direct method to avoid pcl::TexMaterial encoding
308  if (!m_visualizer3D->addTextureMeshFromCCMesh(mesh, viewID,
309  viewport)) {
311  "[PCLDisplayTools::drawMesh] Failed to add texture "
312  "mesh directly, falling back to PCLTextureMesh");
313  // Fallback to old method for backward compatibility
314  PCLTextureMesh::Ptr textureMesh =
315  cc2smReader(ecvCloud, true).getPclTextureMesh(mesh);
316  if (textureMesh) {
317  m_visualizer3D->draw(context, textureMesh);
318  } else {
320  "[PCLDisplayTools::drawMesh] Failed to create "
321  "PCLTextureMesh, falling back to regular mesh");
322  PCLMesh::Ptr pclMesh =
323  cc2smReader(ecvCloud, true).getPclMesh(mesh);
324  if (!pclMesh) return;
325  m_visualizer3D->draw(context, pclMesh);
326  }
327  }
328 
329  } else {
330  PCLMesh::Ptr pclMesh =
331  cc2smReader(ecvCloud, true).getPclMesh(mesh);
332  if (!pclMesh) return;
333  m_visualizer3D->draw(context, pclMesh);
334 
335  // Add mesh name to VTK FieldData after PCL creates the actor
336  // (for tooltip display, ParaView style)
337  std::string viewID = CVTools::FromQString(context.viewID);
338  vtkActor* actor = m_visualizer3D->getActorById(viewID);
339  if (actor && actor->GetMapper() &&
340  mesh->getName().length() > 0) {
341  vtkPolyData* polyData = vtkPolyData::SafeDownCast(
342  actor->GetMapper()->GetInput());
343  if (polyData) {
344  QString meshName = mesh->getName();
346  QString("[PCLDisplayTools::drawMesh] "
347  "Adding DatasetName to "
348  "non-textured mesh: '%1'")
349  .arg(meshName));
350 
351  vtkSmartPointer<vtkStringArray> datasetNameArray =
353  datasetNameArray->SetName("DatasetName");
354  datasetNameArray->SetNumberOfTuples(1);
355  datasetNameArray->SetValue(0, meshName.toStdString());
356  polyData->GetFieldData()->AddArray(datasetNameArray);
357  }
358  }
359  }
360  } else {
361  // Non-first display and no need for complete rebuild: only update
362  // properties (color, visibility, normals, etc.)
364  "[PCLDisplayTools::drawMesh] Update path: updating "
365  "properties only");
366  m_visualizer3D->resetScalarColor(viewID, true, viewport);
367  if (!updateEntityColor(context, ecvCloud)) {
368  if (applyMaterials || showTextures) {
369  // Update texture materials (without rebuilding geometry)
370  const ccMaterialSet* materials = mesh->getMaterialSet();
371  if (materials) {
373  "[PCLDisplayTools::drawMesh] Updating textures "
374  "for %zu materials",
375  materials->size());
376  if (!m_visualizer3D->updateTexture(context,
377  materials)) {
379  "[PCLDisplayTools::drawMesh] Update "
380  "texture failed!");
381  }
382  }
383  } else {
384  PCLMesh::Ptr pclMesh =
385  cc2smReader(ecvCloud, true).getPclMesh(mesh);
386  if (!pclMesh) return;
387  m_visualizer3D->draw(context, pclMesh);
388  }
389  }
390  }
391  m_visualizer3D->transformEntities(context);
392  }
393 
394  if (m_visualizer3D->contains(viewID)) {
395  m_visualizer3D->setMeshRenderingMode(context.meshRenderingMode, viewID,
396  viewport);
397 
398  // Set the source mesh for direct extraction during selection operations
399  // This allows bypassing VTK→ccMesh conversion when extracting
400  // selections Cast to ccMesh for source object tracking
401  ccMesh* ccMeshObj = dynamic_cast<ccMesh*>(mesh);
402  if (ccMeshObj && (firstShow || mesh->isRedraw())) {
403  m_visualizer3D->setCurrentSourceObject(ccMeshObj, viewID);
404  }
405 
406  if ((!context.drawParam.showColors && !context.drawParam.showSF) ||
407  mesh->isColorOverridden()) {
408  ecvColor::Rgbf meshColor =
409  ecvTools::TransFormRGB(context.defaultMeshColor);
410  m_visualizer3D->setPointCloudUniqueColor(
411  meshColor.r, meshColor.g, meshColor.b, viewID, viewport);
412  }
413  m_visualizer3D->setPointCloudOpacity(context.opacity, viewID, viewport);
414  }
415 }
416 
417 void PCLDisplayTools::drawPolygon(const CC_DRAW_CONTEXT& context,
418  ccPolyline* polyline) {
419  std::string viewID = CVTools::FromQString(context.viewID);
420  bool firstShow = !m_visualizer3D->contains(viewID);
421  int viewport = context.defaultViewPort;
422 
423  if (polyline->isRedraw() || firstShow) {
424  PCLPolygon::Ptr pclPolygon = cc2smReader(true).getPclPolygon(polyline);
425  if (!pclPolygon) return;
426  m_visualizer3D->draw(context, pclPolygon, polyline->isClosed());
427  }
428 
429  if (m_visualizer3D->contains(viewID)) {
430  ecvColor::Rgbf polygonColor =
431  ecvTools::TransFormRGB(context.defaultPolylineColor);
432  m_visualizer3D->setShapeUniqueColor(polygonColor.r, polygonColor.g,
433  polygonColor.b, viewID, viewport);
434  m_visualizer3D->setLineWidth(context.currentLineWidth, viewID,
435  viewport);
436  m_visualizer3D->setLightMode(viewID, viewport);
437  }
438 }
439 
440 void PCLDisplayTools::drawLines(const CC_DRAW_CONTEXT& context,
442  std::string viewID = CVTools::FromQString(context.viewID);
443  bool firstShow = !m_visualizer3D->contains(viewID);
444  int viewport = context.defaultViewPort;
445 
446  if (lineset->isRedraw() || firstShow) {
447  m_visualizer3D->draw(context, lineset);
448  m_visualizer3D->transformEntities(context);
449  }
450 
451  if (m_visualizer3D->contains(viewID)) {
452  if (lineset->isColorOverridden() || !lineset->HasColors()) {
453  ecvColor::Rgbf polygonColor =
454  ecvTools::TransFormRGB(context.defaultPolylineColor);
455  m_visualizer3D->setShapeUniqueColor(polygonColor.r, polygonColor.g,
456  polygonColor.b, viewID,
457  viewport);
458  }
459 
460  m_visualizer3D->setLineWidth(context.currentLineWidth, viewID,
461  viewport);
462  m_visualizer3D->setLightMode(viewID, viewport);
463  }
464 }
465 
466 void PCLDisplayTools::drawImage(const CC_DRAW_CONTEXT& context,
467  ccImage* image) {
468  if (!image || !m_visualizer2D) return;
469 
470  std::string viewID = CVTools::FromQString(context.viewID);
471  bool firstShow = !m_visualizer2D->contains(viewID);
472 
473  bool imageExists = !firstShow;
474 
475  // Note: isRedraw() might be true even if only opacity changed,
476  // because ccHObject::draw() always sets setRedraw(true) at the end.
477  // So we check if image already exists - if it does and only opacity
478  // changed, we can just update opacity without reloading image data.
479  bool needsImageReload = firstShow || (image->isRedraw() && !imageExists);
480 
481  double opacity = image->getAlpha();
482  // Only reload image data if image data has changed or first time showing
483  if (needsImageReload) {
484  const QImage& qimage = image->data();
485  if (qimage.isNull()) {
487  "[PCLDisplayTools::drawImage] Failed to get image data!");
488  return;
489  }
490 
492  "[PCLDisplayTools::drawImage] Reloading image data: %d x %d, "
493  "opacity: %f, redraw: %d, firstShow: %d, isEnabled: %d",
494  image->getW(), image->getH(), image->getAlpha(),
495  image->isRedraw(), firstShow, image->isEnabled());
496 
497  // ParaView-style: Use addQImage with vtkQImageToImageSource for
498  // efficient conversion This avoids manual format conversion and memory
499  // copying
500  m_visualizer2D->addQImage(qimage, viewID, opacity);
501  } else {
502  // Only update opacity if image already exists and data hasn't changed
504  "[PCLDisplayTools::drawImage] Updating opacity only for image "
505  "%s, "
506  "opacity: %f",
507  viewID.c_str(), opacity);
508  m_visualizer2D->changeOpacity(opacity, viewID);
509  }
510 }
511 
512 void PCLDisplayTools::drawSensor(const CC_DRAW_CONTEXT& context,
513  ccSensor* sensor) {
514  if (!sensor) {
515  return;
516  }
517 
518  std::string viewID = CVTools::FromQString(context.viewID);
519  bool firstShow = !m_visualizer3D->contains(viewID);
520  int viewport = context.defaultViewPort;
521 
522  if (sensor->isRedraw() || firstShow) {
523  m_visualizer3D->draw(context, sensor);
524  m_visualizer3D->transformEntities(context);
525  }
526 
527  if (m_visualizer3D->contains(viewID)) {
528  m_visualizer3D->setLineWidth(context.currentLineWidth, viewID,
529  viewport);
530  }
531 }
532 
533 bool PCLDisplayTools::updateEntityColor(const CC_DRAW_CONTEXT& context,
534  ccHObject* ent) {
535 #ifdef _DEBUG
537 #endif // _DEBUG
539  if (!cloud) {
540  return false;
541  }
542 
543  std::string viewID = CVTools::FromQString(context.viewID);
544  vtkActor* modelActor = m_visualizer3D->getActorById(viewID);
545  if (!modelActor) {
546  return false;
547  }
548 
549  // Get the current poly data
551  reinterpret_cast<vtkPolyDataMapper*>(modelActor->GetMapper())
552  ->GetInput();
553  if (!polydata) return (false);
554 
555  // Get the colors from the handler
556  bool has_colors = false;
557  double minmax[2];
559  cc2smReader converter(cloud, true);
560  unsigned old_points_num =
561  static_cast<unsigned>(polydata->GetNumberOfPoints());
562  unsigned new_points_num = converter.getvisibilityNum();
563  if (old_points_num != new_points_num) {
564  return false;
565  }
566 
567  if (!context.drawParam.showColors && !context.drawParam.showSF) {
568  return false;
569  }
570 
571  if (converter.getvtkScalars(scalars, context.drawParam.showSF)) {
572  // Update the data
573  polydata->GetPointData()->SetScalars(scalars);
574  scalars->GetRange(minmax);
575  has_colors = true;
576  }
577 
578  if (has_colors) {
579 #if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
580  modelActor->GetMapper()->ImmediateModeRenderingOff();
581 #endif
582  modelActor->GetMapper()->SetScalarRange(minmax);
583  // Update the mapper
584 #if VTK_MAJOR_VERSION < 6
585  reinterpret_cast<vtkPolyDataMapper*>(modelActor->GetMapper())
586  ->SetInput(polydata);
587 #else
588  reinterpret_cast<vtkPolyDataMapper*>(modelActor->GetMapper())
589  ->SetInputData(polydata);
590 #endif
591  }
592 
593  CVLog::PrintDebug(QString("updateEntityColor: finish cost %1 s")
594  .arg(CVTools::TimeOff()));
595 
596  return (true);
597 }
598 
600  const ccHObject* obj) {
601  if (obj->isA(CV_TYPES::POINT_CLOUD)) {
602  // the cloud to draw
603  ccPointCloud* ecvCloud =
604  ccHObjectCaster::ToPointCloud(const_cast<ccHObject*>(obj));
605  if (!ecvCloud) return;
606 
607  drawPointCloud(context, ecvCloud);
608  } else if (obj->isKindOf(CV_TYPES::MESH) ||
610  // the mesh to draw
611  ccGenericMesh* tempMesh =
612  ccHObjectCaster::ToGenericMesh(const_cast<ccHObject*>(obj));
613  if (!tempMesh) {
615  "[PCLDisplayTools::draw] Failed to cast to ccGenericMesh!");
616  return;
617  }
618  drawMesh(const_cast<CC_DRAW_CONTEXT&>(context), tempMesh);
619  } else if (obj->isA(CV_TYPES::POLY_LINE)) {
620  // the polyline to draw
621  ccPolyline* tempPolyline =
622  ccHObjectCaster::ToPolyline(const_cast<ccHObject*>(obj));
623  if (!tempPolyline) return;
624  drawPolygon(context, tempPolyline);
625  } else if (obj->isA(CV_TYPES::LINESET)) {
626  // the polyline to draw
628  ccHObjectCaster::ToLineSet(const_cast<ccHObject*>(obj));
629  if (!lineset) return;
630  drawLines(context, lineset);
631  } else if (obj->isA(CV_TYPES::IMAGE)) {
632  // the image to draw
633  ccImage* image = ccHObjectCaster::ToImage(const_cast<ccHObject*>(obj));
634  if (!image) return;
635  drawImage(context, image);
636  } else if (obj->isKindOf(CV_TYPES::SENSOR)) // must use isKindOf here
637  {
638  // the sensor to draw
639  ccSensor* sensor =
640  ccHObjectCaster::ToSensor(const_cast<ccHObject*>(obj));
641  if (!sensor) return;
642  drawSensor(context, sensor);
643  } else {
644  return;
645  }
646 
647  if (m_visualizer3D) {
648  m_visualizer3D->resetCameraClippingRange(context.defaultViewPort);
649  }
650 }
651 
652 bool PCLDisplayTools::checkEntityNeedUpdate(std::string& viewID,
653  const ccHObject* obj) {
654  bool firstShow = !m_visualizer3D->contains(viewID);
655  if (firstShow) return true;
656 
657  ccPointCloud* cloud =
658  ccHObjectCaster::ToPointCloud(const_cast<ccHObject*>(obj));
659  if (!cloud) {
660  return true;
661  }
662 
663  vtkActor* modelActor = m_visualizer3D->getActorById(viewID);
664  if (!modelActor) {
665  return true;
666  }
667 
668  // Get the current poly data
670  reinterpret_cast<vtkPolyDataMapper*>(modelActor->GetMapper())
671  ->GetInput();
672  if (!polydata) {
673  return true;
674  }
675 
676  cc2smReader converter(cloud);
677  unsigned old_points_num =
678  static_cast<unsigned>(polydata->GetNumberOfPoints());
679  unsigned new_points_num = converter.getvisibilityNum();
680  if (old_points_num != new_points_num) {
681  return true;
682  }
683 
684  double bounds[6];
685  polydata->GetBounds(bounds);
686  CCVector3 minCorner(bounds[0], bounds[2], bounds[4]);
687  CCVector3 maxCorner(bounds[1], bounds[3], bounds[5]);
688  ccBBox oldBBox(minCorner, maxCorner);
689  ccBBox newBBox = cloud->getOwnBB();
690 
691  if (abs((oldBBox.minCorner() - newBBox.minCorner()).normd()) >
692  EPSILON_VALUE) {
693  return true;
694  }
695 
696  if (abs((oldBBox.maxCorner() - newBBox.maxCorner()).normd()) >
697  EPSILON_VALUE) {
698  return true;
699  }
700 
701  return false;
702 }
703 
705  const ccBBox* bbox) {
706  ecvColor::Rgbf colf = ecvTools::TransFormRGB(context.bbDefaultCol);
707  int viewport = context.defaultViewPort;
708  if (m_visualizer3D) {
709  std::string bboxID = CVTools::FromQString(context.viewID);
710  if (!m_visualizer3D->contains(bboxID)) {
711  m_visualizer3D->addCube(bbox->minCorner().x, bbox->maxCorner().x,
712  bbox->minCorner().y, bbox->maxCorner().y,
713  bbox->minCorner().z, bbox->maxCorner().z,
714  colf.r, colf.g, colf.b, bboxID, viewport);
715 
716  // m_visualizer3D->setMeshRenderingMode(context.meshRenderingMode,
717  // bboxID, viewport);
718  m_visualizer3D->setShapeRenderingProperties(
719  pcl::visualization::PCL_VISUALIZER_REPRESENTATION,
720  pcl::visualization::PCL_VISUALIZER_REPRESENTATION_WIREFRAME,
721  bboxID, viewport);
722  m_visualizer3D->setLineWidth(context.defaultLineWidth, bboxID,
723  viewport);
724  m_visualizer3D->setLightMode(bboxID, viewport);
725  }
726 
727  // Always update properties (color, opacity, line width) even if
728  // BoundingBox already exists
729  m_visualizer3D->setShapeUniqueColor(colf.r, colf.g, colf.b, bboxID,
730  viewport);
731  m_visualizer3D->setLineWidth(context.defaultLineWidth, bboxID,
732  viewport);
733 
734  // Apply opacity if specified in context
735  if (context.opacity >= 0.0 && context.opacity <= 1.0) {
736  m_visualizer3D->setShapeRenderingProperties(
737  pcl::visualization::PCL_VISUALIZER_OPACITY, context.opacity,
738  bboxID, viewport);
739  }
740  }
741 }
742 
744  const ecvOrientedBBox* obb) {
745  int viewport = context.defaultViewPort;
746  if (m_visualizer3D) {
747  std::string bboxID = CVTools::FromQString(context.viewID);
748  if (m_visualizer3D->contains(bboxID)) {
749  m_visualizer3D->removeShape(bboxID);
750  }
751 
752  m_visualizer3D->addOrientedCube(*obb, bboxID, viewport);
753  m_visualizer3D->setLineWidth(context.defaultLineWidth, bboxID,
754  viewport);
755  m_visualizer3D->setLightMode(bboxID, viewport);
756  }
757 }
758 
760  return m_visualizer3D->pclMarkerAxesShown();
761 }
762 
764  if (state) {
765  m_visualizer3D->showPclMarkerAxes(
766  m_visualizer3D->getRenderWindowInteractor());
767  } else {
768  m_visualizer3D->hidePclMarkerAxes();
769  }
770 }
771 
773  if (context.removeEntityType == ENTITY_TYPE::ECV_IMAGE ||
774  context.removeEntityType == ENTITY_TYPE::ECV_LINES_2D ||
775  context.removeEntityType == ENTITY_TYPE::ECV_CIRCLE_2D ||
776  context.removeEntityType == ENTITY_TYPE::ECV_RECTANGLE_2D ||
777  context.removeEntityType == ENTITY_TYPE::ECV_TRIANGLE_2D ||
778  context.removeEntityType == ENTITY_TYPE::ECV_MARK_POINT) {
779  if (!m_visualizer2D) return;
780  std::string viewId = CVTools::FromQString(context.removeViewID);
781  if (m_visualizer2D->contains(viewId)) {
782  m_visualizer2D->removeLayer(viewId);
783  }
784  } else {
785  if (context.removeEntityType == ENTITY_TYPE::ECV_TEXT2D ||
786  context.removeEntityType == ENTITY_TYPE::ECV_POLYLINE_2D) {
787  if (m_visualizer2D) {
788  std::string viewId = CVTools::FromQString(context.removeViewID);
789  if (m_visualizer2D->contains(viewId)) {
790  m_visualizer2D->removeLayer(viewId);
791  }
792  }
793  }
794 
795  if (m_visualizer3D && m_visualizer3D->removeEntities(context)) {
796  m_visualizer3D->resetCameraClippingRange(context.defaultViewPort);
797  }
798  }
799 }
800 
802  std::string viewId = CVTools::FromQString(context.viewID);
803 
804  if (context.hideShowEntityType == ENTITY_TYPE::ECV_IMAGE ||
805  context.removeEntityType == ENTITY_TYPE::ECV_LINES_2D ||
806  context.removeEntityType == ENTITY_TYPE::ECV_CIRCLE_2D ||
807  context.removeEntityType == ENTITY_TYPE::ECV_TRIANGLE_2D ||
808  context.removeEntityType == ENTITY_TYPE::ECV_RECTANGLE_2D ||
809  context.removeEntityType == ENTITY_TYPE::ECV_MARK_POINT) {
810  if (!m_visualizer2D || !m_visualizer2D->contains(viewId)) return false;
811 
812  m_visualizer2D->hideShowActors(context.visible, viewId);
813  return true;
814  } else if (context.removeEntityType == ENTITY_TYPE::ECV_CAPTION) {
815  if (m_visualizer3D->containWidget(viewId)) {
816  m_visualizer3D->hideShowWidgets(context.visible, viewId,
817  context.defaultViewPort);
818  }
819  } else {
820  if (context.removeEntityType == ENTITY_TYPE::ECV_TEXT2D ||
821  context.removeEntityType == ENTITY_TYPE::ECV_POLYLINE_2D) {
822  if (m_visualizer2D && m_visualizer2D->contains(viewId)) {
823  m_visualizer2D->hideShowActors(context.visible, viewId);
824  }
825  }
826 
827  if (!m_visualizer3D->contains(viewId)) {
828  return false;
829  }
830 
831  m_visualizer3D->hideShowActors(context.visible, viewId,
832  context.defaultViewPort);
833 
834  // for normals case
835  std::string normalViewId =
836  CVTools::FromQString(context.viewID + "-normal");
837  if (m_visualizer3D->contains(normalViewId)) {
838  m_visualizer3D->hideShowActors(context.visible, normalViewId,
839  context.defaultViewPort);
840  }
841 
842  m_visualizer3D->resetCameraClippingRange(context.defaultViewPort);
843  }
844 
845  return true;
846 }
847 
849  // ccHObject * entity = param.entity;
850  int viewport = param.viewport;
851  std::string viewID = CVTools::FromQString(param.viewID);
852  switch (param.type) {
854  break;
856  break;
858  if (m_visualizer2D) {
859  std::string text = CVTools::FromQString(param.text);
860  m_visualizer2D->addText(param.rect.x(), param.rect.y(), text,
861  param.color.r, param.color.g,
862  param.color.b, viewID, param.color.a,
863  param.fontSize);
864  } else {
867  ecvTextParam tParam;
868  tParam.display3D = false;
870  tParam.opacity = param.color.a;
871  tParam.text = param.text;
872  tParam.textPos =
873  CCVector3d(param.rect.x(), param.rect.y(), 0.0);
874  context.textDefaultCol = ecvColor::FromRgbafToRgb(param.color);
875  context.textParam = tParam;
876  context.viewID = tParam.text;
877  m_visualizer3D->displayText(context);
878  }
879 
881  if (param.lineWidget.valid && !m_visualizer3D->contains(viewID)) {
882  PointT lineSt;
883  lineSt.x = param.lineWidget.lineSt.x;
884  lineSt.y = param.lineWidget.lineSt.y;
885  lineSt.z = param.lineWidget.lineSt.z;
886  PointT lineEd;
887  lineEd.x = param.lineWidget.lineEd.x;
888  lineEd.y = param.lineWidget.lineEd.y;
889  lineEd.z = param.lineWidget.lineEd.z;
890  unsigned char lineWidth =
891  (unsigned char)param.lineWidget.lineWidth;
892  ecvColor::Rgbf lineColor =
894  m_visualizer3D->addLine(lineSt, lineEd, lineColor.r,
895  lineColor.g, lineColor.b, viewID,
896  viewport);
897  m_visualizer3D->setLineWidth(lineWidth, viewID, viewport);
898  }
899  break;
901  if (!m_visualizer3D->contains(viewID)) {
902  PointT center;
903  center.x = param.center.x;
904  center.y = param.center.y;
905  center.z = param.center.z;
906  m_visualizer3D->addSphere(center, param.radius, param.color.r,
907  param.color.g, param.color.b, viewID,
908  viewport);
909  }
910  break;
911 
913  if (!m_visualizer3D->updateScalarBar(param.context)) {
914  m_visualizer3D->addScalarBar(param.context);
915  }
916  break;
918  if (!m_visualizer3D->updateCaption(
919  CVTools::FromQString(param.text), param.pos,
920  param.center, param.color.r, param.color.g,
921  param.color.b, param.color.a, param.fontSize, viewID,
922  viewport)) {
923  m_visualizer3D->addCaption(
924  CVTools::FromQString(param.text), param.pos,
925  param.center, param.color.r, param.color.g,
926  param.color.b, param.color.a, param.fontSize, viewID,
927  param.handleEnabled, viewport);
928  }
929  break;
931  if (m_visualizer2D) {
932  m_visualizer2D->addLine(param.p1.x(), param.p1.y(),
933  param.p2.x(), param.p2.y(),
934  param.color.r, param.color.g,
935  param.color.b, viewID, param.color.a);
936  }
937  break;
939  if (m_visualizer2D) {
940  if (param.entity &&
942  ccPolyline* poly =
944  if (poly->size() <= 1) {
945  return;
946  }
947 
948  if (!poly->is2DMode()) {
950  "[PCLDisplayTools::drawWidgets] draw mode is "
951  "incompatible with entity mode!");
952  return;
953  }
954 
955  viewID = CVTools::FromQString(poly->getViewId());
956 
958  if (poly->isColorOverridden()) {
960  } else if (poly->colorsShown()) {
961  color = ecvColor::FromRgb(poly->getColor());
962  }
963 
964  for (unsigned i = 1; i < poly->size(); ++i) {
965  const CCVector3* p1 = poly->getPoint(i - 1);
966  const CCVector3* p2 = poly->getPoint(i);
967 
968  m_visualizer2D->addLine(static_cast<int>(p1->x),
969  static_cast<int>(p1->y),
970  static_cast<int>(p2->x),
971  static_cast<int>(p2->y),
972  color.r, color.g, color.b,
973  viewID, param.opacity);
974  }
975 
976  if (poly->isClosed()) {
977  m_visualizer2D->addLine(
978  static_cast<int>(
979  poly->getPoint(poly->size() - 1)->x),
980  static_cast<int>(
981  poly->getPoint(poly->size() - 1)->y),
982  static_cast<int>(poly->getPoint(0)->x),
983  static_cast<int>(poly->getPoint(0)->y), color.r,
984  color.g, color.b, viewID, param.opacity);
985  }
986  }
987  } else {
988  if (param.entity &&
990  ccPolyline* poly =
992  if (poly->size() <= 1) {
993  return;
994  }
995 
997  WIDGETS_PARAMETER(poly,
999  true);
1000  }
1001  }
1002  break;
1004  if (m_visualizer2D) {
1005  // edge 1
1006  m_visualizer2D->addLine(param.p1.x(), param.p1.y(),
1007  param.p2.x(), param.p2.y(),
1008  param.color.r, param.color.g,
1009  param.color.b, viewID, param.color.a);
1010 
1011  // edge 2
1012  m_visualizer2D->addLine(param.p2.x(), param.p2.y(),
1013  param.p3.x(), param.p3.y(),
1014  param.color.r, param.color.g,
1015  param.color.b, viewID, param.color.a);
1016  if (param.p4.x() >= 0 && param.p4.y() >= 0) {
1017  // edge 3
1018  m_visualizer2D->addLine(
1019  param.p3.x(), param.p3.y(), param.p4.x(),
1020  param.p4.y(), param.color.r, param.color.g,
1021  param.color.b, viewID, param.color.a);
1022  // edge 4
1023  m_visualizer2D->addLine(
1024  param.p4.x(), param.p4.y(), param.p1.x(),
1025  param.p1.y(), param.color.r, param.color.g,
1026  param.color.b, viewID, param.color.a);
1027  } else {
1028  // edge 3
1029  m_visualizer2D->addLine(
1030  param.p3.x(), param.p3.y(), param.p1.x(),
1031  param.p1.y(), param.color.r, param.color.g,
1032  param.color.b, viewID, param.color.a);
1033  }
1034  }
1035  break;
1037  if (m_visualizer2D) {
1040  param.color.r, param.color.g, param.color.b);
1041  m_visualizer2D->markPoint(param.rect.x(), param.rect.y(), color,
1042  color, param.radius, viewID,
1043  param.color.a);
1044  }
1045  break;
1047  if (m_visualizer2D) {
1048  int minX = std::max(param.rect.x(), 0);
1049  int maxX = std::min(minX + param.rect.width(),
1050  m_visualizer2D->getSize()[0]);
1051  int minY = std::max(param.rect.y(), 0);
1052  int maxY = std::min(minY + param.rect.height(),
1053  m_visualizer2D->getSize()[1]);
1054 
1055  if (param.filled) {
1056  m_visualizer2D->addFilledRectangle(
1057  minX, maxX, minY, maxY, param.color.r,
1058  param.color.g, param.color.b, viewID,
1059  param.color.a);
1060  } else {
1061  m_visualizer2D->addRectangle(minX, maxX, minY, maxY,
1062  param.color.r, param.color.g,
1063  param.color.b, viewID,
1064  param.color.a);
1065  }
1066  }
1067  break;
1069  if (m_visualizer2D) {
1070  m_visualizer2D->addCircle(param.rect.x(), param.rect.y(),
1071  param.radius, param.color.r,
1072  param.color.g, param.color.b, viewID,
1073  param.color.a);
1074  }
1075  break;
1077  if (m_visualizer2D) {
1078  if (param.image.isNull()) return;
1079 
1080  m_visualizer2D->addRGBImage(param.image, param.rect.x(),
1081  param.rect.y(), viewID,
1082  param.opacity);
1083  }
1084  break;
1085  default:
1086  break;
1087  }
1088 }
1089 
1091  if (m_visualizer2D) {
1092  ecvTextParam textParam = context.textParam;
1093  std::string viewID = CVTools::FromQString(context.viewID);
1094  std::string text = CVTools::FromQString(textParam.text);
1095 
1096  ecvColor::Rgbf textColor =
1097  ecvTools::TransFormRGB(context.textDefaultCol);
1098  {
1099  m_visualizer2D->addText(
1100  textParam.textPos.x, textParam.textPos.y, text, textColor.r,
1101  textColor.g, textColor.b, viewID, textParam.opacity,
1102  textParam.font.pointSize(), textParam.font.bold());
1103  }
1104  } else {
1105  m_visualizer3D->displayText(context);
1106  }
1107 }
1108 
1110  if (m_visualizer2D) {
1111  m_visualizer2D->enable2Dviewer(state);
1112  }
1113 }
1114 
1115 QString PCLDisplayTools::pick2DLabel(int x, int y) {
1116  if (m_visualizer2D) {
1117  return m_visualizer2D->pickItem(x, y).c_str();
1118  }
1119 
1120  return QString();
1121 }
1122 
1123 QString PCLDisplayTools::pick3DItem(int x, int y) {
1124  if (m_visualizer3D) {
1125  return m_visualizer3D->pickItem(x, y).c_str();
1126  }
1127 
1128  return QString();
1129 }
1130 
1131 QString PCLDisplayTools::pickObject(double x, double y) {
1132  if (m_visualizer3D) {
1133  vtkActor* pickedActor = m_visualizer3D->pickActor(x, y);
1134  if (pickedActor) {
1135  if (pickedActor) {
1136  return m_visualizer3D->getIdByActor(pickedActor).c_str();
1137  } else {
1138  return "-1";
1139  }
1140  }
1141  }
1142  return "-1";
1143 }
1144 
1145 QImage PCLDisplayTools::renderToImage(int zoomFactor,
1146  bool renderOverlayItems,
1147  bool silent,
1148  int viewport) {
1149  if (m_visualizer3D) {
1150  return m_visualizer3D->renderToImage(zoomFactor, renderOverlayItems,
1151  silent, viewport);
1152  } else {
1153  if (!silent)
1154  CVLog::Error(
1155  "[PCLDisplayTools::renderToImage] PCLVis Initialization "
1156  "failed! (not enough memory?)");
1157  return QImage();
1158  }
1159 }
1160 
1162  if (m_visualizer3D) {
1163  return m_visualizer3D->getParallelScale(viewport);
1164  }
1165 
1166  return -1;
1167 }
1168 
1169 void PCLDisplayTools::setParallelScale(double scale, int viewport) {
1170  if (m_visualizer3D) {
1171  m_visualizer3D->setParallelScale(scale, viewport);
1172  }
1173 }
1174 
1175 void PCLDisplayTools::getProjectionMatrix(double* projArray, int viewport) {
1176  Eigen::Matrix4d projMat;
1177  m_visualizer3D->getCamera(viewport).computeProjectionMatrix(projMat);
1178  // m_visualizer3D->getProjectionTransformMatrix(projMat);
1179  double* tempArray = projMat.data();
1180  projArray[0] = tempArray[0];
1181  projArray[1] = tempArray[1];
1182  projArray[2] = tempArray[2];
1183  projArray[3] = tempArray[3];
1184  projArray[4] = tempArray[4];
1185  projArray[5] = tempArray[5];
1186  projArray[6] = tempArray[6];
1187  projArray[7] = tempArray[7];
1188  projArray[8] = tempArray[8];
1189  projArray[9] = tempArray[9];
1190  projArray[10] = tempArray[10];
1191  projArray[11] = tempArray[11];
1192  projArray[12] = tempArray[12];
1193  projArray[13] = tempArray[13];
1194  projArray[14] = tempArray[14];
1195  projArray[15] = tempArray[15];
1196 }
1197 
1198 void PCLDisplayTools::getViewMatrix(double* ViewArray, int viewport) {
1199  Eigen::Matrix4d viewMat;
1200  m_visualizer3D->getCamera(viewport).computeViewMatrix(viewMat);
1201  // m_visualizer3D->getModelViewTransformMatrix(viewMat);
1202  double* tempArray = viewMat.data();
1203  ViewArray[0] = tempArray[0];
1204  ViewArray[1] = tempArray[1];
1205  ViewArray[2] = tempArray[2];
1206  ViewArray[3] = tempArray[3];
1207  ViewArray[4] = tempArray[4];
1208  ViewArray[5] = tempArray[5];
1209  ViewArray[6] = tempArray[6];
1210  ViewArray[7] = tempArray[7];
1211  ViewArray[8] = tempArray[8];
1212  ViewArray[9] = tempArray[9];
1213  ViewArray[10] = tempArray[10];
1214  ViewArray[11] = tempArray[11];
1215  ViewArray[12] = tempArray[12];
1216  ViewArray[13] = tempArray[13];
1217  ViewArray[14] = tempArray[14];
1218  ViewArray[15] = tempArray[15];
1219 }
1220 
1221 void PCLDisplayTools::setViewMatrix(const ccGLMatrixd& viewMat, int viewport) {
1222  if (m_visualizer3D) {
1223  m_visualizer3D->setModelViewMatrix(viewMat, viewport);
1224  }
1225 }
1226 
1228  const std::string& viewID,
1229  int viewport) {
1230  if (m_visualizer2D) {
1231  m_visualizer2D->changeOpacity(opacity, viewID);
1232  }
1233 }
1234 
1236  std::string viewId = CVTools::FromQString(param.viewId);
1237  int viewport = param.viewport;
1238  switch (param.property) {
1240  m_visualizer3D->setPointSize(param.pointSize, viewId, viewport);
1241  } break;
1243  m_visualizer3D->setLineWidth(
1244  static_cast<unsigned char>(param.lineWidth), viewId,
1245  viewport);
1246  } break;
1249  switch (param.entityType) {
1251  case ENTITY_TYPE::ECV_MESH: {
1252  m_visualizer3D->setPointCloudUniqueColor(
1253  colf.r, colf.g, colf.b, viewId, viewport);
1254  } break;
1257  m_visualizer3D->setShapeUniqueColor(colf.r, colf.g, colf.b,
1258  viewId, viewport);
1259  } break;
1260  default:
1261  break;
1262  }
1263  } break;
1265  switch (param.entityType) {
1267  // Point clouds use PCL's point cloud opacity setting
1268  m_visualizer3D->setPointCloudOpacity(param.opacity, viewId,
1269  viewport);
1270  } break;
1271  case ENTITY_TYPE::ECV_MESH: {
1272  // Meshes (textured or not) use dedicated mesh opacity
1273  // method This properly handles:
1274  // - Textured meshes with alpha blending
1275  // - Non-textured meshes with simple opacity
1276  // - Depth peeling for correct transparency rendering
1277  m_visualizer3D->setMeshOpacity(param.opacity, viewId,
1278  viewport);
1279  } break;
1282  m_visualizer3D->setShapeOpacity(param.opacity, viewId,
1283  viewport);
1284  } break;
1285  default:
1286  break;
1287  }
1288  } break;
1290  switch (param.entityType) {
1292  case ENTITY_TYPE::ECV_MESH: {
1293  m_visualizer3D->setMeshShadingMode(param.shadingMode,
1294  viewId, viewport);
1295  }
1298  m_visualizer3D->setShapeShadingMode(param.shadingMode,
1299  viewId, viewport);
1300  } break;
1301  default:
1302  break;
1303  }
1304  } break;
1305 
1306  default:
1307  break;
1308  }
1309 }
1310 
1312  getQVtkWidget()->transformCameraView(viewMat.data());
1313 }
1314 
1317 }
1318 
1319 // ============================================================================
1320 // View Properties Implementation (ParaView-compatible)
1321 // ============================================================================
1322 
1324  if (!m_visualizer3D) {
1325  CVLog::Warning("[PCLDisplayTools] No 3D visualizer available");
1326  return;
1327  }
1328 
1329  // Delegate to PCLVis
1330  m_visualizer3D->ToggleCameraOrientationWidget(show);
1331 }
1332 
1334  if (!m_visualizer3D) {
1335  return false;
1336  }
1337 
1338  // Delegate to PCLVis
1339  return m_visualizer3D->IsCameraOrientationWidgetShown();
1340 }
1341 
1342 // Override base class virtual methods (ecvDisplayTools interface)
1345 }
1346 
1349 }
1350 
1351 void PCLDisplayTools::setLightIntensity(double intensity) {
1352  if (!m_visualizer3D) {
1353  CVLog::Warning("[PCLDisplayTools] No 3D visualizer available");
1354  return;
1355  }
1356 
1357  // Delegate to PCLVis
1358  m_visualizer3D->setLightIntensity(intensity);
1359 }
1360 
1362  if (!m_visualizer3D) {
1363  return 1.0; // Default intensity
1364  }
1365 
1366  // Delegate to PCLVis
1367  return m_visualizer3D->getLightIntensity();
1368 }
1369 
1370 // ============================================================================
1371 // Axes Grid Properties (ParaView-compatible)
1372 // ============================================================================
1373 
1374 // Unified struct-based interface (Simplified - direct pass-through)
1376  const AxesGridProperties& props,
1377  int viewport) {
1378  if (!m_visualizer3D) {
1379  CVLog::Warning("[PCLDisplayTools] No 3D visualizer available");
1380  return;
1381  }
1382 
1383  // Direct delegation to PCLVis (no type conversion needed, PCLVis now
1384  // handles Qt types)
1385  m_visualizer3D->SetDataAxesGridProperties(CVTools::FromQString(viewID),
1386  props);
1387 }
1388 
1390  AxesGridProperties& props,
1391  int viewport) const {
1392  if (!m_visualizer3D) {
1393  // Return default values
1394  props = AxesGridProperties();
1395  return;
1396  }
1397  m_visualizer3D->GetDataAxesGridProperties(CVTools::FromQString(viewID),
1398  props);
1399 }
constexpr double EPSILON_VALUE
Definition: CVConst.h:87
Vector3Tpl< double > CCVector3d
Double 3D Vector.
Definition: CVGeom.h:804
std::shared_ptr< core::Tensor > image
bool has_colors
math::float4 color
pcl::PointXYZ PointT
Definition: PCLCloud.h:16
static bool PrintDebug(const char *format,...)
Same as Print, but works only in Debug mode.
Definition: CVLog.cpp:153
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Definition: CVLog.cpp:133
static bool PrintVerbose(const char *format,...)
Prints out a verbose formatted message in console.
Definition: CVLog.cpp:103
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Definition: CVLog.cpp:143
static QString TimeOff()
Definition: CVTools.cpp:39
static std::string FromQString(const QString &qs)
Definition: CVTools.cpp:100
static void TimeStart()
Definition: CVTools.cpp:37
QVTKWidgetCustom * getQVtkWidget()
QVTKWidgetCustom * m_vtkWidget
virtual void setViewMatrix(const ccGLMatrixd &viewMat, int viewport=0) override
PclUtils::ImageVisPtr m_visualizer2D
virtual void getProjectionMatrix(double *projArray, int viewport=0) override
void getDataAxesGridProperties(const QString &viewID, AxesGridProperties &props, int viewport=0) const override
Get Data Axes Grid properties (Unified Interface)
virtual void transformCameraView(const ccGLMatrixd &viewMat) override
virtual QImage renderToImage(int zoomFactor=1, bool renderOverlayItems=false, bool silent=false, int viewport=0) override
bool isCameraOrientationWidgetShown() const override
virtual void setParallelScale(double scale, int viewport=0) override
virtual void drawWidgets(const WIDGETS_PARAMETER &param) override
double getLightIntensity() const override
Get current Light Kit intensity.
virtual void registerVisualizer(QMainWindow *widget, bool stereoMode=false) override
register visualizer callback function
virtual void updateMeshTextures(const CC_DRAW_CONTEXT &context, const ccGenericMesh *mesh) override
virtual void toggle2Dviewer(bool state) override
void ToggleCameraOrientationWidget(bool show)
Toggle Camera Orientation Widget visibility (ParaView-style)
virtual bool orientationMarkerShown() override
virtual double getParallelScale(int viewport=0) override
virtual void drawOrientedBBox(const CC_DRAW_CONTEXT &context, const ecvOrientedBBox *obb) override
virtual QString pick3DItem(int x=-1, int y=-1) override
virtual QString pickObject(double x=-1, double y=-1) override
virtual ~PCLDisplayTools() override
Destructor.
bool IsCameraOrientationWidgetShown() const
Check if Camera Orientation Widget is shown.
virtual void draw(const CC_DRAW_CONTEXT &context, const ccHObject *obj) override
PclUtils::PCLVisPtr m_visualizer3D
void toggleCameraOrientationWidget(bool show) override
virtual void transformCameraProjection(const ccGLMatrixd &projMat) override
virtual void changeEntityProperties(PROPERTY_PARAM &param) override
virtual void removeEntities(const CC_DRAW_CONTEXT &context) override
bool checkEntityNeedUpdate(std::string &viewID, const ccHObject *obj)
virtual void displayText(const CC_DRAW_CONTEXT &context) override
virtual void getViewMatrix(double *ViewArray, int viewport=0) override
virtual void drawBBox(const CC_DRAW_CONTEXT &context, const ccBBox *bbox) override
void setDataAxesGridProperties(const QString &viewID, const AxesGridProperties &props, int viewport=0) override
Set Data Axes Grid properties (Unified Interface)
void setLightIntensity(double intensity) override
Set global light intensity (ParaView-style) Directly modifies the renderer's default light intensity.
virtual void changeOpacity(double opacity, const std::string &viewID, int viewport=0) override
virtual bool hideShowEntities(const CC_DRAW_CONTEXT &context) override
virtual void toggleOrientationMarker(bool state) override
virtual QString pick2DLabel(int x, int y) override
Container widget for vtk.
void transformCameraProjection(const double *projMat)
void transformCameraView(const double *viewMat)
void initVtk(vtkSmartPointer< vtkRenderWindowInteractor > interactor, bool useVBO=false)
void SetRenderWindow(vtkRenderWindow *win)
Type y
Definition: CVGeom.h:137
Type x
Definition: CVGeom.h:137
Type z
Definition: CVGeom.h:137
CC to PCL cloud converter.
Definition: cc2sm.h:43
PCLCloud::Ptr getPointNormals() const
Definition: cc2sm.cpp:307
PCLCloud::Ptr getAsSM(std::list< std::string > &requested_fields) const
Definition: cc2sm.cpp:607
PCLPolygon::Ptr getPclPolygon(ccPolyline *polyline) const
Definition: cc2sm.cpp:1538
unsigned getvisibilityNum() const
Definition: cc2sm.cpp:111
PCLMesh::Ptr getPclMesh(ccGenericMesh *mesh)
Definition: cc2sm.cpp:894
PCLTextureMesh::Ptr getPclTextureMesh(ccGenericMesh *mesh)
Definition: cc2sm.cpp:1375
Bounding box structure.
Definition: ecvBBox.h:25
virtual bool colorsShown() const
Returns whether colors are shown or not.
virtual bool sfShown() const
Returns whether active scalar field is visible.
virtual bool isColorOverridden() const
virtual bool isRedraw() const
Returns whether entity is to be redraw.
virtual const ecvColor::Rgb & getTempColor() const
Returns current temporary (unique) color.
T * data()
Returns a pointer to internal data.
Double version of ccGLMatrixTpl.
Definition: ecvGLMatrix.h:56
Generic mesh interface.
virtual bool materialsShown() const
Sets whether textures/material should be displayed or not.
virtual bool hasTextures() const =0
Returns whether textures are available for this mesh.
virtual const ccMaterialSet * getMaterialSet() const =0
virtual bool hasMaterials() const =0
ccBBox getOwnBB(bool withGLFeatures=false) override
Returns the entity's own bounding-box.
static ccPolyline * ToPolyline(ccHObject *obj)
Converts current object to ccPolyline (if possible)
static ccImage * ToImage(ccHObject *obj)
static cloudViewer::geometry::LineSet * ToLineSet(ccHObject *obj)
static ccGenericMesh * ToGenericMesh(ccHObject *obj)
Converts current object to ccGenericMesh (if possible)
static ccSensor * ToSensor(ccHObject *obj)
Converts current object to ccSensor (if possible)
static ccPointCloud * ToPointCloud(ccHObject *obj, bool *isLockedVertices=nullptr)
Converts current object to 'equivalent' ccPointCloud.
Hierarchical CLOUDVIEWER Object.
Definition: ecvHObject.h:25
QString getViewId() const
Definition: ecvHObject.h:225
Generic image.
Definition: ecvImage.h:19
Mesh (triangle) material.
Triangular mesh.
Definition: ecvMesh.h:35
virtual QString getName() const
Returns object name.
Definition: ecvObject.h:72
bool isA(CV_CLASS_ENUM type) const
Definition: ecvObject.h:131
bool isKindOf(CV_CLASS_ENUM type) const
Definition: ecvObject.h:128
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
int getCurrentDisplayedScalarFieldIndex() const
Returns the currently displayed scalar field index (or -1 if none)
Colored polyline.
Definition: ecvPolyline.h:24
bool is2DMode() const
Returns whether the polyline is considered as 2D or 3D.
Definition: ecvPolyline.h:63
const ecvColor::Rgb & getColor() const
Returns the polyline color.
Definition: ecvPolyline.h:99
Generic sensor interface.
Definition: ecvSensor.h:27
const Vector3Tpl< T > & maxCorner() const
Returns max corner (const)
Definition: BoundingBox.h:156
const Vector3Tpl< T > & minCorner() const
Returns min corner (const)
Definition: BoundingBox.h:154
unsigned getNumberOfScalarFields() const
Returns the number of associated (and active) scalar fields.
bool isClosed() const
Returns whether the polyline is closed or not.
Definition: Polyline.h:26
unsigned size() const override
Returns the number of points.
const CCVector3 * getPoint(unsigned index) const override
Returns the ith point.
LineSet define a sets of lines in 3D. A typical application is to display the point cloud corresponde...
Definition: LineSet.h:29
bool HasColors() const
Returns true if the objects lines contains colors.
Definition: LineSet.h:85
RGB color structure.
Definition: ecvColorTypes.h:49
static bool USE_2D
static void SetCurrentScreen(QWidget *widget)
static void DrawWidgets(const WIDGETS_PARAMETER &param, bool update=false)
static void SetMainScreen(QWidget *widget)
static QFont GetLabelDisplayFont()
static void GetContext(CC_DRAW_CONTEXT &CONTEXT)
Returns context information.
@ ECV_COLOR_PROPERTY
@ ECV_SHADING_PROPERTY
@ ECV_POINTSSIZE_PROPERTY
@ ECV_OPACITY_PROPERTY
@ ECV_LINEWITH_PROPERTY
@ WIDGET_RECTANGLE_2D
@ WIDGET_CAPTION
@ WIDGET_IMAGE
@ WIDGET_TRIANGLE_2D
@ WIDGET_POINTS_2D
@ WIDGET_COORDINATE
@ WIDGET_LINE_3D
@ WIDGET_SPHERE
@ WIDGET_T2D
@ WIDGET_SCALAR_BAR
@ WIDGET_POLYLINE
@ WIDGET_POLYLINE_2D
@ WIDGET_BBOX
@ WIDGET_CIRCLE_2D
@ WIDGET_LINE_2D
@ ECV_LINES_2D
@ ECV_POLYLINE_2D
@ ECV_CAPTION
@ ECV_IMAGE
@ ECV_LINES_3D
@ ECV_TEXT2D
@ ECV_TRIANGLE_2D
@ ECV_MESH
@ ECV_SHAPE
@ ECV_CIRCLE_2D
@ ECV_RECTANGLE_2D
@ ECV_MARK_POINT
@ ECV_POINT_CLOUD
ImGuiContext * context
Definition: Window.cpp:76
normal_z y
normal_z x
@ SENSOR
Definition: CVTypes.h:116
@ MESH
Definition: CVTypes.h:105
@ IMAGE
Definition: CVTypes.h:114
@ POINT_CLOUD
Definition: CVTypes.h:104
@ POLY_LINE
Definition: CVTypes.h:112
@ SUB_MESH
Definition: CVTypes.h:106
@ LINESET
Definition: CVTypes.h:152
Rgb FromRgbafToRgb(const Rgbaf &color)
Conversion from Rgbaf.
constexpr Rgb green(0, MAX, 0)
Rgbf FromRgb(const Rgb &color)
static ecvColor::Rgbf TransFormRGB(const ecvColor::Rgb &col)
Definition: ecvTools.h:53
Eigen::Array< unsigned char, 3, 1 > Vector3ub
Definition: image_viewer.h:32
Data Axes Grid properties structure Encapsulates all properties for vtkCubeAxesActor configuration.
CCVector3 lineEd
CCVector3 lineSt
ecvColor::Rgb lineColor
PointCoordinateType lineWidth
unsigned char pointSize
ENTITY_TYPE entityType
ecvColor::Rgb color
PROPERTY_MODE property
SHADING_MODE shadingMode
QString viewId
Display scalar field (prioritary on colors)
LineWidget lineWidget
ecvColor::Rgbaf color
CC_DRAW_CONTEXT context
WIDGETS_TYPE type
ccHObject * entity
Display context.
glDrawParams drawParam
CCVector3d textPos
bool showNorms
Display normals.
bool showSF
Display scalar field (prioritary on colors)