I am trying to create my “Magic” button for which there are many angles of attack.
In short, i am trying standardise the linestyles in my projects whilsts allowing my users to continue to import schematics and details with legacy and incorrect linestyles. And you know… magic button fix.
What i can do (In Python)
-Create linestyle patterns (dash dot etc…)
-Create linestyles (Name, weight, pattern) and name the lines appropriate to color, weight and pattern
-change linestyle colors
-change linestyle patterns
-Find duplicate linesstyles, transfer all the curves in the project from the wrong one to the new one and delete the old one
What i cant do
-Analyse existing line patterns to determine the spacing and lengths of their respectice dash dots and spaces etc… (to determine duplicates to my correct types and replace them)
Does anyone know how to correctly utilise the API to correctly get the linepattern segments and lengths, i have sruggled for a while on this.
As far as i get is this but ive struggled to use it correctly to get a result of any use. http://disq.us/t/2j6bhda
Ideally, linepattern in… dash [space value], dot [space value], dash, [space value] etc etc… out. I can analyse thr strings after that.
Any chance you can share the code for accessing the line styles, patterns, and the like? Think I can pull the pattern readily, but building the base to get to where you are will take a bit.
This might not be directly workable in your context, but it will pull most of the information you want from every line style in the project, allowing for comparison of completed patterns using the pattern string value(s).
import clr #import the common language runtime (CLR) so we can access .net libraries in the Python environment
clr.AddReference("RevitNodes") #add the Revit nodes library to the CLR
import Revit #import the Revit library to the python environment
clr.ImportExtensions(Revit.Elements) #add the Revit.Elemetns extention to the Dynamo environment
clr.AddReference("RevitServices") #add the Revit Services library to the CLR
import RevitServices #import the Revit services namespace to the python environment
from RevitServices.Persistence import DocumentManager #import the document manager to the python environment
clr.AddReference("RevitAPI") #add the Revit API to the CLR
import Autodesk #importing the autodesk namepace to the python environment
from Autodesk.Revit.DB import * #importing all of the Revit DB namespace to the python environment so we can be sure we catch what we need in development
doc = DocumentManager.Instance.CurrentDBDocument #the current document
lineStyles = list(doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines).SubCategories) #line styles are a sub-category of the lines category, so we don't use a filtered element collector to gather them
results = [] #an empty list to hold the results
for lineStyle in lineStyles: #for every linestyle in the list of linestyles
name = lineStyle.Name #get the name
color = lineStyle.LineColor #get the line color
red = color.Red #get the Red value
green = color.Green #get the green value
blue = color.Blue #get the blue value
patternId = lineStyle.GetLinePatternId(GraphicsStyleType.Projection) #get the pattern id
pattern = doc.GetElement(patternId) #get the pattern element
if pattern != None: #if the pattern element is valid, perform the offset items below
linePattern = LinePatternElement.GetLinePattern(doc, patternId) #get the line pattern from the document using the pattern id
segments = linePattern.GetSegments() #get the segments from the line pattern
types = [s.Type for s in segments] #get the segment type from each segment
segmentTypes = ["Dash","Space","Dot"] #convert the segment types into a more understandable string
types = [segmentTypes[i] for i in types] #get the understandable string type for each segment
lengths = [s.Length for s in segments] #get the length of each segment - you might want to round off here at some value
segmentPatternString = "\r".join([types[i] + " - "+ str(lengths[i]) for i in range(len(types))]) #build a human readible string for the segment types
else: #if the pattern was not valid, set the values to something human readible and informative
segmentPattern = None #a null value for the segment pattern element
segmentPatternString = "Solid" #a string of 'solid' for the segment pattern string
segments = [] #a empty list for the segments list
data = {"Line Style": lineStyle, "Line Style ide": lineStyle.Id, "Line Style Name": name, "Color": color, "Color Red Value": red, "Color Green Value": green, "Color Blue Value": blue, "Line Pattern Element": pattern, "Line Pattern Id": patternId, "Line Pattern String": segmentPatternString, "Line Segments": segments} #build the dictionary of line information
results.append(data) #append the line information dictionary to the resutls list
OUT = results #return the results list to the Dynamo environment
An update here for anyone interested.
I used @jacob.small 's code to only pull the Line Pattern string into what i was working on.
and then following that i converted it to ironPython2 incase i needed to integrate it into anything in that engine.
the two versions are below, i leave for anyone in future as a return gesture for Jacob’s Help
Code - IronPython2
import clr
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
doc = DocumentManager.Instance.CurrentDBDocument
lineStyles = list(doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines).SubCategories)
results = []
for lineStyle in lineStyles:
patternId = lineStyle.GetLinePatternId(GraphicsStyleType.Projection)
pattern = doc.GetElement(patternId)
if pattern is not None:
linePattern = LinePatternElement.GetLinePattern(doc, patternId)
segments = linePattern.GetSegments()
types = [int(s.Type) for s in segments] # Convert enumeration types to integers
segmentTypes = ["Dash", "Space", "Dot"]
types = [segmentTypes[i] for i in types]
lengths = [s.Length for s in segments]
segmentPatternString = "\r".join([types[i] + " - " + str(lengths[i]) for i in range(len(types))])
else:
segmentPatternString = "Solid"
data = {"Pattern String": segmentPatternString}
results.append(data)
OUT = results
Code - cPython3
import clr
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
doc = DocumentManager.Instance.CurrentDBDocument
lineStyles = list(doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines).SubCategories)
results = []
for lineStyle in lineStyles:
patternId = lineStyle.GetLinePatternId(GraphicsStyleType.Projection)
pattern = doc.GetElement(patternId)
if pattern is not None:
linePattern = LinePatternElement.GetLinePattern(doc, patternId)
segments = linePattern.GetSegments()
types = [s.Type for s in segments]
segmentTypes = ["Dash", "Space", "Dot"]
types = [segmentTypes[i] for i in types]
lengths = [s.Length for s in segments]
segmentPatternString = "\r".join([types[i] + " - " + str(lengths[i]) for i in range(len(types))])
else:
segmentPatternString = "Solid"
data = {"Pattern String": segmentPatternString}
results.append(data)
OUT = results
Shout out to say THANK-YOU!
This post saved my sanity today!
Spent hours trolling the forums and api docs unable to get this working properly
Your sample code here gave me the piece of the puzzle I was missing!
So happy right now, I just had to post and say thanks for your efforts and for sharing!