Você está na página 1de 24

Comunidades de Usurios Autodesk Brasil

O Poder do ObjectARX
Fernando P. Malard ofcdesk, LLC. Este Tutorial, para usurios avanados e desenvolvedores do AutoCAD ir apresentar uma introduo simples mas completa para criao e utilizao de entidades personalizadas com a fantstica API de programao ObjectARX. Inicialmente, sero apresentados alguns conceitos bsicos da programao ObjectARX. Os leitores iro aprender a criar aplicativos ObjectARX bsicos utilizando o ARX Wizard. A seguir, a estrutura de dados do AutoCAD ser explorada para entedermos seu funcionamento, organizao e utilizao dos seus objetos. No final, ser apresentado um exemplo completo com uma descrio detalhada passo a passo.

Sobre o Autor:

Fernando Engenheiro Civil especialista em AutoCAD e ObjectARX desde 1996. Ele membro da Autodesk Developer Network desde 1996. Ele desenvolve diversos aplicativos para AutoCAD para Engenharia Civil, Arquitetura e GIS usando ObjectARX, .NET, SQL e Oracle . Fernando tem ainda grande experincia no ensino de AutoCAD, C++, MFC, COM, SQL, .NET e ObjectARX h mais de 15 anos. Atualmente continua utilizando o ObjectARX em complexas solues ERP e atua como CTO da ofcdesk. E-mail: fernando.malard@ofcdesk.com / fpmalard@yahoo.com.br

O Poder do ObjectARX

