How to dimension exterior walls from end to end

I am trying to dimension exterior walls, like from one end to another. Following is my code:

opt = Options()
opt.ComputeReferences = True
opt.IncludeNonVisibleObjects = True
opt.View = doc.ActiveView
for twall in targetWalls:
	refarray = ReferenceArray()
	for obj in twall.get_Geometry(opt):
		if isinstance(obj, Solid):
			gline = obj
			vertReferences,vertEdges = [],[]
			for edges in gline.Edges:
				if round(edges.AsCurve().GetEndPoint(0).ToPoint().Z,10) != round(edges.AsCurve().GetEndPoint(1).ToPoint().Z,10):
					vertReferences.append(edges.Reference)
					vertEdges.append(edges)
	if type == "Option 1":
		opt1 = []
		refVector = twall.Orientation
		bbox = twall.get_BoundingBox(doc.ActiveView)
		dim_line = twall.Location.Curve.CreateOffset(offDist,refVector)
		for ref,edg in zip(vertReferences,vertEdges):
			if round(edg.AsCurve().GetEndPoint(0).Y) == round(bbox.Max.Y):
				opt1.append(edg.AsCurve().GetEndPoint(0).X)
				if round(edg.AsCurve().GetEndPoint(0).X) == round(bbox.Min.X):
					refarray.Append(ref)
				elif round(edg.AsCurve().GetEndPoint(0).X) == round(bbox.Max.X):
					refarray.Append(ref)
		dim = doc.Create.NewDimension(doc.ActiveView,dim_line,refarray)
		dimensions.append(dim)

it mostly gives error due to references. Can anyone help me optimize this code so I can get only the end references to dimension

-first I am not able to set the offset properly
-second this works for some horizontal walls, I know I can create a try except statement for vertical and horizontal walls but it is still not working for some horizontal walls and I don’t know why

an update to the code, its creating dimensions but some of them are not visible in the view. Any one can help me out/

opt = Options()
opt.ComputeReferences = True
opt.IncludeNonVisibleObjects = True
opt.View = doc.ActiveView
for twall in targetWalls:
	refarray = ReferenceArray()
	for obj in twall.get_Geometry(opt):
		if isinstance(obj, Solid):
			gline = obj
			vertReferences,vertFaces = [],[]
			for face in gline.Faces:
				if face.FaceNormal.Normalize().IsAlmostEqualTo(XYZ(0,0,1)) == False:
					vertReferences.append(face.Reference)
					vertFaces.append(face)
	if type == "Option 1":
		opt1r,opt1f = [],[]
		refVector = twall.Orientation
		bbox = twall.get_BoundingBox(doc.ActiveView)
		dim_line = twall.Location.Curve.CreateOffset(offDist,refVector)
		for ref,f in zip(vertReferences,vertFaces):
			if round(refVector.DotProduct(f.FaceNormal)) == 0:
				opt1r.append(ref)
				opt1f.append(f)
		l = 0
		refa = [0,0]
		le = []
		for a,r in zip(opt1f,opt1r):
			p = a.Origin
			for a1,r1 in zip(opt1f,opt1r):
				len = p.DistanceTo(a1.Origin)
				le.append(len)
				if len > l:
					l = len
					refa[0] = r
					refa[1] = r1
		for ref in refa:
			refarray.Append(ref)
		#dim = doc.Create.NewDimension(doc.ActiveView,dim_line,refarray)
		#dimensions.append(dim)

this is working but when I try to select the Dimensions in Revit with select by ID and click on show, it prompts that no good view could be found. I am using Revit 2021

The first thing that I see is this:
if face.FaceNormal.Normalize().IsAlmostEqualTo(XYZ(0,0,1)) == False
This is not removing all horizontal faces but only the ones that have the normal looking up. That could leave faces that have a normal of XYZ(0,0,-1). Check for parallelity with Cross Product or dot product instead of checking if they are almost equal.


if round(refVector.DotProduct(f.FaceNormal)) == 0:

This is rounding to a whole number. It isn’t exactly ideal.
Basically what I’d do is get the faces that are perpendicular to the curve which I’m using for placing the dimensions. That way you will always get the right faces.

2 Likes

you mean face normal will be parallel to line direction right?

yes

apparently the condition for horizontal faces was the one causing problems but the script is working now. just that for one or two cases face.Reference is giving out a null so a face in the middle is getting selected instead. not sure why is that happening…any suggestions?

It is possible that the face.Reference returns a null. I haven’t got that error, but I checked if the solid has a volum larger than 0 before checking for the faces.

Make a new list of faces and only append to the that list if the face.Reference returns a value.
That way you’d have matching faces and references and you wouldn’t get a different face.
I’d also like to encourage you to share more visual aid when looking for help on these forums - screenshots of the workflow, the errors etc.