A class used to intersect and return elements based on an origin point and direction.
Namespace: Autodesk.Revit.DB
Assembly: RevitAPI (in RevitAPI.dll) Version: 2015.0.0.0 (2015.0.0.0)
Since: 2013
Syntax
C# |
---|
|
Visual Basic |
---|
|
Visual C++ |
---|
|
Examples

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 = revit.Application.Application.Create.NewPlane(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;
}
}

<Autodesk.Revit.Attributes.Journaling(Autodesk.Revit.Attributes.JournalingMode.NoCommandData)> _
<Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Automatic)> _
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 = revit.Application.Application.Create.NewPlane(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