Introduo Durante os ltimos anos o AutoCAD evoluiu e se tornou uma plataforma CAD genrica e extremamente poderosa proporcionando uma revoluo no CAD e na Indstria de Projetos. Essa evoluo, em sua maioria, se deve reduo da lacuna existente entre as situaes reais e dos projetos conceituais. Isso foi possvel somente com a abertura da arquitetura do AutoCAD que foi iniciada oficialmente na verso 13. Naquele momento, a Autodesk decidiu disponibilizar parte do cdigo fonte nativo do AutoCAD para desenvolvedores em uma forma de SDK (Kit de Desenvolvimento). Essa ferramenta poderosa permitiu que os desenvolvedores criassem aplicativos e solues que usassem todo o poder do ncleo do AutoCAD. O ObjectARX, inicialmente chamado de ARX, foi introduzido oficialmente na verso 13. Depois disso, o AutoCAD evoluiu para uma interface poderosa com a verso 14 e a seguir com a verso MDI (Interface de Mltiplos Documentos) na verso 2000. Atualmente, o AutoCAD est na verso 19.0 (mais conhecida como 2013) apresentando muitas tecnologias de ponta na programao tais como a interface .NET (linguagens C# e VB.NET) alm do WPF. O ObjectARX, atravs do C++, est no topo da lista de velocidade e performance quando comparado como outras linguagens de programao do AutoCAD. A razo muito simples, at hoje grande parte do cdigo do AutoCAD ainda est em C++ e provavelmente no ir mudar to cedo. verdade que temos hoje grande parte da API disponvel atravs do .NET mas muita coisa realmente apenas uma casca de acesso ao cdigo real dentro do ncleo C++. O ObjectARX leva uma grande vantagem quando comparado s outras linguagens de programao do AutoCAD. Atualmente a nica que permite a implementao completa de Custom Entities (Entidades Personalizadas). Essa grande capacidade do ObjectARX em C++ foi intensivamente usada pela prpria Autodesk para criar os outros produtos verticais no topo do AutoCAD R13. Hoje temos inmeros produtos baseados no AutoCAD feitos pela prpria Autodesk usando todo o poder proporcionado pelo ObjectARX. Podemos citar alguns produtos verticais como o AutoCAD Architecture e AutoCAD Civil. Esses dois produtos so exemplos do uso intensivo de Custom Entities para aproximar a ferramenta CAD ao cenrio real da indstria. Ao invs de usarmos linhas e crculos para representarmos smbolos arquitetnicos, o AutoCAD Architecture capaz de criar entidades especficas como janelas, portas, escadas, etc. Isso faz com que o aplicativo CAD seja muito mais adequado para sua indstria especfica e que haja reduo substancial de tempo de criao de projetos. Neste Tutorial, voc poder experimentar parte desse poder ao implementar uma simples Custom Entity dentro do AutoCAD. Voc iniciar o aprendizado com conceitos bsicos de um aplicativo ObjectARX. A seguir voc aprender conceitos importantes sobre a estrutura de dados do AutoCAD, como seus objetos so organizados, armazenados e como manipul-los. Finalmente, voc aprender como criar uma simples entidade personalizada com funcionalidades bsicas alm de como expandi-la para uma entidade mais complexa. Nota: Ns iremos utilizar o AutoCAD 2012, Visual Studio 2008 SP1 e ObjectARX 2010 neste Tutorial. Os mdulos ObjectARX criados com o ObjectARX 2010 so binariamente compatveis com o AutoCAD 2010, 2011 e 2012. Para o AutoCAD 2013 necessrio utilizar o Visual Studio 2010 SP1 e o ObjectARX 2013 sendo que os mdulos compilados no sero compatveis com as verses anteriores ao 2013. Estrutura de Dados do AutoCAD A estrutura de dados do AutoCAD bem organizada para facilitar a manipulao dos seus objetos. Para melhor entender como as coisas acontecem voc pode encarar a estrutura de dados como um banco de dados de objetos que recebe comandos, reage a eventos, dispara seus prprios eventos e atua como um repositrio de objetos. Esse banco de dados opera sob algumas condies e regras. Algumas vezes sua manipulao um pouco burocrtica mas isso garante sua integridade e a estabilidade do aplicativo. Quando voc est criando um desenho dentro do AutoCAD, voc est na verdade criando, excluindo e modificando objetos no seu banco de dados. O banco de dados do AutoCAD um conjunto

O Poder do ObjectARX

de objetos hierarquicamente organizado cuja representao um desenho (um arquivo DWG). Se pegarmos como exemplo uma entidade simples, digamos uma LINE, ela contm todos os dados necessrios para se representar graficamente. Como um aplicativo vetorial, o AutoCAD no armazena pixels entre os pontos inicial e final de uma linha. Ele apenas armazena as coordenadas dos pontos inicial e final dessa linha (X,Y,Z). O desenho ento da linha propriamente dita feito atravs da equao matemtica que representa uma linha desenhada na tela automaticamente atravs de pixels. O processo completo de criao de uma LINE no est completo apenas se especificarmos suas propriedades mas requer ainda que voc especifique aonde e como esta LINE ser armazenada. Dentro do banco de dados do AutoCAD existem diversos tipo de objetos do tipo containers cuja finalidade armazenar e manter objetos. Cada container tem seus prprios procedimentos e regras para armazenar e recuperar seus objetos. Na maioria dos casos, responsvel por manter e salvar seus objetos. No exemplo da LINE ela poderia ser armazenadas num container de entidades. Esses containers de entidades so chamados de Block Table Records (BTR). Cada BTR pode armazenar diversos tipos de entidades como lines, circles, texts, blocks, etc. O diagrama da Figura 1, mostra parte da estrutura de dados do AutoCAD.

Figura 1 Banco de dados do AutoCAD mostrando os containers

A Figura 1 que as entidades podem ser armazenadas no Model Space, Paper Space ou outros Block Table Records. Esses outros BTR podem ser uma pgina de Layout ou mesmo outro Bloco. Cada bloco inserido dentro de um desenho do AutoCAD uma entidade Block Reference que aponta para o Bloco original que um Block Table Record. Por isso, quando editamos um Bloco com o comando REFEDIT ele reflete em todas as cpias desse Bloco pois na prtica voc est editando o Bloco original. A seguir, veja um trecho de cdigo que demonstra o processo de criao de uma entidade LINE em C++. O cdigo ir criar uma LINE do ponto (1.0, 1.0, 0.0) at o ponto (10.0, 10.0, 0.0):

O Poder do ObjectARX

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16

// cria dois pontos e uma linha AcGePoint3d startPt (1.0, 1.0, 0.0); AcGePoint3d endPt (10.0, 10.0, 0.0); AcDbLine* pLine = new AcDbLine (startPt, endPt); // abre o objeto container apropriado AcDbBlockTable* pBlock = NULL; AcDbDatabase* pDB = acdbHostApplicationServices()->workingDatabase(); pDB->getSymbolTable(pBlock,AcDb::kForRead); AcDbBlockTableRecord* pBTR = NULL; pBlock->getAt(ACDB_MODEL_SPACE, pBTR, AcDb::kForWrite); pBlock->close(); // agora, armazena a entidade no container AcDbObjectId Id; pBTR->appendAcDbEntity(Id, pLine); pBTR->close(); pLine->close();

O processo de criao da LINE similar ao processo de criao das outras entidades e ele basicamente consiste dos seguintes passos: Primeiro Instanciamos um ponteiro para a classe da entidade (alguns construtores iro permitir e exigir que voc fornea alguns parmetros); A seguir, precisamos abrir o Block Table aonde iremos encontrar o container apropriado. Nesse exemplo ns iremos usar o container Model Space; Depois disso, ns abrimos o Model Space (um Block Table Record) e adicionamos a ele a entidade recentemente instanciada.

muito importante notar que esse processo exige que voc abra e feche cada objeto especfico para ter acesso s suas propriedades e mtodos. Uma vez que a entidade seja adicionada ao banco de dados ela vai receber um identificador nico associado automaticamente pelo banco de dados do AutoCAD, chamado AcDbObjectId. Essa a chave de acesso entidade sempre que voc quiser. Ele vlido e permanece inalterado somente durante a sesso de desenho do AutoCAD. Essa apenas uma viso geral do processo para deixar claro os passos necessrios para criar uma entidade simples e para demonstrar o processo de acesso aos mtodos e procedimentos. A seguir voc ir aprender a criar um aplicativo ObjectARX usando o Visual Studio.

Viso Geral do Aplicativo ObjectARX O Aplicativo ObjectARX uma DLL (Dynamic Link Library). Isso permite com que ele seja carregado dentro do AutoCAD em tempo de execuo. Esse conceito evoluiu posteriormente para o Object Enabler que foi introduzido h algum tempo. Esse conceito divide o aplicativo em duas partes. O Object Enabler um aplicativo ObjectARX contendo apenas um conjunto de classes para objetos e entidades. Ele chamado de ObjectDBX e compatvel com todas as solues Autodesk construdas com a tecnologia RealDWG como os visualizadores DWG e todos os outros verticais AutoCAD. As ltimas trs letras do nome determinam sua finalidade: ARX (AutoCAD Runtime Extension) e DBX (Database Extension). Normalmente seu aplicativo ser constitudo por diversos mdulos ARX e DBX que iro representar as seguintes funcionalidades: Interfaces: Iro conter todas as janelas, comandos, eventos e qualquer outro cdigo relacionado s interfaces do AutoCAD. Ele ser um aplicativo ObjectARX representado por uma DLL (extenso de arquivo .arx) e ser compatvel somente com o AutoCAD e seus verticais; Classes customizadas: Iro conter todas as classes customizadas (objetos e/ou entidades) que no requerem a presena do aplicativo AutoCAD mas apenas do RealDWG. Ele ser um aplicativo

O Poder do ObjectARX

ObjectDBX representado por uma DLL (extenso de arquivo .dbx) e no poder conter qualquer chamada ou referncia a cdigo especfico do AutoCAD. Ele poder ser carregado dentro do AutoCAD, seus verticais e todos os aplicativos Autodesk com suporte ao ObjectDBX; Voc pode dividir seu aplicativo em diversos mdulos ARX e DBX e, dependendo da complexidade, isso far com que seu aplicativo seja muito mais organizado e escalvel. Imagine que voc precise trabalhar com um conjunto de clientes que pertencem ao mesmo segmento de indstria com pequenas diferenas entre seus produtos. Voc poder organizar seu aplicativo em classes para serem implementadas usando dois nveis de derivao. O primeiro nvel ir implementar o que existe de comum entre os produtos dos clientes. O prximo nvel ir implementar requisitos especficos de cada cliente e ir permitir que voc ajuste seu aplicativo especificamente para cada demanda. A estrutura geral de uma aplicao desse tipo teria os seguintes mdulos: MyClientBasics.dbx; MyClient1.dbx, MyClient2.dbx, MyClient3.dbx, etc.

Dessa forma, voc poder usar o mesmo ncleo de cdigo entre os clientes, e melhor, quando voc consertar um problema ou adicionar uma nova funcionalidade em seus mdulos base todos os clientes sero contemplados na prxima atualizao. Essa uma tima estratgia para manter seu aplicativo organizado, atualizado e ajustado para cada indstria com suas regras de negcio especficas. Os dois mdulos ARX e DBX podem ser carregados no AutoCAD usando um dos seguintes procedimentos: Comando ARX; Arquivo acad.rx; Comando APPLOAD; Mtodo AutoLISP arxload() ou mtodo ObjectARX acedArxLoad(); Opes de inicializao do AutoCAD: ld ou /ld; Entradas de Registro do Windows para Demand loading (carregamento automtico).

Esses procedimentos podem ser usados em situaes diferentes dependendo dos requisitos do seu aplicativo e dos mecanismos de distribuio e instalao.

Usando o ARXWizard Exerccio 1 O kit de desenvolvimento ObjectARX contm um plug-in do Visual Studio chamado ARXWizard. Esse plug-in ajuda voc a no somente criar um aplicativo ARX ou DBX mas tambm auxilia muito no processo de criao das suas classes personalizadas. O instalador do ARXWizard est localizado na pasta \utils\ObjARXWiz do seu kit. Basta executar esse instalador (com o Visual Studio fechado) que ele ir criar uma nova opo de tipo de projetos dentro do Visual Studio na janela New Project (dentro da categoria Visual C++) como mostrado na Figura 2.

O Poder do ObjectARX

Para criar um novo mdulo ARX ou DBX, abra o Visual Studio e faa o seguinte: Abra o menu File > New > Project; Selecione ObjectARX dentro do grupo Visual C++; Selecione o item ObjectARX/DBX/OMF Project; Especifique o nome do projeto, pasta e nome da soluo; Clique OK para continuar.

Figura 2 Janela New Project do Visual Studio

A seguir, voc precisa escolher o tipo de projeto (ARX ou DBX), suporte adicional do SDK, MFC, COM e .NET. Essas opes so descritas a seguir: Welcome Especifique seu smbolo de desenvolvedor para ser usado como preixo para todas as classes (isso evitar conflito com outros aplicativos ObjectARX/ObjectDBX de outros usurios ou empresas). Se desejar (recomendo que sim), habilite a opo do smbolo _DEBUG que ir permitir desvios no cdigo durante procedimentos de depurao.

Application Type Selecione o tipo de aplicativo: ObjectARX ou ObjectDBX.

Additional SDK Support Se desejar desenvolver um aplicativo que utilizar funcionalidades especificas ou classes do AutoCAD Architecture (OMF SDK) ou AutoCAD MAP (MAP API) habilite as opes.

O Poder do ObjectARX

MFC Support Se o seu aplicativo utilizar a biblioteca MFC necessrio habilitar o suporte atravs da opo MFC support. Adicionalmente, se for tambm utilizar os controles AutoCAD MFC, habilite essa opo. *Somente aplicativos do tipo ARX podem utilizar os controles AutoCAD MFC.

COM Options Se o seu aplicativo for utilizar as bibliotecas COM para cliente our servidor (ATL recomendado), escolha as opes necessrias.

.NET Support Se planejar desenvolver um aplicativo do tipo mixed-mode, habilite esta opo. Essa opo ir adicionar suporte ao .NET Framework alm do acesso s classes AutoCAD .NET de dentro do cdigo C++.

Esse processo ir criar o conhecido Esqueleto do Aplicativo que ir evitar um gasto de tempo considervel configurando tudo manualmente. Uma vez finalizado o processo de criao, A Solution do seu aplicativo ser algo como apresentado na Figura 3.

Para compilar esse projeto, precisamos adicionar os caminhos do ObjectARX (pasta include e lib) nas opes do Visual Studio. Isso precisar ser feito apenas uma vez e ir valer para os prximos projetos criados na mesma mquina. Acesse o menu Tools > Options, abra a entrada VC++ Directories. Siga as instrues das Figuras 4 e 5 e a seguir clique em OK para finalizar.

Figura 3 Tpica Solution ObjectARX

O Poder do ObjectARX

Na caixa Show directories for: selecione Include files e adicione duas pastas [drive:]\ObjectARX 2010\inc e [drive:]\ObjectARX 2010\inc-win32 (Figura 4). Se estiver em um sistema de 64-bit, utilize a pasta [drive:]\ObjectARX 2010\inc-x64. Repita a configurao para a opo Reference files. *[drive:] o seu drive local, normalmente C: ou D:

Figura 4 Pastas do ObjectARX para Include

A seguir, selecione Library files: na mesma caixa e adicione a nova pasta: [drive:]\ObjectARX 2010\lib-win32. Para sistemas de 64-bit, utilize: [drive:]\ObjectARX 2010\lib-x64 (Figura 5).

Figura 5 Pasta do ObjectARX para Library

Para compilar o projeto, primeiramente mude a configurao de compilao para Release. Para fazer isso, v ao menu Build, escolha Configuration Manager, selecione Release na caixa Active solution configuration. A seguir, v ao menu Build e escolha Build Solution. Voc deve obter algum resultado parecido com a tela de Output/Build a seguir (Figura 6).

Agora basta carregar seu aplicativo dentro do AutoCAD. Abra o AutoCAD e acione o comando APPLOAD. Procure pelo arquivo ArxProject1.arx dentro da pasta ArxProject1\Release, selecione o arquivo e click em LOAD.

Figura 6 Tpica tela de resultados de um Build

O Poder do ObjectARX

Conceitos de uma Entidade Customizada Uma vez que voc aprendeu a criar um aplicativo ObjectARX/ObjectDBX podemos agora aprofundar no assunto de Custom Entities. Como uma poderosa linguagem Orientada a Objetos, o C++ aos desenvolvedores derivar classes proporcionando uma grande reutilizao de cdigo. O conceito de herana (derivao) no um dos nossos objetivos mas podemos observar parte da hierarquia de classes do ObjectARX para entender melhor como as classes do AutoCAD so organizadas (Figura 7). O mesmo potencial de reutilizao de classes usado nos verticais do AutoCAD est disponvel atravs do ObjectARX. O primeiro passo para criarmos uma entidade customizada est na escolha de qual classe base iremos derivar. A seguir, necessrio escolher quais mtodos sua entidade ir redefinir. Quando a classe da sua entidade for carregada dentro do AutoCAD ela ser registrada na rvore dinmica de classes do ObjectARX ficando assim disponvel para utilizao. A entidade customizada participar, por padro, de vrias operaes e eventos disparados e coordenados pelo prprio AutoCAD.

AcDbEntity
YOUR CUSTOM ENTITY

AcDbCurve

AcDbDimension
AcDbAlignedDimension AcDbRotateDimension AcDbArcDimension

AcDbPolyline

AcDbCircle

AcDbLine

Figura 7 Parte da rvore de classes do ObjectARX

Como exemplo, o mtodo subWorldDraw() responsvel pelo desenho grfico da entidade. Esse mtodo tem uma assinatura especfica e virtual (pode ser sobrecarregado por classes derivadas) permitindo que sua entidade tenha sua prpria implementao. Uma vez que o AutoCAD precise refazer o desenho na tela ele inicia um processo de iterao no seu banco de dados chamando o mtodo subWorldDraw() e caso retorne false, chamando o mtodo subViewportDraw(). Certamente voc est pensando: Como o AutoCAD sabe como chamar o mtodo de uma classe que voc criou?. Ele no sabe mas o que ele sabe que sua entidade deriva de AcDbEntity aonde o mtodo subWorldDraw() foi inicialmente definido. O mecanismo da linguagem C++ ir ento, em tempo de execuo, redirecionar a chamada feita pelo AutoCAD no nvel AcDbEntity para o nvel da instncia da entidade aonde o mtodo foi definido. O mesmo processo ocorre para todos os outros mtodos virtuais. Dessa maneira, o AutoCAD abstrai todo o gerenciamento dos objetos no nvel de classe base refletindo nas classes derivadas. Se sua classe no implementar algum mtodo virtual especfico, ser feita uma chamada na prxima classe superiore assim sucessivamente at chegar-se no nvel da classe AcDbEntity. A maior parte dos mtodos da classe AcDbEntity no faz nada por padro e portanto necessrio implementar o cdigo especfico na sua classe.

...

...

O Poder do ObjectARX

Criando uma Custom Entity Exerccio 2 Etapa 1 Voc ir aprender nesse exerccio como criar uma simples entidade customizada. A simplicidade ser mantida para podermos manter o foco nos conceitos bsicos envolvidos. Nos prximos passos iremos aprimorar essa entidade acrescentando novas funcionalidades. O primeiro passo dar um nome para a entidade e escolher de qual classe ela ir derivar. Lembre-se que devemos dividir nosso aplicativo em dois mdulos, um ARX (interfaces) e um DBX (para as classes customizadas). Os dois projetos ficaro dentro de uma mesma Solution do Visual Studioe o mdulo ARX ir depender do mdulo DBX. Os nomes sero os seguintes (sem acentuao): Solution: Exercicio2 (o Visual Studio ir criar o arquivo Exercicio2.sln); DBX: AuCustomObjects (o Visual Studio ir criar o arquivo AuCustomObjects.vcproj); ARX: AuUserInterface (o Visual Studio ir criar o arquivo AuUserInterface.vcproj); Abra o Visual Studio, v ao menu File > New Project Abra Other Project Types e clique em Visual Studio Solutions. Selecione ento o template Blank Solution. De o nome de Exercicio2 (pode ser em qualquer pasta do seu computador). Clique em OK para continuar (Figura 8).

Figura 8 Projeto Blank Solution

Agora, boto direito na Solution; selectione Add e depois New Project, (Figura 9). A janela apresentada no Exerccio1 ir aparecer. Selecione na lista o template ObjectARX e crie os mdulos AuUserInterface e AuCustomObjects. Lembre-se de escolher o tipo ARX ou DBX apropriadamente.

Figura 9 Criando projetos na Solution

A localizao de cada projeto ser dentro da pasta da Solution por padro. No mude a localizao aps criar os projetos. Habilite a opo MFC em ambos os projetos (no necessrio habilitar o suporte a AutoCAD MFC). Habilite o smbolo _DEBUG. No habilite nada relacionado ao COM ou .NET em ambos os projetos. Faa com que o projeto AuUserInterface dependa do projeto AuCustomObjects. Para fazer isso, boto direito no projeto AuUserInterface e escolha Dependencies Marque ento o projeto AuCustomObjects na lista e clique em OK. Boto direito no projeto AuUserInterface novamente e selecione Set as Startup Project (ele ficar em negrito). Agora teste a compilao da sua Solution: V ao menu Build > Build Solution. Voc dever obter um Build sem erros e possivelmente alguns avisos que poderemos ignorar com segurana.

10

O Poder do ObjectARX

O teste final dessa etapa carregar o aplicativo dentro do AutoCAD. Lembre-se que nosso projeto AuUserInterface depende do projeto AuCustomObjects ento o mdulo DBX precisa ser carregado primeiro que o mdulo ARX. O processo de descarregamento deve ser feito na ordem inversa, AuUserInterface primeiro e em seguida o AuCustomObjects. Tudo dever funcionar de acordo. Nota: Voc pode compilar os projetos em Debug ou Release mas sempre recomendado carregar os dois projetos com o mesmo tipo de compilao. Agora que temos nossos mdulos DBX e ARX hora de criar a classe da nossa entidade customizada. Nesse exemplo, nossa entidade ir derivar da classe AcDbPolyline que representa a entidade POLYLINE do AutoCAD. O motivo da escolha que nossa entidade customizada ir se comportar quase exatamente como uma polyline mas iremos adicionar funcionalidades extras como numerao dos vrtices, smbolos de direo, hachura, etc. Para adicionar essa classe customizada iremos utilizar a ferramenta Autodesk Class Explorer localizada na barra de ferramentas do ARXWizard. Podemos acion-la pelo segundo boto conforme mostra a Firgura 10.

Figura 10 Barra de ferramentas do ARXWizard

Ao clicar nesse boto, uma janela ir aparecer exibindo todas as classes dos seus projetos. Nesse momento ainda no temos nenhuma classe. Selecione o mdulo DBX e ento clique com o boto direito nele. Um menu pop-up ser exibido. Selecione a opo Add an ObjectDBX Custom Object (Figura 11).

Figura 11 Janela Autodesk Class Explorer

Esse assistente tem 3 passos. O primeiro, chamado Names (Figura 12), permite especificar todas as caractersticas bsicas da entidade. Primeiro, d o nome AuPolyline. Escolha como classe base a classe AcDbPolyline (note que existem diversas outras classes das quais voc pode derivar). Os demais campos sero preenchidos automaticamente. Aperte Next.

Figura 12 Custom Object Wizard - Names

Como a classe polyline foi selecionada como base voc est especificando que sua entidade customizada se comportar como uma polyline exceto aonde voc redefinir. Isso ser feito atravs de mtodos virtuais como mencionado anteriormente. O assistente Custom Object Wizard tambm ir ajudar na implementao das funcionalidades bsicas. Isso feito atravs do segundo passo desse assistente, pgina Protocols. Habilitando essas opes o assistente fica instrudo de adicionar os respectivos mtodos virtuais simplificando o processo de criao da classe.

11

O Poder do ObjectARX

Nessa pgina voc poder definir se sua entidade participar dos protocolos DWG/DWF, se ela ir implementar pontos de OSNAP, pontos de GRIP e grficos independentes em viewports. Alm disso, poder ainda definir os protocolos genricos de curvas. Nesse exemplo, habilitaremos apenas o protocolo DWG e todos os 3 da classe base AcDbEntity. Esses protocolos iro permitir a implementao de funcionalidades bsicas (Figura 13).

Figura 13 Custom Object Wizard - Protocols

O terceiro passo, chamado Advanced, permitir a adio de notificaes e funcionalidades de cpia para a entidade customizada. Nesse exemplo no utilizaremos tais funcionalidades. Existem muitas outras funcionalidades que podem ser redefinidas atravs de uma grande coleo de mtodos virtuais mas para manter esse exemplos simples implementaremos somente essas. Clique em Finish para criar a classe da sua entidade. Lembre-se, ela ser criada no mdulo DBX. Se voc inspecionar o painel Solution Explorer ir observar dois novos arquivos: AuPolyline.h e AuPolyline.cpp. Esses arquivos, dentro do seu mdulo DBX, so responsveis pela declarao e implementao da entidade customizada. Abra esses dois arquivos e observe o cdigo criado. Agora iremos adicionar um comando, dentro do mdulo ARX, para criar uma instncia da nossa entidade customizada. Para fazer isso, no painel Solution Explorer, clique com o boto direito no projeto AuUserInterface e ento em Set as Startup Project (o nome do projeto ficar em negrito). Agora, clique no primeiro cone da toolbar ARXWizard (cone com o smbolo a>). Esse boto abrir a janela ObjectARX Commands. Existem duas listas nessa janela. Boto direito na primeira lista e selecione a opo New. Uma nova linha ser adicionada na lista com um nome padro de comando chamado MyCommand1. Na coluna Mode, troque de Transparent para Modal. Clique OK. Se voc abrir o arquivo acrxEntryPoint.cpp no projeto AuUserInterface ir encontrar, dentro da classe CAuUserInterfaceApp, um mtodo chamado AuUserInterface_MyCommand1() que ser acionado assim que digitar o comando MYCOMMAND1 dentro do AutoCAD. Nesse mtodo iremos criar um cdigo para instanciar nossa entidade AuPolyline. Lembre-se que a implementao da classe customizada est dentro do projeto DBX. Por esse motivo, precisamos adicionar (atravs da instruo #include) uma referncia para a classe AuPolyline e seu arquivo de cabealho (.H). Para fazer isso, adicione a seguinte linha no incio do arquivo acrxEntryPoint.cpp no mdulo ARX logo aps a linha #include "resource.h": #include "..\AuCustomObjects\AuPolyline.h" A barra ..\ faz com que a busca seja feita uma pasta acima (voltando pata raiz da Solution) e avanando ento dentro da pasta do mdulo DBX. O cdigo a seguir ir criar uma polyline de 10 lados (fechada) e vai adicion-la ao Model Space Block Table Record (container responsvel por armazenar entidades).

12

O Poder do ObjectARX

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

// - AuUserInterface._MyCommand1 command (do not rename) static void AuUserInterface_MyCommand1(void) { // Entidade AuPolyline AuPolyline* pL = new AuPolyline(); int nSides = 10; double incAngle = 2*3.141592 / nSides; // Adiciona a lista de vrtices for (int i=0; i<nSides; i++) pL->addVertexAt(i,AcGePoint2d(10*cos(i*incAngle), 10*sin(i*incAngle))); // Fecha a Polyline pL->setClosed(Adesk::kTrue); // Abre o container apropriado AcDbBlockTable* pBT = NULL; AcDbDatabase* pDB = acdbHostApplicationServices()>workingDatabase(); pDB->getSymbolTable(pBT,AcDb::kForRead); AcDbBlockTableRecord* pBTR = NULL; pBT->getAt(ACDB_MODEL_SPACE, pBTR, AcDb::kForWrite); pBT->close(); // Agora adiciona a entidade ao container AcDbObjectId Id; pBTR->appendAcDbEntity(Id, pL); pBTR->close(); pL->close(); }

No trecho das linhas 05-07 criamos a entidade e inicializamos variveis locais. Depois, nas linhas 9-10 adicionamos os vrtices. Na linha 12 configuramos a polyline como fechada. Nas linhas 1419 abrimos o banco de dados do AutoCAD, abrimos o container Block Table e pegamos o container Model Space. Nas linhas 21-24 adicionamos a entidade e fechamos os containers e a prpria entidade. Nota: Voc no pode acionar o operador delete em entidades adicionadas ao banco de dados do AutoCAD. O gerenciamento da entidade foi delegado ao AutoCAD e voc s precisa chamar o mtodo close(). Se voc chamar delete nesse ponteiro vai causar um erro fatal do AutoCAD. A seguir, boto direito no projeto AuUserInterface, Project Dependencies... e escolha o produto AuCustomObjects na lista. Isso ir instruir o compilar a sempre compilar primeiro o DBX e depois o ARX. Agora podemos compilar novamente o projeto (assegure que ambos os projetos estejam no mesmo modo Debug ou Release e mesma plataforma Win32 ou x64). A seguir, abra o AutoCAD, dispare o comando APPLOAD, carregue primeiro o mdulo DBX e a seguir o mdulo ARX (voc ver duas mensagens no prompt do AutoCAD indicando o carregamento dos mdulos com sucesso). Digite agora o comando MYCOMMAND1 e depois o comando ZOOM EXTENTS para visualizar a entidade criada. Se rodar o comando LIST e selecionar a entidade criada, ir observar seus dados.

Criando uma Custom Entity Exerccio 2 Etapa 2 Agora, depois de criarmos a entidade bsica, voc ir aprender como adicionar grficos a ela. Os grficos da entidade customizada so gerados primariamente pelo mtodo subWorldDraw() e opcionalmente pelo mtodo subViewportDraw() que pode gerar desenhos diferenciados por Viewport.

13

O Poder do ObjectARX

Como a classe base j capaz de gerar o desenho de uma polyline ns s precisaremos adicionar os grficos extras. Cada vrtice ir receber um ndice numrico e uma flecha indicando a direo de construo da polyline (Figura 14). Iremos utilizar cores diferentes para cada tipo de grfico. O ndice numrico utilizar a cor 256 que significa a cor ByLayer e as flechas utilizaro a cor 1 que representa a cor vermelho. Se voc alterar a cor do layer aonde sua entidade foi criada todo o grfico ir acompanhar a mudana exceto as flechas. Alm disso, todas as flechas tero o desenho feito com preenchimento.
Figura 14 Entidade com nmeros e flechas

Para criar esses elementos grficos utilizaremos alguns mtodos geomtricos. O cdigo a seguir mostra como podemos gerar o desenho da entidade: 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 Adesk::Boolean AuPolyline::subWorldDraw (AcGiWorldDraw *mode) { assertReadEnabled(); // Primeiro, chamamos o desenho da classe base AcDbPolyline::subWorldDraw(mode); double szRef = 5.0; // ================================================================ // Direo e numerao dos vrtices int signal = 1; double ht2 = szRef/4.0; for(int i=0; i<numVerts(); i++) { AcGePoint3d pti; this->getPointAt(i,pti); // Desenha o texto do vrtice CString strNum; strNum.Format(_T("%d"),i); AcGePoint3d ptTxt = pti + (AcGeVector3d::kXAxis*ht2) + (AcGeVector3d::kYAxis*ht2); mode->subEntityTraits().setColor(256); // ByLayer mode->geometry().text(ptTxt, AcGeVector3d::kZAxis, AcGeVector3d::kXAxis, ht2, 1.0, 0.0, strNum); // Direo da Flecha AcGePoint3d ptj; this->getPointAt(i<(numVerts()-1) ? (i+1) : 0, ptj); AcGeVector3d dir = (ptj - pti).normalize(); // Vetores perpendiculares AcGeVector3d perp = dir; perp.rotateBy(3.141592/2.0,AcGeVector3d::kZAxis); AcGePoint3d pt1 = ptj - (dir*ht2) + (perp*(ht2/4.0)); AcGePoint3d pt2 = ptj - (dir*ht2) - (perp*(ht2/4.0)); AcGePoint3d pts[3]; pts[0] = ptj; pts[1] = pt1; pts[2] = pt2;

14

O Poder do ObjectARX

34 35 36 37 38 39 40 41 42

// Desenha o polgono da flecha mode->subEntityTraits().setFillType(kAcGiFillAlways); mode->subEntityTraits().setColor(1); // red mode->geometry().polygon(3,pts); mode->subEntityTraits().setFillType(kAcGiFillNever); } //------ Returning Adesk::kFalse here will force viewportDraw() call return (Adesk::kTrue); }

Na linha 03 excutamos o mtodo de assert adequado que informa o tipo de acesso aos dados desse mtodo. Como nada est sendo alterado apenas precisamos LER dados da entidade e por isso chamamos o mtodo assertReadEnabled(). Na linha 05 chamamos o mtodo de desenho da classe base que ir desenhar as linhas da polyline. Nas linhas 06-10 incializamos variveis locais. A seguir, nas linhas 11-39 fazemos um lao de repetio em todos os vrtices para desenhar nossos grficos. Nas linhas 13-14 pegamos o ponto do vrtice em questo. Nas linhas 16-20 desenhamos o texto com o mtodo text() num ponto ligeiramente deslocado. Nas linhas 22-24 calculamos o centro (ptj) de cada segmento e seu vetor unitrio directional (dir). Depois, nas linhas 2633 calculamos 3 pontos para o desenho da cabea da flecha. O vetor perp permitir o desenho de cada lado da cabea da flecha como mostra a Figura 15. Nas linhas 35-38 desenhamos a cabea da flecha com a primitiva polygon() na cor vermelha e com o modo de preenchimento ligado. Finalmente, na linha 41, retornamos Adesk::kTrue para evitar uma chamada ao mtodo subViewportDraw(). As classes com prefixo AcGe utilizadas nesse mtodo, fazem parte da biblioteca AcGe que contm diversas classes e mtodos utilitrios para auxiliar nos clculos geomtricos. Isso nos ajuda muito devido a alta complexidade desses clculos.
Figura 15 Desenho da Flecha.

Criando uma Custom Entity Exerccio 2 Etapa 3 Agora voc ir aprender a adicionar pontos de GRIP na sua entidade. De fato, como a implementao padro da classe AuPolyline repassa a chamada para a classe base voc j deve ter notado que os pontos de GRIP esto visveis e funcionando. O comportamento do ponto de GRIP feito atravs de dois mtodos. O primeiro, chamado subGetGripPoints() responsvel pela obteno de todos os pontos de GRIP da entidade. O segundo, chamado subMoveGripPointsAt(), responsvel pela ao disparada quando cada GRIP acionado. A ao padro de cada GRIP mover o vrtice selecionado. Nesse exemplo ns queremos adicionar um GRIP extra posicionado no centro do polgono. Para fazer isso iremos primeiro criar um mtodo que calcula o centro do polgono. Iremos percorrer todos os pontos somando as coordenadas e depois dividindo o resultado por numVerts(). Esse mtodo no ir alterar dados da entidade ento recomendado que ele seja CONST utilizando apenas o mtodo de acesso assertReadEnabled():

15

O Poder do ObjectARX

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18

AcGePoint3d AuPolyline::GetPolylineCenter() const { assertReadEnabled(); AcGePoint3d ptC,pti; double cx = 0.0, cy = 0.0, cz = 0.0; for (int i=0; i<numVerts(); i++) { this->getPointAt(i,pti); cx += pti[X]; cy += pti[Y]; cz += pti[Z]; } cx = cx / numVerts(); cy = cy / numVerts(); cz = cz / numVerts(); ptC.set(cx, cy, cz); return ptC; }

Nas linhas 04-15 aplicamos a frmula do centro e na linha 16 criamos o ponto usando cx, cy e cz como as coordenadas X, Y e Z respectivamente. Agora, precisamos alterar o funcionamento padro dos mtodos relacionados aos pontos de GRIP. Primeiro iremos definir o mtodo subGetGripPoints(). Esse mtodo tem 2 assinaturas mas iremos implementar somente o cdigo para o mtodo que contm o parmetro AcDbGripDataPtrArray. Esse mtodo recebe um array de ponteiros AcDbGripData. Esses objetos representam as informaes do ponto de GRIP. Precisaremos informar o ponto e seus dados arbitrrios(void*). Esses dados arbitrrios podem ser usados posteriormente para recuperar as informaes de cada ponto de GRIP permitindo que o mtodo subMoveGripPointsAt() execute aes personalizadas. Alm disso, esse mtodo no ir alterar os dados da entidade ento ele ser tambm um mtodo do tipo CONST chamando assertReadEnabled(). Nas linhas 09-12 intanciamos um ponteiro para AcDbGripData e guardamos um valor aleatrio (9999 nesse caso) alm do ponto calculado pelo mtodo GetPolylineCenter() criado anteriormente. Depois, na linha 13 ns repassamos a chamada para o mtodo da classe base AcDbPolyline para que ela possa completar com seus prprios pontos de GRIP. Esses pontos de GRIP so os vrtices da polyline mencionados anteriormente: 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 Acad::ErrorStatus AuPolyline::subGetGripPoints ( AcDbGripDataPtrArray &grips, const double curViewUnitSize, const int gripSize, const AcGeVector3d &curViewDir, const int bitflags) const { assertReadEnabled () ; AcDbGripData* gpd = new AcDbGripData(); gpd->setAppData((void*)9999); // Dados do ponto central gpd->setGripPoint(GetPolylineCenter()); grips.append(gpd); AcDbPolyline::subGetGripPoints (grips, curViewUnitSize, gripSize, curViewDir, bitflags); return (Acad::eOk); }

O prximo passo alterar o mtodo subMoveGripPointsAt() de forma que quando o usurio clicar no GRIP no centro ele ir refletir uma ao especfica. Nesse exemplo, nossa ao para esse GRIP ser mover a polyline. O cdigo a seguir mostra como fazer isso:

16

O Poder do ObjectARX

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18

Acad::ErrorStatus AuPolyline::subMoveGripPointsAt ( const AcDbVoidPtrArray &gripAppData, const AcGeVector3d &offset, const int bitflags) { assertWriteEnabled () ; for (int g=0; g<gripAppData.length(); g++) { // Recupera os dados do Grip int i = (int)gripAppData.at(g); // Se for o nosso Grip, move a entidade inteira if (i == 9999) this->transformBy(offset); else AcDbCurve::subMoveGripPointsAt (gripAppData,offset,bitflags); } return (Acad::eOk); }

Dessa vez, nosso mtodo no pode ser CONST pois iremos alterar dados da entidade. Por isso chamaremos o mtodo assertWriteEnabled() logo no incio. Na linha 07 percorremos o array AcDbVoidPtrArray (ponteiros para void) procurando pelo nosso dado (9999). Esse mtodo tambm recebe um vetor 3D que representa o deslocamento aplicado ao GRIP. Se o GRIP modificado guardar o valor 9999 aplicaremos a transformao na polyline inteira. Faremos isso atravs do mtodo transformBy() passando o vetor 3D (Figura 16).
Figura 16 Ao do GRIP central

Se o GRIP acionado no guardar o cdigo 9999 repassaremos a chamada para a classe AcDbCurve (classe base da AcDbPolyline) que ir tratar esse ponto. O comportamento resultante ao selecionarmos um GRIP no contorno da Polyline ser o esticamento/encolhimento e quando selecionarmos o GRIP do centro a entidade inteira ir mover.

Criando uma Custom Entity Exerccio 2 Etapa 4 Agora voc ir aprender como adicionar os pontos de preciso ou pontos OSNAP. Se executar o programa at o momento ir perceber que a entidade j mostra alguns pontos de OSNAP automaticamente (ENDPOINT e MIDPOINT). Nesse exemplo, queremos adicionar um ponto de CENTER na nossa polyline que permitir aos usurios selecionarem o nosso ponto central. Para implementar isso, precisaremos alterar o mtodo subGetOsnapPoints(). Esse mtodo tem 2 assinaturas e implementaremos apenas o mtodo que recebe um parmetro AcDbIntArray. Iremos ento analisar o tipo de OSNAP solicitado, no caso o CENTER, retornando assim o nosso ponto central:

17

O Poder do ObjectARX

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18

Acad::ErrorStatus AuPolyline::subGetOsnapPoints ( AcDb::OsnapMode osnapMode, int gsSelectionMark, const AcGePoint3d &pickPoint, const AcGePoint3d &lastPoint, const AcGeMatrix3d &viewXform, AcGePoint3dArray &snapPoints, AcDbIntArray &geomIds) const { assertReadEnabled () ; switch(osnapMode) { case AcDb::kOsModeCen: snapPoints.append(GetPolylineCenter()); break; } return (AcDbPolyline::subGetOsnapPoints (osnapMode, gsSelectionMark, pickPoint, lastPoint, viewXform, snapPoints, geomIds)) ; }

Esse mtodo recebe um array de pontos no qual precisamos adicionar nosso ponto central sempre que o OSNAP CENTER for solicitado. Na linha 13 testamos o tipo kOsModeCen e adicionamos o ponto central ao array snapPoints (Figura 17). Mesmo tratando o OSNAP CENTER em particular o mtodo precisa repassar a chamada para a classe base. A classe da polyline ir tratar os demais casos de OSNAP.
Figura 17 OSNAP CENTER

Nota: Essa soluo de OSNAP trata apenas casos simples como CENTER, MIDPOINT e ENDPOINT. Casos de OSNAP mais complexos como INTERSECTION requer a implementao de outros mtodos e procedimentos.

Criando uma Custom Entity Exerccio 2 Etapa 5 Muitas vezes precisamos enviar os desenhos de AutoCAD contendo nossa entidade customizada. Por padro, quando o AutoCAD abre um desenho e encontra alguma entidade que ele no reconhece nativamente, ele protege os dados numa entidade Proxy. A entidade Proxy protege os dados do objeto evitando que usurios indesejados alterem a entidade. A entidade proxy meramente um pacote de dados com uma representao grfica fixa. A maioria das funcionalidade da sua entidade no estaro disponveis pois o seu cdigo no estar presente para implementar as funcionalidades. Se o desenho for aberto por um usurio inadvertidamente ele dever ser informado da existncia de entidades Proxy. A entidade Proxy grficos especficos gerados atravs de uma chamada ao mtodo subWorldDraw() logo antes do AutoCAD fechar o desenho. O mtodo subWorldDraw() recebe um parmetro, um ponteiro para AcGiWorldDraw, que d acesso ao mtodo regenType() que permite descobrir se a chamada ao mtodo foi feita para fins de gerar os grficos de Proxy. Nesse momento,

18

O Poder do ObjectARX

voc poder at desenhar grficos diferentes para a sua entidade ou at um texto avisando Meu aplicativo no est disponvel. O cdigo a seguir mostra como tratar o desenho do Proxy: 01 02 03 04 05 06 07 08 09 // ================================================================== // PROXY if (mode->regenType() == kAcGiSaveWorldDrawForProxy) { // Desenha um texto qualquer de aviso CString strTxt = _T("AU Polyline"); AcGePoint3d ptTxt = GetPolylineCenter(); mode->geometry().text(ptTxt, AcGeVector3d::kZAxis, AcGeVector3d::kXAxis, szRef, 1.0, 0.0, strTxt); }

Nesse exemplo, o nosso desenho de Proxy ser o desenho padro da entidade acrescido de um texto informativo. Voc poderia at colocar a URL do seu produto ou empresa. Para simplificar, criaremos esse texto iniciando no ponto central da polyline. Para entidades derivadas de AcDbPolyline ainda necessrio mais um passo para implementar o Proxy. O mtodo saveAs() precisa ser implementado na classe para que o mtodo subWorldDraw() possa ser acionado no momento apropriado para a gerao do Proxy. Esse mtodo pode ser declarado no arquivo .H da seguinte maneira: virtual void saveAs(AcGiWorldDraw * mode, AcDb::SaveType st); A respectiva implementao, no arquivo .CPP ser: 01 02 03 04 05 06 void AuPolyline::saveAs(AcGiWorldDraw * mode, AcDb::SaveType st) { AcDbPolyline::saveAs (mode, st) ; if (mode->regenType() == kAcGiSaveWorldDrawForProxy) this->worldDraw(mode); }

Esse mtodo chama incialmente a classe base e a seguir testa se o mtodo regenType() para gerao de grficos de Proxy. Se for verdadeiro ns executamos nosso prprio mtodo subWorldDraw() que ir gerar o desenho da nossa classe customizada acrescido do texto de Proxy. Para testar esse comportamento, crie a nossa entidade AuPolyline e salve o desenho. Feche o AutoCAD e abra novamente o DWG salvo mas sem carregar os mdulos. Uma vez que o DWG for aberto voc ver um aviso de proxy contendo informaes do aplicativo e classe ausentes (Figura 18).

Figura 18 Informaes de Proxy

19

O Poder do ObjectARX

Note que na Figura 18 o texto configurado para Proxy exibido. Na janela de informaes de Proxy, sero exibidas informaes do aplicativo ausente. Essa janela permite ao usurio configurar as opes de exibio das entidades Proxy. Voc tambm poder configurar a exibio das entidades Proxy atravs do menu Tools > Options > Open and Save. Lembre-se que o mdulo DBX pode ser carregado para restaurar o modo de desenho normal e por isso voc pode enviar o mdulo DBX juntamente com o DWG permitindo assim que outros usurios possam visualizar suas entidades com o desenho apropriado. Nesse caso voc forneceria apenas as classes do seu programa no forneceria os comandos e janelas (que esto no mdulo ARX). Nesse cenrio os usurios sero capazes de visualizar a entidade mas sem editar pelos comandos que voc criou. O AutoCAD permite algumas alteraes bsicas em entidades proxy como apagar, alterar o layer, alterar a color e algumas transformaes grficas. Essas operaes surtiro efeito sobre os grficos proxy atravs da representao grfica que voc definiu (os dados da entidade estaro preservados a no ser que o usurio apague ela do desenho). O desenvolvedor determina as opes e limitaes mais adequadas para a entidade proxy. Isso uma opo definida em tempo de compilao atravs de uma macro na implementao da classe da entidade (ACRX_DXF_DEFINE_MEMBERS). Essas opes podem ser combinadas para completar o comportamento desejado da entidade Proxy. Consulte a documentao do ObjectARX SDK para mais detalhes dos proxy flags.

Criando uma Custom Entity Exerccio 2 Etapa 6 Nessa etapa iremos implementar uma funcionalidade muito interessante. Imagine que voc desejasse adicionar uma hachura sua entidade. Podemos tirar vantagem da funcionalidade do ObjectARX de objetos embebidos para implementar a hachura. Existe uma classe chamada AcDbHatch que representa a entidade de hachura no AutoCAD. Essa classe pode ser usada como um objeto embebido e podemos usar seu mtodo worldDraw() para desenhar nosso padro de hachura. A primeira coisa que precisamos fazer adicionar um membro do tipo AcDbHatch na classe da nossa entidade. Tambm criaremos um mtodo chamado SetupHatch() que ir configurar as propriedades da hachura. Para fazer isso, abra o arquivo AuPolyline.h e adicione as seguintes linhas no final da declarao da classe: protected: AcDbHatch m_Hatch; public: void SetupHatch();

Alm disso, precisamos adicionar mais 3 mtodos nossa classe para lidar com as modificaes feitas pelo usurio. O primeiro mtodo ir lidar com as transformaes grficas. Os outros 2 mtodos iro dar suporte ao comando STRETCH: public: virtual Acad::ErrorStatus subTransformBy(const AcGeMatrix3d & xform); virtual Acad::ErrorStatus subGetStretchPoints( AcGePoint3dArray & stretchPoints) const; virtual Acad::ErrorStatus subMoveStretchPointsAt( const AcDbIntArray & indices, const AcGeVector3d & offset);

20

O Poder do ObjectARX

Nosso objeto embebido de hachura precisa ser configurado. Para fazer isso, dentro do construtor da classe localizando no arquivo AuPolyline.cpp, o seguinte cdigo (observe que a configurao s precisa ser feita uma vez na inicializao dos objetos dessa classe): 01 02 03 04 05 06 07 08 09 10 AuPolyline::AuPolyline () : AcDbPolyline () { m_Hatch.setNormal(AcGeVector3d::kZAxis); m_Hatch.setElevation(this->elevation()); m_Hatch.setAssociative(true); m_Hatch.setPatternScale(1.0); m_Hatch.setPatternAngle(45.0); m_Hatch.setHatchStyle(AcDbHatch::kNormal); m_Hatch.setPattern(AcDbHatch::kPreDefined,_T("LINE")); }

Essa configurao ir escolher o padro, vetor normal, elevao, escala, ngulo e estilo. Nesse exemplo esses valores so fixos mas voc poderia criar uma propriedade para cada um permitindo que o usurio alterasse essas propriedades durante a execuo do programa. Agora precisamos implementar o mtodo SetupHatch() que ir construir o loop da hachura de acordo com o contorno da nossa polyline. O cdigo o seguinte: 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 void AuPolyline::SetupHatch() { assertWriteEnabled(); // Remove qualquer loop existente for (int l=0; l<m_Hatch.numLoops(); l++) m_Hatch.removeLoopAt(l); // Insere o novo loop AcGePoint2dArray vertexPts; AcGeDoubleArray vertexBulges; // Obtm os pontos for(int i=0; i<numVerts(); i++) { AcGePoint2d pt2d; double bulge = 0.0; this->getPointAt(i,pt2d); this->getBulgeAt(i,bulge); vertexPts.append(pt2d); vertexBulges.append(bulge); } // Fecha o loop vertexPts.append(vertexPts.first()); vertexBulges.append(vertexBulges.first()); m_Hatch.appendLoop(AcDbHatch::kDefault, vertexPts,vertexBulges); // Atualiza o Hatch m_Hatch.evaluateHatch(); }

Nas linhas 05-06 nos asseguramos que no exista nenhum loop. Nas linhas 11-18 percorremos os vrtices da polyline pegando os pontos e bulges (um bulge a tangente de 1/4 do ngulo includo do arco entre o vrtice selecionado e o prximo vrtice). A informao obtida ser armazenada em vetores

21

O Poder do ObjectARX

dinmicos: AcGePoint3dArray e AcGeDoubleArray. Nas linhas 20-21 fechamos o loop da polyline para asseguramos que o contorno da hachura seja fechado. Na linha 22 adicionamos os arrays como loops da hachura. Um loop tambm pode representar um buraco na superfcie hachurada mas nesse exemplo nosso loop do tipo AcDbHatch::kDefault. Na linha 24 finalizamos o processo de configurao do hatch chamando o mtodo evaluateHatch() que ir recriar a hachura baseada nas informaes fornecidas. Precisamos chamar o mtodo SetupHatch() dentro de outros mtodos necessrios. O primeiro lugar no mtodo dwgInFields(). Adicione a chamada ao mtodo no final como mostrado a seguir: 01 02 03 04 05 06 07 Acad::ErrorStatus AuPolyline::dwgInFields (AcDbDwgFiler *pFiler) { [ linhas omitidas para simplificao ] // Configura hachura SetupHatch(); return (pFiler->filerStatus ()) ; }

A seguir, precisamos colocar outra chamada dentro do mtodo subMoveGripPointsAt(). Quando o usurio mover algum dos pontos de GRIP precisamos recalcular o contorno da hachura. Precisaremos fazer isso somente nos casos que o GRIP selecionado for o nosso ponto central. A alterao feita nas linhas 15-18 conforme mostrado a seguir: 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 Acad::ErrorStatus AuPolyline::subMoveGripPointsAt ( const AcDbVoidPtrArray &gripAppData, const AcGeVector3d &offset, const int bitflags) { assertWriteEnabled () ; for (int g=0; g<gripAppData.length(); g++) { // Recupera os dados do Grip int i = (int)gripAppData.at(g); // Se for o nosso Grip, move a entidade inteira if (i == 9999) this->transformBy(offset); else { AcDbCurve::moveGripPointsAt(gripAppData,offset,bitflags); SetupHatch(); } } return (Acad::eOk); }

Para fazermos a entidade da hachura aparecer como parte do desenho da nossa entidade customizada precisamos chamar o mtodo geometry()->draw() dentro do mtodo subWorldDraw() da classe da entidade:

22

O Poder do ObjectARX

01 02 03 04 05 06 07 08 09

Adesk::Boolean AuPolyline::subWorldDraw (AcGiWorldDraw *mode) { [ linhas omitidas para simplificao ] // ======================================================= // HATCH mode->geometry().draw(&m_Hatch); //------ Returning Adesk::kFalse to force viewportDraw() call return (Adesk::kTrue) ; }

Finalmente, precisamos implementar o cdigo para os 3 novos mtodos que declaramos na classe da entidade. Abra o arquivo AuPolyline.cpp e adicione os mtodos seguintes: 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 // ------------------------------------------------------------------Acad::ErrorStatus AuPolyline::subTransformBy(const AcGeMatrix3d & xform) { Acad::ErrorStatus retCode = AcDbPolyline::subTransformBy(xform); m_Hatch.transformBy(xform); return (retCode) ; } // ------------------------------------------------------------------Acad::ErrorStatus AuPolyline::subGetStretchPoints(AcGePoint3dArray & stretchPoints) const { AcDbIntArray osnapModes,geomIds; return this->subGetGripPoints(stretchPoints,osnapModes,geomIds); } // ------------------------------------------------------------------Acad::ErrorStatus AuPolyline::subMoveStretchPointsAt( const AcDbIntArray & indices, const AcGeVector3d & offset) { Acad::ErrorStatus ret = AcDbPolyline::subMoveGripPointsAt (indices, offset); SetupHatch(); return ret; }

O primeiro mtodo nas linhas 02-07, subTransformBy(), responsvel por todas as transformaes grficas como MOVE, ROTATE, SCALE, etc. Primeiro repassamos a chamada para a classe e depois aplicamos a mesma transformao para a hachura. Dessa maneira ela seguir todas as transformaes aplicadas nossa AuPolyline. Os segundo mtodo, nas linhas 09-13, subGetStretchPoints(), responsvel por retornar os pontos que so habilitados para o stretch da entidade. Nesse caso iremos habilitar todos os vrtices da nossa polyline. Podemos utilizar os mesmos pontos obtidos pelo mtodo subGetGripPoints() pois so os mesmos que desejamos nesse momento. O ltimo mtodo, nas linhas 15-22, subMoveStretchPointsAt(), responsvel pela aplicao da transformao de stretch na entidade. Tambm podemos reutilizar o mtodo subMoveGripPointsAt() porque ele faz exatamente o que precisamos. A seguir apenas precisamos chamar o mtodo SetupHatch() para garantir que hachura estar atualizada como o novo contorno resultante das modificaes feitas pelo comando STRETCH. Antes de testar nossa entidade, precisamos colocar uma chamada ao mtodo SetupHatch() logo antes de fechar nossa entidade no mtodo de criao. Abra o arquivo acrxEntryPoint.cpp, no projeto AuUserInterface, mtodo AuUserInterface_MyCommand1(). Veja o cdigo a seguir:

23

O Poder do ObjectARX

01 02 03 04 05 06

static void AuUserInterface_MyCommand1(void) { [ linhas omitidas para simplificao ] pL->SetupHatch(); pL->close(); }

Agora faa um Build na Solution. No devem aparecer erros. Abra o AutoCAD, carregue os mdulos (lembre-se, primeiro o BDX e depois o ARX). Acione o comando MYCOMMAND1 e crie uma entidade AuPolyline. Depois teste as diversas funcionalidades implementadas. Tente o comando COPY na entidade, depois MOVE, ROTATE, SCALE e at o comando MIRROR. Voc pode ainda usar o comando STRETCH e acionar os pontos de GRIP para alterar a forma da entidade. Nossa entidade AuPolyline deriva de AcDbPolyline, correto? Ento supostamente os comandos PEDIT deveriam funcionar com nossa entidade? SIM, funciona! Tente usar o comando PEDIT e selecione nossa entidade. Ele ir aceita-la e permitir que voc altere a AuPolyline como se ela fosse uma Polyline nativa do AutoCAD. Voc pode adicionar novos vrtices, remover existentes, adicionar novos segmentos e tudo mais (Figura 19). Genial, no?

Figura 19 AuPolyline modificadas

Concluso Nesse curso voc aprendeu como criar uma entidade customizada e adicionar algumas funcionalidades que o ObjectARX permite. Isso apenas uma introduo. Existem muito mais coisas que voc pode fazer utilizando as classes do ObjectARX e implementando coisas sofisticadas. Espero que esse curso lhe ajude a conhecer um pouco do mundo do ObjectARX. Se tiver alguma dvida entre em contato por e-mail ou visite meu Blog atravs do endereo: http://arxdummies.blogspot.com/ e encontre mais informaes sobre o assunto. Obrigado!

24