如何使用TopoDS_Wire构造TopoDS_Face

时间:2024-03-12 17:08:56

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());
}

完整代码可看