• Nenhum resultado encontrado

ObjectARX.pdf

N/A
N/A
Protected

Academic year: 2021

Share "ObjectARX.pdf"

Copied!
104
0
0

Texto

(1)

Esta é a versão em html do arquivo http://www.cadtec.dees.ufmg.br/publico/Regina/ObjectARX%20B% C3%A1sico/ApostilaARX/ObjARX_Apostila.doc.

Google cria automaticamente versões em texto de documentos à medida que vasculha a web.

ObjectARX

For AutoCAD Release 14

Apostila do Desenvolvedor

Revisão Abril/98

1

a

Edição

Editor

José Ricardo Queiroz Franco

Autores

Alexandra Hütner Fernando Poinho Malard

Jacqueline Maria Flor

Juliana Mascarenhas

Índice Analítico

Usando a Plataforma ARX

(2)

ObjectARX é o ambiente de programação do AutoCAD Runtime Extension. Este ambiente inclui bibliotecas da linguagem C++, que permitem o desenvolvimento de aplicativos específicos de classes e protocolos no AutoCAD extendidos, e cria novos comandos que operam da mesma maneira que os comandos intrínsecos do AutoCAD.

A utilização da linguagem C++ orientada a objetos pelo ObjectARX, faz com que se tenha um desenvolvimento performático bastante superior aos já existentes. Na análise Orientada a Objetos, dados e procedimentos fazem parte de um só elemento básico ( objeto ou classe ). Esses elementos básicos, ao estabelecer comunicação entre si, caracterizam a execução do programa. Assim, ao contrário da filosofia estruturada, onde dados e procedimentos são entidades dissociadas, no paradigma da orientação a objetos os dados e procedimentos estão encapsulados em um só elemento. Em termos técnicos, o desenvolvimento exige alguns Softwares para que se possa fazer o devido uso das ferramentas de linguagem. Apesar de o ObjectARX já ter sido implementado na versão 13 do AutoCAD, é recomendável pela sua confiabilidade, a utilizaçào do AutoCAD release 14 for Windows. Da mesma forma recomenda-se o Visual C++ 4.1a e ainda mais eficiente, o Visual C++ 5.0. A Autodesk envia aos seus desenvolvedores um CD de consulta on line chamado ObjectARX que torna o trabalho ainda mais imediato.

I.

Visão Geral

Uma aplicação ARX é uma biblioteca de vínculo dinâmico (dynamic link library _ DLL) que compartilha o espaço no mesmo endereço do AutoCAD e chama funções diretamente do AutoCAD. As bibliotecas do ARX incluem macros para facilitar a definição de novas classes e oferecer a habilidade para adicionar funcionalidade às classes existentes. O ARX pode ser usado juntamente com o AutoCAD Development System (ADefS) e também com aplicativos em AutoLISP.

Ambiente ARX

O ambiente ARX fornece uma interface para a aplicação da linguagem orientada a objetos C++ que habilita desenvolvedores usar, customizar, e automatizar o AutoCAD. O ARX é de extrema versatilidade na utilização do seu banco de dados, no sistema gráfico, e na definição dos seus comandos nativos.

O ambiente ARX difere do ADS e do AutoLISP de enumeras formas. O AutoLISP é uma linguagem interpretada pelo AutoCAD, uma simples forma de apenas adicionar comandos. Sua conecção com o AutoCAD é feita através de um interprocesso de comunicação (IPC). Dessa mesma forma é também o ADS que é escrito em C e compilado antes de ser carregado via IPC pelo AutoLISP e só assim executado no AutoCAD. O ADS é apenas uma tradução do AutoLISP.

(3)

IPC

AutoLISP

IPC

AutoCAD

Aplicativos ARX

Bibliotecas ARX

Classe AcRx

O AcRx fornece o nível de classes para a inicialização DLL, linkagem e também registro e identificação das classes. A classe básica é AcRxObject.

O AcRx também fornece um conjunto de macros em C++ para ajudar na criação de novas classes em

ARX, que são derivadas do AcRxObject.

Outra importante classe é AcRxDictionary que é um dicionário de strings que aponta para outro objeto. O AcRx armazena classes, objetos e dicionários.

Classe hierárquica: AcRxObject AcRxClass AcRxDictionary AcRxDLinkerReactor AcRxDynamicLinker AcRxIterator AcRxDictionaryIterator AcRxService Classe AcEd

(4)

operam da mesma maneira que os comandos internos do AutoCAD. Ambos comandos residem na mesma estrutura interna, AcEdCommandStack. Uma classe importante é a AcEditorReactor, que monitora o editor do AutoCAD e notifica os eventos ocorridos.

Classe hierárquica: AcRxObject AcEdCommandIterator AcEdCommandStack AcEditor AcEdJig AcEditorReactor AcTransaction AcTransactionManager AcTransactionReactor Classe AcDb

O AcDb fornece classes que possibilitam o acesso na estrutura do banco de dados do AutoCAD. Este banco de dados armazena todas as informações para os objetos gráficos (entidades) e não gráficos que compõe um desenho do AutoCAD.

O banco de dados do AutoCAD contém:

 Um conjunto de nove symbol tables

 Um named object dictionary ( class AcDbDictionary ) que contém uma tabela de conteúdos para o AutoCAD que pode ser facilmente alterada

 Um conjunto fixo de 200 variáveis de cabeçalho definidas pelo AutoCAD

Classe hierárquica: AcDbAuditInfo AcDbRecover

AcDbRecoverCallBack

AcDbHandle (Identificação do objeto) AcDbObjectId

AcDbHardOwnershipId AcDbHardPointerId AcDbSoftOwnershipId AcDbSoftPointerId

(5)

AcDbIdMapping (Usado para deep clone) AcDbIdMappingIter AcDbIdPair AcDbSymbolTableIterator (Iterators) AcDbBlockTableIterator AcDbBlockTableRecordIterator AcDbDimStyleTableIterator AcDbLayerTableIterator AcDbLinetypeTableIterator AcDbRegAppTableIterator AcDbTextStyleTableIterator AcDbUCSTableIterator AcDbAbstractViewTableIterator AcDbViewTableIterator AcDbViewportTableIterator AcDbGroup Iterator AcDbExtents AcDbDate AcDbIntArray AcDbObjectIdArray AcDbVoidPtrArray AcRxObject

AcDbDatabase (AutoCAD banco de dados) AcDbDictionaryIterator

AcDbDwgFiler (Arquivos) AcDbDwgCopyFiler AcDbDeepCloneFiler

(6)

AcDbWblockCloneFiler AcDbDwgUndoFiler AcDbDxfFiler

(AcRxObject)

AcDbObject (Classe mais importante) AcDbDictionary

AcDbEntity (AutoCAD entidades) AcDb3dSolid AcDbBlockBegin AcDbBlockEnd AcDbBlockReference AcDbMInsertBlock AcDbBody AcDbCurve AcDb2dPolyline AcDb3dPolyline AcDbArc AcDbCircle AcDbEllipse AcDbLeader AcDbLine AcDbRay AcDbSpline AcDbXline AcDbDimension AcDb2LineAngularDimension AcDb3PointAngularDimension

(7)

AcDbAlignedDimension AcDbDiametricDimension AcDbOrdinateDimension AcDbRadialDimension AcDbRotatedDimension AcDbFace AcDbFaceRecord AcDbFcf AcDbMline AcDbMText AcDbOleFrame AcDbPoint AcDbPolyFaceMesh AcDbPolygonMesh AcDbRegion AcDbSequenceEnd AcDbShape AcDbSolid AcDbText AcDbAttribute AcDbAttributeDefinition AcDbTrace AcDbVertex AcDb2dPolylineVertex AcDb3dPolylineVertex AcDbPolyFaceMeshVertex AcDbPolygonMeshVertex

(8)

AcDbViewport AcDbProxyEntity (AcRxObject) (AcDbObject) AcDbGroup AcDbMlineStyle

AcDbSymbolTable (Symbol tables) AcDbBlockTable AcDbDimStyleTable AcDbLayerTable AcDbLinetypeTable AcDbRegAppTable AcDbTextStyleTable AcDbUCSTable AcDbAbstractViewTable AcDbViewportTable AcDbViewTable

AcDbSymbolTableRecord (Symbol table records) AcDbAbstractViewTableRecord AcDbViewportTableRecord AcDbViewTableRecord AcDbBlockTableRecord AcDbDimStyleTableRecord AcDbLayerTableRecord AcDbLinetypeTableRecord AcDbRegAppTableRecord AcDbTextStyleTableRecord

(9)

AcDbUCSTableRecord AcDbProxyObject

AcDbObjectIterator

AcDbObjectReactor (Notificação de eventos) AcDbEntityReactor

AcDbDatabaseReactor

Classe AcGi

