// // (C) Copyright 2003-2008 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. // //#define LANGUAGE_DEPENDENT_CATEGORY_COMPARISON // jeremy #define USE_FILTERS_TO_SELECT_FAMILY_SYMBOLS // jeremy namespace Revit.SDK.Samples.FrameBuilder.CS { using System; using System.Text; using System.Collections.Generic; using Autodesk.Revit; using Autodesk.Revit.Symbols; using Autodesk.Revit.Elements; //using Autodesk.Revit.Geometry; // jeremy using UV = Autodesk.Revit.Geometry.UV; // jeremy /// /// 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 UV m_frameOrigin = new 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 bool m_isSuspendUpdating = false; // whether use suspend updating method 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 /// /// whether use suspend updating method /// public bool IsSuspendUpdating { get { return m_isSuspendUpdating; } set { m_isSuspendUpdating = value; } } /// /// 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 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.ActiveDocument.Create; 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 = createDoc.NewLevel(elevation); createDoc.NewViewPlan(newLevel.Name, newLevel, Autodesk.Revit.Enums.ViewType.FloorPlan); 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; Document doc = app.ActiveDocument; Categories categories = doc.Settings.Categories; BuiltInCategory bipColumn = BuiltInCategory.OST_StructuralColumns; // jeremy BuiltInCategory bipFraming = BuiltInCategory.OST_StructuralFraming; // jeremy ElementId idColumn = categories.get_Item( bipColumn ).Id; ElementId idFraming = categories.get_Item( bipFraming ).Id; #if USE_FILTERS_TO_SELECT_FAMILY_SYMBOLS // NEW VERSION -> LANGUAGE INDEPENDENT AND FILTER USE List a = new List(); doc.get_Elements( typeof( Level ), a ); foreach( Level lev in a ) { m_levels.Add( lev.Elevation, lev ); } a.Clear(); Autodesk.Revit.Creation.Filter cf = app.Create.Filter; // // without filtering for the structural categories, // our sample project was returning over 500 family symbols; // adding the category filters reduced this number to 40: // Filter filterSymbols = cf.NewTypeFilter( typeof( FamilySymbol ) ); Filter filterCols = cf.NewCategoryFilter( bipColumn ); Filter filterFram = cf.NewCategoryFilter( bipFraming ); Filter filterStruct = cf.NewLogicOrFilter( filterCols, filterFram ); Filter filter = cf.NewLogicAndFilter( filterSymbols, filterStruct ); doc.get_Elements( filter, a ); foreach( FamilySymbol symbol in a ) { ElementId categoryId = symbol.Category.Id; if( idFraming.Equals( categoryId ) ) { m_beambracesSymbolsMgr.AddSymbol( symbol ); } else if( idColumn.Equals( categoryId ) ) { m_columnSymbolsMgr.AddSymbol( symbol ); } } #else // if not USE_FILTERS_TO_SELECT_FAMILY_SYMBOLS ElementIterator itor = m_commandData.Application.ActiveDocument.Elements; itor.Reset(); while (itor.MoveNext()) { object obj = itor.Current; // add level to list Level aLevel = obj as Level; if (null != aLevel) { m_levels.Add(aLevel.Elevation, aLevel); continue; } // get Family to get FamilySymbols Family aFamily = obj as Family; if (null == aFamily) { continue; } foreach (FamilySymbol symbol in aFamily.Symbols) { if (null == symbol.Category) { continue; } #if LANGUAGE_DEPENDENT_CATEGORY_COMPARISON // // this is language dependent: -- jeremy // // add symbols to lists according to category name string categoryName = symbol.Category.Name; if ("Structural Framing" == categoryName) { m_beambracesSymbolsMgr.AddSymbol(symbol); } else if ("Structural Columns" == categoryName) { m_columnSymbolsMgr.AddSymbol(symbol); } #else // if not LANGUAGE_DEPENDENT_CATEGORY_COMPARISON // // this is language independent: -- jeremy // // add symbols to lists according to category ElementId categoryId = symbol.Category.Id; if( idFraming.Equals( categoryId ) ) { m_beambracesSymbolsMgr.AddSymbol( symbol ); } else if( idColumn.Equals( categoryId ) ) { m_columnSymbolsMgr.AddSymbol( symbol ); } #endif // LANGUAGE_DEPENDENT_CATEGORY_COMPARISON } } #endif // if not USE_FILTERS_TO_SELECT_FAMILY_SYMBOLS } /// /// 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."); } } } }