Before execution, it was required to decide how to implement the task. Change the program in Dynamo for the current tasks or abandon the developments, using only parts of the algorithm, and try the solution using only text programming in IronPython language (hereinafter ipy) using the RevitPythonShell add-in (hereinafter RPS). I chose the second option and was not disappointed at all. It was also possible to implement this solution using the C # language in the Visual Studio program, but due to the fact that I do not have sufficient qualifications, this option has not yet been considered.
To execute the script, the RPS plug-in was used, which is an IronPython interpreter built into Autodesk Revit, which executes the code on ipy without using Dynamo, which allows the user not to switch between programs, and RPS can also create new panels and bring a button to the panel, upon clicking on which the script will be executed, the path to which is specified in the RevitPythonShell.xml settings file. Another advantage of RPS is that there is no temptation to use nodes from downloadable Dynamo packages, which often conflict with each other, thereby causing unpredictable script results and complicating the programmer’s work.
When you click on the corresponding button, the script allows the user to select the raised floor plate in the Revit window, so the program will output an object as an instance of the FootPrintRoof class.
As the initial data, we take the names of the standard sizes for the support racks for 2, 3 and 4 beams.
Further, by getting an object of standard size by name from the standard sizes of the project using the appropriate function. You will also need the level at which the raised floor is located for the method that will create the rack and the Offset from Level parameter to determine the height of the future racks.
Get the boundary lines for an instance of the FootPrintRoof class using the GetProfiles method and the GeometryCurve property.
Now we will get the cut lines of the raised floor using the CurtainGrids properties and the GetUGridLineIds () method, which will give the Id of the element, we will supply it to the next construction — Document. GetElement (Id) and at the output we find an element that corresponds to this Id, from it we extract the line corresponding to the element using the FullCurve property.
Obtaining points for further construction of support posts occurs by analyzing 2 groups of lines obtained above for intersection, as a result, we get 3 groups of points:
1 group of points (corner_points) is formed by crossing the boundary lines of the raised floor plate with each other, removing duplicates so that there are no duplicate posts in the future.
2 group of points (inner_point) is formed by intersecting the array of cut lines of the raised floor with each other.
3 group of points (boundary_point) is formed by the intersection of the raised floor cutting lines array and the raised floor slab boundary lines.
In all three cases, the Intersect method is used, the SetComparisonResult class, which indicates the type of intersection, and IntersectionResultArr, which stores the result of the intersection.
Since it is difficult to get a plane from the FootPrintRoof object due to the use of stained-glass glazing, the panels of which are raised floor tiles, we will use the construction of an additional floor object from the raised floor boundary lines. Add these lines to an instance of the CurveArray () class using the Append method and construct an overlap based on them using the following Document.Create.NewFloor construction. Then, using the Geometry [Options ()] and Faces properties, we get the element planes, to calculate the plane we need, we check for FaceNormal.Z is not 0, we get 2 planes, each of which will lie in the XY plane. After the necessary manipulations, remove the overlap.
Orientation, i.e., the angle to which you want to rotate the rack is determined by slightly incrementing the X and Y coordinates and projecting the new point onto the plane obtained in the previous step. Next, there is a check — whether the projection of the point with incremented coordinates lies on the plane or not. Now you can easily get the angle of rotation of the rack.
The rotation itself is carried out using the Location properties and the Rotate method of the Location class, for which you need to get an auxiliary line of the vertical axis around which the rotation will occur.
The family is created using the following construct Document.Create.NewFamilyInstance (point, type, level, StructuralType), where point is the insertion point of the family, type is the type of the new family, level is the level at which the family will be inserted, and StructuralType is the structural type.
In the script, the Dynamo add-in was used to debug and control the correctness of building and obtaining geometry, this is possible thanks to the python script from string nodes, which «reads» the code from the file, the RevitNodes libraries and the Revit.GeometryConversion and Revit.Elements extensions, which allow converting Revit elements to Dynamo elements, including geometric ones. The ToProtoType () method is used to convert instances of the Line and BoundingBox classes, and ToPoint () is used for Point. And already in Dynamo, thanks to the built-in graphics engine, it is possible to control the correct execution of the code when working with geometry. Dynamo is a powerful tool and shouldn’t be written off with a full switch to IronPython or C #.
The second part of the script is temporarily executed in dynamo, but in the future, it will be run via RPS.
After the user has manually laid the trays, we will run the script that will build the beams and consoles for attaching the trays.
As the initial data, you need to select all racks and trays in the Revit window through the Select Model Elements node, from the drop-down list of the Family Types node, select the name of the console and beam type to get an object of the type using dynamo nodes. In the Boolean node, select True to create beams or False if they have already been created and only the consoles need to be built.
The first step is to filter the selected items into racks and trays using the GetType ().Name method.
From the rack element, we can get the value of the “Level” property for constructing beams at this level using the GetParameterValueByName () method and the value of the custom parameter “Height to place the beam”.
Now let’s work with the trays. Let’s get the elevation values of the bottom of each of the trays and select the unique ones using the Parameter indexer for the tray element and the BuiltInParameter.RBS_CTC_BOTTOM_ELEVATION object, which we will pass to the get_Parameter method as an argument. Now that we have unique values for the elevations of the bottom of the trays, we will create an array with trays with the same elevation for each of the elevations.
For each base point of the rack, draw a line to all other insertion points, now select among these lines only vertical and horizontal using math.trunc (Line.Direction.X) == 0 and math.trunc (Line.Direction.Y) == 0. The trunc function from the math module is used to strip off the fractional part, because revit gets very small values where it should get 0 and the comparison will return False unless trunc or a similar function is used. As a result, we get lines for future beams.
For each of the groups of trays, we go through a loop and find the intersection point of the axis of the tray and the line of the future beam using the Geometry.Geometry.DoesIntersect method from the Autodesk.DesignScript namespace, an intersection check is performed, and the Geometry.Geometry.Intersect method returns the result of the intersection as a point . Now looking for the closest rack base point to insert the console
Using the FamilyInstance.ByPointAndLevel method from the Revit.Elements namespace, create a bracket element and rotate it using the SetRotation method, the angle for this method we define using the custom function AngleByVector, which analyzes the line for its direction and returns the angle by which the console should be rotated.
If the node with the custom name “Create Beams” is set to True and the type of the beam is specified, then the beams will be constructed using the starting points of the resulting lines using the same method as for creating bracket, the rotation of the beam is also determined by the AngleByVector function.
As a result of the scripts, we will get a finished model of the raised floor.