OOP com python – Uma breve introdução.
Olá pessoal, tudo bem?
Tem muita novidade vindo, mas não é hora, nem lugar, nem o tema para falar sobre. Mas como o show tem que continuar, trago para vocês uma breve introdução sobre Orientação a Objetos com Python. Confesso que já venho estudando Python a algum tempo, mas nunca com tanta intensidade quanto agora, isso por que surgiram projetos para trabalhar com geodjango (uma framework web em python) e a descobri pyqgis.
Deixando de enrolação...
Bem, Python é uma liguagem Orientada a Objetos, mas que permite que você desenvolva aplicativos programando estrutural, é uma liguagem interpretada, que não exige que você indique o tipo da variável (dinamicamente tipada), possui fácil controle de bloco, o que te prende só ao código, sem ter que perder tempo analisando símbolos em casos de erro de sintaxe, e o melhor de tudo, é livre!
Para melhor compreensão, precisamos entender alguns conceitos, como classe, objeto, atributo e método. Para ser diferente (ou não!), começo falando de objetos. Objetos são todas as coisas as quais você deseja abstrair. Bem, você é um objeto! Como assim eu tou louco? É verdade, você é um objeto. Melhor, você alem de ser um objeto, você faz parte de uma classe... Não, esquece a geografia por equanto, que mané classe social... eu estou afirmando que você faz parte de uma classe, a dos Humanos. Legal né? Continuando, seus atributos, de fato são seus atributos (ou características, como queiram.), e os métodos, bem, esses se referem as ações tomadas por você hoje. Acho que você acordou, comeu, andou... Isso são os métodos, as ações tomadas pelos objetos!
E como desenvolver usando OOP com Python?
Para o desenvolvimento em Python usando OOP, é preciso conhecer algumas palavras reservadas, como class, que se refere a uma classe de objetos abstraídos, self que é um parametro que possibilita você fazer referencia a um argumento, substitui o this do Java, dentre outras que veremos conforme a necessidade.
Para exemplificar vou criar aqui um programa bastante simples que pede para você inserir uma mensagem, e esta mensagem é retornada para você. Vejamos:
class Mensagem:
def __init__ (self,pessoa,texto):
self.nome = pessoa
self.opniao = texto
def __str__(self):
saida = self.nome+ ' escreveu: \n' +self.opniao
return saida
nome_saida = raw_input ('Digite seu nome: ')
opniao_saida = raw_input ('O que você achou? \n')
print Mensagem(nome_saida,opniao_saida)
Explicando o código:
No método __init__ da classe Mensagem, foram jogados dois parametros: pessoa e texto. O self, primeiro parametro apresentado é padrao da linguagem, entao é conveniente utilizá-lo.
O trecho self.nome e self.opniao, sao referencias (instanciação)dos objetos antes apresentados: pessoa e texto.
O método __str__(), é mais um método mágico do Python, que determina o que será retornado do objeto.[1]
Perceba que este código sempre que invocado, ira inserir valores setados pelo usuário nos mesmo objetos, o que pra mim, é o segredo da OOP.
Finalizando
Bem, acho que deu para ter noção de como usar OOP em Python. Para maiores referencias sobre o assunto, aconselho visitar a Página da comunidade brasileira
Em breve, outras ferramentas Python... mas isto fica para um próximo post.
P.S.: Agradeço as correções sugeridas pelo amigo George, feitas no código, e ainda os ensinamentos sobre OOP.
Abraço a todos.
Vicente Martins
Convocando…
Fala pessoal, blz? Muito bom estar colaborando com toda essa gente boa que tem aqui.
Bem, o post de hoje é fruto de um plano antigo que venho alimentando desde o começo de 2009. Para quem me acomapanhava no blog antigo, sabe que venho estudando desenvolvimento já a algum tempo. Desde o começo do ano passado tambem me dedico a colaboração de projetos novos, como o ThubanGIS, e projetos mais sólidos, como GRASS GIS, e foruns que acho convenientes (Será que é o Geo.NET? Nããããoooo!!! kkkk). Estas colaborações passaram por elaboração de tutorias, até traduções de documentação, mas infelizmente não tive nenhum "BUM" que me fizesse parar para desenvolver alguma ferramenta (ou ao menos tentar...).
Atualmente trabalho com topografia/geodésia na Companhia de Habitação Popular da Paraíba, e sinceramente, estou achando bom demais... Falem o que quiser, mas CAMPO É BOM DEMAIS!
Navegando entre pesquisas por algum software livre que possibilitasse processar os dados de topografia (TS) e outros que processassem GPS, adivinhem: Dei com os burros n'água! Dái a velha sede por planos antigos voltou: Desenvolver um aplicativo que possibilitasse ler/processar os dados da TS e resolver as pendencias da topografia, bem como pós-prociessar os dados GPS. Bem, o desafio me foi lançado (por mim mesmo
) e aceito (por mim mesmo tambem
), então, a partir desta semana, as minhas terças e quintas estão ocupadas das 19:00 as 21:00. Desculpem todos que necessitarão de mim para as farras e bebedeiras, mas é nobre a causa!
Brincadeiras a parte, aproveito o espaço para convocar desenvolvedores, testers, designers e interessados no projeto para que possamos criar um equipe e trabalharmos juntos para o bem comum.
A causa é nobre e o apoio de vocês é extremamente importante.
Abraço a todos.
Vicente Martins
Hello World, ArcGIS style!
Boa noite pessoal,
Conforme prometi, vamos começar a brincar de ArcObjects.
Se vocês instalaram o Visual Studio 2005 (pode ser o Express, disponível gratuitamente) e depois instalaram o software development kit vocês não teram problema para acompanhar este simples guia.
Notas importantes
- Não irei focar no código. Não irei explicar detalhadamente o que cada função faz. Isto é trabalho de vocês.
- Irei ajudar na parte mais difícil: como começar. Existem algumas coisinhas que são chatíssimas quando programamos para ArcGIS, mas ainda bem que o próprio Visual Studio resolve algumas delas para nós.
Início
Primeiramente, abra o Visual Studio e peça um New Project. Selecione um Empty Project e dê um nome para seu projeto.
Depois de isso feito, termos algo mais ou menos assim:
O Visual Studio é extremamente personalizável, portanto não precisa se concentar em deixar sua tela exatamente igual a minha. Quero que você veja o Solution Explorer que fica à direita.
Vamos para o rock. O que iremos fazer?
Vamos criar uma simples barrinha de ferramentas que nos avisa quantas camadas temos em um determinado MXD. Simples né? Besta né? Mas isso vai ser o fundamento, coisas mais complexas virão.
Então vamos lá. Vá na raiz do projeto (escrito HelloWorldArcGIS) e clique com o botão direito. Clique em Add ArcGIS Reference.
O que isto exatamente faz? Bem, o ArcGIS como diversos softwares, são muito grandes, e não podemos/devemos referenciar todo o código junto. Para que adicionar referências que não iremos utilizar?
Certo, quando você clicar no botãozinho, irá aparecer uma janelinha. Vá na opção Desktop ArcMap e adicione as seguintes assemblies:
- ESRI.ArcGIS.ArcMapUI;
- ESRI.ArcGIS.ArcMap;
- ESRI.ArcGIS.Display;
- ESRI.ArcGIS.Framework;
- ESRI.ArcGIS.Geodatabase;
- ESRI.ArcGIS.System;
- ESRI.ArcGIS.Carto;
Clique em Finish.
Você verá que a pasta References foi atualizada. Vamos adicionar algumas assemblies do Windows e do .NET.
Siga o mesmo passo acima, mas ao invés de escolher Add ArcGIS Reference, escolha Add Reference. Uma caixinha irá se abrir, portanto em .NET, seleciona as seguintes assemblies:
- System
- System.Drawing
- System.Windows.Forms
Clique ok. Estamos good to go.
Nossas referências estão no lugar. Isto significa que poderemos utilizar código pronto contido nestas assemblies. Isto é importante e interessante que se aprenda cedo, senão algo pode deixar de funcionar simplesmente porque você nao colocou aquela referência...
Vamos agora criar uma barra de ferramentas para colocar nossas coisinhas nela.
Clique com o botão direito na raiz do projeto e clique em Add > Add New Item.
Selecione Base Toolbar e dê um nome à esta toolbar. Algo como HelloWorldToolbar, e clique em Add. Um tela irá aparecer perguntando qual tipo de barra de ferramentas você quer. Selecione ArcMap e boa.
Olhe suas referências. Elas foram atualizadas e adicionados alguns assemblies extras. Não se preocupe com eles. O Visual Studio é até inteligente para colocar algumas que você pode ter esquecido, mas só pelos canais oficiais (como este de adicionar uma toolbar). Se você criar uma classe e tentar herdar de BaseToolbar você provavelmente ganhará um erro.
Ele abriu um arquivo de código com a extensão .cs que contém diversas coisas, uns números muito doidos e por aí vai. Vamos explicar:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.ADF.CATIDs;
using ESRI.ArcGIS.ADF.BaseClasses;
namespace HelloWorldArcGIS
{
///
/// Summary description for HelloWorldToolbar.
///
[Guid("cc7ed839-de6c-46a7-9817-f4a3756cc57c")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("HelloWorldArcGIS.HelloWorldToolbar")]
public sealed class HelloWorldToolbar : BaseToolbar
{
#region COM Registration Function(s)
[ComRegisterFunction()]
[ComVisible(false)]
static void RegisterFunction(Type registerType)
{
// Required for ArcGIS Component Category Registrar support
ArcGISCategoryRegistration(registerType);
//
// TODO: Add any COM registration code here
//
}
[ComUnregisterFunction()]
[ComVisible(false)]
static void UnregisterFunction(Type registerType)
{
// Required for ArcGIS Component Category Registrar support
ArcGISCategoryUnregistration(registerType);
//
// TODO: Add any COM unregistration code here
//
}
#region ArcGIS Component Category Registrar generated code
///
/// Required method for ArcGIS Component Category registration -
/// Do not modify the contents of this method with the code editor.
///
private static void ArcGISCategoryRegistration(Type registerType)
{
string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
MxCommandBars.Register(regKey);
}
///
/// Required method for ArcGIS Component Category unregistration -
/// Do not modify the contents of this method with the code editor.
///
private static void ArcGISCategoryUnregistration(Type registerType)
{
string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
MxCommandBars.Unregister(regKey);
}
#endregion
#endregion
public HelloWorldToolbar()
{
//
// TODO: Define your toolbar here by adding items
//
//AddItem("esriArcMapUI.ZoomInTool");
//BeginGroup(); //Separator
//AddItem("{FBF8C3FB-0480-11D2-8D21-080009EE4E51}", 1); //undo command
//AddItem(new Guid("FBF8C3FB-0480-11D2-8D21-080009EE4E51"), 2); //redo command
}
public override string Caption
{
get
{
//TODO: Replace bar caption
return "My C# Toolbar";
}
}
public override string Name
{
get
{
//TODO: Replace bar ID
return "HelloWorldToolbar";
}
}
}
}
Vamos lá:
O que merece nota imediata:
- O construtor da barra de ferramentas. O construtor é o método responsável por instanciar um novo objeto do tipo HelloWorldToolbar. Veja que existem um monte de comentários ensinando como podemos inserir ferramentas ou botões nele. À seguir utilizaremos eles. Mas dê uma lida nos comments com carinho.
- A propriedade Caption. Nela temos "My C# Toolbar" como caption. Altere para o que achar melhor. Este nome é o nome que irá aparecer dentro do ArcGIS.
- A propriedade Name. Deve ser único. Portanto, é melhor nem mexer com isto, por enquanto.
- O restante são funções para registro/desregistro da barra de ferramentas. Isto é um pré-requisito, pois estamos trabalhando com tecnologia COM, se lembram? Não altere nada.
Nossa barra de ferramentas está criada, mas uma barra de ferramentas sozinha não me adianta de nada. Vamos criar umas ferramentinhas. Siga o mesmo procedimento que utilizou para criar a barra de ferramentas, mas desta vez, escolha BaseCommand e nomeie ele como achar melhor. No meu caso, vou dar o nome de ComandoHelloWorld.
Mais uma vez um prompt irá aparecer e te perguntar qual é o tipo de comando você quer criar. Vejamos...escolha Desktop ArcMap Command e boa.
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.ADF.BaseClasses;
using ESRI.ArcGIS.ADF.CATIDs;
using ESRI.ArcGIS.Framework;
using ESRI.ArcGIS.ArcMapUI;
namespace HelloWorldArcGIS
{
///
/// Summary description for ComandoHelloWorld.
///
// preste atenção neste valor aqui!
[Guid("2423ecdf-4f14-4993-a165-df9d79167f4d")]
// preste atenção neste valor aqui!
[ClassInterface(ClassInterfaceType.None)]
[ProgId("HelloWorldArcGIS.ComandoHelloWorld")]
public sealed class ComandoHelloWorld : BaseCommand
{
#region COM Registration Function(s)
[ComRegisterFunction()]
[ComVisible(false)]
static void RegisterFunction(Type registerType)
{
// Required for ArcGIS Component Category Registrar support
ArcGISCategoryRegistration(registerType);
//
// TODO: Add any COM registration code here
//
}
[ComUnregisterFunction()]
[ComVisible(false)]
static void UnregisterFunction(Type registerType)
{
// Required for ArcGIS Component Category Registrar support
ArcGISCategoryUnregistration(registerType);
//
// TODO: Add any COM unregistration code here
//
}
#region ArcGIS Component Category Registrar generated code
///
/// Required method for ArcGIS Component Category registration -
/// Do not modify the contents of this method with the code editor.
///
private static void ArcGISCategoryRegistration(Type registerType)
{
string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
MxCommands.Register(regKey);
}
///
/// Required method for ArcGIS Component Category unregistration -
/// Do not modify the contents of this method with the code editor.
///
private static void ArcGISCategoryUnregistration(Type registerType)
{
string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
MxCommands.Unregister(regKey);
}
#endregion
#endregion
private IApplication m_application;
public ComandoHelloWorld()
{
//
// TODO: Define values for the public properties
//
base.m_category = ""; //localizable text
base.m_caption = ""; //localizable text
base.m_message = ""; //localizable text
base.m_toolTip = ""; //localizable text
base.m_name = ""; //unique id, non-localizable (e.g. "MyCategory_ArcMapCommand")
try
{
//
// TODO: change bitmap name if necessary
//
string bitmapResourceName = GetType().Name + ".bmp";
base.m_bitmap = new Bitmap(GetType(), bitmapResourceName);
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message, "Invalid Bitmap");
}
}
#region Overriden Class Methods
///
/// Occurs when this command is created
///
///
Instance of the application
public override void OnCreate(object hook)
{
if (hook == null)
return;
m_application = hook as IApplication;
//Disable if it is not ArcMap
if (hook is IMxApplication)
base.m_enabled = true;
else
base.m_enabled = false;
// TODO: Add other initialization code
}
///
/// Occurs when this command is clicked
///
public override void OnClick()
{
// TODO: Add ComandoHelloWorld.OnClick implementation
}
#endregion
}
}
Pontos merecedores de notas:
- Novamente o construtor do comando. Ele tem diversas informações que são mostradas ao usuário no ArcGIS. Não irei explicar uma à uma, brinque com elas e teste.
- Um campo (field) importantissímo: m_application. Ele guarda uma referência de memória à sua aplicação que está rodando. Sem o software não teria como chamar coisas que estão lá dentro.
- Método OnClick(). Este método é que irá rodar quando o usuário clicar no comando. Nós implementaremos as coisinhas todas ali. Capiche?
Vamos adicionar nosso comando à barra de ferramentas. Lembram do construtor da barra de ferramentas, que contém alguns exemplos de Add?
Vá no seu comando e procure pelo valor GUID dele. O meu é 2423ecdf-4f14-4993-a165-df9d79167f4d. Digite isto (claro, com o seu valor GUID) no construtor da barra de ferramentas.
AddItem(new Guid("2423ecdf-4f14-4993-a165-df9d79167f4d"), 0);
Vamos tentar compilar. Aperte F6.
Um erro deve aparecer. Ainda não configuramos nossa aplicação para abrir com o ArcMap. Vá na raiz do projeto, clique com o botão direito e vá em Properties.
Você irá ver um monte de coisas.
Na parte de Application procure Output Type e escolha Class Library.
Em Build marque a última opção, Register for COM Interop. Lembra que tudo que fazemos com ArcObjects temos que fazer com COM? Ficou estranho isso, mas válá.
Vá em DEBUG e procure a seção Start Action. Marque Start External Program e localize o arquivo ArcMap.exe no seu computador. O meu fica em C:\Program Files\ArcGIS\bin\ArcMap.exe.
Tente compilar novamente. Aperte F6. Você não deve ver nenhum erro. O ArcGIS irá abrir sozinho.
Nossa barrinha de ferramentas esta lá!
Agora vamos implementar a nossa super-ultra-mega-complexa funcionalidade. Feche o ArcMap. Retorne ao Visual Studio.
Abra o arquivo de código do nosso comando. Suba até o topo de nosso arquivo.
Você verá um monte de coisas como using System.Drawing entre outros. Aqui nós dizemos ao Visual Studio quais assemblies este arquivo poderá acessar. Faltam duas importantes para nós aí.
Insira a assembly ESRI.ArcGIS.Carto e a assembly System.Windows.Forms. Lembre-se de colocar cada uma em uma linha, e não se esqueça do ponto-e-vírgula.
public override void OnClick()
{
// pegue uma referência ao documento que está rodando
// note o uso do campo m_application
IMxDocument documento = (IMxDocument)this.m_application.Document;
// pegue uma referência ao mapa atual
// note que caso tenha múltiplos data-frames isto pode não funcionar como esperado...
IMap mapa = documento.FocusMap;
// vamos contar quantas camadas temos no nosso mapa?
Int32 numeroCamadas = mapa.LayerCount;
// me diga quantas camadas eu tenho!
MessageBox.Show("Temos neste mapa " + numeroCamadas.ToString() + " camadas!");
}
Altere sua função OnClick nestes termos. Não copie e cole. Tente entender o que está acontencendo dentro do código. Digite linha por linha. Porque? Porque faz bem e o Visual Studio ainda irá mostrar para vocês a jóia de sua coroa, o Intellisense. Ele te sugere o que você pode estar precisando. Você conseguirá enxergar diversos atributos e propriedades de cada uma destas classes.
Tem bastante coisa interessante só nessas três classezinhas. Navegue. Use o EDN. Use o Help (F1). E poste suas dúvidas.
Bem, agora é com vocês. Me digam o que acharam. Foi difícil? À princípio vai ser difícil sim! Como meu bom e velho avô diz: rapadura é doce mas não é mole não!
Estou no aguardo das dúvidas, comentários e blasfêmias!
Espero que tenham gostado,
Um abraço,
George R. C. Silva
ArcObjects #1 – introdução
Boa tarde pessoal,
Mais uma vez venho a vocês com uma futura série de pequenos artigos, desta vez sobre ArcObjects, a API da ESRI para o desenvolvimento de funções que levam em conta o espaço e dados espaciais.
Bem, primeiramente devemos começar dizendo que ArcObjects não é um bicho de sete cabeças, é um bicho só de cinco. Não é nada complicado, quando você entende o que quer fazer e onde procurar.
Para quem está perdido, API é um conjunto de rotinas e funcionalidades já escritas que pode-se extender, através de programação. Ou seja, ArcObjects é essencialmente os blocos construtivos do software ArcGIS. Os caras na ESRI desenvolvem o ArcObjects e depois o usam para montar o ArcMap, por exemplo.
E realmente são muitos blocos. A API é composta (hoje, na versão 9.3) por quatro mil classes, cinco mil interfaces, mais de mil enumerações e cinquenta structs, isso sem contar os tipos escondidos e restritos!
Certo e o que mais precisamos saber sobre a API ArcObjects para começar a programar para o ArcGIS? Nada, na realidade, mas existem alguns conceitos que devem ser conhecidos. Toda a API foi desenvolvida seguindo o modelo COM (Component Object Model), o padrão para distribuição de bibliotecas binárias em ambiente desktop, desenvolvido pela Microsoft.
E isto muda tudo. A tecnologia COM estabelece padrões e exige alguns requisitos para que um software seja COM-compatible. Finalmente, devemos entender que COM é uma arquitetura, uma forma de desenvolver software.
A arquitetura COM é baseada em servidores e clientes. O servidor, ou o objeto, dá uma funcionalidade e o cliente a utiliza. Para facilitar ainda mais, um servidor pode ser um cliente e vice-versa. A arquitetura COM facilita a comunicação entre estes dois processos (servidor/cliente). Existem muitas particularidades da tecnologia, que realmente não cabem no escopo deste post, mas todos devem ficar de olho nisto, pois software mal desenvolvido que utiliza COM é software que um dia irá explodir. Esta arquitetura tem sérios problemas de perfomance e coleta de lixo.
Para saber mais, visite esta página e esta página.
Certo, o que podemos fazer com ArcObjects? Tudo o que podemos fazer dentro do ArcGIS, podemos fazer utilizando ArcObjects. Tudo e muito mais, claro. Como o próprio ArcGIS foi construído sobre ArcObjects, estamos na realidade falando de uma coisa só!
O que preciso para desenvolver em ArcObjects?
Bem, a API está implementada em uma porção de linguagens, sendo possível utilizar qualquer uma e realizar as mesmas tarefas. As linguagens suportadas são: VC++ (Visual C++), C# (minha favorita), VB.NET, Java e até VBA (cuidado, o suporte para VBA ACABOU!).
Não existe melhor ou pior, apenas diferente
. Caso você tenha experiência com uma ou outra, sugiro que comece pela linguagem que tem maior familiaridade, mas um aviso: existem tendências e a tendência é .NET (C# principalmente).
Após escolher sua linguagem de preferência, instale um IDE (Integrated Development Environment - como o Visual Studio, no caso de .NET) e instale as bibliotecas que veêm com o ArcGIS. Note que as bibliotecas já estão no CD de instalação do ArcGIS Desktop (as bibliotecas de programação para Desktop, claro).
Primeiro instale o ambiente de desenvolvimento e depois a biblioteca. Nunca o contrário.
Depois que tudo estiver instalado, sugiro que passe um tempo se familiarizando com cada IDE e com a referência oficial da ESRI. Ache um pequeno problema que lhe incomoda no ArcGIS (algo que poderia ser mais fácil, ou poderia ser diferente e facilitaria seu trabalho - imagino que existem diversas coisas) e tente criar alguma coisa em ArcObjects para isto.
Como são muitas classes e interfaces, não se preocupe em conhecer todas, se preocupe em conhecer como achar na referência oficial dados sobre determinada classe/interface.
Aviso aos navegantes: é muito comum em ArcObjects você ter de instaciar dois, três ou quatro objetos para fazer uma coisinha simples (como é o caso das interfaces IFields e IFieldsEdit, IField e IFieldEdit, entre outras).
Os namespaces mais utilizados, provavelmente são esriSystem, ArcMap, ArcMapUI, Geometry e Geodatabase. Todos tem sua própria página na ESRI, incluindo um diagrama completo do mesmo.
Caso tenham dúvidas, estamos aqui! Próximo post: Hello World, ArcGIS style!
Abraços
George
#Python – pt4
Como disse anteriormente o Python é a linguagem "preferida" pela ESRI para se construir ferramentas e modelos de geoprocessamento.
Na última vez, usei um exemplo pequeno, mas até útil.
Hoje vou mostrar como se pode fazer múltiplas operações, com uma só Feature Class.
O Python é ótimo em executar tarefas tediosas e repetitivas, daquelas que gastaríamos anos para terminar se feito na mão.
Imagine que você precise converter uma série de SRTMs para pontos, juntá-los, e depois interpolar tudo isso (espero que seu computador seja bom
)
Vamos ao exemplo:
#lembrem-se que o python faz questão de código identado, se ele não tiver identado, não funcionará.
#aqui ao invez de espaços usaremos -
#vamos importar nossas coisas
import sys, os, arcgisscripting, string
gp = arcgisscripting.create(9.3)
diretorio = raw_input("Digite o diretório que contém os rasters. Não se esqueça de duplicar as barras \\, senão não conseguirei achar o caminho...")
#aqui você pode indicar qualquer coisa, um diretório, um banco de dados SDE e até um banco de dados file/personal.
if diretorio:
----pass
else:
----print "Workspace/Espaço de trabalho inválido. Reinicie o script e tente denovo."
----exit()
gp.Workspace = diretorio
ListaRasters = gp.ListDatasets("*","Raster")
#se tivessemos escolhido "SRTM*" ao invés de "*" o Python listaria todos os rasters que começam com as letras SRTM
gp.AddToolbox("conversion") #adiciona a toolbox conversion
gp.AddToolbox("sa") #adiciona a toolbox do spatial analyst - só funciona para quem TEM a licença eim pessoal.
gp.AddToolbox("management") #adiciona management
#já temos nossas ferramentas, mãos à obra.
for Raster in ListaRasters:
----OutFeature = diretorio + "\\" + "ponto_convertido_" + Raster
----gp.RasterToPoint_conversion(Raster,OutFeature)
----print Raster + " convertido para ponto."
#vamos listar nossas feature classes de ponto. lembra do "*"?
ListaFeatureClasses = gp.ListFeatureClasses("ponto_convertido_*","POINT")
#assim garantimos que só vamos mosaicar as featureclasses convertidas e não outras perdidas no mesmo workspace, e claro só do tipo ponto
#a ferramenta merge exige uma lista das featureclasses a serem juntadas separadas por ponto e virgula, entao vamos dar a ela o que ela quer!
OutputMerge = gp.Workspace+"\\" + "MergeFinal"
gp.Merge_management(string.join(ListaFeatureClasses,";"),OutputMerge)
#a funcao join concatena uma lista utilizando um caractere (ou caracteres separadores) ou seja: ['shape1','shape2',shape3'] viram shape1;shape2;shape3
print "Já está tudo junto, vamos interpolar?"
print "interpolando. deve demorar, vá tomar um café..."
gp.Idw_sa(OutputMerge,"VALUE",gp.workspace+"\\"+"raster_interpolado",30,1)
print "interpolado. parabens!"
Bem pessoal, não testei o código, mas deve funcionar de acordo. O python é muito poderoso e suas funções internas se encaixam muito bem com a API da ESRI. Vejam na parte do Merge. Em outras linguagens teriamos de escrever loops e loops para concatenar as palavras daquela maneira, mas em python tudo é feito rapidinho!
Espero que gostem e que comecem a utilizar Python no seu dia a dia. É de fato um negócio muito útil. 1 hora para escrever um script, mas te salva 80mil horas de trabalho chato, cansativo e passível de erro humano.
Ahn! Não se esqueçam de consultar a documentação das funções utilizadas (join do Python, Merge_management, RasterToPoint_conversion e IDW_sa). Todas as versões do Help do ArcGIS possuem essa documentação. É só apertar F1 e correr para o help de cada ferramentinha, na última parte delas, Scripting. Se acharem algum erro no código postados, favor dar um toque que eu corrijo.
Python Rocks!
#Python – pt3
Vou mostrar a segunda maneira. Os scripts criados pelo ArcGIS são bastante simples, mas é preciso um pouco mais de base teórica, então fica pra depois.
Bem, para isso precisamos utilizar umas manhazinhas. Esta solução vai em duas partes, e poderia ser muito mais complexa, mas o Python vai nos ajudar.
Primeiramente, como perguntar qualquer coisa ao usuário? O Python tem uma pequena função chamada raw_input.
A função raw_input tem como único argumento opcional uma mensagem à ser passada ao seu usuário, mostrando a ele o que ele tem de digitar:
pasta = raw_input("Digite a pasta onde se encontram os shapefiles. ")
#funciona
pasta2 = raw_input()
#funciona também, mas sem mensagem
Bem, antes do script rodar e começar a tentar processar as pastas, é bom testar se o valor que o usuário digitou é válido. Existem diversas validações que poderiam ser executadas, mas vamos usar uma em especial.
#lembre-se que cada - equivale à um espaço e um conjunto com ---- equivale à uma tabulacao.
import sys, os, arcgisscripting
pasta = raw_input("Digite a pasta que deseja projetar. Lembre-se de duplicar as barras \\ senão não acho o caminho. ")
if os.path.isdir(pasta) == true:
----#é uma pasta válida e existe.
----#processe
else:
----#não é uma pasta válida.
----#imprima uma mensagem de erro e saia do script.
----print "Erro, a pasta indicada não é válida."
----exit
Bem pessoal, esse é o começo de tudo. Não repetirei os processamentos com o arcgisscripting, e isso é pra vocês estudarem e tentarem por aí.
Não se esqueçam, o F1 do Python traz a ajuda da versão utilizada, que contém as assinaturas de funções (quais são os paramêtros de entrada e qual é a saída), notas importantes e exemplos de como usá-las.
Agora, como permitir o usuário escolher o datum? Essa é um pouco mais difícil. Teremos de usar um outro tipo de dados do Python, chamado dicionário, que é tão poderoso quanto as listas, mas existem algumas diferenças sobre ele. O dicionário não suporta aquela maravilha de "for x in lista:", pois ele é um...dicionário, e não uma lista.
Os dicionários tem alguns métodos que nos ajudam a achar o que queremos:
a = {'SAD6922SUL':'\\Coordinate Systems\\Projected Coordinate Systems\\Utm\\Other GCS\\South American 1969 UTM Zone 22S.prj'}
Este é um dicionário com somente uma entrada. Enquanto as listas utilizam a posição de cada item (de 0 à n), os dicionários utlizam as keys. No caso supracitado, a key para este endereço monstro é SAD6922SUL, ou seja, ela armazena um valor, que é o diretório para este datum.
Métodos:
len(dicionario) retorna o tamanho do dicionario.
k in dicionario. Verdadeiro se a chave k está presente no dicionario dicionario.
k not in dicionario. Verdadeiro se a chave k NÃO está presente em dicionario.
dicionario.has_key(k). Mesmo que k in dicionario. Versão nova da função.
dicionario.keys(). Copia as keys para uma lista.
dicionario.values(). Copia os valores para uma lista.
dicionario[k] = v. Adiciona uma chave k com o valor de v no dicionario.
Existem outros métodos, mas estes são os mais básicos e necessários para começar.
Imagine o seguinte dicionario:
dicionarioDatums = {'sad69utm22s':\\Coordinate Systems\\Projected Coordinate Systems\\Utm\\Other GCS\\South American 1969 UTM Zone 22S.prj',
'sad69utm23s':'\\Coordinate Systems\\Projected Coordinate Systems\\Utm\\Other GCS\\South American 1969 UTM Zone 23S.prj',
'sad69utm24s':'\\Coordinate Systems\\Projected Coordinate Systems\\Utm\\Other GCS\\South American 1969 UTM Zone 24S.prj'}
e o código a seguir:
chaveDatums = dicionarioDatums.keys()
for chave in chaveDatums:
----print chave
datumEscolhido = raw_input("Digite o datum de sua escolha. ")
if datumDicionario.has_key(datumEscolhido):
----#processo
else:
----print "Você não escolheu um datum válido. Reinicie e tente novamente."
Bem, veja que hoje apenas estruturei a solução. Quero ver algum código aí nos comentários. Alguém tem uma outra idéia para fazer isso?
É bom notar que existem melhoras a serem feitas neste script, por exemplo, forçar o usuário a digitar algo correto no último raw_input, e software não sair daí enquanto ele não o fizer. Existe também a possibilidade de se mapear a pasta Coordinate System automaticamente, sem a necessidade de sempre que precisarmos de um datum novo, que não está na lista, reescrever o código. Deem suas sugestões e espero ter ajudado.
Abraço
George
#Python – pt2
Buenas pessoal,
Bem, Python, como expliquei no post passado é uma linguagem de alto nível e muito recomendada pela ESRI para se construir modelos de geoprocessamento (semelhantes aos construídos no ModelBuilder) e scripts para processamento de informações.
Primeiro, para quem deseja aprender Python:
Aqui encontramos algumas coisas fundamentais, como documentação e links para trocar idéias com a comunidade que desenvolve em Python.
Segundo: irc.freenode.net nos canais #python e #python-br . Nestes locais é possível conversar com desenvolvedores brasileiros e internacionais e resolver possíveis dúvidas.
Terceiro: este aplicado a quem quer integrar esta poderosa ferramenta aos seus métodos de trabalho - WebHelp ESRI e WebHelp Esri 2.
Não tenha medo de errar e não tenha medo de buscar ajuda.
Então vamos lá.
Para qualquer coisa que você queira fazer em python, é necessário importar o módulo que cuida dos objetos geográficos da ESRI, o arcgisscripting.
#importando o módulo arcgisscripting
import arcgisscripting
Quando um script .py contém esta instrução (ela deve ser feita no ínicio do seu script), o python deixa a sua disposição os objetos da ESRI. No webhelp você pode encontrar uma descrição ampla de TODOS eles, bem como exemplos.
Certo, mas depois que este módulo está disponível, o que fazemos para começar a mexer com o ArcGIS?
É necessário criar um objeto do tipo geoprocessing, fornecido pelo módulo arcgisscripting. Olhem o exemplo
gp = arcgisscripting.create()
#este método, sem parâmetros serve tanto para 9.2 quanto para 9.3
#para 9.3, é melhor especificar o paramêtro 9.3 e.g.: gp = arcgisscripting.create(9.3)
O que podemos fazer com o Python? Bem, em teoria, tudo o que estiver disponível dentro de uma Toolbox do ArctoolBox também está disponível para o Python. O Python na verdade, consegue fazer qualquer coisa que esteja em uma toolbox e ainda mais!
Lembre-se que o Python contém muitos módulos, como acesso à sítios remotos, módulos para gerenciar emails, matemáticos, FTP, conversores para PDF, acesso à banco de dados (MSSQL, PostgreSQL, SQLite, entre outros), manipuladores XML...ou seja, é muito flexível e extensível.
Para realizarmos operações dentro do ArcGIS, temos que utilizar o módulo sys e geralmente o módulo os, ambos nativos no Python. Hoje não falarei de como construir scripts que rodam à partir do ArcGIS, apenas scripts que rodam diretamente da shell python (alguém conhece alguma utilidade pra isso? acessar objetos geográficos sem abrir o ArcGIS?)
Bem, imaginemos que queremos Projetar ou Definir projeção de diversos itens, ao mesmo tempo:
#projetar diversos shapefiles para uma única projeção
import sys, os, arcgisscripting
Caminho = "C:\\Pasta\\Shapefiles\\"
#no Python, temos de duplicar as barras, pois uma barra \ é interpretada como alguns
#caracteres especiais, como nova linha, tabulação, entre outros
gp = arcgisscripting.create(9.3)
#vamos projetar shapefiles/featureclasses. temos de utilizar
#as toolboxes correspondentes, entao vamos adicioná-las
gp.AddToolbox("C:\\CaminhoAtéAToolbox\\Nome da Toolbox.tbx")
#podemos adicionar tantas toolboxes quanto precisarmos
#só devemos lembrar que mesmo através de scripts Python, as licensas de extensões
#SÃO CHECADAS. se você não tiver o spatial analyst, o Python irá dar um chilique
gp.Workspace = Caminho
#vamos definir o workspace. No ArcGIS + Python, muita coisa depende do workspace.
#ele é basicamente um apontamento para o diretório correto.
ListaShapefiles = gp.ListDatasets("*","ALL")
#vamos criar um objeto do tipo lista, e inserir nela todos os objetos do arcgis.
#os parametros "*" e "ALL" está dizendo para o ArcGIS inserir na lista todos
#os objetos, sem especificação de tipo (que podem ser Feature, TIN, Raster e CAD)
print ListaShapefiles
#me mostre o que será projetado
projecao = "C:\\CaminhoAteAProjecao\\Projecao.prj"
for Shapefile in ListaShapefiles:
----gp.Project_management(Shapefile,Shapefile+"_projetado",projecao)
----print "Projetei " + Shapefile
#considere os quatro - como uma identação, um toque na tecla tab (o blog está engolindo os espaços)
#fim
Este script é bem simples, deve ser salvo como .py, e ser rodado através da shell python ou com dois cliques no mesmo (desde que o Python esteja devidamente e corretamente instalado).
Algumas notas no entanto: note a forma que duplicamos as barras. Se você utilizar somente uma barra o Python não conseguirá achar os caminhos corretamente.
Os nomes de saída da função project são Shapefile_projetado.
A identação no trecho "gp.Project_management..." é PROPOSITAL E DEVE ESTAR LÁ. SEM ELA O SCRIPT NÃO FUNCIONARÁ. O Python usa a identação obrigatória como forma de controle de código.
Não se esqueça, tudo o que vem depois de # é considerado pelo Python um comentário, não influenciando no programa.
Note que para projetar uma pasta/set de shapefiles diferentes, temos que alterar a variável Caminho, lá em cima. O que podemos fazer para dinamizar esta questão? Como podemos perguntar ao usuário qual é a pasta que precisamos projetar? E a projeção, como definir ela dinamicamente? Essa fica de dever de casa
E agora senhores, o que podemos fazer com Python? Podemos utilizar todas as Toolboxes do ArcGIS para realizar milhares de operações com diversos shapes/featureclasses, e até mesmo cosntruir modelos complexos, do tipo que vemos em ModelBuilder, simulando eventos.
Vamos aprender Python?
#Python – o que é?
Olá pessoal,
Primeiro gostaria de falar sobre a Geo Rede. GeoRede é um projeto do site Geo.NET, um agregador de feeds de diversos blogs sobre Geoprocessamento/Sensoriamento Remoto em geral.
Estou lá também! Depois passem lá e deêm uma olhada. Se você não conhece o Geo.NET é mais uma coisa bacana. Fórum, seção de downloads e muito mais.
Bem, hoje falo para os usuários de ArcGIS. Vocês já devem ter notado, que durante a instalação do ArcGIS ele te pergunta/pede para instalar uma linguagem de programação chamada Python. Bem, se algum de vocês já abriram a aba dela no menu Iniciar do windows devem ter se deparado com algo bastante simples, a IDLE. A IDLE é um shell que intepreta comandos em Python. Algo como o DOS.
Bem, não dá pra fazer muita coisa pela IDLE, já que estamos limitados a "programas" de uma linha. Mas o porque estou falando de Python? O ArcGIS, felizmente, tem um ambiente customizável e permite ao usuário mais avançado a desenvolver suas próprias ferramentinhas, para executar uma infinidade de ações. Desde tarefas de "geoprocessamento" (geoprocessing) à customizar suas layers e representações.
Existem duas maneiras de se estender o ArcGIS. Uma delas é através de uma linguagem compilada .NET (ou VBA) e através do Python.
De acordo com a própria ESRI, a linguagem recomendada para se trabalhar com geoprocessing é Python. O .NET é mais fácil caso você precise estender a GUI (Graphic User Interface) e montar coisinhas mais complexas. O Python é recomendado para geoprocessing e a criação de ferramentas mais simples justamente pelo Python ser simples. A linguagem Python, criada em 1991, é considerada VHLL (Very High Level Language) e traz enormes facilidades para desenvolvedores iniciantes.
Primeiramente, ela é dinamicamente tipada (what the hell?!). Bem isso significa que não é necessário declarar com QUE tipos de variáveis queremos trabalhar antecipadamente. Você coloca alguma coisa na variável e o Python identifica o que ela é pra você. Ou seja, não existe muita confusão no momento de falar que A = 3 ou A = "spam". (neste exemplo, A = 3, representa automaticamente que A é uma variável do tipo inteiro e que em segundo momento, ela é do tipo string)
Segundamente, Python não é uma linguagem compilada. Não é necessário desenvolver um arquivo executável ou algo do tipo, ela é interpretada conforme o Python lê o código digitado. Isso traz uma perda de velocidade (nada muito importante) mas o ganho em agilidade no desenvolvimento compensa.
Python tem tipos muito flexíveis, como listas e dicionários. Não entrarei em detalhes, mas você pode com uma única expressão, criar uma lista com valores que você esteja trabalhando e de forma mais fácil ainda, ler os mesmos.
Um exemplo de lista, que sempre estão entre COLCHETES:
ListaTeste = ['spam','geoprocessamento',2,['arcgis','envi','arcsde']]
Temos na lista acima os items 'spam', 'geoprocessamento',2 e uma outra lista! aninhada, com os objetos 'arcgis','envi' e 'arcsde'. Listas são o carro-chefe do Python e devem ser aprendidas o quanto antes. Através delas podemos fazer o capeta com muito pouco código.
Agora, como integro ArcGIS com Python? A ESRI disponibiliza uma "API" própria para manipulação (de seus) objetos geográficos, como Feature Classes, Layers, Datasets, Geodatabases entres outros.
tudo o que tiver após # são considerados comentários, e não são interpretados pelo Python.
Um exemplinho simples de um script em Python (embora não muito útil) manipulando dados do ArcGIS seria:
import os, sys, arcgisscripting
gp = arcgisscripting.create(9.3) #vamos criar um objeto do tipo geoprocessing, versão 9.3
ListaCamadas = gp.ListDatasets(r"C:\teste python\geodatabase.gdb")
#pega uma lista dos featuredatasets no geodatabase.gdb
for camada in ListaCamadas: #para cada camada em ListaCamadas
print camada #imprima camada
#a resposta do Python vai ser algo assim.
>>>>['Hidrografia','Altimetria','Geologia','Transportes']
Bem, vejam como é fácil andar pelas listas e realizar operações em série. Os loops em Python são descomplicadíssimos.
Sugiro que agora, corram ao site da ESRI, e deem uma olhada nos geoprocessing Objects. Eles podem facilitar muito a vida de um utilizador de SIG.
Um abraço
Sql Server 2008 e o sistema de uma projeção só
Boa noite pessoal,
Estava trabalhando em alguns assuntos no Sql Server 2008 e até aí tudo bem. Tinha alguns dados em outro banco de dados, representativos de pontos. Tudo UTM SAD69. O banco do GIS em Lat/Long SAD69.
As tabelas eram mais ou menos assim:
CREATE TABLE foo ( id SERIAL NOT NULL, x DOUBLE PRECISION NOT NULL, y DOUBLE PRECISION NOT NULL, z DOUBLE PRECISION NOT NULL, sistema_coordenada VARCHAR(20) NOT NULL,0 -- etc );
Sempre com diversos pontos e diversos sistemas de coordenadas.
Bem, a idéia era montar uma visão no banco de dados, registar a parada com o ArcSDE, e disponibilizar os dados que eu queria em tempo real para os usuários do GIS, inclusive eu.
Liguei em uma certa empresa que comercializa um certo software, no suporte. Expliquei a situação, perguntei se o rapaz ou alguém lá saberia de uma solução para realizar o idealizado. De forma alguma (eu) estava viajando na maionese, pela minha experiência (que não é muita) com o PostGIS, sabia que era fazível.
O certo indivíduo que me atendeu, deve ter feito uma cara do outro lado de "What the hell?" sugeriu que eu jogasse minha tabela no ArcMap e rodasse um XY para plotar os dados. Valeu pela super dica amigão. Se você ler isto e lembrar de mim sabe que existe uma forma!
Mas vamos lá. O PostGIS, que é um tanto mais avançado que o Sql Server 2008 nesses quesitos, bastaria o seguinte para criar uma visão espacial (com um ponto de verdade, e não um par de coordenadas) e transformar a parada para o datum que eu queria:
CREATE OR REPLACE VIEW view_foo AS
SELECT ST_Transform(ST_Point(X,Y),4618), coluna1, coluna2 from foo;
Bem, simples né? Acontece que o SQL Server 2008 NÃO POSSUI funções nativas para conversão de coordenadas/projeção de um sistema para outro.
Um camarada do trabalho, Danilo, me falou que já havia visto no CodePlex, um site com um repositório de código da Microsoft, um projeto que realizava o serviço. Bem, o projeto, Sql Spatial Tools, tem muita utilidade e outras funções, como agregador de geometrias, mas as funções de conversão de coordenadas estava furada. Pelo menos a que nós precisávamos usar.
Lembrei que o PostGIS, que também não tem esta capacidade nativa, mas é fornecida pela Proj4, e talvez poderíamos utilizar a Proj4. Mais uma busca no Codeplex e achamos a ProjNET, uma adaptação da Proj4 (acho que é escrita em C) para .NET, em C#.
Utilizamos o modelo da Sql Spatial Tools para registrar bibliotecas externas (muito top, parabéns Sql Server, muito tetinha de fazer) e para expor uma única função que criamos para o Sql Server. A ProjNET, ao contrário da Sql Spatial Tools, realmente converte as coordenadas.
Dicas
-
Sempre olhe no Codeplex.
-
Para registrar uma dll externa (dentro do Sql Server) utilize (isto é código SQL): CREATE ASSEMBLY ProjNet 'caminhoParaDll'
-
Para registrar uma função: CREATE FUNCTION nomeFuncao (parametros) returns tipoRetorno AS external ProjNet.Namespace.Funcao
É só.
No final nossa idéia ficou similar a do PostGIS, and it works. Resultado: utilizamos os dados que temos, sem a necessidade de administrar/atualizar FeatureClasses e realizar tarefas tediosas de Add XY data-Project Data e propensas à erros. E o melhor de tudo, é tudo em tempo real. Se o outro sistema for atualizado às 10:01:01:0001, nós iremos ver os dados atualizados às 10:01:01:0002.
Lições aprendidas
-
Novamente, sempre olhe no CodePlex.
-
É muito fácil desenvolver/linkar APIs e outros frameworks ao Sql Server 2008.
-
Nunca, nunca confie no suporte técnico oferecido.
Thank you notes/Agradecimentos
Danilão! Pelo tempo gasto nisso e paciência.
Onald McDonald e Ogerio McDonald, pela torcida.
Ed Katibah, lead developer at Microsoft, who exchanged several emails with me and noticed that their implementation of Sql Spatial Tools is not correct (for UTM projections), and opened a ticket for fixing. Soon Sql Spatial Tools will be ready to handle all conversions.
History Tables – pt 1
Boa noite pessoal.
Uns posts atrás falei sobre uma função que permitisse e criasse automaticamente as regras e tabelas para armazenamento de registros históricos no PostGIS.
Bem, aqui vão algumas questões: O PostgreSQL nos permite lidar com este tipo de situação de duas formas: Rules e/ou Triggers.
No caso do nosso projetinho, foram utilizadas rules para lidar com o que precisamos fazer. Bem, o que deve ter um histórico de feições?
Primeiramente ele deve guardar todas as feições inseridas, atualizadas e deletadas, bem como a data, hora, nome do usuário que realizou a alteração, e uma coisa interessante, qual é a versão atual daquela feição. Desta forma podemos rastrear quais foram as alterações históricas de cada versão e caso preciso, achar a versão mais apropriada e restaurá-la para o banco de dados principal.
Além disso, temos um registro histórico de fato. Sabemos todas as alterações de uma feição. É possível entender como um lote mudou, por exemplo, ou como um animal rastreado por GPS está se movimentando. Outra coisa bacana, podemos saber como está evoluindo a cobertura vegetal de uma determinada região. Aumentou? Diminuiu? Não existe ambiguidade ou imperícia. Tudo pode ser restaurado e analisado de acordo com uma dimensão extra, o tempo.
Bem, vou postar aqui a estrutura de uma tabela histórica:
CREATE TABLE foo_history ( history_id SERIAL NOT NULL, date_created timestamp NOT NULL DEFAULT NOW(), date_deleted timestamp DEFAULT NULL, operation VARCHAR(20) NOT NULL, user VARCHAR(80) NOT NULL DEFAULT CURRENT_USER, current_version VARCHAR(80), LIKE foo, CONSTRAINT foo_history_pk PRIMARY KEY(history_id) );
É mais ou menos isso. Deêm uma olhada na linha 8, a expressão LIKE foo. Ela diz ao PostgreSQL que ele deve procurar a estrutura da tabela foo, e copiar ela todinha embaixo. Legal não? Imagine a tabela foo:
CREATE TABLE foo ( fid SERIAL NOT NULL, classe_vegetacao VARCHAR(30) NOT NULL, CONSTRAINT foo_pk PRIMARY KEY(fid) ); -- nossa tabela final gerada pela função é: CREATE TABLE foo_history ( history_id SERIAL NOT NULL, date_created timestamp NOT NULL DEFAULT NOW(), date_deleted timestamp DEFAULT NULL, operation VARCHAR(20) NOT NULL, user VARCHAR(80) NOT NULL DEFAULT CURRENT_USER, current_version VARCHAR(80), fid INTEGER, classe_vegetacao VARCHAR(30), CONSTRAINT foo_history_pk PRIMARY KEY(history_id) );
*Uma particularidade: qualquer campo do tipo SERIAL (como fid, na tabela foo) é realmente do tipo INTEGER. Quando declaramos SERIAL, o PostgreSQL entende que deve criar uma sequência específica para aquele campo e escolhe o valor padrão para aquele campo o próximo valor daquela sequência.
Bem, para começar precisamos de um código SQL que gere automaticamente este código acima. Ele precisa gerar a tabela sem que o usuário digite nada, apenas escolha a tabela que ele quer montar um registro histórico.
Nosso código também precisa montar automaticamente as regras que vão realizar a gestão desta tabelinha acima. Lembre-se que precisamos de uma regra para cada tipo de modificação na tabela, uma para INSERT, uma para UPDATE e uma para DELETE.
Cada uma tem uma particularidade, pois as alterações na tabela histórica não são as mesmas. A regra para delete, por exemplo, não deve criar novo registro na série histórica, apenas indicar que o registro foi deletado.
Não é muito complicado, mas também não é muito simples. Daqui uns dias falo deste códigozinho e dou umas dicas sobre ele.
George Silva




