“圆柱”曲面展开
沿轴向展开,展开后横坐标为弧长,纵坐标为轴向坐标,高程为曲面到参考圆柱曲面的距离。
定义参考圆柱
//!轴
enum AXIS {
AXIS_X,
AXIS_Y,
AXIS_Z
};
//! 投影圆柱
struct GEO_CYLINDER
{
//!轴向
AXIS Axial;
//!径向:横/纵 ,横向弧长,纵向偏差
AXIS RadialTran;
AXIS RadialLong;
//!径向截面圆心中心
double CenterTran;
double CenterLong;
//!半径
double R;
};
由“圆柱”曲面展开“平”曲面
void CylinderToPlane(vtkPolyData* srcData, vtkPolyData* destData, GEO_CYLINDER proj_cylinder) {
vtkSmartPointer<vtkPoints>srcPoints = srcData->GetPoints();
//destData->DeepCopy(srcData);
vtkSmartPointer<vtkPoints>destPoints = vtkSmartPointer<vtkPoints>::New();
int num = srcPoints->GetNumberOfPoints();
double p[3],r[3],cross[3];
//v1展开起点,v0 当前截面的圆
double v0[3] = { 0 }, v1[3] = {0};
//截面中心点
v0[proj_cylinder.RadialTran] = proj_cylinder.CenterTran;
v0[proj_cylinder.RadialLong] = proj_cylinder.CenterLong;
//沿轴向展开
v1[proj_cylinder.RadialTran] = proj_cylinder.R;
v1[proj_cylinder.RadialLong] = 0;
//弧长
double azmith;
for (int i = 0; i < num; ++i) {
srcPoints->GetPoint(i, p);
v0[proj_cylinder.Axial]= p[proj_cylinder.Axial];
vtkMath::Subtract(p, v0, p);
azmith = vtkMath::AngleBetweenVectors(v1,p);
vtkMath::Cross(v1, p, cross);
if (cross[proj_cylinder.Axial]<0)
azmith = vtkMath::Pi()*2-azmith;
r[proj_cylinder.RadialTran]= proj_cylinder.CenterTran+ azmith*proj_cylinder.R;
r[proj_cylinder.Axial] = v0[proj_cylinder.Axial];
r[proj_cylinder.RadialLong] =sqrt(p[0] * p[0] + p[1] * p[1] + p[2] * p[2]) - proj_cylinder.R;
//CyPointToPPoint(p, r, proj_cylinder);
destPoints->InsertPoint(i,r);
}
//添加切口线上的点(恢复时使其闭合)
/*double bound[6];
srcData->GetBounds(bound);
p[proj_cylinder.RadialTran] = proj_cylinder.CenterTran + 2*vtkMath::Pi()*proj_cylinder.R;
p[proj_cylinder.Axial] = bound[2* proj_cylinder.Axial];
p[proj_cylinder.RadialLong] = 0;
destPoints->InsertNextPoint(p);
p[proj_cylinder.Axial] = bound[2 * proj_cylinder.Axial+1];
destPoints->InsertNextPoint(p);*/
//
destData->SetPoints(destPoints);
}
由“平”曲面恢复“圆柱”曲面
void PPointToCyPoint(double pp[3], double cy[3], GEO_CYLINDER proj_cylinder)
{
double arc_length;
//弧长
arc_length = pp[proj_cylinder.RadialTran] - proj_cylinder.CenterTran;
//径向-横向
cy[proj_cylinder.RadialLong] = proj_cylinder.CenterLong + sin(2*vtkMath::Pi()-arc_length / proj_cylinder.R)*(proj_cylinder.R+pp[proj_cylinder.RadialLong]);
//轴向
cy[proj_cylinder.Axial] = pp[proj_cylinder.Axial];
//径向-纵向
cy[proj_cylinder.RadialTran] = proj_cylinder.CenterTran + cos(2 * vtkMath::Pi()-arc_length / proj_cylinder.R)*(proj_cylinder.R + pp[proj_cylinder.RadialLong]);
}
void PlaneToCylinder(vtkPolyData * srcData, vtkPolyData * destData, GEO_CYLINDER proj_cylinder)
{
vtkSmartPointer<vtkPoints>srcPoints = srcData->GetPoints();
destData->DeepCopy(srcData);
vtkSmartPointer<vtkPoints>destPoints = vtkSmartPointer<vtkPoints>::New();
int num = srcPoints->GetNumberOfPoints();
double p[3],r[3];
for (int i = 0; i < num; ++i) {
srcPoints->GetPoint(i, p);
PPointToCyPoint(p,r,proj_cylinder);
destPoints->InsertPoint(i, r);
}
destData->SetPoints(destPoints);
}
计算参考圆柱
vtkPolyData * destData = reader->GetOutput();
double bound[6];
destData->GetBounds(bound);
//定义转换圆柱
GEO_CYLINDER proj_cylinder;
proj_cylinder.R = (bound[1] - bound[0]) / 2; //半径
proj_cylinder.Axial = AXIS::AXIS_Y; //沿Y轴展开
proj_cylinder.RadialTran = AXIS::AXIS_X;
proj_cylinder.RadialLong = AXIS::AXIS_Z;
proj_cylinder.CenterTran = (bound[1] + bound[0]) / 2.0;
proj_cylinder.CenterLong = (bound[5] + bound[4]) / 2.0;
”圆柱“曲面
计算参考圆柱
”圆柱“曲面展开
圆柱“曲面展开和参考圆柱展开
测试
int main(int argc, char const *argv[])
{
double radius = 1;
double center[3] = {0,0,0};
vtkSmartPointer<vtkCylinderSource> cylinderSource = vtkSmartPointer<vtkCylinderSource>::New();
cylinderSource->SetCapping(false);
cylinderSource->SetRadius(radius);
cylinderSource->SetCenter(center);
cylinderSource->SetHeight(5);
cylinderSource->SetResolution(100);
cylinderSource->Update();
//定义参考圆柱
GEO_CYLINDER proj_cylinder;
proj_cylinder.R = radius; //半径
proj_cylinder.Axial = AXIS::AXIS_Y; //沿Y轴展开
proj_cylinder.RadialTran = AXIS::AXIS_X;
proj_cylinder.RadialLong = AXIS::AXIS_Z;
proj_cylinder.CenterTran = center[AXIS::AXIS_X]; //横向
proj_cylinder.CenterLong = center[AXIS::AXIS_Z]; //纵向
//
vtkSmartPointer<vtkPolyData>destPlane = vtkSmartPointer<vtkPolyData>::New();
CylinderToPlane(cylinderSource->GetOutput(), destPlane, proj_cylinder);
//
vtkSmartPointer<vtkDelaunay2D>delaunay2d = vtkSmartPointer<vtkDelaunay2D>::New();
delaunay2d->SetInputData(destPlane);
delaunay2d->Update();
vtkSmartPointer<vtkPolyData>cylinderBack = vtkSmartPointer<vtkPolyData>::New();
PlaneToCylinder(delaunay2d->GetOutput(), cylinderBack, proj_cylinder);
//source
vtkSmartPointer<vtkPolyDataMapper> polyDataMapperSource =
vtkSmartPointer<vtkPolyDataMapper>::New();
polyDataMapperSource->SetInputData(cylinderSource->GetOutput());
vtkSmartPointer<vtkActor> actorSource = vtkSmartPointer<vtkActor>::New();
actorSource->SetMapper(polyDataMapperSource);
vtkSmartPointer<vtkRenderer> rendererSource = vtkSmartPointer<vtkRenderer>::New();
rendererSource->SetViewport(0, 0, 0.2, 1);
rendererSource->AddActor(actorSource);
rendererSource->SetBackground(10, 0, 0);
//plane
vtkSmartPointer<vtkPolyDataMapper> polyDataMapperDest =
vtkSmartPointer<vtkPolyDataMapper>::New();
polyDataMapperDest->SetInputData(delaunay2d->GetOutput());
vtkSmartPointer<vtkActor> actorDest = vtkSmartPointer<vtkActor>::New();
actorDest->SetMapper(polyDataMapperDest);
actorDest->GetProperty()->SetColor(0, 0, 1);
vtkSmartPointer<vtkRenderer> rendererDest = vtkSmartPointer<vtkRenderer>::New();
rendererDest->SetViewport(0.2, 0, 0.8, 1);
rendererDest->AddActor(actorDest);
rendererDest->AddActor(actorSource);
rendererDest->SetBackground(10, 0, 0);
//backToCylinder
vtkSmartPointer<vtkPolyDataMapper> polyDataMapperBack =
vtkSmartPointer<vtkPolyDataMapper>::New();
polyDataMapperBack->SetInputData(cylinderBack);
vtkSmartPointer<vtkActor> actorBack = vtkSmartPointer<vtkActor>::New();
actorBack->SetMapper(polyDataMapperBack);
actorBack->GetProperty()->SetColor(0, 0, 1);
vtkSmartPointer<vtkRenderer> rendererBack = vtkSmartPointer<vtkRenderer>::New();
rendererBack->SetViewport(0.8, 0, 1, 1);
rendererBack->AddActor(actorBack);
rendererBack->SetBackground(10, 0, 0);
vtkSmartPointer<vtkRenderWindow> renderWin = vtkSmartPointer<vtkRenderWindow>::New();
renderWin->AddRenderer(rendererSource);
renderWin->AddRenderer(rendererDest);
renderWin->AddRenderer(rendererBack);
renderWin->SetSize(1500, 600);
vtkSmartPointer<vtkRenderWindowInteractor>rwi =vtkSmartPointer<vtkRenderWindowInteractor>::New();
rwi->SetRenderWindow(renderWin);
rwi->Initialize();
rwi->Start();
return 0;
}
展开到复原