vtk中点的描绘和操作在vtkPoints类中完成,调用SetPoint或InsertPoint可以设置点的vtkIdType(类似id的值)和三维坐标,2个函数的功能相同,区别在于InsertPoint先要完成点的范围检查和内存分配工作,所以速度较慢。注:这2个函数的实质是调用SetTuple或InsertTuple在数组的第i个位置赋值。适用于bit\char\data\double\float等所有array。以vtkFloatArray为例函数void vtkFloatArray::SetTuple( const vtkIdType i, const float * tuple ) [virtual] 的第一个参数是位置内容,第二个参数是数据指针。
实际操作的时候只需要考虑vtkPoints的指针就可以了,只是在点操作的时候才需要调用上述函数。
vtkCellArray中设置cell单元,调用InsertNextCell函数逐步添加新的cell,例如函数vtkCellArray::InsertNextCell ( vtkIdType npts, vtkIdType * pts ) [inline] 的第一个参数值标是cell中点的个数,第二个参数指向那些点的坐标数据。(说明:vtkIdType * pts 存储的是所包括点在points中的顺序信息,其个数当然应该和前面的npts一致。)
这里,2点可以连成一条线,三点可以得到一个面。也就是说:vtk中关于点、线、面的那些信息都是存放在cellarray中,应用时也是直接对cellarray指针进行处理,数据的写入和读取在vtkCellArray类完成。
接下来的工作是定义一个vtkPolyData,得到包括顶点、线、多边形、三角形带在内的几何结构,即三维实体。这里通过函数SetPoints设置点信息,SetPolys设置单元排列(cell array)定义多边形,cell array设置单元排列(cell array)定义线,SetStrips设置单元排列(cell array)定义三角形带strip,SetVerts设置顶点,诸如此类....
然后定义vtkPolyDataMapper,通过SetInput输入vtkPolyData信息,再定义vtkActor,调用SetMapper导入vtkPolyDataMapper,接下来vtkRenderer,调用AddActor,然后 vtkRenderWindow调用Render,再加上其他辅助的函数,就可以完整的完成输出了。
以下是在vtk中绘制四面体的函数代码:
int i;
static float x[4][3]={{0,0,0}, {1,0,0}, {0,1,0},{0,0,1}};
static vtkIdType pts[4][3]={{0,1,2},{0,1,3},{0,2,3},{1,2,3}};
//这里说明了每个pts[i]由哪几个点构成,如第一个由{0,0,0}, {1,0,0}, {0,1,0}组成。
vtkPolyData *tetrahedron = vtkPolyData::New();
vtkPoints *points = vtkPoints::New();
vtkCellArray *polys = vtkCellArray::New();
for (i=0; i<4; i++) points->InsertPoint(i,x[i]);//输入各点
for (i=0; i<4; i++) polys->InsertNextCell(3,pts[i]);//输入各cell信息
tetrahedron->SetPoints(points);
points->Delete();
tetrahedron->SetPolys(polys);
polys->Delete();
//导入信息到vtkPolyData
vtkPolyDataMapper *tetrahedronMapper = vtkPolyDataMapper::New();
tetrahedronMapper->SetInput(tetrahedron);
tetrahedronMapper->SetScalarRange(0,7);
vtkActor *tetrahedronActor = vtkActor::New();
tetrahedronActor->SetMapper(tetrahedronMapper);
vtkCamera *camera = vtkCamera::New();
camera->SetPosition(1,1,1);
camera->SetFocalPoint(0,0,0);
vtkRenderer *renderer = vtkRenderer::New();
vtkRenderWindow *renWin = vtkRenderWindow::New();
renWin->AddRenderer(renderer);
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renWin);
renderer->AddActor(tetrahedronActor);
renderer->SetActiveCamera(camera);
renderer->ResetCamera();
renderer->SetBackground(0,0,0);
renWin->SetSize(300,300);
renWin->Render();
iren->Start();
tetrahedron->Delete();
tetrahedronMapper->Delete();
tetrahedronActor->Delete();
camera->Delete();
renderer->Delete();
renWin->Delete();
iren->Delete();
vtk是通过YYSTYPE结构来存放vrml相关信息的,YYSTYPE的定义如下:
typedef union {
char *string;
float sffloat;
vtkPoints *vec3f;
vtkIdTypeArray *mfint32;
int sfint;
} YYSTYPE;
vtk中导入vrml的主要工作是在yyparse中完成的,我们关心的是yylval,它是定义的YYSTYPE类型指针。下段代码就是通过该指针,设置了各标量位置的颜色。yylval的一些细节目前还没有搞清楚....
{
vtkCellArray *cells;
int index, j;
vtkIdType *pts=0;
vtkIdType npts;
vtkPolyData *pd = (vtkPolyData *)this->CurrentMapper->GetInput();
if (pd->GetNumberOfPolys() > 0)
cells = pd->GetPolys();
else
cells = pd->GetLines();
cells->InitTraversal();
index = 0;j = 0;
cells->GetNextCell(npts, pts);
for (int i=0;i <= yylval.mfint32->GetMaxId();i++)
{
if (yylval.mfint32->GetValue(index) == -1)
{
cells->GetNextCell(npts, pts);
// Pass by the -1
index++;
j = 0;
}
else
{
// Redirect color into scalar position
this->CurrentScalars->SetComponent(pts[j++], 0,
yylval.mfint32->GetValue(index++));
}
}
}
从3ds提取点线面信息的方法:
在我们读3ds文件的时候,先是由this->FileFD = fopen (this->FileName, "rb")打开文件,然后程序调用Read3DS,Read3DS再调用parse_3ds_file解析文件....
vtk3DSImporter类包括有
vtk3DSOmniLight *OmniList;
vtk3DSSpotLight *SpotLightList;
vtk3DSCamera *CameraList;
vtk3DSMesh *MeshList;
vtk3DSMaterial *MaterialList;
vtk3DSMatProp *MatPropList;
由vtk3DSMesh指针就可以得到我们希望得到的那些关于点、线、面的信息,因此可以按照
文件->vtk3DSImporter指针->vtk3DSMesh指针(包含相关信息)
->aMapper,aStripper,aNormal,face,aCellArray,aPoints,aPolyData
的顺序得到相关数据。
下面是导入actor到renderer的函数,从中可以清晰的看到vtk中数据是如何处理的
步骤:从MeshList提取mesh->从mesh创建actor->添加actor到renderer
注释:1、mesh结构包含有aMapper,aStripper,aNormal,face, aCellArray,aPoints,aPolyData等等,这些就是我们希望得到的那些信息。
2、GeneratePolyData:从mesh到vtkPolyData
从mesh结构提取face,aCellArray,aPoints,aPolyData保存所需要的信息到
vtk3DSFace *face;
vtkCellArray *triangles;
vtkPoints *vertices;
vtkPolyData *polyData;
最后通过调用SetPolys 、SetPoints函数,返回包括有完整信息的vtkPolyData指针。
polyData->SetPolys (triangles);
polyData->SetPoints (vertices);
3、下面是ImportActors函数和GeneratePolyData 函数的代码。
void vtk3DSImporter::ImportActors (vtkRenderer *renderer)
{
vtk3DSMatProp *material;
vtk3DSMesh *mesh;
vtkStripper *polyStripper;
vtkPolyDataNormals *polyNormals;
vtkPolyDataMapper *polyMapper;
vtkPolyData *polyData;
vtkActor *actor;
// walk the list of meshes, creating actors
for (mesh = this->MeshList; mesh != (vtk3DSMesh *) NULL;
mesh = (vtk3DSMesh *) mesh->next)
{
if (mesh->faces == 0)
{
vtkWarningMacro (<< "part " << mesh->name << " has zero faces... skipping\n");
continue;
}
polyData = this->GeneratePolyData (mesh);
mesh->aMapper = polyMapper = vtkPolyDataMapper::New ();
mesh->aStripper = polyStripper = vtkStripper::New ();
// if ComputeNormals is on, insert a vtkPolyDataNormals filter
if (this->ComputeNormals)
{
mesh->aNormals = polyNormals = vtkPolyDataNormals::New ();
polyNormals->SetInput (polyData);
polyStripper->SetInput (polyNormals->GetOutput ());
}
else
{
polyStripper->SetInput (polyData);
}
polyMapper->SetInput (polyStripper->GetOutput ());
vtkDebugMacro (<< "Importing Actor: " << mesh->name);
mesh->anActor = actor = vtkActor::New ();
actor->SetMapper (polyMapper);
material = (vtk3DSMatProp *)VTK_LIST_FIND(this->MatPropList, mesh->mtl[0]->name);
actor->SetProperty (material->aProperty);
renderer->AddActor (actor);
}
}
vtkPolyData *vtk3DSImporter::GeneratePolyData (vtk3DSMesh *mesh)
{
int i;
vtk3DSFace *face;
vtkCellArray *triangles;
vtkPoints *vertices;
vtkPolyData *polyData;
face = mesh->face;
mesh->aCellArray = triangles = vtkCellArray::New ();
triangles->Allocate(mesh->faces * 3);
for (i = 0; i < mesh->faces; i++, face++)
{
triangles->InsertNextCell (3);
triangles->InsertCellPoint (face->a);
triangles->InsertCellPoint (face->b);
triangles->InsertCellPoint (face->c);
}
mesh->aPoints = vertices = vtkPoints::New ();
vertices->Allocate(mesh->vertices);
for (i = 0; i < mesh->vertices; i++)
{
vertices->InsertPoint (i, (float *) mesh->vertex[i]);
}
mesh->aPolyData = polyData = vtkPolyData::New ();
polyData->SetPolys (triangles);
polyData->SetPoints (vertices);
return polyData;
}