How to programatical select a TopoDS_Shape (Face/Edge/Vertex...) in a local context?

Hi everybody!
How to programatical select a TopoDS_Shape( such as Face/Edge/Vertex...) in a local context?

Hugues's picture

This is recurrent question that has still no clear answers. I'm facing the same problem. Actually I can tell interactive objects or topological shapes to be selected, but further user mouse selection on the selected items does not work.
Here is some threads about this issue :

Hope you can find a solution, if so please give it here!!!

Roman Lygin's picture

To select in local context you need to use AIS_InteractiveContext::AddOrRemoveSelect (const TopoDS_Shape&).

To unselect in local context you need to use
AIS_InteractiveContext::AddOrRemoveSelect (const Handle(SelectMgr_EntityOwner) &).
Or AIS_InteractiveContext::::ClearSelected() to unselect all.

So you need to know a correspondence between your subshapes and owners.

To retrieve a shape from the owner use
SelectMgr_EntityOwner:: Shape()

To get an owner for the shape use AIS_InteractiveContext::FindSelectedOwnerFromShape();

For better performance (since FindSelected...() iterates over all shapes) you may want to store owner-shape pairs in some your map.

Other useful methods:

to iterate over currently selected owners use:
for (myAISContext->InitSelected(); myAISContext->MoreSelected(); myAISContext->NextSelected()) {
Handle(SelectMgr_EntityOwner) anOwner = myAISContext->SelectedOwner();

Hope it helps.


Hugues's picture

I retried a modified version of Adrian Helcman's source code for selecting edges. The edges get selected, but shift selection does not work on these edges. You simply cannot deselect them, unless you use simple selection.
Here is the routine :

// Select `edge' among the interactive objects `ais_objects'.
void select_edge (AIS_ListOfInteractive& ais_objects,
const TopologicalEdge& edge, Boolean update_display)
AIS_ListIteratorOfListOfInteractive iobject;
for (iobject.Initialize (ais_objects); iobject.More (); iobject.Next ())
if (iobject.Value ()->IsKind (STANDARD_TYPE (AIS_Shape)))
InteractiveShape interactive = InteractiveShape::DownCast (iobject.Value ());
for (interactive->Init (); interactive->More (); interactive->Next ())
const Handle_SelectMgr_Selection& selection = interactive->CurrentSelection ();
for (selection->Init (); selection->More (); selection->Next ())
const Handle_SelectBasics_SensitiveEntity& po_sel_entity = selection->Sensitive ();
const Handle_SelectBasics_EntityOwner& po_basic_owner = po_sel_entity->OwnerId ();
const Handle_SelectMgr_EntityOwner& po_mgr_owner = Handle_SelectMgr_EntityOwner::DownCast (po_basic_owner);
const TopoDS_Shape& owner_shape = ((Handle_StdSelect_BRepOwner&)po_mgr_owner)->Shape();

if (owner_shape.ShapeType () == TopAbs_EDGE and
TopoDS::Edge (owner_shape).IsSame (edge))
ais_context->AddOrRemoveSelected (po_mgr_owner);

I tried to use the overloaded version of AddOrRemoveSelected i.e. AddOrRemoveSelected (const TopoDS_Shape& shape), but it just does not work, nothing is selected.

Also AIS_InteractiveContext::FindSelectedOwnerFromShape() is not accessible, this function is defined in the class AIS_LocalContext.

So the problem still remains : with OpenCascade it is impossible to have a working programmatic selection.

Roman, have you already succeed with this problem?

ngoctn's picture

I agree with you. AddOrRemoveSelected (const TopoDS_Shape& shape), doesn't work. i tried your code, it work well.
Thanks you verty much.

Roman Lygin's picture

Indeed, I just realized that I had patched OCC AIS_LocalContext_1.cxx to make it work (in similar way as suggested here - Also to implement Add... functionality another couple of files need to be patched. I'll send a code to OCC guys to have them review/integrate as soon as they approach to it.
Feel free to contact me if you need it earlier (email available in this tread).

Roman Lygin's picture

Hi Hugues,
The excerpts I posted above are ones from a real working code.
Those who are interested may email me.

Hugues's picture

Hi Roman,

Yes I am very interested by the source code you mentionned. What is your email address?

Roman Lygin's picture

It should be visible in the message if you are subscribed to this forum.
Anyway ... roman_lygin at yahoo dot com.

wyiya's picture
Hugues's picture

Hello Roman,
I have installed your patches ("fix018_update5") and rebuilt TKV3d.dll. Now AIS_InteractiveContext::AddOrRemoveSelected (const TopoDS_Shape& shape) works. That's a good point.
But it still upset shift selections.
It is really a huge bug of Open Cascade v52.
Try this test case :
-Create an interactive context and a view.
-Open a local context in the interative context.
-Set the interactive context to be in edge selection model for example.
-Load in the interactive context a shape.
-For every edges of the loaded shape, cal AddOrRemoveSelected.
-Implement shift selection, i.e. when the left mouse button is clicked, call AIS_InteraciveContext::ShiftSelect. Do not forget to call MoveTo (x, y) on mouse moves.
-Compile and test the program : all the displayed edges should be selected, try to click (unselect/select) on them : shift selection does not work.

Roman, have you already tested function AddOrRemoveSelected and user shift selections? It is clear to me that they do not work together.

Roman Lygin's picture

Hi Hugues,

I can’t reproduce your problem. Instead I can successfully enable shift-selection as follows:
1). Install the patch I sent you
2). In AIS_Local_Context_1.cxx add the following lines at line #1538
if (myMainVS->Primitives().IsEmpty()) {
myMainVS->UpdateSort(); //ensure sensitive areas are computed after local context has been opened
they should be followed by
SelectMgr_DataMapIteratorOfDataMapOfIntegerSensitive aSensitiveIt (myMainVS->Primitives());

3). Use AISSelect sample and add the following lines into AISSelectDoc.cpp (::OnEdges() is an existing method)

