ReferenceIntersector Class


A class used to find and return elements that intersect a ray created from an origin point and direction.

Namespace: Autodesk.Revit.DB
Assembly: RevitAPI (in RevitAPI.dll) Version: 17.0.0.0 (17.0.484.0)
Since: 2013

Syntax

C#
public class ReferenceIntersector : IDisposable
Visual Basic
Public Class ReferenceIntersector _
	Implements IDisposable
Visual C++
public ref class ReferenceIntersector : IDisposable

Remarks

An instance of this class can be constructed to return any 3D geometric element that intersects the ray created by the origin and direction, or to return a subset of elements based on filtering and flags. The caller can opt to filter the results using an ElementFilter, or by applying a specific list of acceptable elements. The caller can also specify the type of object to be returned, which might be whole elements, geometry objects, or a combination. In all cases the caller is required to supply a 3D view for evaluation; the view and visibility settings on the input view will determine if a particular element is returned (for example, hidden elements will never be returned by this tool, nor will elements whose geometry is outside the section box of the view).

The class is configured so that a single instance can be constructed and used for multiple evaluations of different rays. The results of the evaluation are not preserved between invocations on the same ReferenceIntersector.

The class also offers an option to return element results encountered in Revit Links. When the FindReferencesInRevitLinks flag is set, the results may include elements in the host document and in any RevitLinkInstance encountered, depending on the other flags set. See the remarks for FindReferencesInRevitLinks for details on how the flags affect the results obtained from links.

Examples

Copy C#
public class RayProjection : IExternalCommand
{
    public Result Execute(ExternalCommandData revit, ref string message, ElementSet elements)
    {
        Document doc = revit.Application.ActiveUIDocument.Document;

        ICollection<ElementId> selectedIds = revit.Application.ActiveUIDocument.Selection.GetElementIds();

        // If skylight is selected, process it.
        FamilyInstance skylight = null;
        if (selectedIds.Count == 1)
        {
            foreach (ElementId id in selectedIds)
            {
                Element e = doc.GetElement(id);
                if (e is FamilyInstance)
                {
                    FamilyInstance instance = e as FamilyInstance;
                    bool isWindow = (instance.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Windows);
                    bool isHostedByRoof = (instance.Host.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Roofs);

                    if (isWindow && isHostedByRoof)
                    {
                        skylight = instance;
                    }
                }
            }
        }

        if (skylight == null)
        {
            message = "Please select one skylight.";
            return Result.Cancelled;
        }

        // Calculate the height
        Line line = CalculateLineAboveFloor(doc, skylight);

        // Create a model curve to show the distance
        Plane plane = Plane.CreateByNormalAndOrigin(new XYZ(1, 0, 0), line.GetEndPoint(0));
        SketchPlane sketchPlane = SketchPlane.Create(doc, plane);

        ModelCurve curve = doc.Create.NewModelCurve(line, sketchPlane);

        // Show a message with the length value
        TaskDialog.Show("Distance", "Distance to floor: " + String.Format("{0:f2}", line.Length));

        return Result.Succeeded;
    }

