What’s the difference between deep copy and shallow copy in vtkPolyData?
We can find an answer after reading the two interface’s implementation.
ShallowCopy just changes the pointer pointing, two vtkPolydata objects share the individual elements.
DeepCopy
makes the current polydata have own points and cells, it copies every element.
void vtkPolyData::ShallowCopy(vtkDataObject *dataObject)
{
vtkPolyData *polyData = vtkPolyData::SafeDownCast(dataObject);
if (this == polyData)
return;
if ( polyData != nullptr )
{
this->SetVerts(polyData->GetVerts());
this->SetLines(polyData->GetLines());
this->SetPolys(polyData->GetPolys());
this->SetStrips(polyData->GetStrips());
// I do not know if this is correct but.
if (this->Cells)
{
this->Cells->UnRegister(this);
}
this->Cells = polyData->Cells;
if (this->Cells)
{
this->Cells->Register(this);
}
if (this->Links)
{
this->Links->Delete();
}
this->Links = polyData->Links;
if (this->Links)
{
this->Links->Register(this);
}
}
// Do superclass
this->vtkPointSet::ShallowCopy(dataObject);
}
//----------------------------------------------------------------------------
void vtkPolyData::DeepCopy(vtkDataObject *dataObject)
{
// Do superclass
// We have to do this BEFORE we call BuildLinks, else there are no points
// to build the links on (the parent DeepCopy copies the points)
this->vtkPointSet::DeepCopy(dataObject);
vtkPolyData *polyData = vtkPolyData::SafeDownCast(dataObject);
if ( polyData != nullptr )
{
vtkCellArray *ca;
ca = vtkCellArray::New();
ca->DeepCopy(polyData->GetVerts());
this->SetVerts(ca);
ca->Delete();
ca = vtkCellArray::New();
ca->DeepCopy(polyData->GetLines());
this->SetLines(ca);
ca->Delete();
ca = vtkCellArray::New();
ca->DeepCopy(polyData->GetPolys());
this->SetPolys(ca);
ca->Delete();
ca = vtkCellArray::New();
ca->DeepCopy(polyData->GetStrips());
this->SetStrips(ca);
ca->Delete();
if ( this->Cells )
{
this->Cells->UnRegister(this);
this->Cells = nullptr;
}
if (polyData->Cells)
{
this->BuildCells();
}
if ( this->Links )
{
this->Links->UnRegister(this);
this->Links = nullptr;
}
if (polyData->Links)
{
this->BuildLinks();
}
}
}
Test code:
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(diff)
find_package( VTK REQUIRED )
include( ${VTK_USE_FILE} )
add_executable(${PROJECT_NAME} "main.cpp")
target_link_libraries( ${PROJECT_NAME} ${VTK_LIBRARIES} )
main.cpp
#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkConeSource.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkLight.h>
#include <vtkCamera.h>
#include <vtkActor2D.h>
#include <vtkLineSource.h>
#include <vtkAppendPolyData.h>
#include <vtkPointData.h>
#include <vtkFloatArray.h>
#include <vtkQuadricDecimation.h>
#include <vtkTriangleFilter.h>
#include <vtkPlaneSource.h>
using namespace std;
int main()
{
vtkPolyData *leftPolydata = vtkPolyData::New();
vtkPolyData *rightPolydata = vtkPolyData::New();
int i;
static float x[8][3]={{0,0,0}, {1,0,0}, {1,1,0}, {0,1,0},
{0,0,1}, {1,0,1}, {1,1,1}, {0,1,1}};
static vtkIdType pts[6][4]={{0,1,2,3}, {4,5,6,7}, {0,1,5,4},
{1,2,6,5}, {2,3,7,6}, {3,0,4,7}};
vtkPoints *points = vtkPoints::New();
vtkCellArray *polys = vtkCellArray::New();
vtkFloatArray *scalars = vtkFloatArray::New();
// Load the point, cell, and data attributes.
for (i=0; i<8; i++) points->InsertPoint(i,x[i]);
for (i=0; i<6; i++) polys->InsertNextCell(4,pts[i]);
for (i=0; i<8; i++) scalars->InsertTuple1(i,i);
leftPolydata->SetPoints(points);
leftPolydata->SetPolys(polys);
leftPolydata->GetPointData()->SetScalars(scalars);
rightPolydata->ShallowCopy( leftPolydata );
scalars->Initialize();
for (i=0; i<8; i++) scalars->InsertTuple1(i,0);
leftPolydata->GetPointData()->SetScalars( scalars );
leftPolydata->Modified();
points->Delete();
polys->Delete();
scalars->Delete();
vtkSmartPointer<vtkPolyDataMapper> leftMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
leftMapper->SetInputData( leftPolydata );
vtkSmartPointer<vtkActor> leftActor =
vtkSmartPointer<vtkActor>::New();
leftActor->SetMapper( leftMapper );
// Define viewport ranges
// (xmin, ymin, xmax, ymax) left-top and right-bottom point
double leftViewport[4] = {0.0, 0.0, 0.5, 1.0};
double rightViewport[4] = {0.5, 0.0, 1.0, 1.0};
// Setup renderers
vtkSmartPointer<vtkRenderer> leftRenderer =
vtkSmartPointer<vtkRenderer>::New();
leftRenderer->SetViewport(leftViewport);
leftRenderer->SetBackground(0, 0, 0);
vtkSmartPointer<vtkRenderer> rightRenderer =
vtkSmartPointer<vtkRenderer>::New();
rightRenderer->SetViewport(rightViewport);
rightRenderer->SetBackground(0, 0, 0);
leftRenderer->AddActor( leftActor );
vtkSmartPointer<vtkPolyDataMapper> rightMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
rightMapper->SetInputData( rightPolydata );
rightPolydata->FastDelete();
vtkSmartPointer<vtkActor> rightActor =
vtkSmartPointer<vtkActor>::New();
rightActor->SetMapper( rightMapper );
rightRenderer->AddActor( rightActor );
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
leftRenderer->SetActiveCamera( camera );
rightRenderer->SetActiveCamera( camera );
leftRenderer->ResetCamera();
rightRenderer->ResetCamera();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->SetSize(600, 300);
renderWindow->AddRenderer( leftRenderer );
renderWindow->AddRenderer( rightRenderer );
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow( renderWindow );
renderWindow->Render();
renderWindowInteractor->Start();
return 0;
}
If we change the scalar for left polydata, right polydata is also changed because it is created by ShallowCopy.
We can see the different results if the right polydata is created by DeepCopy.
//rightPolydata->ShallowCopy( leftPolydata );
rightPolydata->DeepCopy( leftPolydata );