// // (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.FrameBuilder.CS { using System; using System.Text; using System.Collections.Generic; using Autodesk.Revit; using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using UV = Autodesk.Revit.DB.UV; /// /// data class contains information to create framing /// public class FrameData { const int XNumberMaxValue = 50; // maximum number of Columns in the X Direction const int XNumberMinValue = 2; // minimum number of Columns in the X Direction const int XNumberDefault = 3; // default number of Columns in the X Direction const int YNumberMaxValue = 50; // maximum number of Columns in the Y Direction const int YNumberMinValue = 2; // minimum number of Columns in the Y Direction const int YNumberDefault = 3; // default number of Columns in the Y Direction const int TotalMaxValue = 200; // maximum total number of Columns to create const int FloorNumberMinValue = 1; // minimum number of floors const int FloorNumberMaxValue = 200; // maximum number of floors const double DistanceMaxValue = 3000; // maxinum distance between 2 adjoining columns const double DistanceMinValue = 1; // mininum distance between 2 adjoining columns const double DistanceDefault = 5; // default distance between 2 adjoining columns const double LevelHeightMaxValue = 100; // maximum height between 2 new levels const double LevelHeightMinValue = 1; // minimum height between 2 new levels const int DigitPrecision = 4; // the number of significant digits(precision) int m_xNumber = XNumberDefault; // number of Columns in the X Direction int m_yNumber = XNumberDefault; // number of Columns in the Y Direction double m_distance = DistanceDefault; // distance between 2 adjoining columns int m_floorNumber; // number of floors double m_levelHeight; // increaced height of autogenerated levels Autodesk.Revit.DB.UV m_frameOrigin = new Autodesk.Revit.DB.UV(0.0, 0.0); // bottom left point of the frame double m_frameOriginAngle = 0.0; // the angle to rotate around bottom left point int m_originalLevelSize; // the number of levels before invoke external command FamilySymbol m_columnSymbol; // column's type FamilySymbol m_beamSymbol; // beam's type FamilySymbol m_braceSymbol; // brace's type ExternalCommandData m_commandData; FrameTypesMgr m_columnSymbolsMgr; // object manage all column types FrameTypesMgr m_beambracesSymbolsMgr; // object manage all beam types SortedList m_levels; // list of all levels in the order of Elevation /// /// command data pass from entry point /// public ExternalCommandData CommandData { get { return m_commandData; } } /// /// object manage all column types /// public FrameTypesMgr ColumnSymbolsMgr { get { return m_columnSymbolsMgr; } } /// /// object manage all beam types /// public FrameTypesMgr BeamSymbolsMgr { get { return m_beambracesSymbolsMgr; } } /// /// object manage all brace types /// public FrameTypesMgr BraceSymbolsMgr { get { return m_beambracesSymbolsMgr; } } /// /// number of Columns in the Y Direction /// public int YNumber { get { return m_yNumber; } set { if (value < YNumberMinValue || value > YNumberMaxValue) { string message = "Number of Columns in the Y Direction should no less than " + YNumberMinValue.ToString() + " and no more than " + YNumberMaxValue.ToString(); throw new ErrorMessageException(message); } CheckTotalNumber(value * XNumber * (m_floorNumber - 1)); m_yNumber = value; } } /// /// number of Columns in the X Direction /// public int XNumber { get { return m_xNumber; } set { if (value < XNumberMinValue || value > XNumberMaxValue) { string message = "Number of Columns in the X Direction should no less than " + XNumberMinValue.ToString() + " and no more than " + XNumberMaxValue.ToString(); throw new ErrorMessageException(message); } CheckTotalNumber(value * YNumber * (m_floorNumber - 1)); m_xNumber = value; } } /// /// distance between 2 adjoining columns /// public double Distance { get { return m_distance; } set { if (value < DistanceMinValue || value > DistanceMaxValue) { string message = "The distance between columns shoule no less than " + DistanceMinValue.ToString() + "and no more than " + DistanceMaxValue.ToString(); throw new ErrorMessageException(message); } m_distance = value; } } /// /// number of floors /// public int FloorNumber { get { return m_floorNumber; } set { if (value < FloorNumberMinValue || value > FloorNumberMaxValue) { string message = "Number of floors should no less than " + FloorNumberMinValue.ToString() + " and no more than " + FloorNumberMaxValue.ToString(); throw new ErrorMessageException(message); } CheckTotalNumber(XNumber * YNumber * (value - 1)); m_floorNumber = value; } } /// /// increased height of autogenerated levels /// public double LevelHeight { get { return Math.Round(m_levelHeight, DigitPrecision); } set { if (value < LevelHeightMinValue || value > LevelHeightMaxValue) { string message = "The distance between columns shoule no less than " + LevelHeightMinValue.ToString() + "and no more than " + LevelHeightMaxValue.ToString(); throw new ErrorMessageException(message); } m_distance = value; } } /// /// bottom left point of the frame /// public Autodesk.Revit.DB.UV FrameOrigin { get { return m_frameOrigin; } set { m_frameOrigin = value; } } /// /// the angle to rotate around bottom left point /// public double FrameOriginAngle { get { return m_frameOriginAngle; } set { m_frameOriginAngle = value; } } /// /// column's type /// public FamilySymbol ColumnSymbol { get { return m_columnSymbol; } } /// /// beam's type /// public FamilySymbol BeamSymbol { get { return m_beamSymbol; } } /// /// brace's type /// public FamilySymbol BraceSymbol { get { return m_braceSymbol; } } /// /// list of all levels in the ordr of Elevation /// public SortedList Levels { get { return m_levels; } } /// /// the number of levels before invoke external command /// public int OriginalLevelSize { get { return m_originalLevelSize; } } /// /// create FramingData object. applicationException will throw out, /// if current Revit document doesn't satisfy the condition to create framing /// /// /// public static FrameData CreateInstance(ExternalCommandData commandData) { FrameData data = new FrameData(commandData); data.Initialize(); data.Validate(); // initialize members after checking precondition data.m_floorNumber = (data.m_levels.Count - 1) > 0 ? (data.m_levels.Count - 1) : 1; data.m_columnSymbol = data.m_columnSymbolsMgr.FramingSymbols[0]; data.m_beamSymbol = data.m_beambracesSymbolsMgr.FramingSymbols[0]; data.m_braceSymbol = data.m_beambracesSymbolsMgr.FramingSymbols[0]; data.m_levelHeight = data.m_levels.Values[data.m_levels.Count - 1].Elevation - data.m_levels.Values[data.m_levels.Count - 2].Elevation; return data; } /// /// cast object to FamilySymbol and set as column's type /// /// FamilySymbol object /// failed to cast and set public bool SetColumnSymbol(object obj) { FamilySymbol symbol = obj as FamilySymbol; if (null == symbol) { return false; } m_columnSymbol = symbol; return true; } /// /// cast object to FamilySymbol and set as beam's type /// /// FamilySymbol object /// failed to cast and set public bool SetBeamSymbol(object obj) { FamilySymbol symbol = obj as FamilySymbol; if (null == symbol) { return false; } m_beamSymbol = symbol; return true; } /// /// cast object to FamilySymbol and set as brace's type /// /// FamilySymbol object /// failed to cast and set public bool SetBraceSymbol(object obj) { FamilySymbol symbol = obj as FamilySymbol; if (null == symbol) { return false; } m_braceSymbol = symbol; return true; } /// /// add more levels so that level number can meet floor number /// public void UpdateLevels() { double baseElevation = m_levels.Values[m_levels.Count - 1].Elevation; Autodesk.Revit.Creation.Document createDoc = m_commandData.Application.ActiveUIDocument.Document.Create; Autodesk.Revit.DB.Document m_Doc = m_commandData.Application.ActiveUIDocument.Document; FilteredElementCollector collector = new FilteredElementCollector(m_Doc); IList viewFamilyTypes = collector.OfClass(typeof(ViewFamilyType)).ToElements(); ElementId floorPlanId = ElementId.InvalidElementId; foreach (Element e in viewFamilyTypes) { ViewFamilyType v = e as ViewFamilyType; if (v != null && v.ViewFamily == ViewFamily.FloorPlan) { floorPlanId = e.Id; break; } } int newLevelSize = (m_floorNumber + 1) - m_levels.Count; if (newLevelSize == 0) { return; } for (int ii = 0; ii < newLevelSize; ii++) { double elevation = baseElevation + m_levelHeight * (ii + 1); Level newLevel = Level.Create(m_commandData.Application.ActiveUIDocument.Document, elevation); //createDoc.NewViewPlan(newLevel.Name, newLevel, Autodesk.Revit.DB.ViewPlanType.FloorPlan); ViewPlan viewPlan = ViewPlan.Create(m_Doc, floorPlanId, newLevel.Id); viewPlan.Name = newLevel.Name; m_levels.Add(elevation, newLevel); } m_originalLevelSize = m_levels.Count; } /// /// it is only used for object factory method /// /// private FrameData(ExternalCommandData commandData) { // initialize members m_commandData = commandData; m_columnSymbolsMgr = new FrameTypesMgr(commandData); m_beambracesSymbolsMgr = new FrameTypesMgr(commandData); m_levels = new SortedList(); m_originalLevelSize = m_levels.Count; m_yNumber = YNumberDefault; m_xNumber = XNumberDefault; m_distance = DistanceDefault; } /// /// check the total number of columns to create less than certain value /// /// /// private static void CheckTotalNumber(int number) { if (number > TotalMaxValue) { string message = "The total number of columns should less than " + TotalMaxValue.ToString(); throw new ErrorMessageException(message); } } /// /// initialize list of column, beam and brace's type; /// initialize list of level /// private void Initialize() { Application app = m_commandData.Application.Application; Document doc = m_commandData.Application.ActiveUIDocument.Document; FilteredElementCollector collector1 = new FilteredElementCollector(doc); IList a1 = collector1.OfClass(typeof(Level)).ToElements(); foreach (Level lev in a1) { m_levels.Add(lev.Elevation, lev); } a1.Clear(); Categories categories = doc.Settings.Categories; BuiltInCategory bipColumn = BuiltInCategory.OST_StructuralColumns; BuiltInCategory bipFraming = BuiltInCategory.OST_StructuralFraming; Autodesk.Revit.DB.ElementId idColumn = categories.get_Item(bipColumn).Id; Autodesk.Revit.DB.ElementId idFraming = categories.get_Item(bipFraming).Id; ElementCategoryFilter filterColumn = new ElementCategoryFilter(bipColumn); ElementCategoryFilter filterFraming = new ElementCategoryFilter(bipFraming); LogicalOrFilter orFilter = new LogicalOrFilter(filterColumn, filterFraming); ElementClassFilter filterSymbol = new ElementClassFilter(typeof(FamilySymbol)); LogicalAndFilter andFilter = new LogicalAndFilter(orFilter, filterSymbol); // // without filtering for the structural categories, // our sample project was returning over 500 family symbols; // adding the category filters reduced this number to 40: // FilteredElementCollector collector2 = new FilteredElementCollector(doc); IList a2 = collector2.WherePasses(andFilter).ToElements(); foreach (FamilySymbol symbol in a2) { Autodesk.Revit.DB.ElementId categoryId = symbol.Category.Id; if (idFraming.Equals(categoryId)) { m_beambracesSymbolsMgr.AddSymbol(symbol); } else if (idColumn.Equals(categoryId)) { m_columnSymbolsMgr.AddSymbol(symbol); } } } /// /// validate the precondition to create framing /// private void Validate() { // level shouldn't less than 2 if (m_levels.Count < 2) { throw new ErrorMessageException("The level's number in active document is less than 2."); } // no Structural Column family is loaded in current document if (m_columnSymbolsMgr.Size == 0) { throw new ErrorMessageException("No Structural Column family is loaded in current project."); } // no Structural Beam family is loaded in current document if (m_beambracesSymbolsMgr.Size == 0) { throw new ErrorMessageException("No Structural Beam family is loaded in current project."); } } } }