O AcGi fornece a interface gráfica usada para as entidades do AutoCAD. Ela é usada pelas funções membro do AcDbEntity como worldDraw( ), viewportDraw( ) e saveAs( ), que fazem parte do protocolo padrão da entidade. O worldDraw( ) deve ser definida para todas as classes de entidades customizadas. O objeto AcGiWorldDraw fornece um API através do qual o AcDbEntity::worldDraw

( ) podeproduzir uma representação gráfica em todos os viewports simultâneamente. Similarmente, o

objeto AcGiViewportDraw fornece um API através do qual o AcDbEntity::viewportDraw( ) pode produzir representações gráficas para cada viewport.

Classe hierárquica: AcRxObject AcGiEdgeData AcGiFaceData AcGiSubEntityTraits AcGiTextStyle AcGiVertexData AcGiViewport AcGiViewportDraw AcGiViewportGeometry AcGiWorldDraw AcGiWorldGeometry Classe AcGe

O AcGe é usado pelo AcDb e fornece classes úteis assim como vetores, pontos e matrizes (2D e 3D). Ela também disponibiliza objetos geométricos simples como pontos, curvas e superfícies. Essas classes que compõe AcGe podem ser usadas para operações básicas com vetores, pontos e matrizes. Os membros dessa classe devem ser declarados públicos.

Classe hierárquica: AcGePoint2d AcGeVector2d

(10)

AcGeMatrix2d AcGeScale2d AcGePoint2dArray AcGeVector2dArray AcGePoint3d AcGeVector3d AcGeMatrix3d AcGeScale3d AcGePoint3dArray AcGeVector3dArray AcGeTolerance AcGeInterval AcGeCurveBoundary AcGeDoubleArray AcGeKnotVector AcGeEntity2d AcGePointEnt2d AcGePosition2d AcGePointOnCurve2d AcGeCurve2d AcGeLinearEnt2d AcGeLine2d AcGeRay2d AcGeLineSeg2d AcGeCircArc2d AcGeEllipArc2d AcGeSplineEnt2d

(11)

AcGeCubicSpline2d AcGeNurbCurve2d AcGePolyLine2d AcGeExternalCurve2d AcGeEntity3d AcGePointEnt3d AcGePosition3d AcGePointOnCurve3d AcGePointOnSurface AcGeCurve3d AcGeLinearEnt3d AcGeLine3d AcGeRay3d AcGeLineSeg3d AcGeCircArc3d AcGeEllipArc3d AcGeExternalCurve3d AcGeSplineEnt3d AcGeCubicSpline3d AcGeNurbCurve3d AcGePolyLine3d AcGeAugPolyLine3d AcGeSurface AcGePlanarEnt AcGePlane AcGeBoundedPlane AcGeCylinder

(12)

AcGeCone AcGeSphere AcGeTorus AcGeNurbSurface AcGeExternalSurface AcGeOffsetSurface AcGeExternalBoundedSurface

Registrando comandos

No ARX pode-se adicionar novos comandos com a função ads_defun() ou com a macro

acedRegCmds(). Com a biblioteca de comandos ADS, os requisitos são antes passados pelo AutoLISP

e depois para o aplicativo. Com o ARX, os comandos são adicionados diretamente ao conjunto de comandos do AutoCAD.

Cada maneira de registrar os comandos afeta a forma de invocá-los. Se o comando de registro usado for o ads_defun():

Os comandos podem ser evoluídos através do AutoLISP ou das facilidades do ads_invoke()

Os comandos não poderão ser invocados usando a função command do AutoLISP ou a função

ads_command().

Se for usada a macro acedRegCmds():

Os comandos não são reconhecidos pelo AutoLISP ou pelas facilidades do ads_invoke()

Os comandos podem ser invocados usando a função command do AutolISP ou a função

ads_command()

Entrada de pontos

ARX e ADS tem modelos diferentes para comunicar com o AutoCAD. Um aplicativo ADS consiste num loop infinito que espera pela requisição do AutoLISP. Um aplicativo ARX tem um “entry

point” que é usado para mensagens. Então, quando um novo comando é registrado, ele passa a ser um

“entry point” adicional do aplicativo. Quando escrevemos funções virtuais para classes C++ nas biliotecas ARX, elas passam a ser novos “entry point” no aplicativo.

II.

Noções Básicas do Banco de Dados

(13)

O banco de dados do AutoCAD armazena os objetos e entidades que são feitas no desenho do AutoCAD. As entidades são objetos de desenho com representação gráfica e são possuídas pelo block table record que por sua vez é armazenado no block table. O banco de dados é constituído por elementos de banco de dados: o named object dictionary e um conjunto de symbol tables, dentre eles esta o block table.

DATABASE

Symbol Table

Layer Table

NOD

Block Table

Layer Table

Record

Objetos

Symbol Table

Record

Entidades

Block Table

Record

Banco de Dados do AutoCAD

Um desenho de AutoCAD é uma coleção de AcDb-objetos que são armazenados em um banco de dados. Cada objeto no banco de dados tem um handle que é uma identificação única dentro do contexto do desenho. Já as entidades são objetos com uma representação gráfica como, line, circle, etc.

Outros objetos de banco de dados importantes são os symbol tables e dictionaries, que são containers de armazenamento de objetos. No caso do symbol table tem-se um conjunto fixo de elementos no banco de dados, cada um dos quais contem instâncias de uma particular classe do

(14)

symbol table record. Não é permitido adicionar novos symbol table no banco de dados. Os dictionaries são objetos que mapeiam um symbol name para outro AcDb-objeto. Além disso

fornecem um container mais genérico para armazenamento de objetos, ele pode conter qualquer

AcDbObject ou subclasse, e também, pode-se criar novos elementos de banco de dados e

acrescentá-los em um novo dictionary.

Durante as sessões correntes do AutoCAD pode-se obter o banco de dados chamando a função global

acdbCurDwg( ). Múltiplos banco de dados podem ser carregados dentro de uma única sessão do

AutoCAD. Cada objeto na sessão tem um objeto ID, que é um único identificador para o objeto através de todos os banco de dados carregados. Em contraste, um objeto handle não é garantido ser único dentro de uma sessão do AutoCAD. Ele é único somente dentro de um escopo de um particular banco de dados.

Objeto ID

Com um objeto ID pode-se obter um ponteiro para o objeto do banco de dados atual, assim pode-se executar operações com ele. Para obter o objetoID :

 Criar um objeto e acrescentar ao banco de dados

 Usar o protocolo do banco de dados para obter o objeto ID dos objetos que são criados automaticamente se um banco de dados é criado

 Usar o protocolo de classes específicas para obter o objeto ID

 Usar um iterator para percorrer uma lista ou conjunto de objetos

 Selecionar um conjunto de objetos

Objetos Essenciais do Banco de Dados

Quando os objetos são criados, eles são armazenados em containers no banco de dados. Entidades são adicionados para o block table record, e esses são adicionados para os symbol tables. Todos os outros objetos são adicionados para o named object dictionary ou para objetos que são seus proprietários.

O banco de dados tem inicialmente o seguinte aspecto:

 Um conjunto de nove symbol tables que incluem o block table (MODEL_SPACE e PAPER_SPACE ) e o layer table ( layer 0 ).

 Um named object dictionary que já contém p grupo dictionary e MLINE style dictionary ( STANDARD ).

Criando Objetos

Exemplo: Criação de uma line e sua adição no model space block table record:

AcDbObjectId

createLine()

{

(15)

AcGePoint3d endPt(10.0, 7.0, 0.0);

AcDbLine *pLine = new AcDbLine(startPt, endPt); AcDbBlockTable *pBlockTable;

acdbCurDwg()->getBlockTable(pBlockTable, AcDb::kForRead); AcDbBlockTableRecord *pBlockTableRecord;

pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite); pBlockTable->close(); AcDbObjectId lineId; pBlockTableRecord->appendAcDbEntity(lineId, pLine); pBlockTableRecord->close(); pLine->close(); return lineId; }

Exemplo: Criação de um circle e sua adição no model space block table record:

AcDbObjectId

createCircle()

{

AcGePoint3d center(9.0, 3.0, 0.0); AcGeVector3d normal(0.0, 0.0, 1.0);

AcDbCircle *pCirc = new AcDbCircle(center, normal, 2.0); AcDbBlockTable *pBlockTable; acdbCurDwg()->getBlockTable(pBlockTable, AcDb::kForRead); AcDbBlockTableRecord *pBlockTableRecord; pBlockTable->getAt(ACDB_MODEL_SPACE,pBlockTableRecord, AcDb::kForWrite); pBlockTable->close(); AcDbObjectId circleId; pBlockTableRecord->appendAcDbEntity(circleId, pCirc);

(16)

pBlockTableRecord->close(); pCirc->close();

return circleId; }

