VTK多个多边形数据的合并 - vtkAppendPolyData

vtkAppendPolyData

【简介】

该类是一个滤波器,主要的作用就是将多个多边形数据集扩展为单个的多边形数据集(应该说是多面体更加合适)。所有的几何信息都会被提取,但是点、单元属性(标量、向量、法线)的提取和扩展需要每个数据集有这个点或者单元属性,例如 如果一个数据集有点标量信息(如权重)而另一个数据集没有这个点的标量信息,那个这个点的标量信息不会被扩展。


【类继承】


【示例】

#include <vtkVersion.h>
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkSphereSource.h>
#include <vtkConeSource.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkCleanPolyData.h>
#include <vtkAppendPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>

int main(int argc, char *argv[])
{
	vtkSmartPointer<vtkPolyData> input1 =
		vtkSmartPointer<vtkPolyData>::New();
	vtkSmartPointer<vtkPolyData> input2 =
		vtkSmartPointer<vtkPolyData>::New();

	if(argc == 1) //command line arguments not specified
	{
		vtkSmartPointer<vtkSphereSource> sphereSource =
			vtkSmartPointer<vtkSphereSource>::New();
		sphereSource->SetCenter(5,0,0);
		sphereSource->Update();

		input1->ShallowCopy(sphereSource->GetOutput());

		vtkSmartPointer<vtkConeSource> coneSource =
			vtkSmartPointer<vtkConeSource>::New();
		coneSource->Update();

		input2->ShallowCopy(coneSource->GetOutput());
	}
	else
	{
		if(argc != 3)
		{
			std::cout << "argc = " << argc << std::endl;
			std::cout << "Required arguments: File1 File2" << std::endl;
			return EXIT_FAILURE;
		}
		std::string inputFilename1 = argv[1];
		std::string inputFilename2 = argv[2];
		vtkSmartPointer<vtkXMLPolyDataReader> reader1 =
			vtkSmartPointer<vtkXMLPolyDataReader>::New();
		reader1->SetFileName(inputFilename1.c_str());
		reader1->Update();
		input1->ShallowCopy(reader1->GetOutput());

		vtkSmartPointer<vtkXMLPolyDataReader> reader2 =
			vtkSmartPointer<vtkXMLPolyDataReader>::New();
		reader2->SetFileName(inputFilename2.c_str());
		reader2->Update();
		input2->ShallowCopy(reader2->GetOutput());
	}

	//Append the two meshes 
	vtkSmartPointer<vtkAppendPolyData> appendFilter =
		vtkSmartPointer<vtkAppendPolyData>::New();
#if VTK_MAJOR_VERSION <= 5
	appendFilter->AddInputConnection(input1->GetProducerPort());
	appendFilter->AddInputConnection(input2->GetProducerPort());
#else
	appendFilter->AddInputData(input1);
	appendFilter->AddInputData(input2);
#endif
	appendFilter->Update();

	// Remove any duplicate points.
	vtkSmartPointer<vtkCleanPolyData> cleanFilter =
		vtkSmartPointer<vtkCleanPolyData>::New();
	cleanFilter->SetInputConnection(appendFilter->GetOutputPort());
	cleanFilter->Update();

	//Create a mapper and actor
	vtkSmartPointer<vtkPolyDataMapper> mapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	mapper->SetInputConnection(cleanFilter->GetOutputPort());

	vtkSmartPointer<vtkActor> actor =
		vtkSmartPointer<vtkActor>::New();
	actor->SetMapper(mapper);

	//Create a renderer, render window, and interactor
	vtkSmartPointer<vtkRenderer> renderer =
		vtkSmartPointer<vtkRenderer>::New();
	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->SetSize(900, 300);
	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);

	
	// Define viewport ranges
	// (xmin, ymin, xmax, ymax)
	double leftViewport[4] = {0.0, 0.0, 0.33, 1.0};
	double centerViewport[4] = {0.33, 0.0, 0.66, 1.0};
	double rightViewport[4] = {0.66, 0.0, 1.0, 1.0};
	vtkSmartPointer<vtkPolyDataMapper> originalMapper1 = vtkSmartPointer<vtkPolyDataMapper>::New();
	originalMapper1->SetInputData(input1);
	vtkSmartPointer<vtkPolyDataMapper> originalMapper2 = vtkSmartPointer<vtkPolyDataMapper>::New();
	originalMapper2->SetInputData(input2);
	vtkSmartPointer<vtkActor> originalActor1 = vtkSmartPointer<vtkActor>::New();
	originalActor1->SetMapper(originalMapper1);
	//originalActor1->GetProperty()->SetColor(0.6, 0.6, 0.6);
	vtkSmartPointer<vtkRenderer> originalRender1 = vtkSmartPointer<vtkRenderer>::New();
	vtkSmartPointer<vtkActor> originalActor2 = vtkSmartPointer<vtkActor>::New();
	originalActor2->SetMapper(originalMapper2);
	vtkSmartPointer<vtkRenderer> originalRender2 = vtkSmartPointer<vtkRenderer>::New();

	// Add the actors to the scene
	renderer->AddActor(actor);
	renderer->SetBackground(.3, .3, .3); // Background color dark red
	renderWindow->AddRenderer(renderer);
	renderer->SetViewport(rightViewport);
	originalRender1->AddActor(originalActor1);
	originalRender1->SetBackground(.6,.6,.6);
	renderWindow->AddRenderer(originalRender1);
	originalRender1->SetViewport(leftViewport);
	originalRender2->AddActor(originalActor2);
	originalRender2->SetBackground(.8,.8,.8);
	renderWindow->AddRenderer(originalRender2);
	originalRender2->SetViewport(centerViewport);
	//Render and interact
	renderWindow->Render();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}
