使用OCCT构建两个面之间的最短路径

发布时间 2023-12-21 09:19:47作者: GG_bo

查找两个面之间的最短面路径

查找面的邻面。

std::vector<TopoDS_Face> OCCTUtility::adjacentFace(TopoDS_Face const &face, std::optional<TopoDS_Shape>     shape, std::optional<TopTools_IndexedDataMapOfShapeListOfShape> edgeMapFace)
{
    std::vector<TopoDS_Face> result{};
    if (!edgeMapFace)
    {
        TopTools_IndexedDataMapOfShapeListOfShape tmp{};
        if (!shape)
            return result;
        TopExp::MapShapesAndAncestors(shape.value(), TopAbs_EDGE, TopAbs_FACE, tmp);
        if (tmp.Size() == 0)
            return result;
        edgeMapFace = std::move(tmp);
    }

    for (TopExp_Explorer exp(face, TopAbs_EDGE); exp.More(); exp.Next())
    {
        auto faces = edgeMapFace.value().FindFromKey(exp.Current());
        for (auto it = faces.begin(); it != faces.end(); ++it)
        {
            if (*it != face)
                result.push_back(TopoDS::Face(*it));
        }
    }
    return result;
}

广度优先算法搜索面路径结果

std::vector<TopoDS_Face> OCCTUtility::shortestPathOnTwoFace(TopoDS_Shape const &shape, TopoDS_Face const &face1, TopoDS_Face const &face2) noexcept
{
    if (shape.IsNull() || face1.IsNull() || face1.ShapeType() != TopAbs_FACE || face2.IsNull() || face2.ShapeType() != TopAbs_FACE)
        return {};

    TopTools_MapOfShape processedShape{};
    std::queue<std::pair<TopoDS_Face, std::vector<TopoDS_Face>>> not_processedShape{};
    TopTools_IndexedDataMapOfShapeListOfShape edgeMapFace{};
    std::vector<TopoDS_Face> facePath;

    TopExp::MapShapesAndAncestors(shape, TopAbs_EDGE, TopAbs_FACE, edgeMapFace);
    not_processedShape.push({});
    not_processedShape.front().first = face1;
    not_processedShape.front().second = adjacentFace(not_processedShape.front().first, shape, edgeMapFace);

    while (!not_processedShape.empty())
    {
        auto node = not_processedShape.front();
        not_processedShape.pop();

        if (processedShape.Contains(node.first))
            continue;

        facePath.push_back(node.first);
        for (auto const &i : node.second)
        {
            if (processedShape.Contains(i))
                continue;
            facePath.push_back(i);
            if (i == face2)
                return facePath;

            not_processedShape.push({i, adjacentFace(i, {}, edgeMapFace)});
            facePath.pop_back();
        }
    }
    return {};
}

可依据上一步结果(面最短路径)获取最短边(非联通,非C0)路径

获取两个面之间的通用边

std::optional<TopoDS_Edge> OCCTUtility::commentEdge(TopoDS_Face const &face1, TopoDS_Face const &face2) noexcept
{
    if (face1.IsNull() || face2.IsNull())
        return {};

    TopTools_IndexedMapOfShape faceMapEdge1{};
    TopExp::MapShapes(face1, TopAbs_EDGE, faceMapEdge1);
    TopTools_IndexedMapOfShape faceMapEdge2{};
    TopExp::MapShapes(face2, TopAbs_EDGE, faceMapEdge2);

    std::vector<TopoDS_Edge> edges;
    for (auto it = faceMapEdge1.cbegin(); it != faceMapEdge1.cend(); ++it)
    {
        auto fit = std::find_if(faceMapEdge2.cbegin(), faceMapEdge2.cend(),[it](TopoDS_Shape shape)
        {
            return shape.IsSame(*it);
        });
        if (fit != faceMapEdge2.cend())
            edges.push_back(TopoDS::Edge(*fit));
    }
    return edges.back();
}