Hello. I have managed to dispatch when selection occurs. I have have also managed to iterate of objects of class AIS_InteractiveObject. My final step would be obtaining geometric parameters of my selection - for example - coordinates of points. Here is my code:
void GlfwOcctView::OnSelectionChanged(const Handle(AIS_InteractiveContext)& theCtx, const Handle(V3d_View)& theView)
{
// on selection changed handler.
// see \opencascade-7.7.0\samples\qt\Common\src\ApplicationCommon.cxx, OnSelectionChanged
int selectedItemsCount = theCtx->NbSelected();
selectionDescriptor = "SELECTION INFO. ITEMS: ";
selectionDescriptor.append(std::to_string(selectedItemsCount));
if (selectedItemsCount) {
for (theCtx->InitSelected(); theCtx->MoreSelected(); theCtx->NextSelected()) {
opencascade::handle<AIS_InteractiveObject> obbjj = theCtx->SelectedInteractive();
if (obbjj->Type() == AIS_KindOfInteractive_Shape) {
opencascade::handle<AIS_Shape> shapeFromSelection = opencascade::handle<AIS_Shape>::DownCast(obbjj);
if (shapeFromSelection->Type() == AIS_KindOfInteractive_Shape) {
// LET'S SAY, only points are selectable
TopoDS_Shape shapeGeometric = shapeFromSelection->Shape();
// So, how do I get coordinates of that selected point?
}
}
}
}
}
Unfortunately, I am not able to cast TopoDS_Shape to TopoDS_Vertex - compiler won't allow me to do this for some reason. And even if I could - all subclasses of TopoDS_Shape do not contain geometrical data, as I have seen on manual. I think, I have really lost here.
how do I get coordinates of that selected point on object on scene?
void Process (const TopoDS_Shape& theShape)
{
if (theShape.Shapetype() == TopAbs_VERTEX)
{
TopoDS_Vertex V;
V = TopoDS::Vertex (theShape); // Also correct
TopoDS_Vertex V2 = theShape; // Rejected by the compiler
TopoDS_Vertex V3 = TopoDS::Vertex (theShape); // Correct
}
else if (theShape.ShapeType() == TopAbs_EDGE)
{
ProcessEdge (theShape); // This is rejected
ProcessEdge (TopoDS::Edge (theShape)); // Correct
}
else
{
std::cout << "Neither a vertex nor an edge?\n";
ProcessEdge (TopoDS::Edge (theShape));
// OK for compiler but an exception will be raised at run-time
}
}
Best regards, Commenter-1.
02Author
Thank you for a quick answer - but seems like that the problem is somewhat different.
I do select VERTICES by mouse in my program, but instead selected data is viewed as SOLID. Vertices are definitely components of SOLID, but actual selected vertice data is more useful.
if (obbjj->Type() == AIS_KindOfInteractive_Shape) {
opencascade::handle<AIS_Shape> shapeFromSelection = opencascade::handle<AIS_Shape>::DownCast(obbjj);
if (shapeFromSelection->Type() == AIS_KindOfInteractive_Shape) {
TopoDS_Shape shapeGeometric = shapeFromSelection->Shape();
TopAbs_ShapeEnum valll = shapeGeometric.ShapeType();
if (valll == TopAbs_ShapeEnum::TopAbs_VERTEX) {
// Never gets, because valll is SOLID
}
}
}
How may I get those selected vertices?
03Commenter-1
Sometimes solid have no vertices (solid of tessellated faces).
But it looks like you need to choose a little different way to recieve a mouse click position.
Best regards, Commenter-1.
04Commenter-2
for (theCtx->InitSelected(); theCtx->MoreSelected(); theCtx->NextSelected()) {
opencascade::handle obbjj = theCtx->SelectedInteractive();
You get Interactive Object here (AIS_InteractiveContext::SelectedInteractive()), while you need working with selection Owners ( AIS_InteractiveContext::SelectedOwner()) after activating sub-shape selection modes. Then StdSelect_BRepOwner will bring you a picked TopoDS_Vertex, if this is what you are looking for.
From AIS_InteractiveContext::SelectedShape() documentation:
Thanks a lot for your answers. They were super helpful
Here is a complete code which I managed to make. It combines information about selected entities into std::string
void GlfwOcctView::OnSelectionChanged(const Handle(AIS_InteractiveContext)& theCtx, const Handle(V3d_View)& theView)
{
// on selection changed handler.
// see \opencascade-7.7.0\samples\qt\Common\src\ApplicationCommon.cxx, OnSelectionChanged - how to detect selection
// also https://stackoverflow.com/q/69475538/5128696
int selectedItemsCount = theCtx->NbSelected();
selectionDescriptor = "SELECTION INFO. ITEMS: ";
selectionDescriptor.append(std::to_string(selectedItemsCount));
if (selectedItemsCount) {
for (theCtx->InitSelected(); theCtx->MoreSelected(); theCtx->NextSelected()) {
// selection mechanism explained: https://dev.opencascade.org/doc/overview/html/occt_user_guides__visualization.html#occt_visu_2_2
opencascade::handle<SelectMgr_EntityOwner> selOwnrEntitySelected = theCtx->SelectedOwner();
opencascade::handle < SelectMgr_SelectableObject> selectableObj= selOwnrEntitySelected->Selectable();
opencascade::handle< StdSelect_BRepOwner > brepOwnrEntitySelected = opencascade::handle<StdSelect_BRepOwner>::DownCast(selOwnrEntitySelected);
TopoDS_Shape shapeGeometric2 = brepOwnrEntitySelected->Shape();
TopAbs_ShapeEnum shapeTypeEntitySelected = shapeGeometric2.ShapeType();
if (shapeTypeEntitySelected == TopAbs_ShapeEnum::TopAbs_VERTEX) {
// and - I have obtained real geometry instance. It is safe to down cast, because we know and are able to guarantee exact type.
// TopoDS_Shape does not contain geometry data by itself , but it refers to TShape(), which retruns it. TopoDS_TVertex does not provide geometry data as well, but BRep_TVertex does provide it.
// luckily, these all are wrapped in smart pointers, so memory leaks are unlikely here
// see also https://dev.opencascade.org/doc/overview/html/occt_user_guides__modeling_data.html#autotoc_md100
opencascade::handle<BRep_TVertex> realVertex = opencascade::handle<BRep_TVertex>::DownCast(shapeGeometric2.TShape());
char buffer[100];
sprintf_s(buffer,"\nPoint: (%.3f ; %.3f ; %.3f)", realVertex->Pnt().X(), realVertex->Pnt().Y(), realVertex->Pnt().Z());
selectionDescriptor.append(buffer);
} else if (shapeTypeEntitySelected == TopAbs_ShapeEnum::TopAbs_EDGE) {
// calculate length of selected edge, it seems way too unclear. Potentially, area of plane may be same
// ancient forum post (from 2006): https://dev.opencascade.org/content/getting-size-shape
GProp_GProps myProps;
TopoDS_Edge myEdge = TopoDS::Edge(shapeGeometric2);
BRepGProp::LinearProperties(myEdge, myProps);
Standard_Real fLength = myProps.Mass();
char buffer[100];
sprintf_s(buffer, "\nEdge: Length = %.3f ;", fLength );
selectionDescriptor.append(buffer);
}
}
}
}
06Commenter-1
Please use "BRep_Tool::Pnt(TopoDS::Vertex (theShape));" to get vertex position.
I'm not sure, but maybe you need to use Commenter-2's sample to move shape to the correct position before getting gp_Pnt:
> Please use "BRep_Tool::Pnt(TopoDS::Vertex (theShape));" to get vertex position
Is it just to make shorter chain of calls and to eliminate transition to TShape?
> I'm not sure, but maybe you need to use Commenter-2's sample to move shape to the correct position before getting gp_Pnt
Why? Do you assume that `StdSelect_BRepOwner` and corresponding `TopoDS_Shape` may have different geometrical placement? That seems somewhat confusing
08Commenter-2
Is it just to make shorter chain of calls and to eliminate transition to TShape?
It is because TShape classes are (internal) implementation details, that are not expected to be directly used in application code - hence, BRepTools and similar tools exist.
Why? Do you assume that StdSelect_BRepOwner and corresponding TopoDS_Shape may have different geometrical placement? That seems somewhat confusing
Take into account that Interactive Object might have its own location, apart from shape location - e.g. moved by AIS_Manipulator or programically.