Exemplo: Obtem o layer symbol table do banco de dados, cria um novo layer table record e o

nomeia de ASDK_MYLAYER. O layer table record é adicionado para o layer table: void

createNewLayer() {

AcDbLayerTable *pLayerTable;

acdbCurDwg()->getLayerTable(pLayerTable, AcDb::kForWrite);

AcDbLayerTableRecord *pLayerTableRecord = new AcDbLayerTableRecord; pLayerTableRecord->setName("ASDK_MYLAYER"); AcDbLinetypeTable *pLinetypeTbl; acdbCurDwg()->getLinetypeTable(pLinetypeTbl, AcDb::kForRead); AcDbObjectId ltypeObjId; pLinetypeTbl->getAt("CONTINUOUS", ltypeObjId); pLayerTableRecord->setLinetypeObjectId(ltypeObjId); pLayerTable->add(pLayerTableRecord); pLayerTable->close(); pLayerTableRecord->close(); }

Abrindo e Fechando Objetos

Todo objeto precisa ter o protocolo de abrir e ser fechado. Esse protocolo garante que o objeto esta fisicamente na memória quando ele necessita ser acionado. Antes de modificar um objeto ele precisa ser aberto:

AcdbOpenObject( pObject, objId, AcDb::kForWrite );

O último parâmetro especifica se o objeto será lido (read), escrito (write) ou notificado (notify). No caso de write ele pode ser modificado. Quando a modificação estiver acabada, deve-se fechar o objeto, mas nunca antes do objeto ser adicionado no banco de dados:

(17)

PObject->close ( )

Exemplo: O exemplo a seguir muda a cor da entidade:

Acad::ErrorStatus

changeColor(AcDbObjectId entId, Adesk::UInt16 newColor)

{

AcDbEntity *pEntity;

acdbOpenObject(pEntity, entId, AcDb::kForWrite); pEntity->setColorIndex(newColor);

pEntity->close(); return Acad::eOk; }

Adicionando um Grupo para o Group Dictionary

Exemplo: Cria um group (pgroup) e coloca no group dictionary

void

createGroup(AcDbObjectIdArray& objIds, char* pGroupName)

{

AcDbGroup *pGroup = new AcDbGroup(pGroupName); for (int i = 0; i < objIds.length(); i++)

{ pGroup->append(objIds[i]); } AcDbDictionary *pGroupDict; acdbCurDwg()->getGroupDictionary(pGroupDict, AcDb::kForWrite); AcDbObjectId pGroupId;

pGroupDict->setAt(pGroupName, pGroup, pGroupId); pGroupDict->close();

(18)

}

III.

Escrevendo uma aplicação em ARX

Essa sessão descreve como escrever e rodar uma aplicação em ARX. Ela lista as mensagens passadas pelo AutoCAD para aplicações em ARX e mostra como essas aplicações respondem as mensagens. Considera também o registro de novos comandos, como carregar e descarregar uma aplicação e algo mais.

Estrutura de uma Aplicação em ARX

O AutoCAD chama o ARX através do módulo acrxEntryPoint ( ), que substitui o main do C ou ADS. A função acrxEntryPoint ( ) serve não somente como a entrada de pontos para a comunicação com uma aplicação do ARX do AutoCAD, mas também como um caminho para aplicações do ARX passar mensagens e retornar status para o AutoCAD.

extern "C"

AcRx::AppRetCode acrxEntryPoint(AcRx::AppMsgCode msg, void* pkt); msg Representa a mensagem enviada

pkt Pacote de dados

AppRetCode Contem o status retornado do AutoCAD

Dentro da definição do acrxEntryPoint ( ) deve-se escrever um switch para decifrar as mensagens do AutoCAD. O código abaixo mostra o esqueleto:

AcRx::AppRetCode acrxEntryPoint(AcRx::AppMsgCode msg, void* pkt) { switch(msg) { case AcRx::kInitAppMsg: break; case AcRx::kUnloadAppMsg: break; ...

(19)

default: break; } return AcRx::kRetOK; }

Mensagens Enviadas do AutoCAD para as Aplicações ARX

kInitAppMsg . kUnloadAppMsg kOleUnloadAppMsg kLoadDwgMsg kUnloadDwgMsg kDependencyMsg kNoDependencyMsg kInvkSubrMsg kEndMsg kPreQuitMsg kQuitMsg kSaveMsg kCfgMsg kEndMsgkCfgMsgkQuitMsgkSaveMsg

O processo das mensagens é praticamente todo feito em uma só direção, do AutoCAD para o aplicativo em ARX.

Registrando Novos Comandos

Command Stack

Os comandos do AutoCAD são armazenados em grupos no command stack, que é definido pela classe AcEdCommandStack. O command stack é criado para a sessão do AutoCAD e é um comando nativo adicionado ao AutoCAD. A macro acedRegCommands ( ) da o acesso para o command stack.

(20)

Pode-se adicionar comandos com AcEdCommand::addCommand ( ) e remover grupos com

AcEdCommand::removeGroup( ) ou remover comandos com AcEddCommandStack::removeCmd.

Acad::ErrorStatus

AcEdCommandStack::addCommand (const char* cmdGroupName, const char* cmdGlobalName, const char* cmdLocalName, Adesk::Int32 commandFlags, AcRxFunctionPtr functionAddr);

cmdGroupName Representação ASCII do grupo para adicionar o comando

cmdGlobalName Representação ASCII do nome global do comando para adicionar cmdLocalName Representação ASCII do nome local do comando para adicionar command-Flags Flags associados com o comando

functionAddr Endereço da função para sua execução quando invocado pelo AutoCAD

virtual Acad::ErrorStatus

AcEdCommandStack::removeCmd

(const char* cmdGroupName, const char* cmdGlobalName) = 0; virtual Acad::ErrorStatus

AcEdCommandStack::removeGroup (const char* groupName);

Quando um comando é invocado, o command stack é procurado pelo group name e então pelo

command name dentro do group. Essa procura não é feita em uma ordem lógica, porém o usuário, se

quiser, pode ter controle sobre ela.

Lookup Order

Quando um comando é invocado, o comando Stack é procurado pelo nome do grupo e depois pelo nome do comando. Geralmente, o primeiro o primeiro grupo registrado será o primeiro a ser pesquisado, mas podemos saber qual orem irá seguir. Para especificarmos o primeiro grupo que desejamos que seja pesquisado, podemos usar o comando abaixo:

AcEdCommandStack::popGroupToTop()

(21)

Caso não haja necessidade de traduzir o nome do comando local, o nome global pode ser usado para ambas situações.

Comandos Transparentes

Um comando pode ser transparente (ACRX_CMD_TRANSPARENT) ou modal (ACRX_CMD_MODAL). Um comando transparente pode ser invocado quando o usuário utilizando o prompt com outra ação. Já o modal só pode se invocado quando não houver outro comando na linha de prompt.

Querrying Commands

A biblioteca AcEd oferece classes para iteração através do comando Stack e par procurar comandos específicos. Todavia esse questionamento é executado pelo AutoCAD e nós usamos essas funções.

Exemplo: Implementa funções que são chamadas quando a aplicação é carregada (load) e

descarregada (unload) void

initApp()

{

acedRegCmds->addCommand("ASDK_DICTIONARY_COMMANDS", "ASDK_CREATE", "CREATE", ACRX_CMD_MODAL, createDictionary); acedRegCmds->addCommand("ASDK_DICTIONARY_COMMANDS",

"ASDK_ITERATE", "ITERATE", ACRX_CMD_MODAL, iterateDictionary); AsdkMyClass::rxInit(); acrxBuildClassHierarchy(); } void unloadApp() { acedRegCmds->removeGroup("ASDK_DICTIONARY_COMMANDS"); deleteAcRxClass(AsdkMyClass::desc()); }

Carregando uma Aplicação ARX

(22)

Métodos para carregar um aplicativo ARX:

 Fornecer o aplicativo com aspectos que permitam ser carregados pelo AutoCAD

 Especificar o aplicativo no arquivo inicial acad.rx

 Utilizar AcRxDynamicLinker::loadModule( )

 Usar o quadro de diálogo APPLOAD definido no bonus loadapp.arx

 Usar a função arxload do AutoLISP

 Usar a função ads_arxload( ) do ARX ou ADS  Comando ARX no prompt do AutoCAD

Descarregando uma Aplicação ARX

Métodos para descarregar um aplicativo ARX:

 Utilizar AcRxDynamicLinker::unloadModule( )

 Usar o quadro de diálogo APPLOAD definido no bonus loadapp.arx

 Usar a função arxunload do AutoLISP

 Usar a função ads_arxunload( ) do ARX ou ADS

 Comando ARX no prompt do AutoCAD

