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

Powerpoint countdown and current time in slides VBA

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