Paper space limits.py

# purpose and IO: IN[0]=sheet Ids (list/int/ElementId or None), IN[1]=tolerance_ft (float, optional), OUT=per-sheet dict with offending element Ids # Reports any paper-space elements whose bounding box (in the sheet view) lies outside the largest title block's bbox. # Ignores title blocks and CAD Import/Link instances named like "0,0,0" / "0,0-Origin". import clr clr.AddReference('RevitAPI') clr.AddReference('RevitServices') from Autodesk.Revit.DB import ( FilteredElementCollector, ViewSheet, FamilyInstance, BuiltInCategory, ImportInstance, ElementId ) from RevitServices.Persistence import DocumentManager doc = DocumentManager.Instance.CurrentDBDocument input_ids = IN[0] if len(IN)>0 else None tol = float(IN[1]) if len(IN)>1 and IN[1] not in (None, "") else 0.0 # feet def _to_elemid(e): if isinstance(e, ElementId): return e try: return ElementId(int(e)) except: return None target_sheet_ids = None if input_ids: ids = [] seq = input_ids if isinstance(input_ids, (list, tuple)) else [input_ids] for x in seq: eid = _to_elemid(x) if eid: ids.append(eid) if ids: target_sheet_ids = set(ids) def tblocks_on_sheet(sheet): return list( FilteredElementCollector(doc, sheet.Id) .OfCategory(BuiltInCategory.OST_TitleBlocks) .OfClass(FamilyInstance) .WhereElementIsNotElementType() ) def largest_tb_bbox(sheet): ranked = [] for tb in tblocks_on_sheet(sheet): bb = tb.get_BoundingBox(sheet) if bb: area = abs((bb.Max.X - bb.Min.X) * (bb.Max.Y - bb.Min.Y)) ranked.append((area, bb)) if not ranked: return None ranked.sort(key=lambda x:x[0], reverse=True) return ranked[0][1] def is_origin_cad_import(elem): if not isinstance(elem, ImportInstance): return False name = "" try: name = elem.Name or "" except: name = "" if not name: try: sym = doc.GetElement(elem.GetTypeId()) name = sym.Name if sym else "" except: name = "" s = name.lower().replace(" ", "") return ("0,0,0" in s) or ("0,0-origin" in s) or ("00,0-origin" in s) def paper_elems(sheet): return list(FilteredElementCollector(doc, sheet.Id).WhereElementIsNotElementType()) def inside(bb_elem, bb_ref, tol=0.0): # bb_elem is fully inside bb_ref with tolerance (in feet) if not bb_elem or not bb_ref: return True return (bb_elem.Min.X >= bb_ref.Min.X - tol and bb_elem.Min.Y >= bb_ref.Min.Y - tol and bb_elem.Max.X <= bb_ref.Max.X + tol and bb_elem.Max.Y <= bb_ref.Max.Y + tol) results = [] sheets = list(FilteredElementCollector(doc).OfClass(ViewSheet)) if target_sheet_ids: sheets = [s for s in sheets if s.Id in target_sheet_ids] for s in sheets: tb_bb = largest_tb_bbox(s) if not tb_bb: results.append({"sheet": s.SheetNumber, "name": s.Name, "status": "no title block", "offenders": []}) continue offenders = [] for e in paper_elems(s): # skip title blocks and "origin" CAD imports if e.Category and e.Category.Id.IntegerValue == int(BuiltInCategory.OST_TitleBlocks): continue if is_origin_cad_import(e): continue bb = e.get_BoundingBox(s) if not bb: continue if not inside(bb, tb_bb, tol): cat = e.Category.Name if e.Category else "NoCategory" offenders.append({"Id": e.Id.IntegerValue, "Category": cat}) results.append({ "sheet": s.SheetNumber, "name": s.Name, "status": "audited", "tolerance_ft": tol, "offender_count": len(offenders), "offenders": offenders }) OUT = results

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)

Revit Dynamo View Form Python Output Form Resizable, Aggressively on top