Happy Friday! I hope you had an egg-cellent easter if you celebrate or otherwise a good week.
As you know, I am tackling placing exterior elevations based on selected walls. One of our goals was to accommodate curved and angled walls. Our plug-in already accommodates walls at any angle. Now, we need to make a few adjustments to accommodate curved walls. This involves finding the normal for curved walls.
Part 1: elevation by wall
Part 2: phases
Part 3: rotating elevation markers
Part 4: align ViewSection CropBox to Wall CropBox
When we test our plug-in with curved walls, we immediately notice that the elevation
markers do not face the correct direction. Using
RevitLookUp we can see that the
Orientation of the wall does not face away or towards the curve, but instead is the
vector between the wall’s endpoints.
Curved walls fall into two categories:
category A: concave when looking at the wall from the outside
category B: convex when looking at the wall from the outside
Additionally, you can draw walls two different ways, from left to right and from right to left. Wherever you click first, that is the endpoint that is stored in the first index when you retrieve the endpoints of the location curve. We will call these type 1 and type 2. I diagramed these four instances in the image below.
When looking at the Orientation property for the wall, it is possible to notice a
pattern. For walls A1 and A2, the Orientation of the wall is the unit vector
from endpoint(0) to endpoint(1). The Orientation flips if you draw the curve
from right to left instead of from left to right. We will come back to this in a moment.
For now, we are going to make the adjustment to accommodate curved walls in our GetAngleViewtoWall method which we had created in Part 3 rotating elevation markers. Originally, we had used the wall’s Orientation property which is the wall’s normal for a straight wall. As we realized above, the Orientation of curved walls is not equal to the wall normal. When you have a curved wall, the LocationCurve is an Arc instead of a Curve. We can use this to filter our if statement so the part of the code we are about to write only executes if the wall is curved. If the wall is not an arc, the variable wallCurveAsArc will return null.
Since the variable wallCurveAsArc tells us if the wall is curved, we can use an if statement that checks if the variable wallCurveAsArc is not equal to null. From there we can first get the curve’s endpoints. We also want to get the angle between the endpoints using ArcTan and declare our curveNormal variable which we will use later.
We also need to figure out if a wall falls into category A: concave when looking at it from the outside or category B: convex when looking at it from the outside. We know that the Orientation of the walls that fall into category A is the unit vector from endpoint(0) to endpoint(1). This means that if the unit vector from endpoint(0) to endpoint(1) is equal to the Orientation, then it falls into category A. If they are not equal, it falls into category B. To simplify this comparison, we compare the signs for the X and Y value of the vectors to the signs of the X and Y values of the Orientation. This prevents any rounding errors that may happen if we were to compare the actual values.
First, we set up our Boolean variables.
Then we can use an if statement to find the correct curveNormal based on
if the wall is in category A or category B. If the wall is in category A,
the X and Y values of the unit vector from endpoint(0) to endpoint(1) is
equal to the X and Y values of the Orientation. We simplified this comparison
by only comparing the signs as described above. If the wall is in Category A1
then the curveNormal will equal the angle between the endpoints plus 90 degrees.
If the wall is in Category A2 the curveNormal will equal the angle between the
endpoints minus 90 degrees. To adjust if you add or subtract, we are multiplying
it by the YDirection property of the Wall’s LocationCurve. This YDirection tells us
if we flipped endpoints 0 and 1.
All walls that do not fall into category A, fall into category B.
This is our else condition and all we have to do is change from
addition to subtraction to accommodate the flipped condition. And that
is how you find the normal of a curved wall!
Once we find the normal of the curved wall, we need to rotate the elevation marker that we placed for the wall by the wall's normal minus 180 degrees. During testing, I noticed that rotating the marker by a negative angle did not work. So if angleViewtoWall is less than zero, we want to add 360 degrees.
Since we are modifying the GetAngleViewtoWall method that we previously wrote, we add the else statement at the end with the code needed for walls that follow a straight line. And that wraps up finding the normal and rotating the marker for curved walls. Next, we will look at how to place the elevation marker correctly for curved walls so it is not located in the middle of the curve.
UPDATE: 4/23/2020: I would like to add one note about a challenge that I found with the wall's normal. When I was testing this plug-in I had always created new curved walls to try it and had placed them where I wanted to test them. It wasn’t until I accidentally copied and pasted walls and then rotated them when I realized an interesting feature. The endpoints of a wall’s LocationCurve stay the same when you rotate walls. But the x and y direction parameter changes. This means that the walls are first created in the model coordinate space but when you rotate them they will be in a transformed space. The methods we used to find the wall's normal won't work if a curved wall was rotated after it was placed. I believe that this will apply to a small number of cases so I won’t be addressing it in this series. I did want to point it out so you are aware and can adjust your code to accommodate. I do have it on my list to address in the future.
If you want to learn to code and don’t know where to start check out my posts about Steps to Learn to Code [for architects and designers] Part 1 and Part 2.