void CAISSelectDoc::OnEdges()

//Roman Lygin - start of the test
//select all edges of all displayed objects
AIS_ListOfInteractive aDisplayedList;
Standard_Boolean aNeutralPointOnly = Standard_True;
myAISContext->DisplayedObjects (aDisplayedList, aNeutralPointOnly);
AIS_ListIteratorOfListOfInteractive anIter (aDisplayedList);
for (; anIter.More(); anIter.Next()) {
Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (anIter.Value());
if (!aShape.IsNull()) {
TopExp_Explorer anExp (aShape->Shape(), TopAbs_EDGE);
for (; anExp.More(); anExp.Next()) {
myAISContext->AddOrRemoveSelected (anExp.Current(), Standard_False);
myAISContext->UpdateCurrentViewer(); //now update the context
//Roman Lygin - end of the test

4). Now run the sample:
- create a box (clicking on the box icon)
- open a local context with edge selection (clicking on the edge icon) – the code above will be called
- this will select all edges (using AddOrRemoveSelected())
- use Shift-MB1 (left mouse click) to select/unselect.

If your problem still persists consider creating a test case and check with OCC team.
Hope this helps.

Hugues's picture

Roman, thanks for your elaborated answer.
I have tested what you have suggested. Shortly, it works. With the box sample I can select edges after they were selected by calls to AddOrRemoveSelected().
But instead having a simple box I have loaded an IGES shape and there is still the same problem I mentionned : shift selection gets confused.

I have made a little program that isolates the problem. Those who have Qt installed can compile it and test it. It is a very small program. Basically it sets up an OCC environement, loads an IGES shape, and selects all the edges. Then it lets the user performs shift selections.

I can send it to anyone who is interested in this problem. I have sent it to you Roman, so you can give it a look, so you can tell if there is a bug or not.

Roman Lygin's picture

(Posted here for others that could encounter the same confusion)

Hi Hugues,

Well, there is NO bug in OCC. It's just a matter of your shape:
it is a compound consiting of 1 face and 4 floating edges that
overlap with face boundaries.

So, when you first call AddOrRemoveSelected() on all edges, both face
boundaries and floating edges get selected. When you click on
any edge (calling ShiftSelect()), it (either boundary or floating)
is UNselected, but you don't see any difference because the other
still remains selected. When clicking again - unselected edge again
becomes selected.
So at any moment, you either have 1 or 2 selected edges and this
confuses you ;-).

So, remove those floating edges (during import for example) and you
will see that everything gets fine there ! I sent you a screenshot.

Hope this helps.

Good luck !

Hugues's picture

Hi Roman,

Really thank you for the time you took to help us. And my apologizes on my mistakes and misunderstanding. Now AddOrRemoveSelected() works perfectly for me! Open Cascade rocks!

Thanks a lot again.