ExtrudePolyDataAlongLine (沿着线拉伸多变形)
-
Obtain the 2D polydata from a file( or generate a disk).
第一步获取截面轮廓线(contours)。 -
Generates random points in 3D space and fits a spline to the points.
第二步生成放样线,即轮廓线沿着这条线放样。 -
Computes an orientation frame at each point on the line.
第三步计算放样线上每一点的法向量,切向量和副法向量,以便于确定截面在放样线上的空间位置(主要指的是方向)。 -
Places a copy of the 2D polydata at each point on the line, oriented by the the frame at that point.
第四步将轮廓线放置到放样线上,并按照第三步进行旋转。 -
For each contour in the 2D polydata, appends all of the copies.
第五步 确定轮廓线是否含有洞。 -
Creates a ruled surface for each contour.
第六步将放样线上每一个轮廓连接成三角网。红色为截面轮廓,黄色为截面轮廓缩放,平移,旋转 复制到放样线上
FrenetSerret Fram Demo
#include <vtkFrenetSerretFrame.h>
#include <vtkSmartPointer.h>
#include <vtkParametricSpline.h>
#include <vtkParametricFunctionSource.h>
#include <vtkSphereSource.h>
#include <vtkArrowSource.h>
#include <vtkGlyph3D.h>
#include <vtkPointSource.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkProperty.h>
#include <vtkPolyDataMapper.h>
#include <vtkCamera.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
static void MakeGlyphs(vtkPolyData *src, double size, vtkGlyph3D *glyph);
int main(int, char *[])
{
// Generate some random points
int numberOfPoints = 8;
vtkSmartPointer<vtkPointSource> pointSource =
vtkSmartPointer<vtkPointSource>::New();
pointSource->SetNumberOfPoints(numberOfPoints);
pointSource->Update();
vtkPoints* points = pointSource->GetOutput()->GetPoints();
// 拟合
vtkSmartPointer<vtkParametricSpline> spline =
vtkSmartPointer<vtkParametricSpline>::New();
spline->SetPoints(points);
vtkSmartPointer<vtkParametricFunctionSource> functionSource =
vtkSmartPointer<vtkParametricFunctionSource>::New();
functionSource->SetParametricFunction(spline);
functionSource->SetUResolution(10 * numberOfPoints);
functionSource->SetVResolution(10 * numberOfPoints);
functionSource->SetWResolution(10 * numberOfPoints);
// Create the frame
vtkSmartPointer<vtkFrenetSerretFrame> frame =
vtkSmartPointer<vtkFrenetSerretFrame>::New();
frame->SetInputConnection(functionSource->GetOutputPort());
frame->ConsistentNormalsOn();
frame->Update();
vtkSmartPointer<vtkGlyph3D> glyph3DNormals =
vtkSmartPointer<vtkGlyph3D>::New();
vtkSmartPointer<vtkGlyph3D> glyph3DTangents =
vtkSmartPointer<vtkGlyph3D>::New();
vtkSmartPointer<vtkGlyph3D> glyph3DBinormals =
vtkSmartPointer<vtkGlyph3D>::New();
// for each vector, create a Glyph3D and DeepCopy the output
double radius = .05;
frame->GetOutput()->GetPointData()->SetActiveVectors("FSNormals");
MakeGlyphs(frame->GetOutput(), radius, glyph3DNormals.GetPointer());
vtkSmartPointer<vtkPolyData> normalsPolyData =
vtkSmartPointer<vtkPolyData>::New();
normalsPolyData->DeepCopy(glyph3DNormals->GetOutput());
frame->GetOutput()->GetPointData()->SetActiveVectors("FSTangents");
MakeGlyphs(frame->GetOutput(), radius, glyph3DTangents.GetPointer());
vtkSmartPointer<vtkPolyData> tangentsPolyData =
vtkSmartPointer<vtkPolyData>::New();
tangentsPolyData->DeepCopy(glyph3DTangents->GetOutput());
frame->GetOutput()->GetPointData()->SetActiveVectors("FSBinormals");
MakeGlyphs(frame->GetOutput(), radius, glyph3DBinormals.GetPointer());
vtkSmartPointer<vtkPolyData> binormalsPolyData =
vtkSmartPointer<vtkPolyData>::New();
binormalsPolyData->DeepCopy(glyph3DBinormals->GetOutput());
// Setup actors and mappers
vtkSmartPointer<vtkPolyDataMapper> glyph3DNormalsMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
glyph3DNormalsMapper->SetInputData(normalsPolyData);
vtkSmartPointer<vtkActor> glyph3DNormalsActor =
vtkSmartPointer<vtkActor>::New();
glyph3DNormalsActor->SetMapper(glyph3DNormalsMapper);
glyph3DNormalsActor->GetProperty()->SetColor(0.8900, 0.8100, 0.3400);
vtkSmartPointer<vtkPolyDataMapper> glyph3DTangentsMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
glyph3DTangentsMapper->SetInputData(tangentsPolyData);
vtkSmartPointer<vtkActor> glyph3DTangentsActor =
vtkSmartPointer<vtkActor>::New();
glyph3DTangentsActor->SetMapper(glyph3DTangentsMapper);
glyph3DTangentsActor->GetProperty()->SetColor(1.0000, 0.3882, 0.2784);
vtkSmartPointer<vtkPolyDataMapper> glyph3DBinormalsMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
glyph3DBinormalsMapper->SetInputData(binormalsPolyData);
vtkSmartPointer<vtkActor> glyph3DBinormalsActor =
vtkSmartPointer<vtkActor>::New();
glyph3DBinormalsActor->SetMapper(glyph3DBinormalsMapper);
glyph3DBinormalsActor->GetProperty()->SetColor(0.1804,0.5451,0.3412);
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(functionSource->GetOutputPort());
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
// Setup render window, renderer, and interactor
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->AddActor(glyph3DNormalsActor);
renderer->AddActor(glyph3DTangentsActor);
renderer->AddActor(glyph3DBinormalsActor);
renderer->AddActor(actor);
renderer->SetBackground(.4, .5, .7);
// Pick a good view
renderer->ResetCamera();
renderer->GetActiveCamera()->Azimuth(120);
renderer->GetActiveCamera()->Elevation(30);
renderer->GetActiveCamera()->Dolly(1.8);
renderer->ResetCameraClippingRange();
renderWindow->SetSize(640, 480);
renderWindow->Render();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
void MakeGlyphs(vtkPolyData *src, double size, vtkGlyph3D *glyph)
{
// Source for the glyph filter
vtkSmartPointer<vtkArrowSource> arrow =
vtkSmartPointer<vtkArrowSource>::New();
arrow->SetTipResolution(16);
arrow->SetTipLength(.3);
arrow->SetTipRadius(.1);
glyph->SetSourceConnection(arrow->GetOutputPort());
glyph->SetInputData(src);
glyph->SetVectorModeToUseVector();
glyph->SetScaleModeToScaleByVector();
glyph->SetScaleFactor(size);
glyph->OrientOn();
glyph->Update();
}
In the example, the normal vectors are yellow, the tangent vectors are red and the binormal vectors.
法向量黄色;切向量红色;副法向量
ExtrudePolyDataAlongLine
int main(int argc, char *argv[])
{
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
// Setup render window, renderer, and interactor
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->SetBackground(.4, .5, .7);
// For testing
vtkMath::RandomSeed(7859821);
// Read a polydata
// 读取或生成截面轮廓线
vtkSmartPointer<vtkPolyData> polyData = ReadPolyData(argc > 1 ? argv[1] : "");;
int numberOfContours = polyData->GetNumberOfLines();
std::cout << "Number of contours: " << numberOfContours << std::endl;
/*{
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputData(polyData);
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->GetProperty()->SetColor(1, 0, 0);
actor->SetMapper(mapper);
renderer->AddActor(actor);
}
*/
// Generate some random points
int numberOfPoints = 5 ;
vtkSmartPointer<vtkPointSource> pointSource =
vtkSmartPointer<vtkPointSource>::New();
pointSource->SetNumberOfPoints(numberOfPoints);
pointSource->Update();
// 随机生成十个点
/*{
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(pointSource->GetOutputPort());
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->GetProperty()->SetPointSize(10);
actor->SetMapper(mapper);
renderer->AddActor(actor);
}*/
//点加密生成光滑曲线
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
points->InsertNextPoint(0, 0, 0);
points->InsertNextPoint(0, 5, 0);
points->InsertNextPoint(5, 5, 0);
points->InsertNextPoint(10, 5, 0);
points->InsertNextPoint(15, 5, 0);
// vtkPoints* points = pointSource->GetOutput()->GetPoints();
//vtkPoints* points = linepts;
vtkSmartPointer<vtkParametricSpline> spline =
vtkSmartPointer<vtkParametricSpline>::New();
spline->SetPoints(points);
vtkSmartPointer<vtkParametricFunctionSource> functionSource =
vtkSmartPointer<vtkParametricFunctionSource>::New();
functionSource->SetParametricFunction(spline);
functionSource->SetUResolution(50 * numberOfPoints);
functionSource->SetVResolution(50 * numberOfPoints);
functionSource->SetWResolution(50 * numberOfPoints);
// Create the frame
//
vtkSmartPointer<vtkFrenetSerretFrame> frame =
vtkSmartPointer<vtkFrenetSerretFrame>::New();
frame->SetInputConnection(functionSource->GetOutputPort());
frame->ConsistentNormalsOn();
frame->Update();
//In the example, the normal vectors are yellow, the tangent vectors are red and the binormal vectors
//
frame->GetOutput()->GetPointData()->SetActiveVectors("FSNormals");
frame->GetOutput()->GetPointData()->SetActiveVectors("FSTangents");
frame->GetOutput()->GetPointData()->SetActiveVectors("FSBinormals");
vtkPoints *linePoints = frame->GetOutput()->GetPoints();
std::vector<vtkSmartPointer<vtkAppendPolyData> >skeletons;
for (int i = 0; i < numberOfContours; ++i)
{
skeletons.push_back(vtkSmartPointer<vtkAppendPolyData>::New());
}
//为每一个frame生成截面
for (int i = 0; i < linePoints->GetNumberOfPoints(); ++i)
{
vtkSmartPointer<vtkTransform> transform =
vtkSmartPointer<vtkTransform>::New();
// Compute a basis
double normalizedX[3];
frame->GetOutput()->GetPointData()->SetActiveVectors("FSNormals");
frame->GetOutput()->GetPointData()->GetVectors()->GetTuple(i, normalizedX);
double normalizedY[3];
frame->GetOutput()->GetPointData()->SetActiveVectors("FSBinormals");
frame->GetOutput()->GetPointData()->GetVectors()->GetTuple(i, normalizedY);
double normalizedZ[3];
frame->GetOutput()->GetPointData()->SetActiveVectors("FSTangents");
frame->GetOutput()->GetPointData()->GetVectors()->GetTuple(i, normalizedZ);
// Create the direction cosine matrix
// 余弦矩阵
// 旋转
vtkSmartPointer<vtkMatrix4x4> matrix =
vtkSmartPointer<vtkMatrix4x4>::New();
matrix->Identity();
for (unsigned int j = 0; j < 3; ++j)
{
matrix->SetElement(j, 0, normalizedX[j]);
matrix->SetElement(j, 1, normalizedY[j]);
matrix->SetElement(j, 2, normalizedZ[j]);
}
//平移
transform->Translate(linePoints->GetPoint(i)[0],
linePoints->GetPoint(i)[1],
linePoints->GetPoint(i)[2]);
//缩放
transform->Scale(.02, .02, .02);
//旋转
transform->Concatenate(matrix);
vtkSmartPointer<vtkTransformPolyDataFilter> transformPD =
vtkSmartPointer<vtkTransformPolyDataFilter>::New();
vtkSmartPointer<vtkPolyData> polyDataCopy =
vtkSmartPointer<vtkPolyData>::New();
polyDataCopy->DeepCopy(polyData);
transformPD->SetTransform(transform);
transformPD->SetInputData(polyDataCopy);
transformPD->Update();
//获取连通区域
vtkSmartPointer<vtkPolyDataConnectivityFilter> contours =
vtkSmartPointer<vtkPolyDataConnectivityFilter>::New();
contours->SetInputConnection(transformPD->GetOutputPort());
contours->Update();
/*{
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(contours->GetOutputPort());
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->GetProperty()->SetColor(1, 0, 1);
actor->SetMapper(mapper);
renderer->AddActor(actor);
}*/
for (int r = 0; r < contours->GetNumberOfExtractedRegions(); ++r)
{
contours->SetExtractionModeToSpecifiedRegions();
contours->InitializeSpecifiedRegionList();
contours->AddSpecifiedRegion(r);
contours->Update();
vtkSmartPointer<vtkPolyData> skeleton =
vtkSmartPointer<vtkPolyData>::New();
skeleton->DeepCopy(contours->GetOutput());
skeletons[r]->AddInputData(skeleton);
}
}
// 由截面生成三角网
for (int i = 0; i < numberOfContours; ++i)
{
{
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(skeletons[i]->GetOutputPort());
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->GetProperty()->SetColor(1, 0, 1);
actor->SetMapper(mapper);
renderer->AddActor(actor);
}
vtkSmartPointer<vtkRuledSurfaceFilter> ruled =
vtkSmartPointer<vtkRuledSurfaceFilter>::New();
ruled->SetRuledModeToPointWalk();
ruled->CloseSurfaceOff();
ruled->SetOnRatio(1);
ruled->SetDistanceFactor(10000000);
ruled->SetInputConnection(skeletons[i]->GetOutputPort());
vtkSmartPointer<vtkTriangleMeshPointNormals> normals =
vtkSmartPointer<vtkTriangleMeshPointNormals>::New();
normals->SetInputConnection(ruled->GetOutputPort());
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(normals->GetOutputPort());
vtkSmartPointer<vtkProperty> backProp =
vtkSmartPointer<vtkProperty>::New();
backProp->SetColor(1.0, 0.3882, 0.278);
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetBackfaceProperty(backProp);
actor->GetProperty()->SetColor(0.8900, 0.8100, 0.3400);
actor->SetMapper(mapper);
renderer->AddActor(actor);
//
vtkSmartPointer<vtkXMLPolyDataWriter>write = vtkSmartPointer<vtkXMLPolyDataWriter>::New();
write->SetFileName("tunel.vtp");
write->SetInputConnection(normals->GetOutputPort());
write->Write();
}
/* {
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(functionSource->GetOutputPort());
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
renderer->AddActor(actor);
}
{
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(frame->GetOutputPort());
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->GetProperty()->SetColor(1, 1, 0);
actor->GetProperty()->SetPointSize(10);
actor->SetMapper(mapper);
renderer->AddActor(actor);
}*/
// Pick a good view
renderer->ResetCamera();
renderer->GetActiveCamera()->Azimuth(120);
renderer->GetActiveCamera()->Elevation(30);
renderer->GetActiveCamera()->Dolly(1.1);
renderer->ResetCameraClippingRange();
renderWindow->SetSize(512, 512);
renderWindow->Render();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
截面轮廓线
生成隧道