File size: 6,167 Bytes
7dafa38 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | """
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))
|