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

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

Revit CSV file manager for families and re-exporting to a CSV file