How to get geometric data of selection?

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?

Dmitrii Pasukhin's picture

Hello, there are should not be any problem with getting TopoDS_Vertex if aShape.ShapeType() == TopAbs_Vertex. Please make a look into https://dev.opencascade.org/doc/overview/html/occt_user_guides__modeling...

There a small example

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, Dmitrii.

Ivan P's picture

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?

Dmitrii Pasukhin's picture

Sometimes solid have no vertices (solid of tessellated faces).

You be able to iterate throught choosen shape to get only Vertives use the next documentation:https://dev.opencascade.org/doc/overview/html/occt_user_guides__modeling...

But it looks like you need to choose a little different way to recieve a mouse click position.

Best regards, Dmitrii.

gkv311 n's picture

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:

  const Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast (SelectedOwner());
  TopoDS_Shape aSelShape     = aBRepOwner->Shape();
  TopoDS_Shape aLocatedShape = aSelShape.Located (aBRepOwner->Location() * aSelShape.Location());
Ivan P's picture

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

    }
}
}
Dmitrii Pasukhin's picture

Please use "BRep_Tool::Pnt(TopoDS::Vertex (theShape));" to get vertex position.

I'm not sure, but maybe you need to use gkv311 n's sample to move shape to the correct position before getting gp_Pnt:

  const Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast (SelectedOwner());
  TopoDS_Shape aSelShape     = aBRepOwner->Shape();
  TopoDS_Shape aLocatedShape = aSelShape.Located (aBRepOwner->Location() * aSelShape.Location());

Best regards, Dmitrii.

Ivan P's picture

> 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 gkv311 n'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

gkv311 n's picture

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.