// // (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.Linq; using System.Text; using Autodesk.Revit; using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Autodesk.Revit.UI.Selection; namespace Revit.SDK.Samples.CompoundStructureCreation.CS { #region A Class For Create CompoundStructure /// /// This command allows to create vertical CompoundStructure and applying to walls. /// [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] [Autodesk.Revit.Attributes.Journaling(Autodesk.Revit.Attributes.JournalingMode.NoCommandData)] public class WallCompoundStructure : Autodesk.Revit.UI.IExternalCommand { /// /// store the application /// UIApplication m_application; /// /// store the document /// UIDocument m_document; /// /// 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 Result Execute(Autodesk.Revit.UI.ExternalCommandData commandData, ref string message, ElementSet elements) { m_application = commandData.Application; m_document = m_application.ActiveUIDocument; Transaction transaction = new Transaction(m_document.Document, "Create CompoundStructure for Wall"); try { // Select at least a wall. ElementSet selectedElements = new ElementSet(); foreach (ElementId elementId in m_document.Selection.GetElementIds()) { selectedElements.Insert(m_document.Document.GetElement(elementId)); } if (selectedElements.IsEmpty) { TaskDialog.Show("Error","Please select one wall at least."); return Autodesk.Revit.UI.Result.Cancelled; } // Create the CompoundStructure for wall. transaction.Start(); if (selectedElements.IsEmpty) return Result.Failed; foreach (Element elem in selectedElements) { Wall wall = elem as Wall; if (wall != null) { CreateCSforWall(wall); break; } } transaction.Commit(); return Result.Succeeded; } catch (Exception ex) { // If any error, give error information and return failed message = ex.Message; transaction.RollBack(); return Result.Failed; } } /// /// Create vertical CompoundStructure for wall: new layers, split new region, new sweep and new reveal. /// /// The wall applying the new CompoundStructure. public void CreateCSforWall(Wall wall) { // Get CompoundStructure WallType wallType = wall.WallType; //wallType.Name = wallType.Name + "_WithNewCompoundStructure"; CompoundStructure wallCS = wallType.GetCompoundStructure(); // Get material for CompoundStructureLayer Material masonry_Brick = CreateSampleBrickMaterial(); Material concrete = CreateSampleConcreteMaterial(); // Create CompoundStructureLayers and add the materials created above to them. List csLayers = new List(); CompoundStructureLayer finish1Layer = new CompoundStructureLayer(0.2, MaterialFunctionAssignment.Finish1, masonry_Brick.Id); CompoundStructureLayer substrateLayer = new CompoundStructureLayer(0.1, MaterialFunctionAssignment.Substrate, ElementId.InvalidElementId); CompoundStructureLayer structureLayer = new CompoundStructureLayer(0.5, MaterialFunctionAssignment.Structure, concrete.Id); CompoundStructureLayer membraneLayer = new CompoundStructureLayer(0, MaterialFunctionAssignment.Membrane, ElementId.InvalidElementId); CompoundStructureLayer finish2Layer = new CompoundStructureLayer(0.2, MaterialFunctionAssignment.Finish2, concrete.Id); csLayers.Add(finish1Layer); csLayers.Add(substrateLayer); csLayers.Add(structureLayer); csLayers.Add(membraneLayer); csLayers.Add(finish2Layer); // Set the created layers to CompoundStructureLayer wallCS.SetLayers(csLayers); //Set which layer is used for structural analysis wallCS.StructuralMaterialIndex = 2; // Set shell layers and wrapping. wallCS.SetNumberOfShellLayers(ShellLayerType.Interior, 2); wallCS.SetNumberOfShellLayers(ShellLayerType.Exterior, 1); wallCS.SetParticipatesInWrapping(0, false); // Points for adding wall sweep and reveal. UV sweepPoint = UV.Zero; UV revealPoint = UV.Zero; // split the region containing segment 0. int segId = wallCS.GetSegmentIds()[0]; foreach (int regionId in wallCS.GetAdjacentRegions(segId)) { // Get the end points of segment 0. UV endPoint1 = UV.Zero; UV endPoint2 = UV.Zero; wallCS.GetSegmentEndPoints(segId, regionId, out endPoint1, out endPoint2); // Split a new region in split point and orientation. RectangularGridSegmentOrientation splitOrientation = (RectangularGridSegmentOrientation)(((int)(wallCS.GetSegmentOrientation(segId)) + 1) % 2); UV splitUV = (endPoint1 + endPoint2) / 2.0; int newRegionId = wallCS.SplitRegion(splitUV, splitOrientation); bool isValidRegionId = wallCS.IsValidRegionId(newRegionId); // Find the enclosing region and the two segments intersected by a line through the split point int segId1; int segId2; int findRegionId = wallCS.FindEnclosingRegionAndSegments(splitUV, splitOrientation, out segId1, out segId2); // Get the end points of finding segment 1 and compute the wall sweep point. UV eP1 = UV.Zero; UV eP2 = UV.Zero; wallCS.GetSegmentEndPoints(segId1, findRegionId, out eP1, out eP2); sweepPoint = (eP1 + eP2) / 4.0; // Get the end points of finding segment 2 and compute the wall reveal point. UV ep3 = UV.Zero; UV ep4 = UV.Zero; wallCS.GetSegmentEndPoints(segId2, findRegionId, out ep3, out ep4); revealPoint = (ep3 + ep4) / 2.0; } // Create a WallSweepInfo for wall sweep WallSweepInfo sweepInfo = new WallSweepInfo(true, WallSweepType.Sweep); PrepareWallSweepInfo(sweepInfo, sweepPoint.V); // Set sweep profile: Sill-Precast : 8" Wide sweepInfo.ProfileId = GetProfile("8\" Wide").Id; sweepInfo.Id = 101; wallCS.AddWallSweep(sweepInfo); // Create a WallSweepInfo for wall reveal WallSweepInfo revealInfo = new WallSweepInfo(true, WallSweepType.Reveal); PrepareWallSweepInfo(revealInfo, revealPoint.U); revealInfo.Id = 102; wallCS.AddWallSweep(revealInfo); // Set the new wall CompoundStructure to the type of wall. wallType.SetCompoundStructure(wallCS); } /// /// Setting the WallSweepInfo for sweep and reveal. /// /// The WallSweepInfo. /// The distance from either the top or base of the wall private void PrepareWallSweepInfo(WallSweepInfo wallSweepInfo, double distance) { wallSweepInfo.DistanceMeasuredFrom = DistanceMeasuredFrom.Base; wallSweepInfo.Distance = distance; wallSweepInfo.WallSide = WallSide.Exterior; wallSweepInfo.Id = -1; wallSweepInfo.WallOffset = -0.1; } /// /// Getting the specific material by name. /// /// The name of specific material. /// The specific material private Material GetMaterial(string name) { FilteredElementCollector collector = new FilteredElementCollector(m_document.Document); collector.WherePasses(new ElementCategoryFilter(BuiltInCategory.OST_Materials)); var MaterialElement = from element in collector where element.Name == name select element; if (MaterialElement.Count() == 0) return null; return MaterialElement.First() as Material; } /// /// Create a new brick material /// /// The specific material private Material CreateSampleBrickMaterial() { SubTransaction createMaterial = new SubTransaction(this.m_document.Document); createMaterial.Start(); Material materialNew = null; //Try to copy an existing material. If it is not available, create a new one. Material masonry_Brick = GetMaterial("Brick, Common"); if (masonry_Brick != null) { materialNew = masonry_Brick.Duplicate(masonry_Brick.Name + "_new"); System.Diagnostics.Debug.WriteLine(masonry_Brick.MaterialClass); materialNew.MaterialClass = "Brick"; } else { ElementId idNew = Material.Create(m_document.Document, "New Brick Sample"); materialNew = m_document.Document.GetElement(idNew) as Material; materialNew.Color = new Autodesk.Revit.DB.Color(255, 0, 0); } createMaterial.Commit(); SubTransaction createPropertySets = new SubTransaction(this.m_document.Document); createPropertySets.Start(); //Create a new structural asset and set properties on it. StructuralAsset structuralAsssetBrick = new StructuralAsset("BrickStructuralAsset" , Autodesk.Revit.DB.StructuralAssetClass.Generic); PropertySetElement pseStructural = PropertySetElement.Create(m_document.Document, structuralAsssetBrick); //Create a new thermal asset and set properties on it. ThermalAsset thermalAssetBrick = new ThermalAsset("BrickThermalAsset", Autodesk.Revit.DB.ThermalMaterialType.Solid); thermalAssetBrick.Porosity = 0.1; thermalAssetBrick.Permeability = 0.2; thermalAssetBrick.Compressibility = .5; thermalAssetBrick.ThermalConductivity = .5; //Create PropertySets from assets and assign them to the material. PropertySetElement pseThermal = PropertySetElement.Create(m_document.Document, thermalAssetBrick); createPropertySets.Commit(); SubTransaction setPropertySets = new SubTransaction(this.m_document.Document); setPropertySets.Start(); materialNew.SetMaterialAspectByPropertySet(MaterialAspect.Structural, pseStructural.Id); materialNew.SetMaterialAspectByPropertySet(MaterialAspect.Thermal, pseThermal.Id); //also try //materialNew.ThermalAssetId = pseThermal.Id; setPropertySets.Commit(); return materialNew; } /// /// Create a new concrete material. /// /// The specific material private Material CreateSampleConcreteMaterial() { Material materialNew = null; //Try to copy an existing material. If it is not available, create a new one. Material masonry_Concrete = GetMaterial("Concrete, Lightweight"); if (masonry_Concrete != null) { materialNew = masonry_Concrete.Duplicate(masonry_Concrete.Name + "_new"); materialNew.MaterialClass = "Concrete"; } else { ElementId idNew = Material.Create(m_document.Document, "New Concrete Sample"); materialNew = m_document.Document.GetElement(idNew) as Material; materialNew.Color = new Autodesk.Revit.DB.Color(130, 150, 120); } //Create a new structural asset and set properties on it. StructuralAsset structuralAsssetConcrete= new StructuralAsset("ConcreteStructuralAsset", Autodesk.Revit.DB.StructuralAssetClass.Concrete); structuralAsssetConcrete.ConcreteBendingReinforcement = .5; //Create a new thermal asset and set properties on it. ThermalAsset thermalAssetConcrete= new ThermalAsset("ConcreteThermalAsset", Autodesk.Revit.DB.ThermalMaterialType.Solid); thermalAssetConcrete.Porosity = 0.2; thermalAssetConcrete.Permeability = 0.3; thermalAssetConcrete.Compressibility = .5; thermalAssetConcrete.ThermalConductivity = .5; //Create PropertySets from assets and assign them to the material. PropertySetElement pseThermal = PropertySetElement.Create(m_document.Document, thermalAssetConcrete); PropertySetElement pseStructural = PropertySetElement.Create(m_document.Document, structuralAsssetConcrete); materialNew.SetMaterialAspectByPropertySet(MaterialAspect.Structural, pseStructural.Id); materialNew.SetMaterialAspectByPropertySet(MaterialAspect.Thermal, pseThermal.Id); return materialNew; } /// /// Getting the profile for sweep or reveal. /// /// The name of specific profile. /// The specific profile. private FamilySymbol GetProfile(string name) { FilteredElementCollector profiles = new FilteredElementCollector(m_document.Document); profiles.OfCategory(BuiltInCategory.OST_ProfileFamilies); var MaterialElement = from element in profiles where element.Name == name select element; return MaterialElement.First() as FamilySymbol; } } #endregion Create CompoundStructure }