结果图:


【源码分析】

看这个类的源代码没有多长一千行都不到


① RequestData() 为什么看这个函数,是因为vtkAppendPolyData这个类继承自vtkPolyDataAlgorithm,之前我也分析过这个类,这个类的子类在输入正确的数据之后调用Update(),默认的执行过程中入口就是这个函数,主要实现类的主要功能(可以这么讲)。

// This method is much too long, and has to be broken up!
// Append data sets into single polygonal data set.
int vtkAppendPolyData::RequestData(vtkInformation *vtkNotUsed(request),
	vtkInformationVector **inputVector,
	vtkInformationVector *outputVector)
{
	// get the info object
	// get the ouptut
	vtkPolyData *output = vtkPolyData::GetData(outputVector, 0);

	int numInputs = inputVector[0]->GetNumberOfInformationObjects();
	if (numInputs == 1)
	{
		output->ShallowCopy(vtkPolyData::GetData(inputVector[0], 0));
		return 1;
	}

	vtkPolyData** inputs = new vtkPolyData*[numInputs];
	for (int idx = 0; idx < numInputs; ++idx)
	{
		inputs[idx] = vtkPolyData::GetData(inputVector[0], idx);
	}
	int retVal = this->ExecuteAppend(output, inputs, numInputs);
	delete [] inputs;
	return retVal;
}
其实代码很简单,首先获取输入输出,如果输入数据只有一个,那直接输出数据就是输入;多个输入数据时,调用  ExecuteAppend() ,需要注意的是 inputs 为一个二级指针,可以学习如何使用一个二级指针(C++ 学的没有很深,二级指针用的不熟,需要多学习)。

②  ExecuteAppend() 这个函数的代码是有点长,好在代码整洁、干净,大部分都是数据的初始化等操作,对于数据的扩充调用AppendData().

该函数的功能就是将多个多边形数据连接成一个多边形数据。

