Monday, April 25, 2011

ARCH653 Project 2

Motivations

For the last project in ARCH653, under the direction of Dr. Wei Yan at Texas A&M University, I decided to create a model that determines sightlines for theater design, concert hall, auditoriums, etc. This is a tedious and time consuming technical aspect of architectural design when made manually, but that can be automated for analysis of different design alternatives of a building, like a cinema complex. The "isacoustic" curve was developed by John Scott Russell in 1836, and my attempt is to automate the curve in Revit. There are many variations in sizes and distances according to the standards (distance from seats, distance from focal point, etc), but I chose some arbitrary standard units and started from there. However, those units can later be changed for different standards or purposes.

Model

Initially, I created a generic model mass family for each step (“step.rfa”) with an assigned “n” (instance parameter), which will be used later to assign a horizontal position in the project. That position will condition the height of the step to provide a proper sightline. The approach is to create parameters that can be easily assigned to a Revit model, leaving the complex parameters to be calculated by Revit API. In addition, I imported a theater seat and created parameters for an array arrangement based upon the width of the row.
Figure 1: Parameters in the generic model family in Revit.
To assign the horizontal position for “n” step, we used a “stage distance” (SD), in conjunction with a “focalheight” that determines the position of the most critical focal point. Then, I assigned a “Length” distance based on the “n” serial number multiplied by the constant separation between seats (n* T), where T = 3’6”). The “x” dimension includes the total distance from the focal point, represented by “SD + Length”. Finally, I created a parameter called “C”, which is basically the total height of the person seated minus the focalheight variable. This parameter will be linked later to calculate the vertical position of each seat using trigonometry in Revit API. I also added a “chair_v_d” parameter (stands for chair vertical distance) to control the distance of the seat to the top of the mass family (C parameter), taking as a reference the flat surface of the arm rest. I understand that the seats in a cinema will share the arm rest with their adjacent seats, but to simplify this project I will use a simpler arrangement.
Figure 2: Formulas for each parameter in the generic model family.
To find out the exact formulas, I made a diagram of the manual calculation to find out the formulas:
where n denotes the serial number; C is the parameter to be calculated in Revit API; A is one angle of the triangle formed by the focal point (also calculated in Revit API), seat distance and the eye level of each spectator; SD is the Stage distance (known value); and T is the Thread (constant value of 3’6”). From this formula we can derive:
Atan (An) = C* (n-1) + 4” / SD + T (n-2);
Cn = Tan (An)* SD * (T * (n-1));
Figure 3: Concept drawing to explain the trigonometric formulas used.
Then I created another generic model mass family (Project2.rfa) where I uploaded several “step.rfa” instances, all of them in the same location, selected one instance at a time and changed the "n" serial number in a consecutive order (1, 2, 3...etc). According to their serial “n”, each instance will move to the expected horizontal position. This family only incorporated the type parameters “StageDistance” and “focalheight” to be used later in the Revit API.
Figure 4: Project2.rfa parameters.

Revit API

