User Selection

User Selection

The Selection class also has methods for allowing the user to select new objects, or even a point on screen. This allows the user to select one or more Elements (or other objects, such as an edge or a face) using the cursor and then returns control to your application. These functions do not automatically add the new selection to the active selection collection.

The type of object to be selected is specified when calling PickObject() or PickObjects. Types of objects that can be specified are: Element, PointOnElement, Edge or Face.

The StatusbarTip property shows a message in the status bar when your application prompts the user to pick objects or elements. Each of the Pick functions has an overload that has a String parameter in which a custom status message can be provided.

Code Region 7-2: Adding selected elements with PickObject() and PickElementsByRectangle()

UIDocument uidoc = new UIDocument(document);
Selection choices = uidoc.Selection;
// Pick one object from Revit.
Reference hasPickOne = choices.PickObject(ObjectType.Element);
if (hasPickOne != null)
{
    TaskDialog.Show("Revit", "One element selected.");
}

// Use the rectangle picking tool to identify model elements to select.
IList<Element> pickedElements = uidoc.Selection.PickElementsByRectangle("Select by rectangle");
if (pickedElements.Count > 0)
{ 
    // Collect Ids of all picked elements
    IList<ElementId> idsToSelect = new List<ElementId>(pickedElements.Count);
    foreach (Element element in pickedElements)
    {
        idsToSelect.Add(element.Id);
    }
                
    // Update the current selection
    uidoc.Selection.SetElementIds(idsToSelect);
    TaskDialog.Show("Revit", string.Format("{0} elements added to Selection.", idsToSelect.Count));
}

The PickPoint() method has 2 overloads with an ObjectSnapTypes parameter which is used to specify the type of snap types used for the selection. More than one can be specified, as shown in the next example.

Code Region 7-3: Snap points

public void PickPoint(UIDocument uidoc)
{
        
        ObjectSnapTypes snapTypes = ObjectSnapTypes.Endpoints | ObjectSnapTypes.Intersections;
        XYZ point = uidoc.Selection.PickPoint(snapTypes, "Select an end point or intersection");
        
        string strCoords = "Selected point is " + point.ToString();
        
        TaskDialog.Show("Revit", strCoords);
}

The PickBox() method takes a PickBoxStyle enumerator. The options are Crossing, the style used when selecting objects completely or partially inside the box, Enclosing, the style used selecting objects that are completely enclosed by the box, and Directional, in which the style of the box depends on the direction in which the box is being drawn. It uses the Crossing style if it is being drawn from right to left, or the Enclosing style when drawn in the opposite direction.

PickBox() returns a PickedBox which contains the Min and Max points selected. The following example demonstrates the use of PickBox() in Point Cloud selection.

Code Region: PickBox

public void PromptForPointCloudSelection(UIDocument uiDoc, PointCloudInstance pcInstance)
{
    Application app = uiDoc.Application.Application;
    Selection currentSel = uiDoc.Selection;

    PickedBox pickedBox = currentSel.PickBox(PickBoxStyle.Enclosing, "Select region of cloud for highlighting");

    XYZ min = pickedBox.Min;
    XYZ max = pickedBox.Max;

    //Transform points into filter
    View view = uiDoc.ActiveView;
    XYZ right = view.RightDirection;
    XYZ up = view.UpDirection;

    List<Plane> planes = new List<Plane>();

    // X boundaries
    bool directionCorrect = IsPointAbovePlane(right, min, max);
    planes.Add(app.Create.NewPlane(right, directionCorrect ? min : max));
    planes.Add(app.Create.NewPlane(-right, directionCorrect ? max : min));

    // Y boundaries
    directionCorrect = IsPointAbovePlane(up, min, max);
    planes.Add(app.Create.NewPlane(up, directionCorrect ? min : max));
    planes.Add(app.Create.NewPlane(-up, directionCorrect ? max : min));

    // Create filter
    PointCloudFilter filter = PointCloudFilterFactory.CreateMultiPlaneFilter(planes);
    Transaction t = new Transaction(uiDoc.Document, "Highlight");
    t.Start();
    pcInstance.SetSelectionFilter(filter);
    pcInstance.FilterAction = SelectionFilterAction.Highlight;
    t.Commit();
    uiDoc.RefreshActiveView();
}

private static bool IsPointAbovePlane(XYZ normal, XYZ planePoint, XYZ point)
{
    XYZ difference = point - planePoint;
    difference = difference.Normalize();
    double dotProduct = difference.DotProduct(normal);
    return dotProduct > 0;
}