Comando ARX

A partir do comando ARX na linha de comando, tem-se o seguinte na liha de prompt:

?/Load/Unload/Commands/Options: Entre uma opção ou pressione ENTER ? - Lista as aplicações em ARX carregedas

Load - Carrega os arquivos .arx que foram especificados Unload - Descarrega as aplicações em ARX especificadas

Commands - Mostra todos os nomes de comandos e grupos registrados Options - Apresenta o relatório de alguns ítens do programa

Controle de Memória

Os objetos criados devem ser devidamente liberados da memória. No caso do C++, deve-se usar

AcDbObject::new para criar um objeto e AcDbObject::delete para destruí-lo.

IV.

Operações do Banco de Dados

(23)

Essa sessão descreve o protocolo básico do banco de dados incluindo como criar um banco de dados, como ler em um arquivo de desenho, e como salvar o banco de dados. As funções wblock e insert são também descritas aqui.

Banco de Dados Inicial

Quando uma sessão do AutoCAD começa tem-se os seguintes elementos:

 Um conjunto de sete symbol tables

Block table (AcDbBlockTable)

Dimension style table (AcDbDimStyleTable) Layer table (AcDbLayerTable)

Linetype table (AcDbLinetypeTable)

Registered applications table (AcDbRegAppTable) Text style table (AcDbTextStyleTable)

User coordinate system table (AcDbUCSTable) Viewport table (AcDbViewportTable)

View table (AcDbViewTable)

 Um named object dictionary

 Um conjunto fixo de variáveis header

Criando e Populando um Banco de Dados

Usa-se new para criar um banco de dados e delete para destruí-lo. O construtor AcDbDatabase tem um argumento com default de Adesk::kTrue que cria o banco de dados populado com o objeto padrão. Se o argumento for Adesk::kFalse , então o banco de dados é criado vazio e pode ser populado.

Salvando um Banco de Dados

Para salvar o banco de dados: Acad::ErrorStatus

AcDbDatabase::saveAs(char* fileName);

(24)

A Operação wblock

A classe AcDbDatabase contém uma função wblock( ) sobrecarregada com três formas:

 Criando um novo banco de dados a partir de um já existente

Acad::ErrorStatus

AcDbDatabase::wblock(AcDbDatabase*& newDb);

 Criando um novo banco de dados com entidades: Copiando um Named Block

Acad::ErrorStatus

AcDbDatabase::wblock(AcDbDatabase*& newDb, AcDbObjectId recordId);

 Criando um novo banco de dados com entidades: Copiando um Array de Entidades

Acad::ErrorStatus

AcDbDatabase::wblock(AcDbDatabase*& newDb, const AcDbObjectIdArray& idArray, const AcGePoint3d* point);

Inserindo um Banco de Dados

As funções AcDbDatabase::insert( ) copiam um banco de dados para o banco de dados que invocou a função, porém se alguns objetos tiverem um ponteiro do tipo ownership no named object

dictionary, é necessário utilizar a função de notificação AcEditorReactor.

Setando os Valores do Banco de Dados Corrente

Color

Se a cor não é especificada por uma entidade, o banco de dados armazena no sistema de variáveis CECOLOR.

Acad::ErrorStatus

AcDbDatabase::setCecolor(const AcCmColor& color); AcCmColor AcDbDatabase::cecolor() const;

(25)

Acad::ErrorStatus

AcDbDatabase::setCeltype(AcDbObjectId); AcDbObjectId AcDbDatabase::celtype() const;

Linetype Scale

Acad::ErrorStatus

AcDbDatabase::setLtscale(double); double AcDbDatabase::ltScale() const; Acad::ErrorStatus

AcDbDatabase::setCeltscale(double); double AcDbDatabase::celtscale() const; Acad::ErrorStatus

AcDbDatabase::setPsltscale(Adesk::Boolean) Adesk::Boolean AcDbDatabase::psltscale() const;

Layer

Acad::ErrorStatus

AcDbDatabase::setClayer(AcDbObjectId); AcDbObjectId AcDbDatabase::clayer() const;

Referências Externas

Referências externas (xrefs) são criadas exclusivamente pelo AutoCAD que cria um banco de dados contendo os xrefs. Para que se possa monitorar esse banco de dados deve-se usar as funções da classe

AcEditorReactor:  beginAttach( )  otherAttach( )  abortAttach( )  endAttach( )  redirected( )  comandeered( )

(26)

void

createDwg()

{

// Cria um novo banco de dados

AcDbDatabase *pDb = new AcDbDatabase; // Obtem o model space block table record AcDbBlockTable *pBtbl; pDb->getBlockTable(pBtbl, AcDb::kForRead); AcDbBlockTableRecord *pBtblRcd; pBtbl->getAt(ACDB_MODEL_SPACE, pBtblRcd, AcDb::kForWrite); pBtbl->close();

// Cria dois circles e acrescenta no banco de dados

AcDbCircle *pCir1 = new AcDbCircle(AcGePoint3d(1,1,1), AcGeVector3d(0,0,1), 1.0),

*pCir2 = new AcDbCircle(AcGePoint3d(4,4,4), AcGeVector3d(0,0,1), 2.0); pBtblRcd->appendAcDbEntity(pCir1); pCir1->close(); pBtblRcd->appendAcDbEntity(pCir2); pCir2->close(); pBtblRcd->close(); pDb->saveAs("test1.dwg"); delete pDb; } void readDwg()

(27)

{

AcDbDatabase *pDb = new AcDbDatabase; pDb->readDwgFile("test1.dwg");

// abre o model space block table record AcDbBlockTable *pBlkTbl; pDb->getBlockTable(pBlkTbl, AcDb::kForRead); AcDbBlockTableRecord *pBlkTblRcd; pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd, AcDb::kForRead); pBlkTbl->close(); AcDbBlockTableRecordIterator *pBlkTblRcdItr; pBlkTblRcd->newIterator(pBlkTblRcdItr); AcDbEntity *pEnt;

for (pBlkTblRcdItr->start(); !pBlkTblRcdItr->done(); pBlkTblRcdItr->step()) { pBlkTblRcdItr->getEntity(pEnt, AcDb::kForRead); ads_printf("classname: %s\n", (pEnt->isA())->name()); pEnt->close(); } pBlkTblRcd->close(); delete pBlkTblRcdItr; delete pDb; }

V.

Objetos Banco de Dados

(28)

Essa sessão relata todos os objetos banco de dados do AutoCAD, entidades, symbol tables records e dictionaries. Também inclui abrir e fechar comandos, administrar objetos na memória, objetos ownership, e extensão de um objeto ou extension dictionary.

Abrindo e Fechando Objetos

Cada objeto pode ser referenciado de três formas:

 Pelo seu handle: enquanto o AutoCAD não é salvo o desenho é armazenado no DWG, assim os

objetos são identificados pelos seus handles;

 Pelo seu object ID: depois que o desenho é aberto as informações do desenho estão

armazenadas no AcDbDatabase, assim cada objeto tem no banco de dados um object ID. Esse object Id persiste durante a edição corrente, desde a criação até sua deleção;

 Por um ponteiro em C++: As funções de abertura pegam o object ID como um argumento e retornam um ponteiro para um AcDbObject, esse ponteiro é válido até o objeto ser fechado.

DWG

Handle

Abre o Objeto Abre o Objeto

AcDbDatabase

Object ID

C++

Pointer

SAVE WBLOCK Fecha o Objeto

A função para abrir um objeto é: Acad::ErrorStatus

AcDbDatabase::acdbOpenObject(AcDbObject*& obj, AcDbObjectId id,

(29)

AcDb::OpenMode mode,

Adesk::Boolean openErasedObject = Adesk::kFalse) A função para mapear um handle para um object ID é:

Acad::ErrorStatus

getAcDbObjectId(AcDbObjectId& retId, Adesk::Boolean createIfNotFound, const AcDbHandle& objHandle, Adesk::UInt32 xRefId=0);

A função para abrir um objeto e requerer seu handle é: AcDbObject* pObject;

AcDbHandle handle;

pObject->getAcDbHandle(handle);

Um ads_name é equivalente para um AcDbObjectId, pode-se mudar usando-se: AcdbGetAdsName (ads_name& objName, AcDbObjectId objId);

AcdbGetObjectId (AcDbObjectId& objId, ads_name objName);

Geralmente, obtém-se um objeto através de uma seleção, e então o retorno é um ads_name que precisa ser trocado para um AcDbObjectId e ser aberto:

AcDbEntity*

selectEntity(AcDbObjectId& eId, AcDb::OpenMode openMode) {

ads_name en; ads_point pt;

ads_entsel("\nSelect an entity: ", en, pt); // muda ads_name para um object Id acdbGetObjectId(eId, en);

AcDbEntity * pEnt;

acdbOpenObject(pEnt, eId, openMode); return pEnt;

(30)

}

