很高兴在雪易的CSDN遇见你 ,给你糖糖![]()
![]()
![]()
欢迎大家加入雪易社区-CSDN社区云
本博文主要介绍VTK中几个常见的Clip/Trim接口,同时介绍下3-matic软件中对应的功能;希望能帮到各位小伙伴,有什么问题欢迎交流学习。
感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步!
你的点赞就是我的动力(^U^)ノ~YO
目录
vtk中针对剪裁有多个接口,各自有优点和缺点,现详细列出,小伙伴可以有针对性的进行选择接口。裁剪的接口有vtkClipClosedSurface 、vtkClipConvexPolyData 、 vtkClipDataSet 、 vtkClipPolyData 、vtkClipVolume。目前主要介绍vtkClipClosedSurface 、 vtkClipPolyData两个接口。
效果图


vtkClipPolyData效果图



vtkClipClosedSurface效果图
两者差异:vtkClipPolyData切割带有锯齿形状且不是封闭的模型;vtkClipClosedSurface通过插值确保切割面为光滑且封闭的。
用途:通过用户定义的隐函数或输入的标量数据,裁剪polygonal data。
采用隐函数裁剪的方法:定义裁剪隐函数;SetClipFunction; GenerateClipScalarsOn;
核心算法:
- if (this->ClipFunction)
- {
- vtkFloatArray* tmpScalars = vtkFloatArray::New();
- tmpScalars->SetNumberOfTuples(numPts);
- inPD = vtkPointData::New();
- inPD->ShallowCopy(input->GetPointData()); // copies original
- if (this->GenerateClipScalars)
- {
- inPD->SetScalars(tmpScalars);
- }
- for (i = 0; i < numPts; i++)
- {
- //遍历输入数据的每个点,计算是否满足ClipFunction的条件;若ClipFunction为vtkPolyPlane,则判断点是否在PolyLine内,若在内,则s为正数;反之为负数。
- s = this->ClipFunction->FunctionValue(inPts->GetPoint(i));
- tmpScalars->SetComponent(i, 0, s);
- }
- clipScalars = tmpScalars;
- }
-
- //用上述判定点的结果对cell进行分割
- cell->Clip(this->Value, cellScalars, this->Locator, connList, inPD, outPD, inCD, cellId, outCD,
- this->InsideOut);
用途:通过一组切割平面实现对闭合曲面的切割。将输入数据切割未由多边形面组成的闭合曲面。
约束:输入的曲面不应该有开放的边缘,也不能有任何被两个以上的面共享的边缘。 vtkFeatureEdges过滤器可以用来验证一个数据集是否满足这些条件。此外,输入的面不应该是自相交的,即曲面的各个面应该只与它们的边缘相接触。
选项:
a. 如果 "生成轮廓"(GenerateOutline)是打开的,这个过滤器将在剪裁平面与数据相交处生成一个轮廓,如下图所示。

b. PassPointData;若打开表示将点数据传递给输出,若新点产生时,点数据将会进行插值。此变量默认关闭。
c. ScalarMode选项将在输出中添加单元格标量,这样生成的面就可以用与原始面不同的颜色显示。可以用与原始表面不同的颜色来显示。
注意:
(1)一组切割平面应该是一组凸平面,否则生成的结果可能为空。
(2)生成的结果为多个平面围成的部分。
(3)若ScalarMode设置为On时,则是通过标量来映射Mapper的颜色;此时通过
actor->GetProperty()->SetColor(color);设置颜色时不生效;解决方案:关闭Mapper的
ScalarVisibility,颜色设置才能生效。
核心算法:
- // Go through the clipping planes and clip the input with each plane
- vtkCollectionSimpleIterator iter;
- int numPlanes = 0;
- if (planes)
- {
- planes->InitTraversal(iter);
- numPlanes = planes->GetNumberOfItems();
- }
-
- vtkPlane* plane = nullptr;
- for (int planeId = 0; planes && (plane = planes->GetNextPlane(iter)); planeId++)
- {
- this->UpdateProgress((planeId + 1.0) / (numPlanes + 1.0));
- if (this->GetAbortExecute())
- {
- break;
- }
-
- // Is this the last cut plane? If so, generate triangles.
- int triangulate = 5;
- if (planeId == numPlanes - 1)
- {
- triangulate = polyMax;
- }
-
- // Is this the active plane?
- int active = (planeId == this->ActivePlaneId);
-
- // Convert the plane into an easy-to-evaluate function
- double pc[4];
- plane->GetNormal(pc);
- pc[3] = -vtkMath::Dot(pc, plane->GetOrigin());
-
- // Create the clip scalars by evaluating the plane at each point
- vtkIdType numPoints = points->GetNumberOfPoints();
- pointScalars->SetNumberOfValues(numPoints);
- for (vtkIdType pointId = 0; pointId < numPoints; pointId++)
- {
- double p[3];
- points->GetPoint(pointId, p);
-
- //*重要*计算每个点到切平面的距离,若>0表示该点在切平面的法向方向上,若<0表示该点在切平面法向的反方向上
- double val = p[0] * pc[0] + p[1] * pc[1] + p[2] * pc[2] + pc[3];
- pointScalars->SetValue(pointId, val);
- }
-
- // Prepare the output scalars
- outLineData->CopyAllocate(inLineData, 0, 0);
- outPolyData->CopyAllocate(inPolyData, 0, 0);
-
- // Reset the locator
- edgeLocator->Initialize();
-
- // Clip the lines
- //*重要*若直线的两点均在切平面法向的相反方向,则过滤掉该直线;若直线的两点均在切平面法向上,则保留该直线;若直线与切平面相交,则对该直线进行插值,保留切平面法向方向上的直线部分。
- this->ClipLines(
- points, pointScalars, pointData, edgeLocator, lines, newLines, inLineData, outLineData);
-
- // Clip the polys
- if (polys)
- {
- // Get the number of lines remaining after the clipping
- vtkIdType numClipLines = newLines->GetNumberOfCells();
-
- // Cut the polys to generate more lines
- //*重要*获取组成该多边形的点,若某边与切平面相交则进行插值;
- this->ClipAndContourPolys(points, pointScalars, pointData, edgeLocator, triangulate, polys,
- newPolys, newLines, inPolyData, outPolyData, outLineData);
-
- // Add scalars for the newly-created contour lines
- vtkUnsignedCharArray* scalars =
- vtkArrayDownCast
(outLineData->GetScalars()); -
- if (scalars)
- {
- // Set the color to the active color if plane is active
- unsigned char* color = colors[1 + active];
- unsigned char* activeColor = colors[2];
-
- vtkIdType numLines = newLines->GetNumberOfCells();
- for (vtkIdType lineId = numClipLines; lineId < numLines; lineId++)
- {
- unsigned char oldColor[3];
- scalars->GetTypedTuple(lineId, oldColor);
- if (numberOfScalarComponents != 3 || oldColor[0] != activeColor[0] ||
- oldColor[1] != activeColor[1] || oldColor[2] != activeColor[2])
- {
- scalars->SetTypedTuple(lineId, color);
- }
- }
- }
-
- // Generate new polys from the cut lines
- vtkIdType cellId = newPolys->GetNumberOfCells();
- vtkIdType numClipAndContourLines = newLines->GetNumberOfCells();
-
- // Create a polydata for the lines
- tmpContourData->SetPoints(points);
- tmpContourData->SetLines(newLines);
- tmpContourData->BuildCells();
-
- this->TriangulateContours(
- tmpContourData, numClipLines, numClipAndContourLines - numClipLines, newPolys, pc);
-
- // Add scalars for the newly-created polys
- scalars = vtkArrayDownCast
(outPolyData->GetScalars()); -
- if (scalars)
- {
- unsigned char* color = colors[1 + active];
-
- vtkIdType numCells = newPolys->GetNumberOfCells();
- if (numCells > cellId)
- {
- // The insert allocates space up to numCells-1
- scalars->InsertTypedTuple(numCells - 1, color);
- for (; cellId < numCells; cellId++)
- {
- scalars->SetTypedTuple(cellId, color);
- }
- }
- }
-
- // Add scalars to any diagnostic lines that added by
- // TriangulateContours(). In usual operation, no lines are added.
- scalars = vtkArrayDownCast
(outLineData->GetScalars()); -
- if (scalars)
- {
- unsigned char color[3] = { 0, 255, 255 };
-
- vtkIdType numCells = newLines->GetNumberOfCells();
- if (numCells > numClipAndContourLines)
- {
- // The insert allocates space up to numCells-1
- scalars->InsertTypedTuple(numCells - 1, color);
- for (vtkIdType lineCellId = numClipAndContourLines; lineCellId < numCells; lineCellId++)
- {
- scalars->SetTypedTuple(lineCellId, color);
- }
- }
- }
- }
-
- // Swap the lines, points, etcetera: old output becomes new input
- vtkCellArray* tmp1 = lines;
- lines = newLines;
- newLines = tmp1;
- newLines->Initialize();
-
- if (polys)
- {
- vtkCellArray* tmp2 = polys;
- polys = newPolys;
- newPolys = tmp2;
- newPolys->Initialize();
- }
-
- vtkCellData* tmp4 = inLineData;
- inLineData = outLineData;
- outLineData = tmp4;
- outLineData->Initialize();
-
- vtkCellData* tmp5 = inPolyData;
- inPolyData = outPolyData;
- outPolyData = tmp5;
- outPolyData->Initialize();
- }
》vtkAreaPicker:获取裁剪平面
》vtkClipClosedSurface:完成裁剪

代码:
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include "vtkClipClosedSurface.h"
- #include "vtkPlaneCollection.h"
- #include "vtkAxesActor.h"
- #define VTKISRBP_ORIENT 0
- #define VTKISRBP_SELECT 1
-
-
- namespace {
- // Define interaction style
- class HighlightInteractorStyle : public vtkInteractorStyleRubberBandPick
- {
- public:
- static HighlightInteractorStyle* New();
- vtkTypeMacro(HighlightInteractorStyle, vtkInteractorStyleRubberBandPick);
-
- HighlightInteractorStyle() : vtkInteractorStyleRubberBandPick()
- {
- this->SelectedMapper = vtkSmartPointer
::New(); - this->SelectedActor = vtkSmartPointer
::New(); - this->SelectedActor->SetMapper(SelectedMapper);
- }
-
- virtual void OnLeftButtonUp() override
- {
- // Forward events
- vtkInteractorStyleRubberBandPick::OnLeftButtonUp();
-
- if (this->CurrentMode == VTKISRBP_SELECT)
- {
- vtkNew
colors; -
- vtkPlanes* frustum = static_cast
(this->GetInteractor()->GetPicker())->GetFrustum(); -
- vtkNew
planeCollection; - int pCount = frustum->GetNumberOfPlanes() - 2;
- for (int i = 0; i < pCount; i++)
- {
- double normal[3];
- frustum->GetPlane(i)->GetNormal(normal);
- double origin[3];
- frustum->GetPlane(i)->GetOrigin(origin);
-
- vtkNew
plane; - plane->SetOrigin(origin[0], origin[1], origin[2]);
- plane->SetNormal(-normal[0], -normal[1], -normal[2]);
- planeCollection->AddItem(plane);
- }
-
- vtkNew
clipper; - clipper->SetInputData(this->PolyData);
- clipper->SetClippingPlanes(planeCollection);
- clipper->Update();
-
- if (m_SrcActor != nullptr)
- m_SrcActor->VisibilityOff();
-
- this->SelectedMapper->SetInputData(clipper->GetOutput());
-
- this->SelectedActor->GetProperty()->SetColor(1.0000, 0.3882, 0.2784);
- this->GetInteractor()->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->AddActor(SelectedActor);
- this->GetInteractor()->GetRenderWindow()->Render();
- this->HighlightProp(NULL);
- }
- }
-
- void SetPolyData(vtkSmartPointer
polyData) - {
- this->PolyData = polyData;
- }
- vtkActor* m_SrcActor = nullptr;
- private:
- vtkSmartPointer
PolyData; - vtkSmartPointer
SelectedActor; - vtkSmartPointer
SelectedMapper; - };
- vtkStandardNewMacro(HighlightInteractorStyle);
-
- } // namespace
-
- int main(int argc, char* argv[])
- {
-
- vtkNew
source; - source->SetPhiResolution(49);
- source->SetThetaResolution(200);
- source->Update();
- auto polyData = source->GetOutput();
-
-
- // Create a mapper and actor
- vtkNew
mapper; - mapper->SetInputData(polyData);
- mapper->ScalarVisibilityOff();
-
- vtkNew
actor; - actor->SetMapper(mapper);
- actor->GetProperty()->SetPointSize(5);
-
- vtkNew
axes; - // Visualize
- vtkNew
renderer; - renderer->UseHiddenLineRemovalOn();
-
- vtkNew
renderWindow; - renderWindow->AddRenderer(renderer);
- renderWindow->SetSize(640, 480);
- renderWindow->SetWindowName("HighlightSelection");
-
- vtkNew
areaPicker; - vtkNew
renderWindowInteractor; - renderWindowInteractor->SetPicker(areaPicker);
- renderWindowInteractor->SetRenderWindow(renderWindow);
-
- renderer->AddActor(actor);
- renderer->AddActor(axes);
-
- renderWindow->Render();
-
- vtkNew
style; - style->m_SrcActor = actor;
- style->SetPolyData(polyData);
- style->SetCurrentRenderer(renderer);
- renderWindowInteractor->SetInteractorStyle(style);
-
- renderWindowInteractor->Start();
-
- return EXIT_SUCCESS;
- }
-
本文主要介绍了vtkClipPolyData 和 vtkClipClosedSurface两个接口的使用方法、两者的处理结果和缺点。
感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步!
你的赞赏是我的最最最最大的动力(^U^)ノ~YO
