Filled Region Edge Graphic Style Id

python

#1

Following the script @Giovanni_Brogiolo provided, I was able to get each edge of the filled region from all of the filled regions in the project, but I would like to ask for help checking each edge against a defined Graphic Style and change it if different. I have provided a couple images for reference. I am not sure why I can’t get the doc.GetElement(edge.GraphicsStyleId) == gs2 to work. Thanks in advance for any help you may offer.

Here is the script:
import clr
clr.AddReference(‘ProtoGeometry’)
from Autodesk.DesignScript.Geometry import *

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application


region = UnwrapElement(IN[0])
geoOpt = app.Create.NewGeometryOptions()
gs1 = IN[1]
gs2 = IN[2]

TransactionManager.Instance.EnsureInTransaction(doc)

edgeArray = []
for r in region:
	geoElem = r.get_Geometry(geoOpt)
	enum1 = geoElem.GetEnumerator() ; enum1.MoveNext()
	geo2 = enum1.Current
	edgeArray.append(geo2.Edges)
	
lineStyles = []
for i in range(0,len(edgeArray)):
	ls = []
	lineStyles.append(ls)
	for edge in edgeArray[i]:
		if doc.GetElement(edge.GraphicsStyleId) == gs2:
			ls.append(doc.GetElement(edge.GraphicsStyleId))

TransactionManager.Instance.TransactionTaskDone()

#Assign your outputs to the OUT variable
OUT = lineStyles, gs2

Here is what I get when I use the code as is:
broken

Here is what I get when I don’t use the “if”:
working


#2

There are a couple of things…
edgeArray is your full list of filled region boundaries. There’s no need to say for i in range[…] for edgeArray AND for edge in edgeArray as they do the same thing. They both iterate through edgeArray. You’re also appending your line styles (ls) before populating them, so you just have empty lists. Lastly, you don’t need to GetElement for edge as edge is already the element.


#3

Also please post your urchin as preformatted code. Will save a lot of headaches for those who try and help more directly.


#4

What are IN[1] and IN[2] supposed to be? Line Types?


#5

@Nick_Boyts - To be honest, I thought the same thing, and when I first used the code which I found on another post, but when I tried to simplify it I think I realized that edgeArray is all of the edges for each region, and then “edge” is each individual edge within each set of edges. perhaps I have that wrong, and I would love to simplify it if I could. I will adjust the location of the append but it does work above because the for and if are nested below for iterating through I think. I figure the formatted I am delivering “gs2” in isn’t matching what edge.GraphicStyleId is providing. Thoughts?


#6

Yes, I pick two elements from the model:
gs1 - line style I want to be changed
gs2 - line style I want to change to

Full Graph:


#7

I don’t see where gs1 is even called in the code. And you’re currently using line type name instead of the actual element type.


#8

@Nick_Boyts, I haven’t gotten far enough to call gs1. I am trying to work through matching them I worked the code a little bit and I am testing against one filled region for clarity.

You can see here that I get all four lines of the filled region rectangle, and the GraphicStyle of each. Then the other out is gs2, the graphicStyle of the line I selected in the model. You can see that they match.

Code changes:

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

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application


region = UnwrapElement(IN[0])
geoOpt = app.Create.NewGeometryOptions()
gs1 = IN[1]
gs2 = IN[2]

TransactionManager.Instance.EnsureInTransaction(doc)

edgeArray = []
for r in region:
	geoElem = r.get_Geometry(geoOpt)
	enum1 = geoElem.GetEnumerator() ; enum1.MoveNext()
	geo2 = enum1.Current
	edgeArray.append(geo2.Edges)
	
lineStyles = []
for reg in edgeArray:
	ls = []
	lineStyles.append(ls)
	for edge in reg:
		ls.append(doc.GetElement(edge.GraphicsStyleId))
	
TransactionManager.Instance.TransactionTaskDone()

#Assign your outputs to the OUT variable
OUT = lineStyles, gs2

Image of what I see:
image

However, when I try to run the “if” against them in the following code, I get an empty list:

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

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application


region = UnwrapElement(IN[0])
geoOpt = app.Create.NewGeometryOptions()
gs1 = IN[1]
gs2 = IN[2]

TransactionManager.Instance.EnsureInTransaction(doc)

edgeArray = []
for r in region:
	geoElem = r.get_Geometry(geoOpt)
	enum1 = geoElem.GetEnumerator() ; enum1.MoveNext()
	geo2 = enum1.Current
	edgeArray.append(geo2.Edges)
	
lineStyles = []
for reg in edgeArray:
	ls = []
	lineStyles.append(ls)
	for edge in reg:
		if doc.GetElement(edge.GraphicsStyleId) == gs2:
			ls.append(doc.GetElement(edge.GraphicsStyleId))
	
TransactionManager.Instance.TransactionTaskDone()

#Assign your outputs to the OUT variable
OUT = lineStyles, gs2

