Sunday, April 11, 2010

Get List of All Shapes in OpenCascade

OpenCascade have an interesting design regarding separating between the scene and the visualization (is a Model-View-Controller design). In short the visualization happens in View (and less in Viewer) code, the scene is done in an OpenCascade context. Another good part is that OpenCascade separate the selection from highlighting shapes. The selected shapes are named Current shapes, the selected shapes (that you click on) are named named Selected shapes.
Sometimes it may happen that you will want to select a shape that is under another face, or a bug in OpenCascade visualization will make the selection blinking so you will be hit that you cannot make your shape later. To overcome this, I did tried to make a way to make that pressing a key (exactly Control) and clicking in a place, if there are more objects under mouse, you should get a list of that shapes and you will be able to select the expected one.

This code makes a list will all the selected shapes. As NaroCAD have a persistent way to store the TopoDS_Shapes as the source that generates them, this code will do as following: it will check under the mouse if there is a shape, it identify the node that is the selection one, it hides the shape, and go forward until it will not find nothing under mouse. At the end, it will reshow the hidden shapes. As the shapes are decorated by the NodeBuilder the revisualization is done automatically by NaroCAD framework, but if you will want to do similar code, you just have to show the into OpenCascade's context, the correspond AIS_Shape(s) that you just removed.

public static List<NodeBuilder> GetAllHighlightedShapes(Node root, OCAIS_InteractiveContext context, OCV3d_View view, int mouseX, int mouseY)
{
var shapeList = new List<NodeBuilder>();

// Try to see if anything selected in the local context
bool found = true;
while (found)
{
found = false;
context.MoveTo(mouseX, mouseY, view);
context.Select(false);
context.InitSelected();
if (context.MoreSelected())
{
var current = context.SelectedInteractive();
var shape = GeomUtils.ExtractShapeFromAis(current);
if (shape != null)
{
var node = IdentifyNode(root, shape).Node;
var builder = new NodeBuilder(node);
shapeList.Add(builder);
builder.Visibility = ObjectVisibility.Hidden;
found = true;
}
context.CloseAllContexts(false);
context.ClearSelected(false);
}
}

foreach (var removedObject in shapeList)
{
removedObject.Visibility = ObjectVisibility.ToBeDisplayed;
}

return shapeList;
}

I hope that this trick is interesting and you will enjoy the new functionality if you will have a complex shape setup. Also this code works only with MetaActions.

No comments: