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))