Using python or dynamo to differentiate the inside and outside of a building

Hi, I’ve been using and modifying python code to create elevation markers from https://learndynamo.com/mod2/ to create curtain wall elevations.

One thing I’m not sure how to do or even code is how to always create an elevation marker on the outside of the building. Because curtain walls dont have a location line. I’ve had a think about it and could you have rules that if there’s a floor it will create on the other side of that? But then you have decks as floors on the outside sometimes so how would that help. Is it possible to create a perimeter line of a building at each floor and create an elevation marker on the outside of that. Maybe there’s something much simpler I haven’t thought of. Maybe there’s something that could be done in dynamo before going into the python script with the location point.

The elevation marker creator code below

import clr
clr.AddReference('RevitAPI')
clr.AddReference("RevitServices")
clr.AddReference("RevitNodes")
import RevitServices
import Revit
import Autodesk
from Autodesk.Revit.DB import *
from math import *

clr.ImportExtensions(Revit.GeometryConversion)

from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument

toggle = IN[0]
points = UnwrapElement(IN[1])
modelPoints = UnwrapElement(IN[2])
cropCurves = UnwrapElement(IN[3])
viewType = UnwrapElement(IN[4])

lst = []
viewid = []
output = []

#Get Family View Type
vft = 0
collector = FilteredElementCollector(doc).OfClass(ViewFamilyType).ToElements()

#eleViews = []
for i in collector:
	if i.ViewFamily == ViewFamily.Elevation:		
		vft = i.Id
		break
 
if toggle == True:
	
	TransactionManager.Instance.EnsureInTransaction(doc)
	
	for ind, point in enumerate(points):
	
		#Retrieve the mid point of model lines and get X,Y.		
		modelMP = modelPoints[ind].ToXyz()
		modelMPX = modelMP.X
		modelMPY = modelMP.Y
		
		#Retrieve individual lines of crop window.		
		cropLines = cropCurves[ind]
		l1 = cropLines[0].ToRevitType()
		l2 = cropLines[1].ToRevitType()
		l3 = cropLines[2].ToRevitType()
		l4 = cropLines[3].ToRevitType()
					
		# Create a line in the z-Axis for elevation marker to rotate around.			
		elevationPT = point.ToXyz()
		elptRotate = XYZ(elevationPT.X, elevationPT.Y, elevationPT.Z+100)
		ln = Line.CreateBound(elevationPT, elptRotate)

		#Calculate the angle between Model Mid Point and Elevation Point.
		elevationPTY = elevationPT.Y
		elevationPTX = elevationPT.X							
		combY = elevationPTY-modelMPY
		combX = elevationPTX-modelMPX			
		ang = atan2(combY, combX)/2 
		ang1 = atan2(combY, combX)/2

		#Create elevation marker and elevation in position 0.
		eleMarker = ElevationMarker.CreateElevationMarker(doc, viewType.Id, elevationPT, 100)
		ele = eleMarker.CreateElevation(doc, doc.ActiveView.Id , 0)
		viewid.append(ele)
		
		#Rotate elevation marker towars model line.
		ElementTransformUtils.RotateElement(doc, eleMarker.Id, ln, ang)
		ElementTransformUtils.RotateElement(doc, eleMarker.Id, ln, ang1)
		
		#	
		crManager = ele.GetCropRegionShapeManager()
		#crShape = crManager.GetCropRegionShape()

		newCurveLoop = []
		newCurveLoop.Add(l1)
		newCurveLoop.Add(l2)
		newCurveLoop.Add(l3)
		newCurveLoop.Add(l4)
			
		cLoop = CurveLoop.Create(newCurveLoop)

		try:			
			crManager.SetCropShape(cLoop)
			lst.append("Elevation Created")
		
		except:
			pass
			lst.append("Missed Elevation")

	TransactionManager.Instance.TransactionTaskDone()
	
	output.append([lst,viewid])
	
	OUT = output
	
	
else:

	OUT = "Set Run Gate to TRUE"

1 Like

Hey,

I’ll watch this topic with interest :slight_smile:

My hunch is that you will always get some errors… if 95% are correct, tidying the rest is perhaps acceptable?

Your floor idea is neat, you could filter out floors with ‘deck’ or ‘external’ perhaps? Or if there is a floor on both sides?

The host wall for the curtain wall will have a facing orientation… can you grab that?

I’ll have a play tomorrow…

Mark

By the way thanks mark, I found your solution in the comments to always get the elevation marker facing the right way at least :slight_smile:

I know I have a lot of jobs with curtain walls without a host wall.

I’ve got a bit of tunnel vision but going to try create a perimeter outline of a building at levels by the elements/walls. Then possibly turn this perimeter outline of the building into an area that elevation markers can not be placed and will revert to the other side? hmmmmm

Chucking ideas around is easy, getting the graph to work is hard :slight_smile:

I like your inginuity and tenacity!

Perhaps you have already made an Area for you gross/net internal area calculation? (If you haven’t somehow already automated that :wink:)

1 Like

There is a node in Archilab called Wall.ExteriorDirection. I have found that it works quit well. You will have had to modeled you curtain walls the correct direction though. I have been trying to do this same thing for some time 95% of the way there. I have had good results with that node though.

1 Like

Why not use a room on the outside of your building for this? For each level, make a massive box of room separation lines which completely encompass your project, place a ‘room’ called 'exterior, and then get it’s perimeter boundaries, group the curves, drop the ones which align with the created room separation elemetns, and offset by X units (pushing the boundary off the wall face. Once done, delete the box and the room (unless you want it. I usually do).

2 Likes

I’ve gone with floors to eliminate explaining to anyone that they need to create a room in their project. Not sure if the room would mold to the exterior of building with odd shaped levels as it goes up. If the level above was smaller then the level below, would it wrap onto the smaller level, just something I noticed in section.

Another thing to identify if a elevation point is in the building is if its intersected with a room

managed to reverse the elevation points if they intersected with a floor!
image

figured out a much cleaner way of finding an intersection and moving it with If statements, list.isempty and Intersection.Findintersection

1 Like