{ public Result Execute(ExternalCommandData revit, refstring 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; }