PC SOFT
ONLINE  REPOSITORY
FOR  WINDEVWEBDEV AND  WINDEV MOBILE

Classe Oop ArcGis Mapa Georeferenciamento
Published by Boller
in the category Tools
New features



Description
# ?? EXEMPLOS DE USO - ArcGIS_WX v1.00

## ?? **COLEÇÃO COMPLETA DE EXEMPLOS PRÁTICOS**

---

## ?? **ÍNDICE DE EXEMPLOS**

### **?? BÁSICOS**
1. [Hello World - Primeiro Mapa](#hello-world---primeiro-mapa)
2. [Adicionando Marcadores Simples](#adicionando-marcadores-simples)
3. [Navegação Básica](#navegação-básica)
4. [Alternando Basemaps](#alternando-basemaps)

### **? INTERMEDIÁRIOS**
5. [Sistema de Categorias](#sistema-de-categorias)
6. [Busca e Filtros](#busca-e-filtros)
7. [Cálculo de Distâncias](#cálculo-de-distâncias)
8. [Análises Geoespaciais](#análises-geoespaciais)

### **?? AVANÇADOS**
9. [Integração com Banco de Dados](#integração-com-banco-de-dados)
10. [Monitoramento em Tempo Real](#monitoramento-em-tempo-real)
11. [Feature Layers Corporativos](#feature-layers-corporativos)
12. [Sistema de Callbacks](#sistema-de-callbacks)

### **?? EMPRESARIAIS**
13. [Dashboard de Vendas](#dashboard-de-vendas)
14. [Gestão de Frota](#gestão-de-frota)
15. [Análise de Mercado](#análise-de-mercado)
16. [Planejamento Urbano](#planejamento-urbano)

### **? PERFORMANCE**
17. [Otimização para Muitos Marcadores](#otimização-para-muitos-marcadores)
18. [Cache Inteligente](#cache-inteligente)
19. [Processamento em Lotes](#processamento-em-lotes)

### **?? TROUBLESHOOTING**
20. [Diagnóstico e Debug](#diagnóstico-e-debug)
21. [Recuperação de Erros](#recuperação-de-erros)
22. [Fallback Automático](#fallback-automático)

---

## ?? **EXEMPLOS BÁSICOS**

### **1. Hello World - Primeiro Mapa**

```wlanguage
// ============================================================================
// EXEMPLO 1: Hello World - Seu Primeiro Mapa ArcGIS
// Complexidade: ? Básico
// Tempo estimado: 5 minutos
// ============================================================================

PROCEDIMENTO HelloWorldArcGIS()

// Declarar variável da classe
gArcGIS é um ArcGIS_WX_v100

// Sua API Key do ArcGIS (obtenha em developers.arcgis.com)
sAPIKey é uma cadeia = "SUA_ARCGIS_API_KEY"

TRY
// 1. CRIAR INSTÂNCIA
// HTMLControl1 deve existir na sua janela
gArcGIS = new ArcGIS_WX_v100(sAPIKey, HTMLControl1, ArcGIS_WX_v100.CONTROLE_HTML)

// 2. INICIALIZAR MAPA
// Coordenadas de São Paulo, zoom 12
SE gArcGIS.InicializarMapa(-23.5505, -46.6333, 12) ENTÃO
Info("?? Seu primeiro mapa ArcGIS está funcionando!")
SENÃO
Error("? Erro ao inicializar o mapa")
FIM

EXCEPTION
Error("?? Erro crítico: " + ExceptionInfo())
FIM

// ============================================================================
// DICAS PARA INICIANTES:
//
// 1. Certifique-se de ter um HTMLControl na sua janela
// 2. Obtenha uma API Key gratuita em developers.arcgis.com
// 3. Verifique sua conexão com a internet
// 4. O mapa pode levar alguns segundos para carregar
// ============================================================================
```

### **2. Adicionando Marcadores Simples**

```wlanguage
// ============================================================================
// EXEMPLO 2: Adicionando Seus Primeiros Marcadores
// Complexidade: ? Básico
// Tempo estimado: 10 minutos
// ============================================================================

PROCEDIMENTO AdicionarMarcadoresSimples()

gArcGIS é um ArcGIS_WX_v100
sAPIKey é uma cadeia = "SUA_ARCGIS_API_KEY"

TRY
// Inicializar mapa
gArcGIS = new ArcGIS_WX_v100(sAPIKey, HTMLControl1, ArcGIS_WX_v100.CONTROLE_HTML)
gArcGIS.InicializarMapa(-23.5505, -46.6333, 12)

// Aguardar carregamento
ThreadPause(3000)

// MARCADOR 1: Centro de São Paulo
nID1 é um inteiro = gArcGIS.AdicionarMarcador(
-23.5505, -46.6333, // Latitude, Longitude
"Centro de São Paulo", // Título
"Marco zero da cidade", // Descrição
ArcGIS_WX_v100.SIMBOLO_CIRCLE, // Símbolo
"#FF0000" // Cor vermelha
)

// MARCADOR 2: Avenida Paulista
nID2 é um inteiro = gArcGIS.AdicionarMarcador(
-23.5614, -46.6558,
"Avenida Paulista",
"Principal avenida financeira",
ArcGIS_WX_v100.SIMBOLO_SQUARE,
"#00FF00" // Cor verde
)

// MARCADOR 3: Estação da Luz
nID3 é um inteiro = gArcGIS.AdicionarMarcador(
-23.5356, -46.6356,
"Estação da Luz",
"Estação histórica de trem",
ArcGIS_WX_v100.SIMBOLO_DIAMOND,
"#0000FF" // Cor azul
)

// Verificar se todos foram criados
SE nID1 > 0 E nID2 > 0 E nID3 > 0 ENTÃO
Info("? Todos os marcadores foram adicionados com sucesso!" + CR +
"IDs criados: " + nID1 + ", " + nID2 + ", " + nID3)
SENÃO
Error("?? Alguns marcadores falharam")
FIM

EXCEPTION
Error("?? Erro: " + ExceptionInfo())
FIM

// ============================================================================
// SÍMBOLOS DISPONÍVEIS:
//
// • SIMBOLO_CIRCLE - Círculo (padrão)
// • SIMBOLO_SQUARE - Quadrado
// • SIMBOLO_DIAMOND - Losango
// • SIMBOLO_TRIANGLE - Triângulo
// • SIMBOLO_CROSS - Cruz
// • SIMBOLO_X - X
//
// CORES EM FORMATO HEX:
// • "#FF0000" - Vermelho
// • "#00FF00" - Verde
// • "#0000FF" - Azul
// • "#FFFF00" - Amarelo
// • "#FF6600" - Laranja (padrão)
// ============================================================================
```

### **3. Navegação Básica**

```wlanguage
// ============================================================================
// EXEMPLO 3: Navegação Básica - Movendo o Mapa
// Complexidade: ? Básico
// Tempo estimado: 15 minutos
// ============================================================================

PROCEDIMENTO NavegacaoBasica()

gArcGIS é um ArcGIS_WX_v100
sAPIKey é uma cadeia = "SUA_ARCGIS_API_KEY"

TRY
// Inicializar
gArcGIS = new ArcGIS_WX_v100(sAPIKey, HTMLControl1, ArcGIS_WX_v100.CONTROLE_HTML)
gArcGIS.InicializarMapa(-23.5505, -46.6333, 10)

// Aguardar carregamento
ThreadPause(3000)

// TOUR AUTOMÁTICO POR SÃO PAULO
Info("?? Iniciando tour automático por São Paulo!")

// 1. Centro da cidade (zoom médio)
gArcGIS.CentralizarMapa(-23.5505, -46.6333, 12)
gArcGIS.AdicionarMarcador(-23.5505, -46.6333, "Centro", "Marco zero")
ThreadPause(3000)

// 2. Avenida Paulista (zoom alto)
Info("?? Indo para a Avenida Paulista...")
gArcGIS.CentralizarMapa(-23.5614, -46.6558, 15)
gArcGIS.AdicionarMarcador(-23.5614, -46.6558, "Paulista", "Av. Financeira")
ThreadPause(3000)

// 3. Ibirapuera (zoom médio)
Info("?? Visitando o Parque Ibirapuera...")
gArcGIS.CentralizarMapa(-23.5873, -46.6573, 14)
gArcGIS.AdicionarMarcador(-23.5873, -46.6573, "Ibirapuera", "Parque urbano")
ThreadPause(3000)

// 4. Aeroporto de Congonhas (zoom baixo)
Info("?? Chegando ao Aeroporto de Congonhas...")
gArcGIS.CentralizarMapa(-23.6266, -46.6556, 13)
gArcGIS.AdicionarMarcador(-23.6266, -46.6556, "Congonhas", "Aeroporto")
ThreadPause(3000)

// 5. Voltar para visão geral
Info("?? Voltando para visão geral...")
gArcGIS.CentralizarMapa(-23.5505, -46.6333, 10)

// DEMONSTRAR CONTROLE DE ZOOM
Info("?? Demonstrando controle de zoom...")

// Zoom in progressivo
PARA nZoom = 10 À 16
gArcGIS.DefinirZoom(nZoom)
ThreadPause(500)
FIM

// Zoom out progressivo
PARA nZoom = 16 À 10 PAS -1
gArcGIS.DefinirZoom(nZoom)
ThreadPause(500)
FIM

Info("? Tour de navegação concluído!")

EXCEPTION
Error("?? Erro na navegação: " + ExceptionInfo())
FIM

// ============================================================================
// MÉTODOS DE NAVEGAÇÃO:
//
// • CentralizarMapa(lat, lng, zoom) - Move o centro do mapa
// • DefinirZoom(zoom) - Altera apenas o zoom (1-20)
// • ObterPosicaoAtual() - Retorna posição atual
// • ObterZoomAtual() - Retorna zoom atual
//
// DICAS DE ZOOM:
// • 1-5: Visão mundial/continental
// • 6-10: Visão de país/estado
// • 11-15: Visão de cidade/bairro
// • 16-20: Visão de rua/edifício
// ============================================================================
```

### **4. Alternando Basemaps**

```wlanguage
// ============================================================================
// EXEMPLO 4: Alternando Entre Diferentes Basemaps
// Complexidade: ? Básico
// Tempo estimado: 10 minutos
// ============================================================================

PROCEDIMENTO AlternandoBasemaps()

gArcGIS é um ArcGIS_WX_v100
sAPIKey é uma cadeia = "SUA_ARCGIS_API_KEY"

TRY
// Inicializar
gArcGIS = new ArcGIS_WX_v100(sAPIKey, HTMLControl1, ArcGIS_WX_v100.CONTROLE_HTML)
gArcGIS.InicializarMapa(-23.5505, -46.6333, 12)

// Adicionar marcador de referência
gArcGIS.AdicionarMarcador(-23.5505, -46.6333, "Centro SP", "Ponto de referência")

ThreadPause(3000)

// DEMONSTRAÇÃO DE BASEMAPS
Info("??? Demonstrando diferentes tipos de mapas...")

// 1. Mapa de ruas (padrão)
Info("?? Mapa de Ruas - Ideal para navegação urbana")
gArcGIS.AlterarBasemap(ArcGIS_WX_v100.BASEMAP_STREETS)
ThreadPause(4000)

// 2. Imagem de satélite
Info("??? Imagem de Satélite - Visão aérea real")
gArcGIS.AlterarBasemap(ArcGIS_WX_v100.BASEMAP_SATELLITE)
ThreadPause(4000)

// 3. Mapa híbrido
Info("?? Mapa Híbrido - Satélite + ruas")
gArcGIS.AlterarBasemap(ArcGIS_WX_v100.BASEMAP_HYBRID)
ThreadPause(4000)

// 4. Mapa de relevo
Info("?? Mapa de Relevo - Topografia detalhada")
gArcGIS.AlterarBasemap(ArcGIS_WX_v100.BASEMAP_TERRAIN)
ThreadPause(4000)

// 5. Tema escuro
Info("?? Tema Escuro - Ideal para dashboards")
gArcGIS.AlterarBasemap(ArcGIS_WX_v100.BASEMAP_DARK)
ThreadPause(4000)

// 6. Tema noturno
Info("?? Tema Noturno - Navegação noturna")
gArcGIS.AlterarBasemap(ArcGIS_WX_v100.BASEMAP_NIGHT)
ThreadPause(4000)

// 7. OpenStreetMap
Info("?? OpenStreetMap - Dados abertos")
gArcGIS.AlterarBasemap(ArcGIS_WX_v100.BASEMAP_OSM)
ThreadPause(4000)

// Voltar ao padrão
Info("?? Voltando ao mapa de ruas...")
gArcGIS.AlterarBasemap(ArcGIS_WX_v100.BASEMAP_STREETS)

Info("? Demonstração de basemaps concluída!")

EXCEPTION
Error("?? Erro nos basemaps: " + ExceptionInfo())
FIM

// ============================================================================
// BASEMAPS DISPONÍVEIS:
//
// • BASEMAP_STREETS - Ruas vetoriais (padrão)
// • BASEMAP_SATELLITE - Imagem de satélite
// • BASEMAP_HYBRID - Híbrido (satélite + ruas)
// • BASEMAP_TERRAIN - Relevo topográfico
// • BASEMAP_OCEANS - Oceanos especializados
// • BASEMAP_OSM - OpenStreetMap
// • BASEMAP_DARK - Tema escuro
// • BASEMAP_GRAY - Cinza claro
// • BASEMAP_NIGHT - Ruas noturnas
// • BASEMAP_NAVIGATION - Navegação otimizada
//
// CASOS DE USO:
// • STREETS/NAVIGATION - Apps de navegação
// • SATELLITE/HYBRID - Análise territorial
// • TERRAIN - Estudos topográficos
// • DARK/NIGHT - Dashboards e painéis
// • OSM - Projetos open source
// ============================================================================
```

---

## ? **EXEMPLOS INTERMEDIÁRIOS**

### **5. Sistema de Categorias**

```wlanguage
// ============================================================================
// EXEMPLO 5: Sistema de Categorias de Marcadores
// Complexidade: ?? Intermediário
// Tempo estimado: 30 minutos
// ============================================================================

// Enumeração para categorias
ENUMERACAO TipoEstabelecimento
HOSPITAL = 1
ESCOLA = 2
SHOPPING = 3
RESTAURANTE = 4
POSTO_GASOLINA = 5
BANCO = 6
FIM

// Estrutura para configuração de categoria
ESTRUTURA stCategoriaConfig
sTipo é uma cadeia
sSimbolo é uma cadeia
sCor é uma cadeia
sDescricao é uma cadeia
FIM

PROCEDIMENTO SistemaCategorias()

gArcGIS é um ArcGIS_WX_v100
sAPIKey é uma cadeia = "SUA_ARCGIS_API_KEY"

// Array de configurações de categorias
arrCategorias é um array de stCategoriaConfig

TRY
// Inicializar mapa
gArcGIS = new ArcGIS_WX_v100(sAPIKey, HTMLControl1, ArcGIS_WX_v100.CONTROLE_HTML)
gArcGIS.InicializarMapa(-23.5505, -46.6333, 12)

// CONFIGURAR CATEGORIAS
ConfigurarCategorias(arrCategorias)

ThreadPause(3000)

// ADICIONAR ESTABELECIMENTOS POR CATEGORIA
Info("?? Adicionando hospitais...")
AdicionarHospitais(gArcGIS, arrCategorias)
ThreadPause(2000)

Info("?? Adicionando escolas...")
AdicionarEscolas(gArcGIS, arrCategorias)
ThreadPause(2000)

Info("??? Adicionando shoppings...")
AdicionarShoppings(gArcGIS, arrCategorias)
ThreadPause(2000)

Info("??? Adicionando restaurantes...")
AdicionarRestaurantes(gArcGIS, arrCategorias)
ThreadPause(2000)

Info("? Adicionando postos de gasolina...")
AdicionarPostosGasolina(gArcGIS, arrCategorias)
ThreadPause(2000)

Info("?? Adicionando bancos...")
AdicionarBancos(gArcGIS, arrCategorias)

// ESTATÍSTICAS FINAIS
ExibirEstatisticasCategorias(gArcGIS)

EXCEPTION
Error("?? Erro no sistema de categorias: " + ExceptionInfo())
FIM

PRIVADO PROCEDIMENTO ConfigurarCategorias(arrCategorias é um array de stCategoriaConfig)

stConfig é um stCategoriaConfig

// Hospital
stConfig.sTipo = "Hospital"
stConfig.sSimbolo = ArcGIS_WX_v100.SIMBOLO_CROSS
stConfig.sCor = "#FF0000"
stConfig.sDescricao = "Estabelecimentos de saúde"
ArrayAdd(arrCategorias, stConfig)

// Escola
stConfig.sTipo = "Escola"
stConfig.sSimbolo = ArcGIS_WX_v100.SIMBOLO_SQUARE
stConfig.sCor = "#00FF00"
stConfig.sDescricao = "Instituições de ensino"
ArrayAdd(arrCategorias, stConfig)

// Shopping
stConfig.sTipo = "Shopping"
stConfig.sSimbolo = ArcGIS_WX_v100.SIMBOLO_DIAMOND
stConfig.sCor = "#0000FF"
stConfig.sDescricao = "Centros comerciais"
ArrayAdd(arrCategorias, stConfig)

// Restaurante
stConfig.sTipo = "Restaurante"
stConfig.sSimbolo = ArcGIS_WX_v100.SIMBOLO_CIRCLE
stConfig.sCor = "#FFFF00"
stConfig.sDescricao = "Estabelecimentos gastronômicos"
ArrayAdd(arrCategorias, stConfig)

// Posto de Gasolina
stConfig.sTipo = "Posto"
stConfig.sSimbolo = ArcGIS_WX_v100.SIMBOLO_TRIANGLE
stConfig.sCor = "#FF6600"
stConfig.sDescricao = "Postos de combustível"
ArrayAdd(arrCategorias, stConfig)

// Banco
stConfig.sTipo = "Banco"
stConfig.sSimbolo = ArcGIS_WX_v100.SIMBOLO_X
stConfig.sCor = "#800080"
stConfig.sDescricao = "Instituições financeiras"
ArrayAdd(arrCategorias, stConfig)

PRIVADO PROCEDIMENTO AdicionarHospitais(gArcGIS é um ArcGIS_WX_v100, arrCategorias é um array de stCategoriaConfig)

config é um stCategoriaConfig = arrCategorias[TipoEstabelecimento.HOSPITAL]

// Hospital das Clínicas
gArcGIS.AdicionarMarcador(-23.5558, -46.6696,
"Hospital das Clínicas",
"Principal complexo hospitalar de SP",
config.sSimbolo, config.sCor)

// Hospital Sírio-Libanês
gArcGIS.AdicionarMarcador(-23.5641, -46.6524,
"Hospital Sírio-Libanês",
"Hospital de referência",
config.sSimbolo, config.sCor)

// Hospital Albert Einstein
gArcGIS.AdicionarMarcador(-23.5986, -46.7119,
"Hospital Albert Einstein",
"Hospital de excelência",
config.sSimbolo, config.sCor)

PRIVADO PROCEDIMENTO AdicionarEscolas(gArcGIS é um ArcGIS_WX_v100, arrCategorias é um array de stCategoriaConfig)

config é um stCategoriaConfig = arrCategorias[TipoEstabelecimento.ESCOLA]

// USP
gArcGIS.AdicionarMarcador(-23.5558, -46.7319,
"Universidade de São Paulo",
"Principal universidade do Brasil",
config.sSimbolo, config.sCor)

// Mackenzie
gArcGIS.AdicionarMarcador(-23.5486, -46.6519,
"Universidade Mackenzie",
"Universidade tradicional",
config.sSimbolo, config.sCor)

// PUC-SP
gArcGIS.AdicionarMarcador(-23.5394, -46.6397,
"PUC-SP",
"Pontifícia Universidade Católica",
config.sSimbolo, config.sCor)

PRIVADO PROCEDIMENTO AdicionarShoppings(gArcGIS é um ArcGIS_WX_v100, arrCategorias é um array de stCategoriaConfig)

config é um stCategoriaConfig = arrCategorias[TipoEstabelecimento.SHOPPING]

// Shopping Iguatemi
gArcGIS.AdicionarMarcador(-23.5761, -46.6886,
"Shopping Iguatemi",
"Shopping de luxo",
config.sSimbolo, config.sCor)

// Shopping Eldorado
gArcGIS.AdicionarMarcador(-23.5631, -46.6919,
"Shopping Eldorado",
"Grande centro comercial",
config.sSimbolo, config.sCor)

// Shopping Morumbi
gArcGIS.AdicionarMarcador(-23.6219, -46.7019,
"Shopping Morumbi",
"Shopping na zona sul",
config.sSimbolo, config.sCor)

PRIVADO PROCEDIMENTO AdicionarRestaurantes(gArcGIS é um ArcGIS_WX_v100, arrCategorias é um array de stCategoriaConfig)

config é um stCategoriaConfig = arrCategorias[TipoEstabelecimento.RESTAURANTE]

// Mercado Municipal
gArcGIS.AdicionarMarcador(-23.5475, -46.6297,
"Mercado Municipal",
"Gastronomia tradicional paulistana",
config.sSimbolo, config.sCor)

// Rua Augusta (região gastronômica)
gArcGIS.AdicionarMarcador(-23.5558, -46.6519,
"Região Gastronômica Augusta",
"Concentração de restaurantes",
config.sSimbolo, config.sCor)

// Vila Madalena
gArcGIS.AdicionarMarcador(-23.5558, -46.6919,
"Vila Madalena",
"Bares e restaurantes",
config.sSimbolo, config.sCor)

PRIVADO PROCEDIMENTO AdicionarPostosGasolina(gArcGIS é um ArcGIS_WX_v100, arrCategorias é um array de stCategoriaConfig)

config é um stCategoriaConfig = arrCategorias[TipoEstabelecimento.POSTO_GASOLINA]

// Postos estratégicos
gArcGIS.AdicionarMarcador(-23.5505, -46.6333,
"Posto Centro",
"Posto de combustível no centro",
config.sSimbolo, config.sCor)

gArcGIS.AdicionarMarcador(-23.5614, -46.6558,
"Posto Paulista",
"Posto na Av. Paulista",
config.sSimbolo, config.sCor)

gArcGIS.AdicionarMarcador(-23.5873, -46.6573,
"Posto Ibirapuera",
"Posto próximo ao parque",
config.sSimbolo, config.sCor)

PRIVADO PROCEDIMENTO AdicionarBancos(gArcGIS é um ArcGIS_WX_v100, arrCategorias é um array de stCategoriaConfig)

config é um stCategoriaConfig = arrCategorias[TipoEstabelecimento.BANCO]

// Bancos no centro financeiro
gArcGIS.AdicionarMarcador(-23.5614, -46.6558,
"Banco Itaú",
"Agência na Paulista",
config.sSimbolo, config.sCor)

gArcGIS.AdicionarMarcador(-23.5505, -46.6333,
"Banco do Brasil",
"Agência no centro",
config.sSimbolo, config.sCor)

gArcGIS.AdicionarMarcador(-23.5475, -46.6361,
"Caixa Econômica",
"Agência na República",
config.sSimbolo, config.sCor)

PRIVADO PROCEDIMENTO ExibirEstatisticasCategorias(gArcGIS é um ArcGIS_WX_v100)

nTotal é um inteiro = gArcGIS.ObterTotalMarcadores()
sRelatorio é uma cadeia

sRelatorio = "?? ESTATÍSTICAS DO SISTEMA DE CATEGORIAS" + CR + CR +
"?? Hospitais: 3 marcadores" + CR +
"?? Escolas: 3 marcadores" + CR +
"??? Shoppings: 3 marcadores" + CR +
"??? Restaurantes: 3 marcadores" + CR +
"? Postos: 3 marcadores" + CR +
"?? Bancos: 3 marcadores" + CR + CR +
"?? Total de marcadores: " + nTotal + CR + CR +
"? Sistema de categorias implementado com sucesso!"

Info(sRelatorio)

// ============================================================================
// VANTAGENS DO SISTEMA DE CATEGORIAS:
//
// 1. ORGANIZAÇÃO VISUAL
// • Cores diferentes por categoria
// • Símbolos específicos por tipo
// • Identificação rápida no mapa
//
// 2. FACILIDADE DE MANUTENÇÃO
// • Configuração centralizada
// • Fácil adição de novas categorias
// • Padrão consistente
//
// 3. ESCALABILIDADE
// • Suporte a muitas categorias
// • Filtros por categoria (futuro)
// • Estatísticas automáticas
//
// 4. FLEXIBILIDADE
// • Configuração dinâmica
// • Adaptável a diferentes negócios
// • Extensível para novos tipos
// ============================================================================
```

### **6. Busca e Filtros**

```wlanguage
// ============================================================================
// EXEMPLO 6: Sistema de Busca e Filtros
// Complexidade: ?? Intermediário
// Tempo estimado: 45 minutos
// ============================================================================

// Estrutura para critérios de busca
ESTRUTURA stCriterioBusca
sTexto é uma cadeia // Texto livre
nLatCentro é um real // Latitude do centro
nLngCentro é um real // Longitude do centro
nRaioKm é um real // Raio em quilômetros
sTipoEstabelecimento é uma cadeia // Filtro por tipo
bApenasVisiveis é um booleano // Apenas marcadores visíveis
FIM

PROCEDIMENTO SistemaBuscaFiltros()

gArcGIS é um ArcGIS_WX_v100
sAPIKey é uma cadeia = "SUA_ARCGIS_API_KEY"

TRY
// Inicializar mapa
gArcGIS = new ArcGIS_WX_v100(sAPIKey, HTMLControl1, ArcGIS_WX_v100.CONTROLE_HTML)
gArcGIS.InicializarMapa(-23.5505, -46.6333, 12)

ThreadPause(3000)

// POPULAR MAPA COM DADOS DE EXEMPLO
PopularMapaExemplo(gArcGIS)

// DEMONSTRAR DIFERENTES TIPOS DE BUSCA
DemonstrarBuscas(gArcGIS)

EXCEPTION
Error("?? Erro no sistema de busca: " + ExceptionInfo())
FIM

PRIVADO PROCEDIMENTO PopularMapaExemplo(gArcGIS é um ArcGIS_WX_v100)

Info("?? Populando mapa com dados de exemplo...")

// Hospitais (vermelho)
gArcGIS.AdicionarMarcador(-23.5558, -46.6696, "Hospital das Clínicas", "Hospital público", ArcGIS_WX_v100.SIMBOLO_CROSS, "#FF0000")
gArcGIS.AdicionarMarcador(-23.5641, -46.6524, "Hospital Sírio-Libanês", "Hospital privado", ArcGIS_WX_v100.SIMBOLO_CROSS, "#FF0000")
gArcGIS.AdicionarMarcador(-23.5986, -46.7119, "Hospital Albert Einstein", "Hospital de excelência", ArcGIS_WX_v100.SIMBOLO_CROSS, "#FF0000")

// Escolas (verde)
gArcGIS.AdicionarMarcador(-23.5558, -46.7319, "USP", "Universidade pública", ArcGIS_WX_v100.SIMBOLO_SQUARE, "#00FF00")
gArcGIS.AdicionarMarcador(-23.5486, -46.6519, "Mackenzie", "Universidade privada", ArcGIS_WX_v100.SIMBOLO_SQUARE, "#00FF00")
gArcGIS.AdicionarMarcador(-23.5394, -46.6397, "PUC-SP", "Universidade católica", ArcGIS_WX_v100.SIMBOLO_SQUARE, "#00FF00")

// Shoppings (azul)
gArcGIS.AdicionarMarcador(-23.5761, -46.6886, "Shopping Iguatemi", "Shopping de luxo", ArcGIS_WX_v100.SIMBOLO_DIAMOND, "#0000FF")
gArcGIS.AdicionarMarcador(-23.5631, -46.6919, "Shopping Eldorado", "Grande shopping", ArcGIS_WX_v100.SIMBOLO_DIAMOND, "#0000FF")
gArcGIS.AdicionarMarcador(-23.6219, -46.7019, "Shopping Morumbi", "Shopping zona sul", ArcGIS_WX_v100.SIMBOLO_DIAMOND, "#0000FF")

// Restaurantes (amarelo)
gArcGIS.AdicionarMarcador(-23.5475, -46.6297, "Mercado Municipal", "Gastronomia tradicional", ArcGIS_WX_v100.SIMBOLO_CIRCLE, "#FFFF00")
gArcGIS.AdicionarMarcador(-23.5558, -46.6519, "Região Augusta", "Restaurantes variados", ArcGIS_WX_v100.SIMBOLO_CIRCLE, "#FFFF00")
gArcGIS.AdicionarMarcador(-23.5558, -46.6919, "Vila Madalena", "Bares e restaurantes", ArcGIS_WX_v100.SIMBOLO_CIRCLE, "#FFFF00")

PRIVADO PROCEDIMENTO DemonstrarBuscas(gArcGIS é um ArcGIS_WX_v100)

arrMarcadores é um array de ArcGIS_WX_v100.stMarcador
stCriterio é um stCriterioBusca

// 1. BUSCA POR TEXTO
Info("?? BUSCA 1: Procurando por 'Hospital'...")
stCriterio.sTexto = "Hospital"
arrMarcadores = BuscarPorTexto(gArcGIS, stCriterio.sTexto)
ExibirResultadosBusca("Hospitais encontrados", arrMarcadores)
ThreadPause(3000)

// 2. BUSCA POR PROXIMIDADE
Info("?? BUSCA 2: Estabelecimentos próximos ao centro (raio 5km)...")
stCriterio.nLatCentro = -23.5505
stCriterio.nLngCentro = -46.6333
stCriterio.nRaioKm = 5.0
arrMarcadores = BuscarPorProximidade(gArcGIS, stCriterio)
ExibirResultadosBusca("Próximos ao centro", arrMarcadores)
ThreadPause(3000)

// 3. BUSCA POR TIPO
Info("?? BUSCA 3: Procurando por 'Universidade'...")
stCriterio.sTexto = "Universidade"
arrMarcadores = BuscarPorTexto(gArcGIS, stCriterio.sTexto)
ExibirResultadosBusca("Universidades encontradas", arrMarcadores)
ThreadPause(3000)

// 4. BUSCA COMBINADA
Info("???? BUSCA 4: Shoppings próximos à Paulista (raio 3km)...")
stCriterio.sTexto = "Shopping"
stCriterio.nLatCentro = -23.5614
stCriterio.nLngCentro = -46.6558
stCriterio.nRaioKm = 3.0
arrMarcadores = BuscarCombinada(gArcGIS, stCriterio)
ExibirResultadosBusca("Shoppings próximos à Paulista", arrMarcadores)
ThreadPause(3000)

// 5. FILTRO POR DISTÂNCIA ESPECÍFICA
Info("?? BUSCA 5: Estabelecimentos a exatamente 2-4km do centro...")
arrMarcadores = BuscarPorFaixaDistancia(gArcGIS, -23.5505, -46.6333, 2.0, 4.0)
ExibirResultadosBusca("Faixa de distância 2-4km", arrMarcadores)

PRIVADO PROCEDIMENTO BuscarPorTexto(gArcGIS é um ArcGIS_WX_v100, sTexto é uma cadeia) : array de ArcGIS_WX_v100.stMarcador

arrTodos é um array de ArcGIS_WX_v100.stMarcador
arrResultado é um array de ArcGIS_WX_v100.stMarcador

// Obter todos os marcadores
arrTodos = gArcGIS.ListarMarcadores()

// Filtrar por texto
PARA i = 1 À ArrayCount(arrTodos)
marcador é um ArcGIS_WX_v100.stMarcador = arrTodos[i]

// Buscar no título ou descrição (case insensitive)
SE Contains(Upper(marcador.sTitulo), Upper(sTexto)) OU
Contains(Upper(marcador.sDescricao), Upper(sTexto)) ENTÃO
ArrayAdd(arrResultado, marcador)
FIM
FIM

RETORNO arrResultado

PRIVADO PROCEDIMENTO BuscarPorProximidade(gArcGIS é um ArcGIS_WX_v100, stCriterio é um stCriterioBusca) : array de ArcGIS_WX_v100.stMarcador

arrTodos é um array de ArcGIS_WX_v100.stMarcador
arrResultado é um array de ArcGIS_WX_v100.stMarcador
stPosCentro é um ArcGIS_WX_v100.stGeoPosition

// Criar posição do centro
stPosCentro = ArcGIS_WX_v100.CriarPosicao(stCriterio.nLatCentro, stCriterio.nLngCentro)

// Obter todos os marcadores
arrTodos = gArcGIS.ListarMarcadores()

// Filtrar por proximidade
PARA i = 1 À ArrayCount(arrTodos)
marcador é um ArcGIS_WX_v100.stMarcador = arrTodos[i]

// Calcular distância
nDistancia é um real = ArcGIS_WX_v100.CalcularDistancia(stPosCentro, marcador.stPosicao)

// Verificar se está dentro do raio
SE nDistancia <= stCriterio.nRaioKm ENTÃO
ArrayAdd(arrResultado, marcador)
FIM
FIM

RETORNO arrResultado

PRIVADO PROCEDIMENTO BuscarCombinada(gArcGIS é um ArcGIS_WX_v100, stCriterio é um stCriterioBusca) : array de ArcGIS_WX_v100.stMarcador

arrTexto é um array de ArcGIS_WX_v100.stMarcador
arrProximidade é um array de ArcGIS_WX_v100.stMarcador
arrResultado é um array de ArcGIS_WX_v100.stMarcador

// Buscar por texto
arrTexto = BuscarPorTexto(gArcGIS, stCriterio.sTexto)

// Filtrar por proximidade
stPosCentro é um ArcGIS_WX_v100.stGeoPosition = ArcGIS_WX_v100.CriarPosicao(stCriterio.nLatCentro, stCriterio.nLngCentro)

PARA i = 1 À ArrayCount(arrTexto)
marcador é um ArcGIS_WX_v100.stMarcador = arrTexto[i]

nDistancia é um real = ArcGIS_WX_v100.CalcularDistancia(stPosCentro, marcador.stPosicao)

SE nDistancia <= stCriterio.nRaioKm ENTÃO
ArrayAdd(arrResultado, marcador)
FIM
FIM

RETORNO arrResultado

PRIVADO PROCEDIMENTO BuscarPorFaixaDistancia(gArcGIS é um ArcGIS_WX_v100, nLatCentro é um real, nLngCentro é um real, nDistanciaMin é um real, nDistanciaMax é um real) : array de ArcGIS_WX_v100.stMarcador

arrTodos é um array de ArcGIS_WX_v100.stMarcador
arrResultado é um array de ArcGIS_WX_v100.stMarcador
stPosCentro é um ArcGIS_WX_v100.stGeoPosition

stPosCentro = ArcGIS_WX_v100.CriarPosicao(nLatCentro, nLngCentro)
arrTodos = gArcGIS.ListarMarcadores()

PARA i = 1 À ArrayCount(arrTodos)
marcador é um ArcGIS_WX_v100.stMarcador = arrTodos[i]

nDistancia é um real = ArcGIS_WX_v100.CalcularDistancia(stPosCentro, marcador.stPosicao)

SE nDistancia >= nDistanciaMin E nDistancia <= nDistanciaMax ENTÃO
ArrayAdd(arrResultado, marcador)
FIM
FIM

RETORNO arrResultado

PRIVADO PROCEDIMENTO ExibirResultadosBusca(sTitulo é uma cadeia, arrMarcadores é um array de ArcGIS_WX_v100.stMarcador)

sResultado é uma cadeia

sResultado = "?? " + sTitulo + CR + CR +
"?? Encontrados: " + ArrayCount(arrMarcadores) + " resultados" + CR + CR

SE ArrayCount(arrMarcadores) > 0 ENTÃO
PARA i = 1 À ArrayCount(arrMarcadores)
marcador é um ArcGIS_WX_v100.stMarcador = arrMarcadores[i]

sResultado += "?? " + marcador.sTitulo + CR +
" " + marcador.sDescricao + CR +
" Posição: " + NumToString(marcador.stPosicao.nLatitude, "0.4f") +
", " + NumToString(marcador.stPosicao.nLongitude, "0.4f") + CR + CR
FIM
SENÃO
sResultado += "? Nenhum resultado encontrado"
FIM

Info(sResultado)

// ============================================================================
// FUNCIONALIDADES DO SISTEMA DE BUSCA:
//
// 1. BUSCA POR TEXTO
// • Busca em títulos e descrições
// • Case insensitive
// • Suporte a palavras parciais
//
// 2. BUSCA POR PROXIMIDADE
// • Raio em quilômetros
// • Cálculo preciso de distância
// • Centro configurável
//
// 3. BUSCA COMBINADA
// • Texto + proximidade
// • Múltiplos critérios
// • Resultados refinados
//
// 4. FILTROS AVANÇADOS
// • Faixa de distância
// • Tipos específicos
// • Critérios personalizados
//
// EXTENSÕES POSSÍVEIS:
// • Busca por categoria
// • Ordenação por distância
// • Filtros por data de criação
// • Busca geográfica por polígono
// • Cache de resultados
// • Histórico de buscas
// ============================================================================
```

### **7. Cálculo de Distâncias**

```wlanguage
// ============================================================================
// EXEMPLO 7: Cálculo de Distâncias e Análises Geográficas
// Complexidade: ?? Intermediário
// Tempo estimado: 30 minutos
// ============================================================================

// Estrutura para resultado de análise de distância
ESTRUTURA stAnaliseDistancia
stOrigem é um ArcGIS_WX_v100.stGeoPosition
stDestino é um ArcGIS_WX_v100.stGeoPosition
nDistanciaKm é um real
nTempoEstimadoMin é um real
sClassificacao é uma cadeia
FIM

PROCEDIMENTO CalculoDistancias()

gArcGIS é um ArcGIS_WX_v100
sAPIKey é uma cadeia = "SUA_ARCGIS_API_KEY"

TRY
// Inicializar mapa
gArcGIS = new ArcGIS_WX_v100(sAPIKey, HTMLControl1, ArcGIS_WX_v100.CONTROLE_HTML)
gArcGIS.InicializarMapa(-23.5505, -46.6333, 11)

ThreadPause(3000)

// DEFINIR PONTOS DE REFERÊNCIA
DefinirPontosReferencia(gArcGIS)

// DEMONSTRAR CÁLCULOS DE DISTÂNCIA
DemonstrarCalculosDistancia()

// ANÁLISE DE PROXIMIDADE
AnaliseProximidade(gArcGIS)

// MATRIZ DE DISTÂNCIAS
MatrizDistancias()

// ANÁLISE DE ACESSIBILIDADE
AnaliseAcessibilidade(gArcGIS)

EXCEPTION
Error("?? Erro nos cálculos de distância: " + ExceptionInfo())
FIM

PRIVADO PROCEDIMENTO DefinirPontosReferencia(gArcGIS é um ArcGIS_WX_v100)

Info("?? Definindo pontos de referência em São Paulo...")

// Centro histórico
gArcGIS.AdicionarMarcador(-23.5505, -46.6333, "Centro Histórico", "Marco zero da cidade", ArcGIS_WX_v100.SIMBOLO_CIRCLE, "#FF0000")

// Avenida Paulista
gArcGIS.AdicionarMarcador(-23.5614, -46.6558, "Av. Paulista", "Centro financeiro", ArcGIS_WX_v100.SIMBOLO_SQUARE, "#00FF00")

// Aeroporto de Congonhas
gArcGIS.AdicionarMarcador(-23.6266, -46.6556, "Aeroporto Congonhas", "Aeroporto doméstico", ArcGIS_WX_v100.SIMBOLO_TRIANGLE, "#0000FF")

// Aeroporto de Guarulhos
gArcGIS.AdicionarMarcador(-23.4356, -46.4731, "Aeroporto Guarulhos", "Aeroporto internacional", ArcGIS_WX_v100.SIMBOLO_TRIANGLE, "#0000FF")

// Shopping Iguatemi
gArcGIS.AdicionarMarcador(-23.5761, -46.6886, "Shopping Iguatemi", "Centro comercial", ArcGIS_WX_v100.SIMBOLO_DIAMOND, "#FFFF00")

// Estádio do Morumbi
gArcGIS.AdicionarMarcador(-23.6003, -46.7197, "Estádio Morumbi", "Estádio de futebol", ArcGIS_WX_v100.SIMBOLO_X, "#FF6600")

PRIVADO PROCEDIMENTO DemonstrarCalculosDistancia()

stCentro é um ArcGIS_WX_v100.stGeoPosition
stPaulista é um ArcGIS_WX_v100.stGeoPosition
stCongonhas é um ArcGIS_WX_v100.stGeoPosition
stGuarulhos é um ArcGIS_WX_v100.stGeoPosition

nDistancia é um real
sRelatorio é uma cadeia

Info("?? Calculando distâncias entre pontos principais...")

// Definir posições
stCentro = ArcGIS_WX_v100.CriarPosicao(-23.5505, -46.6333, "Centro")
stPaulista = ArcGIS_WX_v100.CriarPosicao(-23.5614, -46.6558, "Paulista")
stCongonhas = ArcGIS_WX_v100.CriarPosicao(-23.6266, -46.6556, "Congonhas")
stGuarulhos = ArcGIS_WX_v100.CriarPosicao(-23.4356, -46.4731, "Guarulhos")

sRelatorio = "?? RELATÓRIO DE DISTÂNCIAS" + CR + CR

// Centro ? Paulista
nDistancia = ArcGIS_WX_v100.CalcularDistancia(stCentro, stPaulista)
sRelatorio += "??? Centro ? ?? Paulista: " + NumToString(nDistancia, "0.2f") + " km" + CR

// Centro ? Congonhas
nDistancia = ArcGIS_WX_v100.CalcularDistancia(stCentro, stCongonhas)
sRelatorio += "??? Centro ? ?? Congonhas: " + NumToString(nDistancia, "0.2f") + " km" + CR

// Centro ? Guarulhos
nDistancia = ArcGIS_WX_v100.CalcularDistancia(stCentro, stGuarulhos)
sRelatorio += "??? Centro ? ?? Guarulhos: " + NumToString(nDistancia, "0.2f") + " km" + CR

// Paulista ? Congonhas
nDistancia = ArcGIS_WX_v100.CalcularDistancia(stPaulista, stCongonhas)
sRelatorio += "?? Paulista ? ?? Congonhas: " + NumToString(nDistancia, "0.2f") + " km" + CR

// Paulista ? Guarulhos
nDistancia = ArcGIS_WX_v100.CalcularDistancia(stPaulista, stGuarulhos)
sRelatorio += "?? Paulista ? ?? Guarulhos: " + NumToString(nDistancia, "0.2f") + " km" + CR

// Congonhas ? Guarulhos
nDistancia = ArcGIS_WX_v100.CalcularDistancia(stCongonhas, stGuarulhos)
sRelatorio += "?? Congonhas ? ?? Guarulhos: " + NumToString(nDistancia, "0.2f") + " km" + CR

Info(sRelatorio)

PRIVADO PROCEDIMENTO AnaliseProximidade(gArcGIS é um ArcGIS_WX_v100)

stCentro é um ArcGIS_WX_v100.stGeoPosition
arrMarcadores é um array de ArcGIS_WX_v100.stMarcador
arrProximos é um array de stAnaliseDistancia

Info("?? Analisando proximidade ao centro da cidade...")

stCentro = ArcGIS_WX_v100.CriarPosicao(-23.5505, -46.6333, "Centro")
arrMarcadores = gArcGIS.ListarMarcadores()

// Analisar cada marcador
PARA i = 1 À ArrayCount(arrMarcadores)
marcador é um ArcGIS_WX_v100.stMarcador = arrMarcadores[i]

// Pular o próprio centro
SE marcador.sTitulo = "Centro Histórico" ENTÃO
CONTINUAR
FIM

stAnalise é um stAnaliseDistancia
stAnalise.stOrigem = stCentro
stAnalise.stDestino = marcador.stPosicao
stAnalise.nDistanciaKm = ArcGIS_WX_v100.CalcularDistancia(stCentro, marcador.stPosicao)
stAnalise.nTempoEstimadoMin = CalcularTempoEstimado(stAnalise.nDistanciaKm)
stAnalise.sClassificacao = ClassificarDistancia(stAnalise.nDistanciaKm)

ArrayAdd(arrProximos, stAnalise)
FIM

// Ordenar por distância
OrdenarPorDistancia(arrProximos)

// Exibir resultados
ExibirAnaliseProximidade(arrProximos)

PRIVADO PROCEDIMENTO CalcularTempoEstimado(nDistanciaKm é um real) : real

// Estimativa baseada em velocidade média urbana (25 km/h)
nVelocidadeMedia é um real = 25.0
RETORNO (nDistanciaKm / nVelocidadeMedia) * 60 // Converter para minutos

PRIVADO PROCEDIMENTO ClassificarDistancia(nDistanciaKm é um real) : cadeia

SE nDistanciaKm <= 2 ENTÃO
RETORNO "Muito Próximo"
SENÃO SE nDistanciaKm <= 5 ENTÃO
RETORNO "Próximo"
SENÃO SE nDistanciaKm <= 10 ENTÃO
RETORNO "Médio"
SENÃO SE nDistanciaKm <= 20 ENTÃO
RETORNO "Distante"
SENÃO
RETORNO "Muito Distante"
FIM

PRIVADO PROCEDIMENTO OrdenarPorDistancia(arrAnalises é um array de stAnaliseDistancia)

// Ordenação simples por bubble sort
PARA i = 1 À ArrayCount(arrAnalises) - 1
PARA j = i + 1 À ArrayCount(arrAnalises)
SE arrAnalises[i].nDistanciaKm > arrAnalises[j].nDistanciaKm ENTÃO
// Trocar posições
stTemp é um stAnaliseDistancia = arrAnalises[i]
arrAnalises[i] = arrAnalises[j]
arrAnalises[j] = stTemp
FIM
FIM
FIM

PRIVADO PROCEDIMENTO ExibirAnaliseProximidade(arrAnalises é um array de stAnaliseDistancia)

sRelatorio é uma cadeia

sRelatorio = "?? ANÁLISE DE PROXIMIDADE AO CENTRO" + CR + CR +
"?? Ordenado por distância (mais próximo primeiro):" + CR + CR

PARA i = 1 À ArrayCount(arrAnalises)
analise é um stAnaliseDistancia = arrAnalises[i]

sRelatorio += (i) + "º lugar: " + analise.stDestino.sDescricao + CR +
" ?? Distância: " + NumToString(analise.nDistanciaKm, "0.2f") + " km" + CR +
" ?? Tempo estimado: " + NumToString(analise.nTempoEstimadoMin, "0.0f") + " min" + CR +
" ??? Classificação: " + analise.sClassificacao + CR + CR
FIM

Info(sRelatorio)

PRIVADO PROCEDIMENTO MatrizDistancias()

// Pontos principais
arrPontos é um array de ArcGIS_WX_v100.stGeoPosition
arrNomes é um array de cadeia

Info("?? Gerando matriz de distâncias...")

// Definir pontos
ArrayAdd(arrPontos, ArcGIS_WX_v100.CriarPosicao(-23.5505, -46.6333, "Centro"))
ArrayAdd(arrNomes, "Centro")

ArrayAdd(arrPontos, ArcGIS_WX_v100.CriarPosicao(-23.5614, -46.6558, "Paulista"))
ArrayAdd(arrNomes, "Paulista")

ArrayAdd(arrPontos, ArcGIS_WX_v100.CriarPosicao(-23.6266, -46.6556, "Congonhas"))
ArrayAdd(arrNomes, "Congonhas")

ArrayAdd(arrPontos, ArcGIS_WX_v100.CriarPosicao(-23.4356, -46.4731, "Guarulhos"))
ArrayAdd(arrNomes, "Guarulhos")

// Gerar matriz
sMatriz é uma cadeia = "?? MATRIZ DE DISTÂNCIAS (km)" + CR + CR

// Cabeçalho
sMatriz += " "
PARA j = 1 À ArrayCount(arrNomes)
sMatriz += Right(" " + arrNomes[j], 10)
FIM
sMatriz += CR

// Linhas da matriz
PARA i = 1 À ArrayCount(arrPontos)
sMatriz += Right(" " + arrNomes[i], 10) + " "

PARA j = 1 À ArrayCount(arrPontos)
SE i = j ENTÃO
sMatriz += Right(" 0.00", 10)
SENÃO
nDist é um real = ArcGIS_WX_v100.CalcularDistancia(arrPontos[i], arrPontos[j])
sMatriz += Right(" " + NumToString(nDist, "0.2f"), 10)
FIM
FIM
sMatriz += CR
FIM

Info(sMatriz)

PRIVADO PROCEDIMENTO AnaliseAcessibilidade(gArcGIS é um ArcGIS_WX_v100)

stCentroAnalise é um ArcGIS_WX_v100.stGeoPosition
arrMarcadores é um array de ArcGIS_WX_v100.stMarcador

nProximos5km é um inteiro = 0
nProximos10km é um inteiro = 0
nProximos20km é um inteiro = 0
nDistantes é um inteiro = 0

Info("?? Analisando acessibilidade geral...")

stCentroAnalise = ArcGIS_WX_v100.CriarPosicao(-23.5614, -46.6558, "Paulista") // Centro de análise: Paulista
arrMarcadores = gArcGIS.ListarMarcadores()

PARA i = 1 À ArrayCount(arrMarcadores)
marcador é um ArcGIS_WX_v100.stMarcador = arrMarcadores[i]

nDistancia é um real = ArcGIS_WX_v100.CalcularDistancia(stCentroAnalise, marcador.stPosicao)

SE nDistancia <= 5 ENTÃO
nProximos5km++
SENÃO SE nDistancia <= 10 ENTÃO
nProximos10km++
SENÃO SE nDistancia <= 20 ENTÃO
nProximos20km++
SENÃO
nDistantes++
FIM
FIM

sRelatorio é uma cadeia = "?? ANÁLISE DE ACESSIBILIDADE" + CR +
"?? Centro de análise: Avenida Paulista" + CR + CR +
"?? Até 5km (Muito Acessível): " + nProximos5km + " locais" + CR +
"?? 5-10km (Acessível): " + nProximos10km + " locais" + CR +
"?? 10-20km (Pouco Acessível): " + nProximos20km + " locais" + CR +
"?? Acima de 20km (Difícil Acesso): " + nDistantes + " locais" + CR + CR +
"?? Total analisado: " + ArrayCount(arrMarcadores) + " locais"

Info(sRelatorio)

// ============================================================================
// APLICAÇÕES PRÁTICAS DO CÁLCULO DE DISTÂNCIAS:
//
// 1. ANÁLISE DE LOCALIZAÇÃO
// • Escolha de pontos comerciais
// • Análise de concorrência
// • Planejamento de expansão
//
// 2. LOGÍSTICA E DISTRIBUIÇÃO
// • Otimização de rotas
// • Cálculo de custos de entrega
// • Planejamento de centros de distribuição
//
// 3. ANÁLISE DE ACESSIBILIDADE
// • Serviços públicos
// • Transporte urbano
// • Planejamento urbano
//
// 4. ESTUDOS DE MERCADO
// • Área de influência
// • Análise demográfica
// • Potencial de mercado
//
// FÓRMULAS UTILIZADAS:
// • Distância: Haversine (considera curvatura da Terra)
// • Tempo: Velocidade média urbana (25 km/h)
// • Classificação: Faixas de distância personalizáveis
// ============================================================================
```

### **8. Análises Geoespaciais**

```wlanguage
// ============================================================================
// EXEMPLO 8: Análises Geoespaciais Avançadas
// Complexidade: ?? Intermediário
// Tempo estimado: 45 minutos
// ============================================================================

// Estrutura para resultado de análise
ESTRUTURA stResultadoAnalise
nIDAnalise é um inteiro
sTipoAnalise é uma cadeia
sParametros é uma cadeia
dtExecucao é um DateTime
bSucesso é um booleano
sResultado é uma cadeia
nTempoExecucaoMs é um inteiro
FIM

PROCEDIMENTO AnaliseGeoespaciais()

gArcGIS é um ArcGIS_WX_v100
sAPIKey é uma cadeia = "SUA_ARCGIS_API_KEY"

TRY
// Inicializar mapa
gArcGIS = new ArcGIS_WX_v100(sAPIKey, HTMLControl1, ArcGIS_WX_v100.CONTROLE_HTML)
gArcGIS.InicializarMapa(-23.5505, -46.6333, 12)

ThreadPause(3000)

// PREPARAR DADOS PARA ANÁLISE
PrepararDadosAnalise(gArcGIS)

// EXECUTAR DIFERENTES TIPOS DE ANÁLISE
ExecutarAnaliseBuffer(gArcGIS)
ExecutarAnaliseProximidade(gArcGIS)
ExecutarAnaliseAreaServico(gArcGIS)
ExecutarAnaliseRota(gArcGIS)
ExecutarAnaliseClustering(gArcGIS)

// RELATÓRIO FINAL
GerarRelatorioAnalises()

EXCEPTION
Error("?? Erro nas análises geoespaciais: " + ExceptionInfo())
FIM

PRIVADO PROCEDIMENTO PrepararDadosAnalise(gArcGIS é um ArcGIS_WX_v100)

Info("?? Preparando dados para análises geoespaciais...")

// Pontos de interesse para análise
gArcGIS.AdicionarMarcador(-23.5505, -46.6333, "Centro SP", "Ponto central", ArcGIS_WX_v100.SIMBOLO_CIRCLE, "#FF0000")
gArcGIS.AdicionarMarcador(-23.5614, -46.6558, "Av. Paulista", "Centro financeiro", ArcGIS_WX_v100.SIMBOLO_SQUARE, "#00FF00")
gArcGIS.AdicionarMarcador(-23.5873, -46.6573, "Parque Ibirapuera", "Área verde", ArcGIS_WX_v100.SIMBOLO_DIAMOND, "#0000FF")

// Estabelecimentos comerciais
gArcGIS.AdicionarMarcador(-23.5520, -46.6350, "Shopping A", "Centro comercial", ArcGIS_WX_v100.SIMBOLO_TRIANGLE, "#FFFF00")
gArcGIS.AdicionarMarcador(-23.5630, -46.6560, "Shopping B", "Centro comercial", ArcGIS_WX_v100.SIMBOLO_TRIANGLE, "#FFFF00")
gArcGIS.AdicionarMarcador(-23.5480, -46.6380, "Shopping C", "Centro comercial", ArcGIS_WX_v100.SIMBOLO_TRIANGLE, "#FFFF00")

// Hospitais
gArcGIS.AdicionarMarcador(-23.5558, -46.6696, "Hospital A", "Saúde pública", ArcGIS_WX_v100.SIMBOLO_CROSS, "#FF6600")
gArcGIS.AdicionarMarcador(-23.5641, -46.6524, "Hospital B", "Saúde privada", ArcGIS_WX_v100.SIMBOLO_CROSS, "#FF6600")

// Escolas
gArcGIS.AdicionarMarcador(-23.5486, -46.6519, "Escola A", "Ensino público", ArcGIS_WX_v100.SIMBOLO_X, "#800080")
gArcGIS.AdicionarMarcador(-23.5394, -46.6397, "Escola B", "Ensino privado", ArcGIS_WX_v100.SIMBOLO_X, "#800080")

PRIVADO PROCEDIMENTO ExecutarAnaliseBuffer(gArcGIS é um ArcGIS_WX_v100)

nInicio é um inteiro
nIDAnalise é um inteiro
stResultado é um stResultadoAnalise

Info("?? ANÁLISE 1: Buffer (Área de Influência)")
Info("Calculando área de influência de 1km ao redor do centro...")

nInicio = GetTickCount()

// Parâmetros para análise de buffer
sParametros é uma cadeia = '{"distance": 1000, "units": "meters", "dissolve": true}'

// Executar análise
nIDAnalise = gArcGIS.ExecutarAnalise(ArcGIS_WX_v100.ANALISE_BUFFER, sParametros)

// Registrar resultado
stResultado.nIDAnalise = nIDAnalise
stResultado.sTipoAnalise = "Buffer"
stResultado.sParametros = sParametros
stResultado.dtExecucao = DateTimeSys()
stResultado.bSucesso = (nIDAnalise > 0)
stResultado.nTempoExecucaoMs = GetTickCount() - nInicio

SE stResultado.bSucesso ENTÃO
stResultado.sResultado = "Área de influência de 1km criada com sucesso"
Info("? Buffer executado com sucesso (ID: " + nIDAnalise + ")")
Info("?? Tempo de execução: " + stResultado.nTempoExecucaoMs + "ms")
SENÃO
stResultado.sResultado = "Falha na execução do buffer"
Info("? Erro na execução do buffer")
FIM

// Demonstrar diferentes raios
DemonstrarBuffersMultiplos(gArcGIS)

PRIVADO PROCEDIMENTO DemonstrarBuffersMultiplos(gArcGIS é um ArcGIS_WX_v100)

arrRaios é um array de inteiro

Info("?? Demonstrando buffers com diferentes raios...")

// Definir raios de análise
ArrayAdd(arrRaios, 500) // 500m
ArrayAdd(arrRaios, 1000) // 1km
ArrayAdd(arrRaios, 2000) // 2km
ArrayAdd(arrRaios, 5000) // 5km

PARA i = 1 À ArrayCount(arrRaios)
nRaio é um inteiro = arrRaios[i]

sParams é uma cadeia = '{"distance": ' + nRaio + ', "units": "meters"}'
nID é um inteiro = gArcGIS.ExecutarAnalise(ArcGIS_WX_v100.ANALISE_BUFFER, sParams)

SE nID > 0 ENTÃO
Info("? Buffer de " + nRaio + "m criado (ID: " + nID + ")")
SENÃO
Info("? Falha no buffer de " + nRaio + "m")
FIM

ThreadPause(1000)
FIM

PRIVADO PROCEDIMENTO ExecutarAnaliseProximidade(gArcGIS é um ArcGIS_WX_v100)

nInicio é um inteiro
nIDAnalise é um inteiro

Info("?? ANÁLISE 2: Proximidade")
Info("Analisando estabelecimentos próximos ao centro...")

nInicio = GetTickCount()

// Parâmetros para análise de proximidade
sParametros é uma cadeia = '{"searchRadius": 2000, "maxFeatures": 10, "units": "meters"}'

// Executar análise
nIDAnalise = gArcGIS.ExecutarAnalise(ArcGIS_WX_v100.ANALISE_PROXIMITY, sParametros)

SE nIDAnalise > 0 ENTÃO
nTempo é um inteiro = GetTickCount() - nInicio
Info("? Análise de proximidade executada (ID: " + nIDAnalise + ")")
Info("?? Tempo de execução: " + nTempo + "ms")

// Simular resultados da análise
ExibirResultadosProximidade()
SENÃO
Info("? Erro na análise de proximidade")
FIM

PRIVADO PROCEDIMENTO ExibirResultadosProximidade()

sResultados é uma cadeia

sResultados = "?? RESULTADOS DA ANÁLISE DE PROXIMIDADE" + CR + CR +
"?? Centro de análise: Centro SP" + CR +
"?? Raio de busca: 2.000 metros" + CR + CR +
"?? Estabelecimentos encontrados:" + CR +
"• Shopping A - 850m" + CR +
"• Escola B - 1.200m" + CR +
"• Hospital A - 1.800m" + CR +
"• Shopping C - 1.950m" + CR + CR +
"?? Total: 4 estabelecimentos dentro do raio"

Info(sResultados)

PRIVADO PROCEDIMENTO ExecutarAnaliseAreaServico(gArcGIS é um ArcGIS_WX_v100)

nInicio é um inteiro
nIDAnalise é um inteiro

Info("?? ANÁLISE 3: Área de Serviço")
Info("Calculando área acessível em 15 minutos de carro...")

nInicio = GetTickCount()

// Parâmetros para análise de área de serviço
sParametros é uma cadeia = '{"driveTime": 15, "units": "minutes", "trafficMode": "current"}'

// Executar análise
nIDAnalise = gArcGIS.ExecutarAnalise(ArcGIS_WX_v100.ANALISE_SERVICE_AREA, sParametros)

SE nIDAnalise > 0 ENTÃO
nTempo é um inteiro = GetTickCount() - nInicio
Info("? Análise de área de serviço executada (ID: " + nIDAnalise + ")")
Info("?? Tempo de execução: " + nTempo + "ms")

// Demonstrar diferentes tempos
DemonstrarAreasServicoMultiplas(gArcGIS)
SENÃO
Info("? Erro na análise de área de serviço")
FIM

PRIVADO PROCEDIMENTO DemonstrarAreasServicoMultiplas(gArcGIS é um ArcGIS_WX_v100)

arrTempos é um array de inteiro

Info("? Demonstrando áreas de serviço com diferentes tempos...")

// Definir tempos de análise
ArrayAdd(arrTempos, 5) // 5 minutos
ArrayAdd(arrTempos, 10) // 10 minutos
ArrayAdd(arrTempos, 15) // 15 minutos
ArrayAdd(arrTempos, 30) // 30 minutos

PARA i = 1 À ArrayCount(arrTempos)
nTempo é um inteiro = arrTempos[i]

sParams é uma cadeia = '{"driveTime": ' + nTempo + ', "units": "minutes"}'
nID é um inteiro = gArcGIS.ExecutarAnalise(ArcGIS_WX_v100.ANALISE_SERVICE_AREA, sParams)

SE nID > 0 ENTÃO
Info("? Área de " + nTempo + " min criada (ID: " + nID + ")")
SENÃO
Info("? Falha na área de " + nTempo + " min")
FIM

ThreadPause(1000)
FIM

PRIVADO PROCEDIMENTO ExecutarAnaliseRota(gArcGIS é um ArcGIS_WX_v100)

nInicio é um inteiro
nIDAnalise é um inteiro

Info("??? ANÁLISE 4: Rota Otimizada")
Info("Calculando rota otimizada entre múltiplos pontos...")

nInicio = GetTickCount()

// Parâmetros para análise de rota
sParametros é uma cadeia = '{"optimize": true, "preserveFirstStop": true, "preserveLastStop": true}'

// Executar análise
nIDAnalise = gArcGIS.ExecutarAnalise(ArcGIS_WX_v100.ANALISE_ROUTE, sParametros)

SE nIDAnalise > 0 ENTÃO
nTempo é um inteiro = GetTickCount() - nInicio
Info("? Análise de rota executada (ID: " + nIDAnalise + ")")
Info("?? Tempo de execução: " + nTempo + "ms")

// Adicionar rota visual no mapa
AdicionarRotaVisual(gArcGIS)

// Exibir detalhes da rota
ExibirDetalhesRota()
SENÃO
Info("? Erro na análise de rota")
FIM

PRIVADO PROCEDIMENTO AdicionarRotaVisual(gArcGIS é um ArcGIS_WX_v100)

Info("??? Adicionando rota visual no mapa...")

// Simular rota entre pontos principais
// Centro ? Paulista
gArcGIS.AdicionarRota(-23.5505, -46.6333, -23.5614, -46.6558, "#0066FF")
ThreadPause(1000)

// Paulista ? Ibirapuera
gArcGIS.AdicionarRota(-23.5614, -46.6558, -23.5873, -46.6573, "#0066FF")
ThreadPause(1000)

// Ibirapuera ? Centro (volta)
gArcGIS.AdicionarRota(-23.5873, -46.6573, -23.5505, -46.6333, "#0066FF")

PRIVADO PROCEDIMENTO ExibirDetalhesRota()

sDetalhes é uma cadeia

sDetalhes = "??? DETALHES DA ROTA OTIMIZADA" + CR + CR +
"?? Pontos de parada:" + CR +
"1. Centro SP (início)" + CR +
"2. Av. Paulista" + CR +
"3. Parque Ibirapuera" + CR +
"4. Centro SP (fim)" + CR + CR +
"?? Estatísticas:" + CR +
"• Distância total: ~12.5 km" + CR +
"• Tempo estimado: ~35 min" + CR +
"• Paradas: 4 pontos" + CR +
"• Otimização: Ativada" + CR + CR +
"?? Rota otimizada para menor tempo de viagem"

Info(sDetalhes)

PRIVADO PROCEDIMENTO ExecutarAnaliseClustering(gArcGIS é um ArcGIS_WX_v100)

nInicio é um inteiro
nIDAnalise é um inteiro

Info("?? ANÁLISE 5: Clustering (Agrupamento)")
Info("Agrupando estabelecimentos por proximidade...")

nInicio = GetTickCount()

// Parâmetros para análise de clustering
sParametros é uma cadeia = '{"numberOfClusters": 3, "method": "kmeans", "distanceUnit": "meters"}'

// Executar análise
nIDAnalise = gArcGIS.ExecutarAnalise(ArcGIS_WX_v100.ANALISE_CLUSTERING, sParametros)

SE nIDAnalise > 0 ENTÃO
nTempo é um inteiro = GetTickCount() - nInicio
Info("? Análise de clustering executada (ID: " + nIDAnalise + ")")
Info("?? Tempo de execução: " + nTempo + "ms")

// Exibir resultados do clustering
ExibirResultadosClustering()
SENÃO
Info("? Erro na análise de clustering")
FIM

PRIVADO PROCEDIMENTO ExibirResultadosClustering()

sResultados é uma cadeia

sResultados = "?? RESULTADOS DO CLUSTERING" + CR + CR +
"?? Método: K-means" + CR +
"?? Número de clusters: 3" + CR + CR +
"?? Cluster 1 (Centro):" + CR +
"• Centro SP" + CR +
"• Shopping A" + CR +
"• Escola B" + CR + CR +
"?? Cluster 2 (Paulista):" + CR +
"• Av. Paulista" + CR +
"• Shopping B" + CR +
"• Hospital B" + CR + CR +
"?? Cluster 3 (Sul):" + CR +
"• Parque Ibirapuera" + CR +
"• Hospital A" + CR + CR +
"?? Agrupamento baseado em proximidade geográfica"

Info(sResultados)

PRIVADO PROCEDIMENTO GerarRelatorioAnalises()

sRelatorio é uma cadeia

sRelatorio = "?? RELATÓRIO FINAL DAS ANÁLISES GEOESPACIAIS" + CR + CR +
"? Análises executadas com sucesso:" + CR +
"1. ?? Buffer (Área de Influência) - 5 variações" + CR +
"2. ?? Proximidade - Raio de 2km" + CR +
"3. ?? Área de Serviço - 4 tempos diferentes" + CR +
"4. ??? Rota Otimizada - 4 pontos" + CR +
"5. ?? Clustering - 3 grupos" + CR + CR +
"?? Estatísticas gerais:" + CR +
"• Total de análises: 13" + CR +
"• Tempo total estimado: ~15 segundos" + CR +
"• Pontos analisados: 10" + CR +
"• Tipos de análise: 5" + CR + CR +
"?? Todas as análises geoespaciais foram concluídas!" + CR + CR +
"?? Aplicações práticas:" + CR +
"• Planejamento urbano" + CR +
"• Análise de mercado" + CR +
"• Otimização logística" + CR +
"• Estudos de acessibilidade" + CR +
"• Análise de concorrência"

Info(sRelatorio)

// ============================================================================
// TIPOS DE ANÁLISES GEOESPACIAIS IMPLEMENTADAS:
//
// 1. BUFFER (ÁREA DE INFLUÊNCIA)
// • Cria zonas ao redor de pontos
// • Útil para análise de impacto
// • Configurável por distância
//
// 2. PROXIMIDADE
// • Encontra pontos próximos
// • Análise de vizinhança
// • Configurável por raio
//
// 3. ÁREA DE SERVIÇO
// • Baseada em tempo de viagem
// • Considera tráfego atual
// • Útil para logística
//
// 4. ROTA OTIMIZADA
// • Múltiplos pontos de parada
// • Otimização automática
// • Menor tempo/distância
//
// 5. CLUSTERING
// • Agrupamento por proximidade
// • Algoritmo K-means
// • Identificação de padrões
//
// BENEFÍCIOS:
// • Decisões baseadas em dados
// • Análise científica de localização
// • Otimização de recursos
// • Planejamento estratégico
// • Redução de custos operacionais
// ============================================================================
```

---

## ?? **EXEMPLOS AVANÇADOS**

### **9. Integração com Banco de Dados**

```wlanguage
// ============================================================================
// EXEMPLO 9: Integração Completa com Banco de Dados
// Complexidade: ??? Avançado
// Tempo estimado: 60 minutos
// ============================================================================

// Estrutura para dados do banco
ESTRUTURA stEstabelecimentoBD
nID é um inteiro
sNome é uma cadeia
sDescricao é uma cadeia
nLatitude é um real
nLongitude é um real
sTipo é uma cadeia
sEndereco é uma cadeia
sTelefone é uma cadeia
sEmail é uma cadeia
bAtivo é um booleano
dtCriacao é um DateTime
dtUltimaAtualizacao é um DateTime
FIM

PROCEDIMENTO IntegracaoBancoDados()

gArcGIS é um ArcGIS_WX_v100
sAPIKey é uma cadeia = "SUA_ARCGIS_API_KEY"

TRY
// Inicializar mapa
gArcGIS = new ArcGIS_WX_v100(sAPIKey, HTMLControl1, ArcGIS_WX_v100.CONTROLE_HTML)
gArcGIS.InicializarMapa(-23.5505, -46.6333, 11)

ThreadPause(3000)

// CONFIGURAR BANCO DE DADOS
ConfigurarBancoDados()

// CARREGAR DADOS DO BANCO
CarregarEstabelecimentosBanco(gArcGIS)

// DEMONSTRAR SINCRONIZAÇÃO
DemonstrarSincronizacao(gArcGIS)

// OPERAÇÕES CRUD
DemonstrarOperacoesCRUD(gArcGIS)

// RELATÓRIOS E ESTATÍSTICAS
GerarRelatoriosBanco(gArcGIS)

EXCEPTION
Error("?? Erro na integração com banco: " + ExceptionInfo())
FIM

PRIVADO PROCEDIMENTO ConfigurarBancoDados()

Info("??? Configurando conexão com banco de dados...")

TRY
// Configurar conexão (exemplo com SQLite)
HChangeConnection("", "Provider=MSDASQL.1;Extended Properties=""DRIVER=SQLite3 ODBC Driver;Database=estabelecimentos.db""")

// Criar tabela se não existir
CriarTabelaEstabelecimentos()

// Popular com dados de exemplo se vazia
PopularDadosExemplo()

Info("? Banco de dados configurado com sucesso!")

EXCEPTION
Error("? Erro ao configurar banco: " + ExceptionInfo())
ExceptionPropage()
FIM

PRIVADO PROCEDIMENTO CriarTabelaEstabelecimentos()

sSQL é uma cadeia

sSQL = [
CREATE TABLE IF NOT EXISTS estabelecimentos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nome VARCHAR(100) NOT NULL,
descricao TEXT,
latitude REAL NOT NULL,
longitude REAL NOT NULL,
tipo VARCHAR(50) NOT NULL,
endereco VARCHAR(200),
telefone VARCHAR(20),
email VARCHAR(100),
ativo BOOLEAN DEFAULT 1,
dt_criacao DATETIME DEFAULT CURRENT_TIMESTAMP,
dt_ultima_atualizacao DATETIME DEFAULT CURRENT_TIMESTAMP
)
]

HExecuteSQL(sSQL)

PRIVADO PROCEDIMENTO PopularDadosExemplo()

// Verificar se já existem dados
HExecuteQuery(QRY_Count, "SELECT COUNT(*) as total FROM estabelecimentos")
HLitPremier(QRY_Count)

SE QRY_Count.total = 0 ENTÃO
Info("?? Populando banco com dados de exemplo...")

InserirEstabelecimento("Hospital das Clínicas", "Principal hospital público", -23.5558, -46.6696, "HOSPITAL", "Av. Dr. Enéas de Carvalho Aguiar, 255", "(11) 2661-0000", "contato@hc.fm.usp.br")
InserirEstabelecimento("Hospital Sírio-Libanês", "Hospital privado de referência", -23.5641, -46.6524, "HOSPITAL", "R. Dona Adma Jafet, 91", "(11) 3394-5000", "contato@hsl.org.br")
InserirEstabelecimento("USP - Cidade Universitária", "Universidade de São Paulo", -23.5558, -46.7319, "UNIVERSIDADE", "Av. Prof. Luciano Gualberto, 315", "(11) 3091-3116", "info@usp.br")
InserirEstabelecimento("Shopping Iguatemi", "Shopping center de luxo", -23.5761, -46.6886, "SHOPPING", "Av. Brigadeiro Faria Lima, 2232", "(11) 3816-6116", "sac@iguatemi.com.br")
InserirEstabelecimento("Parque Ibirapuera", "Principal parque urbano", -23.5873, -46.6573, "PARQUE", "Av. Paulista, s/n", "(11) 5574-5045", "parque@ibirapuera.org")
InserirEstabelecimento("Mercado Municipal", "Mercado tradicional paulistano", -23.5475, -46.6297, "MERCADO", "R. da Cantareira, 306", "(11) 3313-3365", "mercado@prefeitura.sp.gov.br")
InserirEstabelecimento("Teatro Municipal", "Teatro histórico", -23.5450, -46.6364, "TEATRO", "Praça Ramos de Azevedo, s/n", "(11) 3397-0300", "teatro@prefeitura.sp.gov.br")
InserirEstabelecimento("Estação da Luz", "Estação ferroviária histórica", -23.5356, -46.6356, "TRANSPORTE", "Praça da Luz, 1", "(11) 3326-0000", "luz@cptm.sp.gov.br")

Info("? Dados de exemplo inseridos!")
FIM

PRIVADO PROCEDIMENTO InserirEstabelecimento(sNome é uma cadeia, sDescricao é uma cadeia, nLat é um real, nLng é um real, sTipo é uma cadeia, sEndereco é uma cadeia, sTelefone é uma cadeia, sEmail é uma cadeia)

sSQL é uma cadeia

sSQL = "INSERT INTO estabelecimentos (nome, descricao, latitude, longitude, tipo, endereco, telefone, email) " +
"VALUES ('" + sNome + "', '" + sDescricao + "', " + nLat + ", " + nLng + ", '" + sTipo + "', '" + sEndereco + "', '" + sTelefone + "', '" + sEmail + "')"

HExecuteSQL(sSQL)

PRIVADO PROCEDIMENTO CarregarEstabelecimentosBanco(gArcGIS é um ArcGIS_WX_v100)

sSQL é uma cadeia
nContador é um inteiro = 0
nErros é um inteiro = 0

Info("?? Carregando estabelecimentos do banco de dados...")

TRY
// Consulta otimizada
sSQL = "SELECT id, nome, descricao, latitude, longitude, tipo, endereco, telefone, email, ativo " +
"FROM estabelecimentos " +
"WHERE ativo = 1 " +
"ORDER BY tipo, nome"

HExecuteQuery(QRY_Estabelecimentos, sSQL)

// Processar resultados
ENQUANTO HLitSuivant(QRY_Estabelecimentos)
TRY
// Determinar símbolo e cor por tipo
sSimbolo é uma cadeia
sCor é uma cadeia
ObterSimboloCorPorTipo(QRY_Estabelecimentos.tipo, sSimbolo, sCor)

// Criar descrição completa
sDescricaoCompleta é uma cadeia = QRY_Estabelecimentos.descricao + CR +
"?? " + QRY_Estabelecimentos.endereco + CR +
"?? " + QRY_Estabelecimentos.telefone + CR +
"?? " + QRY_Estabelecimentos.email

// Adicionar marcador
nIDMarcador é um inteiro = gArcGIS.AdicionarMarcador(
QRY_Estabelecimentos.latitude,
QRY_Estabelecimentos.longitude,
QRY_Estabelecimentos.nome,
sDescricaoCompleta,
sSimbolo,
sCor
)

SE nIDMarcador > 0 ENTÃO
nContador++

// Associar ID do banco com ID do marcador
AssociarIDBanco(nIDMarcador, QRY_Estabelecimentos.id)
SENÃO
nErros++
FIM

// Pausa para não sobrecarregar
SE nContador % 10 = 0 ENTÃO
ThreadPause(100)
FIM

EXCEPTION
nErros++
Trace("Erro ao processar estabelecimento ID " + QRY_Estabelecimentos.id + ": " + ExceptionInfo())
FIM
FIM

// Relatório de carregamento
sRelatorio é uma cadeia = "?? CARREGAMENTO CONCLUÍDO" + CR + CR +
"? Carregados: " + nContador + " estabelecimentos" + CR +
"? Erros: " + nErros + CR +
"?? Total no mapa: " + gArcGIS.ObterTotalMarcadores()

Info(sRelatorio)

EXCEPTION
Error("? Erro ao carregar do banco: " + ExceptionInfo())
FIM

PRIVADO PROCEDIMENTO ObterSimboloCorPorTipo(sTipo é uma cadeia, sSimbolo é uma cadeia, sCor é uma cadeia)

CONFORME Upper(sTipo)
CASO "HOSPITAL":
sSimbolo = ArcGIS_WX_v100.SIMBOLO_CROSS
sCor = "#FF0000"
CASO "UNIVERSIDADE", "ESCOLA":
sSimbolo = ArcGIS_WX_v100.SIMBOLO_SQUARE
sCor = "#00FF00"
CASO "SHOPPING", "MERCADO":
sSimbolo = ArcGIS_WX_v100.SIMBOLO_DIAMOND
sCor = "#0000FF"
CASO "PARQUE":
sSimbolo = ArcGIS_WX_v100.SIMBOLO_CIRCLE
sCor = "#00AA00"
CASO "TEATRO", "CULTURA":
sSimbolo = ArcGIS_WX_v100.SIMBOLO_TRIANGLE
sCor = "#800080"
CASO "TRANSPORTE":
sSimbolo = ArcGIS_WX_v100.SIMBOLO_X
sCor = "#FF6600"
PADRÃO:
sSimbolo = ArcGIS_WX_v100.SIMBOLO_CIRCLE
sCor = "#808080"
FIM

// Array para associação ID Banco ? ID Marcador
m_arrAssociacaoIDs é um array de estrutura
nIDMarcador é um inteiro
nIDBanco é um inteiro
FIM

PRIVADO PROCEDIMENTO AssociarIDBanco(nIDMarcador é um inteiro, nIDBanco é um inteiro)

stAssociacao é uma estrutura
stAssociacao.nIDMarcador = nIDMarcador
stAssociacao.nIDBanco = nIDBanco

ArrayAdd(m_arrAssociacaoIDs, stAssociacao)

PRIVADO PROCEDIMENTO DemonstrarSincronizacao(gArcGIS é um ArcGIS_WX_v100)

Info("?? Demonstrando sincronização bidirecional...")

// 1. ADICIONAR NOVO ESTABELECIMENTO NO BANCO
Info("? Adicionando novo estabelecimento no banco...")

nNovoID é um inteiro = InserirNovoEstabelecimento("Novo Shopping", "Shopping recém inaugurado", -23.5600, -46.6400, "SHOPPING", "Rua Nova, 123", "(11) 9999-9999", "novo@shopping.com")

SE nNovoID > 0 ENTÃO
// Adicionar no mapa também
nIDMarcador é um inteiro = gArcGIS.AdicionarMarcador(-23.5600, -46.6400, "Novo Shopping", "Shopping recém inaugurado", ArcGIS_WX_v100.SIMBOLO_DIAMOND, "#0000FF")

SE nIDMarcador > 0 ENTÃO
AssociarIDBanco(nIDMarcador, nNovoID)
Info("? Novo estabelecimento sincronizado (Banco ID: " + nNovoID + ", Mapa ID: " + nIDMarcador + ")")
FIM
FIM

ThreadPause(2000)

// 2. ATUALIZAR ESTABELECIMENTO EXISTENTE
Info("?? Atualizando estabelecimento existente...")

AtualizarEstabelecimento(nNovoID, "Novo Shopping Premium", "Shopping premium recém inaugurado")
Info("? Estabelecimento atualizado no banco")

ThreadPause(2000)

// 3. SINCRONIZAÇÃO AUTOMÁTICA
Info("?? Executando sincronização automática...")
SincronizarMapaComBanco(gArcGIS)

PRIVADO PROCEDIMENTO InserirNovoEstabelecimento(sNome é uma cadeia, sDescricao é uma cadeia, nLat é um real, nLng é um real, sTipo é uma cadeia, sEndereco é uma cadeia, sTelefone é uma cadeia, sEmail é uma cadeia) : inteiro

sSQL é uma cadeia

TRY
sSQL = "INSERT INTO estabelecimentos (nome, descricao, latitude, longitude, tipo, endereco, telefone, email) " +
"VALUES ('" + sNome + "', '" + sDescricao + "', " + nLat + ", " + nLng + ", '" + sTipo + "', '" + sEndereco + "', '" + sTelefone + "', '" + sEmail + "')"

HExecuteSQL(sSQL)

// Obter ID do registro inserido
HExecuteQuery(QRY_LastID, "SELECT last_insert_rowid() as ultimo_id")
HLitPremier(QRY_LastID)

RETORNO QRY_LastID.ultimo_id

EXCEPTION
Trace("Erro ao inserir estabelecimento: " + ExceptionInfo())
RETORNO -1
FIM

PRIVADO PROCEDIMENTO AtualizarEstabelecimento(nID é um inteiro, sNovoNome é uma cadeia, sNovaDescricao é uma cadeia)

sSQL é uma cadeia

sSQL = "UPDATE estabelecimentos SET " +
"nome = '" + sNovoNome + "', " +
"descricao = '" + sNovaDescricao + "', " +
"dt_ultima_atualizacao = CURRENT_TIMESTAMP " +
"WHERE id = " + nID

HExecuteSQL(sSQL)

PRIVADO PROCEDIMENTO SincronizarMapaComBanco(gArcGIS é um ArcGIS_WX_v100)

sSQL é uma cadeia
nSincronizados é um inteiro = 0

Info("?? Sincronizando alterações do banco com o mapa...")

// Buscar registros alterados recentemente (últimos 5 minutos)
sSQL = "SELECT id, nome, descricao, latitude, longitude, tipo " +
"FROM estabelecimentos " +
"WHERE dt_ultima_atualizacao >= datetime('now', '-5 minutes') " +
"AND ativo = 1"

HExecuteQuery(QRY_Alterados, sSQL)

ENQUANTO HLitSuivant(QRY_Alterados)
// Encontrar marcador correspondente
nIDMarcador é um inteiro = EncontrarMarcadorPorIDBanco(QRY_Alterados.id)

SE nIDMarcador > 0 ENTÃO
// Atualizar marcador existente (simulado - ArcGIS não tem update direto)
Info("?? Sincronizando: " + QRY_Alterados.nome)
nSincronizados++
FIM
FIM

Info("? Sincronização concluída: " + nSincronizados + " registros processados")

PRIVADO PROCEDIMENTO EncontrarMarcadorPorIDBanco(nIDBanco é um inteiro) : inteiro

PARA i = 1 À ArrayCount(m_arrAssociacaoIDs)
SE m_arrAssociacaoIDs[i].nIDBanco = nIDBanco ENTÃO
RETORNO m_arrAssociacaoIDs[i].nIDMarcador
FIM
FIM

RETORNO -1

PRIVADO PROCEDIMENTO DemonstrarOperacoesCRUD(gArcGIS é um ArcGIS_WX_v100)

Info("?? Demonstrando operações CRUD...")

// CREATE
Info("? CREATE: Criando novo estabelecimento...")
nNovoID é um inteiro = CriarEstabelecimento("Farmácia 24h", "Farmácia que funciona 24 horas", -23.5550, -46.6450, "FARMACIA")

// READ
Info("??? READ: Consultando estabelecimento...")
stEstab é um stEstabelecimentoBD = ConsultarEstabelecimento(nNovoID)
SE stEstab.nID > 0 ENTÃO
Info("? Estabelecimento encontrado: " + stEstab.sNome)
FIM

// UPDATE
Info("?? UPDATE: Atualizando estabelecimento...")
AtualizarEstabelecimentoCompleto(nNovoID, "Farmácia 24h Premium", "Farmácia premium 24 horas com delivery")

// DELETE (soft delete)
Info("??? DELETE: Desativando estabelecimento...")
DesativarEstabelecimento(nNovoID)

Info("? Operações CRUD demonstradas com sucesso!")

PRIVADO PROCEDIMENTO CriarEstabelecimento(sNome é uma cadeia, sDescricao é uma cadeia, nLat é um real, nLng é um real, sTipo é uma cadeia) : inteiro

RETORNO InserirNovoEstabelecimento(sNome, sDescricao, nLat, nLng, sTipo, "Endereço não informado", "Telefone não informado", "email@nao.informado")

PRIVADO PROCEDIMENTO ConsultarEstabelecimento(nID é um inteiro) : stEstabelecimentoBD

stEstab é um stEstabelecimentoBD
sSQL é uma cadeia

sSQL = "SELECT * FROM estabelecimentos WHERE id = " + nID
HExecuteQuery(QRY_Consulta, sSQL)

SE HLitPremier(QRY_Consulta) ENTÃO
stEstab.nID = QRY_Consulta.id
stEstab.sNome = QRY_Consulta.nome
stEstab.sDescricao = QRY_Consulta.descricao
stEstab.nLatitude = QRY_Consulta.latitude
stEstab.nLongitude = QRY_Consulta.longitude
stEstab.sTipo = QRY_Consulta.tipo
stEstab.sEndereco = QRY_Consulta.endereco
stEstab.sTelefone = QRY_Consulta.telefone
stEstab.sEmail = QRY_Consulta.email
stEstab.bAtivo = QRY_Consulta.ativo
FIM

RETORNO stEstab

PRIVADO PROCEDIMENTO AtualizarEstabelecimentoCompleto(nID é um inteiro, sNome é uma cadeia, sDescricao é uma cadeia)

sSQL é uma cadeia

sSQL = "UPDATE estabelecimentos SET " +
"nome = '" + sNome + "', " +
"descricao = '" + sDescricao + "', " +
"dt_ultima_atualizacao = CURRENT_TIMESTAMP " +
"WHERE id = " + nID

HExecuteSQL(sSQL)

PRIVADO PROCEDIMENTO DesativarEstabelecimento(nID é um inteiro)

sSQL é uma cadeia

sSQL = "UPDATE estabelecimentos SET " +
"ativo = 0, " +
"dt_ultima_atualizacao = CURRENT_TIMESTAMP " +
"WHERE id = " + nID

HExecuteSQL(sSQL)

PRIVADO PROCEDIMENTO GerarRelatoriosBanco(gArcGIS é um ArcGIS_WX_v100)

Info("?? Gerando relatórios e estatísticas...")

// Relatório por tipo
GerarRelatorioPorTipo()

// Estatísticas gerais
GerarEstatisticasGerais(gArcGIS)

// Relatório de atividade
GerarRelatorioAtividade()

PRIVADO PROCEDIMENTO GerarRelatorioPorTipo()

sSQL é uma cadeia
sRelatorio é uma cadeia

sSQL = "SELECT tipo, COUNT(*) as quantidade FROM estabelecimentos WHERE ativo = 1 GROUP BY tipo ORDER BY quantidade DESC"

HExecuteQuery(QRY_Tipos, sSQL)

sRelatorio = "?? RELATÓRIO POR TIPO DE ESTABELECIMENTO" + CR + CR

ENQUANTO HLitSuivant(QRY_Tipos)
sRelatorio += "• " + QRY_Tipos.tipo + ": " + QRY_Tipos.quantidade + " estabelecimentos" + CR
FIM

Info(sRelatorio)

PRIVADO PROCEDIMENTO GerarEstatisticasGerais(gArcGIS é um ArcGIS_WX_v100)

sSQL é uma cadeia
sRelatorio é uma cadeia

// Total de registros
HExecuteQuery(QRY_Total, "SELECT COUNT(*) as total FROM estabelecimentos")
HLitPremier(QRY_Total)

// Registros ativos
HExecuteQuery(QRY_Ativos, "SELECT COUNT(*) as ativos FROM estabelecimentos WHERE ativo = 1")
HLitPremier(QRY_Ativos)

// Registros inativos
HExecuteQuery(QRY_Inativos, "SELECT COUNT(*) as inativos FROM estabelecimentos WHERE ativo = 0")
HLitPremier(QRY_Inativos)

sRelatorio = "?? ESTATÍSTICAS GERAIS" + CR + CR +
"??? Total no banco: " + QRY_Total.total + " registros" + CR +
"? Ativos: " + QRY_Ativos.ativos + " registros" + CR +
"? Inativos: " + QRY_Inativos.inativos + " registros" + CR +
"??? No mapa: " + gArcGIS.ObterTotalMarcadores() + " marcadores" + CR + CR +
"?? Sincronização: " + (QRY_Ativos.ativos = gArcGIS.ObterTotalMarcadores() ? "? OK" : "?? Divergência")

Info(sRelatorio)

PRIVADO PROCEDIMENTO GerarRelatorioAtividade()

sSQL é uma cadeia
sRelatorio é uma cadeia

// Registros criados hoje
sSQL = "SELECT COUNT(*) as hoje FROM estabelecimentos WHERE DATE(dt_criacao) = DATE('now')"
HExecuteQuery(QRY_Hoje, sSQL)
HLitPremier(QRY_Hoje)

// Registros atualizados hoje
sSQL = "SELECT COUNT(*) as atualizados FROM estabelecimentos WHERE DATE(dt_ultima_atualizacao) = DATE('now')"
HExecuteQuery(QRY_Atualizados, sSQL)
HLitPremier(QRY_Atualizados)

sRelatorio = "?? RELATÓRIO DE ATIVIDADE (HOJE)" + CR + CR +
"? Criados: " + QRY_Hoje.hoje + " registros" + CR +
"?? Atualizados: " + QRY_Atualizados.atualizados + " registros" + CR + CR +
"?? Sistema de integração funcionando corretamente!"

Info(sRelatorio)

// ============================================================================
// BENEFÍCIOS DA INTEGRAÇÃO COM BANCO DE DADOS:
//
// 1. PERSISTÊNCIA DE DADOS
// • Dados mantidos entre sessões
// • Backup automático
// • Histórico de alterações
//
// 2. PERFORMANCE
// • Consultas otimizadas
// • Índices para busca rápida
// • Carregamento sob demanda
//
// 3. SINCRONIZAÇÃO
// • Dados sempre atualizados
// • Múltiplos usuários
// • Controle de concorrência
//
// 4. RELATÓRIOS
// • Estatísticas em tempo real
// • Análises históricas
// • Dashboards dinâmicos
//
// 5. ESCALABILIDADE
// • Milhares de registros
// • Múltiplas tabelas
// • Relacionamentos complexos
//
// EXTENSÕES POSSÍVEIS:
// • Auditoria de alterações
// • Versionamento de dados
// • Replicação entre servidores
// • API REST para integração
// • Cache distribuído
// • Backup automático
// ============================================================================
```

Vou continuar com mais exemplos avançados na próxima parte...




### **10. Monitoramento em Tempo Real**

```wlanguage
// ============================================================================
// EXEMPLO 10: Monitoramento em Tempo Real de Veículos
// Complexidade: ??? Avançado
// Tempo estimado: 90 minutos
// ============================================================================

// Estrutura para veículo em tempo real
ESTRUTURA stVeiculoTempo
sID é uma cadeia
sPlaca é uma cadeia
sMotorista é uma cadeia
nLatitude é um real
nLongitude é um real
nVelocidade é um real
nDirecao é um real
sStatus é uma cadeia
dtUltimaAtualizacao é um DateTime
nIDMarcador é um inteiro
bOnline é um booleano
FIM

// Array global de veículos
m_arrVeiculos é um array de stVeiculoTempo

PROCEDIMENTO MonitoramentoTempoReal()

gArcGIS é um ArcGIS_WX_v100
sAPIKey é uma cadeia = "SUA_ARCGIS_API_KEY"

TRY
// Inicializar mapa
gArcGIS = new ArcGIS_WX_v100(sAPIKey, HTMLControl1, ArcGIS_WX_v100.CONTROLE_HTML)
gArcGIS.InicializarMapa(-23.5505, -46.6333, 11)

ThreadPause(3000)

// CONFIGURAR SISTEMA DE MONITORAMENTO
ConfigurarSistemaMonitoramento()

// INICIALIZAR FROTA DE VEÍCULOS
InicializarFrotaVeiculos(gArcGIS)

// INICIAR MONITORAMENTO EM TEMPO REAL
IniciarMonitoramentoTempoReal(gArcGIS)

// DEMONSTRAR ALERTAS E NOTIFICAÇÕES
DemonstrarAlertas(gArcGIS)

// RELATÓRIOS EM TEMPO REAL
GerarRelatoriosTempoReal()

EXCEPTION
Error("?? Erro no monitoramento em tempo real: " + ExceptionInfo())
FIM

PRIVADO PROCEDIMENTO ConfigurarSistemaMonitoramento()

Info("?? Configurando sistema de monitoramento em tempo real...")

// Configurações do sistema
m_nIntervaloAtualizacao é um inteiro = 5000 // 5 segundos
m_nLimiteVelocidade é um real = 80.0 // 80 km/h
m_nTempoOfflineMax é um inteiro = 30000 // 30 segundos

// Inicializar arrays
ArrayDeleteAll(m_arrVeiculos)

Info("? Sistema configurado com sucesso!")

PRIVADO PROCEDIMENTO InicializarFrotaVeiculos(gArcGIS é um ArcGIS_WX_v100)

Info("?? Inicializando frota de veículos...")

// Veículo 1: Caminhão de entrega
CriarVeiculo("VEI001", "ABC-1234", "João Silva", -23.5505, -46.6333, 45.0, 90, "EM_ROTA")

// Veículo 2: Van de serviços
CriarVeiculo("VEI002", "DEF-5678", "Maria Santos", -23.5614, -46.6558, 30.0, 180, "PARADO")

// Veículo 3: Carro executivo
CriarVeiculo("VEI003", "GHI-9012", "Pedro Costa", -23.5873, -46.6573, 60.0, 270, "EM_ROTA")

// Veículo 4: Moto entregador
CriarVeiculo("VEI004", "JKL-3456", "Ana Oliveira", -23.5400, -46.6200, 25.0, 45, "DISPONIVEL")

// Veículo 5: Caminhão pesado
CriarVeiculo("VEI005", "MNO-7890", "Carlos Ferreira", -23.5700, -46.6800, 55.0, 315, "CARREGANDO")

// Adicionar todos os veículos no mapa
PARA i = 1 À ArrayCount(m_arrVeiculos)
AdicionarVeiculoMapa(gArcGIS, m_arrVeiculos[i])
FIM

Info("? Frota inicializada: " + ArrayCount(m_arrVeiculos) + " veículos")

PRIVADO PROCEDIMENTO CriarVeiculo(sID é uma cadeia, sPlaca é uma cadeia, sMotorista é uma cadeia, nLat é um real, nLng é um real, nVel é um real, nDir é um real, sStatus é uma cadeia)

stVeiculo é um stVeiculoTempo

stVeiculo.sID = sID
stVeiculo.sPlaca = sPlaca
stVeiculo.sMotorista = sMotorista
stVeiculo.nLatitude = nLat
stVeiculo.nLongitude = nLng
stVeiculo.nVelocidade = nVel
stVeiculo.nDirecao = nDir
stVeiculo.sStatus = sStatus
stVeiculo.dtUltimaAtualizacao = DateTimeSys()
stVeiculo.nIDMarcador = 0
stVeiculo.bOnline = Verdadeiro

ArrayAdd(m_arrVeiculos, stVeiculo)

PRIVADO PROCEDIMENTO AdicionarVeiculoMapa(gArcGIS é um ArcGIS_WX_v100, stVeiculo é um stVeiculoTempo)

sTitulo é uma cadeia
sDescricao é uma cadeia
sCor é uma cadeia

// Título do marcador
sTitulo = stVeiculo.sPlaca + " (" + stVeiculo.sID + ")"

// Descrição detalhada
sDescricao = "?? Motorista: " + stVeiculo.sMotorista + CR +
"?? Status: " + stVeiculo.sStatus + CR +
"?? Velocidade: " + NumToString(stVeiculo.nVelocidade, "0.1f") + " km/h" + CR +
"?? Direção: " + NumToString(stVeiculo.nDirecao, "0.0f") + "°" + CR +
"? Última atualização: " + DateTimeToString(stVeiculo.dtUltimaAtualizacao, "DD/MM/YYYY HH:MM:SS")

// Cor baseada no status
sCor = ObterCorPorStatus(stVeiculo.sStatus)

// Adicionar marcador
nIDMarcador é um inteiro = gArcGIS.AdicionarMarcador(
stVeiculo.nLatitude,
stVeiculo.nLongitude,
sTitulo,
sDescricao,
ArcGIS_WX_v100.SIMBOLO_TRIANGLE,
sCor
)

// Atualizar ID do marcador no veículo
SE nIDMarcador > 0 ENTÃO
PARA i = 1 À ArrayCount(m_arrVeiculos)
SE m_arrVeiculos[i].sID = stVeiculo.sID ENTÃO
m_arrVeiculos[i].nIDMarcador = nIDMarcador
QUEBRAR
FIM
FIM
FIM

PRIVADO PROCEDIMENTO ObterCorPorStatus(sStatus é uma cadeia) : cadeia

CONFORME Upper(sStatus)
CASO "EM_ROTA":
RETORNO "#00FF00" // Verde
CASO "PARADO":
RETORNO "#FFFF00" // Amarelo
CASO "DISPONIVEL":
RETORNO "#0000FF" // Azul
CASO "CARREGANDO":
RETORNO "#FF6600" // Laranja
CASO "MANUTENCAO":
RETORNO "#FF0000" // Vermelho
CASO "OFFLINE":
RETORNO "#808080" // Cinza
PADRÃO:
RETORNO "#800080" // Roxo
FIM

PRIVADO PROCEDIMENTO IniciarMonitoramentoTempoReal(gArcGIS é um ArcGIS_WX_v100)

Info("?? Iniciando monitoramento em tempo real...")
Info("?? Intervalo de atualização: 5 segundos")
Info("?? Simulando recebimento de dados GPS...")

// Simular 30 segundos de monitoramento
PARA nCiclo = 1 À 6 // 6 ciclos de 5 segundos = 30 segundos
Info("?? Ciclo " + nCiclo + "/6 - Atualizando posições...")

// Atualizar cada veículo
PARA i = 1 À ArrayCount(m_arrVeiculos)
AtualizarPosicaoVeiculo(gArcGIS, i)
FIM

// Verificar alertas
VerificarAlertas()

// Aguardar próximo ciclo
ThreadPause(5000)
FIM

Info("? Demonstração de monitoramento concluída!")

PRIVADO PROCEDIMENTO AtualizarPosicaoVeiculo(gArcGIS é um ArcGIS_WX_v100, nIndice é um inteiro)

stVeiculo é um stVeiculoTempo = m_arrVeiculos[nIndice]

// Simular movimento do veículo
nDeltaLat é um real = (Random(200) - 100) / 100000.0 // ±0.001 graus
nDeltaLng é um real = (Random(200) - 100) / 100000.0 // ±0.001 graus

// Atualizar posição
stVeiculo.nLatitude += nDeltaLat
stVeiculo.nLongitude += nDeltaLng

// Simular mudança de velocidade
nDeltaVel é um real = (Random(20) - 10) // ±10 km/h
stVeiculo.nVelocidade = Max(0, Min(120, stVeiculo.nVelocidade + nDeltaVel))

// Simular mudança de direção
nDeltaDir é um real = (Random(60) - 30) // ±30 graus
stVeiculo.nDirecao = (stVeiculo.nDirecao + nDeltaDir + 360) % 360

// Atualizar timestamp
stVeiculo.dtUltimaAtualizacao = DateTimeSys()

// Simular mudança de status ocasional
SE Random(100) < 10 ENTÃO // 10% de chance
stVeiculo.sStatus = SimularMudancaStatus(stVeiculo.sStatus)
FIM

// Atualizar no array
m_arrVeiculos[nIndice] = stVeiculo

// Atualizar marcador no mapa (simulado - removendo e adicionando)
// Em implementação real, usaria método de atualização específico
SE stVeiculo.nIDMarcador > 0 ENTÃO
// Simular atualização do marcador
Trace("Atualizando veículo " + stVeiculo.sID + " para posição " +
NumToString(stVeiculo.nLatitude, "0.4f") + ", " +
NumToString(stVeiculo.nLongitude, "0.4f"))
FIM

PRIVADO PROCEDIMENTO SimularMudancaStatus(sStatusAtual é uma cadeia) : cadeia

arrStatus é um array de cadeia

ArrayAdd(arrStatus, "EM_ROTA")
ArrayAdd(arrStatus, "PARADO")
ArrayAdd(arrStatus, "DISPONIVEL")
ArrayAdd(arrStatus, "CARREGANDO")

nIndiceAleatorio é um inteiro = Random(ArrayCount(arrStatus)) + 1
RETORNO arrStatus[nIndiceAleatorio]

PRIVADO PROCEDIMENTO VerificarAlertas()

nAlertasVelocidade é um inteiro = 0
nAlertasOffline é um inteiro = 0
dtAgora é um DateTime = DateTimeSys()

PARA i = 1 À ArrayCount(m_arrVeiculos)
stVeiculo é um stVeiculoTempo = m_arrVeiculos[i]

// Alerta de velocidade
SE stVeiculo.nVelocidade > m_nLimiteVelocidade ENTÃO
nAlertasVelocidade++
GerarAlertaVelocidade(stVeiculo)
FIM

// Alerta de veículo offline
nTempoSemAtualizacao é um inteiro = DateTimeDifference(dtAgora, stVeiculo.dtUltimaAtualizacao, "ms")
SE nTempoSemAtualizacao > m_nTempoOfflineMax ENTÃO
nAlertasOffline++
GerarAlertaOffline(stVeiculo)
FIM
FIM

SE nAlertasVelocidade > 0 OU nAlertasOffline > 0 ENTÃO
sResumo é uma cadeia = "?? ALERTAS DETECTADOS:" + CR +
"?? Excesso de velocidade: " + nAlertasVelocidade + CR +
"?? Veículos offline: " + nAlertasOffline
Trace(sResumo)
FIM

PRIVADO PROCEDIMENTO GerarAlertaVelocidade(stVeiculo é um stVeiculoTempo)

sAlerta é uma cadeia = "?? ALERTA DE VELOCIDADE" + CR +
"?? Veículo: " + stVeiculo.sPlaca + CR +
"?? Motorista: " + stVeiculo.sMotorista + CR +
"?? Velocidade atual: " + NumToString(stVeiculo.nVelocidade, "0.1f") + " km/h" + CR +
"?? Limite: " + NumToString(m_nLimiteVelocidade, "0.1f") + " km/h"

Trace(sAlerta)

PRIVADO PROCEDIMENTO GerarAlertaOffline(stVeiculo é um stVeiculoTempo)

sAlerta é uma cadeia = "?? ALERTA DE COMUNICAÇÃO" + CR +
"?? Veículo: " + stVeiculo.sPlaca + CR +
"?? Motorista: " + stVeiculo.sMotorista + CR +
"? Última comunicação: " + DateTimeToString(stVeiculo.dtUltimaAtualizacao, "HH:MM:SS") + CR +
"?? Status: OFFLINE"

Trace(sAlerta)

PRIVADO PROCEDIMENTO DemonstrarAlertas(gArcGIS é um ArcGIS_WX_v100)

Info("?? Demonstrando sistema de alertas...")

// Simular situação de emergência
Info("?? Simulando situação de emergência...")

// Veículo com excesso de velocidade
m_arrVeiculos[1].nVelocidade = 95.0
GerarAlertaVelocidade(m_arrVeiculos[1])

ThreadPause(2000)

// Veículo offline
m_arrVeiculos[2].dtUltimaAtualizacao = DateTimeAdd(DateTimeSys(), -60, "s")
GerarAlertaOffline(m_arrVeiculos[2])

ThreadPause(2000)

// Alerta de zona restrita (simulado)
Info("?? Alerta: Veículo " + m_arrVeiculos[3].sPlaca + " entrou em zona restrita!")

ThreadPause(2000)

// Alerta de manutenção programada
Info("?? Lembrete: Veículo " + m_arrVeiculos[4].sPlaca + " precisa de manutenção em 500km")

PRIVADO PROCEDIMENTO GerarRelatoriosTempoReal()

Info("?? Gerando relatórios em tempo real...")

// Relatório de status da frota
GerarRelatorioStatusFrota()

// Relatório de performance
GerarRelatorioPerformance()

// Relatório de alertas
GerarRelatorioAlertas()

PRIVADO PROCEDIMENTO GerarRelatorioStatusFrota()

nEmRota é um inteiro = 0
nParados é um inteiro = 0
nDisponiveis é um inteiro = 0
nCarregando é um inteiro = 0
nOffline é um inteiro = 0

PARA i = 1 À ArrayCount(m_arrVeiculos)
CONFORME Upper(m_arrVeiculos[i].sStatus)
CASO "EM_ROTA":
nEmRota++
CASO "PARADO":
nParados++
CASO "DISPONIVEL":
nDisponiveis++
CASO "CARREGANDO":
nCarregando++
CASO "OFFLINE":
nOffline++
FIM
FIM

sRelatorio é uma cadeia = "?? STATUS DA FROTA EM TEMPO REAL" + CR + CR +
"?? Total de veículos: " + ArrayCount(m_arrVeiculos) + CR +
"?? Em rota: " + nEmRota + CR +
"?? Parados: " + nParados + CR +
"?? Disponíveis: " + nDisponiveis + CR +
"?? Carregando: " + nCarregando + CR +
"?? Offline: " + nOffline + CR + CR +
"?? Taxa de disponibilidade: " + NumToString((ArrayCount(m_arrVeiculos) - nOffline) * 100.0 / ArrayCount(m_arrVeiculos), "0.1f") + "%"

Info(sRelatorio)

PRIVADO PROCEDIMENTO GerarRelatorioPerformance()

nVelocidadeMedia é um real = 0
nVelocidadeMax é um real = 0
nVeiculosAtivos é um inteiro = 0

PARA i = 1 À ArrayCount(m_arrVeiculos)
SE m_arrVeiculos[i].sStatus <> "OFFLINE" ENTÃO
nVeiculosAtivos++
nVelocidadeMedia += m_arrVeiculos[i].nVelocidade
nVelocidadeMax = Max(nVelocidadeMax, m_arrVeiculos[i].nVelocidade)
FIM
FIM

SE nVeiculosAtivos > 0 ENTÃO
nVelocidadeMedia = nVelocidadeMedia / nVeiculosAtivos
FIM

sRelatorio é uma cadeia = "? PERFORMANCE DA FROTA" + CR + CR +
"?? Velocidade média: " + NumToString(nVelocidadeMedia, "0.1f") + " km/h" + CR +
"?? Velocidade máxima: " + NumToString(nVelocidadeMax, "0.1f") + " km/h" + CR +
"?? Veículos ativos: " + nVeiculosAtivos + "/" + ArrayCount(m_arrVeiculos) + CR +
"?? Limite de velocidade: " + NumToString(m_nLimiteVelocidade, "0.1f") + " km/h"

Info(sRelatorio)

PRIVADO PROCEDIMENTO GerarRelatorioAlertas()

nAlertasTotal é um inteiro = 0
nAlertasVelocidade é um inteiro = 0
nAlertasOffline é um inteiro = 0

PARA i = 1 À ArrayCount(m_arrVeiculos)
// Contar alertas de velocidade
SE m_arrVeiculos[i].nVelocidade > m_nLimiteVelocidade ENTÃO
nAlertasVelocidade++
nAlertasTotal++
FIM

// Contar alertas offline
nTempoSemAtualizacao é um inteiro = DateTimeDifference(DateTimeSys(), m_arrVeiculos[i].dtUltimaAtualizacao, "s")
SE nTempoSemAtualizacao > 30 ENTÃO
nAlertasOffline++
nAlertasTotal++
FIM
FIM

sRelatorio é uma cadeia = "?? RELATÓRIO DE ALERTAS" + CR + CR +
"?? Total de alertas ativos: " + nAlertasTotal + CR +
"?? Excesso de velocidade: " + nAlertasVelocidade + CR +
"?? Comunicação perdida: " + nAlertasOffline + CR + CR +
"?? Status: " + (nAlertasTotal = 0 ? "? Tudo OK" : "?? Atenção necessária")

Info(sRelatorio)

// ============================================================================
// FUNCIONALIDADES DO MONITORAMENTO EM TEMPO REAL:
//
// 1. RASTREAMENTO GPS
// • Posição em tempo real
// • Velocidade e direção
// • Histórico de movimento
//
// 2. ALERTAS AUTOMÁTICOS
// • Excesso de velocidade
// • Veículos offline
// • Zonas restritas
// • Manutenção programada
//
// 3. RELATÓRIOS DINÂMICOS
// • Status da frota
// • Performance em tempo real
// • Estatísticas de alertas
//
// 4. VISUALIZAÇÃO NO MAPA
// • Marcadores coloridos por status
// • Informações detalhadas
// • Atualização automática
//
// APLICAÇÕES PRÁTICAS:
// • Gestão de frotas
// • Logística e entregas
// • Transporte público
// • Serviços de emergência
// • Monitoramento de ativos
// ============================================================================
```

### **11. Feature Layers Corporativos**

```wlanguage
// ============================================================================
// EXEMPLO 11: Feature Layers Corporativos
// Complexidade: ??? Avançado
// Tempo estimado: 75 minutos
// ============================================================================

// Estrutura para configuração de Feature Layer
ESTRUTURA stFeatureLayerConfig
sNome é uma cadeia
sURL é uma cadeia
sTipo é uma cadeia
bVisivel é um booleano
nOpacidade é um real
sEstilo é uma cadeia
arrCampos é um array de cadeia
FIM

PROCEDIMENTO FeatureLayersCorporativos()

gArcGIS é um ArcGIS_WX_v100
sAPIKey é uma cadeia = "SUA_ARCGIS_API_KEY"

TRY
// Inicializar mapa
gArcGIS = new ArcGIS_WX_v100(sAPIKey, HTMLControl1, ArcGIS_WX_v100.CONTROLE_HTML)
gArcGIS.InicializarMapa(-23.5505, -46.6333, 10)

ThreadPause(3000)

// CONFIGURAR FEATURE LAYERS CORPORATIVOS
ConfigurarFeatureLayersCorporativos(gArcGIS)

// DEMONSTRAR CONSULTAS AVANÇADAS
DemonstrarConsultasAvancadas(gArcGIS)

// ANÁLISE DE DADOS CORPORATIVOS
AnaliseFeatureLayersCorporativos(gArcGIS)

// INTEGRAÇÃO COM SISTEMAS CORPORATIVOS
IntegracaoSistemasCorporativos(gArcGIS)

// RELATÓRIOS CORPORATIVOS
GerarRelatoriosCorporativos()

EXCEPTION
Error("?? Erro nos Feature Layers corporativos: " + ExceptionInfo())
FIM

PRIVADO PROCEDIMENTO ConfigurarFeatureLayersCorporativos(gArcGIS é um ArcGIS_WX_v100)

arrLayers é um array de stFeatureLayerConfig

Info("?? Configurando Feature Layers corporativos...")

// 1. LAYER DE VENDAS POR REGIÃO
CriarConfigLayer(arrLayers, "Vendas por Região",
"https://services.arcgis.com/exemplo/vendas/FeatureServer/0",
"VENDAS", Verdadeiro, 0.8, "vendas_style")

// 2. LAYER DE CLIENTES CORPORATIVOS
CriarConfigLayer(arrLayers, "Clientes Corporativos",
"https://services.arcgis.com/exemplo/clientes/FeatureServer/0",
"CLIENTES", Verdadeiro, 0.9, "clientes_style")

// 3. LAYER DE CONCORRÊNCIA
CriarConfigLayer(arrLayers, "Análise de Concorrência",
"https://services.arcgis.com/exemplo/concorrencia/FeatureServer/0",
"CONCORRENCIA", Falso, 0.7, "concorrencia_style")

// 4. LAYER DE DADOS DEMOGRÁFICOS
CriarConfigLayer(arrLayers, "Dados Demográficos",
"https://services.arcgis.com/exemplo/demografia/FeatureServer/0",
"DEMOGRAFIA", Verdadeiro, 0.6, "demografia_style")

// 5. LAYER DE LOGÍSTICA
CriarConfigLayer(arrLayers, "Centros de Distribuição",
"https://services.arcgis.com/exemplo/logistica/FeatureServer/0",
"LOGISTICA", Verdadeiro, 1.0, "logistica_style")

// Adicionar layers no mapa
PARA i = 1 À ArrayCount(arrLayers)
AdicionarFeatureLayerCorporativo(gArcGIS, arrLayers[i])
FIM

Info("? Feature Layers corporativos configurados!")

PRIVADO PROCEDIMENTO CriarConfigLayer(arrLayers é um array de stFeatureLayerConfig, sNome é uma cadeia, sURL é uma cadeia, sTipo é uma cadeia, bVisivel é um booleano, nOpacidade é um real, sEstilo é uma cadeia)

stConfig é um stFeatureLayerConfig

stConfig.sNome = sNome
stConfig.sURL = sURL
stConfig.sTipo = sTipo
stConfig.bVisivel = bVisivel
stConfig.nOpacidade = nOpacidade
stConfig.sEstilo = sEstilo

// Configurar campos específicos por tipo
ConfigurarCamposPorTipo(stConfig)

ArrayAdd(arrLayers, stConfig)

PRIVADO PROCEDIMENTO ConfigurarCamposPorTipo(stConfig é um stFeatureLayerConfig)

CONFORME Upper(stConfig.sTipo)
CASO "VENDAS":
ArrayAdd(stConfig.arrCampos, "regiao")
ArrayAdd(stConfig.arrCampos, "vendas_mes")
ArrayAdd(stConfig.arrCampos, "meta_mes")
ArrayAdd(stConfig.arrCampos, "vendedor")
ArrayAdd(stConfig.arrCampos, "produto_principal")

CASO "CLIENTES":
ArrayAdd(stConfig.arrCampos, "nome_cliente")
ArrayAdd(stConfig.arrCampos, "segmento")
ArrayAdd(stConfig.arrCampos, "faturamento_anual")
ArrayAdd(stConfig.arrCampos, "data_cadastro")
ArrayAdd(stConfig.arrCampos, "status_cliente")

CASO "CONCORRENCIA":
ArrayAdd(stConfig.arrCampos, "nome_concorrente")
ArrayAdd(stConfig.arrCampos, "tipo_negocio")
ArrayAdd(stConfig.arrCampos, "nivel_ameaca")
ArrayAdd(stConfig.arrCampos, "participacao_mercado")

CASO "DEMOGRAFIA":
ArrayAdd(stConfig.arrCampos, "populacao")
ArrayAdd(stConfig.arrCampos, "renda_media")
ArrayAdd(stConfig.arrCampos, "faixa_etaria")
ArrayAdd(stConfig.arrCampos, "escolaridade")
ArrayAdd(stConfig.arrCampos, "poder_compra")

CASO "LOGISTICA":
ArrayAdd(stConfig.arrCampos, "nome_centro")
ArrayAdd(stConfig.arrCampos, "capacidade")
ArrayAdd(stConfig.arrCampos, "utilizacao_atual")
ArrayAdd(stConfig.arrCampos, "custo_operacional")
ArrayAdd(stConfig.arrCampos, "area_cobertura")
FIM

PRIVADO PROCEDIMENTO AdicionarFeatureLayerCorporativo(gArcGIS é um ArcGIS_WX_v100, stConfig é um stFeatureLayerConfig)

nIDLayer é um inteiro

Info("?? Adicionando layer: " + stConfig.sNome)

TRY
// Adicionar Feature Layer
nIDLayer = gArcGIS.AdicionarFeatureLayer(stConfig.sURL, stConfig.sNome)

SE nIDLayer > 0 ENTÃO
Info("? Layer adicionado com sucesso (ID: " + nIDLayer + ")")

// Configurar estilo do layer
ConfigurarEstiloLayer(gArcGIS, nIDLayer, stConfig)

// Configurar visibilidade
SE NÃO stConfig.bVisivel ENTÃO
// gArcGIS.DefinirVisibilidadeLayer(nIDLayer, Falso)
Info("??? Layer configurado como invisível")
FIM

SENÃO
Info("? Erro ao adicionar layer: " + stConfig.sNome)
FIM

EXCEPTION
Info("?? Exceção ao adicionar layer: " + ExceptionInfo())
FIM

PRIVADO PROCEDIMENTO ConfigurarEstiloLayer(gArcGIS é um ArcGIS_WX_v100, nIDLayer é um inteiro, stConfig é um stFeatureLayerConfig)

sEstiloJSON é uma cadeia

// Gerar configuração de estilo baseada no tipo
CONFORME Upper(stConfig.sTipo)
CASO "VENDAS":
sEstiloJSON = GerarEstiloVendas(stConfig.nOpacidade)
CASO "CLIENTES":
sEstiloJSON = GerarEstiloClientes(stConfig.nOpacidade)
CASO "CONCORRENCIA":
sEstiloJSON = GerarEstiloConcorrencia(stConfig.nOpacidade)
CASO "DEMOGRAFIA":
sEstiloJSON = GerarEstiloDemografia(stConfig.nOpacidade)
CASO "LOGISTICA":
sEstiloJSON = GerarEstiloLogistica(stConfig.nOpacidade)
PADRÃO:
sEstiloJSON = GerarEstiloPadrao(stConfig.nOpacidade)
FIM

// Aplicar estilo (simulado)
Info("?? Aplicando estilo personalizado para " + stConfig.sTipo)

PRIVADO PROCEDIMENTO GerarEstiloVendas(nOpacidade é um real) : cadeia

sEstilo é uma cadeia = '{'
sEstilo += '"type": "simple",'
sEstilo += '"symbol": {'
sEstilo += ' "type": "simple-fill",'
sEstilo += ' "color": [0, 255, 0, ' + NumToString(nOpacidade, "0.2f") + '],'
sEstilo += ' "outline": {"color": [0, 128, 0, 1], "width": 2}'
sEstilo += '},'
sEstilo += '"visualVariables": [{'
sEstilo += ' "type": "color",'
sEstilo += ' "field": "vendas_mes",'
sEstilo += ' "stops": [{"value": 0, "color": "#ff0000"}, {"value": 100000, "color": "#00ff00"}]'
sEstilo += '}]'
sEstilo += '}'

RETORNO sEstilo

PRIVADO PROCEDIMENTO GerarEstiloClientes(nOpacidade é um real) : cadeia

sEstilo é uma cadeia = '{'
sEstilo += '"type": "unique-value",'
sEstilo += '"field": "segmento",'
sEstilo += '"uniqueValueInfos": ['
sEstilo += ' {"value": "CORPORATIVO", "symbol": {"type": "simple-marker", "color": [0, 0, 255, ' + NumToString(nOpacidade, "0.2f") + '], "size": 12}},'
sEstilo += ' {"value": "VAREJO", "symbol": {"type": "simple-marker", "color": [255, 165, 0, ' + NumToString(nOpacidade, "0.2f") + '], "size": 8}},'
sEstilo += ' {"value": "GOVERNO", "symbol": {"type": "simple-marker", "color": [128, 0, 128, ' + NumToString(nOpacidade, "0.2f") + '], "size": 10}}'
sEstilo += ']'
sEstilo += '}'

RETORNO sEstilo

PRIVADO PROCEDIMENTO GerarEstiloConcorrencia(nOpacidade é um real) : cadeia

sEstilo é uma cadeia = '{'
sEstilo += '"type": "class-breaks",'
sEstilo += '"field": "nivel_ameaca",'
sEstilo += '"classBreakInfos": ['
sEstilo += ' {"minValue": 1, "maxValue": 3, "symbol": {"type": "simple-marker", "color": [255, 255, 0, ' + NumToString(nOpacidade, "0.2f") + '], "size": 8}},'
sEstilo += ' {"minValue": 4, "maxValue": 6, "symbol": {"type": "simple-marker", "color": [255, 165, 0, ' + NumToString(nOpacidade, "0.2f") + '], "size": 10}},'
sEstilo += ' {"minValue": 7, "maxValue": 10, "symbol": {"type": "simple-marker", "color": [255, 0, 0, ' + NumToString(nOpacidade, "0.2f") + '], "size": 12}}'
sEstilo += ']'
sEstilo += '}'

RETORNO sEstilo

PRIVADO PROCEDIMENTO GerarEstiloDemografia(nOpacidade é um real) : cadeia

sEstilo é uma cadeia = '{'
sEstilo += '"type": "simple",'
sEstilo += '"symbol": {'
sEstilo += ' "type": "simple-fill",'
sEstilo += ' "color": [135, 206, 235, ' + NumToString(nOpacidade, "0.2f") + '],'
sEstilo += ' "outline": {"color": [0, 0, 139, 1], "width": 1}'
sEstilo += '},'
sEstilo += '"visualVariables": [{'
sEstilo += ' "type": "opacity",'
sEstilo += ' "field": "renda_media",'
sEstilo += ' "stops": [{"value": 1000, "opacity": 0.3}, {"value": 10000, "opacity": 1.0}]'
sEstilo += '}]'
sEstilo += '}'

RETORNO sEstilo

PRIVADO PROCEDIMENTO GerarEstiloLogistica(nOpacidade é um real) : cadeia

sEstilo é uma cadeia = '{'
sEstilo += '"type": "simple",'
sEstilo += '"symbol": {'
sEstilo += ' "type": "simple-marker",'
sEstilo += ' "style": "diamond",'
sEstilo += ' "color": [255, 140, 0, ' + NumToString(nOpacidade, "0.2f") + '],'
sEstilo += ' "size": 14,'
sEstilo += ' "outline": {"color": [139, 69, 19, 1], "width": 2}'
sEstilo += '}'
sEstilo += '}'

RETORNO sEstilo

PRIVADO PROCEDIMENTO GerarEstiloPadrao(nOpacidade é um real) : cadeia

sEstilo é uma cadeia = '{'
sEstilo += '"type": "simple",'
sEstilo += '"symbol": {'
sEstilo += ' "type": "simple-marker",'
sEstilo += ' "color": [128, 128, 128, ' + NumToString(nOpacidade, "0.2f") + '],'
sEstilo += ' "size": 8'
sEstilo += '}'
sEstilo += '}'

RETORNO sEstilo

PRIVADO PROCEDIMENTO DemonstrarConsultasAvancadas(gArcGIS é um ArcGIS_WX_v100)

Info("?? Demonstrando consultas avançadas em Feature Layers...")

// 1. CONSULTA DE VENDAS POR REGIÃO
ConsultaVendasPorRegiao()

// 2. ANÁLISE DE CLIENTES POR SEGMENTO
AnaliseClientesPorSegmento()

// 3. IDENTIFICAÇÃO DE OPORTUNIDADES
IdentificacaoOportunidades()

// 4. ANÁLISE DE CONCORRÊNCIA
AnaliseConcorrencia()

PRIVADO PROCEDIMENTO ConsultaVendasPorRegiao()

sConsulta é uma cadeia

Info("?? Executando consulta: Vendas por região...")

// Simular consulta SQL-like no Feature Layer
sConsulta = "SELECT regiao, SUM(vendas_mes) as total_vendas, AVG(meta_mes) as meta_media " +
"FROM vendas_layer " +
"WHERE vendas_mes > 50000 " +
"GROUP BY regiao " +
"ORDER BY total_vendas DESC"

// Simular resultados
ExibirResultadosVendas()

PRIVADO PROCEDIMENTO ExibirResultadosVendas()

sResultados é uma cadeia = "?? RESULTADOS: VENDAS POR REGIÃO" + CR + CR +
"?? Região Sul: R$ 2.850.000 (Meta: R$ 2.500.000) ?" + CR +
"?? Região Sudeste: R$ 2.420.000 (Meta: R$ 2.600.000) ??" + CR +
"?? Região Centro-Oeste: R$ 1.890.000 (Meta: R$ 1.800.000) ?" + CR +
"4º Região Nordeste: R$ 1.650.000 (Meta: R$ 1.700.000) ??" + CR +
"5º Região Norte: R$ 980.000 (Meta: R$ 1.000.000) ??" + CR + CR +
"?? Total geral: R$ 9.790.000" + CR +
"?? Meta total: R$ 9.600.000" + CR +
"? Performance: 102% da meta"

Info(sResultados)

PRIVADO PROCEDIMENTO AnaliseClientesPorSegmento()

Info("?? Executando análise: Clientes por segmento...")

// Simular análise de clientes
sResultados é uma cadeia = "?? ANÁLISE DE CLIENTES POR SEGMENTO" + CR + CR +
"?? Corporativo:" + CR +
" • Quantidade: 245 clientes" + CR +
" • Faturamento médio: R$ 850.000/ano" + CR +
" • Crescimento: +12% vs ano anterior" + CR + CR +
"??? Varejo:" + CR +
" • Quantidade: 1.850 clientes" + CR +
" • Faturamento médio: R$ 45.000/ano" + CR +
" • Crescimento: +8% vs ano anterior" + CR + CR +
"??? Governo:" + CR +
" • Quantidade: 89 clientes" + CR +
" • Faturamento médio: R$ 1.200.000/ano" + CR +
" • Crescimento: +5% vs ano anterior" + CR + CR +
"?? Insight: Segmento corporativo apresenta maior potencial de crescimento"

Info(sResultados)

PRIVADO PROCEDIMENTO IdentificacaoOportunidades()

Info("?? Identificando oportunidades de negócio...")

sOportunidades é uma cadeia = "?? OPORTUNIDADES IDENTIFICADAS" + CR + CR +
"?? Regiões com baixa penetração:" + CR +
" • Zona Leste SP: 15% de penetração (potencial +200 clientes)" + CR +
" • ABC Paulista: 22% de penetração (potencial +150 clientes)" + CR +
" • Região de Campinas: 18% de penetração (potencial +120 clientes)" + CR + CR +
"?? Segmentos em crescimento:" + CR +
" • E-commerce: +35% de demanda" + CR +
" • Saúde digital: +28% de demanda" + CR +
" • Educação online: +22% de demanda" + CR + CR +
"?? Ações recomendadas:" + CR +
" 1. Intensificar prospecção na Zona Leste" + CR +
" 2. Desenvolver produtos para e-commerce" + CR +
" 3. Parcerias estratégicas no ABC"

Info(sOportunidades)

PRIVADO PROCEDIMENTO AnaliseConcorrencia()

Info("?? Executando análise de concorrência...")

sAnalise é uma cadeia = "?? ANÁLISE DE CONCORRÊNCIA" + CR + CR +
"?? Ameaças identificadas:" + CR +
" • Concorrente A: Nível 8/10 (Região Sul)" + CR +
" - Participação: 35% do mercado" + CR +
" - Estratégia: Preços agressivos" + CR + CR +
" • Concorrente B: Nível 6/10 (Região Sudeste)" + CR +
" - Participação: 22% do mercado" + CR +
" - Estratégia: Inovação tecnológica" + CR + CR +
" • Concorrente C: Nível 4/10 (Região Norte)" + CR +
" - Participação: 18% do mercado" + CR +
" - Estratégia: Atendimento local" + CR + CR +
"??? Estratégias defensivas:" + CR +
" 1. Reforçar presença na Região Sul" + CR +
" 2. Acelerar inovação tecnológica" + CR +
" 3. Melhorar atendimento regional"

Info(sAnalise)

PRIVADO PROCEDIMENTO AnaliseFeatureLayersCorporativos(gArcGIS é um ArcGIS_WX_v100)

Info("?? Executando análises avançadas nos Feature Layers...")

// 1. ANÁLISE DE CORRELAÇÃO
AnaliseCorrelacao()

// 2. ANÁLISE PREDITIVA
AnalisePreditiva()

// 3. ANÁLISE DE CLUSTERS
AnaliseClustersCorporativos()

// 4. ANÁLISE DE TENDÊNCIAS
AnaliseTendencias()

PRIVADO PROCEDIMENTO AnaliseCorrelacao()

Info("?? Análise de correlação entre variáveis...")

sAnalise é uma cadeia = "?? ANÁLISE DE CORRELAÇÃO" + CR + CR +
"?? Correlações identificadas:" + CR +
" • Renda média ? Vendas: 0.78 (forte correlação)" + CR +
" • Densidade populacional ? Clientes: 0.65 (correlação moderada)" + CR +
" • Concorrência ? Preços: -0.52 (correlação negativa)" + CR +
" • Escolaridade ? Produtos premium: 0.71 (forte correlação)" + CR + CR +
"?? Insights:" + CR +
" • Focar em regiões de alta renda para maximizar vendas" + CR +
" • Produtos premium têm melhor aceitação em áreas educadas" + CR +
" • Pressão competitiva exige estratégia de preços dinâmica"

Info(sAnalise)

PRIVADO PROCEDIMENTO AnalisePreditiva()

Info("?? Executando análise preditiva...")

sPredicao é uma cadeia = "?? ANÁLISE PREDITIVA - PRÓXIMOS 6 MESES" + CR + CR +
"?? Projeções de vendas:" + CR +
" • Região Sul: R$ 3.200.000 (+12% vs atual)" + CR +
" • Região Sudeste: R$ 2.680.000 (+11% vs atual)" + CR +
" • Região Centro-Oeste: R$ 2.100.000 (+11% vs atual)" + CR +
" • Região Nordeste: R$ 1.850.000 (+12% vs atual)" + CR +
" • Região Norte: R$ 1.150.000 (+17% vs atual)" + CR + CR +
"?? Fatores de crescimento:" + CR +
" • Expansão econômica: +8%" + CR +
" • Novos produtos: +5%" + CR +
" • Melhoria de processos: +3%" + CR + CR +
"?? Riscos identificados:" + CR +
" • Instabilidade econômica: -5%" + CR +
" • Entrada de novos concorrentes: -3%"

Info(sPredicao)

PRIVADO PROCEDIMENTO AnaliseClustersCorporativos()

Info("?? Executando análise de clusters corporativos...")

sClusters é uma cadeia = "?? ANÁLISE DE CLUSTERS CORPORATIVOS" + CR + CR +
"?? Cluster 1 - 'Mercado Premium':" + CR +
" • Localização: Zona Sul SP, Alphaville" + CR +
" • Características: Alta renda, baixa concorrência" + CR +
" • Estratégia: Produtos premium, atendimento VIP" + CR + CR +
"?? Cluster 2 - 'Mercado Competitivo':" + CR +
" • Localização: Centro SP, Vila Olímpia" + CR +
" • Características: Alta densidade, muita concorrência" + CR +
" • Estratégia: Preços competitivos, diferenciação" + CR + CR +
"?? Cluster 3 - 'Mercado Emergente':" + CR +
" • Localização: Zona Leste, Grande ABC" + CR +
" • Características: Crescimento rápido, baixa penetração" + CR +
" • Estratégia: Expansão agressiva, produtos básicos" + CR + CR +
"?? Recomendação: Personalizar estratégias por cluster"

Info(sClusters)

PRIVADO PROCEDIMENTO AnaliseTendencias()

Info("?? Analisando tendências de mercado...")

sTendencias é uma cadeia = "?? ANÁLISE DE TENDÊNCIAS" + CR + CR +
"?? Tendências de crescimento:" + CR +
" • Digitalização: +45% de demanda" + CR +
" • Sustentabilidade: +32% de interesse" + CR +
" • Personalização: +28% de preferência" + CR +
" • Mobilidade: +25% de adoção" + CR + CR +
"?? Tendências de declínio:" + CR +
" • Processos manuais: -35%" + CR +
" • Produtos padronizados: -22%" + CR +
" • Atendimento presencial: -18%" + CR + CR +
"?? Oportunidades emergentes:" + CR +
" • IA e Machine Learning" + CR +
" • IoT e sensores inteligentes" + CR +
" • Blockchain e segurança" + CR +
" • Realidade aumentada"

Info(sTendencias)

PRIVADO PROCEDIMENTO IntegracaoSistemasCorporativos(gArcGIS é um ArcGIS_WX_v100)

Info("?? Demonstrando integração com sistemas corporativos...")

// 1. INTEGRAÇÃO COM CRM
IntegracaoCRM()

// 2. INTEGRAÇÃO COM ERP
IntegracaoERP()

// 3. INTEGRAÇÃO COM BI
IntegracaoBI()

// 4. INTEGRAÇÃO COM API EXTERNA
IntegracaoAPIExterna()

PRIVADO PROCEDIMENTO IntegracaoCRM()

Info("?? Integrando com sistema CRM...")

// Simular integração com CRM
sIntegracao é uma cadeia = "?? INTEGRAÇÃO CRM CONCLUÍDA" + CR + CR +
"?? Dados sincronizados:" + CR +
" • 2.184 clientes ativos" + CR +
" • 456 leads em prospecção" + CR +
" • 89 oportunidades em andamento" + CR +
" • 234 contratos renovados" + CR + CR +
"??? Visualização no mapa:" + CR +
" • Clientes por região" + CR +
" • Pipeline de vendas geolocalizado" + CR +
" • Rotas de vendedores otimizadas" + CR +
" • Análise de territórios"

Info(sIntegracao)

PRIVADO PROCEDIMENTO IntegracaoERP()

Info("?? Integrando com sistema ERP...")

sIntegracao é uma cadeia = "?? INTEGRAÇÃO ERP CONCLUÍDA" + CR + CR +
"?? Dados operacionais:" + CR +
" • 15 centros de distribuição" + CR +
" • 2.450 produtos em estoque" + CR +
" • 1.890 pedidos em processamento" + CR +
" • 567 entregas programadas" + CR + CR +
"?? Logística otimizada:" + CR +
" • Rotas de entrega calculadas" + CR +
" • Capacidade de armazéns monitorada" + CR +
" • Custos logísticos por região" + CR +
" • Tempo de entrega estimado"

Info(sIntegracao)

PRIVADO PROCEDIMENTO IntegracaoBI()

Info("?? Integrando com sistema de BI...")

sIntegracao é uma cadeia = "?? INTEGRAÇÃO BI CONCLUÍDA" + CR + CR +
"?? Dashboards geoespaciais:" + CR +
" • KPIs por região em tempo real" + CR +
" • Análise de performance territorial" + CR +
" • Comparativo histórico geolocalizado" + CR +
" • Alertas automáticos por área" + CR + CR +
"?? Métricas principais:" + CR +
" • ROI por região: 15-28%" + CR +
" • Custo de aquisição: R$ 450/cliente" + CR +
" • Lifetime value: R$ 12.500/cliente" + CR +
" • Churn rate: 8.5% anual"

Info(sIntegracao)

PRIVADO PROCEDIMENTO IntegracaoAPIExterna()

Info("?? Integrando com APIs externas...")

sIntegracao é uma cadeia = "?? INTEGRAÇÃO APIs EXTERNAS" + CR + CR +
"??? Dados governamentais:" + CR +
" • IBGE: Dados demográficos atualizados" + CR +
" • Receita Federal: Informações empresariais" + CR +
" • BACEN: Indicadores econômicos" + CR + CR +
"?? Dados de mercado:" + CR +
" • Nielsen: Participação de mercado" + CR +
" • SERASA: Score de crédito" + CR +
" • Google Trends: Tendências de busca" + CR + CR +
"?? Dados geográficos:" + CR +
" • OpenStreetMap: Dados de ruas" + CR +
" • Weather API: Dados meteorológicos" + CR +
" • Traffic API: Informações de tráfego"

Info(sIntegracao)

PRIVADO PROCEDIMENTO GerarRelatoriosCorporativos()

Info("?? Gerando relatórios corporativos...")

// 1. RELATÓRIO EXECUTIVO
GerarRelatorioExecutivo()

// 2. RELATÓRIO OPERACIONAL
GerarRelatorioOperacional()

// 3. RELATÓRIO DE PERFORMANCE
GerarRelatorioPerformance()

PRIVADO PROCEDIMENTO GerarRelatorioExecutivo()

sRelatorio é uma cadeia = "?? RELATÓRIO EXECUTIVO - FEATURE LAYERS" + CR + CR +
"?? RESUMO ESTRATÉGICO:" + CR +
" • 5 Feature Layers corporativos ativos" + CR +
" • 15.000+ registros geoespaciais" + CR +
" • 98.5% de disponibilidade dos dados" + CR +
" • Integração com 4 sistemas corporativos" + CR + CR +
"?? PRINCIPAIS INSIGHTS:" + CR +
" • Região Sul: Melhor performance (102% da meta)" + CR +
" • Segmento corporativo: Maior potencial (+12%)" + CR +
" • Zona Leste: Oportunidade de expansão (+200 clientes)" + CR +
" • Digitalização: Tendência dominante (+45%)" + CR + CR +
"?? IMPACTO FINANCEIRO:" + CR +
" • ROI médio: 22% por região" + CR +
" • Economia operacional: R$ 2.8M/ano" + CR +
" • Receita adicional identificada: R$ 5.2M" + CR + CR +
"?? PRÓXIMOS PASSOS:" + CR +
" 1. Expandir para Zona Leste" + CR +
" 2. Acelerar digitalização" + CR +
" 3. Fortalecer segmento corporativo"

Info(sRelatorio)

PRIVADO PROCEDIMENTO GerarRelatorioOperacional()

sRelatorio é uma cadeia = "?? RELATÓRIO OPERACIONAL" + CR + CR +
"?? STATUS DOS SISTEMAS:" + CR +
" • Feature Layers: 5/5 operacionais" + CR +
" • Integrações: 4/4 funcionando" + CR +
" • Consultas/dia: 2.450 em média" + CR +
" • Tempo de resposta: 1.2s médio" + CR + CR +
"?? QUALIDADE DOS DADOS:" + CR +
" • Completude: 96.8%" + CR +
" • Precisão: 98.2%" + CR +
" • Atualização: Tempo real" + CR +
" • Consistência: 99.1%" + CR + CR +
"?? SINCRONIZAÇÃO:" + CR +
" • CRM: Última sync 10min atrás" + CR +
" • ERP: Última sync 5min atrás" + CR +
" • BI: Última sync 2min atrás" + CR +
" • APIs: Tempo real" + CR + CR +
"?? ALERTAS:" + CR +
" • Nenhum alerta crítico" + CR +
" • 2 avisos de performance" + CR +
" • 1 manutenção programada"

Info(sRelatorio)

PRIVADO PROCEDIMENTO GerarRelatorioPerformance()

sRelatorio é uma cadeia = "?? RELATÓRIO DE PERFORMANCE" + CR + CR +
"?? MÉTRICAS DE USO:" + CR +
" • Usuários ativos: 145/dia" + CR +
" • Consultas executadas: 2.450/dia" + CR +
" • Dados visualizados: 15.000 registros" + CR +
" • Relatórios gerados: 89/semana" + CR + CR +
"? PERFORMANCE TÉCNICA:" + CR +
" • Tempo de carregamento: 1.2s" + CR +
" • Taxa de erro: 0.3%" + CR +
" • Disponibilidade: 99.8%" + CR +
" • Throughput: 500 req/min" + CR + CR +
"?? INSIGHTS DE USO:" + CR +
" • Layer mais usado: Vendas (45%)" + CR +
" • Horário de pico: 9h-11h" + CR +
" • Consulta mais comum: Vendas por região" + CR +
" • Usuário mais ativo: Diretoria comercial" + CR + CR +
"?? OTIMIZAÇÕES SUGERIDAS:" + CR +
" • Cache para consultas frequentes" + CR +
" • Índices adicionais em campos de busca" + CR +
" • Compressão de dados históricos"

Info(sRelatorio)

// ============================================================================
// BENEFÍCIOS DOS FEATURE LAYERS CORPORATIVOS:
//
// 1. INTEGRAÇÃO DE DADOS
// • Múltiplas fontes em uma visualização
// • Dados corporativos + geográficos
// • Sincronização em tempo real
//
// 2. ANÁLISES AVANÇADAS
// • Correlações espaciais
// • Análises preditivas
// • Clustering inteligente
// • Tendências de mercado
//
// 3. TOMADA DE DECISÃO
// • Insights baseados em localização
// • Visualização de oportunidades
// • Identificação de riscos
// • Otimização de recursos
//
// 4. EFICIÊNCIA OPERACIONAL
// • Automatização de relatórios
// • Dashboards em tempo real
// • Alertas automáticos
// • Integração com sistemas existentes
//
// CASOS DE USO EMPRESARIAIS:
// • Análise de mercado e concorrência
// • Planejamento de expansão
// • Otimização de logística
// • Gestão de territórios de vendas
// • Análise de performance regional
// • Identificação de oportunidades
// ============================================================================
```

### **12. Sistema de Callbacks**

```wlanguage
// ============================================================================
// EXEMPLO 12: Sistema Avançado de Callbacks e Eventos
// Complexidade: ??? Avançado
// Tempo estimado: 60 minutos
// ============================================================================

// Enumeração para tipos de eventos
ENUMERACAO TipoEventoMapa
EVENTO_MAPA_CARREGADO = 1
EVENTO_MAPA_CLICADO = 2
EVENTO_MAPA_MOVIDO = 3
EVENTO_ZOOM_ALTERADO = 4
EVENTO_MARCADOR_CLICADO = 5
EVENTO_MARCADOR_HOVER = 6
EVENTO_BASEMAP_ALTERADO = 7
EVENTO_LAYER_ADICIONADO = 8
EVENTO_ANALISE_CONCLUIDA = 9
EVENTO_ERRO_OCORRIDO = 10
FIM

// Estrutura para dados do evento
ESTRUTURA stDadosEvento
nTipoEvento é um TipoEventoMapa
dtTimestamp é um DateTime
sOrigem é uma cadeia
nLatitude é um real
nLongitude é um real
nZoom é um inteiro
sParametros é uma cadeia
pDadosAdicionais é um ponteiro
FIM

// Estrutura para callback registrado
ESTRUTURA stCallbackRegistrado
nTipoEvento é um TipoEventoMapa
sProcedimento é uma cadeia
bAtivo é um booleano
nPrioridade é um inteiro
sDescricao é uma cadeia
FIM

// Arrays globais para gerenciamento de eventos
m_arrCallbacks é um array de stCallbackRegistrado
m_arrHistoricoEventos é um array de stDadosEvento

PROCEDIMENTO SistemaCallbacks()

gArcGIS é um ArcGIS_WX_v100
sAPIKey é uma cadeia = "SUA_ARCGIS_API_KEY"

TRY
// Inicializar sistema de eventos
InicializarSistemaEventos()

// Inicializar mapa
gArcGIS = new ArcGIS_WX_v100(sAPIKey, HTMLControl1, ArcGIS_WX_v100.CONTROLE_HTML)
gArcGIS.InicializarMapa(-23.5505, -46.6333, 12)

ThreadPause(3000)

// REGISTRAR CALLBACKS
RegistrarCallbacksBasicos()
RegistrarCallbacksAvancados()

// DEMONSTRAR EVENTOS
DemonstrarEventosBasicos(gArcGIS)
DemonstrarEventosAvancados(gArcGIS)

// SISTEMA DE MONITORAMENTO
MonitorarEventos()

// RELATÓRIOS DE EVENTOS
GerarRelatoriosEventos()

EXCEPTION
Error("?? Erro no sistema de callbacks: " + ExceptionInfo())
FIM

PRIVADO PROCEDIMENTO InicializarSistemaEventos()

Info("?? Inicializando sistema de eventos e callbacks...")

// Limpar arrays
ArrayDeleteAll(m_arrCallbacks)
ArrayDeleteAll(m_arrHistoricoEventos)

// Configurar sistema
m_nMaxHistorico é um inteiro = 1000 // Máximo de eventos no histórico
m_bLogEventos é um booleano = Verdadeiro

Info("? Sistema de eventos inicializado!")

PRIVADO PROCEDIMENTO RegistrarCallbacksBasicos()

Info("?? Registrando callbacks básicos...")

// Callback para carregamento do mapa
RegistrarCallback(TipoEventoMapa.EVENTO_MAPA_CARREGADO, "OnMapaCarregado", 10, "Callback de carregamento do mapa")

// Callback para cliques no mapa
RegistrarCallback(TipoEventoMapa.EVENTO_MAPA_CLICADO, "OnMapaClicado", 5, "Callback de clique no mapa")

// Callback para movimento do mapa
RegistrarCallback(TipoEventoMapa.EVENTO_MAPA_MOVIDO, "OnMapaMovido", 3, "Callback de movimento do mapa")

// Callback para alteração de zoom
RegistrarCallback(TipoEventoMapa.EVENTO_ZOOM_ALTERADO, "OnZoomAlterado", 5, "Callback de alteração de zoom")

// Callback para clique em marcador
RegistrarCallback(TipoEventoMapa.EVENTO_MARCADOR_CLICADO, "OnMarcadorClicado", 8, "Callback de clique em marcador")

Info("? Callbacks básicos registrados!")

PRIVADO PROCEDIMENTO RegistrarCallbacksAvancados()

Info("?? Registrando callbacks avançados...")

// Callback para hover em marcador
RegistrarCallback(TipoEventoMapa.EVENTO_MARCADOR_HOVER, "OnMarcadorHover", 2, "Callback de hover em marcador")

// Callback para alteração de basemap
RegistrarCallback(TipoEventoMapa.EVENTO_BASEMAP_ALTERADO, "OnBasemapAlterado", 4, "Callback de alteração de basemap")

// Callback para adição de layer
RegistrarCallback(TipoEventoMapa.EVENTO_LAYER_ADICIONADO, "OnLayerAdicionado", 6, "Callback de adição de layer")

// Callback para conclusão de análise
RegistrarCallback(TipoEventoMapa.EVENTO_ANALISE_CONCLUIDA, "OnAnaliseConcluida", 7, "Callback de análise concluída")

// Callback para tratamento de erros
RegistrarCallback(TipoEventoMapa.EVENTO_ERRO_OCORRIDO, "OnErroOcorrido", 10, "Callback de tratamento de erros")

Info("? Callbacks avançados registrados!")

PRIVADO PROCEDIMENTO RegistrarCallback(nTipoEvento é um TipoEventoMapa, sProcedimento é uma cadeia, nPrioridade é um inteiro, sDescricao é uma cadeia)

stCallback é um stCallbackRegistrado

stCallback.nTipoEvento = nTipoEvento
stCallback.sProcedimento = sProcedimento
stCallback.bAtivo = Verdadeiro
stCallback.nPrioridade = nPrioridade
stCallback.sDescricao = sDescricao

ArrayAdd(m_arrCallbacks, stCallback)

Trace("?? Callback registrado: " + sDescricao + " (Prioridade: " + nPrioridade + ")")

PRIVADO PROCEDIMENTO DemonstrarEventosBasicos(gArcGIS é um ArcGIS_WX_v100)

Info("?? Demonstrando eventos básicos...")

// 1. SIMULAR CARREGAMENTO DO MAPA
Info("?? Simulando evento: Mapa carregado")
DispararEvento(TipoEventoMapa.EVENTO_MAPA_CARREGADO, -23.5505, -46.6333, 12, "Mapa inicializado com sucesso")
ThreadPause(2000)

// 2. SIMULAR CLIQUE NO MAPA
Info("?? Simulando evento: Clique no mapa")
DispararEvento(TipoEventoMapa.EVENTO_MAPA_CLICADO, -23.5614, -46.6558, 12, "Usuário clicou na Av. Paulista")
ThreadPause(2000)

// 3. ADICIONAR MARCADOR E SIMULAR CLIQUE
nIDMarcador é um inteiro = gArcGIS.AdicionarMarcador(-23.5614, -46.6558, "Av. Paulista", "Centro financeiro", ArcGIS_WX_v100.SIMBOLO_CIRCLE, "#FF0000")
Info("?? Simulando evento: Clique em marcador")
DispararEvento(TipoEventoMapa.EVENTO_MARCADOR_CLICADO, -23.5614, -46.6558, 12, "ID:" + nIDMarcador + ",Titulo:Av. Paulista")
ThreadPause(2000)

// 4. SIMULAR ALTERAÇÃO DE ZOOM
Info("?? Simulando evento: Alteração de zoom")
gArcGIS.DefinirZoom(15)
DispararEvento(TipoEventoMapa.EVENTO_ZOOM_ALTERADO, -23.5614, -46.6558, 15, "Zoom alterado para 15")
ThreadPause(2000)

// 5. SIMULAR MOVIMENTO DO MAPA
Info("??? Simulando evento: Movimento do mapa")
gArcGIS.CentralizarMapa(-23.5873, -46.6573, 15)
DispararEvento(TipoEventoMapa.EVENTO_MAPA_MOVIDO, -23.5873, -46.6573, 15, "Mapa movido para Ibirapuera")

PRIVADO PROCEDIMENTO DemonstrarEventosAvancados(gArcGIS é um ArcGIS_WX_v100)

Info("?? Demonstrando eventos avançados...")

// 1. SIMULAR HOVER EM MARCADOR
Info("?? Simulando evento: Hover em marcador")
DispararEvento(TipoEventoMapa.EVENTO_MARCADOR_HOVER, -23.5614, -46.6558, 15, "Hover no marcador Av. Paulista")
ThreadPause(2000)

// 2. SIMULAR ALTERAÇÃO DE BASEMAP
Info("??? Simulando evento: Alteração de basemap")
gArcGIS.AlterarBasemap(ArcGIS_WX_v100.BASEMAP_SATELLITE)
DispararEvento(TipoEventoMapa.EVENTO_BASEMAP_ALTERADO, -23.5873, -46.6573, 15, "Basemap alterado para satellite")
ThreadPause(2000)

// 3. SIMULAR ADIÇÃO DE LAYER
Info("?? Simulando evento: Adição de Feature Layer")
nIDLayer é um inteiro = gArcGIS.AdicionarFeatureLayer("https://exemplo.com/layer", "Layer Corporativo")
DispararEvento(TipoEventoMapa.EVENTO_LAYER_ADICIONADO, -23.5873, -46.6573, 15, "Layer ID:" + nIDLayer + ",Nome:Layer Corporativo")
ThreadPause(2000)

// 4. SIMULAR CONCLUSÃO DE ANÁLISE
Info("?? Simulando evento: Análise concluída")
nIDAnalise é um inteiro = gArcGIS.ExecutarAnalise(ArcGIS_WX_v100.ANALISE_BUFFER, '{"distance": 1000}')
DispararEvento(TipoEventoMapa.EVENTO_ANALISE_CONCLUIDA, -23.5873, -46.6573, 15, "Análise ID:" + nIDAnalise + ",Tipo:Buffer,Status:Sucesso")
ThreadPause(2000)

// 5. SIMULAR ERRO
Info("?? Simulando evento: Erro ocorrido")
DispararEvento(TipoEventoMapa.EVENTO_ERRO_OCORRIDO, 0, 0, 0, "Erro simulado para demonstração")

PRIVADO PROCEDIMENTO DispararEvento(nTipoEvento é um TipoEventoMapa, nLat é um real, nLng é um real, nZoom é um inteiro, sParametros é uma cadeia)

stEvento é um stDadosEvento

// Criar dados do evento
stEvento.nTipoEvento = nTipoEvento
stEvento.dtTimestamp = DateTimeSys()
stEvento.sOrigem = "Sistema"
stEvento.nLatitude = nLat
stEvento.nLongitude = nLng
stEvento.nZoom = nZoom
stEvento.sParametros = sParametros

// Adicionar ao histórico
AdicionarAoHistorico(stEvento)

// Executar callbacks registrados
ExecutarCallbacks(stEvento)

PRIVADO PROCEDIMENTO AdicionarAoHistorico(stEvento é um stDadosEvento)

// Adicionar evento ao histórico
ArrayAdd(m_arrHistoricoEventos, stEvento)

// Limitar tamanho do histórico
SE ArrayCount(m_arrHistoricoEventos) > m_nMaxHistorico ENTÃO
ArrayDelete(m_arrHistoricoEventos, 1)
FIM

// Log do evento
SE m_bLogEventos ENTÃO
sLog é uma cadeia = "?? " + DateTimeToString(stEvento.dtTimestamp, "HH:MM:SS") +
" - Evento: " + ObterNomeEvento(stEvento.nTipoEvento) +
" - Params: " + stEvento.sParametros
Trace(sLog)
FIM

PRIVADO PROCEDIMENTO ObterNomeEvento(nTipoEvento é um TipoEventoMapa) : cadeia

CONFORME nTipoEvento
CASO TipoEventoMapa.EVENTO_MAPA_CARREGADO:
RETORNO "MAPA_CARREGADO"
CASO TipoEventoMapa.EVENTO_MAPA_CLICADO:
RETORNO "MAPA_CLICADO"
CASO TipoEventoMapa.EVENTO_MAPA_MOVIDO:
RETORNO "MAPA_MOVIDO"
CASO TipoEventoMapa.EVENTO_ZOOM_ALTERADO:
RETORNO "ZOOM_ALTERADO"
CASO TipoEventoMapa.EVENTO_MARCADOR_CLICADO:
RETORNO "MARCADOR_CLICADO"
CASO TipoEventoMapa.EVENTO_MARCADOR_HOVER:
RETORNO "MARCADOR_HOVER"
CASO TipoEventoMapa.EVENTO_BASEMAP_ALTERADO:
RETORNO "BASEMAP_ALTERADO"
CASO TipoEventoMapa.EVENTO_LAYER_ADICIONADO:
RETORNO "LAYER_ADICIONADO"
CASO TipoEventoMapa.EVENTO_ANALISE_CONCLUIDA:
RETORNO "ANALISE_CONCLUIDA"
CASO TipoEventoMapa.EVENTO_ERRO_OCORRIDO:
RETORNO "ERRO_OCORRIDO"
PADRÃO:
RETORNO "EVENTO_DESCONHECIDO"
FIM

PRIVADO PROCEDIMENTO ExecutarCallbacks(stEvento é um stDadosEvento)

arrCallbacksAtivos é um array de stCallbackRegistrado

// Filtrar callbacks ativos para este tipo de evento
PARA i = 1 À ArrayCount(m_arrCallbacks)
SE m_arrCallbacks[i].nTipoEvento = stEvento.nTipoEvento E m_arrCallbacks[i].bAtivo ENTÃO
ArrayAdd(arrCallbacksAtivos, m_arrCallbacks[i])
FIM
FIM

// Ordenar por prioridade (maior prioridade primeiro)
OrdenarCallbacksPorPrioridade(arrCallbacksAtivos)

// Executar callbacks
PARA i = 1 À ArrayCount(arrCallbacksAtivos)
TRY
ExecutarCallback(arrCallbacksAtivos[i], stEvento)
EXCEPTION
Trace("? Erro ao executar callback: " + arrCallbacksAtivos[i].sProcedimento + " - " + ExceptionInfo())
FIM
FIM

PRIVADO PROCEDIMENTO OrdenarCallbacksPorPrioridade(arrCallbacks é um array de stCallbackRegistrado)

// Ordenação simples por prioridade (bubble sort)
PARA i = 1 À ArrayCount(arrCallbacks) - 1
PARA j = i + 1 À ArrayCount(arrCallbacks)
SE arrCallbacks[i].nPrioridade < arrCallbacks[j].nPrioridade ENTÃO
// Trocar posições
stTemp é um stCallbackRegistrado = arrCallbacks[i]
arrCallbacks[i] = arrCallbacks[j]
arrCallbacks[j] = stTemp
FIM
FIM
FIM

PRIVADO PROCEDIMENTO ExecutarCallback(stCallback é um stCallbackRegistrado, stEvento é um stDadosEvento)

// Simular execução do callback
sLog é uma cadeia = "?? Executando callback: " + stCallback.sProcedimento +
" (Prioridade: " + stCallback.nPrioridade + ")"
Trace(sLog)

// Aqui seria executado o procedimento real
// ExecuteProcedure(stCallback.sProcedimento, stEvento)

// Para demonstração, chamar procedimentos específicos
CONFORME stCallback.sProcedimento
CASO "OnMapaCarregado":
OnMapaCarregado(stEvento)
CASO "OnMapaClicado":
OnMapaClicado(stEvento)
CASO "OnMapaMovido":
OnMapaMovido(stEvento)
CASO "OnZoomAlterado":
OnZoomAlterado(stEvento)
CASO "OnMarcadorClicado":
OnMarcadorClicado(stEvento)
CASO "OnMarcadorHover":
OnMarcadorHover(stEvento)
CASO "OnBasemapAlterado":
OnBasemapAlterado(stEvento)
CASO "OnLayerAdicionado":
OnLayerAdicionado(stEvento)
CASO "OnAnaliseConcluida":
OnAnaliseConcluida(stEvento)
CASO "OnErroOcorrido":
OnErroOcorrido(stEvento)
FIM

// ============================================================================
// IMPLEMENTAÇÃO DOS CALLBACKS ESPECÍFICOS
// ============================================================================

PRIVADO PROCEDIMENTO OnMapaCarregado(stEvento é um stDadosEvento)

sMsg é uma cadeia = "??? CALLBACK: Mapa carregado com sucesso!" + CR +
"?? Posição inicial: " + NumToString(stEvento.nLatitude, "0.4f") + ", " + NumToString(stEvento.nLongitude, "0.4f") + CR +
"?? Zoom inicial: " + stEvento.nZoom + CR +
"? Timestamp: " + DateTimeToString(stEvento.dtTimestamp, "HH:MM:SS")

Trace(sMsg)

PRIVADO PROCEDIMENTO OnMapaClicado(stEvento é um stDadosEvento)

sMsg é uma cadeia = "?? CALLBACK: Clique detectado no mapa!" + CR +
"?? Coordenadas: " + NumToString(stEvento.nLatitude, "0.4f") + ", " + NumToString(stEvento.nLongitude, "0.4f") + CR +
"?? Detalhes: " + stEvento.sParametros + CR +
"?? Ação sugerida: Adicionar marcador nesta posição"

Trace(sMsg)

PRIVADO PROCEDIMENTO OnMapaMovido(stEvento é um stDadosEvento)

sMsg é uma cadeia = "??? CALLBACK: Mapa foi movido!" + CR +
"?? Nova posição central: " + NumToString(stEvento.nLatitude, "0.4f") + ", " + NumToString(stEvento.nLongitude, "0.4f") + CR +
"?? Zoom atual: " + stEvento.nZoom + CR +
"?? Ação: Atualizar dados visíveis na nova área"

Trace(sMsg)

PRIVADO PROCEDIMENTO OnZoomAlterado(stEvento é um stDadosEvento)

sMsg é uma cadeia = "?? CALLBACK: Zoom alterado!" + CR +
"?? Novo nível: " + stEvento.nZoom + CR +
"?? Centro: " + NumToString(stEvento.nLatitude, "0.4f") + ", " + NumToString(stEvento.nLongitude, "0.4f") + CR +
"?? Ação: Ajustar densidade de marcadores"

Trace(sMsg)

PRIVADO PROCEDIMENTO OnMarcadorClicado(stEvento é um stDadosEvento)

sMsg é uma cadeia = "?? CALLBACK: Marcador clicado!" + CR +
"?? Posição: " + NumToString(stEvento.nLatitude, "0.4f") + ", " + NumToString(stEvento.nLongitude, "0.4f") + CR +
"?? Dados: " + stEvento.sParametros + CR +
"?? Ação: Exibir detalhes do marcador"

Trace(sMsg)

PRIVADO PROCEDIMENTO OnMarcadorHover(stEvento é um stDadosEvento)

sMsg é uma cadeia = "?? CALLBACK: Hover em marcador!" + CR +
"?? Posição: " + NumToString(stEvento.nLatitude, "0.4f") + ", " + NumToString(stEvento.nLongitude, "0.4f") + CR +
"?? Ação: Exibir tooltip com informações rápidas"

Trace(sMsg)

PRIVADO PROCEDIMENTO OnBasemapAlterado(stEvento é um stDadosEvento)

sMsg é uma cadeia = "??? CALLBACK: Basemap alterado!" + CR +
"?? Detalhes: " + stEvento.sParametros + CR +
"?? Ação: Ajustar estilo dos marcadores para novo basemap"

Trace(sMsg)

PRIVADO PROCEDIMENTO OnLayerAdicionado(stEvento é um stDadosEvento)

sMsg é uma cadeia = "?? CALLBACK: Feature Layer adicionado!" + CR +
"?? Dados: " + stEvento.sParametros + CR +
"?? Ação: Atualizar legenda e controles de visibilidade"

Trace(sMsg)

PRIVADO PROCEDIMENTO OnAnaliseConcluida(stEvento é um stDadosEvento)

sMsg é uma cadeia = "?? CALLBACK: Análise geoespacial concluída!" + CR +
"?? Resultado: " + stEvento.sParametros + CR +
"?? Ação: Exibir resultados e gerar relatório"

Trace(sMsg)

PRIVADO PROCEDIMENTO OnErroOcorrido(stEvento é um stDadosEvento)

sMsg é uma cadeia = "?? CALLBACK: Erro detectado!" + CR +
"? Detalhes: " + stEvento.sParametros + CR +
"?? Ação: Registrar erro e tentar recuperação automática"

Trace(sMsg)

PRIVADO PROCEDIMENTO MonitorarEventos()

Info("?? Iniciando monitoramento de eventos...")

// Estatísticas de eventos
GerarEstatisticasEventos()

// Análise de padrões
AnalisarPadroesEventos()

// Detecção de anomalias
DetectarAnomalias()

PRIVADO PROCEDIMENTO GerarEstatisticasEventos()

arrContadores é um array de estrutura
nTipoEvento é um TipoEventoMapa
nQuantidade é um inteiro
FIM

// Contar eventos por tipo
PARA i = 1 À ArrayCount(m_arrHistoricoEventos)
nTipo é um TipoEventoMapa = m_arrHistoricoEventos[i].nTipoEvento
nIndice é um inteiro = EncontrarContador(arrContadores, nTipo)

SE nIndice > 0 ENTÃO
arrContadores[nIndice].nQuantidade++
SENÃO
stContador é uma estrutura
stContador.nTipoEvento = nTipo
stContador.nQuantidade = 1
ArrayAdd(arrContadores, stContador)
FIM
FIM

// Exibir estatísticas
sEstatisticas é uma cadeia = "?? ESTATÍSTICAS DE EVENTOS" + CR + CR +
"?? Total de eventos: " + ArrayCount(m_arrHistoricoEventos) + CR + CR

PARA i = 1 À ArrayCount(arrContadores)
sEstatisticas += "• " + ObterNomeEvento(arrContadores[i].nTipoEvento) + ": " + arrContadores[i].nQuantidade + CR
FIM

Info(sEstatisticas)

PRIVADO PROCEDIMENTO EncontrarContador(arrContadores é um array de estrutura, nTipo é um TipoEventoMapa) : inteiro

PARA i = 1 À ArrayCount(arrContadores)
SE arrContadores[i].nTipoEvento = nTipo ENTÃO
RETORNO i
FIM
FIM

RETORNO 0

PRIVADO PROCEDIMENTO AnalisarPadroesEventos()

Info("?? Analisando padrões de eventos...")

// Análise temporal
nEventosUltimos5Min é um inteiro = 0
dtLimite é um DateTime = DateTimeAdd(DateTimeSys(), -5, "min")

PARA i = 1 À ArrayCount(m_arrHistoricoEventos)
SE DateTimeCompare(m_arrHistoricoEventos[i].dtTimestamp, dtLimite) > 0 ENTÃO
nEventosUltimos5Min++
FIM
FIM

// Análise de sequências
sUltimaSequencia é uma cadeia = ""
SE ArrayCount(m_arrHistoricoEventos) >= 3 ENTÃO
nUltimos é um inteiro = ArrayCount(m_arrHistoricoEventos)
sUltimaSequencia = ObterNomeEvento(m_arrHistoricoEventos[nUltimos-2].nTipoEvento) + " ? " +
ObterNomeEvento(m_arrHistoricoEventos[nUltimos-1].nTipoEvento) + " ? " +
ObterNomeEvento(m_arrHistoricoEventos[nUltimos].nTipoEvento)
FIM

sAnalise é uma cadeia = "?? ANÁLISE DE PADRÕES" + CR + CR +
"? Eventos nos últimos 5 min: " + nEventosUltimos5Min + CR +
"?? Taxa de eventos: " + NumToString(nEventosUltimos5Min / 5.0, "0.1f") + " eventos/min" + CR +
"?? Última sequência: " + sUltimaSequencia + CR + CR +
"?? Padrão detectado: " + (nEventosUltimos5Min > 10 ? "Alta atividade" : "Atividade normal")

Info(sAnalise)

PRIVADO PROCEDIMENTO DetectarAnomalias()

Info("?? Detectando anomalias...")

nAnomalias é um inteiro = 0
arrAnomalias é um array de cadeia

// Verificar eventos de erro
PARA i = 1 À ArrayCount(m_arrHistoricoEventos)
SE m_arrHistoricoEventos[i].nTipoEvento = TipoEventoMapa.EVENTO_ERRO_OCORRIDO ENTÃO
nAnomalias++
ArrayAdd(arrAnomalias, "Erro detectado: " + m_arrHistoricoEventos[i].sParametros)
FIM
FIM

// Verificar sequências anômalas (muitos cliques em pouco tempo)
nCliquesRapidos é um inteiro = 0
dtUltimo é um DateTime

PARA i = 1 À ArrayCount(m_arrHistoricoEventos)
SE m_arrHistoricoEventos[i].nTipoEvento = TipoEventoMapa.EVENTO_MAPA_CLICADO ENTÃO
SE i > 1 E DateTimeDifference(m_arrHistoricoEventos[i].dtTimestamp, dtUltimo, "s") < 2 ENTÃO
nCliquesRapidos++
FIM
dtUltimo = m_arrHistoricoEventos[i].dtTimestamp
FIM
FIM

SE nCliquesRapidos > 5 ENTÃO
nAnomalias++
ArrayAdd(arrAnomalias, "Sequência de cliques muito rápida detectada")
FIM

// Relatório de anomalias
sRelatorio é uma cadeia = "?? DETECÇÃO DE ANOMALIAS" + CR + CR +
"?? Total de anomalias: " + nAnomalias + CR + CR

SE nAnomalias > 0 ENTÃO
PARA i = 1 À ArrayCount(arrAnomalias)
sRelatorio += "?? " + arrAnomalias[i] + CR
FIM
SENÃO
sRelatorio += "? Nenhuma anomalia detectada"
FIM

Info(sRelatorio)

PRIVADO PROCEDIMENTO GerarRelatoriosEventos()

Info("?? Gerando relatórios de eventos...")

// Relatório geral
GerarRelatorioGeralEventos()

// Relatório de performance
GerarRelatorioPerformanceEventos()

// Relatório de callbacks
GerarRelatorioCallbacks()

PRIVADO PROCEDIMENTO GerarRelatorioGeralEventos()

nTotalEventos é um inteiro = ArrayCount(m_arrHistoricoEventos)
dtPrimeiro é um DateTime
dtUltimo é um DateTime

SE nTotalEventos > 0 ENTÃO
dtPrimeiro = m_arrHistoricoEventos[1].dtTimestamp
dtUltimo = m_arrHistoricoEventos[nTotalEventos].dtTimestamp
FIM

nDuracaoMin é um real = DateTimeDifference(dtUltimo, dtPrimeiro, "min")
nEventosPorMin é um real = SE(nDuracaoMin > 0, nTotalEventos / nDuracaoMin, 0)

sRelatorio é uma cadeia = "?? RELATÓRIO GERAL DE EVENTOS" + CR + CR +
"?? Total de eventos registrados: " + nTotalEventos + CR +
"? Período analisado: " + NumToString(nDuracaoMin, "0.1f") + " minutos" + CR +
"?? Taxa média: " + NumToString(nEventosPorMin, "0.2f") + " eventos/min" + CR +
"?? Callbacks registrados: " + ArrayCount(m_arrCallbacks) + CR +
"? Callbacks ativos: " + ContarCallbacksAtivos() + CR + CR +
"?? Sistema de eventos funcionando perfeitamente!"

Info(sRelatorio)

PRIVADO PROCEDIMENTO ContarCallbacksAtivos() : inteiro

nAtivos é um inteiro = 0

PARA i = 1 À ArrayCount(m_arrCallbacks)
SE m_arrCallbacks[i].bAtivo ENTÃO
nAtivos++
FIM
FIM

RETORNO nAtivos

PRIVADO PROCEDIMENTO GerarRelatorioPerformanceEventos()

nTempoMedioExecucao é um real = 2.5 // Simulado
nTaxaSucesso é um real = 98.5 // Simulado

sRelatorio é uma cadeia = "? RELATÓRIO DE PERFORMANCE" + CR + CR +
"?? Tempo médio de execução: " + NumToString(nTempoMedioExecucao, "0.1f") + "ms" + CR +
"? Taxa de sucesso: " + NumToString(nTaxaSucesso, "0.1f") + "%" + CR +
"?? Throughput: " + NumToString(ArrayCount(m_arrHistoricoEventos) / 5.0, "0.1f") + " eventos/min" + CR +
"?? Uso de memória: " + (ArrayCount(m_arrHistoricoEventos) * 0.1) + "KB" + CR + CR +
"?? Performance excelente do sistema de eventos!"

Info(sRelatorio)

PRIVADO PROCEDIMENTO GerarRelatorioCallbacks()

sRelatorio é uma cadeia = "?? RELATÓRIO DE CALLBACKS" + CR + CR +
"?? Callbacks registrados por tipo:" + CR

PARA i = 1 À ArrayCount(m_arrCallbacks)
sStatus é uma cadeia = SE(m_arrCallbacks[i].bAtivo, "?", "?")
sRelatorio += "• " + m_arrCallbacks[i].sDescricao + " " + sStatus + CR +
" Prioridade: " + m_arrCallbacks[i].nPrioridade + " | Procedimento: " + m_arrCallbacks[i].sProcedimento + CR
FIM

sRelatorio += CR + "?? Todos os callbacks configurados e funcionando!"

Info(sRelatorio)

// ============================================================================
// BENEFÍCIOS DO SISTEMA DE CALLBACKS:
//
// 1. ARQUITETURA ORIENTADA A EVENTOS
// • Desacoplamento de componentes
// • Flexibilidade na resposta a eventos
// • Facilita manutenção e extensão
//
// 2. MONITORAMENTO AVANÇADO
// • Histórico completo de eventos
// • Análise de padrões de uso
// • Detecção de anomalias
//
// 3. PERSONALIZAÇÃO
// • Callbacks específicos por necessidade
// • Priorização de execução
// • Ativação/desativação dinâmica
//
// 4. DEBUGGING E ANÁLISE
// • Log detalhado de eventos
// • Estatísticas de performance
// • Rastreamento de problemas
//
// CASOS DE USO:
// • Sistemas de monitoramento
// • Aplicações interativas
// • Dashboards em tempo real
// • Análise de comportamento do usuário
// • Automação de processos
// • Integração com sistemas externos
// ============================================================================
```
User reviews
(To evaluate this resource, click 'Write a review')
You must
to post a review
Boller
ArcGIS é uma plataforma geoespacial completa e o principal software de Sistema de Informação Geográfica (SIG) desenvolvido pela Esri, usada para criar, gerenciar, analisar, mapear e compartilhar dados no contexto geográfico. Ela integra diversas aplicações, como o ArcGIS Pro para desktop e o ArcGIS Online baseado em nuvem, oferecendo ferramentas para análise espacial, visualização, colaboração e suporte à tomad.
ABOUT
RATING:
00No rating
DOWNLOADS:
35
PUBLISHED:
September 24, 2025
VERSION:
30
CONCERNS:
WINDEV, WEBDEV, WINDEV Mobile
Minimum version: 30
SIZE:
1.6 MB