//----------------------------------------------------------------------------
int vtkAppendPolyData::ExecuteAppend(vtkPolyData* output,
	vtkPolyData* inputs[], int numInputs)
{
	int idx;
	vtkPolyData *ds;
	vtkPoints  *inPts;
	vtkPoints *newPts;
	vtkCellArray *inVerts, *newVerts;
	vtkCellArray *inLines, *newLines;
	vtkCellArray *inPolys, *newPolys;
	vtkIdType sizePolys, numPolys;
	vtkCellArray *inStrips, *newStrips;
	vtkIdType numPts, numCells;
	vtkPointData *inPD = NULL;
	vtkCellData *inCD = NULL;
	vtkPointData *outputPD = output->GetPointData();
	vtkCellData *outputCD = output->GetCellData();
	vtkDataArray *newPtScalars = NULL;
	vtkDataArray *newPtVectors = NULL;
	vtkDataArray *newPtNormals = NULL;
	vtkDataArray *newPtTCoords = NULL;
	vtkDataArray *newPtTensors = NULL;
	int i;
	vtkIdType *pts = 0;
	vtkIdType *pPolys;
	vtkIdType npts = 0;
	vtkIdType ptId, cellId;

	vtkDebugMacro(<<"Appending polydata");

	// loop over all data sets, checking to see what point data is available.
	numPts = 0;
	numCells = 0;
	sizePolys = numPolys = 0;

	int countPD=0;
	int countCD=0;

	vtkIdType numVerts = 0, numLines = 0, numStrips = 0;

	// These Field lists are very picky.  Count the number of non empty inputs
	// so we can initialize them properly.
	for (idx = 0; idx < numInputs; ++idx)
	{
		ds = inputs[idx];
		if (ds != NULL)
		{
			if ( ds->GetNumberOfPoints() > 0)
			{
				++countPD;
			}
			if (ds->GetNumberOfCells() > 0 )
			{
				++countCD;
			} // for a data set that has cells
		} // for a non NULL input
	} // for each input

	// These are used to determine which fields are available for appending
	vtkDataSetAttributes::FieldList ptList(countPD);
	vtkDataSetAttributes::FieldList cellList(countCD);

	countPD = countCD = 0;
	for (idx = 0; idx < numInputs; ++idx)
	{
		ds = inputs[idx];
		if (ds != NULL)
		{
			// Skip points and cells if there are no points.  Empty inputs may have no arrays.
			if ( ds->GetNumberOfPoints() > 0)
			{
				numPts += ds->GetNumberOfPoints();
				// Take intersection of available point data fields.
				inPD = ds->GetPointData();
				if ( countPD == 0 )
				{
					ptList.InitializeFieldList(inPD);
				}
				else
				{
					ptList.IntersectFieldList(inPD);
				}
				++countPD;
			} // for a data set that has points

			// Although we cannot have cells without points ... let's not nest.
			if (ds->GetNumberOfCells() > 0 )
			{
				// keep track of the size of the poly cell array
				if (ds->GetPolys())
				{
					sizePolys += ds->GetPolys()->GetNumberOfConnectivityEntries();
				}
				numCells += ds->GetNumberOfCells();
				// Count the cells of each type.
				// This is used to ensure that cell data is copied at the correct
				// locations in the output.
				numVerts += ds->GetNumberOfVerts();
				numLines += ds->GetNumberOfLines();
				numPolys += ds->GetNumberOfPolys();
				numStrips += ds->GetNumberOfStrips();

				inCD = ds->GetCellData();
				if ( countCD == 0 )
				{
					cellList.InitializeFieldList(inCD);
				}
				else
				{
					cellList.IntersectFieldList(inCD);
				}
				++countCD;
			} // for a data set that has cells
		} // for a non NULL input
	} // for each input

	if ( numPts < 1 || numCells < 1 )
	{
		vtkDebugMacro(<<"No data to append!");
		return 1;
	}
	this->UpdateProgress(0.10);

	// Examine the points and check if they're the same type. If not,
	// use highest (double probably), otherwise the type of the first
	// array (float no doubt). Depends on defs in vtkSetGet.h - Warning.
	int ttype, firstType=1, AllSame=1;
	int pointtype = 0;

	// Keep track of types for fast point append
	for (idx = 0; idx < numInputs; ++idx)
	{
		ds = inputs[idx];
		if (ds != NULL && ds->GetNumberOfPoints()>0)
		{
			if ( firstType )
			{
				firstType = 0;
				pointtype = ds->GetPoints()->GetData()->GetDataType();
			}
			ttype = ds->GetPoints()->GetData()->GetDataType();

			if ( ttype != pointtype )
			{
				AllSame = 0;
				vtkDebugMacro(<<"Different point data types");
			}
			pointtype = pointtype > ttype ? pointtype : ttype;
		}
	}

	// Allocate geometry/topology
	newPts = vtkPoints::New();

	// Set the desired precision for the points in the output.
	if(this->OutputPointsPrecision == vtkAlgorithm::DEFAULT_PRECISION)
	{
		newPts->SetDataType(pointtype);
	}
	else if(this->OutputPointsPrecision == vtkAlgorithm::SINGLE_PRECISION)
	{
		newPts->SetDataType(VTK_FLOAT);
	}
	else if(this->OutputPointsPrecision == vtkAlgorithm::DOUBLE_PRECISION)
	{
		newPts->SetDataType(VTK_DOUBLE);
	}

	newPts->SetNumberOfPoints(numPts);

	newVerts = vtkCellArray::New();
	newVerts->Allocate(numCells*4);

	newLines = vtkCellArray::New();
	newLines->Allocate(numCells*4);

	newStrips = vtkCellArray::New();
	newStrips->Allocate(numCells*4);

	newPolys = vtkCellArray::New();
	pPolys = newPolys->WritePointer(numPolys, sizePolys);

	if (!pPolys && sizePolys > 0)
	{
		vtkErrorMacro(<<"Memory allocation failed in append filter");
		return 0;
	}

	// These are created manually for faster execution
	// Uses the properties of the last input
	vtkDataArray *inDA=0;
	if ( ptList.IsAttributePresent(vtkDataSetAttributes::SCALARS) > -1 )
	{
		inDA=inPD->GetScalars();
		outputPD->CopyScalarsOff();
		newPtScalars = inDA->NewInstance();
		newPtScalars->SetNumberOfComponents(inDA->GetNumberOfComponents());
		newPtScalars->CopyComponentNames( inDA );
		newPtScalars->SetName(inDA->GetName());
		newPtScalars->SetNumberOfTuples(numPts);
		if (inDA->HasInformation())
		{
			newPtScalars->CopyInformation(inDA->GetInformation(),/*deep=*/1);
		}
	}
	if ( ptList.IsAttributePresent(vtkDataSetAttributes::VECTORS) > -1 )
	{
		inDA=inPD->GetVectors();
		outputPD->CopyVectorsOff();
		newPtVectors = inDA->NewInstance();
		newPtVectors->SetNumberOfComponents(inDA->GetNumberOfComponents());
		newPtVectors->CopyComponentNames( inDA );
		newPtVectors->SetName(inDA->GetName());
		newPtVectors->SetNumberOfTuples(numPts);
		if (inDA->HasInformation())
		{
			newPtVectors->CopyInformation(inDA->GetInformation(),/*deep=*/1);
		}
	}
	if ( ptList.IsAttributePresent(vtkDataSetAttributes::TENSORS) > -1 )
	{
		inDA=inPD->GetTensors();
		outputPD->CopyTensorsOff();
		newPtTensors = inDA->NewInstance();
		newPtTensors->SetNumberOfComponents(inDA->GetNumberOfComponents());
		newPtTensors->CopyComponentNames( inDA );
		newPtTensors->SetName(inDA->GetName());
		newPtTensors->SetNumberOfTuples(numPts);
		if (inDA->HasInformation())
		{
			newPtTensors->CopyInformation(inDA->GetInformation(),/*deep=*/1);
		}
	}
	if ( ptList.IsAttributePresent(vtkDataSetAttributes::NORMALS) > -1 )
	{
		inDA=inPD->GetNormals();
		outputPD->CopyNormalsOff();
		newPtNormals = inDA->NewInstance();
		newPtNormals->SetNumberOfComponents(inDA->GetNumberOfComponents());
		newPtNormals->CopyComponentNames( inDA );
		newPtNormals->SetName(inDA->GetName());
		newPtNormals->SetNumberOfTuples(numPts);
		if (inDA->HasInformation())
		{
			newPtNormals->CopyInformation(inDA->GetInformation(),/*deep=*/1);
		}
	}
	if ( ptList.IsAttributePresent(vtkDataSetAttributes::TCOORDS) > -1 )
	{
		inDA=inPD->GetTCoords();
		outputPD->CopyTCoordsOff();
		newPtTCoords = inDA->NewInstance();
		newPtTCoords->SetNumberOfComponents(inDA->GetNumberOfComponents());
		newPtTCoords->CopyComponentNames( inDA );
		newPtTCoords->SetName(inDA->GetName());
		newPtTCoords->SetNumberOfTuples(numPts);
		if (inDA->HasInformation())
		{
			newPtTCoords->CopyInformation(inDA->GetInformation(),/*deep=*/1);
		}
	}

	// Allocate the point and cell data
	outputPD->CopyAllocate(ptList,numPts);
	outputCD->CopyAllocate(cellList,numCells);

	// loop over all input sets
	vtkIdType ptOffset = 0;
	vtkIdType vertOffset = 0;
	vtkIdType linesOffset = 0;
	vtkIdType polysOffset = 0;
	vtkIdType stripsOffset = 0;
	countPD = countCD = 0;
	for (idx = 0; idx < numInputs; ++idx)
	{
		this->UpdateProgress(0.2 + 0.8*idx/numInputs);
		ds = inputs[idx];
		// this check is not necessary, but I'll put it in anyway
		if (ds != NULL)
		{
			numPts = ds->GetNumberOfPoints();
			numCells = ds->GetNumberOfCells();
			if ( numPts <= 0 && numCells <= 0 )
			{
				continue; //no input, just skip
			}

			inPD = ds->GetPointData();
			inCD = ds->GetCellData();

			inPts = ds->GetPoints();
			inVerts = ds->GetVerts();
			inLines = ds->GetLines();
			inPolys = ds->GetPolys();
			inStrips = ds->GetStrips();

			if (ds->GetNumberOfPoints() > 0)
			{
				// copy points directly
				if (AllSame)
				{
					this->AppendData(newPts->GetData(),
						inPts->GetData(), ptOffset);
				}
				else
				{
					this->AppendDifferentPoints(newPts->GetData(),
						inPts->GetData(), ptOffset);
				}
				// copy scalars directly
				if (newPtScalars)
				{
					this->AppendData(newPtScalars,inPD->GetScalars(), ptOffset);
				}
				// copy normals directly
				if (newPtNormals)
				{
					this->AppendData(newPtNormals, inPD->GetNormals(), ptOffset);
				}
				// copy vectors directly
				if (newPtVectors)
				{
					this->AppendData(newPtVectors, inPD->GetVectors(), ptOffset);
				}
				// copy tcoords directly
				if (newPtTCoords)
				{
					this->AppendData(newPtTCoords, inPD->GetTCoords() , ptOffset);
				}
				// copy tensors directly
				if (newPtTensors)
				{
					this->AppendData(newPtTensors, inPD->GetTensors(), ptOffset);
				}
				// append the remainder of the field data
				for (ptId=0; ptId < numPts; ptId++)
				{
					outputPD->CopyData(ptList,inPD,countPD,ptId,ptId+ptOffset);
				}
				++countPD;
			}


			if (ds->GetNumberOfCells() > 0)
			{
				// These are the cellIDs at which each of the cell types start.
				vtkIdType linesIndex = ds->GetNumberOfVerts();
				vtkIdType polysIndex = linesIndex + ds->GetNumberOfLines();
				vtkIdType stripsIndex = polysIndex + ds->GetNumberOfPolys();

				// cell data could be made efficient like the point data,
				// but I will wait on that.
				// copy cell data
				for (cellId=0; cellId < numCells; cellId++)
				{
					vtkIdType outCellId = 0;
					if (cellId < linesIndex)
					{
						outCellId = vertOffset;
						vertOffset++;
					}
					else if (cellId < polysIndex)
					{
						// outCellId = number of lines we already added + total number of
						// verts expected in the output.
						outCellId = linesOffset + numVerts;
						linesOffset++;
					}
					else if (cellId < stripsIndex)
					{
						// outCellId = number of polys we already added + total number of
						// verts and lines expected in the output.
						outCellId = polysOffset + numLines + numVerts;
						polysOffset++;
					}
					else
					{
						// outCellId = number of tstrips we already added + total number of
						// polys, verts and lines expected in the output.
						outCellId = stripsOffset + numPolys + numLines + numVerts;
						stripsOffset++;
					}
					outputCD->CopyData(cellList,inCD,countCD,cellId,outCellId);
				}
				++countCD;

				// copy the cells
				pPolys = this->AppendCells(pPolys, inPolys, ptOffset);

				// These other cell arrays could be made efficient like polys ...
				for (inVerts->InitTraversal(); inVerts->GetNextCell(npts,pts); )
				{
					newVerts->InsertNextCell(npts);
					for (i=0; i < npts; i++)
					{
						newVerts->InsertCellPoint(pts[i]+ptOffset);
					}
				}

				for (inLines->InitTraversal(); inLines->GetNextCell(npts,pts); )
				{
					newLines->InsertNextCell(npts);
					for (i=0; i < npts; i++)
					{
						newLines->InsertCellPoint(pts[i]+ptOffset);
					}
				}

				for (inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); )
				{
					newStrips->InsertNextCell(npts);
					for (i=0; i < npts; i++)
					{
						newStrips->InsertCellPoint(pts[i]+ptOffset);
					}
				}
			}
			ptOffset += numPts;
		}
	}

	// Update ourselves and release memory
	//
	output->SetPoints(newPts);
	newPts->Delete();

	if (newPtScalars)
	{
		output->GetPointData()->SetScalars(newPtScalars);
		newPtScalars->Delete();
	}
	if (newPtNormals)
	{
		output->GetPointData()->SetNormals(newPtNormals);
		newPtNormals->Delete();
	}
	if (newPtVectors)
	{
		output->GetPointData()->SetVectors(newPtVectors);
		newPtVectors->Delete();
	}
	if (newPtTCoords)
	{
		output->GetPointData()->SetTCoords(newPtTCoords);
		newPtTCoords->Delete();
	}
	if (newPtTensors)
	{
		output->GetPointData()->SetTensors(newPtTensors);
		newPtTensors->Delete();
	}

	if ( newVerts->GetNumberOfCells() > 0 )
	{
		output->SetVerts(newVerts);
	}
	newVerts->Delete();

	if ( newLines->GetNumberOfCells() > 0 )
	{
		output->SetLines(newLines);
	}
	newLines->Delete();

	if ( newPolys->GetNumberOfCells() > 0 )
	{
		output->SetPolys(newPolys);
	}
	newPolys->Delete();

	if ( newStrips->GetNumberOfCells() > 0 )
	{
		output->SetStrips(newStrips);
	}
	newStrips->Delete();

	// When all optimizations are complete, this squeeze will be unnecessary.
	// (But it does not seem to cost much.)
	output->Squeeze();

	return 1;
}
其实代码的注释已经很明了了,这个做个简单的总结。

  1.  循环遍历输入 inputs, 统计非空数据集中可用的点集数目 countPD,和可用的单元(cell)数目 countCD,用于申请 vtkDataSetAttributes::FieldList 列表的长度;
  2.  统计输入数据的点集、单元信息:
    • numPts: 所有多边形数据的点个数总和
    • ptList :多边形数据集的点集列表
    • sizePolys
    • numCells += ds->GetNumberOfCells();
      // Count the cells of each type.
      // This is used to ensure that cell data is copied at the correct locations in the output.
      numVerts += ds->GetNumberOfVerts();
      numLines += ds->GetNumberOfLines();
      numPolys += ds->GetNumberOfPolys();
      numStrips += ds->GetNumberOfStrips();
    • cellList :多边形数据集的Cell列表
  3.  检查所有的点的类型是否相同,不同使用最高级类型; 确认输出点newPts的数据类型
  4.  为点的不同属性初始化变量: 
    1. 数据集的属性vtkDataSetAttributes包括:
      scalars, vectors, normals, texture coordinates, tensors, global ids, pedigree ids, and field data
      标量        向量    法线             文理坐标 张量    全局ID       谱系ID(不知道)    字段数据
  5.  AppendData()、AppendCells()