For writing Revit API codes, I used a template created and provided by Dr. Yan in class, using Microsoft Visual Studio 2008. First, I needed to identify the ID’s of each step used in Project2.rfa. For this, I selected them all, went to Manage in Revit, and clicked “ID’s of Selection”. Then I selected the numbers, copy (CTRL+C) and paste them in my VisualStudio code lines (you can see the comments in green in the API code). For this project, I created 6 instances of steps, so I have a total of 6 ID’s to include. The second step was to verify that the ID’s are consecutive numbers. To achieve this, I selected each instance in Revit, checked their “n” value, checked their ID number and re-located the ID’s in API to be consistent with the order of “n”.
The next step was to assign a FamilyManager value for “focalheight”, since I will use this to determine the location of the first C value.
Then I created a loop function to calculate each step’s vertical position, since each new position depends on the position of the seat right in front of it (for (int n = 1; n < 6; n++). Notice that we don’t need to calculate the first seat position, but we need to start calculating the position of the second row until the last “n”. In Revit API, the first of an array or series has an n=0 for the first instance, so our second row will have an n=1 value. ”n<6” means that we will calculate up to the 6th row, and n++ means that we will increment “n” by 1 for each consecutive step or row.
Figure 5: Revit API initial lines of codes.
For getting objects in Revit API, we must refer to the Project2.rfa in order to input the values we need. If you recall, we are using Revit API to calculate what cannot be done in Revit Architecture, so we will only get the parameters needed for complex calculations. We need to separate the instance parameters from the type parameters, so as C is a parameter that has individual values according to the “n” associated with the instance step, it is considered as an Instance Parameter. Stage distance is a constant value for all the different rows, as well as the Thread parameter (constant value of 3’ 6”), so they are considered under type parameters.
Finally, we need to calculate the new C for each row, so we call math calculation formulas in API:
double An = Math.Atan((C[n - 1] + 4) / (StageDistanceParam.AsDouble() + ThreadParam.AsDouble() * (n - 2)));
C[n] = Math.Tan(An) * ((StageDistanceParam.AsDouble() + ThreadParam.AsDouble() * (n-1)));
And then we need to set C parameter values to re-locate each row in their expected vertical position. For this, we set the CParam according to each respective “n” value, and finish the loop here.
CParam.Set(C[n]);
Figure 6: Revit API codes for writing formulas.
 The calculation in Revit can be seen in Figure 7, where each row that follows the first seat changes its top surface.
Figure 7: Wrong calculation in vertical distance.
However, after measuring the distance between the steps, I found obvious errors. The vertical distance between each row should increase when “n” increases, but the opposite was occurring. Also, the vertical distance between rows was too high, which means that somehow the formula was incorrect.
double An = Math.Atan((C[n - 1] + 4) / (StageDistanceParam.AsDouble() + ThreadParam.AsDouble() * (n - 2)));
C[n] = Math.Tan(An) * ((StageDistanceParam.AsDouble() + ThreadParam.AsDouble() * (n-1)));
Since the original C in the diagram was calculated using the eye level and the additional 4” between the eye level and the top of the head; however, those 4” have to be converted into feet units (0.33’).
double An = Math.Atan((C[n - 1] + 0.33) / (StageDistanceParam.AsDouble() + ThreadParam.AsDouble() * (n - 2)));
C[n] = Math.Tan(An) * ((StageDistanceParam.AsDouble() + ThreadParam.AsDouble() * (n-1)));
Figure 8: Revit API "Get Objects", "Parameters" and “Calculate new values”.
That change led to better results calculating the vertical distance, but the progression in the vertical distance with increments of “n” was still backwards.
Figure 9: Changes in our Project2.rfa after using our Add-ins from Revit API.
Figure 10: The measurements show that the increment in the vertical distance still works in the opposite way.
To correct that progression, Dr. Yan and I noticed that the second formula was wrong, where n-1 being the divider of the equation will decrease the values progressively, so we changed it to:
double An = Math.Atan((C[n - 1] + 0.33) / (StageDistanceParam.AsDouble() + ThreadParam.AsDouble()* (n - 1)));
C[n] = Math.Tan(An) * ((StageDistanceParam.AsDouble() + ThreadParam.AsDouble() * (n)));
After this change, we got results very close to the manual calculations done in AutoCAD. The last correction was made to the vertical seat positioning, in particular the first seat. We know that the first seat will set the conditions for the remaining seats, but we forgot to add the calculations for the first seat before the loop. From the second to the last row, each step.rfa family instance was correct, except the first. These lines of codes were added to correct this issue, right bellow "C[0] = 3.75 - focalheight;":
            #region 2. Get objects
            // use id to get the Step family instance
            ElementId id;
            id = new ElementId(IDS[0]); //ID value of a Step family instance, obtained from the Revit model by selecting the opening and using menu Manage->IDs of Selection.
            FamilyInstance StepInstance = doc.get_Element(id) as FamilyInstance; //Get the element by ID and cast it to FamilyInstance, use id to get the focal point
            #endregion

            #region 3. Get Instance Parameters of the objects
            Parameter CParam = StepInstance.get_Parameter("C");
            #endregion
            CParam.Set(C[0]);
Where C[0] refers to the first seat (remember that the first element of a series when writing codes has a “0” by number). By making these changes, we had to delete redundancy on the codes, and since the C parameter was already defined earlier after this change, we now refer to it in the loop, so some lines of codes have to be simplified.
Figure 11: Final codes after correction.
This parametric file was tested against settings calculated manually in AutoCAD, with stage distances of 12'  -focalheight = 3’- and 23 rows, with a margin of error of ± 3”. The difference at the 23rd row was 2-7/16", being the manual calculation higher, due to the level of precision in the formula where 4 inches are converted into feet (0.33 or 0.33333333333333). With 14 decimals, the precision was improved with a difference at the 23rd row of 5/16". Please note that this is a logarithmic curve, so the longer the distance from the focal point, the greater the difference will be unless we improve the level of accuracy in the conversion from inches to feet.
This means that we can specify the level of accuracy depending on the size of the room. For smaller theater rooms or for testing different layout options, we could specify a level of accuracy of two to four decimals, which will accelerate calculation time. For final design or for larger rooms, the calculation should be more accurate (up to ten or fifteen decimals).

Figure 12: Superimposition of manual calculation in AutoCAD and the results from the Revit API, with 2 decimals of accuracy in the formula.
The idea is to use this parametric file to create the basic information, and to upload it later in a Revit project (.rvt). Revit API will be used to calculate the vertical variations (height) of each row, based upon the stage’s distance and the focal point. The modeling of the steps can be done by using the bottom surface of the mass, creating floors and align them to the bottom of a seat in a particular row. Later, the mass containing the seats can be hidden, so you will only see the seats that will be arranged based upon the width of each row. In summary, with these lines of codes we have been able to create a parametric file to be used in “real life”, facilitating the decision-making process of highly technical design situations.
Figure 13: Example showing the use of this parametric model and RevitAPI to calculate row positioning and number of chairs in a theater.
Work in progress:
  • create a graphic user interface to input required data; 
  • include customizable chairs with specific array options;
  • link construction details with each row for creating detail section documents; and
  • automate the creation of other row instances and their position.

Acknowledgments: I would like to thank Dr. Yan for his continuous support and patience during this project, since his help was invaluable...

Thursday, March 17, 2011

ARCH 653 Project 1


Project 1_Francisco Farías      ARCH 653

Motivations

This exercise is part of the ARCH 653 - "Building Information Modeling in Architecture" class at Texas A&M University, under the direction of Dr. Wei Yan.
I consider myself as a strong BIM advocate. However, I am aware of some of the limitations of these tools, so I wanted to check how difficult it will be to generate a complex Euclidean geometry under Autodesk Revit Architecture constraints of vertical walls and windows. I chose to model the Drager house designed by Franklin Israel as a case study, using the book
Drager House: Berkeley, California, 1994, Franklin D. Israel (Architecture in Detail), by Aaron Betsky, from the Phaidon series book as the main reference.

Modeling Process

First, I had to create Autocad reference drawings and import them into the desired levels in a 3D mode in Revit, creating the levels (1 level, 2 level, etc) and attaching the imported CAD to each level. Please notice that the Autocad reference drawings were taken from a book (scanned) and that the drawings in the book are not “as-built”, so I interpreted additional information from the photos provided. Second, I started with the topography, also importing a CAD reference where each topographic line was already in its correct 3D position using "elevation" (a tip: use poly-lines instead of splines for the topographic curves). Then I picked “Create from import” to create the site and then simplified the surface whenever it was necessary using “Simplify surface”, or simply by moving some points of the topographic surface. Following that, I created the building pad to leave a “hole” in the topographic surface to insert the building. The building pad was created picking the lines provided in the imported site Autocad reference file. 
Figure 1: Imported Autocad drawing of the site, with building pad profile included.
It is important to mention that the site and all the reference CAD needs to be correctly scaled before doing any intervention in Revit, because later on, the site cannot be scaled down (or up). I simplified the surface by 10’, and later on I had to correct the elevation of some points, using as a reference the elevation value of adjacent points in the same topographic line.
Figure 2: Site before correction

Figure 3: Site after correction.
The next step was to start modeling the walls, doors and floors, which was a pretty straight forward process of modeling walls following the reference Autocad drawings, one for each level. I had problems with some of the sliding opaque doors that are hidden inside the walls (between the dining-room/kitchen and the master bedroom). Revit does not currently have a family that represents that kind of doors, so I replaced them with regular doors in order to have an adequate representation of the space enclosure. The floors were created using “pick lines” from the imported Autocad file, and editing the profile when necessary, aligning it to walls or topography.
Figure 4: Walls, doors, floors and stairs being modeled.
For the tilted walls and roofs, I had to create a mass family that will later shape the exterior walls and roofs (pick by face). The main challenge was to model the tilted walls and roof’s angles. The slope of the roofs have two axis, plus the non-rectangular plan shape. For accomplishing this correctly, I had to create basic and simple rectangular massing first, in the second place I had to create reference planes for the roof’s slopes changing the angle in elevation views, moving the ending points of the surface until they reaches both reference planes (eliminate constraints!).
Figure 5: Selecting ending points of the basic mass surface.


Figure 6: Moving the ending points of the basic surface to reach the desired roof's slope according to the reference plane.
Then, I was able to create a void mass to extract additional mass so I could reproduce the actual shape of the envelope. If you start creating the mass form trying to recreate the actual shape in plan view (non rectangular), and later on change the roof slope you will have non planar surfaces, which may cause you several problems. The key is to try to keep the original planar surfaces intact through the whole process to avoid inconsistency or misaligned surfaces.
The insertion of the mass family is another important step (plan view and 3D view), since it will affect the position and reference of the walls and roofs created. It will not be possible to achieve the same results if you insert the mass family in another position apart from the intended, create the walls and roofs from it and then try to re-locate the walls and roofs. Even if you group them, the geometry will be altered if you move them from the original insertion point.
Later on, some of the walls were modified using the “Edit profile” option. However, the tilted walls could not be edited using “Edit profile”, which forced me to recreate the actual shape of the walls perfectly in the original mass family (more on that later). It is worth mentioning that one the roofs (it is a ceiling actually in the entrance in level 3) is a non-planar surface, which lead me to create a special mass for it to simulate the double curvature of that ceiling. The information about this ceiling was not clear from the book.
For the tilted wall, I used a similar approach as the rest, creating reference planes to create void mass and then to extract them from the original mass. 
Figure 7: Moving ending points of the surface to reach the desired reference plane.
Figure 8: Creating the first "void mass"to reproduce the tilted wall angle.
Figure 9: Creating the second "void mass"to reproduce the actual shape of the tilted wall.
I faced many problems while creating the tilted walls:
  • In a mass family, walls can only be rotated in one plane, which is not the angle that allows the wall to be correctly tilted. This led us to control the angle by moving points or segments with a distance from a reference plane, which is not very accurate and it makes it very difficult to control while modeling.
  • Measuring in a mass family is very limited (only through elevation views, not in the 3D mode).
  • The profile of tilted walls of a family cannot be edited.
  • Align function for 3D surfaces do not work properly since it deforms some surfaces of the volume (see Figures bellow).
Figure 10: The top of the volume is a planar/horizontal surface that needs to align with the tilted reference plane.
Figure 11: Notice that the top is not a horizontal surface anymore, since the alignment tool picks the nearest perpendicular point of the reference plane as a reference.
The chimney of the master bedroom was one of the most difficult pieces to model, since it has two tilted walls that intersect different walls and floors, so the shape of the wall was very difficult to get from a simple and single mass. This forced me to create several different mass families for each challenge to simplify the visualization of each piece.
Another challenge was the creation of the tilted corner windows. You can put a regular window on a tilted wall, but the window will not follow the angle of the tilted wall (it will still be a vertical window). To accomplish this, the window was approached as a curtain wall system (picked by face); however, the glass corner joint with no mullions (just structural silicone) was not possible to be recreated. Some corner windows had mullions, whose design was achieved establishing the grid lines, and then the mullion by picking the grid lines.
The roofs were also created in the Mass Family, where I had to leave a space for the two skylights using “void form”. After the roofs were created, I could attach (Attach Top/Base) the interior walls to it so the space was correctly enclosed. The skylights were created using mass and curtain wall systems (picked by face), which offers more flexibility creating mullions and its subdivisions, establishing the maximum number and/or distance. The windows were created duplicating existing window types and modifying them accordingly. Some windows required a combination of two or more window types located one next to the other, which was grouped later as a single window.
Stairs was another issue during the modeling, since I could not create one of the monolithic exterior stairs. An error message said that the top level was under the base level of the stair, which was not true… but after changing the stair type (not monolithic) the final stair was able to be created. Railings were also difficult to customize, since the profile of the handrail and the profile of cables of my railing were not possible to be edited quickly, hence the appearance is not exactly the same as the railing designed in the actual house.
The interface for materials and visualization is in general very intuitive and easy to follow. The rendering quality is quite good in my opinion (nice shadows), although some post process in Photoshop would be nice since the overall rendering looks kind of washed-out (I used it for my renderings).
In summary, Revit still have many limitations trying to recreate building shapes such as tilted walls, corner windows, or some specific and unique conditions like a special railing design. The interface and the overall procedure to accomplish them are rather complicated and non-intuitive. If you are modeling a very small but complex building geometry-wise, other tools may be better suited. Or you can start generating the mass in another 3D modeler and then import it into Revit.
In my opinion, the power of Revit resides on creating formula driven shapes, and controlling parameters to change their properties, besides the possibility of generating schedules, material take-offs, geometry for energy analysis, 4D simulation, and so on… Also, it is best suited for traditional big scale buildings where standard components are used in serial repetitions (stairs, windows, doors, furniture, etc.), which allows for an efficient management of the parts and pieces.

Parametric Modeling

The parametric family was intended to recreate part of the roof/wall envelope of the Drager house, in terms of the possibility to have a tilted wall+roof and control the angles of both the roof and the tilted wall.
The basic equations are based upon trigonometric functions. I have parametric height for the space, a parametric width of the space (tilt wall start), angle for the tilted wall (related to the sun altitude) and an angle for the roof, and the beginning of the tilted wall - where the angle starts - which gives an overall envelope thickness to start with.
The generation of the 3d shape was tricky: if you select the profile and then generate the form, you will keep the constraints only on the first profile, not in the second. If you add later the constraints and rules to the second profile, the performance will be very limited and constraints will not be satisfied. The solution was to copy another profile, add the rules to it and then create the form using “sweep” or selecting both profiles to generate the form.
Using a combination of 2 or more of this family can help to generate a similar roof and walls as the ones found in the Drager House. Rotation and “void mass” will be required to recreate the actual shape of the house.  I tried with no success to add another set of rules to rotate the roof in two axes, rather than the roof angle only, so that is a challenge for further work.
Figure 12: Entering the parameters for the first interaction.
Figure 13: Results of the parametric input 1.

Figure 14: Entering the parameters for the second interaction.
Figure 15: Results of the parameter input 2.

Figure 16: Diagram with equations.
Note: there was a conditional formula that if c = 0, i.e.  no tilted wall is present, then keep the “Tilt wall start” as 20’ (arbitrary… it can be changed), otherwise, keep the rule of “Tilt wall start” + c. 


Renderings of the finished model:
Figure 17: Exterior view 1

Figure 18: Exterior view 2

Figure 19: Exterior view 3

Figure 20: Interior view 1
Figure 21: Interior view 2


Figure 22: Perspective Section


The next post will be about Revit API, so stay tuned!