TopoDS_Wire在OCC中是边的集合,一个边集合能否构造成一个面,涉及到非常多的判断情况
TopoDS_Shape GeoCommandTool::makeFace(std::vector<TopoDS_Wire>& w)
{
if (w.empty())
return TopoDS_Shape();
std::vector<TopoDS_Wire> wires = w;
//从小到大排列
std::sort(wires.begin(), wires.end(), Wire_Compare());
std::list<TopoDS_Wire> wire_list;
//从大到小装进去
wire_list.insert(wire_list.begin(), wires.rbegin(), wires.rend());
// separate the wires into several independent faces
std::list< std::list<TopoDS_Wire> > sep_wire_list;
while (!wire_list.empty())
{
//先把第一个wire装进去
std::list<TopoDS_Wire> sep_list;
TopoDS_Wire wire = wire_list.front();
wire_list.pop_front();
sep_list.push_back(wire);
std::list<TopoDS_Wire>::iterator it = wire_list.begin();
while (it != wire_list.end())
{
//把连续相交的线都放在一起,判断是否相交
if (isInside(wire, *it))
{
sep_list.push_back(*it);
it = wire_list.erase(it);
}
else
{
++it;
}
}
sep_wire_list.push_back(sep_list);
}
if (sep_wire_list.size() == 1)
{
std::list<TopoDS_Wire>& wires = sep_wire_list.front();
return makeFace(wires);
}
//有多个各自相连的线,那么就把它当成混合物处理
else if (sep_wire_list.size() > 1)
{
TopoDS_Compound comp;
BRep_Builder builder;
builder.MakeCompound(comp);
for (std::list< std::list<TopoDS_Wire> >::iterator it = sep_wire_list.begin(); it != sep_wire_list.end(); ++it)
{
//各自生成一个面,添加进混合物中
TopoDS_Shape aFace = makeFace(*it);
if (!aFace.IsNull())
builder.Add(comp, aFace);
}
//多个面组合成一个复合物,如果复合物不是封闭的则失败
if (comp.Closed() == false)
{
return TopoDS_Shape();//no closed.
}
return comp;
}
else
{
return TopoDS_Shape(); // error
}
}
TopoDS_Shape GeoCommandTool::makeFace(std::list<TopoDS_Wire>& wires)
{
if (wires.size() < 1)
{
return TopoDS_Shape();
}
BRepBuilderAPI_MakeFace mkFace(wires.front());
const TopoDS_Face& face = mkFace.Face();
if (face.IsNull())
return face;
gp_Dir axis(0, 0, 1);
BRepAdaptor_Surface adapt(face);
if (adapt.GetType() == GeomAbs_Plane)
{
axis = adapt.Plane().Axis().Direction();
}
wires.pop_front();
for (std::list<TopoDS_Wire>::iterator it = wires.begin(); it != wires.end(); ++it)
{
BRepBuilderAPI_MakeFace mkInnerFace(*it);
const TopoDS_Face& inner_face = mkInnerFace.Face();
// failure,直接返回
if (inner_face.IsNull())
return inner_face;
gp_Dir inner_axis(0, 0, 1);
BRepAdaptor_Surface adapt(inner_face);
if (adapt.GetType() == GeomAbs_Plane)
{
inner_axis = adapt.Plane().Axis().Direction();
}
// It seems that orientation is always 'Forward' and we only have to reverse
// if the underlying plane have opposite normals.
if (axis.Dot(inner_axis) < 0)
it->Reverse();
//把所有能组成面的wire都装进去
mkFace.Add(*it);
}
return validateFace(mkFace.Face());
}
完整代码可看