// // (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. // using System; using System.Collections.Generic; using System.Collections; using System.Text; using System.Windows.Forms; using System.Linq; using Autodesk; using Autodesk.Revit; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Autodesk.Revit.DB.Structure; namespace Revit.SDK.Samples.CreateWallsUnderBeams.CS { /// /// Implements the Revit add-in interface IExternalCommand /// [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)] [Autodesk.Revit.Attributes.Journaling(Autodesk.Revit.Attributes.JournalingMode.NoCommandData)] public class CreateWallsUnderBeams : IExternalCommand { // Private Members IList m_wallTypeCollection; // Store all the wall types in current document ArrayList m_beamCollection; // Store the selection of beams in Revit WallType m_selectedWallType; // Store the selected wall type Level m_level; // Store the level which wall create on Boolean m_isStructural; // Indicate whether create structural walls String m_errorInformation; // Store the error information const Double PRECISION = 0.0000000001; // Define a precision of double data // Properties /// /// Inform all the wall types can be created in current document /// public IList WallTypes { get { return m_wallTypeCollection; } } /// /// Inform the wall type selected by the user /// public Object SelectedWallType { set { m_selectedWallType = value as WallType; } } /// /// Inform whether the user want to create structural or architecture walls /// public Boolean IsSturctual { get { return m_isStructural; } set { m_isStructural = value; } } // Methods /// /// Default constructor of CreateWallsUnderBeams /// public CreateWallsUnderBeams() { m_wallTypeCollection = new List(); m_beamCollection = new ArrayList(); m_isStructural = true; } #region IExternalCommand Members Implementation /// /// Implement this method as an external command for Revit. /// /// An object that is passed to the external application /// which contains data related to the command, /// such as the application object and active view. /// A message that can be set by the external application /// which will be displayed if a failure or cancellation is returned by /// the external command. /// A set of elements to which the external application /// can add elements that are to be highlighted in case of failure or cancellation. /// Return the status of the external command. /// A result of Succeeded means that the API external method functioned as expected. /// Cancelled can be used to signify that the user cancelled the external operation /// at some point. Failure should be returned if the application is unable to proceed with /// the operation. public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, Autodesk.Revit.DB.ElementSet elements) { Autodesk.Revit.UI.UIApplication revit = commandData.Application; UIDocument project = revit.ActiveUIDocument; // Find the selection of beams in Revit ElementSet selection = new ElementSet(); foreach (ElementId elementId in project.Selection.GetElementIds()) { selection.Insert(project.Document.GetElement(elementId)); } foreach (Autodesk.Revit.DB.Element e in selection) { FamilyInstance m = e as FamilyInstance; if (null != m) { if (StructuralType.Beam == m.StructuralType) { // Store all the beams the user selected in Revit m_beamCollection.Add(e); } } } if (0 == m_beamCollection.Count) { message = "Can not find any beams."; return Autodesk.Revit.UI.Result.Failed; } // Make sure all the beams have horizontal analytical line if (!CheckBeamHorizontal()) { message = m_errorInformation; return Autodesk.Revit.UI.Result.Failed; } // Search all the wall types in the Revit FilteredElementCollector filteredElementCollector = new FilteredElementCollector(project.Document); filteredElementCollector.OfClass(typeof(WallType)); m_wallTypeCollection = filteredElementCollector.Cast().ToList(); // Show the dialog for the user select the wall style using (CreateWallsUnderBeamsForm displayForm = new CreateWallsUnderBeamsForm(this)) { if (DialogResult.OK != displayForm.ShowDialog()) { return Autodesk.Revit.UI.Result.Failed; } } // Create the walls which along and under the path of the beams. if (!BeginCreate(project.Document)) { message = m_errorInformation; return Autodesk.Revit.UI.Result.Failed; } // If everything goes right, return succeeded. return Autodesk.Revit.UI.Result.Succeeded; } #endregion IExternalCommand Members Implementation /// /// Create the walls which along and under the path of the selected beams /// /// A reference of current document /// true if there is no error in process; otherwise, false. Boolean BeginCreate(Autodesk.Revit.DB.Document project) { // Begin to create walls along and under each beam for (int i = 0; i < m_beamCollection.Count; i++) { // Get each selected beam. FamilyInstance m = m_beamCollection[i] as FamilyInstance; if (null == m) { m_errorInformation = "The program should not go here."; return false; } // Get the analytical model of the beam, // the wall will be created using this model line as path. AnalyticalModel model = m.GetAnalyticalModel(); if (null == model) { m_errorInformation = "The beam should have analytical model."; return false; } // Get the level using the beam's reference level Autodesk.Revit.DB.ElementId levelId = m.get_Parameter(BuiltInParameter.INSTANCE_REFERENCE_LEVEL_PARAM).AsElementId(); m_level = project.GetElement(levelId) as Level; if (null == m_level) { m_errorInformation = "The program should not go here."; return false; } Transaction t = new Transaction(project, Guid.NewGuid().GetHashCode().ToString()); t.Start(); Wall createdWall = Wall.Create(project, model.GetCurve(), m_selectedWallType.Id, m_level.Id, 10, 0, true, m_isStructural); if (null == createdWall) { m_errorInformation = "Can not create the walls"; return false; } // Modify some parameters of the created wall to make it look better. Double offset = model.GetCurve().GetEndPoint(0).Z - m_level.Elevation; createdWall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).Set(levelId); createdWall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).Set(offset - 3000 / 304.8); createdWall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).Set(levelId); t.Commit(); } return true; } /// /// Check whether all the beams have horizontal analytical line /// /// true if each beam has horizontal analytical line; otherwise, false. Boolean CheckBeamHorizontal() { for (int i = 0; i < m_beamCollection.Count; i++) { // Get the analytical curve of each selected beam. // And check if Z coordinate of start point and end point of the curve are same. FamilyInstance m = m_beamCollection[i] as FamilyInstance; AnalyticalModel model = m.GetAnalyticalModel(); if (null == model) { m_errorInformation = "The beam should have analytical model."; return false; } else if ((PRECISION <= model.GetCurve().GetEndPoint(0).Z - model.GetCurve().GetEndPoint(1).Z) || (-PRECISION >= model.GetCurve().GetEndPoint(0).Z - model.GetCurve().GetEndPoint(1).Z)) { m_errorInformation = "Please only select horizontal beams."; return false; } } return true; } } }