<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog Geo.NET &#187; ArcObjects</title>
	<atom:link href="http://blog.geoprocessamento.net/tag/arcobjects/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.geoprocessamento.net</link>
	<description>Geoprocessamento, SIG e Sensoriamento Remoto</description>
	<lastBuildDate>Wed, 21 Sep 2011 12:00:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.5</generator>
		<item>
		<title>Cascading Class Extensions</title>
		<link>http://blog.geoprocessamento.net/2011/07/cascading-class-extensions/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=cascading-class-extensions</link>
		<comments>http://blog.geoprocessamento.net/2011/07/cascading-class-extensions/#comments</comments>
		<pubDate>Mon, 11 Jul 2011 12:35:31 +0000</pubDate>
		<dc:creator>George Rodrigues da Cunha Silva</dc:creator>
				<category><![CDATA[George Silva]]></category>
		<category><![CDATA[ArcObjects]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[ESRI]]></category>

		<guid isPermaLink="false">http://blog.geoprocessamento.net/?p=1299</guid>
		<description><![CDATA[


Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2011/02/arcobjects-e-class-extensions-2/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #2'>ArcObjects e Class Extensions #2</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/12/arcobjects-e-class-extensions-1/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #1'>ArcObjects e Class Extensions #1</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/02/hello-world-arcgis-style/' rel='bookmark' title='Permanent Link: Hello World, ArcGIS style!'>Hello World, ArcGIS style!</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Olá pessoal, este aqui é um post com mais substância que os outros.</p>
<p style="text-align: justify;">Hoje estou trabalhando em um projeto comp</p>
<p style="text-align: justify;">lexo com requisitos, bem, acima da média. Nosso usuário é bastante exigente e com razão. Há uns milhares de posts atrás, falei sobre class extensions <a title="ce1" href="http://blog.geoprocessamento.net/?p=1029" target="_blank">aqui </a>e <a title="ce2" href="http://blog.geoprocessamento.net/?p=1059" target="_blank">aqui</a>.</p>
<p style="text-align: justify;">Class extensions são uma forma muito poderosa se customizar o comportamente básico do ArcGIS, em qualquer versão ou em qualquer ambiente. Elas funcionam em Java, C#, com server, em desktop e com ArcEngine. São praticamente universais para os produtos ESRI. Além disso, são relativamente fáceis de implementar e não possuem muitos requisitos.</p>
<p style="text-align: justify;">Só possui um único requisito de deploy:</p>
<ul style="text-align: justify;">
<li>O código desenvolvido necessita estar na máquina (cliente, server, ou qualquer coisa que o valha - e claro, não o código, mas sim os binários que foram gerados);</li>
</ul>
<p style="text-align: justify;">E uma limitação:</p>
<ul style="text-align: justify;">
<li>Uma tabela ou feature class, só pode ter uma e somente uma, class extension.</li>
</ul>
<p style="text-align: justify;">Tudo bem até aí. Nos primeiros posts falei de class extensions que poderiam herdar funcionalidade de outras class extensions. Mas o código cresce rapidamente e se temos que cuidar de um ou mais comportamentos na mesma class extension, isso pode ficar simplesmente <strong>insuportável</strong> para o desenvolvedor.</p>
<p style="text-align: justify;">Uma outra maneira de se fazer as coisas é através de composição. Ao invés de criarmos uma hierarquia complexa de class extensions, na qual a CE mais específica deriva da CE mais geral, foi necessário construir uma class extension que fosse extensível, mas <strong>sem recompilar o código</strong> e sem afetar o funcionamento básico de outras funcionalidades.</p>
<p style="text-align: justify;">Uma das partes do problema é que elas são configuráveis através de um conjunto de dados, o objeto IPropertySet. Acessá-lo não é difícil, mas traz uma chateação à mais para o desenvoledor.</p>
<p style="text-align: justify;">Bem, o que fizemos: abstraimos toda a funcionalidade da class extension. A única class extensions verdadeira que temos contém uma referência à um grupo de classes que implementam as funcionalidades, mas <strong>não são registradas</strong> na classe. Isso nos permite adicionar e ou remover uma parte da funcionalidade sem afetar as outras.</p>
<p style="text-align: justify;">Temos basicamente três objetos principais:</p>
<ul style="text-align: justify;">
<li>Uma class extension geral (a quem chamamos de <em>polimórfica</em>);</li>
<li>Um ClassExtensionContainer (que segura referências à outras classes que fazem todo o trabalho);</li>
<li>Uma fábrica de ClassExtensionContainer. Como não queremos que a nossa class extension determine quais serão as funcionalidades que ela executará, não podemos deixar à cargo da mesma a criação do nosso container.</li>
</ul>
<p style="text-align: justify;">Agora, por que separar esses caras assim? Bem, queremos que nossa class extension (que será registrada com nossa feature class ou tabela) consiga ser executada, independente do que existe no container. E não queremos que ela crie o container, pois bem, existem várias maneiras de criá-lo, e.g. chamada direta, lendo um arquivo texto ou até mesmo acessando um banco de dados. Por isso criamos a fábrica. Se quisermos mudar a maneira de como criar o container, só mudamos a fábrica e não nosso projeto completo.</p>
<p style="text-align: justify;">Bem, o projeto é mais ou menos assim:</p>
<p style="text-align: justify;">
<pre name="code" class="c-sharp">
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Core.Model;
using ESRI.ArcGIS.ADF.CATIDs;
using ESRI.ArcGIS.Editor;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using log4net;
using ILog = log4net.ILog;

namespace Core.Extension.ModelExtension
{
    [Guid("32f7294c-eaf3-4df1-90aa-03e2828f305e")]
    [ClassInterface(ClassInterfaceType.None)]
    [ProgId("Core.Extension.ModelExtension.PolymorphicExtension")]
    public class PolymorphicExtension :
        BaseClasse,
        IInterfaceCustomizadaQueImplementaInterfacesESRI, // IClassExtension, IObjectClass, etc.
        IObjectInspector
    {

        // código de registro com removido 

        private IClassExtensionContainer _container;

        public override void Initialize()
        {
            var dataset = (IDataset)_helper.Class;
            _elementType = DetermineElementType(dataset);
           // inicializamos o container.
            _container = ClassExtensionContainerFactory.CreateContainer(_elementType);

            // inicializamos outras class extensions, que talvez precisem de serem inicializadas!
            foreach(var ext in _container.Extensions)
            {
                ext.Init(_helper, null);
            }
        }

        public override void Shutdown()
        {

        }

        public override void OnChange(IObject obj)
        {
            foreach (var ext in _container.Extensions)
            {
                _log.InfoFormat("Disparando OnChange de {0}", ext.ExtensionName);
                ext.OnChange(obj);
            }
        }

        public override void OnCreate(IObject obj)
        {
            foreach(var ext in _container.Extensions)
            {
                _log.InfoFormat("Disparando OnCreate de {0}", ext.ExtensionName);
                ext.OnCreate(obj);
            }
        }

        public override void OnDelete(IObject obj)
        {
            foreach(var ext in _container.Extensions)
            {
                _log.InfoFormat("Disparando OnDelete de {0}", ExtensionName);
                ext.OnDelete(obj);
            }
        }

        public override string ValidateField(IRow row, string fieldName)
        {
            _log.InfoFormat("Validando campo {0}",fieldName);

            var sb = new StringBuilder();

            foreach (var ext in _container.Extensions)
            {
                try
                {
                    _log.InfoFormat("Validando extensão {0}", ExtensionName);
                    sb.AppendLine(ext.ValidateField(row, fieldName));
                }
                catch (Exception ex)
                {
                    _log.ErrorFormat("Ocorreu um erro ao tentar validar o campo {0} em {1}", fieldName, ExtensionName);
                    _log.Error(ex.Message, ex);
                    continue;
                }
            }

            return sb.ToString();
        }

        public override string ValidateRow(IRow row)
        {
            _log.Info("Validando linha");

            var sb = new StringBuilder();

            foreach (var ext in _container.Extensions)
            {
                try
                {
                    _log.InfoFormat("Validando extensão {0}", ExtensionName);
                    sb.AppendLine(ext.ValidateRow(row));
                }
                catch (Exception ex)
                {
                    _log.ErrorFormat("Ocorreu um erro ao tentar validar a linha em {0}", ExtensionName);
                    _log.Error(ex.Message, ex);
                    continue;
                }
            }

            return sb.ToString();
        }

        public void Inspect(IEnumRow objects, IEditor editor)
        {
            _container.CustomInspector.Inspect(objects, editor);
        }

        public void Clear()
        {
            _container.CustomInspector.Clear();
        }

        public void Copy(IRow srcRow)
        {
            _container.CustomInspector.Copy(srcRow);
        }

        public int HWND
        {
            get { return _container.CustomInspector.HWND; }
        }
    }
}</pre>
<p>A principal sacada neste caso, é o nosso container. Ele contém uma referência para uma interface customizada, que implementa a parte principal dos comportamentos, que são:</p>
<ul>
<li>IObjectClassExtension</li>
<li>IClassExtension</li>
<li>IFeatureExtension</li>
<li>IObjectClassEvents</li>
<li>IObjectClassValidation</li>
<li>IObjectInspector (este cara aqui é para customizarmos o painel de edição default do ArcGIS! nosso container também contém ele!)</li>
</ul>
<p>Estas interfaces da ESRI que vão segurar toda nossas funcionalidades, quaisquer que sejam. Segue nosso container:</p>
<pre name="code" class="c-sharp">
public interface IClassExtensionContainer
 {
 List&lt;ICustomClassExtension&gt; Extensions { get; }
 IObjectInspector AirspaceInspector { get; }
 }</pre>
<p>Ele é só isso. A mágica fica na fábrica, que preenche este camarada e passa ele para nossa extensão de verdade. Depois que o container foi inicializado, durante o método Init() da classe principal - a própria CE inicializa as outras;</p>
<p>Este padrão é seguido nos outros métodos. Ela delega para as classes que contém funcionalidade as ações que devem ser executadas. Desta maneira conseguimos múltiplos comportamentos customizados e uma facilidade enorme para adicionar ou removê-los.</p>
<p>Por isso o nome de Cascading Class Extension. Na realidade, temos única class extension que cuida de tudo para nós, <strong>cascateando</strong> todo o comportamento interessante para nós.</p>
<p>O que acharam? ArcObjects não é complicado, é cheio de manhas. Depois que as conhecemos, fica muito fácil!</p>
<p>Ah, em nota: tenho desenvolvido algum código baseado em ArcObjects que vou disponibilizar em breve. Assim que disponibilizar, você poderá ver esta implementação acima, completa!</p>
<p>Abraços</p>
<p>George R. C. Silva</p>


<p>Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2011/02/arcobjects-e-class-extensions-2/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #2'>ArcObjects e Class Extensions #2</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/12/arcobjects-e-class-extensions-1/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #1'>ArcObjects e Class Extensions #1</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/02/hello-world-arcgis-style/' rel='bookmark' title='Permanent Link: Hello World, ArcGIS style!'>Hello World, ArcGIS style!</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.geoprocessamento.net/2011/07/cascading-class-extensions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Padr&#227;o de Projeto ActiveRecord e ArcObjects</title>
		<link>http://blog.geoprocessamento.net/2011/03/padro-de-projeto-activerecord-e-arcobjects/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=padro-de-projeto-activerecord-e-arcobjects</link>
		<comments>http://blog.geoprocessamento.net/2011/03/padro-de-projeto-activerecord-e-arcobjects/#comments</comments>
		<pubDate>Mon, 07 Mar 2011 04:17:57 +0000</pubDate>
		<dc:creator>George Rodrigues da Cunha Silva</dc:creator>
				<category><![CDATA[George Silva]]></category>
		<category><![CDATA[ArcObjects]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[ESRI]]></category>
		<category><![CDATA[ORM]]></category>

		<guid isPermaLink="false">http://blog.geoprocessamento.net/2011/03/padro-de-projeto-activerecord-e-arcobjects/</guid>
		<description><![CDATA[Boa noite pessoal! Depois de um tempinho apareço denovo! Hoje quero falar um pouco sobre padrões de projeto (Design Patterns) e a como acessar dados via ArcObjects. Como vocês sabem, os objetos da ESRI são bastante chatinhos de se trabalhar. Eles tem peculiaridades incríveis e se nos esquecermos delas vamos acabar nos dando mal! A [...]


Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2011/02/arcobjects-e-class-extensions-2/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #2'>ArcObjects e Class Extensions #2</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/12/arcobjects-e-class-extensions-1/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #1'>ArcObjects e Class Extensions #1</a></li>
<li><a href='http://blog.geoprocessamento.net/2011/07/cascading-class-extensions/' rel='bookmark' title='Permanent Link: Cascading Class Extensions'>Cascading Class Extensions</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p align="justify">Boa noite pessoal!</p>
<p align="justify">Depois de um tempinho apareço denovo! Hoje quero falar um pouco sobre padrões de projeto (Design Patterns) e a como acessar dados via ArcObjects.</p>
<p align="justify">Como vocês sabem, os objetos da ESRI são bastante chatinhos de se trabalhar. Eles tem peculiaridades incríveis e se nos esquecermos delas vamos acabar nos dando mal! A grande questão estamos falando de uma biblioteca enorme e temos, com certeza, algumas interfaces centrais. Duas delas, com certeza são IObject e IObjectClass.</p>
<p align="justify">Em termos simples, IObject é uma linha de uma tabela, enquanto IObjectClass representa a tabela como um todo. Quase tudo que armazenamos dentro de um geodatabase é uma IObjectClass e seus filhotes, um IObject – até mesmo <em>rasters</em>.</p>
<p align="justify">Mas porque é tão difícil acessar e manipular as informações utilizando a API da ESRI? Bem, não é que é difícil. Para coisas pequenas é bastante tranquilo e simples, exemplo:</p>
<pre class="c#" name="code">public class LeitorValores
{
	// esta classe lê os valores de uma tabela
	// ou feature class e os escreve na console.

	private IWorkspace _Workspace;
	private ITable _Tabela;

	public LeitorValores(IWorkspace workspace,string nomeTabela)
	{
		_Workspace = workspace;
		_Tabela = ((IFeatureWorkspace)workspace).OpenTable(nomeTabela);
	}

	public LerValores()
	{
		// poderiamos ter configurado o filtro como parâmetro

		IQueryFilter filter = new QueryFilterClass();
		filter.WhereClause = &quot;&quot;;
		// a query está vazia, pois queremos ler e escrever todos os valores;

		ICursor cursor = _Tabela.Search(filter,true);

                // aqui poderíamos ter utilizado a interface mãe: IObject
                // IObject tempObject = null;		

                IRow tempRow = null;
		// tempObjectt = cursro.NextRow() as IObject
		while ((tempRow = cursor.NextRow()) != null)
		{
			for (int i = 0; i &lt;= tempRow.Fields.FieldCount -1; i++)
			{
				Console.Write(tempRow.get_Value(i).ToString());
				Console.Write(&quot;\t&quot;);
			}
			Console.WriteLine();
		}
	}
}</pre>
<p>&#160;</p>
<p align="justify">É um classe bem simples, mas repare no seguinte fluxo:</p>
<ol>
<li>
<div align="justify">Construímos uma query vazia (equivalente à “SELECT * FROM TABLE”);</div>
</li>
<li>
<div align="justify">Pedimos um ICursor (o cursor é um objeto que lhe permite navegar por linhas da tabela de forma ordenada, <em>forward only</em>, ou seja, só permite Next, e não Previous);</div>
</li>
<li>
<div align="justify">Iteramos pelo cursor, pegando cada linha da tabela e percorrendo suas colunas, uma à uma para buscar seu valor;</div>
</li>
</ol>
<p align="justify">Note que só temos uma forma de ler o valor de uma coluna: utilizando o método <em>get_Value(int i)</em>;</p>
<p align="justify">Para exemplos simples, não existem problemas, mas porém quando estamos falando de um sistema maior e que necessita de ser bem estruturado, como sabemos em nossos arquivos de código que o campo <em>n</em> é necessariamente, NomeRodovia, por exemplo? Se mudarem o modelo (por qualquer motivo) nosso código vai falhar (ou pior, vai funcionar e vai começar à nos passar valores errados – de coluna).</p>
<p align="justify">Deve existir um jeito mais fácil! Bem, existem algumas alternativas:</p>
<ul>
<li>
<div align="justify">Passar todo o acesso à dados para um <em>framework</em> <em>ORM (Object Relational Mapping)</em>, por exemplo, <a rel="nofollow" target="_blank" href="http://www.nhforge.org">NHibernate</a>, <a rel="nofollow" target="_blank" href="http://fluentnhibernate.org">Fluent NHibernate</a>, <a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/.../aa697427(v=vs.80).aspx">Entity Framework</a> entre outros;</div>
</li>
<li>
<div align="justify">Utilizar ADO.NET puro;</div>
</li>
<li>
<div align="justify">Ficar maluco tentando escrever ArcObjects esperto o suficiente para dar conta de seus problemas;</div>
</li>
</ul>
<p align="justify">As alternativas, estão em ordem: da melhor para pior. O primeiro caso, de um <em>ORM</em>, teremos maior controle sobre nossas coisas, classes específicas para cada entidade ou para cada punhado de entidades (de acordo com sua necessidade) e teremos uma <a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Domain-driven_design">camada de domínio forte</a>.</p>
<p align="justify">Mas <em>ORMs</em> comuns tem um problema: não utilizam as interfaces nativas do ArcObjects para acesso à dados, e nos leva, novamente as famosas gambetas. Exemplo: é ótimo acessar dados diretamente do banco de dados. É, em termos, mais rápido, mais confiável. </p>
<p align="justify">Mas inviabiliza completamente o uso de <strong>versionamento</strong> (pelo menos o nativo do ArcSDE), <strong>topologia, histórico,<em> </em></strong>entre outras coisinhas mais, as quais pagamos à ESRI. Ou seja, estamos <strong>mutilando, para nosso próprio benefício </strong>(como desenvolvedor – facilitar nosso trampo!) o software que nosso cliente comprou.</p>
<p align="justify">Nenhuma das outras alternativas é muito atraente pois incentiva os desenvolvedores à prática feia do Ctrl+C/Ctrl+V – você acaba tendo de repetir querys e regras de negócio por todo o código e você arruina qualquer chance de testabilidade (a capacidade de testar e garantir que seu código funciona!)</p>
<p align="justify">Bem, a outra alternativa, é tentar: olhe bem, eu disse tentar, utilizar um padrão de projeto para dar conta de todos esses problemas que enfrentamos. Criar uma forma de acessar os dados <strong>dentro do geodatabase utilizando as ferramentas nativas</strong>, ou seja, ArcObjects.</p>
<p align="justify">É um desafio e tanto, já que é muito difícil controlar alguns aspectos desses objetos. (maldito erro COM! quem já viu um “COM object that has been separated from it’s underlying RCW cannot be used” sabe do que eu estou falando.)</p>
<p align="justify">Após estudar e fazer diversas tentativas de escrever algo que funcionasse, fosse de certa forma perfomático (pelo menos na mesma velocidade do acesso nativa aos objetos ou até um cadinho mais lento) e trouxesse produtividade, cheguei à um padrão projeto interessante: <a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Active_record_pattern">ActiveRecord</a>.</p>
<p align="justify">É um padrão que basicamente tem um objeto vindo do banco de dados e propriedades que expõem comportamentos básicos de acesso e escrita ao objeto. Outro componente essencial é um <a rel="nofollow" target="_blank" href="http://martinfowler.com/eaaCatalog/repository.html">repositório</a> (outro padrão de projeto), que vai ser o responsável por conhecer nossas regras de acesso e como chegar ao banco de dados.</p>
<p align="justify">Um exemplo simples e não completamente estruturado:</p>
<pre class="c#" name="code">public class Lote
{
	private IObject _ObjetoBanco;

	public Lote(IObject lote)
	{
		_ObjectBanco = lote;
	}

	public int IdentidadeLote
	{
		get { return Convert.ToInt32(_ObjetoBanco.get_value(1)); }
		set { _ObjetoBanco.set_Value(1); }
	}

	public string NomeProprietario
	{
		get { return _ObjetoBanco.get_Valeu(2).ToString(); }
		set { _ObjetoBanco.set_Value(2).ToString(); }
	}

	public void Salvar()
	{
		// comando ArcObjects para persistir o objeto na base
		_ObjetoBanco.Store();
	}
}</pre>
<p>&#160;</p>
<p>Veja que conseguimos mapear nossas colunas em único lugar e tratar este objeto por igual em qualquer lugar de nossa aplicação?</p>
<p align="justify">O problema de nosso primeiro exemplo, enquanto ele funciona, misturamos diversas funcionalidades e resposabilidade distintas em um único objeto. Ele sabe como ir ao banco, como mapear as colunas, e como jogá-las na tela. Caso precisássemos de ir ao banco novamente, em outra ocasião, teríamos de escrever a query novamente.</p>
<p align="justify">Existem outros padrões que podem auxiliar na mesma tarefa, mas a grande questão está na presença de código ArcObjects. Sem ele, fica difícil garantir que tudo <strong>funciona</strong>.</p>
<p align="justify">Existem duas implementações .NET para o padrão Active Record:</p>
<ul>
<li>
<div align="justify"><a rel="nofollow" target="_blank" href="http://www.castleproject.org/activerecord/">Castle Active Record</a> (que é construído em cima do NHibernate);</div>
</li>
<li>
<div align="justify"><a rel="nofollow" target="_blank" href="http://www.nhydrate.org/">nHydrate</a></div>
</li>
</ul>
<p align="justify">A grande idéia aqui, é estudar o código de ambos e trazer uma implementação utilizando código ArcObjects. Não sei se é uma grande idéia, ou se não tem absolutamente valor algum (outras alternativas já são melhores).</p>
<p align="justify">Já tenho algo em desenvolvimento e quem tiver interesse, entre em contato que disponibilizo o link para o controle de versão do código.</p>
<p align="justify">E aí pessoal, o que acharam? São tópicos razoavelmente avançados, mas nada muito difícil de compreender. Fiquem à vontade para tecer comentários.</p>
<p align="justify">Abraços</p>
<p align="justify">George R. C. Silva</p>


<p>Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2011/02/arcobjects-e-class-extensions-2/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #2'>ArcObjects e Class Extensions #2</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/12/arcobjects-e-class-extensions-1/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #1'>ArcObjects e Class Extensions #1</a></li>
<li><a href='http://blog.geoprocessamento.net/2011/07/cascading-class-extensions/' rel='bookmark' title='Permanent Link: Cascading Class Extensions'>Cascading Class Extensions</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.geoprocessamento.net/2011/03/padro-de-projeto-activerecord-e-arcobjects/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ArcObjects e Class Extensions #2</title>
		<link>http://blog.geoprocessamento.net/2011/02/arcobjects-e-class-extensions-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=arcobjects-e-class-extensions-2</link>
		<comments>http://blog.geoprocessamento.net/2011/02/arcobjects-e-class-extensions-2/#comments</comments>
		<pubDate>Sun, 06 Feb 2011 22:18:36 +0000</pubDate>
		<dc:creator>George Rodrigues da Cunha Silva</dc:creator>
				<category><![CDATA[George Silva]]></category>
		<category><![CDATA[ArcObjects]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[ESRI]]></category>

		<guid isPermaLink="false">http://blog.geoprocessamento.net/2011/02/arcobjects-e-class-extensions-2/</guid>
		<description><![CDATA[Boa tarde pessoal, Lembram do artigo #1 sobre as class extensions? Falei um pouco sobre como as CEs funcionam? Dê lida aqui antes de ler este aqui. Bem, as class extensions são um pouco difíceis de se manter, pois elas geram muito código, são controladas de forma esotérica (através de IPropertySet’s) e podem controlar alguns [...]


Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2011/07/cascading-class-extensions/' rel='bookmark' title='Permanent Link: Cascading Class Extensions'>Cascading Class Extensions</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/12/arcobjects-e-class-extensions-1/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #1'>ArcObjects e Class Extensions #1</a></li>
<li><a href='http://blog.geoprocessamento.net/2011/03/padro-de-projeto-activerecord-e-arcobjects/' rel='bookmark' title='Permanent Link: Padr&atilde;o de Projeto ActiveRecord e ArcObjects'>Padr&atilde;o de Projeto ActiveRecord e ArcObjects</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p align="justify">Boa tarde pessoal,</p>
<p align="justify">Lembram do artigo #1 sobre as class extensions? Falei um pouco sobre como as <em>CEs</em> funcionam? Dê lida <a rel="nofollow" target="_blank" href="blog.geoprocessamento.net/2010/12/arcobjects-e-class-extensions-1/">aqui</a> antes de ler este aqui.</p>
<p align="justify">Bem, as <em>class extensions</em> são um pouco difíceis de se manter, pois elas geram muito código, são controladas de forma esotérica (através de <em>IPropertySet’s</em>) e podem controlar alguns eventos importantes, como <em>OnChange, OnCreate </em>e <em>OnDelete</em> bem como as validações de uma feição.</p>
<p align="justify">Portanto, qual é uma maneira um pouco mais sã de construí-las? Uma primeira tentativa que fiz, foi utilizar herança para construí-las. Uma classe base com algumas funcionalidades era herdada por classes mais “abaixo” na cadeia e ia herdando funcionalidade. Mas como dizem por aí, composição é melhor que herança para extensão de função.</p>
<p align="justify"><a href="http://blog.geoprocessamento.net/wp-content/uploads/2011/02/ClassDiagram1.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Diagrama de classes (herança)" border="0" alt="Diagrama de classes (herança)" src="http://blog.geoprocessamento.net/wp-content/uploads/2011/02/ClassDiagram1_thumb.png" width="467" height="500" /></a> </p>
<p align="justify">Na figura acima, percebemos que toda a funcionalidade é herdada através de herança. Todas as operações em OldBaseClassExtension (a mãe de todas) são marcadas como <em>virtual</em>, dando a possibilidade de sobreescrevemos o método pela classe filha.</p>
<p align="justify">Em código temos algo assim:</p>
<pre class="c#" name="code">    public interface IOldClassExtension : IClassExtension, IObjectClassExtension, IObjectClassValidation, IObjectClassEvents
    {
        // aqui dizemos que todas as classes derivadas de IOldClassExtension
        // devem implementar os métodos das interfaces correspondentes.
    }

    public class OldBaseClassExtension:IOldClassExtension
    {
        public virtual void Init(IClassHelper ClassHelper, ESRI.ArcGIS.esriSystem.IPropertySet ExtensionProperties)
        {
            throw new NotImplementedException();
        }

        public virtual void Shutdown()
        {
            throw new NotImplementedException();
        }

        public virtual string ValidateField(IRow Row, string FieldName)
        {
            throw new NotImplementedException();
        }

        public virtual string ValidateRow(IRow Row)
        {
            throw new NotImplementedException();
        }

        public virtual void OnChange(IObject obj)
        {
            throw new NotImplementedException();
        }

        public virtual void OnCreate(IObject obj)
        {
            throw new NotImplementedException();
        }

        public virtual void OnDelete(IObject obj)
        {
            throw new NotImplementedException();
        }
    }

    public class OldConcreteClassExtensionA : OldBaseClassExtension
    {
        public override void Init(IClassHelper ClassHelper, ESRI.ArcGIS.esriSystem.IPropertySet ExtensionProperties)
        {
            base.Init(ClassHelper, ExtensionProperties);
            // nova funcionalidade customizada
        }

        public override void Shutdown()
        {
            base.Shutdown();
            // nova funcionalidade customizada
        }

        public override string ValidateField(IRow Row, string FieldName)
        {
            base.ValidateField(Row, FieldName);
            // nova funcionalidade customizada
            return &quot;resultado de nova validação de campo&quot;;
        }

        public override string ValidateRow(IRow Row)
        {
            base.ValidateRow(Row);
            // nova funcionalidade customizada
            return &quot;resultado de nova validação de linha&quot;;
        }

        public override void OnChange(IObject obj)
        {
            base.OnChange(obj);
            // nova funcionalidade customizada
        }

        public override void OnCreate(IObject obj)
        {
            base.OnCreate(obj);
            // nova funcionalidade customizada
        }

        public override void OnDelete(IObject obj)
        {
            base.OnDelete(obj);
            // nova funcionalidade customizada
        }
    }

    public class OldConcreteClassExtensionB : OldBaseClassExtension
    {
        public override void Init(IClassHelper ClassHelper, ESRI.ArcGIS.esriSystem.IPropertySet ExtensionProperties)
        {
            base.Init(ClassHelper, ExtensionProperties);
            // nova funcionalidade customizada
        }

        public override void Shutdown()
        {
            base.Shutdown();
            // nova funcionalidade customizada
        }

        public override string ValidateField(IRow Row, string FieldName)
        {
            base.ValidateField(Row, FieldName);
            // nova funcionalidade customizada
            return &quot;resultado de nova validação de campo&quot;;
        }

        public override string ValidateRow(IRow Row)
        {
            base.ValidateRow(Row);
            // nova funcionalidade customizada
            return &quot;resultado de nova validação de linha&quot;;
        }

        public override void OnChange(IObject obj)
        {
            base.OnChange(obj);
            // nova funcionalidade customizada
        }

        public override void OnCreate(IObject obj)
        {
            base.OnCreate(obj);
            // nova funcionalidade customizada
        }

        public override void OnDelete(IObject obj)
        {
            base.OnDelete(obj);
            // nova funcionalidade customizada
        }
    }

    public class OldConcreteClassExtensionC : OldConcreteClassExtensionA
    {
        public override void Init(IClassHelper ClassHelper, ESRI.ArcGIS.esriSystem.IPropertySet ExtensionProperties)
        {
            base.Init(ClassHelper, ExtensionProperties);
            // nova funcionalidade customizada
        }

        public override void Shutdown()
        {
            base.Shutdown();
            // nova funcionalidade customizada
        }

        public override string ValidateField(IRow Row, string FieldName)
        {
            base.ValidateField(Row, FieldName);
            // nova funcionalidade customizada
            return &quot;resultado de nova validação de campo&quot;;
        }

        public override string ValidateRow(IRow Row)
        {
            base.ValidateRow(Row);
            // nova funcionalidade customizada
            return &quot;resultado de nova validação de linha&quot;;
        }

        public override void OnChange(IObject obj)
        {
            base.OnChange(obj);
            // nova funcionalidade customizada
        }

        public override void OnCreate(IObject obj)
        {
            base.OnCreate(obj);
            // nova funcionalidade customizada
        }

        public override void OnDelete(IObject obj)
        {
            base.OnDelete(obj);
            // nova funcionalidade customizada
        }
    }</pre>
<p>&#160;</p>
<p align="justify">Perceba como determinamos a funcionalidade nas classes filhas: além de herdarmos e sobreescrevermos o método, chamamos também o método base, através de base.OnChange(obj), por exemplo.</p>
<p align="justify">Ok, funciona, mas quando temos algumas <em>Class Extensions</em> e uma hierarquia com dois ou três níveis já se torna impossível de manter e <em>debugar</em> o código. Demora-se muito para atingir um resultado razoável.</p>
<p align="justify">Como faríamos se usássemos composição? Bem, vamos imaginar o seguinte: temos algumas tabelas que descrevem as <em>class extensions </em>de <strong>acordo com sua funcionalidade básica </strong>(nem todas as <em>CEs</em> precisam implementar IObjectClassValidation, caso não às usem) e uma forma de ler e instanciar estas <em>CEs</em> de acordo com esta tabela. O diagrama de classes seria basicamente este aqui:</p>
<p><a href="http://blog.geoprocessamento.net/wp-content/uploads/2011/02/ClassDiagram2.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Diagrama de CEs utilizando composição" border="0" alt="Diagrama de CEs utilizando composição" src="http://blog.geoprocessamento.net/wp-content/uploads/2011/02/ClassDiagram2_thumb.png" width="529" height="500" /></a> </p>
<p align="justify">Desta maneira temos um código muito mais simples e nenhuma dependência entre cada <em>ClassExtension</em>. Todas as <em>CEs</em> implementariam ICustomClassExtension, pois esta dá visibilidade para todos os eventos / validações (poderíiamos até ter implementado IObjectInspector para dar formas diferentes de edição à cada <em>CE</em>) que precisamos e o sistema faria o restante, consultado o banco de dados (poderia esta dentro de um próprio FileGeodatabase/ArcSDE) e descobrindo à ordem e quais <em>CEs</em> devem ser instanciadas.</p>
<p align="justify">O esquema em SQL ficaria parecido com:</p>
<pre class="sql" name="code">CREATE TABLE ENTIDADES
(
  -- conterá uma lista de feature classes ou de tabelas do ArcGIS
  nome_entidade varchar(128) NOT NULL, -- Lote
  nome_feature_dataset varchar(128) NOT NULL DEFAULT '', -- nome do feature dataset, caso exista
  nome_feature_class varchar(128) NOT NULL, -- nome da feature class, ex: FLTE_LOTES
  CONSTRAINT entidades_pk PRIMARY KEY (nome_entidade)
)

CREATE TABLE CLASS_EXTENSIONS
(
  -- conterá uma lista das class extensions disponíveis em determinada assembly.
  nome_class_extension varchar(128) NOT NULL, -- Validar Geometria de Lote
  descricao_namespace varchar(128) NOT NULL, -- ValidateParcelGeometryExtensions
  CONSTRAINT class_extensions_pk PRIMARY KEY (nome_class_extension),
  CONSTRAINT descricao_namespace_un UNIQUE (descricao_namespace)
)

-- tabela de relacionamento entre entidades e class extensions
-- é um relacionamento M:N
CREATE TABLE ENTIDADE_POSSUI_CLASS_EXTENSION
(
  nome_entidade varchar(128) NOT NULL REFERENCES ENTIDADES on (nome_entidade),
  nome_class_extension varchar(128) NOT NULL REFERENCES CLASS_EXTENSIONS on (nome_class_extension),
  ordem_criacao integer NOT NULL DEFAULT 0,
  CONSTRAINT epc_pk PRIMARY KEY (nome_entidade,nome_class_extension,ordem_criacao)
)</pre>
<p align="justify">&#160;</p>
<p align="justify">Através de um pouco de código C#, podemos descobrir se a classe implementada está disponível, instanciá-la dinamicamente e adicioná-la à uma lista de ClassExtensions (propriedade extensions em ICustomClassExtension). Aqui segue um pouco de código para vocês verem a diferença. Dessa forma cada classe cuida só do que ela precisa e podemos compor dinamicamente <em>class extensions </em>poderosas, apenas alterando os registros presentes no banco de dados e contando que os campos manipulados por cada uma exista na <em>feature class</em>.</p>
<pre class="c#" name="code">    public interface ICustomClassExtension:IClassExtension,IObjectClassExtension,IObjectClassEvents,IObjectClassValidation
    {
        List<iclassextension> extensions { get; set; }
        void CreateExtensions();
    }

    // esta é a classe mais importante. ela provê toda a funcionalidade
    // básica de buscar o banco de dados e encontrar quem são as extensões para
    // cada feature class e como usá-las
    public class CustomClassExtension:ICustomClassExtension
    {
        public List<iclassextension> extensions
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public void CreateExtensions()
        {
            // vá ao banco de dados e descubra quem são as class extensions aplicáveis à esta classe
            /*
             * foreach (Record r in Query)
             * {
             *      Type t = Type.GetType(r.ClassExtensionAssemblyName) // ValidateParcelGeometry
             *      extensions.Add(Activator.CreateInstance(t));
             * }
            */
        }

        public void Init(IClassHelper ClassHelper, ESRI.ArcGIS.esriSystem.IPropertySet ExtensionProperties)
        {
            foreach (IClassExtension classEx in this.extensions)
            {
                // todas as classes implementam init
                classEx.Init(ClassHelper,ExtensionProperties);
            }
        }

        public void Shutdown()
        {
            foreach (IClassExtension classEx in this.extensions)
            {
                classEx.Shutdown();
            }
        }

        public void OnChange(IObject obj)
        {
            // so vou conseguir iterar sobre as classes que implementam IObjectClassEvents
            foreach (IObjectClassEvents classEvents in this.extensions)
            {
                classEvents.OnChange(obj);
            }
        }

        public void OnCreate(IObject obj)
        {
            // so vou conseguir iterar sobre as classes que implementam IObjectClassEvents
            foreach (IObjectClassEvents classEvents in this.extensions)
            {
                classEvents.OnCreate(obj);
            }
        }

        public void OnDelete(IObject obj)
        {
            // so vou conseguir iterar sobre as classes que implementam IObjectClassEvents
            foreach (IObjectClassEvents classEvents in this.extensions)
            {
                classEvents.OnDelete(obj);
            }
        }

        public string ValidateField(IRow Row, string FieldName)
        {
            string result = String.Empty;
            // so vou conseguir iterar sobre as classes que implementam IObjectClassValidation
            foreach (IObjectClassValidation validation in this.extensions)
            {
                result += validation.ValidateField(Row, FieldName);
            }

            return result;
        }

        public string ValidateRow(IRow Row)
        {
            string result = String.Empty;
            // so vou conseguir iterar sobre as classes que implementam IObjectClassValidation
            foreach (IObjectClassValidation validation in this.extensions)
            {
                result += validation.ValidateRow(Row);
            }

            return result;
        }
    }

    public class ValidateParcelGeometryExtensions : IClassExtension, IObjectClassExtension, IObjectClassValidation
    {
        public void Init(IClassHelper ClassHelper, ESRI.ArcGIS.esriSystem.IPropertySet ExtensionProperties)
        {
            throw new NotImplementedException();
        }

        public void Shutdown()
        {
            throw new NotImplementedException();
        }

        public string ValidateField(IRow Row, string FieldName)
        {
            throw new NotImplementedException();
        }

        public string ValidateRow(IRow Row)
        {
            throw new NotImplementedException();
        }
    }

    public class OnParcelEvents : IClassExtension, IObjectClassExtension, IObjectClassEvents
    {
        public void Init(IClassHelper ClassHelper, ESRI.ArcGIS.esriSystem.IPropertySet ExtensionProperties)
        {
            throw new NotImplementedException();
        }

        public void Shutdown()
        {
            throw new NotImplementedException();
        }

        public void OnChange(IObject obj)
        {
            throw new NotImplementedException();
        }

        public void OnCreate(IObject obj)
        {
            throw new NotImplementedException();
        }

        public void OnDelete(IObject obj)
        {
            throw new NotImplementedException();
        }
    }

    public class ValidateDwgFile : IClassExtension, IObjectClassExtension, IObjectClassValidation
    {
        public void Init(IClassHelper ClassHelper, ESRI.ArcGIS.esriSystem.IPropertySet ExtensionProperties)
        {
            throw new NotImplementedException();
        }

        public void Shutdown()
        {
            throw new NotImplementedException();
        }

        public string ValidateField(IRow Row, string FieldName)
        {
            throw new NotImplementedException();
        }

        public string ValidateRow(IRow Row)
        {
            throw new NotImplementedException();
        }
    }</pre>
<p align="justify">As vantagens de algo assim são enormes do ponto de vista de manutenção. São três simples tabelas e uma mudança simples de estrutura de código que vai dar muito mais liberdade para os desenvolvedores e usuários. No momento em que construirmos uma nova extensão, se todos os usuários tiverem à mesma instalada no PC, é só associarmos a mesma à uma entidade que imediatamente deveria funcionar perfeitamente. <strong>Poderíamos até deixar à cargo do usuário ligar ou desligar as <em>class extensions</em> de seu interesse.</strong></p>
<p align="justify">Entendo que este post é um <em>ArcObjects</em> um pouco mais avançado, mas é muito divertido ver como simples mudanças de arquitetura facilitam a vida dos desenvolvedores e transformar a forma como o usuário se relaciona com o software.</p>
<p align="justify">O que acharam?</p>
<p align="justify">Um abraço pessoal,</p>
<p align="justify">George R. C. Silva</p>


<p>Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2011/07/cascading-class-extensions/' rel='bookmark' title='Permanent Link: Cascading Class Extensions'>Cascading Class Extensions</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/12/arcobjects-e-class-extensions-1/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #1'>ArcObjects e Class Extensions #1</a></li>
<li><a href='http://blog.geoprocessamento.net/2011/03/padro-de-projeto-activerecord-e-arcobjects/' rel='bookmark' title='Permanent Link: Padr&atilde;o de Projeto ActiveRecord e ArcObjects'>Padr&atilde;o de Projeto ActiveRecord e ArcObjects</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.geoprocessamento.net/2011/02/arcobjects-e-class-extensions-2/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>ArcObjects e Class Extensions #1</title>
		<link>http://blog.geoprocessamento.net/2010/12/arcobjects-e-class-extensions-1/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=arcobjects-e-class-extensions-1</link>
		<comments>http://blog.geoprocessamento.net/2010/12/arcobjects-e-class-extensions-1/#comments</comments>
		<pubDate>Sat, 11 Dec 2010 20:53:10 +0000</pubDate>
		<dc:creator>George Rodrigues da Cunha Silva</dc:creator>
				<category><![CDATA[George Silva]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ArcGIS]]></category>
		<category><![CDATA[ArcObjects]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[ESRI]]></category>

		<guid isPermaLink="false">http://blog.geoprocessamento.net/2010/12/arcobjects-e-class-extensions-1/</guid>
		<description><![CDATA[Boa noite senhores e senhoras, Class Extensions é um assunto relativamente antigo. Quem já desenvolveu para ArcObjects às conhecem razoavelmente bem e são implementadas em larga escala como forma de customização avançada dos famosos geodatabases (qualquer um deles, seja Personal, File ou ArcSDE). Bem, as class extensions são implementadas através de algumas interfaces especiais e [...]


Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2011/02/arcobjects-e-class-extensions-2/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #2'>ArcObjects e Class Extensions #2</a></li>
<li><a href='http://blog.geoprocessamento.net/2011/03/padro-de-projeto-activerecord-e-arcobjects/' rel='bookmark' title='Permanent Link: Padr&atilde;o de Projeto ActiveRecord e ArcObjects'>Padr&atilde;o de Projeto ActiveRecord e ArcObjects</a></li>
<li><a href='http://blog.geoprocessamento.net/2011/07/cascading-class-extensions/' rel='bookmark' title='Permanent Link: Cascading Class Extensions'>Cascading Class Extensions</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<div align="justify">
Boa noite senhores e senhoras,</p>
<p><i>Class Extensions</i> é um assunto relativamente antigo. Quem já desenvolveu para <i>ArcObjects</i> às conhecem razoavelmente bem e são implementadas em larga escala como forma de customização avançada dos famosos <i>geodatabases</i> (qualquer um deles, seja <i>Personal</i>, <i>File</i> ou <i>ArcSDE</i>).</p>
<p>Bem, as <i>class extensions</i> são implementadas através de algumas interfaces especiais e devem ser registradas em uma categoria apropriada (o assunto das categorias de objetos ESRI merece um post sozinho!), <i>GeoObjectClassExtensions</i> para funcionarem e além disso devem ser aplicadas à uma <i>Feature Class</i> ou <i>Table</i> para rodarem apropriadamente. E outra coisa: elas só funcionam com quem possui o código cliente (da <i>Class Extension</i>) instalado na máquina. Para quem não possui o cliente elas se comportam de maneira comum.</p>
<p>Com <i>Class Extensions</i> é possível customizar o inspetor de objetos (aquele carinha utilizado para editar os objetos), customizar a renderização de objetos (isso é poderoso!) e customizar a validação realizada pelo <i>ArcGIS</i> antes da <i>feature</i> receber uma chamada no método Store() (ou seja, antes de ir para o banco);</p>
<p>Existem diversas coisas legais que podemos fazer com estas <i>class extensions</i> e não existe muita dificuldade de implementação (claro, quanto mais requisitos ou quanto mais complexos, mais complicado é de implementar e manter uma CE.).</p>
<p>As <i>CEs</i> podem existes para os seguintes tipos:</p>
<ul>
<li>Features</li>
<li>Rows</li>
<li>Quaisquer tipos derivados de IRow</li>
</ul>
<p>O que isto quer dizer? Bem, tanto tabelas, quanto <i>feature classes</i> e qualquer objeto derivado disto podem ter <i>CEs</i>.</p>
<p>Os requerimentos/limitações para <i>Class Extensions</i> são:</p>
<ul>
<li>Feature classes e tabelas só podem ter uma <i>class extension;</i></li>
<li>A <i>CE</i> precisa ser registrada na categoria apropriada (<i>GeoObjectClassExtensions</i>)</li>
<li>A funcionalidade não está presente no repositório de dados e sim no cliente. Sempre será necessário realizar o <i>deploy</i> de todo o código das <i>CEs</i> em <b>todos</b> os clientes;</li>
</ul>
<p>Não são requerimentos/limitações muito pesadas, portanto é uma alternativa viável para customizações mais complexas do procedimento de edição/criação/deleção de objetos.</p>
<p>Obrigatoriamente, o desenvolvedor <b>precisa implementar as seguintes interfaces</b>: IObjectClassExtension (e IFeatureClassExtension, caso seja uma extensão para <i>feature classes</i>). Neste ponto, nossa <i>CE</i> não tem nenhuma funcionalidade. Ela apenas existe.</p>
<p>Para adicionar funcionalidade, podemos implementar outras interfaces, listadas à seguir:</p>
<ul>
<li>IObjectClassEvents</li>
<li>IObjectClassValidation</li>
<li>IObjectClassInfo</li>
<li>IRelatedObjectClassEvents</li>
<li>IConfirmSendRelatedObjectEvents</li>
<li>IFeatureClassEdit</li>
<li>IFeatureClassDraw</li>
<li>IFeatureClassCreation</li>
<li>IObjectInspector</li>
</ul>
<p>Estas interfaces são opcionais, cada uma oferencendo um pouquinho de funcionalidade customizada. Hoje falaremos sobre IObjectClassEvents, que é uma das interfaces mais comum de se implementar. Ao longo de uma pequena série tentarei demonstrar a funcionalidade de algumas destas interfaces.</p>
<h3>IObjectClassEvents</h3>
<p>Esta interface é responsável por nos fornecer métodos para lidar com os eventos de criação, atualização e deleção de um registro. Pense em uma <i>trigger</i> de um banco de dados. Sempre que o evento disparar, determinado método será disparado em sequência.</p>
<p>Os métodos que devem ser implementados para total aderência ao contrato (a interface <img src='http://blog.geoprocessamento.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ) são:</p>
<ul>
<li>OnCreate(IObject obj);</li>
<li>OnChange(IObject obj);</li>
<li>OnDelete(IObject obj);</li>
</ul>
<p>Um exemplo de implementação de uma <i>CE</i> com a interface IObjectClassEvents. Note que esta implementação não é completa, ou seja, faltam métodos para o registro da <i>CE</i>, inicialização correta, etc;</p>
<p>Imagine que temos uma tabela log de operação. Nela salvamos os registros relativos às operações realizadas por todos operadores durante o dia. Sua estrutura é a seguinte (em SQL, mas devemos considerar que a tabela está presente em um ambiente ArcGIS - Geodatabases de qualquer tipo);</p>
<pre name="code" class="sql">
CREATE TABLE LOG_OPERACAO(
OBJECTID serial NOT NULL,
NOME_TABELA VARCHAR(100) NOT NULL,
NOME_USUARIO VARCHAR(100) NOT NULL,
TIPO_OPERACAO VARCHAR(20) NOT NULL,
OID_ORIGINAL integer NOT NULL,
DATA_HORA_OPERACAO timestamp NOT NULL default now()
CONSTRAINT LOG_OPERACAO_PK PRIMARY KEY (OBJECTID)
);
</pre>
<pre name="code" class="c#">
    public class LogUsuario:IObjectClassExtension,IObjectClassEvents
    {
        public void OnCreate(IObject obj)
        {
            // vamos adicionar um registro à uma tabela de log de operações
            // precisamos de nosso workspace para abrir a tabela
            IFeatureWorkspace workspace = ((IDataset)obj.Class).Workspace;
            ITable logTable = workspace.OpenTable("LOG_OPERACAO");

            // só vamos tentar adicionar se a tabela existir no geodatabase!
            if (logTable != null)
            {
                // ok, a tabela existe. caso não existisse, ela seria nula
                // portanto, vamos criar um novo registro
                IRow novoRegistroLog = logTable.CreateRow();

                novoRegistroLog.set_Value(1,((IDataset)obj.Class).Name); // nome da tabela que estamos modificando
                novoRegistroLog.set_Value(1,Environment.UserName); // nome do usuario
                novoRegistroLog.set_Value(2,"INSERCAO"); // tipo da operacao
                novoRegistroLog.set_Value(3,obj.OID); // id no geodatabase
                novoRegistroLog.set_Value(4,DateTime.Now); // data e hora
                novoRegistroLog.Store();
           }
     }

        public void OnChange(IObject obj)
        {
            // vamos adicionar um registro à uma tabela de log de operações
            // precisamos de nosso workspace para abrir a tabela
            IFeatureWorkspace workspace = ((IDataset)obj.Class).Workspace;
            ITable logTable = workspace.OpenTable("LOG_OPERACAO");

            // só vamos tentar adicionar se a tabela existir no geodatabase!
            if (logTable != null)
            {
                // ok, a tabela existe. caso não existisse, ela seria nula
                // portanto, vamos criar um novo registro
                IRow novoRegistroLog = logTable.CreateRow();

                novoRegistroLog.set_Value(1,((IDataset)obj.Class).Name); // nome da tabela que estamos modificando
                novoRegistroLog.set_Value(1,Environment.UserName); // nome do usuario
                novoRegistroLog.set_Value(2,"ATUALIZACAO"); // tipo da operacao
                novoRegistroLog.set_Value(3,obj.OID); // id no geodatabase
                novoRegistroLog.set_Value(4,DateTime.Now); // data e hora
                novoRegistroLog.Store();
           }
     }

        public void OnDelete(IObject obj)
        {
            // vamos adicionar um registro à uma tabela de log de operações
            // precisamos de nosso workspace para abrir a tabela
            IFeatureWorkspace workspace = ((IDataset)obj.Class).Workspace;
            ITable logTable = workspace.OpenTable("LOG_OPERACAO");

            // só vamos tentar adicionar se a tabela existir no geodatabase!
            if (logTable != null)
            {
                // ok, a tabela existe. caso não existisse, ela seria nula
                // portanto, vamos criar um novo registro
                IRow novoRegistroLog = logTable.CreateRow();

                novoRegistroLog.set_Value(1,((IDataset)obj.Class).Name); // nome da tabela que estamos modificando
                novoRegistroLog.set_Value(1,Environment.UserName); // nome do usuario
                novoRegistroLog.set_Value(2,"INSERCAO"); // tipo da operacao
                novoRegistroLog.set_Value(3,obj.OID); // id no geodatabase
                novoRegistroLog.set_Value(4,DateTime.Now); // data e hora
                novoRegistroLog.Store();
           }
     }
}
</pre>
<p>Bem, este é um exemplo de implementação da interface IObjectClassEvents. Poderiamos ter deixado o código muito mais limpo (escrevendo uma função à parte para a criação de um registro na tabela de log, por exemplo) e implementado outras funcionalidades. O que importa é que você já sabe como implementar algumas funcionalidades extras dentro do <i>ArcGIS</i>. Lembrando que para esta <i>CE</i> funcionar precisamos aplicar a mesma à uma <i>feature class</i>. Para aplicar uma <i>class extension</i> programaticamente, preciso utilizar algo similar à isto:</p>
<pre name="code" class="c#">
public void ChangeClassExtension(IObjectClass objectClass, String extensionUID,IPropertySet extensionProperties)
{
    ISchemaLock schemaLock = (ISchemaLock)objectClass;

    try
    {
        // Attempt to get an exclusive schema lock.
        schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);

        // Cast the object class to the IClassSchemaEdit2 interface.
        IClassSchemaEdit2 classSchemaEdit = (IClassSchemaEdit2)objectClass;

        if (!extensionUID.Equals(""))
        {
            // Create a unique identifier (UID) object and change the extension.
            UID extUID = new UIDClass();
            extUID.Value = extensionUID;
            classSchemaEdit.AlterClassExtensionCLSID(extUID, extensionProperties);
        }
        else
        {
            // Clear the class extension.
            classSchemaEdit.AlterClassExtensionCLSID(null, null);
        }
    }
    catch (COMException comExc)
    {
        throw new Exception("Could not change class extension.", comExc);
    }
    finally
    {
        schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
    }
}
</pre>
<p>Este <i>snippet</i> de código tirado da documentação da <i><b>EDN (ESRI Developer Network)</b></i>, instalado junto com o <i>SDK</i> faz as seguintes operações:</p>
<ol>
<li>Tenta assumir um <i>lock</i> <b>exclusivo</b> sobre a <i>ObjectClass</i> (veja a interface IObjectClass);</li>
<li>Converte a <i>object class</i> para um <i>class schema edit</i> (veja IClassSchemaEdit2), para poder acessar os membros (métodos e propriedades) de edição;</li>
<li>Acha a extensão através do código GUID (é o carinho que se vê como um atributo de classe, localizado acima da declaração comum de classe, no seu projeto do <i>Visual Studio</i>;</li>
<li>Altera a <i>class extension</i>;</li>
<li>Libera o <i>lock</i> exclusivo (feito na chamada <i>finally</i> para termos garantia que o <i>lock</i> não ficará por lá, atoa);</li>
</ol>
<p>O que acharam pessoal? Não é exatamente um bixo de sete cabeças, mas precisamos aprofundar nos <i>ArcObjects</i> para ter sucesso na implementação de <i>class extensions</i> úteis. O exemplo fornecido é bobo, pode ter utilidade, mas existem milhares de possibilidades com esses diabinhos. Vários produtos de nível corporativo (soluções de energia, da Miner&#038;Miner por exemplo), apostam pesado na customização de <i>feature classes</i> como saída  para problemas <b>complexos</b>.</p>
<p>Tentem brincar um pouquinho com as <i>class extensions</i>. É bem divertido e rende um trabalho interessante.</p>
<p>Vou ficar por aqui!</p>
<p>Um abraço,</p>
<p>George R. C. Silva
</p></div>


<p>Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2011/02/arcobjects-e-class-extensions-2/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #2'>ArcObjects e Class Extensions #2</a></li>
<li><a href='http://blog.geoprocessamento.net/2011/03/padro-de-projeto-activerecord-e-arcobjects/' rel='bookmark' title='Permanent Link: Padr&atilde;o de Projeto ActiveRecord e ArcObjects'>Padr&atilde;o de Projeto ActiveRecord e ArcObjects</a></li>
<li><a href='http://blog.geoprocessamento.net/2011/07/cascading-class-extensions/' rel='bookmark' title='Permanent Link: Cascading Class Extensions'>Cascading Class Extensions</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.geoprocessamento.net/2010/12/arcobjects-e-class-extensions-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Brincando com ArcObjects #2</title>
		<link>http://blog.geoprocessamento.net/2010/06/brincando-com-arcobjects-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=brincando-com-arcobjects-2</link>
		<comments>http://blog.geoprocessamento.net/2010/06/brincando-com-arcobjects-2/#comments</comments>
		<pubDate>Wed, 30 Jun 2010 21:52:35 +0000</pubDate>
		<dc:creator>George Rodrigues da Cunha Silva</dc:creator>
				<category><![CDATA[George Silva]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ArcGIS]]></category>
		<category><![CDATA[ArcObjects]]></category>
		<category><![CDATA[dev]]></category>

		<guid isPermaLink="false">http://blog.geoprocessamento.net/?p=870</guid>
		<description><![CDATA[No último post sobre ArcObjects, falamos como construir pontos de uma maneira simples. Hoje vamos brincar com alguns polígonos e polilinhas. Qual é a diferença? Bem, como explicado anteriormente, um polígono é uma coleção de anéis (rings), formados por pontos ou por segmentos. As polilinhas funcionam quase da mesma maneira, só que ao invés de [...]


Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2010/06/brincando-com-arcobjects/' rel='bookmark' title='Permanent Link: Brincando com ArcObjects'>Brincando com ArcObjects</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/05/funcoes-postgis-3/' rel='bookmark' title='Permanent Link: Funções PostGIS #3'>Funções PostGIS #3</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/01/arcobjects1/' rel='bookmark' title='Permanent Link: ArcObjects #1 &#8211; introdução'>ArcObjects #1 &#8211; introdução</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">No último post sobre <em>ArcObjects</em>, falamos como construir pontos de uma maneira simples. Hoje vamos brincar com alguns polígonos e polilinhas. Qual é a diferença? Bem, como explicado anteriormente, um polígono é uma coleção de anéis (<em>rings</em>), formados por pontos ou por segmentos. As polilinhas funcionam quase da mesma maneira, só que ao invés de anéis, as polilinhas são formadas por uma coleção de caminhos (<em>paths</em>).</p>
<p style="text-align: justify;">Não podemos criar estas geometrias de alto nível, sem criar antes as geometrias de baixo nível que as compõe. É a maneira na qual o ArcGIS trabalha, e é a mais sã, do ponto de vista de desenvolvimento.</p>
<p style="text-align: justify;">Primeiro vamos construir um polígono. Podemos construir os anéis separadamente, de pontos ou de segmentos e logo depois, adicionar à uma coleção de geometrias, na qual o próprio <em>ArcGIS</em> irá entender como um polígono.</p>
<pre name="code" class="c#">
public static IPolygon ConstruirPolígono()
    {
        object _missing = Type.Missing;

        IGeometryCollection poligonoFinal = new PolygonClass();

        // vamos criar primeiro nosso anel exterior
        // perceba com estamos utilizando uma interface IPointCollection

        IPointCollection anelExterior = new RingClass();

        // lembram da função BuildPoint do post anterior?

        anelExterior.AddPoint(BuildPoint(0,0,0),ref _missing, ref _missing);
        anelExterior.AddPoint(BuildPoint(0,1,0),ref _missing, ref _missing);
        anelExterior.AddPoint(BuildPoint(1,1,0),ref _missing, ref _missing);
        anelExterior.AddPoint(BuildPoint(1,0,0),ref _missing, ref _missing);

        // o último ponto deve ser sempre igual ao primeiro - somente assim
        // o polígono está fechado
        // podemos utilizar também uma outra técnica para usar o primeiro ponto
        // sem duplicar o ponto inicial - muito útil se você não sabe de antemão qual é o primeiro ponto.
        // anelExterior.AddPoint(anelExterior.get_Point(0),ref _missing, ref _missing);

        anelExterior.AddPoint(BuildPoint(0,0,0));

        poligono.AddGeometry(anelExterior as IGeometry, ref _missing, ref _missing);

        // definir a referência espacial - sem a referência espacial o ArcGis não realiza operações espaciais direitinho!

        return poligono as IPolygon;
}
</pre>
<div id="attachment_871" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.geoprocessamento.net/wp-content/uploads/2010/06/poligono_simples.png"><img class="size-full wp-image-871" title="BrincandoArcObjects_Figura01" src="http://blog.geoprocessamento.net/wp-content/uploads/2010/06/poligono_simples.png" alt="Polígono construído com o código anterior" width="300" height="300" /></a><p class="wp-caption-text">Polígono construído com o código anterior</p></div><br />
Este é um código simples para a criação de um polígono igualmente simples. Vamos aumentar um pouco a dificuldade inserindo outros anéis.</p>
<pre name="code" class="c#">
public static IPolygon ConstruirPolígono()
    {
        object _missing = Type.Missing;

        IGeometryCollection poligonoFinal = new PolygonClass();

        // vamos criar primeiro nosso anel exterior
        // perceba com estamos utilizando uma interface IPointCollection

        IPointCollection anelExterior = new RingClass();

        // lembram da função BuildPoint do post anterior?

        anelExterior.AddPoint(BuildPoint(0,0,0),ref _missing, ref _missing);
        anelExterior.AddPoint(BuildPoint(0,10,0),ref _missing, ref _missing);
        anelExterior.AddPoint(BuildPoint(10,10,0),ref _missing, ref _missing);
        anelExterior.AddPoint(BuildPoint(10,0,0),ref _missing, ref _missing);

        // o último ponto deve ser sempre igual ao primeiro - somente assim
        // o polígono está fechado
        // podemos utilizar também uma outra técnica para usar o primeiro ponto
        // sem duplicar o ponto inicial - muito útil se você não sabe de antemão qual é o primeiro ponto.
        anelExterior.AddPoint(anelExterior.get_Point(0),ref _missing, ref _missing);

        IPointCollection anelInterior = new RingClass();
        anelInterior.AddPoint(BuildPoint(1,1,0), ref _missing, ref _missing);
        anelInterior.AddPoint(BuildPoint(1,2,0), ref _missing, ref _missing);
        anelInterior.AddPoint(BuildPoint(2,2,0), ref _missing, ref _missing);
        anelInterior.AddPoint(BuildPoint(2,1,0), ref _missing, ref _missing);
        anelInterior.AddPoint(anelInterior.get_Point(0),ref _missing, ref _missing);

        // nao é permitido sobrepor anéis, à menos que eles tenham orientações contrárias
        // nosso anel exterior tem orientação horária - todos os anéis exteriores devem ter orientação horária!
        // anéis interiores, que descrevem buracos em nossos polígonos devem ter orientação anti-horária!
        ICurve curva = anelInterior as ICurve;
        curva.ReverseOrientation();

        poligono.AddGeometry(anelExterior as IGeometry, ref _missing, ref _missing);
        poligono.AddGeometry(anelInterior as IGeometry, ref _missing, ref _missing);

        // definir a referência espacial - sem a referência espacial o ArcGis não realiza operações espaciais direitinho!

        return poligono as IPolygon;
}
</pre>
<p><div id="attachment_872" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.geoprocessamento.net/wp-content/uploads/2010/06/poligono_simples2.png"><img class="size-full wp-image-872" title="BrincandoArcObjects2_Figura02" src="http://blog.geoprocessamento.net/wp-content/uploads/2010/06/poligono_simples2.png" alt="Polígono simples criado pelo código acima" width="300" height="300" /></a><p class="wp-caption-text">Polígono simples criado pelo código acima (fora de escala)</p></div>
<p style="text-align: justify;">Bem, é fácil trabalhar com geometrias da <em>ESRI</em>. Claro, quanto mais complexa a geometria, mais complexo deverá ser o código para cuidar da mesma. Mas não é nenhum bixo de 7 cabeças. Um outro detalhe interessante é que revertemos a orientação da geometria interna usando uma outra interface, e adicionamos nosso anel original. Por que funciona? A biblioteca <em>ArcObjects</em> fica responsável por notificar a geometria original de que certa operação ocorreu e a realiza de acordo.</p>
<p style="text-align: justify;">Em geral, os passos para se trabalhar com geometrias complexas é construir anéis ou segmentos, criados através da interface IPointCollection, pois assim podemos ir adicionando os pontos que temos interesse e depois ajeitar a orientação de cada anel para nos dar o resultado desejado.</p>
<p style="text-align: justify;">Certo, mas e um polígono que contenha curvas? O formato <em>shapefile</em> não suporta(va) o desenho delas e estão disponíveis à partir dos <em>geodatabases</em> (as curvas são convertidas em diversos segmentos, aproximando o resultado. Mas podemos criar um polígon com curvas via código? Sim, claro! O segredo, neste caso, é separar cada segmento em um anel, mesmo que ele, no final, seja parte de uma coisa só.</p>
<p style="text-align: justify;">Vamos criar dois anéis, um para nosso segmento curvo e o outro para nossos segmentos retos. Juntaremos os dois em apenas um anel e depois adicionaremos este anel ao polígono.</p>
<p style="text-align: justify;">Para construir segmentos curvos, existem diversas interfaces do tipo <em>IConstruct*</em> (<em>IConstructCircularArc, IConstructBezierCurve</em>, etc.), cada uma com suas particularidades.</p>
<pre name="code" class="c#">
object _missing = Type.Missing;

        IGeometryCollection polygon = new PolygonClass();

        // building circular arc

        IPoint p1 = PointPolygonBuilder.BuildPoint(1, 2);
        IPoint p2 = PointPolygonBuilder.BuildPoint(1, 1);
        IPoint p3 = PointPolygonBuilder.BuildPoint(1, 0);
        IPoint p4 = PointPolygonBuilder.BuildPoint(0, 0);
        IPoint p5 = PointPolygonBuilder.BuildPoint(0, 1);

        IConstructCircularArc constructCircularArc = new CircularArcClass();
        constructCircularArc.ConstructThreePoints(p5, p2, p1, true);
        ICircularArc circularArc = constructCircularArc as ICircularArc;
        // end circular Arc

        ISegmentCollection finalRing = new RingClass();
        ISegmentCollection ring1 = new RingClass();
        IPointCollection ring2 = new RingClass();

        ring1.AddSegment(circularArc as ISegment, ref _missing, ref _missing);
        ring2.AddPoint(p1, ref _missing, ref _missing);
        ring2.AddPoint(p3, ref _missing, ref _missing);
        ring2.AddPoint(p4, ref _missing, ref _missing);
        ring2.AddPoint(p5, ref _missing, ref _missing);

        finalRing.AddSegmentCollection(ring1);
        finalRing.AddSegmentCollection(ring2 as ISegmentCollection);
        polygon.AddGeometry(finalRing as IGeometry, ref _missing, ref _missing);
</pre>
<div id="attachment_873" class="wp-caption aligncenter" style="width: 190px"><a href="http://blog.geoprocessamento.net/wp-content/uploads/2010/06/poligono_curva.png"><img class="size-medium wp-image-873" title="BrincandoArcObjects2_PoligonoCurva" src="http://blog.geoprocessamento.net/wp-content/uploads/2010/06/poligono_curva-180x300.png" alt="Polígono resultante do código acima" width="180" height="300" /></a><p class="wp-caption-text">Polígono resultante do código acima</p></div>
<p style="text-align: justify;">Note que deu um trabalhinho à mais para montar este segmento curvo. É bom deixar claro também, que o ponto (1,1) representado na figura, não entra no anel feito de segmentos retos, ele é apenas utilizado para construir o segmento curvo.</p>
<p style="text-align: justify;">Outra coisa legal é ver que para acessar alguns métodos, você tem que instanciar certas interfaces. Notem que o <em>finalRing</em> e <em>ring1</em> possuem propriedades semelhantes, pois têm a mesma interface. Já <em>ring2</em> possui outros membros, pois é de interface diferente. Classes iguais, interfaces diferentes = propriedades diferentes.</p>
<p style="text-align: justify;">E aí, o que acharam?</p>
<p style="text-align: justify;">Abraços pessoal!</p>
<p style="text-align: justify;">George R. C. Silva</p>


<p>Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2010/06/brincando-com-arcobjects/' rel='bookmark' title='Permanent Link: Brincando com ArcObjects'>Brincando com ArcObjects</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/05/funcoes-postgis-3/' rel='bookmark' title='Permanent Link: Funções PostGIS #3'>Funções PostGIS #3</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/01/arcobjects1/' rel='bookmark' title='Permanent Link: ArcObjects #1 &#8211; introdução'>ArcObjects #1 &#8211; introdução</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.geoprocessamento.net/2010/06/brincando-com-arcobjects-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Brincando com ArcObjects</title>
		<link>http://blog.geoprocessamento.net/2010/06/brincando-com-arcobjects/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=brincando-com-arcobjects</link>
		<comments>http://blog.geoprocessamento.net/2010/06/brincando-com-arcobjects/#comments</comments>
		<pubDate>Thu, 24 Jun 2010 19:53:32 +0000</pubDate>
		<dc:creator>George Rodrigues da Cunha Silva</dc:creator>
				<category><![CDATA[George Silva]]></category>
		<category><![CDATA[ArcGIS]]></category>
		<category><![CDATA[ArcObjects]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[ESRI]]></category>
		<category><![CDATA[Geometria]]></category>

		<guid isPermaLink="false">http://blog.geoprocessamento.net/?p=834</guid>
		<description><![CDATA[Boa tarde pessoal, ArcObjects é algo relativamente difícil. É complicado pois temos muitas formas de se fazer o que queremos, a documentação - apesar de razoável, não é excelente (existem detalhes importantes que podem estar escondidos em outras páginas) e não existe uma comunidade forte que trate destas questões. Gostaria de mostrar um pouco de [...]


Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2010/06/brincando-com-arcobjects-2/' rel='bookmark' title='Permanent Link: Brincando com ArcObjects #2'>Brincando com ArcObjects #2</a></li>
<li><a href='http://blog.geoprocessamento.net/2011/02/arcobjects-e-class-extensions-2/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #2'>ArcObjects e Class Extensions #2</a></li>
<li><a href='http://blog.geoprocessamento.net/2011/03/padro-de-projeto-activerecord-e-arcobjects/' rel='bookmark' title='Permanent Link: Padr&atilde;o de Projeto ActiveRecord e ArcObjects'>Padr&atilde;o de Projeto ActiveRecord e ArcObjects</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Boa tarde pessoal,</p>
<p style="text-align: justify;">ArcObjects é algo relativamente difícil. É complicado pois temos muitas formas de se fazer o que queremos, a documentação - apesar de razoável, não é excelente (existem detalhes importantes que podem estar escondidos em outras páginas) e não existe uma comunidade forte que trate destas questões.</p>
<p style="text-align: justify;">Gostaria de mostrar um pouco de ArcObjects aos iniciantes, em especial um <em>namespace</em> complicadinho: <strong>ESRI.ArcGIS.Geometry</strong>. Não tenho domínio do namespace suficiente para dizer que sou um <em>expert</em>, mas consigo me virar.</p>
<p style="text-align: justify;">O <em>namespace Geometry</em> é o responsável por cuidar de todas as operações com as geometrias, sejam elas de quaisquer tipos. Primeiramente gostaria de apresentaar à vocês aos tipos de geometria de <strong>alto-nível</strong>. Isto é importante pois algumas funções ou interfaces, só estão disponíveis nas geometrias de alto nível, outras somente nas de baixo nível.</p>
<p style="text-align: justify;">Todas as geometrias de alto nível tem à sua disposição um <em>set </em>teórico de operações possíveis, tais como interseção, união, diferença, diferença simétrica, entre outros. Outras interfaces/classes do <em>namespace</em> ESRI.ArcGIS.Geometry são responsáveis por estas operações.</p>
<h3 style="text-align: justify;">Geometrias de Alto Nível</h3>
<p>As geometrias de alto nível são:</p>
<ul>
<li>Points;</li>
<li>Multipoints;</li>
<li>Polylines;</li>
<li>Polygons;</li>
<li>MultiPatches;</li>
</ul>
<p>Ponto é o tipo de geometria mais simples que podemos encontrar no modelo do ArcGIS. É basicamente composta de uma coordenada X e uma coordenada Y. Opcionalmente os pontos podem ser <em>IdAware, ZAware</em> e <em>MAware</em>, ou seja: podem ter um Id, Z e M. Todas os tipos de geometrias podem ter estes atributos em seus vértices, que em suma, são pontos.</p>
<p>Multipontos é um tipo de geometria representado por uma coleção de pontos. Da mesma maneira que um ponto, cada ponto desta única geometria tem seus atributos.</p>
<p>Polilinhas são composta pela união de diversos <em>paths</em> (uma geometria de nível mais baixo) que são compostos por sua vez de diversos <em>segments</em>, que podem ser dos tipos: <strong>linha</strong>, <strong>arco circular</strong>, <strong>curva bezier</strong> ou <strong>arco elíptico</strong>.</p>
<p>Polígonos são geometrias compostas por <em>rings, </em>que são compostos por <em>segments</em>, dos tipos citados acima. A ordem de cada <em>ring</em> e o sentido de construção (horário/ante-horário) determinar o comportamento de cada <em>ring</em>. Exemplo: todos os <em>rings</em> externos são ordenados em sentido horário, indicando que o interior dele é o polígono. Caso um <em>ring </em>seja ordenado em <strong>anti-horário</strong> você está dizendo ao ArcGIS que ele é <em>hole</em> - com área negativa.</p>
<p>No caso dos polígonos, isso pode ocorrer indefinidamente, sendo determinado pela ordem em que cada <em>ring</em> aparece na <strong>coleção</strong>.</p>
<div id="attachment_861" class="wp-caption aligncenter" style="width: 291px"><a href="http://blog.geoprocessamento.net/wp-content/uploads/2010/06/untitled.png"><img class="size-full wp-image-861" title="ESRI_RingsPolygons" src="http://blog.geoprocessamento.net/wp-content/uploads/2010/06/untitled.png" alt="Ilustração do funcionamento de rings e polígonos - Fonte: ESRI" width="281" height="227" /></a><p class="wp-caption-text">Ilustração do funcionamento de rings e polígonos - Fonte: ESRI</p></div>
<p><em>Multipatches</em> são geometrias compostas e são em três dimensões. São geometrias que podem ter múltiplas superfícies, com textura. É a forma como o ArcGIS representa objetos em três dimensões. São compostas de <em>Triangles, TriangleStrips </em>e <em>TriangleFans</em>.</p>
<p>Todas as geometrias de nível mais baixo são construídas necessáriamente por pontos. É o bloco de construção do ArcGIS.</p>
<h3>Geometrias de Baixo Nível</h3>
<ul>
<li><em>Paths</em></li>
<li><em>Rings</em></li>
<li><em>Segments</em></li>
<li><em>TriangleStrips</em></li>
<li><em>TriangleFans</em></li>
<li><em>Triangles</em></li>
</ul>
<div id="attachment_859" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.geoprocessamento.net/wp-content/uploads/2010/06/polyline.png"><img class="size-medium wp-image-859" title="UMLDiagram_ESRI_Polyline" src="http://blog.geoprocessamento.net/wp-content/uploads/2010/06/polyline-300x170.png" alt="Diagrama mostrando a estrutura de Polyline - Fonte: ESRI" width="300" height="170" /></a><p class="wp-caption-text">Diagrama mostrando a estrutura de Polyline - Fonte: ESRI</p></div>
<div id="attachment_858" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.geoprocessamento.net/wp-content/uploads/2010/06/polygon.png"><img class="size-medium wp-image-858" title="UMLDiagram_ESRI_Polygon" src="http://blog.geoprocessamento.net/wp-content/uploads/2010/06/polygon-300x170.png" alt="Diagrama mostrando à estrutura de Polygon - Fonte: ESRI" width="300" height="170" /></a><p class="wp-caption-text">Diagrama mostrando à estrutura de Polygon - Fonte: ESRI</p></div>
<p>Pela estrutura que temos aí dá pra entender melhor não?</p>
<p>Vamos começar brincando com os pontinhos, já que são as estruturas básicas de trabalho.</p>
<h3 style="text-align: justify;">Classes e Interfaces</h3>
<p style="text-align: justify;">Para simplificar para os iniciantes, classe é um projeto de um objeto. Quando criamos um novo, aquele projeto é "materializado" na memória do computador.</p>
<p style="text-align: justify;">Interface é um contrato. Quando dizemos que uma classe implementa uma interface, queremos dizer que aquela classe assinou um contrato de funcionalidade com aquela interface - ou seja, tudo que realiza operações na interface ou em algum membro da interface, está também disponível na classe, sendo possível utilizar aquela classe em alguma função que requer a interface.</p>
<h3 style="text-align: justify;">PointClass</h3>
<p>Esta classe implementa diversas interfaces (ou contratos) do <em>namespace Geometry</em>. As interfaces definem as funcionalidades que a PointClass terá. Caso você tenha o <em>Help</em> de desenvolvimento do ArcGIS instalado, abra o mesmo e procure esta URL ms-help://ESRI.EDNv9.3/esriGeometry/html/Point.htm .</p>
<p>Caso não tenha o help instalado</p>
<p>Como criamos um novo ponto? É bem simples, vejam só.</p>
<pre name="code" class="c#">
    IPoint ponto = new PointClass();
    ponto.PutCoords(10,10);
</pre>
<p>Vamos criar uma novo projeto C# do tipo ArcGIS&gt;Console Application. Adicione as referências:</p>
<ul>
<li>ESRI.ArcGIS.Geometry;</li>
<li>ESRI.ArcGIS.Framework;</li>
<li>ESRI.ArcGIS.esriSystem;</li>
</ul>
<p>Você verá que o Visual Studio já criou algumas linhas código para nós. Este é o código para buscar a licença na máquina. Em qualquer tipo de aplicação que você for construir, você deve ter um código similar para buscar uma licença, senão ele é automaticamente desligado.</p>
<pre name="code" class="c#">
namespace DesktopConsoleApplication1
{
    class Program
    {
        private static LicenseInitializer m_AOLicenseInitializer = new DesktopConsoleApplication1.LicenseInitializer();

        [STAThread()]
        static void Main(string[] args)
        {
            //ESRI License Initializer generated code.
            m_AOLicenseInitializer.InitializeApplication(new esriLicenseProductCode[] { esriLicenseProductCode.esriLicenseProductCodeArcView },
            new esriLicenseExtensionCode[] { });
            //ESRI License Initializer generated code.
            //Do not make any call to ArcObjects after ShutDownApplication()
            m_AOLicenseInitializer.ShutdownApplication();
        }
    }
}
</pre>
<p>Este é como meu código se parece. O método Main é o que executa o programa de verdade. Para demonstrar o funcionamento da interface IPoint e da PointClass, vamos escrever algo bem simples, para ilustrar.</p>
<p>Acima do <em>namespace</em>, adicione as seguintes linhas:</p>
<pre name="code" class="c#">
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Framework;
</pre>
<p>Elas são necessárias para utilizarmos os objetos contidos nestes <em>namespaces</em> sem qualificá-los totalmente, ex: ESRI.ArcGIS.Geometry.IPoint. Após a adição destas linhas, podemos utilizar somente IPoint, diretamente, pois estes objetos estão à nossa disposição.</p>
<p>Crie um novo método dentro desta classe (isto não é o ideal em código de produção - estude orientação à objetos. este é apenas um <strong>exemplo</strong>) chamado <em>BuildPoint</em>. Este método deve ser estático (não queremos ter de criar uma outra classe <em>Program</em> para acessá-lo), ou seja, pode ser acessado no "projeto" da classe (ao invés de funcionar no objeto). Neste método, queremos construir um ponto, designar suas coordenadas x, y e z e queremos que esta função nos devolva este ponto.</p>
<p>Ficaria assim:</p>
<pre name="code" class="c#">
        static IPoint BuildPoint(double x, double y, double z)
        {
            IPoint ponto = new PointClass();
            ponto.PutCoords(x, y);
            ponto.Z = z;

            return ponto;
        }
</pre>
<p>Sugiro que você não façam somente um Ctrl-C + Ctrl-V dos códigos. Teste isto no Visual Studio. O <em>Intelllisense</em> irá lhe mostrar algumas outras coisinhas interessantes. Não esqueça de consultar a documentação para saber mais sobre cada um dos membros e métodos.</p>
<p>Bem, o que este método faz? Ele simplesmente instancia um novo ponto, atualiza as coordenadas conformes passadas nos argumentos da função e nos devolve o ponto. Para que fazer uma função assim? Bem, são somente 4 linhas de código, mas imagine se você precisa criar 80000 pontos? Certo, então temos nossa primeira função pronta.</p>
<p>O que faremos com ela? Vamos modificar nosso método Main, para ler diversas coordenadas e criar um monte de pontos para nós. Depois iremos pedir para nosso método Main nos mostrar os pontos criados. Além de modificar o Main, vamos construir um segundo método para nos ajudar a criar os pontos.</p>
<p>Vamos lá:</p>
<pre name="code" class="c#">
        [STAThread()]
        static void Main(string[] args)
        {
            //ESRI License Initializer generated code.
            m_AOLicenseInitializer.InitializeApplication(new esriLicenseProductCode[] { esriLicenseProductCode.esriLicenseProductCodeArcView },
            new esriLicenseExtensionCode[] { });
            //ESRI License Initializer generated code.
            //Do not make any call to ArcObjects after ShutDownApplication()
            m_AOLicenseInitializer.ShutdownApplication();

            // após a inicialização da licença, vamos brincar
            string finaliza = "s";
            string leitura;

            // aqui guardaremos nossos pontos
            List listaDePontos = new List();

            // enquanto finaliza for diferente de n, repita:
            while (finaliza.Substring(0,1).ToLower() != "n")
            {
                // vamos dizer ao usuário o que precisamos.
                Console.WriteLine("Digite as coordenadas de seu ponto. Utilize vírgulas para separá-las");
                Console.WriteLine("X,Y,Z");

                // leitura guardará o resultado que nosso usuário digitar!
                leitura = Console.ReadLine();

                // temos uma string. precisamos de um método para quebrá-la
                // e nos devolver um ponto - que será inserido na listaDePontos
                listaDePontos.Add(TraduzirStringPonto(leitura));

                // será que o usuário quer digitar mais pontos?
                Console.WriteLine("Você deseja criar mais pontos? n para não");
                // vamos alterar o valor de finaliza, que será testa mais à frente.
                // note que esta rotina não cobre TODAS AS POSSIBILIDADES
                finaliza = Console.ReadLine();
            }

            // agora que o usuário terminou de criar seus pontos,
            // vamos mostrá-los à ele.
            Console.WriteLine();
            Console.WriteLine("Lista de Pontos:\n");

            // para cada variável do tipo IPoint em listaDePontos, faça
            foreach (IPoint p in listaDePontos)
            {
                // \t é caractere de tabulação.
                Console.Write("ID " + p.ID.ToString() + "\t");
                Console.Write("X " + p.X.ToString() + "\t");
                Console.Write("Y " + p.Y.ToString() + "\t");
                Console.Write("Z " + p.Z.ToString() + "\t");
                Console.WriteLine();
            }
            // vamos esperar o usuário ler os dados e assim que ele teclar denovo
            // finalizamos o programa
            Console.WriteLine();
            Console.WriteLine("Aperte qualquer botão do teclado para finalizar...");
            Console.ReadLine();
        }
</pre>
<p>No meio da função está a lógica do programa. Queremos ler dados, até o usuário dizer não. Note que este programa é bastante simples, não realiza verificação de erros nem os trata. Não deve ser feito <strong>assim</strong> na vida real!</p>
<p>Mostramos para o usuário algumas propriedades da classse IPoint, algumas setadas por nós, outras não. Viram que todos os IDs são iguais à zero?</p>
<p>Agora vou lhes mostrar a função TraduzirStringPonto. Ela envolve mais programação comum, do que ArcObjects. Vou mostrá-la só para não ficarem no escuro <img src='http://blog.geoprocessamento.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<pre name="code" class="c#">
        static IPoint TraduzirStringPonto(string s)
        {
            // recebemos nesta função uma string e queremos transformá-la em números
            // vamos usar o método Split, que tem como argumentos um array de caracteres
            // delimitados como as strings, com a exceção de que usamos aspas simples!
            string[] arrayDeStrings = s.Split(new Char[]{','},3);

            // vamos criar uma array com três posições para receber nossos números!
            double[] arrayDeDoubles = new double[3];

            // para i = 0 até i = 2
            for(int i = 0; i &lt;= 2; i++)
            {
                // assinale o valor da posição i em arrayDeDoubles
                // para ser igual ao valor da posição i em arrayDeStrings,
                // convertendo-os para um objeto do tipo Double
                arrayDeDoubles[i] = Double.Parse(arrayDeStrings[i]);
            }

            // vamos criar nosso ponto. lembra de BuildPoint?
            IPoint ponto = BuildPoint(arrayDeDoubles[0],arrayDeDoubles[1],arrayDeDoubles[2]);

            // nos devolva nosso ponto para que possamos inseri-lo na lista
            return ponto;
        }
</pre>
<p>Novamente um aviso: esta função também não tem identificação de erros ou tratamento dos mesmos. Recomendo ao interessado em desenvolver seu método de validação da entrada de dados, pois se inserirmos em nosso programa os valores:</p>
<blockquote><p>10,eitcha,100</p></blockquote>
<p>ele irá simplesmente travar - no momento da conversão de string para double.</p>
<p>Esta foi uma gentil introdução à manipulação de geometrias em ArcObjects. Os próximos passos são um pouco mais cabeludos, mas nada que seja impossível.</p>
<p>O que acharam?</p>


<p>Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2010/06/brincando-com-arcobjects-2/' rel='bookmark' title='Permanent Link: Brincando com ArcObjects #2'>Brincando com ArcObjects #2</a></li>
<li><a href='http://blog.geoprocessamento.net/2011/02/arcobjects-e-class-extensions-2/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #2'>ArcObjects e Class Extensions #2</a></li>
<li><a href='http://blog.geoprocessamento.net/2011/03/padro-de-projeto-activerecord-e-arcobjects/' rel='bookmark' title='Permanent Link: Padr&atilde;o de Projeto ActiveRecord e ArcObjects'>Padr&atilde;o de Projeto ActiveRecord e ArcObjects</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.geoprocessamento.net/2010/06/brincando-com-arcobjects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Máquina Virtual e Desenvolvimento para ArcObjects</title>
		<link>http://blog.geoprocessamento.net/2010/03/maquina-virtual-e-desenvolvimento-para-arcobjects/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=maquina-virtual-e-desenvolvimento-para-arcobjects</link>
		<comments>http://blog.geoprocessamento.net/2010/03/maquina-virtual-e-desenvolvimento-para-arcobjects/#comments</comments>
		<pubDate>Mon, 15 Mar 2010 15:57:05 +0000</pubDate>
		<dc:creator>George Rodrigues da Cunha Silva</dc:creator>
				<category><![CDATA[George Silva]]></category>
		<category><![CDATA[ArcObjects]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[VM]]></category>

		<guid isPermaLink="false">http://blog.geoprocessamento.net/?p=442</guid>
		<description><![CDATA[Boa tarde pessoal, Sejam bem-vindos à mais nova série de postagens do Blog Geo.NET: Congonha's Post. Bem, ela tem esse nome porque estou postando do aeroporto de Congonhas e hoje vamos falar, rapidinho, sobre máquinas virtuais e o desenvolvimento para ArcObjects. (estava postando do aeroporto de Congonhas, mas meu voô ia sair sem mim, então [...]


Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2010/01/arcobjects1/' rel='bookmark' title='Permanent Link: ArcObjects #1 &#8211; introdução'>ArcObjects #1 &#8211; introdução</a></li>
<li><a href='http://blog.geoprocessamento.net/2011/02/arcobjects-e-class-extensions-2/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #2'>ArcObjects e Class Extensions #2</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/06/brincando-com-arcobjects/' rel='bookmark' title='Permanent Link: Brincando com ArcObjects'>Brincando com ArcObjects</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Boa tarde pessoal,</p>
<p style="text-align: justify;">Sejam bem-vindos à mais nova série de postagens do Blog Geo.NET: <strong>Congonha's Post</strong>.</p>
<p style="text-align: justify;">Bem, ela tem esse nome porque estou postando do aeroporto de Congonhas e hoje vamos falar, rapidinho, sobre máquinas virtuais e o desenvolvimento para <em>ArcObjects</em>. (estava postando do aeroporto de Congonhas, mas meu voô ia sair sem mim, então tive de deixar para hoje <img src='http://blog.geoprocessamento.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> )</p>
<p style="text-align: justify;">Desenvolver para <em>ArcObjects </em>é complicado. Temos de referenciar diversas bibliotecas, instalar diversos softwares para nos auxiliar e temos, no final de tudo, de fazer o <em>deploy</em> de nossos componentes customizados.</p>
<p style="text-align: justify;">Estes dias anteriores, durante um trabalho em um dos clientes, tive de realizar o <em>deploy</em> de um componente customizado, que cuida de simbologia de algumas camadas (em torno de 200).</p>
<p style="text-align: justify;">Estava me dando um trabalhão. Montava um executável, enviava o executável para um máquina de testes, instalava o software, testava. Deu erro? Desinstala o software e começa tudo denovo.</p>
<p style="text-align: justify;">Aí me sugeriram: pegue uma máquina virtual e monte um ambiente similar ao em que realizaremos o <em>deploy</em> final.</p>
<p style="text-align: justify;">Existem diversos softwares para montarmos máquinas virtuais, mas existe um simples, gratuito e da <em>Microsoft</em> que resolve horrores. Virtual PC. Só fazer o download e instalar o sistema (<em>Windows</em>) que você quiser. Do 95 ao 7 <img src='http://blog.geoprocessamento.net/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> . Você pede para criar a máquina virtual, aloca uma certa quantidade de RAM e HD para a mesma, e voilá, você tem um PC dentro do seu PC.</p>
<p style="text-align: justify;">Como isto facilitou minha vida? Ganhei no mínimo, uns quatros dias de trabalho. Instalei a VM (<em>Virtual Machine)</em>, abri uma instância do Windows XP, coloquei um ArcGIS 9.3 e fui realizando os ajustes até finalizar.</p>
<p style="text-align: justify;">Agora, o que é legal é que você pode montar diversas instâncias e testar a <em>backwards compatibility (</em>compatibilidade retroativa - ou algo do tipo) com outras versões, de ArcGIS, de ArcServer, enfim, de diversos ambientes diferentes.</p>
<p style="text-align: justify;">Estou com duas máquinas virtuais, as duas com WinXP SP3, uma com ArcGIS 9.3 e a outra com ArcGIS 9.2.</p>
<p style="text-align: justify;">Fica aí a dica.</p>
<p style="text-align: justify;">George R. C. Silva</p>


<p>Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2010/01/arcobjects1/' rel='bookmark' title='Permanent Link: ArcObjects #1 &#8211; introdução'>ArcObjects #1 &#8211; introdução</a></li>
<li><a href='http://blog.geoprocessamento.net/2011/02/arcobjects-e-class-extensions-2/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #2'>ArcObjects e Class Extensions #2</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/06/brincando-com-arcobjects/' rel='bookmark' title='Permanent Link: Brincando com ArcObjects'>Brincando com ArcObjects</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.geoprocessamento.net/2010/03/maquina-virtual-e-desenvolvimento-para-arcobjects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hello World, ArcGIS style!</title>
		<link>http://blog.geoprocessamento.net/2010/02/hello-world-arcgis-style/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=hello-world-arcgis-style</link>
		<comments>http://blog.geoprocessamento.net/2010/02/hello-world-arcgis-style/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 23:27:58 +0000</pubDate>
		<dc:creator>George Rodrigues da Cunha Silva</dc:creator>
				<category><![CDATA[George Silva]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ArcGIS]]></category>
		<category><![CDATA[ArcObjects]]></category>
		<category><![CDATA[dev]]></category>

		<guid isPermaLink="false">http://blog.geoprocessamento.net/?p=389</guid>
		<description><![CDATA[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 [...]


Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2011/07/diquinhas-de-arcgis-1/' rel='bookmark' title='Permanent Link: Diquinhas de ArcGIS #1'>Diquinhas de ArcGIS #1</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/06/brincando-com-arcobjects/' rel='bookmark' title='Permanent Link: Brincando com ArcObjects'>Brincando com ArcObjects</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/05/arcgis-com-lancado/' rel='bookmark' title='Permanent Link: ArcGIS.com lançado'>ArcGIS.com lançado</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Boa noite pessoal,</p>
<p>Conforme prometi, vamos começar a brincar de <em>ArcObjects</em>.</p>
<p>Se vocês instalaram o Visual Studio 2005 (pode ser o <em>Express</em>, disponível gratuitamente) e <strong>depois</strong> instalaram o <em>software development kit </em>vocês não teram problema para acompanhar este simples guia.</p>
<h3>Notas importantes</h3>
<ul>
<li>Não irei focar no código. Não irei explicar detalhadamente o que cada função faz. Isto é trabalho de vocês.</li>
<li>Irei ajudar na parte mais difícil: como começar. Existem algumas coisinhas que são chatíssimas quando programamos para <em>ArcGIS</em>, mas ainda bem que o próprio <em>Visual Studio</em> resolve algumas delas para nós.</li>
</ul>
<h3>Início</h3>
<p>Primeiramente, abra o <em>Visual Studio</em> e peça um <em>New Project</em>. Selecione um <em>Empty Project </em>e dê um nome para seu projeto.</p>
<div id="attachment_390" class="wp-caption aligncenter" style="width: 420px"><a href="http://blog.geoprocessamento.net/wp-content/uploads/2010/02/p1.png"><img class="size-full wp-image-390 " title="Criando um novo projeto" src="http://blog.geoprocessamento.net/wp-content/uploads/2010/02/p1.png" alt="Criando um novo projeto" width="410" height="278" /></a><p class="wp-caption-text">Criando um novo projeto no Visual Studio 2005</p></div>
<p>Depois de isso feito, termos algo mais ou menos assim:</p>
<p style="text-align: center;">
<div id="attachment_391" class="wp-caption aligncenter" style="width: 440px"><a href="http://blog.geoprocessamento.net/wp-content/uploads/2010/02/p2.png"><img class="size-large wp-image-391  " title="Empty Project" src="http://blog.geoprocessamento.net/wp-content/uploads/2010/02/p2-1024x537.png" alt="Projeto vazio" width="430" height="226" /></a><p class="wp-caption-text">Projeto vazio</p></div>
<p>O Visual Studio é extremamente personalizável, portanto não precisa se concentar em deixar sua tela <strong>exatamente</strong> igual a minha. Quero que você veja o <em>Solution Explorer </em>que fica à direita.</p>
<p>Vamos para o <em>rock.</em> O que iremos fazer?</p>
<p>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.</p>
<p>Então vamos lá. Vá na raiz do projeto (escrito <em>HelloWorldArcGIS</em>) e clique com o botão direito. Clique em <em>Add ArcGIS Reference.</em></p>
<p><strong>O que isto exatamente faz?<em> </em></strong>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 <strong>não iremos utilizar?</strong></p>
<p>Certo, quando você clicar no botãozinho, irá aparecer uma janelinha. Vá na opção <em>Desktop ArcMap </em>e adicione as seguintes <em>assemblies:</em></p>
<ul>
<li>ESRI.ArcGIS.ArcMapUI;</li>
<li>ESRI.ArcGIS.ArcMap;</li>
<li>ESRI.ArcGIS.Display;</li>
<li>ESRI.ArcGIS.Framework;</li>
<li>ESRI.ArcGIS.Geodatabase;</li>
<li>ESRI.ArcGIS.System;</li>
<li>ESRI.ArcGIS.Carto;</li>
</ul>
<p>Clique em <em><strong>Finish.</strong></em></p>
<p>Você verá que a pasta <em><strong>References</strong></em> foi atualizada. Vamos adicionar algumas <em>assemblies </em>do <em>Windows </em>e do .<em>NET.</em></p>
<p>Siga o mesmo passo acima, mas ao invés de escolher <em>Add ArcGIS Reference</em>, escolha <em>Add Reference</em>. Uma caixinha irá se abrir, portanto em .<em>NET</em>, seleciona as seguintes <em>assemblies</em>:</p>
<ul>
<li>System</li>
<li>System.Drawing</li>
<li>System.Windows.Forms</li>
</ul>
<p>Clique <strong>ok</strong>. Estamos <em>good to go.</em></p>
<p>Nossas referências estão no lugar. Isto significa que poderemos utilizar código pronto contido nestas <em>assemblies</em>. Isto é importante e interessante que se aprenda cedo, senão algo pode deixar de funcionar simplesmente porque você nao colocou aquela referência...</p>
<p>Vamos agora criar uma barra de ferramentas para colocar nossas coisinhas nela.</p>
<p>Clique com o botão direito na raiz do projeto e clique em <em>Add &gt; Add New Item</em>.</p>
<div id="attachment_392" class="wp-caption aligncenter" style="width: 419px"><a href="http://blog.geoprocessamento.net/wp-content/uploads/2010/02/p4.png"><img class="size-full wp-image-392 " title="Adicionando uma barra de ferramentas" src="http://blog.geoprocessamento.net/wp-content/uploads/2010/02/p4.png" alt="Adicionando uma barra de ferramentas" width="409" height="247" /></a><p class="wp-caption-text">Adicionando uma barra de ferramentas</p></div>
<p>Selecione Base Toolbar e dê um nome à esta toolbar. Algo como <em>HelloWorldToolbar, </em>e clique em <em>Add.</em> Um tela irá aparecer perguntando <strong>qual tipo </strong>de barra de ferramentas você quer. Selecione <em>ArcMap </em>e boa.</p>
<p>Olhe suas referências. Elas foram atualizadas e adicionados alguns <em>assemblies</em> extras. Não se preocupe com eles. O <em>Visual Studio</em> é até inteligente para colocar algumas que você pode ter esquecido, mas só pelos canais oficiais (como este de adicionar uma <em>toolbar</em>). Se você criar uma classe e tentar herdar de BaseToolbar você provavelmente ganhará um erro.</p>
<p>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:</p>
<pre name="code" class="c-sharp">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";
            }
        }
    }
}
</pre>
<p>Vamos lá:</p>
<p>O que merece nota <strong>imediata:</strong></p>
<ul>
<li>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 <em>comments </em>com carinho.</li>
<li>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 <em>ArcGIS</em>.</li>
<li>A propriedade Name. Deve ser único. Portanto, é melhor nem mexer com isto, por enquanto.</li>
<li>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 <strong>nada.</strong></li>
</ul>
<p>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 <strong>ComandoHelloWorld</strong>.</p>
<p>Mais uma vez um <em>prompt</em> irá aparecer e te perguntar qual é o tipo de comando você quer criar. Vejamos...escolha <em>Desktop ArcMap Command</em> e boa.</p>
<pre name="code" class="c-sharp">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
    }
}
</pre>
<p>Pontos merecedores de notas:</p>
<ul>
<li>Novamente o construtor do comando. Ele tem diversas informações que são mostradas ao usuário no <em>ArcGIS</em>. Não irei explicar uma à uma, brinque com elas e teste.</li>
<li>Um campo (<em>field) </em>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.</li>
<li>Método OnClick(). Este método é que irá rodar quando o usuário clicar no comando. Nós implementaremos as coisinhas todas ali. <em>Capiche?</em></li>
</ul>
<p>Vamos adicionar nosso comando à barra de ferramentas. Lembram do construtor da barra de ferramentas, que contém alguns exemplos de Add?</p>
<p>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.</p>
<pre name="code" class="c-sharp">
    AddItem(new Guid("2423ecdf-4f14-4993-a165-df9d79167f4d"), 0);
</pre>
<p>Vamos tentar compilar. Aperte F6.</p>
<p>Um erro <strong>deve</strong> aparecer. Ainda não configuramos nossa aplicação para abrir com o <em>ArcMap.</em> Vá na raiz do projeto, clique com o botão direito e vá em <em>Properties.</em></p>
<p>Você irá ver um monte de coisas.</p>
<p>Na parte de <em>Application</em> procure <em>Output Type </em>e escolha <em>Class Library.</em></p>
<p>Em <em>Build</em> marque a última opção, <em>Register for COM Interop</em>. Lembra que tudo que fazemos com <em>ArcObjects </em><strong>temos<em> </em></strong>que fazer com COM? Ficou estranho isso, mas válá.</p>
<p>Vá em DEBUG e procure a seção <em>Start Action</em>. Marque <em>Start External Program </em>e localize o arquivo ArcMap.exe no seu computador. O meu fica em C:\Program Files\ArcGIS\bin\ArcMap.exe.</p>
<p>Tente compilar novamente. Aperte F6. Você não deve ver <strong>nenhum</strong> erro. O <em>ArcGIS </em>irá abrir sozinho.</p>
<p style="text-align: left;">
<div id="attachment_395" class="wp-caption aligncenter" style="width: 440px"><a href="http://blog.geoprocessamento.net/wp-content/uploads/2010/02/p51.png"><img class="size-large wp-image-395  " title="ArcGIS aberto e barra de ferramenta disponível" src="http://blog.geoprocessamento.net/wp-content/uploads/2010/02/p51-1024x535.png" alt="ArcGIS aberto e barra de ferramenta disponível" width="430" height="225" /></a><p class="wp-caption-text">ArcGIS aberto e barra de ferramenta disponível</p></div>
<p>Nossa barrinha de ferramentas esta lá!</p>
<p style="text-align: left;">Agora vamos implementar a nossa <em>super-ultra-mega-</em>complexa funcionalidade. Feche o <em>ArcMap. </em>Retorne ao <em>Visual Studio.</em></p>
<p style="text-align: left;">Abra o arquivo de código do nosso comando. Suba até o topo de nosso arquivo.</p>
<p style="text-align: left;">Você verá um monte de coisas como <em>using System.Drawing</em> entre outros. Aqui nós dizemos ao <em>Visual Studio</em> quais assemblies este arquivo poderá acessar. Faltam duas importantes para nós aí.</p>
<p style="text-align: left;">Insira a<em> assembly </em>ESRI.ArcGIS.Carto e a <em>assembly </em>System.Windows.Forms. Lembre-se de colocar cada uma em uma linha, e <strong>não se esqueça do ponto-e-vírgula.</strong></p>
<pre name="code" class="c-sharp">        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!");
        }
</pre>
<p>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 <em>Visual Studio</em> ainda irá mostrar para vocês a jóia de sua coroa, o <em>Intellisense</em>. Ele te sugere o que você <strong>pode </strong>estar precisando. Você conseguirá enxergar diversos atributos e propriedades de cada uma destas classes.</p>
<p>Tem bastante coisa interessante só nessas três classezinhas. Navegue. Use o <a rel="nofollow" target="_blank" title="EDN" href="http://edn.esri.com" target="_blank">EDN</a>. Use o <em>Help (</em>F1). E poste suas dúvidas.</p>
<p>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!</p>
<p>Estou no aguardo das dúvidas, comentários e blasfêmias!</p>
<p>Espero que tenham gostado,</p>
<p>Um abraço,</p>
<p>George R. C. Silva</p>


<p>Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2011/07/diquinhas-de-arcgis-1/' rel='bookmark' title='Permanent Link: Diquinhas de ArcGIS #1'>Diquinhas de ArcGIS #1</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/06/brincando-com-arcobjects/' rel='bookmark' title='Permanent Link: Brincando com ArcObjects'>Brincando com ArcObjects</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/05/arcgis-com-lancado/' rel='bookmark' title='Permanent Link: ArcGIS.com lançado'>ArcGIS.com lançado</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.geoprocessamento.net/2010/02/hello-world-arcgis-style/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>ArcObjects #1 &#8211; introdução</title>
		<link>http://blog.geoprocessamento.net/2010/01/arcobjects1/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=arcobjects1</link>
		<comments>http://blog.geoprocessamento.net/2010/01/arcobjects1/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 20:06:27 +0000</pubDate>
		<dc:creator>George Rodrigues da Cunha Silva</dc:creator>
				<category><![CDATA[George Silva]]></category>
		<category><![CDATA[ArcGIS]]></category>
		<category><![CDATA[ArcObjects]]></category>
		<category><![CDATA[dev]]></category>

		<guid isPermaLink="false">http://blog.geoprocessamento.net/?p=309</guid>
		<description><![CDATA[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 [...]


Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2010/03/maquina-virtual-e-desenvolvimento-para-arcobjects/' rel='bookmark' title='Permanent Link: Máquina Virtual e Desenvolvimento para ArcObjects'>Máquina Virtual e Desenvolvimento para ArcObjects</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/06/brincando-com-arcobjects/' rel='bookmark' title='Permanent Link: Brincando com ArcObjects'>Brincando com ArcObjects</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/12/arcobjects-e-class-extensions-1/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #1'>ArcObjects e Class Extensions #1</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Boa tarde pessoal,</p>
<p style="text-align: justify;">Mais uma vez venho a vocês com uma futura série de pequenos artigos, desta vez sobre <a rel="nofollow" target="_blank" title="ArcObjects" href="http://resources.esri.com/help/9.3/ArcGISDesktop/dotnet/concepts_start.htm" target="_blank"><em>ArcObjects</em></a>, a <em>API </em>da <a rel="nofollow" target="_blank" title="ESRI" href="http://www.esri.com" target="_blank">ESRI</a> para o desenvolvimento de funções que levam em conta o <strong>espaço e dados espaciais.</strong></p>
<p style="text-align: justify;">Bem, primeiramente devemos começar dizendo que ArcObjects não é um bicho de <strong>sete cabeças,</strong> é um bicho só de cinco. Não é nada complicado, quando você entende o que quer fazer e onde procurar.</p>
<p style="text-align: justify;">Para quem está perdido, <em>API</em> é um conjunto de rotinas e funcionalidades já escritas que pode-se extender, através de programação. Ou seja, <em>ArcObjects</em> é essencialmente os blocos construtivos do software <em>ArcGIS</em>. Os caras na<em> ESRI</em> desenvolvem o<em> ArcObjects</em> e depois o usam para montar o <em>ArcMap</em>, por exemplo.</p>
<p style="text-align: justify;">E realmente são muitos blocos. A <em>API</em> é 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!</p>
<p style="text-align: justify;">Certo e o que mais precisamos saber sobre a <em>API ArcObjects</em> para começar a programar para o <em>ArcGIS</em>? Nada, na realidade, mas existem alguns conceitos que <strong>devem</strong> ser conhecidos.  Toda a <em>API</em> foi desenvolvida seguindo o modelo<em> COM</em> (<em>Component Object Model</em>), o padrão para distribuição de bibliotecas binárias em ambiente desktop, desenvolvido pela <em>Microsoft</em>.</p>
<p style="text-align: justify;">E isto muda tudo. A tecnologia <em>COM</em> estabelece padrões e exige alguns requisitos para que um software seja <em>COM-compatible</em>. Finalmente, devemos entender que<em> COM</em> é uma arquitetura, uma forma de desenvolver software.</p>
<p style="text-align: justify;">A arquitetura <em>COM</em> é 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 <em>COM</em> 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 <strong>olho </strong>nisto, pois software mal desenvolvido que utiliza <em>COM</em> é software que um dia irá explodir. Esta arquitetura tem sérios problemas de <strong>perfomance e coleta de lixo.</strong></p>
<p style="text-align: justify;">Para saber mais, visite <a rel="nofollow" target="_blank" title="esta" href="http://edndoc.esri.com/arcobjects/9.0/ArcGISDevHelp/DevelopmentEnvs/COM/IntroToCOM.htm" target="_blank">esta</a> página<strong> </strong>e <a rel="nofollow" target="_blank" title="esta" href="http://resources.esri.com/help/9.3/ArcGISDesktop/dotnet/concepts_start.htm#1f0e8ebb-c59a-49be-998e-aa0b840845e6.htm" target="_blank">esta</a> página.</p>
<p style="text-align: justify;">Certo, o que podemos fazer com <em>ArcObjects</em>? Tudo o que podemos fazer dentro do ArcGIS, podemos fazer utilizando <em>ArcObjects</em>. Tudo e muito mais, claro. Como o próprio <em>ArcGIS</em> foi construído sobre <em>ArcObjects, </em>estamos na realidade falando de <strong>uma coisa só</strong>!</p>
<p style="text-align: justify;">O que preciso para desenvolver em <em>ArcObjects?</em></p>
<p style="text-align: justify;">Bem, a <em>API </em>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 (<strong>cuidado, o suporte para VBA ACABOU!</strong>).</p>
<p style="text-align: justify;">Não existe melhor ou pior, apenas diferente <img src='http://blog.geoprocessamento.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> . 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).</p>
<p style="text-align: justify;">Após escolher sua linguagem de preferência, instale um <em>IDE</em> (<em>Integrated Development Environment - </em>como o <em>Visual Studio, </em>no caso de .NET) e instale as bibliotecas que veêm com o <em>ArcGIS.</em> Note que as bibliotecas já estão no CD de instalação do <em>ArcGIS Desktop</em> (as bibliotecas de programação para <em>Desktop, </em>claro).</p>
<p style="text-align: justify;">Primeiro instale o ambiente de desenvolvimento e <strong>depois</strong> a biblioteca. <strong>Nunca o contrário.</strong></p>
<p style="text-align: center;">
<div id="attachment_310" class="wp-caption aligncenter" style="width: 415px"><a href="http://blog.geoprocessamento.net/wp-content/uploads/2010/01/untitled.png"><img class="size-full wp-image-310 " title="Instalacao" src="http://blog.geoprocessamento.net/wp-content/uploads/2010/01/untitled.png" alt="instalacao sdk" width="405" height="314" /></a><p class="wp-caption-text">Tela de Instalação dos SDK&#39;s ArcGIS Desktop</p></div>
<p style="text-align: justify;">Depois que tudo estiver instalado, sugiro que passe um tempo se familiarizando com cada <em>IDE</em> e com a <a rel="nofollow" target="_blank" title="referência oficial da ESRI" href="http://resources.esri.com/help/9.3/ArcGISDesktop/ArcObjects/ao_start.htm" target="_blank">referência oficial da <em>ESRI</em></a>. Ache um pequeno problema que lhe incomoda no <em>ArcGIS</em> (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 <em>ArcObjects</em> para isto.</p>
<p style="text-align: justify;">Como são muitas classes e interfaces, não se preocupe em conhecer <strong>todas</strong>, se preocupe em conhecer como achar na <strong>referência oficial</strong> dados sobre determinada classe/interface.</p>
<p style="text-align: justify;">Aviso aos navegantes: é muito comum em <em>ArcObjects </em>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).</p>
<p style="text-align: justify;">Os <em>namespaces</em> mais utilizados, provavelmente são esriSystem, ArcMap, ArcMapUI, Geometry e Geodatabase. Todos tem sua própria página na <em>ESRI</em>, incluindo um diagrama completo do mesmo.</p>
<p style="text-align: justify;">Caso tenham dúvidas, estamos aqui! Próximo post: <em>Hello World</em>, <em>ArcGIS style!</em></p>
<p style="text-align: justify;">Abraços</p>
<p style="text-align: justify;">George</p>


<p>Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2010/03/maquina-virtual-e-desenvolvimento-para-arcobjects/' rel='bookmark' title='Permanent Link: Máquina Virtual e Desenvolvimento para ArcObjects'>Máquina Virtual e Desenvolvimento para ArcObjects</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/06/brincando-com-arcobjects/' rel='bookmark' title='Permanent Link: Brincando com ArcObjects'>Brincando com ArcObjects</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/12/arcobjects-e-class-extensions-1/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #1'>ArcObjects e Class Extensions #1</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.geoprocessamento.net/2010/01/arcobjects1/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

