因为vtkIntersectionPolyDataFilter 交线算法有问题所以改为 OCCT BRepAlgoAPI_Section交线算法。
OCCT 生成一个正方体和球体
BRepPrimAPI_MakeBox brepBox = new BRepPrimAPI_MakeBox(new Pnt(0,0,0),10,10,10);
vtkPolyData boxData = OcctConvert.TopoDsShapeToPolyData(brepBox.Shape());
BRepPrimAPI_MakeSphere brepSphere = new BRepPrimAPI_MakeSphere(new Pnt(5,5,5),6);
vtkPolyData sphereData = OcctConvert.TopoDsShapeToPolyData(brepSphere.Shape());
执行OCCT 交线算法
BRepAlgoAPI_Section brepSection = new BRepAlgoAPI_Section(brepBox.Shape(), brepSphere.Shape());
brepSection.ComputePCurveOn1(true);
brepSection.Approximation(true);
brepSection.Build();
OCCT 交线 转换为 vtk
因为OCCT 的 Edge 可能是无序的所以先排序,其次几何上明显是相连的Edge Chains存储时却不是相连,Chains 可以 看做是vtk 的连通域,所以要对Edge 进行连通域的分类。
public static vtkPolyData ChainEdgeList(TopoDS_Shape shape)
{
var order = new ShapeAnalysis_WireOrder();
List<TopoDS_Edge> edges = ShapeEdges(shape);
foreach (var edge in edges)
{
var first = BRep_Tool.Pnt(TopExp.FirstVertex(edge));
var last = BRep_Tool.Pnt(TopExp.LastVertex(edge));
if (edge.Orientation() == TopAbs_Orientation.FORWARD)
order.Add(first.Coord, last.Coord);
else
order.Add(last.Coord, first.Coord);
}
order.Perform(true);
Dictionary<int,List<TopoDS_Edge>> edgeChanis = new Dictionary<int, List<TopoDS_Edge>>();
vtkPoints points = new vtkPoints();
vtkCellArray cellArray = new vtkCellArray();
if (order.IsDone())
{
order.SetChains(0.1);
Pnt lastPoint = new Pnt(-9999,0,0);
for (int chain = 1; chain <= order.NbChains(); chain++)
{
int startIndex = 0, endIndex = 0;
order.Chain(chain, ref startIndex, ref endIndex);
if (startIndex > endIndex)
continue;
edgeChanis.Add(chain-1, new List<TopoDS_Edge>());
for (int index = startIndex; index <= endIndex; index++)
{
int orderIndex = order.Ordered(index);
int originalIndex = Math.Abs(orderIndex) - 1;
if (orderIndex < 0)
{
edges[originalIndex] = ReverseCurveEdge(edges[originalIndex]);
}
TopoDS_Edge edge = edges[originalIndex];
edgeChanis[chain-1].Add(edge);
}
}
bool found = true;
while(found == true)
{
found = false;
for (int i = 0; i < edgeChanis.Keys.Count; i++)
{
if (edgeChanis.Values.ElementAt(i).Count == 0)
{
continue;
}
int keyi = edgeChanis.Keys.ElementAt(i);
for (int j = 0; j < edgeChanis.Keys.Count; j++)
{
if (i == j)
{
continue;
}
int keyj = edgeChanis.Keys.ElementAt(j);
if (edgeChanis[keyj].Count == 0)
{
continue;
}
TopoDS_Edge ife = edgeChanis[keyi].First();
TopoDS_Edge ile = edgeChanis[keyi].Last();
TopoDS_Edge jfe = edgeChanis[keyj].First();
TopoDS_Edge jle = edgeChanis[keyj].Last();
BRepBuilderAPI_MakeWire mWireLF = new BRepBuilderAPI_MakeWire();
mWireLF.Add(ile);
mWireLF.Add(jfe);
BRepBuilderAPI_MakeWire mWireFL = new BRepBuilderAPI_MakeWire();
mWireFL.Add(jle);
mWireFL.Add(ife);
if (mWireLF.Error() != BRepBuilderAPI_WireError.DisconnectedWire)
{
List<TopoDS_Edge> tempEdges = new List<TopoDS_Edge>();
tempEdges.InsertRange(0,edgeChanis[keyj]);
int numj = tempEdges.Count;
for (int k = 0; k < numj; k++)
{
edgeChanis[keyi].Add(tempEdges[k]);
}
edgeChanis[keyj].Clear(); ;
found = true;
continue;
}
else if (mWireFL.Error() != BRepBuilderAPI_WireError.DisconnectedWire)
{
List<TopoDS_Edge> tempEdges = new List<TopoDS_Edge>();
tempEdges.InsertRange(0, edgeChanis[keyi]);
int numi = edgeChanis[keyi].Count;
for (int k = 0; k < numi; k++)
{
edgeChanis[keyj].Add(tempEdges[k]);
}
edgeChanis[keyi].Clear(); ;
found = true;
i = j;
continue;
}
}
}
}
foreach(List<TopoDS_Edge> es in edgeChanis.Values)
{
if(es.Count==0)
{
continue;
}
vtkLine line = new vtkLine();
int m = 0;
foreach (TopoDS_Edge e in es)
{
double first = 0;
double last = 0;
Geom_Curve curve = BRep_Tool.Curve(e, ref first, ref last);
GProp_GProps props = new GProp_GProps();
BRepGProp.LinearProperties(e, props);
double len = props.Mass();
double step1 = (last - first) / 2;
double numLen = len / 0.1;
double step = (last - first) / numLen;
for (double i = first; i <= last; i += step)
{
Pnt p1 = new Pnt();
curve.D0(i, ref p1);
int id= (int)points.InsertNextPoint(p1.X, p1.Y, p1.Z);
line.GetPointIds().InsertId(m,id);
m++;
}
}
// 这段代码可以不要 封闭/开放
int fisrtId = (int)line.GetPointId(0);
double[] firstPos = points.GetPoint(fisrtId);
int lastid = (int)points.InsertNextPoint(firstPos[0], firstPos[1], firstPos[2]);
line.GetPointIds().InsertId(m, lastid);
//
cellArray.InsertNextCell(line);
}
}
vtkPolyData polyData = new vtkPolyData();
polyData.SetPoints(points);
polyData.SetLines(cellArray);
return polyData;
}