Pode-se abrir um objeto de três modos:

 kForRead;

 kForWrite;

 kForNotify;

Pode acontecer vários erros se caso o objeto for aberto de uma forma errada ou se o objeto já estiver aberto.

Deletando Objetos

Quando se cria uma instância de um AcDbObject com o intento de adicionar no banco de dados, deve se usar AcDbObject::new. Quando um objeto é primeiro criado e não foi adicionado no banco de dados, pode-se deletá-lo. Do contrário, se o objeto já tiver sido adicionado no banco de dados, não se pode deletá-lo. O AutoCAD administra a deleção de todos os objetos residentes no banco de dados.

Ownership

Com exceção dos objetos raízes, symbol tables e named object dictionary, os demais objetos têm um dono:

 Block table records possui as entidades;

 Cada symbol table possui um particular tipo de symbol table record

 Um AcDbDictionary pode possuir um AcDbObject;

 Qualquer AcDbObject pode ter um extension dictionary; um objeto possui seu extension

dictionary;

Adicionando Dados Específicos no Objeto

Pode-se utilizar das seguintes formas para adicionar dados em uma aplicação:

 Dados extendidos: consiste numa lista linkada de resbufs usada pelo aplicativo. ;

 Xrecords;

 Extension Dictionary de qualquer objeto: pode conter um arbitrário conjunto de objetos AcDbObject;

 Objetos customizados que podem guardar dados.

Apagando Objetos

Qualquer objeto no banco de dados pode ser apagado com a seguinte função: Acad::ErrorStatus

(31)

AcDbObject::erase(Adesk::Boolean Erasing = Adesk::kTrue);

Quando um objeto do banco de dados é apagada, informações sobre ele são removidas do dictionary. Já quando uma entidade é apagada, ela é apagada no block table record.. Não é permitido abrir e apagar um objeto com AcDbOpenObject(), se isso for feito haverá uma mensagem de erro.Quando um objeto é apagado ele não é arquivado no arquivo DWG ou no DXF.

Objeto Filing

O Objeto Filing é usado nos seguintes casos:

 Escrevendo e lendo arquivos DWG e DXF;

 Na comunicação entre AutoCAD, AutoLISP, ADS e ARX;

 No UNDO, INSERT, XREF e COPY;

 Na paginação.

O AcDbObject tem duas funções membros para arquivar externamente: dwgout() e dxfout(), e duas funções membros para arquivar internamente: dwgin() e dxfin(). Essas funções são chamadas pelo AutoCAD.

VI.

Entidades

Descrição dos objetos com representação gráfica denominados Entidades. Listando as propriedades comuns das entidades.

Definição de Entidades

Uma entidade é um objeto que possui um banco de dados e também, uma representação gráfica como, lines, circles, text e outros. Um usuário pode ver uma entidade no desenho e manipulá-la

Ownership

Entidades no banco de dados normalmente pertencem a um AcDbBlockTableRecord. O block table quando é recém criado pelo banco de dados tem dois predefinidos records, MODEL_SPACE e

PAPER_SPACE. Adicionais records são adicionados sempre que o usuário cria novos block records.

(32)

A estrutura ownership para entidades do banco de dados é a seguinte: AcRxObject AcDbObject AcDbDictionary AcDbEntity AcDb3dSolid AcDbBlockBegin AcDbBlockEnd AcDbBlockReference † AcDbMInsertBlock † AcDbBody AcDbCurve AcDb2dPolyline † AcDb3dPolyline † AcDbArc AcDbCircle AcDbEllipse AcDbLeader AcDbLine AcDbRay AcDbSpline AcDbXline AcDbDimension AcDb2LineAngularDimension AcDb3PointAngularDimension AcDbAlignedDimension AcDbDiametricDimension

(33)

AcDbOrdinateDimension AcDbRadialDimension AcDbRotatedDimension AcDbFace AcDbFaceRecord AcDbFcf AcDbMline AcDbMText AcDbOleFrame AcDbPoint AcDbPolyFaceMesh † AcDbPolygonMesh † AcDbRegion AcDbSequenceEnd AcDbShape AcDbSolid AcDbText AcDbAttribute AcDbAttributeDefinition AcDbTrace AcDbVertex AcDb2dPolylineVertex AcDb3dPolylineVertex AcDbPolyFaceMeshVertex AcDbPolygonMeshVertex AcDbViewport AcDbProxyEntity

(34)

Propriedades Comuns das Entidades

Todas as entidades têm propriedades comuns que quando se adiciona para o block table record, automaticamente o AutoCAD (AcDbEntity::setDatabaseDefaults()) define os valores default, isso se a definição não estiver explícita em seu código:

Color

A cor das entidades pode ser um valor numérico de 0 até 256, sendo que as cores padrão são:

A seguinte função seta a cor da entidade e assim ignora o valor default: virtual Acad::ErrorStatus

AcDbEntity::setColorIndex(Adesk::UInt16 color); Adesk::UInt16

AcDbEntity::colorIndex() const;

Linetype

Quando uma entidade é instanciada, sua linetype é do tipo NULL. Quando a entidade é adicionada no banco de dados, se não tiver sido especificado pela entidade, a linetype é setada no valor default que é armazenado no sistema de variáveis CELTYPE.

A função seguinte permite estabelecer uma linetype para uma entidade: virtual Acad::ErrorStatus

Número da cor Nome da cor

1 Vermelho 2 Amarelo 3 Verde 4 Cinza 5 Blue 6 Magenta 7 Branco ou Preto 0 BYBLOCK 256 BYLAYER

(35)

AcDbEntity::setLinetype(const char* newVal); virtual Acad::ErrorStatus

AcDbEntity::setLinetype(AcDbObjectId newVal); A função retorna o nome da linetype corrente na entidade: char* AcDbEntity::linetype() const;

A função retorna o object ID para o symbol table record especificando a linetype: AcDbObjectId AcDbEntity::linetypeId() const;

Linetype

Scale

Quando uma entidade é instanciada, sua linetype scale é inicializada para um valor inválido. Quando a entidade é adicionada no banco de dados, se não tiver sido especificado pela entidade, a linetype scale é setada no valor default que é armazenado no sistema de variáveis CELTSCALE.

Linetype Scale Especificada pela Entidade

Acad::ErrorStatus

AcDbEntity::setLinetypeScale(double newVal); double

AcDbEntity::linetypeScale() const;

Regenerando um Desenho

Quando uma entidade é regenerada, sua linetype scale é um produto da entidade linetype scale e também do banco de dados global linetype scale.. Assim a linetype scale é calculada da seguinte forma:

effltscale = ent->linetypeScale() * ent->database()->ltscale();

Visibilidade

Se for especificado que uma entidade é invisível ela será independente do que foi estabelecido pelo banco de dados.

Acad::ErrorStatus

AcDbEntity::setVisibility(AcDb::Visibility newVal); AcDb::Visibility

(36)

Layer

Pode-se especificar um layer para toda entidade, se isso não for feito ela terá o layer default 0. Cada layer tem uma série de propriedades associadas frozen/thawed, on/off, locked/unlocked, color,

linetype e viewport. As funções seguintes permitem que o layer seja estabelecido para uma entidade:

Acad::ErrorStatus

AcDbEntity::setLayer(const char* newVal); Acad::ErrorStatus

AcDbEntity::setLayer(AcDbObjectId newVal);

Essa função retorna o nome do layer corrente da entidade: char* AcDbEntity::layer() const;

Essa função retorna o object ID do layer corrente: AcDbObjectId AcDbEntity::layerId() const;

Funções Comuns das Entidades

 intersectWith( ) : é usada em operações de interseção;

 transformBy( ) : é usada como uma matriz de transformação quando o objeto sofre certas

mudanças;

 getTransformedCopy( ) : cria uma cópia e aplica uma transformação no objeto;

 getOsnapPoints( ) : retorna o osnap points e seu tipo;

 getGripPoints( ) : retorna o grip points que é um conjunto do stretch points  getStretchPoints( ) : defaults do para o getGripPoints( )

 moveStretchPointsAt( ) : é usado pelo comando STRETCH para mover certos pontos e defaults

para transformBy( );

 moveGripPointsAt( ) : é usado pelos grips para mover pontos específicos pontos e defaults para

transformBy( );

 worldDraw( ) : cria uma representação gráfica independente da entidade;

 vuewportDraw( ) : : cria uma representação gráfica dependente da entidade;

 draw( ) : desenha as entidades gráficas;

 list( ) : é usada pelo comando LIST e produz um ads_printf( );

 getGeomExtents ( ) : retorna as esquinas de uma caixa fechada da entidade;

 explode( ) : decompõe uma entidade em um conjunto de entidades elementares;

 getSubentPathsAtGsMarker( ) : retorna o caminho da subentidade que corresponde ao dado GS marker;

 getGsMarkersAtSubentPath( ) : retorna o GS marker que corresponde ao caminho da

