Tool to create generic annotations in drafting views of type based on name

Version 2.05 Working

  • Gets all gen anos in project
  • gets drafting view corresponding to the family name of the gen anno
  • gets the types
  • Creates the types in the drafting view to use as a reference for schedule manipulaiton
Adding types after run:
Family NEW added- Re-run:


Need to resolve SORT... NEW should come after numbers!



Update includes moving exsinting (sorted) annotations  to their exact spot in the list:
##https://gist.github.com/gtalarico/e6be055472dfcb6f597e3dcd20d11f37 #import System.Collections.Generic #from System.Collections.Generic import List ##clr.AddReference('RevitAPIUI') ##from Autodesk.Revit.UI import * import clr clr.AddReference('System') clr.AddReference('RevitAPI') ##clr.AddReference('RevitNodes') ##clr.ImportExtensions(Revit.Elements) ##clr.ImportExtensions(Revit.GeometryConversion) ###Creates a Drafting View### from Autodesk.Revit.DB import Transaction, Element, ElementTransformUtils ##https://forum.dynamobim.com/t/collecting-all-elements-of-family-types-in-active-view/19838/2 from Autodesk.Revit.DB import FilteredElementCollector, BuiltInCategory, BuiltInParameter, ParameterValueProvider, ElementId, ElementParameterFilter, FilterNumericEquals, FilterElementIdRule, ElementTransformUtils # Drafting Views from Autodesk.Revit.DB import ViewFamilyType, ViewDrafting, Element from Autodesk.Revit.DB import ViewFamily clr.AddReference('RevitServices') ##May need to re-add for Document Manager import sys import System ##filterAnnot = System.Predicate from System.Collections.Generic import List ##Not same as type() = List import math ##For truncate to integer-RA import re ##Regular expressions for 'natural' sort from itertools import groupby #from Autodesk.Revit.DB import * from Autodesk.Revit.DB import FamilySymbol, FamilyInstance, XYZ, AnnotationSymbol #import Revit #from Revit import * #from Autodesk.DesignScript.Geometry import * ##Point(X,Y,Z) ##cannot use for PY nodes outside Dynamo import RevitServices from RevitServices.Persistence import DocumentManager from RevitServices.Transactions import TransactionManager doc = DocumentManager.Instance.CurrentDBDocument uidoc=DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument ##uidoc = __revit__.ActiveUIDocument ##doc = __revit__.ActiveUIDocument.Document ##################################################################################### ##Create a Drafting View# def get_drafting_type_id(DraftingType): ##Selects First available ViewType that Matches Drafting Type.## ##https://mgfx.co.za/blog/building-architectural-design/revit-view-type-creation-using-excel-with-dynamo-and-python/ viewfamily_types = FilteredElementCollector(doc).OfClass(ViewFamilyType) for i in viewfamily_types: if i.ViewFamily == ViewFamily.Drafting: ##*.ViewFamily Backwards 'parent' ref I've been looking for!##<<<<<<<<<<<<<<<<<<<<<<<<<<HERE return i.Id def GetDraftingViews(): ##https://forums.autodesk.com/t5/revit-api-forum/view3d-collector/td-p/5277451 DraftingViewsList = FilteredElementCollector(doc).OfClass(ViewDrafting).ToElements() ##DraftingViewTemplates = [v.Id for v in DraftingViewsList if v.IsTemplate == True] DraftingViewsList = [v for v in DraftingViewsList if v.IsTemplate == False] return [DraftingViewsList] def GetDraftingViewTemplates(): ##https://forums.autodesk.com/t5/revit-api-forum/view3d-collector/td-p/5277451 DraftingViewsList = FilteredElementCollector(doc).OfClass(ViewDrafting).ToElements() DraftingViewTemplates = [v for v in DraftingViewsList if v.IsTemplate == True] ##DraftingViewsList = [v.Id for v in DraftingViewsList if v.IsTemplate == False] return [DraftingViewTemplates] def GetDraftingViewByBame(strName=""): ##Check if drafting view existds = if not, create it and assign view name if not strName == "": ##If string name is set look for the drafting view DraftingView = FilteredElementCollector(doc).OfClass(ViewDrafting).ToElements() ##Get all drafting views DraftingView = [v for v in DraftingView if v.Name == strName] ##Return Drafting view for each Drafting view eq. Name if DraftingView: DraftingView =DraftingView[0] ##Return single item not list<<<<<<<<<<<<<<< if not DraftingView: ##If no drafting view found drafting_type_id = get_drafting_type_id() ##Get TYPE ID DraftingView = ViewDrafting.Create(doc, drafting_type_id) ##Create View ##After creating view- if not strName=="" : ##IF string is not null set the name of the new view DraftingView.Name = strName return DraftingView ##Return single value def GetGenericAnnotationTypes(): ##BAsed in part ##https://forum.dynamobim.com/t/how-can-i-collect-all-family-types-that-are-considered-annotation-symbols-in-revit/37480/10 ##https://forum.dynamobim.com/t/get-all-generic-annotations-in-a-view/80514/2 filterAnnot = System.Predicate[System.Object](lambda x : x.Family.FamilyCategory.Name == "Generic Annotations") symbAnnot = List[Element](FilteredElementCollector(doc).OfClass(FamilySymbol).ToElements()).FindAll(filterAnnot) return symbAnnot def Lambda_Natural_sort(l): ##Slow 50x but effective ##ORiginal function doesn't work with Objects. ConvertText = lambda ConvertText: int(ConvertText) if ConvertText.isdigit() else ConvertText.lower() alphanum_key = lambda key: [ ConvertText(c) for c in re.split('([0-9]+)', key) ] return sorted(l, key = alphanum_key) def Lambda_GenAnno_Sort_w_fam_name(lstObj): ConvertText = lambda ConvertText: int(ConvertText) if ConvertText.isdigit() else ConvertText.lower() alphanum_key = lambda i: [ ConvertText(c) for c in re.split('(\d+)', i) ] ##GenAnnoTypeName##https://forum.dynamobim.com/t/python-script-to-get-type-name-from-an-element/63306/2 GAstrName = lambda j: [ alphanum_key(c) for c in (j.Family.Name + GetGAName(j))] return sorted(lstObj, key = GAstrName) def GetGAName(GA): ##GenericAnnotationFamilyType".Name" return doc.GetElement(GA.Id).get_Parameter(BuiltInParameter.ALL_MODEL_TYPE_NAME).AsString() def GroupGenAnnos(lstElems): ##test to Group By Key https://forum.dynamobim.com/t/group-by-key-in-python/39145/2 grp=[] ukey=[] ##Presorted by genannolistfort_w_family_name for k, g in groupby(lstElems, lambda x:x.Family.Name): grp.append(list(g)) ukey.append(k) #Assign your output to the OUT variable. return grp def GetAnnosInView(viewView): ##https://forum.dynamobim.com/t/get-all-generic-annotations-in-a-view/80514/2 symbAnnot = [x for x in FilteredElementCollector(doc,viewDraft.Id).OfCategory(BuiltInCategory.OST_GenericAnnotation).WhereElementIsNotElementType()] def ListConv(x): ## Returns list if single item if type(x) is list : return x ##Leave as list if laready list else: try: z=iter(x) ##if element is iterable- e.g. Generic.List - it can be converted to regular list return [x for x in x] ##Convert to list if single item except: return[x] ##Convert single element to list def ListOfList1InList2(list1,list2): list1Out=[] for x in list1: ##For each element in 1st list (Check against elements in 2nd list) found = False ##Reset to not found for next element for y in list2: if x==y: ##If found, found =True ##Set founc to TRUE break ##Can stop looking in second list this round list1Out.append(found) ##Append result return list1Out def List1InList2(list1,list2): ##If any of list 1 in list 2 return TRUE else False for x in list1: ##For each element in 1st list (Check against elements in 2nd list) for y in list2: if x==y: ##If found, return True ##Return True return False ##Return false def GenAnnosInView(viewView): ##GET ANNOTATIONSIN VIEW ##https://forum.dynamobim.com/t/get-all-generic-annotations-in-a-view/80514/2 FEC=FilteredElementCollector(doc,viewView).OfCategory(BuiltInCategory.OST_GenericAnnotation).WhereElementIsNotElementType() return FEC def PlaceGenAnnoArray(GAFamTypes, viewView): #Single family of generic annotaiton types to place ##cast CONSTANTS xSpace = 8.5/12.0 ##Horizontal spacing 8-1/2" Wide ySpace = 3.0/8.0/12.0 ##Vertical spacing 3/16" tall (Text is 3/32" high) yLimit = 10.0/12.0 ##Limit of Y column height 10" (8-1/2"x11" Guide to format into sheet size references) yCount = int(math.floor(yLimit/ySpace)) ##Number of rows in a column for reset y value column = 0 ##Column location count = 1 ##Count position in array of all family types AnnoEXST=[] ##Existing annotaitons in view AnnoNEWW=[] ##New annotaitons creted ##get AllGenAnnosInView - if any... AnnosInView =[] #AnnosInView = FilteredElementCollector(doc,viewView.Id).OfCategory(BuiltInCategory.OST_GenericAnnotation).WhereElementIsNotElementType().ToElements ##https://forum.dynamobim.com/t/get-all-generic-annotations-in-a-view/80514/13 SeanP filterAnnot = System.Predicate[System.Object](lambda x : doc.GetElement(x.GetTypeId()).Family.FamilyCategory.Name == "Generic Annotations") AnnosInView = List[Element](FilteredElementCollector(doc, viewView.Id).OfClass(FamilyInstance).ToElements()).FindAll(filterAnnot) AnnosInView = UnwrapElement(AnnosInView) ##Unwrap to get to get to Revit Type Elements for GAFamType in GAFamTypes : #from 0,0 run down then over for simplicity. These typically will NOT end up on printed sheets #But are head to use to schedule. Any object in any view will schedule regardless of on/off sheet palcement. column = math.floor( yLimit / count * ySpace) ##Get column based on placed elements and Y limit sizes x= column * xSpace ##Get x location y= -ySpace * (count-1 - (column * yCount)) ##Offset Y by column displacemnet objPoint = XYZ(x, y, 0) ##GET POINT #return List1InList2([GetGAName(GAFamType)], [x.Name for x in AnnosInView]) ##DEBUG ##if List1InList2([GetGAName(GAFamType)], [x.Name for x in AnnosInView]): ##if GAFamType Name in list of names in view #return 3 GAiv = None if AnnosInView : ##If ther eare annos in the view for GAivx in AnnosInView: ##For each Gen Anno in view Found = False ##Reset Found for y in GAFamTypes: if GetGAName(GAFamType)==GAivx.Name: ##If found, Found = True ##Return True GAiv=GAivx break ##Break with Found set if Found: ##If found (after for y) break ##Exit out of outer loop with GAiv (Gen Anno In View) set else: GAiv=None if GAiv: AnnoEXST.append(GAFamType) ##Add it to the existing list for GAinVIew in AnnosInView: ##Cycle through to set it if GAinVIew.Name==GetGAName(GAFamType): ##GenericAnnotaitonFamilyTypeCompare GAiv.Location.Point = objPoint ##Sets Fixed Position for element in list. break else: ##Not List1InList2 GAinVIew = doc.Create.NewFamilyInstance(objPoint, GAFamType, viewView) ##Create NEW annotaiton in its loaiton AnnoNEWW.append(GAinVIew) ##Append it to the new list as a double check count +=1 ##increment counter return [AnnoNEWW,AnnoEXST] ##Return the New and Existing. Re-running should only return existing. #### ### ####################################################################################### def Main(): ###Entry point to procedures t = Transaction (doc, 'Create Drafting View') t.Start() outNEWW=[] outEXST=[] GenAnnoTypes = [] GenAnnoTypes = GetGenericAnnotationTypes() ##LIST of FAMILY TYPE of GenAnnoTypes GenAnnoTypes = Lambda_GenAnno_Sort_w_fam_name(GenAnnoTypes) ##Sort in natural order- numbers as numbers text as text GenAnnoTypes = GroupGenAnnos(GenAnnoTypes) ##Create nested list by Family and Types for GAFamType in GenAnnoTypes: ##2D list [1.GenAnnoFamilies][2.GenAnnoTypes] DraftViewName = "" DraftViewName = GAFamType[0].Family.Name ##FAmily name used for drafting view name viewDraft = GetDraftingViewByBame(DraftViewName) ##Get or create drafting view by name OUT = PlaceGenAnnoArray (GAFamType, viewDraft) ##Place or update gfams per view ##Separate lists into NEW and EXISTING## #outNEWW.append(OUT[0]) ##New is index 0 #outEXST.append(OUT[1]) ##Existing is index 1 #OUT=[outNEWW,outEXST] ##Set final OUT to [NEW,Existing] Lists t.Commit() return OUT ############################################################################################ ############################################################################################ OUT=Main () ##Entry point to run all scripts ############################################################################################ ############################################################################################

Comments

Popular posts from this blog

Revit area plans adding new types and references (Gross and rentable)

Powerpoint countdown and current time in slides VBA

Revit Python in Visual Studio Revit Stubs 2022 for Python Revit Intellisense