1 #include <vtkAutoInit.h>
2 VTK_MODULE_INIT(vtkRenderingOpenGL);
3 VTK_MODULE_INIT(vtkRenderingFreeType);
4 VTK_MODULE_INIT(vtkInteractionStyle);
5
6 #include <vtkSmartPointer.h>
7 #include <vtkSphereSource.h>
8 #include <vtkIdTypeArray.h>
9 #include <vtkSelectionNode.h>
10 #include <vtkSelection.h>
11 #include <vtkExtractSelection.h>
12 #include <vtkDataSetSurfaceFilter.h>
13 #include <vtkInformation.h>
14 #include <vtkProperty.h>
15 //生成带孔洞的网格球
16 void GenerateData(vtkSmartPointer<vtkPolyData> input)
17 {
18 vtkSmartPointer<vtkSphereSource> sphereSource =
19 vtkSmartPointer<vtkSphereSource>::New();
20 sphereSource->Update();
21
22 //提供了插入和检索值的方法,并会自动调整大小以保存新数据
23 vtkSmartPointer<vtkIdTypeArray> ids =
24 vtkSmartPointer<vtkIdTypeArray>::New();
25 ids->SetNumberOfComponents(1);
26 ids->InsertNextValue(2);
27 ids->InsertNextValue(10);
28
29 //选择树中的节,用于存储选择结果
30 vtkSmartPointer<vtkSelectionNode> selectionNode =
31 vtkSmartPointer<vtkSelectionNode>::New();
32 selectionNode->SetFieldType(vtkSelectionNode::CELL);
33 selectionNode->SetContentType(vtkSelectionNode::INDICES);
34 selectionNode->SetSelectionList(ids);
35 selectionNode->GetProperties()->Set(vtkSelectionNode::INVERSE(), 1);
36
37 vtkSmartPointer<vtkSelection> selection =
38 vtkSmartPointer<vtkSelection>::New();
39 selection->AddNode(selectionNode);
40
41 //从vtkdataset提取子集,删除操作
42 vtkSmartPointer<vtkExtractSelection> extractSelection =
43 vtkSmartPointer<vtkExtractSelection>::New();
44 extractSelection->SetInputData(0, sphereSource->GetOutput());
45 extractSelection->SetInputData(1, selection);
46 extractSelection->Update();
47
48 //vtkDataSetSurfaceFilter是更快版本的vtkgeometry滤波器
49 //但它没有一个选择范围。比vtkGeometryFilter使用更多的内存
50 //只有一个选择:输入结构类型时是否使用三角形条
51 vtkSmartPointer<vtkDataSetSurfaceFilter> surfaceFilter =
52 vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
53 surfaceFilter->SetInputConnection(extractSelection->GetOutputPort());
54 surfaceFilter->Update();
55
56 input->ShallowCopy(surfaceFilter->GetOutput());
57 }
58 #include <vtkPolyData.h>
59 #include <vtkFeatureEdges.h>
60 #include <vtkPolyDataMapper.h>
61 #include <vtkFillHolesFilter.h>
62 #include <vtkPolyDataNormals.h>
63 #include <vtkActor.h>
64 #include <vtkCamera.h>
65 #include <vtkRenderer.h>
66 #include <vtkRenderWindow.h>
67 #include <vtkRenderWindowInteractor.h>
68
69 int main()
70 {
71 vtkSmartPointer<vtkPolyData> input =
72 vtkSmartPointer<vtkPolyData>::New();
73 GenerateData(input);
74
75 vtkSmartPointer<vtkFeatureEdges> featureEdges =
76 vtkSmartPointer<vtkFeatureEdges>::New();
77 featureEdges->SetInputData(input);
78 featureEdges->BoundaryEdgesOn();
79 featureEdges->FeatureEdgesOff();
80 featureEdges->ManifoldEdgesOff();
81 featureEdges->NonManifoldEdgesOff();
82 featureEdges->Update();
83
84 int numberOfOpenEdges = featureEdges->GetOutput()->GetNumberOfCells();
85 if (numberOfOpenEdges)
86 {
87 std::cout << "该网格模型不是封闭的..." << std::endl;
88 }
89 else
90 {
91 std::cout << "该网格模型是封闭的..." << std::endl;
92 return EXIT_SUCCESS;
93 }
94 vtkSmartPointer<vtkFillHolesFilter> fillHolesFilter =
95 vtkSmartPointer<vtkFillHolesFilter>::New();
96 fillHolesFilter->SetInputData(input);
97 fillHolesFilter->Update();
98
99 vtkSmartPointer<vtkPolyDataNormals> normals =
100 vtkSmartPointer<vtkPolyDataNormals>::New();
101 normals->SetInputConnection(fillHolesFilter->GetOutputPort());
102 normals->ConsistencyOn(); //很重要,根据其他单元点的顺序调整补充点的顺序
103 normals->SplittingOff();
104 normals->Update();
105 /
106 double leftViewport[4] = { 0.0, 0.0, 0.5, 1.0 };
107 double rightViewport[4] = { 0.5, 0.0, 1.0, 1.0 };
108
109 vtkSmartPointer<vtkPolyDataMapper> originalMapper =
110 vtkSmartPointer<vtkPolyDataMapper>::New();
111 originalMapper->SetInputData(input);
112 vtkSmartPointer<vtkProperty> backfaceProp =
113 vtkSmartPointer<vtkProperty>::New();
114 backfaceProp->SetDiffuseColor(0.89, 0.81, 0.34);
115 vtkSmartPointer<vtkActor> originalActor =
116 vtkSmartPointer<vtkActor>::New();
117 originalActor->SetMapper(originalMapper);
118 originalActor->SetBackfaceProperty(backfaceProp);
119 originalActor->GetProperty()->SetDiffuseColor(1.0, 0.3882, 0.2784);
120
121 vtkSmartPointer<vtkPolyDataMapper> edgeMapper =
122 vtkSmartPointer<vtkPolyDataMapper>::New();
123 edgeMapper->SetInputData(featureEdges->GetOutput());
124 vtkSmartPointer<vtkActor> edgeActor =
125 vtkSmartPointer<vtkActor>::New();
126 edgeActor->SetMapper(edgeMapper);
127 edgeActor->GetProperty()->SetEdgeColor(0., 0., 1.0);
128 edgeActor->GetProperty()->SetEdgeVisibility(1);
129 edgeActor->GetProperty()->SetLineWidth(5);
130
131 vtkSmartPointer<vtkPolyDataMapper> filledMapper =
132 vtkSmartPointer<vtkPolyDataMapper>::New();
133 filledMapper->SetInputData(normals->GetOutput());
134 vtkSmartPointer<vtkActor> filledActor =
135 vtkSmartPointer<vtkActor>::New();
136 filledActor->SetMapper(filledMapper);
137 filledActor->GetProperty()->SetDiffuseColor(1.0, 0.3882, 0.2784);
138 ///
139 vtkSmartPointer<vtkRenderer> leftRenderer =
140 vtkSmartPointer<vtkRenderer>::New();
141 leftRenderer->SetViewport(leftViewport);
142 leftRenderer->AddActor(originalActor);
143 leftRenderer->AddActor(edgeActor);
144 leftRenderer->SetBackground(1.0, 1.0, 1.0);
145
146 vtkSmartPointer<vtkRenderer> rightRenderer =
147 vtkSmartPointer<vtkRenderer>::New();
148 rightRenderer->SetViewport(rightViewport);
149 rightRenderer->AddActor(filledActor);
150 rightRenderer->SetBackground(0, 0, 0);
151
152 vtkSmartPointer<vtkRenderWindow> renderWindow =
153 vtkSmartPointer<vtkRenderWindow>::New();
154 renderWindow->AddRenderer(leftRenderer);
155 renderWindow->AddRenderer(rightRenderer);
156 renderWindow->SetSize(640, 320);
157 renderWindow->Render();
158 renderWindow->SetWindowName("Poly Data Closed");
159
160 vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
161 vtkSmartPointer<vtkRenderWindowInteractor>::New();
162 renderWindowInteractor->SetRenderWindow(renderWindow);
163
164 leftRenderer->GetActiveCamera()->SetPosition(0, -1, 0);
165 leftRenderer->GetActiveCamera()->SetFocalPoint(0, 0, 0);
166 leftRenderer->GetActiveCamera()->SetViewUp(0, 0, 1);
167 leftRenderer->GetActiveCamera()->Azimuth(30);
168 leftRenderer->GetActiveCamera()->Elevation(30);
169 leftRenderer->ResetCamera();
170 rightRenderer->SetActiveCamera(leftRenderer->GetActiveCamera()); //同步响应
171 renderWindowInteractor->Start();
172
173 return 0;
174 }
int numberOfOpenEdges = featureEdges->GetOutput()->GetNumberOfCells();
1.3 漏洞填补
很多情况下,检测出是否封闭还是不够的,还需将这些漏洞填补起来。VTK中有现成的类来完成这个功能——vtkFillHolesFilter。
其内部执行过程是首先检测出网格中的所有边界边,然后找出这些边界边中的每一个闭合回路,最后将这些闭合回路进行三角化(即生成三角网格)以实现填补的目的。这个类也是非常简单的,只需要设置需要填补的网格数据即可。
需要注意的是,有些边界的闭合回路是不需要三角化的,例如一个平面网格,若填补其四周的边界边,则会与原网格产生覆盖。vtkFillHolesFilters()中的SetHoleSize()函数可用于控制需要修补的漏洞面积的最大值,大于该值的漏洞则不需要填补处理。
现在,我们需要讨论的一个重要的问题是为什么要使用vtkPolyDataNormals?
这个事之前也提到过,在这里复习一遍。法向量这个东西和光照与阴影的计算密切相关。单元的法向量朝向则与单元的点顺序相关!只有保持所有的单元的点顺序一致才能得到正确的法向量,否则在网格模型显示时会得到意外的结果!如下所示:
由于经过漏洞填充,模型的所有单元的点顺序并不一致,因此使用vtkPolyDataNormals::ConsisitencyOn()进行调整。这样才能避免上面的问题。