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);
}
}
Discussion
1 archived reply
Posts are displayed in their archived order.
01Commenter-1
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);