    /// <summary>
    /// Determines the line segment that connects the skylight to the nearest floor.
    /// </summary>
    /// <returns>The line segment.</returns>
    private Line CalculateLineAboveFloor(Document doc, FamilyInstance skylight)
    {
        // Find a 3D view to use for the ReferenceIntersector constructor
        FilteredElementCollector collector = new FilteredElementCollector(doc);
        Func<View3D, bool> isNotTemplate = v3 => !(v3.IsTemplate);
        View3D view3D = collector.OfClass(typeof(View3D)).Cast<View3D>().First<View3D>(isNotTemplate);

        // Use the center of the skylight bounding box as the start point.
        BoundingBoxXYZ box = skylight.get_BoundingBox(view3D);
        XYZ center = box.Min.Add(box.Max).Multiply(0.5);

        // Project in the negative Z direction down to the floor.
        XYZ rayDirection = new XYZ(0, 0, -1);

        ElementClassFilter filter = new ElementClassFilter(typeof(Floor));

        ReferenceIntersector refIntersector = new ReferenceIntersector(filter, FindReferenceTarget.Face, view3D);
        ReferenceWithContext referenceWithContext = refIntersector.FindNearest(center, rayDirection);

        Reference reference = referenceWithContext.GetReference();
        XYZ intersection = reference.GlobalPoint;

        // Create line segment from the start point and intersection point.
        Line result = Line.CreateBound(center, intersection);
        return result;
    }
}
Copy VB.NET
<Autodesk.Revit.Attributes.Journaling(Autodesk.Revit.Attributes.JournalingMode.NoCommandData)> _
<Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)> _
Public Class RayProjection
   Implements IExternalCommand
   Public Function Execute(revit As ExternalCommandData, ByRef message As String, elements As ElementSet) As Autodesk.Revit.UI.Result Implements IExternalCommand.Execute
      Dim doc As Document = revit.Application.ActiveUIDocument.Document

      Dim selectedIds As ICollection(Of ElementId) = revit.Application.ActiveUIDocument.Selection.GetElementIds()

      ' If skylight is selected, process it.
      Dim skylight As FamilyInstance = Nothing
      If selectedIds.Count = 1 Then
         For Each id As ElementId In selectedIds
            Dim e As Element = doc.GetElement(id)
            If TypeOf e Is FamilyInstance Then
               Dim instance As FamilyInstance = TryCast(e, FamilyInstance)
               Dim isWindow As Boolean = (instance.Category.Id.IntegerValue = CInt(BuiltInCategory.OST_Windows))
               Dim isHostedByRoof As Boolean = (instance.Host.Category.Id.IntegerValue = CInt(BuiltInCategory.OST_Roofs))

               If isWindow AndAlso isHostedByRoof Then
                  skylight = instance
               End If
            End If
         Next
      End If

      If skylight Is Nothing Then
         message = "Please select one skylight."
         Return Result.Cancelled
      End If

      ' Calculate the height
      Dim line As Line = CalculateLineAboveFloor(doc, skylight)

      ' Create a model curve to show the distance
      Dim plane As Plane = plane.CreateByNormalAndOrigin(New XYZ(1, 0, 0), line.GetEndPoint(0))
      Dim sketchPlane__1 As SketchPlane = SketchPlane.Create(doc, plane)

      Dim curve As ModelCurve = doc.Create.NewModelCurve(line, sketchPlane__1)

      ' Show a message with the length value
      TaskDialog.Show("Distance", "Distance to floor: " & [String].Format("{0:f2}", line.Length))

      Return Result.Succeeded
   End Function

   ' <summary>
   ' Determines the line segment that connects the skylight to the nearest floor.
   ' </summary>
   ' <returns>The line segment.</returns>
   Private Function CalculateLineAboveFloor(doc As Document, skylight As FamilyInstance) As Line
      ' Find a 3D view to use for the ReferenceIntersector constructor
      Dim collector As New FilteredElementCollector(doc)
      Dim isNotTemplate As Func(Of View3D, Boolean) = Function(v3) Not (v3.IsTemplate)
      Dim view3D As View3D = collector.OfClass(GetType(View3D)).Cast(Of View3D)().First(isNotTemplate)

      ' Use the center of the skylight bounding box as the start point.
      Dim box As BoundingBoxXYZ = skylight.BoundingBox(view3D)
      Dim center As XYZ = box.Min.Add(box.Max).Multiply(0.5)

      ' Project in the negative Z direction down to the floor.
      Dim rayDirection As New XYZ(0, 0, -1)

      Dim filter As New ElementClassFilter(GetType(Floor))

      Dim refIntersector As New ReferenceIntersector(filter, FindReferenceTarget.Face, view3D)
      Dim referenceWithContext As ReferenceWithContext = refIntersector.FindNearest(center, rayDirection)

      Dim reference As Reference = referenceWithContext.GetReference()
      Dim intersection As XYZ = reference.GlobalPoint

      ' Create line segment from the start point and intersection point.
      Dim result As Line = Line.CreateBound(center, intersection)
      Return result
   End Function
End Class

Inheritance Hierarchy

System Object
Autodesk.Revit.DB ReferenceIntersector

See Also