欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 家装 > C# VTK 自定义封装 vtkwPipeline 多边形管道建模

C# VTK 自定义封装 vtkwPipeline 多边形管道建模

2025/5/3 18:58:12 来源:https://blog.csdn.net/Mrfor516/article/details/139991960  浏览:    关键词:C# VTK 自定义封装 vtkwPipeline 多边形管道建模

vtkwPipeline 简介

   public vtkwPipeline(vtkLineSource lineSource, double outR, double inR, int sides)

vtkwPipeline  是我自定义封装的C# 类 用于对管道壁建模,有内半径,外半径设置,

以及多边形边数设置。

参数

1. vtkLineSource lineSource : 建模的管道路径

2.double outR:外半径

3.double inR: 内半径

4.int sides: 多边形边数

建模逻辑步骤

1.对lineSource第一个点进行 vtkRegularPolygonSource 内外多边形点集构建。

2.利用这个初始pipeFace 一直向下一个点直线移动,直到第二点停止,然后进行节点的角度旋转。

3.构建节点的夹角plane 将两个pipeFace 对应点连接为中心对plane 求进行直线交点,生成节点的pipeFace。

    public class vtkwPipeline{vtkCellArray Plane;vtkPoints Points;vtkPolyData PolyData;double OutRadius = 2;double InRadius = 1;int Sides = 30;vtkLineSource LineSource;public vtkwPipeline(vtkLineSource lineSource, double outR, double inR, int sides){LineSource = lineSource;outR = Math.Abs(outR);inR = Math.Abs(inR);(OutRadius, InRadius) = outR > inR ? (outR, inR) : (inR, outR);Sides = sides;Plane = new vtkCellArray();Points = new vtkPoints();PolyData = new vtkPolyData();}public void Update(){if (LineSource == null || LineSource.GetOutput().GetNumberOfPoints() <= 1){return;}vtkPoints linePoints = LineSource.GetOutput().GetPoints();double[] first = linePoints.GetPoint(0);double[] next = linePoints.GetPoint(1);double[] norm = new double[3] { next[0] - first[0], next[1] - first[1], next[2] - first[2] };PipeFace lastPipeFace = new PipeFace(first, norm, OutRadius, InRadius, Sides);lastPipeFace.InsertPoints(ref Points);lastPipeFace.CellFace(ref Plane);PipeFace lastCalcuPipeFace = lastPipeFace;PipeFace nextPipeFace = new PipeFace();for (int i = 1; i < linePoints.GetNumberOfPoints(); i++){nextPipeFace = new PipeFace();if (i == linePoints.GetNumberOfPoints() - 1){first = linePoints.GetPoint(i - 1);next = linePoints.GetPoint(i);norm = new double[3] { next[0] - first[0], next[1] - first[1], next[2] - first[2] };double[] moveValue = norm;nextPipeFace = new PipeFace(lastPipeFace, moveValue, 0, new double[] { 0, 0, 0 });nextPipeFace.InsertPoints(ref Points);nextPipeFace.CellFace(ref Plane);}else{first = linePoints.GetPoint(i - 1);next = linePoints.GetPoint(i);norm = new double[3] { next[0] - first[0], next[1] - first[1], next[2] - first[2] };double[] moveValue = norm;// 移动到末端节点double[] trid = linePoints.GetPoint(i + 1);PipeFace nodePipe_1 = new PipeFace(lastPipeFace, moveValue, 0, new double[] { 0, 0, 0 });double[] normNext = new double[3] { trid[0] - next[0], trid[1] - next[1], trid[2] - next[2] };double[] rotNorm = CrossProduct(normNext, norm);double rotValue = CalculateAngle(normNext, norm);PipeFace nodePipe_2 = new PipeFace(nodePipe_1, new double[] { 0, 0, 0 }, rotValue, rotNorm);// 计算偏移double[] norm2 = new double[3] { trid[0] - next[0], trid[1] - next[1], trid[2] - next[2] };double dis = CalculateDistance(first, next);norm2 = NormalizeVector(norm2);double[] tempPoint = MovePoint(next, norm2, dis);norm2 = new double[3] { tempPoint[0] - first[0], tempPoint[1] - first[1], tempPoint[2] - first[2] };norm2 = NormalizeVector(norm2);vtkPlane plane = new vtkPlane();plane.SetNormal(norm2[0], norm2[1], norm2[2]);plane.SetOrigin(next[0], next[1], next[2]);vtkPoints outPoints_1 = new vtkPoints();outPoints_1.DeepCopy(lastPipeFace.outPoints);vtkPoints inPoints_1 = new vtkPoints();inPoints_1.DeepCopy(lastPipeFace.intPoints);vtkPoints outPoints_2 = new vtkPoints();outPoints_2.DeepCopy(nodePipe_1.outPoints);vtkPoints inPoints_2 = new vtkPoints();inPoints_2.DeepCopy(nodePipe_1.intPoints);// 投影到交界平面for (int k = 0; k < outPoints_2.GetNumberOfPoints(); k++){double[] pout1 = outPoints_1.GetPoint(k);double[] pin1 = inPoints_1.GetPoint(k);IntPtr pOut1Ptr = Marshal.AllocCoTaskMem(sizeof(double) * 3);Marshal.Copy(pout1, 0, pOut1Ptr, 3);IntPtr pIn1Ptr = Marshal.AllocCoTaskMem(sizeof(double) * 3);Marshal.Copy(pin1, 0, pIn1Ptr, 3);double[] pout2 = outPoints_2.GetPoint(k);double[] pin2 = inPoints_2.GetPoint(k);IntPtr pOut2Ptr = Marshal.AllocCoTaskMem(sizeof(double) * 3);Marshal.Copy(pout2, 0, pOut2Ptr, 3);IntPtr pIn2Ptr = Marshal.AllocCoTaskMem(sizeof(double) * 3);Marshal.Copy(pin2, 0, pIn2Ptr, 3);// 外圈偏移点double t = 0;IntPtr outPtr = Marshal.AllocCoTaskMem(sizeof(double) * 3);plane.IntersectWithLine(pOut1Ptr, pOut2Ptr, ref t, outPtr);Marshal.Copy(outPtr, pout2, 0, 3);outPoints_2.SetPoint(k, pout2[0], pout2[1], pout2[2]);// 内圈偏移点IntPtr inPtr = Marshal.AllocCoTaskMem(sizeof(double) * 3);plane.IntersectWithLine(pIn1Ptr, pIn2Ptr, ref t, inPtr);Marshal.Copy(inPtr, pin2, 0, 3);inPoints_2.SetPoint(k, pin2[0], pin2[1], pin2[2]);}nextPipeFace.center = next;nextPipeFace.outPoints = outPoints_2;nextPipeFace.intPoints = inPoints_2;nextPipeFace.InsertPoints(ref Points);nextPipeFace.CellFace(ref Plane);lastPipeFace = nodePipe_2;}PipeFace.CellArray(lastCalcuPipeFace, nextPipeFace, ref Plane);lastCalcuPipeFace = nextPipeFace;}PolyData = new vtkPolyData();PolyData.SetPoints(Points);PolyData.SetStrips(Plane);}public vtkPolyData GetOutput(){return PolyData;}public static double CalculateAngle(double[] vectorA, double[] vectorB){// 检查向量长度是否相等if (vectorA.Length != 3 || vectorB.Length != 3){throw new ArgumentException("Both vectors must be 3-dimensional.");}// 计算点积double dotProduct = vectorA[0] * vectorB[0] + vectorA[1] * vectorB[1] + vectorA[2] * vectorB[2];// 计算两个向量的模double magnitudeA = Math.Sqrt(vectorA[0] * vectorA[0] + vectorA[1] * vectorA[1] + vectorA[2] * vectorA[2]);double magnitudeB = Math.Sqrt(vectorB[0] * vectorB[0] + vectorB[1] * vectorB[1] + vectorB[2] * vectorB[2]);// 计算夹角的余弦值double cosTheta = dotProduct / (magnitudeA * magnitudeB);// 防止浮点误差引起的 Math.Acos 域错误cosTheta = Math.Max(-1.0, Math.Min(1.0, cosTheta));// 计算并返回夹角(以弧度为单位)double angleInRadians = Math.Acos(cosTheta);// 将弧度转换为度数(如果需要)double angleInDegrees = angleInRadians * (180.0 / Math.PI);return angleInDegrees;}public static double[] NormalizeVector(double[] vector){// 检查向量长度是否为3if (vector.Length != 3){throw new ArgumentException("The input vector must be 3-dimensional.");}// 计算向量的模double magnitude = Math.Sqrt(vector[0] * vector[0] + vector[1] * vector[1] + vector[2] * vector[2]);// 检查向量模是否为零if (magnitude == 0){return vector;throw new ArgumentException("The magnitude of the vector is zero, cannot normalize.");}// 计算单位化向量double[] normalizedVector = new double[3];normalizedVector[0] = vector[0] / magnitude;normalizedVector[1] = vector[1] / magnitude;normalizedVector[2] = vector[2] / magnitude;return normalizedVector;}public static double CalculateDistance(double[] p1, double[] p2){// 计算各坐标的差值double dx = p2[0] - p1[0];double dy = p2[1] - p1[1];double dz = p2[2] - p1[2];// 使用欧几里得距离公式计算距离double distance = Math.Sqrt(dx * dx + dy * dy + dz * dz);return distance;}public static double[] CrossProduct(double[] vectorA, double[] vectorB){// 检查向量长度是否为3if (vectorA.Length != 3 || vectorB.Length != 3){throw new ArgumentException("Both vectors must be 3-dimensional.");}// 计算叉积double[] crossProduct = new double[3];crossProduct[0] = vectorA[1] * vectorB[2] - vectorA[2] * vectorB[1];crossProduct[1] = vectorA[2] * vectorB[0] - vectorA[0] * vectorB[2];crossProduct[2] = vectorA[0] * vectorB[1] - vectorA[1] * vectorB[0];return crossProduct;}public static double[] MovePoint(double[] point, double[] direction, double distance){if (point.Length != 3 || direction.Length != 3){throw new ArgumentException("Both the point and direction vector must be 3-dimensional.");}// 计算方向向量的模double magnitude = Math.Sqrt(direction[0] * direction[0] + direction[1] * direction[1] + direction[2] * direction[2]);// 单位化方向向量double[] unitDirection = new double[3];unitDirection[0] = direction[0] / magnitude;unitDirection[1] = direction[1] / magnitude;unitDirection[2] = direction[2] / magnitude;// 计算移动向量double[] moveVector = new double[3];moveVector[0] = unitDirection[0] * distance;moveVector[1] = unitDirection[1] * distance;moveVector[2] = unitDirection[2] * distance;// 更新点的位置double[] newPoint = new double[3];newPoint[0] = point[0] + moveVector[0];newPoint[1] = point[1] + moveVector[1];newPoint[2] = point[2] + moveVector[2];return newPoint;}public class PipeFace{public double[] center;public vtkPoints outPoints;public vtkPoints intPoints;public List<int> outId = new List<int>();public List<int> inId = new List<int>();public PipeFace(){}public PipeFace(double[] cen, double[] norm, double outRadius, double inRadius, int sides){center = cen;outPoints = GeneratePolygonPoints(center, norm, outRadius, sides);intPoints = GeneratePolygonPoints(center, norm, inRadius, sides);}public PipeFace(PipeFace lastPipeFace, double[] moveValue, double rotValue, double[] rotNorm){TransPipeFace(lastPipeFace, moveValue, rotValue, rotNorm);}public void TransPipeFace(PipeFace lastPipeFace, double[] moveValue, double rotValue, double[] rotNorm){vtkPolyData outPointData = new vtkPolyData();outPointData.SetPoints(lastPipeFace.outPoints);vtkPolyData inPointData = new vtkPolyData();inPointData.SetPoints(lastPipeFace.intPoints);center = lastPipeFace.center;center[0] = lastPipeFace.center[0] + moveValue[0];center[1] = lastPipeFace.center[1] + moveValue[1];center[2] = lastPipeFace.center[2] + moveValue[2];rotNorm = NormalizeVector(rotNorm);vtkTransform transform = new vtkTransform();transform.Translate(moveValue[0], moveValue[1], moveValue[2]);transform.Translate(center[0], center[1], center[2]);transform.RotateWXYZ(-rotValue, rotNorm[0], rotNorm[1], rotNorm[2]);transform.Translate(-center[0], -center[1], -center[2]);transform.Update();vtkTransformFilter transFilter = new vtkTransformFilter();transFilter.SetInputData(outPointData);transFilter.SetTransform(transform);transFilter.Update();outPoints = transFilter.GetOutput().GetPoints();transFilter.SetInputData(inPointData);transFilter.SetTransform(transform);transFilter.Update();intPoints = transFilter.GetOutput().GetPoints();double[] cen2 = transFilter.GetOutput().GetCenter();}public void InsertPoints(ref vtkPoints points){if (outPoints != null && intPoints != null){for (int n = 0; n < outPoints.GetNumberOfPoints(); n++){double[] pos = outPoints.GetPoint(n);int id = (int)points.InsertNextPoint(pos[0], pos[1], pos[2]);outId.Add(id);}for (int k = 0; k < intPoints.GetNumberOfPoints(); k++){double[] pos = intPoints.GetPoint(k);int id = (int)points.InsertNextPoint(pos[0], pos[1], pos[2]);inId.Add(id);}}}public void CellFace(ref vtkCellArray plane){int npts = outId.Count + inId.Count;if (npts == 0){return;}plane.InsertNextCell(npts + 2);for (int n = 0; n < outId.Count; n++){plane.InsertCellPoint(outId[n]);plane.InsertCellPoint(inId[n]);}plane.InsertCellPoint(outId[0]);plane.InsertCellPoint(inId[0]);}public vtkPoints GeneratePolygonPoints(double[] center, double[] norm, double radius, int sides){vtkRegularPolygonSource polygonSource = new vtkRegularPolygonSource();polygonSource.SetCenter(center[0], center[1], center[2]);polygonSource.SetNormal(norm[0], norm[1], norm[2]);polygonSource.SetRadius(radius);polygonSource.SetNumberOfSides(sides);polygonSource.SetGeneratePolygon(1);polygonSource.SetGeneratePolyline(1);polygonSource.Update();vtkStripper stripper = new vtkStripper();stripper.SetInputData(polygonSource.GetOutput());stripper.JoinContiguousSegmentsOn();stripper.Update();return stripper.GetOutput().GetPoints();}public static void CellArray(PipeFace pipe1, PipeFace pipe2, ref vtkCellArray plane){int inNpts = pipe1.inId.Count + pipe2.inId.Count;// 内外条带plane.InsertNextCell(inNpts + 2);for (int n = 0; n < pipe1.inId.Count; n++){plane.InsertCellPoint(pipe1.inId[n]);plane.InsertCellPoint(pipe2.inId[n]);}plane.InsertCellPoint(pipe1.inId[0]);plane.InsertCellPoint(pipe2.inId[0]);int outNpts = pipe1.outId.Count + pipe2.outId.Count;plane.InsertNextCell(outNpts + 2);for (int n = 0; n < pipe1.outId.Count; n++){plane.InsertCellPoint(pipe1.outId[n]);plane.InsertCellPoint(pipe2.outId[n]);}plane.InsertCellPoint(pipe1.outId[0]);plane.InsertCellPoint(pipe2.outId[0]);}}}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词