private static Result createVisualizationSheets(UIDocument uiDoc, BuildingLoadModel buildingLoadModel, IEnumerable <ILoadModel> levelLiveLoadPerSquareFoots) { //Setup Document _doc = uiDoc.Document; double _concreteDensityPoundsForcePerCubicFoot = 153.0; XYZ _capacityViewCoordinate = new XYZ(2.17649771769026, 0.766954561856788, 0); XYZ _combinedViewCoordinate = new XYZ(0.780872717690263, 0.766954561856788, 0); XYZ _demandViewCoordinate = new XYZ(0.780872717690263, 1.83481042377296, 0); var _levels = Getters.GetLevels(_doc).OrderByDescending(p => p.Elevation).ToList(); var _floors = Getters.GetFloors(_doc).OrderBy(p => p.get_BoundingBox(null)?.Max.Z).ToList(); var _structuralColumns = new FilteredElementCollector(_doc).OfCategory(BuiltInCategory.OST_StructuralColumns).OfType <FamilyInstance>().OrderBy(p => p.get_BoundingBox(null)?.Max.Z).ToList(); var _structuralFraming = new FilteredElementCollector(_doc).OfCategory(BuiltInCategory.OST_StructuralFraming).OfType <FamilyInstance>().OrderBy(p => p.get_BoundingBox(null)?.Max.Z).ToList(); var _walls = new FilteredElementCollector(_doc).OfClass(typeof(Wall)).OfType <Wall>().OrderBy(p => p.get_BoundingBox(null)?.Max.Z).ToList(); BoundingBoxXYZ _modelExtents = GeometryHelpers.GetElementsBBox( new FilteredElementCollector(_doc).WhereElementIsViewIndependent().WhereElementIsNotElementType().ToList()); _modelExtents.Min = new XYZ(_modelExtents.Min.X, _modelExtents.Min.Y, _levels.LastOrDefault().Elevation - 1.0); Category _directShapeCategory = Category.GetCategory(_doc, BuiltInCategory.OST_GenericModel); Level _levelAbove = null; Level _bottomLevel = _levels.LastOrDefault(); Level _topLevel = _levels.FirstOrDefault(); //Begin to generate our VisualizationDeliverables - these are sheets with 3 plan-orientation isometric views. // NOTE - isometric views were used so that semi-transparent color overrides can be overlayed over each other to represent demands vs capacities // ToDo: it would be valuable to scale transparency by percentage of overall demand/capacity List <VisualizationDeliverable> _visualizationDeliverables = new List <VisualizationDeliverable>(); foreach (Level _level in _levels) { if (_levelAbove == null) { _levelAbove = _level; } //Get the elements that are on our current Level List <Floor> _currentLevelFloors = _floors.Where(p => p.LevelId == _level.Id).ToList(); List <FamilyInstance> _currentLevelStructuralColumns = new List <FamilyInstance>(); List <FamilyInstance> _currentLevelStructuralFraming = new List <FamilyInstance>(); List <Wall> _currentLevelWalls = new List <Wall>(); BoundingBoxXYZ _levelBounds = new BoundingBoxXYZ { Min = new XYZ(_modelExtents.Min.X, _modelExtents.Min.Y, _level.Elevation), Max = new XYZ(_modelExtents.Max.X, _modelExtents.Max.Y, _levelAbove.Elevation) }; BoundingBoxIsInsideFilter _withinLevelBoundsFilter = new BoundingBoxIsInsideFilter(new Outline(_levelBounds.Min, _levelBounds.Max)); BoundingBoxIntersectsFilter _intersectsLevelBoundsFilter = new BoundingBoxIntersectsFilter(new Outline(_levelBounds.Min, _levelBounds.Max)); if (_structuralColumns.Count > 0) { _currentLevelStructuralColumns = new FilteredElementCollector(_doc, _structuralColumns.Select(p => p.Id).ToList()).WherePasses(_intersectsLevelBoundsFilter).OfType <FamilyInstance>().ToList(); } else { _currentLevelStructuralColumns = new List <FamilyInstance>(); } if (_structuralFraming.Count > 0) { _currentLevelStructuralFraming = new FilteredElementCollector(_doc, _structuralFraming.Select(p => p.Id).ToList()).WherePasses(_withinLevelBoundsFilter).OfType <FamilyInstance>().ToList(); } else { _currentLevelStructuralFraming = new List <FamilyInstance>(); } if (_walls.Count > 0) { _currentLevelWalls = new FilteredElementCollector(_doc, _walls.Select(p => p.Id).ToList()).WherePasses(_withinLevelBoundsFilter).OfType <Wall>().ToList(); } else { _currentLevelWalls = new List <Wall>(); } //Generate LoadModels to populate a full LevelLoadModel LevelLoadModel _currentLevelLoadModel = LevelLoadModel.Create(_level); foreach (Floor _floor in _currentLevelFloors) { //The "top" floor is where the initial Demand is determined, which is to be supported via reshores propagating down through the building //ToDo: it would be valuable to be able to pick which Level to start from if (_level.Id == _topLevel.Id) { Parameter _floorThicknessParameter = _floor.get_Parameter(BuiltInParameter.FLOOR_ATTR_THICKNESS_PARAM); double _floorThickness = _floorThicknessParameter == null ? 0.0 : _floorThicknessParameter.AsDouble(); _currentLevelLoadModel.addFloorDemandLoadModel(_floor, _concreteDensityPoundsForcePerCubicFoot * _floorThickness); } //Add loads from other sources that are also distributed evenly along a level ILoadModel _floorCapacityLoadModel = levelLiveLoadPerSquareFoots.FirstOrDefault(p => p.Name == _level.Name); if (_floorCapacityLoadModel == null) { continue; } List <LoadModel> _floorLoadModels = _currentLevelLoadModel.addFloorCapacityLoadModel(_floor, _floorCapacityLoadModel.PoundsForcePerSquareFoot); foreach (ILoadModel _loadModel in levelLiveLoadPerSquareFoots.Where(p => p.Name.Equals(_level.Name))) { List <ILoadModel> _otherLoadModels = new List <ILoadModel>(); foreach (LoadModel _floorLoadModel in _floorLoadModels) { LoadModel _otherLoadModel = LoadModel.Create(); _otherLoadModel.Name = _loadModel.Name; _otherLoadModel.LoadType = _loadModel.LoadType; _otherLoadModel.PoundsForcePerSquareFoot = _loadModel.PoundsForcePerSquareFoot; _otherLoadModel.AreaSquareFeetXY = _floorLoadModel.AreaSquareFeetXY; _otherLoadModel.HeightFeetZ = _floorLoadModel.HeightFeetZ; _otherLoadModel.OriginXFeet = _floorLoadModel.OriginXFeet; _otherLoadModel.OriginYFeet = _floorLoadModel.OriginYFeet; _otherLoadModel.Curves = _floorLoadModel.Curves; _otherLoadModel.PlanarFace = _floorLoadModel.PlanarFace; _otherLoadModel.Element = _floorLoadModel.Element; _currentLevelLoadModel.addLoadModel(_otherLoadModel); } } } foreach (FamilyInstance _structuralColumn in _currentLevelStructuralColumns) { _currentLevelLoadModel.addFamilyInstanceLoadModel(_structuralColumn, LoadType.Demand, buildingLoadModel.StructuralColumnWeightPerSquareFoot); _currentLevelLoadModel.addFamilyInstanceLoadModel(_structuralColumn, LoadType.Capacity, buildingLoadModel.StructuralColumnWeightPerSquareFoot); } foreach (FamilyInstance _structuralFrame in _currentLevelStructuralFraming) { _currentLevelLoadModel.addFamilyInstanceLoadModel(_structuralFrame, LoadType.Demand, buildingLoadModel.StructuralBeamWeightPerSquareFoot); } foreach (Wall _wall in _currentLevelWalls) { _currentLevelLoadModel.addWallLoadModel(_wall, LoadType.Demand, buildingLoadModel.StructuralWallWeightPerSquareFoot); _currentLevelLoadModel.addWallLoadModel(_wall, LoadType.Capacity, buildingLoadModel.StructuralWallWeightPerSquareFoot); } //Set the Solid elements that we will project through the building, to represent demands/capacities LoadModel.SetSolids(_currentLevelLoadModel.LoadModels.OfType <LoadModel>(), _level, _topLevel, _bottomLevel); VisualizationDeliverable _visualizationDeliverable = new VisualizationDeliverable(_currentLevelLoadModel) { Floors = _currentLevelFloors, StructuralColumns = _currentLevelStructuralColumns, StructuralFraming = _currentLevelStructuralFraming, Walls = _currentLevelWalls, }; _visualizationDeliverables.Add(_visualizationDeliverable); _levelAbove = _level; } //Now that we've gathered all of our LoadModels, let's read the data about their actual demands/capacities buildingLoadModel.LevelLoadModels = _visualizationDeliverables.Select(p => p.LevelLoadModel as ILevelLoadModel).Where(p => p != null).ToList(); buildingLoadModel.ReadLoads(); foreach (LoadModel _loadModel in _visualizationDeliverables.Select(p => p.LevelLoadModel).SelectMany(p => p.LoadModels)) { _loadModel.SetDirectShapeWithParameters(_doc, _directShapeCategory.Id, _loadModel.Name); } //Update Levels in the model with Load details foreach (LevelLoadModel _levelLoadModel in _visualizationDeliverables.Select(p => p.LevelLoadModel)) { _levelLoadModel.SetLevelParameters(); } //Color our active View for the visualization colorActiveView(_doc, _visualizationDeliverables); //ToDo: something happened which broke colors being correctly applied to these sheets - will need to sort this out //createSheetsAndViews(_doc, _visualizationDeliverables, _modelExtents); // //colorViews(_doc, _visualizationDeliverables); // //createViewports(_doc, _visualizationDeliverables, _capacityViewCoordinate, _combinedViewCoordinate, _demandViewCoordinate); return(Result.Succeeded); }
private static Result placeTemporaryShoring(UIDocument uiDoc, BuildingLoadModel buildingLoadModel, List <ILoadModel> loadModels, string reshoringFamilyPathName, string reshoringFamilySymbol) { //Setup Document _doc = uiDoc.Document; //ToDo: it would be valuable to let users pick which Family & Type they want to use - so they can rapidly understand differences in layout for different reshores Dictionary <string, FamilyDefinition> _familyMappings = new List <string> { @"C:\ProgramData\Autodesk\Revit\Addins\2021\ApatosReshoring\Reshoring Poles 6x6.rfa", @"C:\ProgramData\Autodesk\Revit\Addins\2021\ApatosReshoring\Reshoring Poles Ellis 4x4.rfa", @"C:\ProgramData\Autodesk\Revit\Addins\2021\ApatosReshoring\Reshoring Poles Titan-HV.rfa", @"C:\ProgramData\Autodesk\Revit\Addins\2021\ApatosReshoring\Reshoring Poles Titan-XL.rfa", }.ToDictionary(p => Path.GetFileNameWithoutExtension(p), p => FamilyHelpers.GetOrLoadFamilyDefinition(_doc, p)); string _familyName = Path.GetFileNameWithoutExtension(reshoringFamilyPathName); FamilySymbol _temporaryShoreSymbol = null; if (_familyMappings.ContainsKey(_familyName)) { Family _family = _familyMappings[_familyName]?.Family; foreach (ElementId _symbolID in _family.GetFamilySymbolIds()) { FamilySymbol _familySymbol = _doc.GetElement(_symbolID) as FamilySymbol; if (_familySymbol == null) { continue; } if (_familySymbol.Name != reshoringFamilySymbol) { continue; } _temporaryShoreSymbol = _familySymbol; if (_temporaryShoreSymbol != null) { break; } } } if (_temporaryShoreSymbol == null) { return(Result.Failed); } if (_temporaryShoreSymbol.IsActive == false) { _temporaryShoreSymbol.Activate(); } var _levels = Getters.GetLevels(uiDoc.Document).OrderByDescending(p => p.Elevation).ToList(); var _floors = Getters.GetFloors(_doc).OrderBy(p => p.get_BoundingBox(null)?.Max.Z).ToList(); Level _topLevel = _levels.FirstOrDefault(); //Add Level Loads addLevelLoadModels(buildingLoadModel, _levels, _floors, _topLevel, loadModels); buildingLoadModel.ReadLoads(); //Place Temporary Shores Dictionary <double, double> _clearShoreHeightCapacityMappings = getClearShoreHeightCapacityMappings(buildingLoadModel, _topLevel, _temporaryShoreSymbol); LevelLoadModel _levelLoadModelAbove = buildingLoadModel.LevelLoadModels.OfType <LevelLoadModel>().FirstOrDefault(p => p.Level.Id == _topLevel.Id); if (_levelLoadModelAbove == null) { return(Result.Failed); } Dictionary <LevelLoadModel, double> _levelLoadModelXDistances = new Dictionary <LevelLoadModel, double>(); Dictionary <LevelLoadModel, double> _levelLoadModelYDistances = new Dictionary <LevelLoadModel, double>(); LevelLoadModel _lowestReshoredLevelLoadModel = null; double _levelAboveDemand = _levelLoadModelAbove.ReshoreDemandPoundsForcePerSquareFoot; foreach (LevelLoadModel _levelLoadModel in buildingLoadModel.LevelLoadModels) { if (_levelAboveDemand > 0.0) { if (_levelLoadModel.Level.Id == _topLevel.Id) { continue; } double _roundedClearShoreHeight = Math.Round(_levelLoadModel.ClearShoreHeight, 9); if (_clearShoreHeightCapacityMappings.ContainsKey(_roundedClearShoreHeight) == false) { continue; } double _loadCapacityPerShore = _clearShoreHeightCapacityMappings[_roundedClearShoreHeight]; double _minimumAreaPerShore = _loadCapacityPerShore / _levelAboveDemand; double _allowedAreaSquareSideLength = Math.Sqrt(_minimumAreaPerShore); double _roundedSideLength = Math.Floor(_allowedAreaSquareSideLength); //safer to round both down & have a smaller area _levelLoadModelXDistances.Add(_levelLoadModel, _roundedSideLength); _levelLoadModelYDistances.Add(_levelLoadModel, _roundedSideLength); //Adjust our Capacity & Demand, then determine if we can stop adding temportary reshoring _levelLoadModel.ReshoreDemandPoundsForcePerSquareFoot = _levelAboveDemand; _levelAboveDemand -= _levelLoadModel.CapacityPoundsForcePerSquareFoot; } else { if (_lowestReshoredLevelLoadModel == null) { _lowestReshoredLevelLoadModel = _levelLoadModelAbove; } _levelLoadModel.ReshoreDemandPoundsForcePerSquareFoot = 0.0; } _levelLoadModelAbove = _levelLoadModel; } //Update Level parameters foreach (LevelLoadModel _levelLoadModel in buildingLoadModel.LevelLoadModels) { _levelLoadModel.SetLevelParameters(); } //Place temporary reshoring List <FamilyInstance> _temporaryShores = new List <FamilyInstance>(); _levelLoadModelAbove = buildingLoadModel.LevelLoadModels.OfType <LevelLoadModel>().FirstOrDefault(p => p.Level.Id == _topLevel.Id); foreach (LevelLoadModel _levelLoadModel in buildingLoadModel.LevelLoadModels.Where(p => p.ReshoreDemandPoundsForcePerSquareFoot > 0.0)) { if (_levelLoadModel.Level.Id == _topLevel.Id) { continue; } if (_levelLoadModelXDistances.ContainsKey(_levelLoadModel) == false || _levelLoadModelYDistances.ContainsKey(_levelLoadModel) == false) { break; } double _sideXLength = _levelLoadModelXDistances[_levelLoadModel]; double _sideYLength = _levelLoadModelYDistances[_levelLoadModel]; //ToDo: add 1, subtract 1 from each side & check if their total area is closer to the calculated area than a square //ToDo: do this twice, and take the "middle" option List <Floor> _levelAboveFloors = _floors.Where(p => p.LevelId == _levelLoadModelAbove.Level.Id).ToList(); List <FamilyInstance> _temporaryReshores = new List <FamilyInstance>(); foreach (Floor _floor in _levelAboveFloors) { BoundingBoxXYZ _currentFloorBounds = _floor.get_BoundingBox(null); List <double> _xCoords = new List <double>(); for (double _x = 0.0; _x <= _currentFloorBounds.Max.X - _currentFloorBounds.Min.X; _x += _sideXLength) { _xCoords.Add(_x); } List <double> _yCoords = new List <double>(); for (double _y = 0.0; _y <= _currentFloorBounds.Max.Y - _currentFloorBounds.Min.Y; _y += _sideYLength) { _yCoords.Add(_y); } foreach (double _x in _xCoords) { foreach (double _y in _yCoords) { XYZ _insertionCoordinate = new XYZ( _currentFloorBounds.Min.X + _x, _currentFloorBounds.Min.Y + _y, _levelLoadModel.ElevationFeet); FamilyInstance _temporaryShore = _doc.Create.NewFamilyInstance(_insertionCoordinate, _temporaryShoreSymbol, Autodesk.Revit.DB.Structure.StructuralType.Column); Parameter _heightParam = _temporaryShore.LookupParameter("Height"); if (_heightParam != null && _heightParam.IsReadOnly == false) { _heightParam.Set(_levelLoadModel.ClearShoreHeight); } _temporaryShores.Add(_temporaryShore); } } } } //Regenerate so that the latest locations are updated in the model for our newly placed reshores - the intersects filters below will fail without this _doc.Regenerate(); var _scopeBoxes = Getters.GetScopeBoxes(_doc); Dictionary <ElementId, string> _shoreIdScopeBoxNames = new Dictionary <ElementId, string>(); foreach (Element _scopeBox in _scopeBoxes) { List <Element> _columnsInScopeBox = Getters.GetInsideElements(_doc, _temporaryShores, _scopeBox.get_BoundingBox(null)); foreach (Level _level in _levels) { List <Element> _columnsInScopeBoxOnLevel = _columnsInScopeBox.Where(p => ((p.Location as LocationPoint)?.Point.Z - _level.Elevation) <= 1.0).ToList(); string _pourName = Helpers.Views.BoundedViewCreator.GetViewName(_level, _scopeBox, string.Empty, string.Empty); foreach (Element _column in _columnsInScopeBoxOnLevel) { _column.get_Parameter(Ids.PourNameParameterId)?.Set(_pourName); } } } return(Result.Succeeded); }