Obtaining absolute transformation from AIS_Shape

I have an AIS_Shape which has been loaded from file, then had SetLocalTransformation() applied to it (rotation + scaling). It display fine...

I now want to process vertices from this shape, using TopExp_Explorer - but just walking the underlying TopoDS_Shape gives me the pre-local-transformation rotation/scaling.

Q: How do I obtain an 'absolute' shape from AIS_Shape/TopoDS_Shape which has already had local transformations applied? (specifically rotation/scaling)

The obvious work-around is to re-transform the underlying shape, but alas I cannot get BRepBuilderAPI_Transform() to apply the transforms: it either does nothing or throws exceptions - probably because this shape was loaded from an OBJ file and has a very weird internal structure (21637 vertices from only 5 faces???)

For completeness, here is my code to walk the shape (if it helps others)...

void AIS_Shape_Derived_Class::displayVertices() 
{

    struct PntCompare
    {
        bool operator()(const gp_Pnt& a, const gp_Pnt& b) const
        {
            return !a.IsEqual(b, 0.1);
        }
    };
    std::set<gp_Pnt, PntCompare> uniqueVertices;


    // Apply the local transformation to underlying shape
    TopoDS_Shape transformedShape = BRepBuilderAPI_Transform(Shape(), LocalTransformation(), true);
    // DOESN'T DO ANYTHING

    //Walk the faces and reconstruct vertices from them
    TopExp_Explorer explorer;
    for (explorer.Init(transformedShape, TopAbs_FACE); explorer.More(); explorer.Next())
    {
        const TopoDS_Face& face = TopoDS::Face(explorer.Current());
        TopLoc_Location loc();
        Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation(face, loc);

        if (!triangulation.IsNull())
        {
            for (Standard_Integer i = 1; i <= triangulation->NbNodes(); i++)
            {
                gp_Pnt p = triangulation->Node(i).Transformed(loc);
                uniqueVertices.insert(p);
            }
        }
    }

    // Display unique vertices
    for (const gp_Pnt& p : uniqueVertices)
    {
        Handle(AIS_Point) ap = new AIS_Point(new Geom_CartesianPoint(p));
        myCTXPtr->Display(ap, false);
    }
}
gkv311 n's picture

Why over-complicating things with BRepBuilderAPI_Transform, if what you are looking for is a list of transformed 3D points? Just apply gp_Trsf/TopLoc_Location straight ahead to the points.

    const TopoDS_Shape& aShape = Shape();
    const gp_Trsf& aLocTrsf = LocalTransformation();

    // Walk the faces and reconstruct vertices from them
    for (TopExp_Explorer explorer(aShape, TopAbs_FACE); explorer.More(); explorer.Next())
    {
        const TopoDS_Face& face = TopoDS::Face(explorer.Current());
        TopLoc_Location aFaceLoc;
        if (Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation(face, aFaceLoc))
        {
            TopLoc_Location aLoc = TopLoc_Location(aLocTrsf) * aFaceLoc;
            for (Standard_Integer i = 1; i <= triangulation->NbNodes(); i++)
            {
                gp_Pnt p = triangulation->Node(i).Transformed(aLoc);
                uniqueVertices.insert(p);
            }
        }
    }

    // Display unique vertices
    Handle(Graphic3d_ArrayOfPoints) aPntArray = new Graphic3d_ArrayOfPoints(uniqueVertices.size());
    for (const gp_Pnt& p : uniqueVertices)
    {
        aPntArray->AddVertex(p);
    }
    Handle(AIS_PointCloud) aPntCloud = new AIS_PointCloud();
    aPntCloud->SetPoints(aPntArray);
    InteractiveContext()->Display(aPntCloud , false);