subentidade;

 subentPtr( ) : retorna um ponteiro para o caminho da subentidade;

 highlight ( ) : torna as subentidades com uma representação na seleção do tipo highlight.

Object Snap

Para adquirir os snap points para os modos específicos usa-se a função getOsnapPoints( ). Os modos existentes são:

(37)

 kOsModeEnd Endpoint  kOsModeMid Midpoint  kOsModeCen Center  kOsModeNode Node  kOsModeQuad Quadrant  kOsModeIns Insertion  kOsModePerp Perpendicular  kOsModeTan Tangent  kOsModeNear Nearest

A função é da seguinte forma: virtual Acad::ErrorStatus

AcDbEntity::getOsnapPoints( AcDb::OsnapMode osnapMode, int gsSelectionMark,

const AcGePoint3d& pickPoint,

const AcGePoint3d& lastPoint, const AcGeMatrix3d& viewXform, AcGePoint3dArray& snapPoints, AcDbIntArray& geomIds) const;

Funções de Transformação

A classe AcDbEntity fornece duas funções de transformação: virtual Acad::ErrorStatus

AcDbEntity::transformBy(const AcGeMatrix3d& xform);

Essa função é chamada no Grip Move, ROTATE, SCALE e MIRROR virtual Acad::ErrorStatus

AcDbEntity::getTransformedCopy(const AcGeMatrix3d& xform, AcDbEntity*& ent) const;

Essa função é chamada quando houver a necessidade de criar uma nova entidade, como quando uma entidade é explodida e sofre uma escala não uniforme.

Interseção por Pontos

A função intersectWith( ) retorna os pontos onde uma entidade intercepta outra no desenho. Os tipos de interseção podem ser:

(38)

 kOnBothOperands (entidade extendida)

 kExtendThis

 kExtendArg

 kExtendBoth

A função intersectWith( ) é uma função sobrecarregada com duas formas, sendo que a Segunda leva um argumento adicional que o plano de projeção para determinar a aparente interseção:

virtual Acad::ErrorStatus

AcDbEntity::intersectWith( const AcDbEntity* ent, AcDb::Intersect intType,

AcGePoint3dArray& points,

int thisGsMarker = 0, int otherGsMarker = 0) const; virtual Acad::ErrorStatus

AcDbEntity::intersectWith( const AcDbEntity* ent, AcDb::Intersect intType,

const AcGePlane& projPlane, AcGePoint3dArray& points,

int thisGsMarker = 0,

int otherGsMarker = 0) const;

GS Markers e Subentidades

Toda entidade para ser desenhada chama as primitivas gráficas, assim como, lines, circles e etc que são contidas no AcGi library. Qualquer classe derivada do AcDbEntity pode associar um GS( sistema gráfico) marker e cada subclasse da entidade controla onde inserir seu GS markers. Onde um usuário seleciona uma entidade, o GS marker é usado para identificar qual parte da entidade foi selecionada.

Explodindo Entidades

Algumas entidades podem ser explodidas em um conjunto de simples elementos, pois a função explode( ) cria um array de objetos derivados de AcDbEntity. Quando um entidade é explodida:

 A aparencia visual é constante;

 A entidade explodida é apagada do banco de dados;

 Uma ou mais entidades são criadas e adicionadas ao banco de dados.

Criando Instancias de Entidades no AutoCAD

(39)

Criando uma Simples Entidade: criação de uma line e seu acrescimo no model space block table record AcDbObjectId createLine() { AcGePoint3d startPt(4.0, 2.0, 0.0); AcGePoint3d endPt(10.0, 7.0, 0.0);

AcDbLine *pLine = new AcDbLine(startPt, endPt); AcDbBlockTable *pBlockTable; acdbCurDwg()->getBlockTable(pBlockTable, AcDb::kForRead); AcDbBlockTableRecord *pBlockTableRecord; pBlockTable->getAt(ACDB_MODEL_SPACE,pBlockTableRecord, AcDb::kForWrite); pBlockTable->close(); AcDbObjectId lineId; pBlockTableRecord->appendAcDbEntity(lineId, pLine); pBlockTableRecord->close(); pLine->close(); return lineId; }

Criando um Simples Block Table Record: criação de um novo block table record e seu acrescimo

no block table. void

makeABlock()

{

// Cria e nomeia um novo block table record.

AcDbBlockTableRecord *pBlockTableRec = new AcDbBlockTableRecord(); pBlockTableRec->setName("ASDK-NO-ATTR");

(40)

AcDbBlockTable *pBlockTable = NULL;

acdbCurDwg()->getBlockTable(pBlockTable, AcDb::kForWrite); // Adiciona o novo block table record para o block table.

AcDbObjectId blockTableRecordId;

pBlockTable->add(blockTableRecordId, pBlockTableRec); pBlockTable->close();

// Cria e adiciona uma line no block record. AcDbLine *pLine = new AcDbLine(); AcDbObjectId lineId; pLine->setStartPoint(AcGePoint3d(3, 3, 0)); pLine->setEndPoint(AcGePoint3d(6, 6, 0)); pLine->setColorIndex(3); pBlockTableRec->appendAcDbEntity(lineId, pLine); pLine->close(); pBlockTableRec->close(); }

Entidades Complexas

Criando uma Entidade Complexa

void

createPolyline() {

// Seta 4 verteces para a pline AcGePoint3dArray ptArr;

(41)

ptArr.setLogicalLength(4); for (int i = 0; i < 4; i++) {

ptArr[i].set((double)(i/2), (double)(i%2), 0.0); }

// Aloca dinamicamente um objeto AcDb2dPolyline, // dando 4 elementos cujo a locação é fornecida em // ptArr. A polyline é fechada e não é curva.

AcDb2dPolyline *pNewPline = new AcDb2dPolyline( AcDb::k2dSimplePoly, ptArr, 0.0, Adesk::kTrue); pNewPline->setColorIndex(3);

// Ponteiro para um BlockTable Object AcDbBlockTable *pBlockTable;

acdbCurDwg()->getBlockTable(pBlockTable, AcDb::kForRead); // Ponteiro para MODEL_SPACE BlockTableRecord

AcDbBlockTableRecord *pBlockTableRecord;

pBlockTable->getAt(ACDB_MODEL_SPACE,pBlockTableRecord, AcDb::kForWrite); pBlockTable->close();

// Adiciona a pline para o banco de dados e obtem seu object ID AcDbObjectId plineObjId; pBlockTableRecord->appendAcDbEntity(plineObjId, pNewPline); pBlockTableRecord->close(); // Layer "0" pNewPline->setLayer("0"); pNewPline->close(); }

(42)

Acesso ao Sistema de Coordenadas

Funções das entidades setam os valores de suas coordenadas usando World Coordinate System . Tem-se como exceção o caso da clasTem-se AcDb2dPolylineVextex, que usa o valor da Entity Coordinate System.

VII.

Objetos Container

Essa sessão descreve os objetos container usados no banco de dados do AutoCAD: symbol tables, dictionaries, groups e xrecords. Mostra também como utilizá-los , interagi-los e como criá-los.

Comparação entre Symbol Tables e Dictionaries

Symbol tables e dictionaries executam essencialmente a mesma função; eles contem entradas que

são objetos de banco de dados que são acessados utilizando-se uma string chave. Pode-se adicionar outras entradas a esses objetos e também usar iterators para percorrer passos a passo as entradas e conteúdos.

O AutoCAD contem um conjunto fixo de nove symbol tables, que não podem ser criados ou deletados. O que pode ser feito é acrescentar ou mudar as entradas em um symbol tables (records). Sendo que cada symbol table contem somente um tipo particular de objetos.

Os dictionaries fornecem um mecanismo similar para armazenamento e recuperação de objetos com nomes chaves. O AutoCAD cria o named object dictionary sempre que cria um novo desenho, e a partir desse pode se criar outro objetos e adicioná-los no mesmo. Contudo, o mais prático seria adicionar um único objeto no named object dictionary e a partir dele adicionar outros dictionaries. Tipicamente, o objeto possuído é uma classe container assim como um dictionary. O dictionary, por default, contém dois dictionaries: ACAD_GROUP e ACAD_MLINESTYLE.

A classe hierárquica para symbol tables, symbol tables records, dictionaries e iterators é a seguinte: AcRxObject AcDbObject AcDbDictionary AcDbDictionaryIterator (AcRxObject) (AcDbObject)

(43)

AcDbSymbolTable AcDbBlockTable AcDbDimStyleTable AcDbLayerTable AcDbLinetypeTable AcDbRegAppTable AcDbTextStyleTable AcDbUCSTable AcDbAbstractViewTable AcDbViewportTable AcDbViewTable AcDbSymbolTableRecord AcDbBlockTableRecord AcDbDimStyleTableRecord AcDbLayerTableRecord AcDbLinetypeTableRecord AcDbRegAppTableRecord AcDbTextStyleTableRecord AcDbUCSTableRecord AcDbAbstractViewTableRecord AcDbViewportTableRecord AcDbViewTableRecord AcDbSymbolTableIterator AcDbBlockTableIterator AcDbBlockTableRecordIterator AcDbDimStyleTableIterator AcDbLayerTableIterator

(44)

AcDbLinetypeTableIterator AcDbRegAppTableIterator AcDbTextStyleTableIterator AcDbUCSTableIterator AcDbAbstractViewTableIterator AcDbViewTableIterator AcDbViewportTableIterator

Symbol Tables

O banco de dados do AutoCAD contem as seguintes symbol tables:

 Block table (AcDbBlockTable; BLOCK)

 Layer table (AcDbLayerTable; LAYER)

 Text style table (AcDbTextStyleTable; STYLE)

 Linetype table (AcDbLinetypeTable; LTYPE)

 View table (AcDbViewTable; VIEW)

 UCS table (AcDbUCSTable; UCS)

 Viewport table (AcDbViewportTable; VPORT)

 Registered applications table (AcDbRegAppTable)

 Dimension styles table (AcDbDimStyleTable; DIMSTYLE)

Cada classe symbol table fornece uma função getAt( ) para procurar o record especificado pelo nome. Para sobrecarregar essa função tem-se:

Acad::ErrorStatus

AcDb##BASE_NAME##Table::getAt(const char* pEntryName, AcDb::OpenMode mode,

AcDb##BASE_NAME##TableRecord*& pRecord,

Adesk::Boolean openErasedRecord = Adesk::kFalse) const; Acad::ErrorStatus

AcDb##BASE_NAME##Table::getAt(const char* pEntryName, AcDbObjectId& recordId,

Adesk::Boolean getErasedRecord = Adesk::kFalse) const;

