// // (C) Copyright 2003-2019 by Autodesk, Inc. // // Permission to use, copy, modify, and distribute this software in // object code form for any purpose and without fee is hereby granted, // provided that the above copyright notice appears in all copies and // that both that copyright notice and the limited warranty and // restricted rights notice below appear in all supporting // documentation. // // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE // UNINTERRUPTED OR ERROR FREE. // // Use, duplication, or disclosure by the U.S. Government is subject to // restrictions set forth in FAR 52.227-19 (Commercial Computer // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) // (Rights in Technical Data and Computer Software), as applicable. // namespace Revit.SDK.Samples.CreateBeamSystem.CS { using System; using System.Text; using System.Collections.Generic; using System.Collections; using System.Diagnostics; using System.Collections.ObjectModel; using Autodesk.Revit; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Autodesk.Revit.DB.Structure; /// /// mixed data class save the data to show in UI /// and the data used to create beam system /// public class BeamSystemData { /// /// all beam types loaded in current Revit project /// it is declared as static only because of PropertyGrid /// private static Dictionary m_beamTypes = new Dictionary(); /// /// properties of beam system /// private BeamSystemParam m_param; /// /// buffer of ExternalCommandData /// private ExternalCommandData m_commandData; /// /// the lines compose the profile of beam system /// private List m_lines = new List(); /// /// a number of beams that intersect end to end /// so that form a profile used as beam system's profile /// private List m_beams = new List(); /// /// properties of beam system /// public BeamSystemParam Param { get { return m_param; } } /// /// lines form the profile of beam system /// public ReadOnlyCollection Lines { get { return new ReadOnlyCollection(m_lines); } } /// /// buffer of ExternalCommandData /// public ExternalCommandData CommandData { get { return m_commandData; } } /// /// the data used to show in UI is updated /// public event EventHandler ParamsUpdated; /// /// constructor /// if precondition in current Revit project isn't enough, /// ErrorMessageException will be throw out /// /// data from Revit public BeamSystemData(ExternalCommandData commandData) { // initialize members m_commandData = commandData; PrepareData(); InitializeProfile(m_beams); m_param = BeamSystemParam.CreateInstance(LayoutMethod.ClearSpacing); List beamTypes = new List(m_beamTypes.Values); m_param.BeamType = beamTypes[0]; m_param.LayoutRuleChanged += new LayoutRuleChangedHandler(LayoutRuleChanged); } /// /// change the direction to the next line in the profile /// public void ChangeProfileDirection() { Line tmp = m_lines[0]; m_lines.RemoveAt(0); m_lines.Add(tmp); } /// /// all beam types loaded in current Revit project /// it is declared as static only because of PropertyGrid /// /// public static Dictionary GetBeamTypes() { Dictionary beamTypes = new Dictionary(m_beamTypes); return beamTypes; } /// /// initialize members using data from current Revit project /// private void PrepareData() { UIDocument doc = m_commandData.Application.ActiveUIDocument; m_beamTypes.Clear(); // iterate all selected beams foreach (ElementId elementId in doc.Selection.GetElementIds()) { object obj = doc.Document.GetElement(elementId); FamilyInstance beam = obj as FamilyInstance; if (null == beam) { continue; } // add beam to lists according to category name string categoryName = beam.Category.Name; if ("Structural Framing" == categoryName && beam.StructuralType == StructuralType.Beam) { m_beams.Add(beam); } } //iterate all beam types FilteredElementIterator itor = new FilteredElementCollector(doc.Document).OfClass(typeof(Family)).GetElementIterator(); itor.Reset(); while (itor.MoveNext()) { // get Family to get FamilySymbols Family aFamily = itor.Current as Family; if (null == aFamily) { continue; } foreach (ElementId symbolId in aFamily.GetFamilySymbolIds()) { FamilySymbol symbol = doc.Document.GetElement(symbolId) as FamilySymbol; if (null == symbol.Category) { continue; } // add symbols to lists according to category name string categoryName = symbol.Category.Name; if ("Structural Framing" == categoryName) { m_beamTypes.Add(symbol.Family.Name + ":" + symbol.Name, symbol); } } } if (m_beams.Count == 0) { throw new ErrorMessageException("Please select beams."); } if (m_beamTypes.Count == 0) { throw new ErrorMessageException("There is no Beam families loaded in current project."); } } /// /// retrieve the profiles using the selected beams /// ErrorMessageException will be thrown out if beams can't make a closed profile /// /// beams which may form a closed profile private void InitializeProfile(List beams) { // retrieve collection of lines in beams List lines = new List(); foreach (FamilyInstance beam in beams) { LocationCurve locationLine = beam.Location as LocationCurve; Line line = locationLine.Curve as Line; if (null == line) { throw new ErrorMessageException("Please don't select any arc beam."); } lines.Add(line); } // lines should in the same horizontal plane if (!GeometryUtil.InSameHorizontalPlane(lines)) { throw new ErrorMessageException("The selected beams can't form a horizontal profile."); } // sorted lines so that all lines are intersect end to end m_lines = GeometryUtil.SortLines(lines); // lines can't make a closed profile if (null == m_lines) { throw new ErrorMessageException("The selected beams can't form a closed profile."); } } /// /// layout rule of beam system has changed /// /// changed method private void LayoutRuleChanged(ref LayoutMethod layoutMethod) { // create BeamSystemParams instance according to changed LayoutMethod m_param = m_param.CloneInstance(layoutMethod); // raise DataUpdated event OnParamsUpdated(new EventArgs()); // rebind delegate m_param.LayoutRuleChanged += new LayoutRuleChangedHandler(LayoutRuleChanged); } /// /// the data used to show in UI is updated /// /// protected virtual void OnParamsUpdated(EventArgs e) { if (null != ParamsUpdated) { ParamsUpdated(this, e); } } } }