File size: 5,338 Bytes
b5b80df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
150
151
152
153
154
155
156
157
158
import gradio as gr
import pandas as pd
import geopandas as gpd
import openpyxl

# ---------------------------------------
# Função para formatar visualização
# ---------------------------------------
def formatar_float_visualizacao(df, casas=4):
    df_visual = df.copy()
    float_cols = df_visual.select_dtypes(include=['float']).columns
    df_visual[float_cols] = df_visual[float_cols].round(casas)
    return df_visual

# ---------------------------------------
# Carregar shapefile dos eixos
# ---------------------------------------
gdf_eixos = gpd.read_file("EixosLogradouros.shp", engine="fiona")
gdf_eixos_proj = gdf_eixos.to_crs("EPSG:4326")

# ---------------------------------------
# Funções auxiliares
# ---------------------------------------
def carregar_abas(arquivo_excel):
    if arquivo_excel is None:
        return gr.update(choices=[]), None
    xls = pd.ExcelFile(arquivo_excel.name)
    abas = xls.sheet_names
    return gr.update(choices=abas, value=abas[0]), abas[0]


def listar_colunas(arquivo_excel, aba_selecionada):
    if arquivo_excel is None or aba_selecionada is None:
        return gr.update(choices=[]), gr.update(choices=[])

    df = pd.read_excel(arquivo_excel.name, sheet_name=aba_selecionada)
    colunas = df.columns.tolist()
    return gr.update(choices=colunas), gr.update(choices=colunas)


def exibir_tabela(arquivo_excel, aba_selecionada, nome_coluna_num):
    if arquivo_excel is None or aba_selecionada is None:
        return None, ""

    df = pd.read_excel(arquivo_excel.name, sheet_name=aba_selecionada)

    if nome_coluna_num in df.columns:
        df[nome_coluna_num] = pd.to_numeric(df[nome_coluna_num], errors='coerce').fillna(0).astype(int)

    return formatar_float_visualizacao(df), f"O DataFrame possui {df.shape[0]} linhas e {df.shape[1]} colunas."


def obter_cdlog_por_nmidelog(nome_logradouro):
    if not nome_logradouro:
        return None
    cdlog_unicos = gdf_eixos_proj[gdf_eixos_proj["NMIDEABR"] == nome_logradouro]["CDLOG"].unique()
    return int(cdlog_unicos[0]) if len(cdlog_unicos) > 0 else None


# ---------------------------------------
# Interpolação
# ---------------------------------------
def interpolar_enderecos(df, col_cdlog, col_num):

    df[col_num] = pd.to_numeric(df[col_num], errors='coerce').fillna(0).astype(int)
    resultados = []
    falhas = []

    for _, row in df.iterrows():

        cdlog = row[col_cdlog]
        numero = row[col_num]

        segmentos = gdf_eixos_proj[gdf_eixos_proj['CDLOG'] == cdlog]

        if segmentos.empty:
            resultados.append((None, None))
            falhas.append({"cdlog": cdlog, "numero": numero, "motivo": "CDLOG não encontrado"})
            continue

        if numero % 2 == 0:
            cond = (segmentos['NRPARINI'] <= numero) & (segmentos['NRPARFIN'] >= numero)
        else:
            cond = (segmentos['NRIMPINI'] <= numero) & (segmentos['NRIMPFIN'] >= numero)

        segmentos_validos = segmentos[cond]

        if segmentos_validos.empty:
            resultados.append((None, None))
            falhas.append({"cdlog": cdlog, "numero": numero, "motivo": "Numeração fora do intervalo"})
            continue

        linha = segmentos_validos.iloc[0]
        geom = linha.geometry

        ini = linha['NRPARINI'] if numero % 2 == 0 else linha['NRIMPINI']
        fim = linha['NRPARFIN'] if numero % 2 == 0 else linha['NRIMPFIN']

        frac = (numero - ini) / (fim - ini)
        frac = max(0, min(1, frac))

        ponto = geom.interpolate(geom.length * frac)

        resultados.append((ponto.x, ponto.y))

    df["lon"] = [x for x, y in resultados]
    df["lat"] = [y for x, y in resultados]

    output_path = "dados_interpolados.xlsx"
    df.to_excel(output_path, index=False)

    return formatar_float_visualizacao(df), output_path, pd.DataFrame(falhas)


# ---------------------------------------
# Interface
# ---------------------------------------
with gr.Blocks() as app:

    gr.Markdown("## DAI - Geolocalização (Sem Mapa)")

    arquivo = gr.File(label="Arquivo Excel", file_types=[".xlsx"])

    dropdown_abas = gr.Dropdown(label="Aba")
    linhas_colunas_output = gr.Textbox(label="Linhas e Colunas", interactive=False)

    dropdown_cdlog = gr.Dropdown(label="Coluna CDLOG")
    dropdown_num = gr.Dropdown(label="Coluna Número")

    tabela_output = gr.Dataframe(label="Prévia", interactive=True)

    btn_confirmar = gr.Button("Confirmar Dados")
    btn_interpolar = gr.Button("Obter Coordenadas")

    tabela_interpolada = gr.Dataframe(label="Com Coordenadas")
    arquivo_excel_output = gr.File(label="Arquivo Gerado")
    falhas_output = gr.Dataframe(label="Falhas")

    # Eventos
    arquivo.change(fn=carregar_abas, inputs=arquivo, outputs=[dropdown_abas, dropdown_abas])

    dropdown_abas.change(
        fn=exibir_tabela,
        inputs=[arquivo, dropdown_abas, dropdown_num],
        outputs=[tabela_output, linhas_colunas_output]
    ).then(
        fn=listar_colunas,
        inputs=[arquivo, dropdown_abas],
        outputs=[dropdown_cdlog, dropdown_num]
    )

    btn_interpolar.click(
        fn=interpolar_enderecos,
        inputs=[tabela_output, dropdown_cdlog, dropdown_num],
        outputs=[tabela_interpolada, arquivo_excel_output, falhas_output]
    )

app.launch(server_name="0.0.0.0", server_port=7860)