(45)

Outra funções pra o symbol tables são: Adesk::Boolean

AcDb##BASE_NAME##Table::has(const char* pName) const; Acad::ErrorStatus

AcDb##BASE_NAME##Table::add(AcDb##BASE_NAME##TableRecord* pRecord);

Acad::ErrorStatus

AcDb##BASE_NAME##Table::add(AcDbObjectId& record Id, AcDb##BASE_NAME##TableRecord*

pRecord);

Block Table

Entidades no banco de dados pertencem ao block table record. O block table contem dois records como default, MODEL_SPACE e PAPER_SPACE, que correspondem a dois espaços de edição.

Layer Table

O layer table contem um layer, layer 0, por default. O usuário pode adicionar outros através do comando LAYER.

Propriedades do Layer

A classe AcDbLayerTableRecord contem funções membro para especificar o número de propriedades que afetaram a entidade.

Frozen/Thawed void AcDbLayerTableRecord::setIsFrozen(Adesk::Boolean); Adesk::Boolean AcDbLayerTableRecord::isFrozen() const; On/Off void AcDbLayerTableRecord::setIsOff(Adesk::Boolean); Adesk::Boolean AcDbLayerTableRecord::isOff() const; Viewport void AcDbLayerTableRecord::setVPDFLT(Adesk::Boolean);

(46)

Adesk::Boolean AcDbLayerTableRecord::VPDFLT() const; Locked/Unlocked void AcDbLayerTableRecord::setIsLocked(Adesk::Boolean); Adesk::Boolean AcDbLayerTableRecord::isLocked() const; Color

void AcDbLayerTableRecord::setColor(const AcCmColor &color); AcCmColor AcDbLayerTableRecord::color() const; Linetype void AcDbLayerTableRecord::setLinetypeObjectId(AcDbObjectId); AcDbObjectId AcDbLayerTableRecord::linetypeObjectId() const;

Criando e Modificando um Layer Table Record

O exemplo mostra como criar um novo layer table record(AcDbLayerTableRecord) e setar certos atributos do layer.

void addLayer() { AcDbLayerTable *pLayerTbl; acdbCurDwg()->getLayerTable(pLayerTbl, AcDb::kForWrite); if (!pLayerTbl->has("testlayer")) { AcDbLayerTableRecord *pLayerTblRcd = new AcDbLayerTableRecord; pLayerTblRcd->setName("ASDK_TESTLAYER"); pLayerTblRcd->setIsFrozen(0); // layer para THAWED pLayerTblRcd->setIsOff(0); // layer para ON

(47)

pLayerTblRcd->setVPDFLT(0); // viewport default pLayerTblRcd->setIsLocked(0); // un-locked

AcCmColor color;

color.setColorIndex(1); // seta a cor para vermelho pLayerTblRcd->setColor(color);

// Para linetype é necessário fornecer o object id da // linetype record AcDbObjectId ltId; acdbCurDwg()->getLinetypeTable(pLinetypeTbl, AcDb::kForRead); if ((pLinetypeTbl->getAt("DASHED", ltId)) != Acad::eOk) {

ads_printf("\nUnable to find DASHED" " linetype. Using CONTINUOUS"); pLinetypeTbl->getAt("CONTINUOUS", ltId); } pLinetypeTbl->close(); pLayerTblRcd->setLinetypeObjectId(ltId); pLayerTbl->add(pLayerTblRcd); pLayerTblRcd->close(); pLayerTbl->close(); } else {

ads_printf("\nlayer already exists"); }

}

(48)

Cada symbol table tem um iterator correspondente que pode ser criado com a função AcDb##BASE_NAME::newIterator( ). AcDb##BASE_NAME##Table::newIterator() function. Acad::ErrorStatus AcDb##BASE_NAME##Table::newIterator( AcDb##BASE_NAME##TableIterator*& pIterator, Adesk::Boolean atBeginning = Adesk::kTrue, Adesk::Boolean skipErased = Adesk::kTrue) const;

A função newIterator( ) cria um objeto que pode ser usado para percorrer através do conteúdo da

table e estabelecer pIterator para apontar para o objeto iterator. É possível se criar um novo iterator, mas não se pode esquecer de deletá-lo antes de fechar o symbol table. A classe AcDbBlockTableRecord retorna um objeto da classe AcDbBlockTableRecordIterator , que permite

percorrer através das entidades contidas no block table record.

Interagindo sobre Tables

O exemplo cria um iterator que percorre pelo symbol table record na linetype table. void

iterateLinetypes()

{

AcDbLinetypeTable *pLinetypeTbl;

acdbCurDwg()->getLinetypeTable(pLinetypeTbl, AcDb::kForRead); // Cria um novo iterator.

AcDbLinetypeTableIterator *pLtIterator; pLinetypeTbl->newIterator(pLtIterator); // Percorre a table

(49)

char *pLtName;

for (; !pLtIterator->done(); pLtIterator->step()) {

pLtIterator->getRecord(pLtTableRcd, AcDb::kForRead); pLtTableRcd->getName(pLtName);

pLtTableRcd->close();

ads_printf("\nLinetype name is: %s", pLtName); free(pLtName); } delete pLtIterator; pLinetypeTbl->close(); }

Dictionaries

Para criar um novo dictionary, é necessário criar uma instancia do AcDbDictionary, adicionar no banco de dados e registrar com o objeto. Quando isso acontece o dictionary automaticamente anexa um reactor para a entrada. Com a função setAt( ) adiciona objetos para o dictionary e o banco de dados.

Acad::ErrorStatus

AcDbDictionary::setAt(const char* pSrchKey, AcDbObject* pNewValue,

AcDbObjectId& retObjId);

Groups e o Group Dictionary

Um Group é um objeto container que mantem uma coleção ordenada de entidades no banco de dados, porem ele não tem um ownership link para as entidades que contem. Quando uma entidade é apagada , os groups que a contem são automaticamente removidos. Se a mesma entidade for desapagada, os groups são novamente inseridos.

Algumas funções podem ser usadas para os Groups e não é necessário setar cada elemento, por exemplo: setColor(), setLayer(), setLinetype(), setVisibility(), and setHighlight(). Os Groups devem ser armazenados no GROUP dictionary, que pode ser obtido da seguinte forma:

AcDbDictionary* pGrpDict = acdbCurDwg()->getGroupDictionary( pGroupDict, AcDb::kForWrite);

(50)

Criando um Dictionary

O exemplo cria um dictionary(ASDK_DICT) e adiciona para o named object dictionary. Então ele cria dois novos objetos da classe customizada AsdkMyClass e adiciona no dictionary.

void

