“圓柱”曲面展開
沿軸向展開,展開後橫座標爲弧長,縱座標爲軸向座標,高程爲曲面到參考圓柱曲面的距離。
定義參考圓柱
//!軸
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;
}
展開到復原