本文主要介绍使用使用一系列的点生成各种 PolyData 的过程。
我们首先生成螺旋曲线, 这个比较简单。 使用一些简单的数据知识就可以办到:
1 /******************************************** 2 * 描述: 3 * 构建形成线条的所有点集。 4 * 参数列表: 5 * count - 线条所在坐标三个维度的分辨率。 6 * 返回值: 7 * 线条的点集。 8 *******************************************/ 9 std::vector < vtkPoint > BuildPoints ( int count ) 10 { 11 std::vector < vtkPoint > points; 12 13 for ( int y = 0; y < count; y++ ) 14 { 15 vtkPoint point; 16 point.x = radians * cos ( y / vtkMath::Pi() ); 17 point.y = y; 18 point.z = radians * sin ( y / vtkMath::Pi() ); 19 point.radians = 3; 20 points.push_back ( point ); 21 } 22 23 return points; 24 }
有了点之后,我们把这些点连接成线。
1 /******************************************** 2 * 描述:将点连成线 3 * 参数列表: 4 * points - 点集. 5 * 返回值: 6 * 用 vtkPolyData 表示的线条。 7 *******************************************/ 8 vtkPolyData * BuildLines ( std::vector < vtkPoint > & points ) 9 { 10 vtkNew <vtkPoints> polydataPoints; 11 vtkNew < vtkCellArray > cells; 12 13 int count = points.size(); 14 for ( int i=0; i<count; i++ ) 15 { 16 polydataPoints->InsertNextPoint ( points[i].x, points[i].y, points[i].z ); 17 } 18 19 for ( int i=0; i<count-1; i++ ) 20 { 21 vtkIdType pts[2] = { i, i+1 }; 22 cells->InsertNextCell ( 2, pts ); 23 } 24 25 vtkPolyData * polyData = vtkPolyData::New (); 26 polyData->SetPoints ( polydataPoints ); 27 polyData->SetLines ( cells ); 28 29 return polyData; 30 }
然后我们就可以把这个线显示出来:如图
之后我们继续以每个点为圆心作圆。
1 vtkPolyData * BuildCircles ( std::vector < vtkPoint > & points, int resolution ) 2 { 3 std::vector < vtkPoint > circlePoints = BuildCirclePoints ( points, resolution ); 4 5 vtkNew < vtkAppendPolyData > append; 6 int count = circlePoints.size(); 7 8 for ( int i=0; i<count; i+=resolution ) 9 { 10 vtkNew < vtkPoints > vPoints; 11 vtkNew < vtkCellArray > cells; 12 13 for ( int j=0; j<resolution; j++ ) 14 { 15 int idx = i+j; 16 vPoints->InsertNextPoint ( circlePoints[idx].x, circlePoints[idx].y, circlePoints[idx].z ); 17 } 18 19 for ( int j=0; j<resolution; j++ ) 20 { 21 int n = j+1; 22 if ( n >= resolution ) 23 n = 0; 24 25 vtkIdType pts[2] = {j, n}; 26 cells->InsertNextCell ( 2, pts ); 27 } 28 29 vtkNew < vtkPolyData > polyData; 30 polyData->SetPoints ( vPoints ); 31 polyData->SetLines ( cells ); 32 append->AddInputData ( polyData ); 33 } 34 35 // 36 append->Update (); 37 vtkPolyData * retPolyData = append->GetOutput (); 38 retPolyData->Register ( NULL ); 39 40 // 41 return retPolyData; 42 }
将它返回的 retPolyData 显示出来就是下面的样子。
最后,我们只需连接上下两个圆的点,形成面片,就可以生成三维表面了。
1 /******************************************** 2 * 描述: 构建表面。 3 * 参数列表: 4 * points - 点集,每一个点都是一个圆的圆心。 5 * resolution - 圆是由一系列的线段构成, resolution 指定线段数量。 6 * 返回值: 7 * 返回所有圆构成的表面. 8 *******************************************/ 9 vtkPolyData * BuildSurface ( std::vector < vtkPoint > & points, int resolution ) 10 { 11 std::vector < vtkPoint > circlePoints = BuildCirclePoints ( points, resolution ); 12 13 vtkNew < vtkAppendPolyData > append; 14 int count = circlePoints.size() - resolution; 15 16 for ( int i=0; i<count; i+=resolution ) 17 { 18 for ( int j=0; j<resolution; j++ ) 19 { 20 vtkNew < vtkPoints > vPoints; 21 vtkNew < vtkCellArray > cells; 22 23 bool bflag = j == ( resolution-1 ); 24 25 int idx = j+i; 26 int lt = idx; 27 int rt = idx + 1; 28 int rd = rt + resolution; 29 int ld = lt + resolution; 30 31 if ( bflag ) 32 { 33 rt = i; 34 rd = i + resolution; 35 } 36 37 38 vPoints->InsertNextPoint ( circlePoints[lt].x, circlePoints[lt].y, circlePoints[lt].z ); 39 vPoints->InsertNextPoint ( circlePoints[rt].x, circlePoints[rt].y, circlePoints[rt].z ); 40 vPoints->InsertNextPoint ( circlePoints[rd].x, circlePoints[rd].y, circlePoints[rd].z); 41 vPoints->InsertNextPoint ( circlePoints[ld].x, circlePoints[ld].y, circlePoints[ld].z); 42 43 // 44 vtkNew < vtkQuad > quad; 45 for ( int c=0; c<4; c++ ) 46 { 47 quad->GetPointIds()->SetId ( c, c ); 48 } 49 cells->InsertNextCell ( quad ); 50 51 // 52 vtkNew < vtkPolyData > polyData; 53 polyData->SetPoints ( vPoints ); 54 polyData->SetPolys ( cells ); 55 append->AddInputData ( polyData ); 56 } 57 } 58 59 // 60 append->Update (); 61 vtkPolyData * retPolyData = append->GetOutput (); 62 retPolyData->Register ( NULL ); 63 64 // 65 return retPolyData; 66 }
把这里返回的 PolyData 显示出来就是下面的样子: