""" Assistente CAD/BIM - Geracao de Scripts AutoCAD e Dynamo/Revit Para posicionamento de sistemas de prevencao de incendio - NT-01/2025 """ import math import json from datetime import datetime from typing import Dict, List, Tuple class CADAssistant: """ Gera scripts .scr (AutoCAD) e Python (Dynamo/Revit API) para posicionamento automatico de sistemas de incendio. """ BLOCOS = { "extintor": "EXTINTOR_PSCIP", "hidrante": "HIDRANTE_PSCIP", "saida_emerg": "SAIDA_EMERG_PSCIP", "detector": "DETECTOR_FUMACA_PSCIP", "acionador": "ACIONADOR_MANUAL_PSCIP", "ilum_emerg": "BLOCO_AUTONOMO_PSCIP", } LAYERS = { "extintores": "INCENDIO-EXTINTORES", "hidrantes": "INCENDIO-HIDRANTES", "sinalizacao": "INCENDIO-SINALIZACAO", "deteccao": "INCENDIO-DETECCAO", "iluminacao": "INCENDIO-ILUMINACAO", } CORES = {"extintores":"1","hidrantes":"5","sinalizacao":"3","deteccao":"2","iluminacao":"6"} def calcular_posicoes_extintores(self, larg, comp, qtd): posicoes, dist_max = [], 14.0 if qtd <= 0: return posicoes cols = max(1, math.ceil(larg / dist_max)) rows = max(1, math.ceil(comp / dist_max)) while cols * rows < qtd: if larg / (cols+1) >= comp / (rows+1): cols += 1 else: rows += 1 px, py = larg / cols, comp / rows for row in range(rows): for col in range(cols): posicoes.append((round(px*(col+0.5),2), round(py*(row+0.5),2))) if len(posicoes) >= qtd: break if len(posicoes) >= qtd: break return posicoes[:qtd] def calcular_posicoes_saidas(self, larg, comp, num_saidas): pos = [] if num_saidas >= 1: pos.append((larg/2, 0.0, "SUL")) if num_saidas >= 2: pos.append((larg/2, comp, "NORTE")) if num_saidas >= 3: pos.append((0.0, comp/2, "OESTE")) if num_saidas >= 4: pos.append((larg, comp/2, "LESTE")) return pos[:num_saidas] def calcular_posicoes_detectores(self, larg, comp): posicoes, passo = [], 8.0 cols, rows = max(1, math.ceil(larg/passo)), max(1, math.ceil(comp/passo)) px, py = larg/cols, comp/rows return [(round(px*(c+0.5),2), round(py*(r+0.5),2)) for r in range(rows) for c in range(cols)] def gerar_script_autocad(self, dados): larg = dados.get("largura_m", 30.0) comp = dados.get("comprimento_m", 30.0) qtd_ext = dados.get("qtd_extintores", 4) num_saidas = dados.get("num_saidas_emergencia", 2) tem_det = dados.get("tem_deteccao", False) escala = dados.get("escala", 100) f = escala linhas = [ "; ===================================================", "; Script AutoCAD - Agente CBMGO - NT-01/2025", f"; Gerado em: {datetime.now().strftime('%d/%m/%Y %H:%M')}", "; ===================================================", "", "; Criando layers PSCIP...", ] for nome, layer in self.LAYERS.items(): linhas.append(f"-LAYER N {layer} C {self.CORES[nome]} {layer} L CONTINUOUS {layer} ") linhas += ["", f"; --- EXTINTORES ({qtd_ext} un.) - Distancia max. 15m ---", f"-LAYER SET {self.LAYERS['extintores']} "] for i, (x, y) in enumerate(self.calcular_posicoes_extintores(larg, comp, qtd_ext), 1): xc, yc = round(x*f), round(y*f) linhas.append(f"INSERT {self.BLOCOS['extintor']} {xc},{yc} 1 1 0 ") linhas += ["", f"; --- SAIDAS DE EMERGENCIA ({num_saidas} un.) ---", f"-LAYER SET {self.LAYERS['sinalizacao']} "] for i, (x, y, d) in enumerate(self.calcular_posicoes_saidas(larg, comp, num_saidas), 1): xc, yc = round(x*f), round(y*f) ang = {"SUL":90,"NORTE":270,"LESTE":180,"OESTE":0}.get(d, 0) linhas.append(f"INSERT {self.BLOCOS['saida_emerg']} {xc},{yc} 1 1 {ang} ") if tem_det: linhas += ["", "; --- DETECTORES DE FUMACA ---", f"-LAYER SET {self.LAYERS['deteccao']} "] for x, y in self.calcular_posicoes_detectores(larg, comp): linhas.append(f"INSERT {self.BLOCOS['detector']} {round(x*f)},{round(y*f)} 1 1 0 ") linhas += ["", "QSAVE ", "", "; FIM DO SCRIPT"] return "\n".join(linhas) def gerar_relatorio_posicionamento(self, dados): larg = dados.get("largura_m", 30.0) comp = dados.get("comprimento_m", 30.0) qtd_ext = dados.get("qtd_extintores", 4) num_saidas = dados.get("num_saidas_emergencia", 2) pos_ext = self.calcular_posicoes_extintores(larg, comp, qtd_ext) pos_saidas = self.calcular_posicoes_saidas(larg, comp, num_saidas) linhas = [ "=" * 50, "RELATORIO DE POSICIONAMENTO - SISTEMAS PSCIP", f"Data: {datetime.now().strftime('%d/%m/%Y %H:%M')}", f"Planta: {larg:.1f}m x {comp:.1f}m = {larg*comp:.0f}m2", "=" * 50, f"\nEXTINTORES ({qtd_ext} unidades):", ] for i, (x, y) in enumerate(pos_ext, 1): linhas.append(f" EXT-{i:02d}: X={x:.2f}m, Y={y:.2f}m") linhas.append(f"\nSAIDAS DE EMERGENCIA ({num_saidas} unidades):") for i, (x, y, d) in enumerate(pos_saidas, 1): linhas.append(f" SAIDA-{i:02d}: X={x:.2f}m, Y={y:.2f}m (parede {d})") linhas += ["", "Notas:", "- Posicoes calculadas pelo Agente CBMGO", "- Distancia maxima ao extintor: 14m (NT-01/2025 Anexo B)", "- Validar com projeto arquitetonico", "=" * 50] return "\n".join(linhas) _cad_instance = None def get_cad_assistant(): global _cad_instance if _cad_instance is None: _cad_instance = CADAssistant() return _cad_instance if __name__ == "__main__": cad = CADAssistant() dados = {"largura_m": 25.0, "comprimento_m": 40.0, "qtd_extintores": 5, "num_saidas_emergencia": 3, "tem_deteccao": True, "escala": 100} print(cad.gerar_relatorio_posicionamento(dados))