createDictionary() {

AcDbDictionary *pNamedobj;

acdbCurDwg()->getNamedObjectsDictionary(pNamedobj, AcDb::kForWrite); // Checa a existencia do dictionary

AcDbDictionary *pDict;

if (pNamedobj->getAt("ASDK_DICT", (AcDbObject*&) pDict, AcDb::kForWrite) == Acad::eKeyNotFound)

{

pDict = new AcDbDictionary; AcDbObjectId DictId;

pNamedobj->setAt("ASDK_DICT", pDict, DictId); }

pNamedobj->close(); if (pDict) {

// Cria novos objects para adicionar para o novo dictionary, AsdkMyClass *pObj1 = new AsdkMyClass(1);

AsdkMyClass *pObj2 = new AsdkMyClass(2); AcDbObjectId rId1, rId2;

pDict->setAt("OBJ1", pObj1, rId1); pDict->setAt("OBJ2", pObj2, rId2); pObj1->close();

pObj2->close(); pDict->close();

(51)

}

Interagindo sobre Entradas do Dictionary

A classe iterator para dictionaries é AcDbDictionaryIterator. O exemplo a seguir obtem um

dictionary (ASDK_DICT) do named object dictionary e usa um iterador para percorrer as entradas

do dictionary. void iterateDictionary() { AcDbDictionary *pNamedobj; acdbCurDwg()->getNamedObjectsDictionary(pNamedobj, AcDb::kForRead); // Dá o ponteiro para ASDK_DICT dictionary

AcDbDictionary *pDict;

pNamedobj->getAt("ASDK_DICT", (AcDbObject*&)pDict, AcDb::kForRead); pNamedobj->close();

// Dá o iterador para ASDK_DICT dictionary

AcDbDictionaryIterator* pDictIter= pDict->newIterator(); AsdkMyClass *pMyCl;

Adesk::Int16 val;

for (; !pDictIter->done(); pDictIter->next()) { // Dá o corrente record, o abre para ler

pDictIter->getObject((AcDbObject*&)pMyCl, AcDb::kForRead); pMyCl->getData(val);

pMyCl->close();

ads_printf("\nintval is: %d", val); }

delete pDictIter; pDict->close();

(52)

}

Xrecords

Xrecords permite a adição de dados específicos de forma arbitrária e limitada. Essa é uma forma

alternativa de guardar dados mais utilizada em ADS ou AutoLISP.

Definindo Novas Classes

VIII.

Derivando um Classe Customizada ARX

Nessa sessão tem-se como utilizar as macros em ARX derivando da classe customizada ARX.

Derivação da Classe Customizada

É possível derivar novas classes das classes já existentes na hierarquia ARX: AcRxObject AcRxService AcDbObject AcDbEntity AcDbCurve AcDbObjectReactor AcDbDatabaseReactor AcDbEntityReactor AcTransactionReactor AcEdJig AcEditorReactor

Classes que não devem derivar: AcDbAttribute

(53)

AcDbArc AcDbBlockReference AcDbCircle AcDbFace AcDbLine AcDbMInsertBlock AcDbPoint AcDbShape AcDbSolid AcDbText AcDbTrace

All AcDbXxxDimension classes AcDbViewport

AcDbGroup

All classes derived from AcDbSymbolTable All classes derived from AcDbSymbolTableRecord AcDbBlockBegin AcDbBlockEnd AcDbSequenceEnd AcDb2dPolyline AcDb2dPolylineVertex AcDb3dPolyline AcDb3dPolylineVertex AcDbPolygonMesh AcDbPolygonMeshVertex AcDbPolyFaceMesh AcDbPolyFaceMeshVertex

(54)

AcDbFaceRecord

Identificação de Classes Rotina

Toda classe na hierarquia ARX que é derivada de AcRxObject tem uma classe de

descrição do objeto, que é uma instancia de AcRxClass que guarda informações para o

tipo de identificação. Essas classes são criadas na inicialização, quando classes são

registradas com ARX e são adicionadas no dictionary, acrxClassDictionary.

Macro:Classes de Declaração

As macros são usadas numa seção pública das classes de declaração: class myClass : public AcRxObject

{ public: ACRX_DECLARE_MEMBERS(myClass); ... }; Quando expandida:

virtual AcRxClass* isA() const; static AcRxClass* gpDesc; static AcRxClass* desc();

static AsdkPoly* cast(const AcRxObject* inPtr) {

return ((inPtr == 0)

|| !inPtr->isKindOf(AsdkPoly::desc())) ? 0 : (AsdkPoly*)inPtr;

};

static void rxInit();

(55)

Para implementar uma classe customizada, tem-se tres macros:

 ACRX_NO_CONS_DEFINE_MEMBERS(CLASS_NAME, PARENT_CLASS)

Usa-se para classes abstratas e qualquer outra classe que não deve ser instanciada.

 ACRX_CONS_DEFINE_MEMBERS(CLASS_NAME, PARENT_CLASS, VERNO)

Usa-se para classes transientes que podem ser instanciadas, mas não escritas em arquivo.

 ACRX_DXF_DEFINE_MEMBERS(CLASS_NAME,PARENT_CLASS,

PROXY_FLAGS, DXF_NAME, APP)

Usa-se para classes que podem ser escritas, ou lidas de arquivos DWG e DXF. Cada uma dessas classes define:

 Classe de descrição do objeto;

 Classe inicialização (função);

 A função desc( ) para a classe;

 A função virtual isA( ) que a classe deverá sobrecarregar.

Classe de Inicialização ( Função de Inicialização)

A função da classe de inicialização para cada classe é rxInit( ). Uma aplicação que define uma classe customizada invoca essa função durante a inicialização da rotina.

Essa função é definida automaticamente por cada das tres macros

ACRX_XXX_DEFINE_MEMBERS( ) e executa as seguintes tarefas:

 Registra a classe customizada;

 Cria a classe que descreve o objeto e armazena no dicitonary;

IX.

Derivando de AcDbObject

Essa sessão descreve como derivar uma classe customizada de AcDbObject. Fornece detalhes sobre os arquivos, sobre os quatro tipos de objetos referênciados, sobre o undo e o redo.

Overview

Quando se utiliza subclasses de AcDbObject, há um número de funções virtuais que podem ser sobrecarregadas.

(56)

AcDbObject: Funções para Sobrecarregar Essencialmente

virtual Acad::ErrorStatus

dwgInFields(AcDbDwgFiler* filer); virtual Acad::ErrorStatus

dwgOutFields(AcDbDwgFiler* filer) const; virtual Acad::ErrorStatus

dxfInFields(AcDbDxfFiler* filer); virtual Acad::ErrorStatus

dxfOutFields(AcDbDxfFiler* filer) const;

<Destructor>

AcDbObject: Funções para Sobrecarregar Frequentemente

virtual Acad::ErrorStatus audit(AcDbAuditInfo*);

virtual Acad::ErrorStatus subClose(); virtual Acad::ErrorStatus

deepClone(AcDbObject* pOwnerObject, AcDbObject*& pClonedObject, AcDbIdMapping& idMap,

Adesk::Boolean isPrimary = Adesk::kTrue) const; virtual Acad::ErrorStatus

wblockClone(AcRxObject* pOwnerObject, AcDbObject*& pClonedObject, AcDbIdMapping& idMap,

Adesk::Boolean isPrimary = Adesk::kTrue) const;

AcDbObject: Funções para Sobrecarregar Eventualmente

Referências

Documentos relacionados

MANUAL DE INSTRUÇÕES MÁQUINAS DE LIMPEZA DE ALTA PRESSÃO J 6500 - J 6800 (BY PASS) J 6500 - J 6800 (STOP TOTAL) Exclusivo para uso doméstico.. Atenção: Não utilizar

Este trabalho buscou, através de pesquisa de campo, estudar o efeito de diferentes alternativas de adubações de cobertura, quanto ao tipo de adubo e época de

referencial serve de base para o desenvolvimento de um tópico, a presença de um tópico oferece tão somente as condições possibilitadoras e preservadoras da

Este trabalho tem como objetivo geral avaliar a quantidade de água pluvial que pode ser aproveitada após infiltrar em um pavimento permeável de concreto

Como já destacado anteriormente, o campus Viamão (campus da última fase de expansão da instituição), possui o mesmo número de grupos de pesquisa que alguns dos campi

Áreas com indícios de degradação ambiental solo exposto no Assentamento Fazenda Cajueiro A e no Assentamento Nossa Senhora do Carmo B, localizados, respectivamente, no Município de

A curva em azul é referente ao ajuste fornecido pelo modelo de von Bertalany, a curva em vermelho refere-se ao ajuste fornecido pelos valores calculados Lt, dados pela equação

Os estudos sobre diferenciais de salários são explicados por alguns fatores que revelam a existência da relação entre as características pessoais produtivas educação,