1 /*M/////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4 // 5 // By downloading, copying, installing or using the software you agree to this license. 6 // If you do not agree to this license, do not download, install, 7 // copy or use the software. 8 // 9 // 10 // License Agreement 11 // For Open Source Computer Vision Library 12 // 13 // Copyright (C) 2013, OpenCV Foundation, all rights reserved. 14 // Third party copyrights are property of their respective owners. 15 // 16 // Redistribution and use in source and binary forms, with or without modification, 17 // are permitted provided that the following conditions are met: 18 // 19 // * Redistribution's of source code must retain the above copyright notice, 20 // this list of conditions and the following disclaimer. 21 // 22 // * Redistribution's in binary form must reproduce the above copyright notice, 23 // this list of conditions and the following disclaimer in the documentation 24 // and/or other materials provided with the distribution. 25 // 26 // * The name of the copyright holders may not be used to endorse or promote products 27 // derived from this software without specific prior written permission. 28 // 29 // This software is provided by the copyright holders and contributors "as is" and 30 // any express or implied warranties, including, but not limited to, the implied 31 // warranties of merchantability and fitness for a particular purpose are disclaimed. 32 // In no event shall the Intel Corporation or contributors be liable for any direct, 33 // indirect, incidental, special, exemplary, or consequential damages 34 // (including, but not limited to, procurement of substitute goods or services; 35 // loss of use, data, or profits; or business interruption) however caused 36 // and on any theory of liability, whether in contract, strict liability, 37 // or tort (including negligence or otherwise) arising in any way out of 38 // the use of this software, even if advised of the possibility of such damage. 39 // 40 // Authors: 41 // * Ozan Tonkal, ozantonkal (at) gmail.com 42 // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com 43 // 44 //M*/ 45 46 #include "precomp.hpp" 47 48 /////////////////////////////////////////////////////////////////////////////////////////////// 49 /// Point Cloud Widget implementation 50 51 cv::viz::WCloud::WCloud(InputArray cloud, InputArray colors) 52 { 53 WCloud cloud_widget(cloud, colors, cv::noArray()); 54 *this = cloud_widget; 55 } 56 57 cv::viz::WCloud::WCloud(InputArray cloud, const Color &color) 58 { 59 WCloud cloud_widget(cloud, Mat(cloud.size(), CV_8UC3, color)); 60 *this = cloud_widget; 61 } 62 63 cv::viz::WCloud::WCloud(InputArray cloud, const Color &color, InputArray normals) 64 { 65 WCloud cloud_widget(cloud, Mat(cloud.size(), CV_8UC3, color), normals); 66 *this = cloud_widget; 67 } 68 69 cv::viz::WCloud::WCloud(cv::InputArray cloud, cv::InputArray colors, cv::InputArray normals) 70 { 71 CV_Assert(!cloud.empty() && !colors.empty()); 72 73 vtkSmartPointer<vtkCloudMatSource> cloud_source = vtkSmartPointer<vtkCloudMatSource>::New(); 74 cloud_source->SetColorCloudNormals(cloud, colors, normals); 75 cloud_source->Update(); 76 77 vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); 78 VtkUtils::SetInputData(mapper, cloud_source->GetOutput()); 79 mapper->SetScalarModeToUsePointData(); 80 mapper->ImmediateModeRenderingOff(); 81 mapper->SetScalarRange(0, 255); 82 mapper->ScalarVisibilityOn(); 83 84 vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); 85 actor->GetProperty()->SetInterpolationToFlat(); 86 actor->GetProperty()->BackfaceCullingOn(); 87 actor->SetMapper(mapper); 88 89 WidgetAccessor::setProp(*this, actor); 90 91 } 92 93 94 template<> cv::viz::WCloud cv::viz::Widget::cast<cv::viz::WCloud>() 95 { 96 Widget3D widget = this->cast<Widget3D>(); 97 return static_cast<WCloud&>(widget); 98 } 99 100 /////////////////////////////////////////////////////////////////////////////////////////////// 101 /// Painted Cloud Widget implementation 102 103 cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud) 104 { 105 vtkSmartPointer<vtkCloudMatSource> cloud_source = vtkSmartPointer<vtkCloudMatSource>::New(); 106 cloud_source->SetCloud(cloud); 107 cloud_source->Update(); 108 109 Vec6d bounds(cloud_source->GetOutput()->GetPoints()->GetBounds()); 110 111 vtkSmartPointer<vtkElevationFilter> elevation = vtkSmartPointer<vtkElevationFilter>::New(); 112 elevation->SetInputConnection(cloud_source->GetOutputPort()); 113 elevation->SetLowPoint(bounds[0], bounds[2], bounds[4]); 114 elevation->SetHighPoint(bounds[1], bounds[3], bounds[5]); 115 elevation->SetScalarRange(0.0, 1.0); 116 elevation->Update(); 117 118 vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); 119 VtkUtils::SetInputData(mapper, vtkPolyData::SafeDownCast(elevation->GetOutput())); 120 mapper->ImmediateModeRenderingOff(); 121 mapper->ScalarVisibilityOn(); 122 mapper->SetColorModeToMapScalars(); 123 124 vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); 125 actor->GetProperty()->SetInterpolationToFlat(); 126 actor->GetProperty()->BackfaceCullingOn(); 127 actor->SetMapper(mapper); 128 129 WidgetAccessor::setProp(*this, actor); 130 } 131 132 cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud, const Point3d& p1, const Point3d& p2) 133 { 134 vtkSmartPointer<vtkCloudMatSource> cloud_source = vtkSmartPointer<vtkCloudMatSource>::New(); 135 cloud_source->SetCloud(cloud); 136 137 vtkSmartPointer<vtkElevationFilter> elevation = vtkSmartPointer<vtkElevationFilter>::New(); 138 elevation->SetInputConnection(cloud_source->GetOutputPort()); 139 elevation->SetLowPoint(p1.x, p1.y, p1.z); 140 elevation->SetHighPoint(p2.x, p2.y, p2.z); 141 elevation->SetScalarRange(0.0, 1.0); 142 elevation->Update(); 143 144 vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); 145 VtkUtils::SetInputData(mapper, vtkPolyData::SafeDownCast(elevation->GetOutput())); 146 mapper->ImmediateModeRenderingOff(); 147 mapper->ScalarVisibilityOn(); 148 mapper->SetColorModeToMapScalars(); 149 150 vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); 151 actor->GetProperty()->SetInterpolationToFlat(); 152 actor->GetProperty()->BackfaceCullingOn(); 153 actor->SetMapper(mapper); 154 155 WidgetAccessor::setProp(*this, actor); 156 } 157 158 cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud, const Point3d& p1, const Point3d& p2, const Color& c1, const Color c2) 159 { 160 vtkSmartPointer<vtkCloudMatSource> cloud_source = vtkSmartPointer<vtkCloudMatSource>::New(); 161 cloud_source->SetCloud(cloud); 162 163 vtkSmartPointer<vtkElevationFilter> elevation = vtkSmartPointer<vtkElevationFilter>::New(); 164 elevation->SetInputConnection(cloud_source->GetOutputPort()); 165 elevation->SetLowPoint(p1.x, p1.y, p1.z); 166 elevation->SetHighPoint(p2.x, p2.y, p2.z); 167 elevation->SetScalarRange(0.0, 1.0); 168 elevation->Update(); 169 170 Color vc1 = vtkcolor(c1), vc2 = vtkcolor(c2); 171 vtkSmartPointer<vtkColorTransferFunction> color_transfer = vtkSmartPointer<vtkColorTransferFunction>::New(); 172 color_transfer->SetColorSpaceToRGB(); 173 color_transfer->AddRGBPoint(0.0, vc1[0], vc1[1], vc1[2]); 174 color_transfer->AddRGBPoint(1.0, vc2[0], vc2[1], vc2[2]); 175 color_transfer->SetScaleToLinear(); 176 color_transfer->Build(); 177 178 //if in future some need to replace color table with real scalars, then this can be done usine next calls: 179 //vtkDataArray *float_scalars = vtkPolyData::SafeDownCast(elevation->GetOutput())->GetPointData()->GetArray("Elevation"); 180 //vtkSmartPointer<vtkPolyData> polydata = cloud_source->GetOutput(); 181 //polydata->GetPointData()->SetScalars(color_transfer->MapScalars(float_scalars, VTK_COLOR_MODE_DEFAULT, 0)); 182 183 vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); 184 VtkUtils::SetInputData(mapper, vtkPolyData::SafeDownCast(elevation->GetOutput())); 185 mapper->ImmediateModeRenderingOff(); 186 mapper->ScalarVisibilityOn(); 187 mapper->SetColorModeToMapScalars(); 188 mapper->SetLookupTable(color_transfer); 189 190 vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); 191 actor->GetProperty()->SetInterpolationToFlat(); 192 actor->GetProperty()->BackfaceCullingOn(); 193 actor->SetMapper(mapper); 194 195 WidgetAccessor::setProp(*this, actor); 196 } 197 198 template<> cv::viz::WPaintedCloud cv::viz::Widget::cast<cv::viz::WPaintedCloud>() 199 { 200 Widget3D widget = this->cast<Widget3D>(); 201 return static_cast<WPaintedCloud&>(widget); 202 } 203 204 /////////////////////////////////////////////////////////////////////////////////////////////// 205 /// Cloud Collection Widget implementation 206 207 cv::viz::WCloudCollection::WCloudCollection() 208 { 209 vtkSmartPointer<vtkAppendPolyData> append_filter = vtkSmartPointer<vtkAppendPolyData>::New(); 210 211 vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); 212 mapper->SetInputConnection(append_filter->GetOutputPort()); 213 mapper->SetScalarModeToUsePointData(); 214 mapper->ImmediateModeRenderingOff(); 215 mapper->SetScalarRange(0, 255); 216 mapper->ScalarVisibilityOn(); 217 218 vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New(); 219 actor->SetNumberOfCloudPoints(1); 220 actor->GetProperty()->SetInterpolationToFlat(); 221 actor->GetProperty()->BackfaceCullingOn(); 222 actor->SetMapper(mapper); 223 224 WidgetAccessor::setProp(*this, actor); 225 } 226 227 void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, const Affine3d &pose) 228 { 229 vtkSmartPointer<vtkCloudMatSource> source = vtkSmartPointer<vtkCloudMatSource>::New(); 230 source->SetColorCloud(cloud, colors); 231 232 vtkSmartPointer<vtkPolyData> polydata = VtkUtils::TransformPolydata(source->GetOutputPort(), pose); 233 234 vtkSmartPointer<vtkLODActor> actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); 235 CV_Assert("Correctness check." && actor); 236 237 vtkSmartPointer<vtkAlgorithm> producer = actor->GetMapper()->GetInputConnection(0, 0)->GetProducer(); 238 vtkSmartPointer<vtkAppendPolyData> append_filter = vtkAppendPolyData::SafeDownCast(producer); 239 VtkUtils::AddInputData(append_filter, polydata); 240 241 actor->SetNumberOfCloudPoints(std::max<vtkIdType>(1, actor->GetNumberOfCloudPoints() + polydata->GetNumberOfPoints()/10)); 242 } 243 244 void cv::viz::WCloudCollection::addCloud(InputArray cloud, const Color &color, const Affine3d &pose) 245 { 246 addCloud(cloud, Mat(cloud.size(), CV_8UC3, color), pose); 247 } 248 249 void cv::viz::WCloudCollection::finalize() 250 { 251 vtkSmartPointer<vtkLODActor> actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); 252 CV_Assert("Incompatible widget type." && actor); 253 254 vtkSmartPointer<vtkPolyDataMapper> mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); 255 CV_Assert("Need to add at least one cloud." && mapper); 256 257 vtkSmartPointer<vtkAlgorithm> producer = mapper->GetInputConnection(0, 0)->GetProducer(); 258 vtkSmartPointer<vtkAppendPolyData> append_filter = vtkAppendPolyData::SafeDownCast(producer); 259 append_filter->Update(); 260 261 vtkSmartPointer<vtkPolyData> polydata = append_filter->GetOutput(); 262 mapper->RemoveInputConnection(0, 0); 263 VtkUtils::SetInputData(mapper, polydata); 264 } 265 266 template<> cv::viz::WCloudCollection cv::viz::Widget::cast<cv::viz::WCloudCollection>() 267 { 268 Widget3D widget = this->cast<Widget3D>(); 269 return static_cast<WCloudCollection&>(widget); 270 } 271 272 /////////////////////////////////////////////////////////////////////////////////////////////// 273 /// Cloud Normals Widget implementation 274 275 cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, int level, double scale, const Color &color) 276 { 277 Mat cloud = _cloud.getMat(); 278 Mat normals = _normals.getMat(); 279 280 CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); 281 CV_Assert(cloud.size() == normals.size() && cloud.type() == normals.type()); 282 283 int sqlevel = (int)std::sqrt((double)level); 284 int ystep = (cloud.cols > 1 && cloud.rows > 1) ? sqlevel : 1; 285 int xstep = (cloud.cols > 1 && cloud.rows > 1) ? sqlevel : level; 286 287 vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New(); 288 points->SetDataType(cloud.depth() == CV_32F ? VTK_FLOAT : VTK_DOUBLE); 289 290 vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New(); 291 292 int s_chs = cloud.channels(); 293 int n_chs = normals.channels(); 294 int total = 0; 295 296 for(int y = 0; y < cloud.rows; y += ystep) 297 { 298 if (cloud.depth() == CV_32F) 299 { 300 const float *srow = cloud.ptr<float>(y); 301 const float *send = srow + cloud.cols * s_chs; 302 const float *nrow = normals.ptr<float>(y); 303 304 for (; srow < send; srow += xstep * s_chs, nrow += xstep * n_chs) 305 if (!isNan(srow) && !isNan(nrow)) 306 { 307 Vec3f endp = Vec3f(srow) + Vec3f(nrow) * (float)scale; 308 309 points->InsertNextPoint(srow); 310 points->InsertNextPoint(endp.val); 311 312 lines->InsertNextCell(2); 313 lines->InsertCellPoint(total++); 314 lines->InsertCellPoint(total++); 315 } 316 } 317 else 318 { 319 const double *srow = cloud.ptr<double>(y); 320 const double *send = srow + cloud.cols * s_chs; 321 const double *nrow = normals.ptr<double>(y); 322 323 for (; srow < send; srow += xstep * s_chs, nrow += xstep * n_chs) 324 if (!isNan(srow) && !isNan(nrow)) 325 { 326 Vec3d endp = Vec3d(srow) + Vec3d(nrow) * (double)scale; 327 328 points->InsertNextPoint(srow); 329 points->InsertNextPoint(endp.val); 330 331 lines->InsertNextCell(2); 332 lines->InsertCellPoint(total++); 333 lines->InsertCellPoint(total++); 334 } 335 } 336 } 337 338 vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New(); 339 polydata->SetPoints(points); 340 polydata->SetLines(lines); 341 VtkUtils::FillScalars(polydata, color); 342 343 vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New(); 344 VtkUtils::SetInputData(mapper, polydata); 345 346 vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); 347 actor->SetMapper(mapper); 348 349 WidgetAccessor::setProp(*this, actor); 350 } 351 352 template<> cv::viz::WCloudNormals cv::viz::Widget::cast<cv::viz::WCloudNormals>() 353 { 354 Widget3D widget = this->cast<Widget3D>(); 355 return static_cast<WCloudNormals&>(widget); 356 } 357 358 /////////////////////////////////////////////////////////////////////////////////////////////// 359 /// Mesh Widget implementation 360 361 cv::viz::WMesh::WMesh(const Mesh &mesh) 362 { 363 CV_Assert(mesh.cloud.rows == 1 && mesh.polygons.type() == CV_32SC1); 364 365 vtkSmartPointer<vtkCloudMatSource> source = vtkSmartPointer<vtkCloudMatSource>::New(); 366 source->SetColorCloudNormalsTCoords(mesh.cloud, mesh.colors, mesh.normals, mesh.tcoords); 367 source->Update(); 368 369 Mat lookup_buffer(1, (int)mesh.cloud.total(), CV_32SC1); 370 int *lookup = lookup_buffer.ptr<int>(); 371 for(int y = 0, index = 0; y < mesh.cloud.rows; ++y) 372 { 373 int s_chs = mesh.cloud.channels(); 374 375 if (mesh.cloud.depth() == CV_32F) 376 { 377 const float* srow = mesh.cloud.ptr<float>(y); 378 const float* send = srow + mesh.cloud.cols * s_chs; 379 380 for (; srow != send; srow += s_chs, ++lookup) 381 if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2])) 382 *lookup = index++; 383 } 384 385 if (mesh.cloud.depth() == CV_64F) 386 { 387 const double* srow = mesh.cloud.ptr<double>(y); 388 const double* send = srow + mesh.cloud.cols * s_chs; 389 390 for (; srow != send; srow += s_chs, ++lookup) 391 if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2])) 392 *lookup = index++; 393 } 394 } 395 lookup = lookup_buffer.ptr<int>(); 396 397 vtkSmartPointer<vtkPolyData> polydata = source->GetOutput(); 398 polydata->SetVerts(0); 399 400 const int * polygons = mesh.polygons.ptr<int>(); 401 vtkSmartPointer<vtkCellArray> cell_array = vtkSmartPointer<vtkCellArray>::New(); 402 403 int idx = 0; 404 size_t polygons_size = mesh.polygons.total(); 405 for (size_t i = 0; i < polygons_size; ++idx) 406 { 407 int n_points = polygons[i++]; 408 409 cell_array->InsertNextCell(n_points); 410 for (int j = 0; j < n_points; ++j, ++idx) 411 cell_array->InsertCellPoint(lookup[polygons[i++]]); 412 } 413 cell_array->GetData()->SetNumberOfValues(idx); 414 cell_array->Squeeze(); 415 polydata->SetStrips(cell_array); 416 417 vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); 418 mapper->SetScalarModeToUsePointData(); 419 mapper->ImmediateModeRenderingOff(); 420 VtkUtils::SetInputData(mapper, polydata); 421 422 vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); 423 //actor->SetNumberOfCloudPoints(std::max(1, polydata->GetNumberOfPoints() / 10)); 424 actor->GetProperty()->SetRepresentationToSurface(); 425 actor->GetProperty()->BackfaceCullingOff(); // Backface culling is off for higher efficiency 426 actor->GetProperty()->SetInterpolationToFlat(); 427 actor->GetProperty()->EdgeVisibilityOff(); 428 actor->GetProperty()->ShadingOff(); 429 actor->SetMapper(mapper); 430 431 if (!mesh.texture.empty()) 432 { 433 vtkSmartPointer<vtkImageMatSource> image_source = vtkSmartPointer<vtkImageMatSource>::New(); 434 image_source->SetImage(mesh.texture); 435 436 vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New(); 437 texture->SetInputConnection(image_source->GetOutputPort()); 438 actor->SetTexture(texture); 439 } 440 441 WidgetAccessor::setProp(*this, actor); 442 } 443 444 cv::viz::WMesh::WMesh(InputArray cloud, InputArray polygons, InputArray colors, InputArray normals) 445 { 446 Mesh mesh; 447 mesh.cloud = cloud.getMat(); 448 mesh.colors = colors.getMat(); 449 mesh.normals = normals.getMat(); 450 mesh.polygons = polygons.getMat(); 451 *this = WMesh(mesh); 452 } 453 454 template<> CV_EXPORTS cv::viz::WMesh cv::viz::Widget::cast<cv::viz::WMesh>() 455 { 456 Widget3D widget = this->cast<Widget3D>(); 457 return static_cast<WMesh&>(widget); 458 } 459 460 461 /////////////////////////////////////////////////////////////////////////////////////////////// 462 /// Widget Merger implementation 463 464 cv::viz::WWidgetMerger::WWidgetMerger() 465 { 466 vtkSmartPointer<vtkAppendPolyData> append_filter = vtkSmartPointer<vtkAppendPolyData>::New(); 467 468 vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); 469 mapper->SetInputConnection(append_filter->GetOutputPort()); 470 mapper->SetScalarModeToUsePointData(); 471 mapper->ImmediateModeRenderingOff(); 472 mapper->SetScalarRange(0, 255); 473 mapper->ScalarVisibilityOn(); 474 475 vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); 476 actor->GetProperty()->SetInterpolationToFlat(); 477 actor->GetProperty()->BackfaceCullingOn(); 478 actor->SetMapper(mapper); 479 480 WidgetAccessor::setProp(*this, actor); 481 } 482 483 void cv::viz::WWidgetMerger::addWidget(const Widget3D& widget, const Affine3d &pose) 484 { 485 vtkActor *widget_actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(widget)); 486 CV_Assert("Widget is not 3D actor." && widget_actor); 487 488 vtkSmartPointer<vtkPolyDataMapper> widget_mapper = vtkPolyDataMapper::SafeDownCast(widget_actor->GetMapper()); 489 CV_Assert("Widget doesn't have a polydata mapper" && widget_mapper); 490 widget_mapper->Update(); 491 492 vtkSmartPointer<vtkActor> actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this)); 493 vtkSmartPointer<vtkAlgorithm> producer = actor->GetMapper()->GetInputConnection(0, 0)->GetProducer(); 494 vtkSmartPointer<vtkAppendPolyData> append_filter = vtkAppendPolyData::SafeDownCast(producer); 495 CV_Assert("Correctness check" && append_filter); 496 497 VtkUtils::AddInputData(append_filter, VtkUtils::TransformPolydata(widget_mapper->GetInput(), pose)); 498 } 499 500 void cv::viz::WWidgetMerger::finalize() 501 { 502 vtkSmartPointer<vtkActor> actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this)); 503 vtkSmartPointer<vtkAlgorithm> producer = actor->GetMapper()->GetInputConnection(0, 0)->GetProducer(); 504 vtkSmartPointer<vtkAppendPolyData> append_filter = vtkAppendPolyData::SafeDownCast(producer); 505 CV_Assert("Correctness check" && append_filter); 506 append_filter->Update(); 507 508 vtkSmartPointer<vtkPolyDataMapper> mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); 509 mapper->RemoveInputConnection(0, 0); 510 VtkUtils::SetInputData(mapper, append_filter->GetOutput()); 511 mapper->Modified(); 512 } 513 514 template<> CV_EXPORTS cv::viz::WWidgetMerger cv::viz::Widget::cast<cv::viz::WWidgetMerger>() 515 { 516 Widget3D widget = this->cast<Widget3D>(); 517 return static_cast<WWidgetMerger&>(widget); 518 } 519