Here is what I get, an empty list.
image


#9

Here’s how it should* look in order to get everything to run properly (with some visual checks added).
*The problem is that GraphicsStyleId is Read Only for edges. I think you should probably be using the GetBoundaries method in order to return modifiable curves.

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

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application


region = UnwrapElement(IN[0])
geoOpt = app.Create.NewGeometryOptions()
gs1 = UnwrapElement(IN[1])
gs2 = UnwrapElement(IN[2])

TransactionManager.Instance.EnsureInTransaction(doc)

edgeArray = []
for r in region:
	geoElem = r.get_Geometry(geoOpt)
	enum1 = geoElem.GetEnumerator() ; enum1.MoveNext()
	geo2 = enum1.Current
	edgeArray.append(geo2.Edges)
	
currentLineStyles = []
newLineStyles = []
for reg in edgeArray:
	cls = []
	nls = []
	
	for edge in reg:
		cs = doc.GetElement(edge.GraphicsStyleId)
		cls.append(cs)
		if cs.Id == gs1.Id:
			ns = edge.GraphicsStyleId = gs2.Id
			nls.append(ns)
	currentLineStyles.append(cls)
	newLineStyles.append(nls)
TransactionManager.Instance.TransactionTaskDone()

#Assign your outputs to the OUT variable
OUT = currentLineStyles,newLineStyles

#10

@JacobSmall & @Nick_Boyts, thanks for the revisions, I agree that is how it should look, but I think the process of changing individual lines is the problem I don’t have a solution for. One step back on this, I appear to be getting different results from “Select Model Elements” vs “Get Filled Regions”.

When I select one or multiple Filled Regions via Select Model Elements, I get the “IF” statement to work and all of the GraphicsStyleId’s that I am supposed too. However, I just get a broken node when I use 'Get Filled Regions". I have tried to flatten, create list, levels and nothing seems to work. Anyone have thoughts on that?

Here is the current code:

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

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application


region = UnwrapElement(IN[0])
geoOpt = app.Create.NewGeometryOptions()
gs1 = UnwrapElement(IN[1])
gs2 = UnwrapElement(IN[2])

TransactionManager.Instance.EnsureInTransaction(doc)

edgeArray = []
for r in region:
	geoElem = r.get_Geometry(geoOpt)
	enum1 = geoElem.GetEnumerator() ; enum1.MoveNext()
	geo2 = enum1.Current
	edgeArray.append(geo2.Edges)
	
currentLineStyles = []
newLineStyles = []
for reg in edgeArray:
	cls = []
	nls = []
	
	for edge in reg:
		cs = doc.GetElement(edge.GraphicsStyleId)
		if cs.Id == gs1.Id:
			cls.append(True)
		else:
			cls.append(False)
			#ns = edge.GraphicsStyleId = gs2.Id
			#nls.append(ns)
	currentLineStyles.append(cls)
	#newLineStyles.append(nls)
TransactionManager.Instance.TransactionTaskDone()

#Assign your outputs to the OUT variable
OUT = currentLineStyles

Here is the Error when using “Get Filled Regions” node:

Here is what it looks like when I use “Select Model Elements”:


#11

Masking regions and other ‘odd’ types may be causing a problem here. Try filtering them out and see if you get any different results.


#12

Thanks @JacobSmall, I have been working through your suggestion and I was finding a lot of items like MR that were being supplied but didn’t work down the line. I also found several FR that were inside of a group, and were producing “NULL” values for “Id”. Although I have been able to filter those, I seems to get other random errors or null values for regions with complex geometry and/or very short lines. I will post if I can resolve this completely, but for now I am still on the hunt.


#13

Best to start with a smaller selection set than all filled regions then.

Perhaps all elements of category in view (MEPover package) would be a good place to start? Run it via dynamo player on the active view, and watch for errors and/or stuff that doesn’t change. Then switch views and do it again. Could even be run for all views on a given sheet if you really want to speed things along a bit. My guess is groups are going to be the biggest hang up here as you can only edit them when in group edit mode.


#14

You might be able to build an ElementCollector that would just take the type you’re wanting to change. Not sure if it would handle these “non-filled regions” any better.


#15

I agree that is the end goal. Hard part is identifying the issue types/elements.


#16

Oh right. I forgot we’re searching for line types within the filled region, not filled region types.
I guess you could use a try: statement in Python and attempt to skip the “bad” types.


#17

Thanks for all of the help. For now, I am going to look into some try statement within the node getting all of the Ids to see if I can parse any error to keep the script running rather than failing. This should sort out MR and Groups.


#18

@Sean1 There is this node from the package Plissken, that just changes all of the lines. I believe the Python script within this node could be modified to only change lines of a certain line style


#19

Thank you @awilliams, I will take a closer look tomorrow, but this code is much more sophisticated and get the boundaries in a completely different way, which is what I was looking for.