Python wall LocationCurve issue

Hi,

I’m having trouble getting the curve of a wall LocationCurve.
When I try to get the Curve, it gives an error.
What am I doing wrong? I’ve looked at tons of examples where this works.
image

Ultimately, I’m trying to write a python code to find if a wall is exterior or interior by seeing if there’s a room next to it (based off Domina Package)

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)

clr.ImportExtensions(Revit.GeometryConversion)
from Revit.Elements import *

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
TransactionManager.Instance.EnsureInTransaction(doc)

walls = UnwrapElement(IN[0])

for i in range (0,len(walls)):

   wall = walls[i]

   # extract wall geometry and calculate middlepoint
   loc = wall.Location.Curve

OUT = loc

This means that some of the elements under the walls category have most likely been modeled as in-place components. In order to ensure you are only getting actual Wall objects, you can use a FilteredElementCollector like this:

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import FilteredElementCollector, Wall
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager

doc = DocumentManager.Instance.CurrentDBDocument
walls = FilteredElementCollector(doc)\
	.OfClass(Wall)\
	.WhereElementIsNotElementType()

crvs = []
for wall in walls:
	loc = wall.Location
	crvs.append(loc.Curve)
	
OUT = crvs

What @cgartland has shown is great! It will return the internal Revit Type though and to convert that to the Dynamo one, you have to add in a couple of lines as follows:

  1. Add in the RevitNodes reference and import the GeometryConversion type.
  2. Run a loop (Or in my case, a list comprehension) across the returned internal type curves to change to Dynamo’s
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import FilteredElementCollector, Wall
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager

clr.AddReference("RevitNodes")
import Revit
# Import ToProtoType, ToRevitType geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)

doc = DocumentManager.Instance.CurrentDBDocument
walls = FilteredElementCollector(doc)\
.OfClass(Wall)\
.WhereElementIsNotElementType()

crvs = []
for wall in walls:
    loc = wall.Location
    crvs.append(loc.Curve)

OUT = [c.ToProtoType() for c in crvs]

You can explore what these lines do here: https://github.com/DynamoDS/Dynamo/wiki/Python-0.6.3-to-0.7.x-Migration

1 Like

Thank you,

If I want to further filter the walls by a specific workset, what do I add?

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import FilteredElementCollector, Wall
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager

clr.AddReference("RevitNodes")
import Revit
# Import ToProtoType, ToRevitType geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)

doc = DocumentManager.Instance.CurrentDBDocument
walls = FilteredElementCollector(doc).OfClass(Wall).WhereElementIsNotElementType()
bldgwalls = FilteredWorksetIdIterator(walls).OfClass(0).WhereElementIsNotElementType()

crvs = []
for wall in bldgwalls:
	loc = wall.Location
	crvs.append(loc.Curve)
	
OUT = crvs

A bit messy but it will do.

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager

clr.AddReference("RevitNodes")
import Revit
# Import ToProtoType, ToRevitType geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)

doc = DocumentManager.Instance.CurrentDBDocument
walls = FilteredElementCollector(doc).OfClass(Wall).WhereElementIsNotElementType().ToElements()
worksets = FilteredWorksetCollector(doc).OfKind(WorksetKind.UserWorkset)
worksets_name = [i.Name for i in worksets]
worksets_id = [i.Id for i in worksets]
walls_worksets = [i.WorksetId.IntegerValue for i in walls]

worksetname = IN[0]

workset_filtered = []
n = 0
for i in worksets_name:
	for k in worksetname:
		if i == k:
			workset_filtered.append(worksets_id[n].IntegerValue)
	n=n+1

walls_filtered = []
n = 0
for i in walls_worksets:
	for k in workset_filtered:
		if i == k:
			walls_filtered.append(walls[n])
	n=n+1

crvs = []
for wall in walls_filtered:
    loc = wall.Location
    crvs.append(loc.Curve)

OUT = [c.ToProtoType() for c in crvs]

Thanks,

Now I’m trying to get the midpoint of the line. It’s giving me a unexpected indention error.

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager

clr.AddReference("RevitNodes")
import Revit
# Import ToProtoType, ToRevitType geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)

doc = DocumentManager.Instance.CurrentDBDocument
walls = FilteredElementCollector(doc).OfClass(Wall).WhereElementIsNotElementType().ToElements()
worksets = FilteredWorksetCollector(doc).OfKind(WorksetKind.UserWorkset)
worksets_name = [i.Name for i in worksets]
worksets_id = [i.Id for i in worksets]
walls_worksets = [i.WorksetId.IntegerValue for i in walls]

worksetname = ['All Other Elements']

workset_filtered = []
n = 0
for i in worksets_name:
	for k in worksetname:
		if i == k:
			workset_filtered.append(worksets_id[n].IntegerValue)
	n=n+1

walls_filtered = []
n = 0
for i in walls_worksets:
	for k in workset_filtered:
		if i == k:
			walls_filtered.append(walls[n])
	n=n+1

midpoints = []
for wall in walls_filtered:
    loc = wall.Location
    Spoint = loc.Curve.GetEndPoint(0)
    Epoint = loc.Curve.GetEndPoint(1)
    Mpoint = Point.ByCoordinates((Spoint.X+Epoint.X)/2,(Spoint.Y+Epoint.Y)/2,(Spoint.Z+Epoint.Z)/2)
	midpoints.append(Mpoint.Points)

OUT = midpoints

You can use the Curve.Evaluate method
https://www.revitapidocs.com/2019/1145f18e-3e01-60df-e438-e176c38c3ce9.htm

try adding

loc = wall.Location
curv = loc.Curve
Mpoint = loc.Evaluate(0.5, False)

Sorry I didn’t see that there was an indentation issue , I copied and pasted into python IDLE and got a mixed tab/spaces alert.
I wish I had an easy solution for this. When I get this I just use IDLE Dedent/indent for each section.

@ckepner It would be kind of you if you’d tell right away what you are trying to achieve instead of adding every time new thing to your requests.

Evaluate method proposed by @jonathan.talisman is indeed the correct way to get the midpoint of a Revit curve. However, your original request is long solved by @cgartland in the second post. Please choose his solution so the topic is closed. If you want more then create a new topic and specify the whole request so that people with same/similar problem can easily find it. Thank you in advance.

1 Like