③  AppendData():  同类型 vtkDataArray 的合并,vtkIdType offset: dest中最后一个点的位置或者说是已经复制到dest点的个数
void vtkAppendPolyData::AppendData(vtkDataArray *dest, vtkDataArray *src,
	vtkIdType offset)
{
	void *pSrc, *pDest;
	vtkIdType length;

	// sanity checks
	if (src->GetDataType() != dest->GetDataType())
	{
		vtkErrorMacro("Data type mismatch.");
		return;
	}
	if (src->GetNumberOfComponents() != dest->GetNumberOfComponents())   // 维度的判断
	{
		vtkErrorMacro("NumberOfComponents mismatch.");
		return;
	}
	if (src->GetNumberOfTuples() + offset > dest->GetNumberOfTuples())   // Get the number of tuples (a component group) in the array
	{
		vtkErrorMacro("Destination not big enough");
		return;
	}

	// convert from tuples to components.
	offset *= src->GetNumberOfComponents();
	length = src->GetMaxId() + 1;

	switch (src->GetDataType())
	{
		vtkTemplateMacro(
			length *= vtkAppendPolyDataGetTypeSize(static_cast<VTK_TT*>(0))
			);
	default:
		vtkErrorMacro("Unknown data type " << src->GetDataType());
	}

	pSrc  = src->GetVoidPointer(0);
	pDest = dest->GetVoidPointer(offset);

	memcpy(pDest, pSrc, length);
}
memcpy(pDest, pSrc, length);    实现内存数据的复制, pDest:目的地的地址 pSrc:数据源的地址  Length: 数据源的长度

同理不同类型的数据扩充函数

void vtkAppendPolyData::AppendDifferentPoints(vtkDataArray *dest,
vtkDataArray *src,
vtkIdType offset)

在实现部分,需要注意的就是数据源的类型,进而影响 Length 的计算


④ AppendCells()

vtkIdType *vtkAppendPolyData::AppendCells(vtkIdType *pDest, vtkCellArray *src,
	vtkIdType offset)
{
	vtkIdType *pSrc, *end, *pNum;

	if (src == NULL)
	{
		return pDest;
	}

	pSrc = src->GetPointer();
	end = pSrc + src->GetNumberOfConnectivityEntries();
	pNum = pSrc;

	while (pSrc < end)
	{
		if (pSrc == pNum)
		{
			// move cell pointer to next cell
			pNum += 1+*pSrc;
			// copy the number of cells
			*pDest++ = *pSrc++;
		}
		else
		{
			// offset the point index
			*pDest++ = offset + *pSrc++;
		}
	}

	return pDest;
}


vtkAppendFilter

【简介】

将一个或多个的数据集连接整一个单独的非结构化网格(存储空间大,计算耗时)


  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值