Russian version
English version
ОБ АЛЬЯНСЕ | НАШИ УСЛУГИ | КАТАЛОГ РЕШЕНИЙ | ИНФОРМАЦИОННЫЙ ЦЕНТР | СТАНЬТЕ СПОНСОРАМИ SILICON TAIGA | ISDEF | КНИГИ И CD | ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ | УПРАВЛЕНИЕ КАЧЕСТВОМ | РОССИЙСКИЕ ТЕХНОЛОГИИ | НАНОТЕХНОЛОГИИ | ЮРИДИЧЕСКАЯ ПОДДЕРЖКА | АНАЛИТИКА | КАРТА САЙТА | КОНТАКТЫ
 
Программное обеспечение
 
Для зарегистрированных пользователей
 
РАССЫЛКИ НОВОСТЕЙ
IT-Новости
Новости компаний
Российские технологии
Новости ВПК
Нанотехнологии
 
Поиск по статьям
 
RSS-лента
Подписаться
Графика и изображения

Объектная модель AutoCAD

Данное издание подготовлено в качестве ознакомительного материала объектной модели AutoCAD.

В вкратце, для непосвящённых, объектная модель AutoCAD - это структура объектов: приложения AutoCAD, его документов (открытых чертежей), объектов черчения (точки, линии и т.п.), словарей (смотри документацию по AutoLisp), их свойств и методов. Все эти объекты описаны в системе COM и предоставлены любым языкам программирования. Описание объектной модели осуществлено в файлах с расширением tlb (type library - библиотека типов), а доступ к объёктам и их свойствам описано в реестре.

В данном издании все примеры будут строиться для языка программирования Delphi (точнее для его версии Delphi 7).

Для самостоятельного ознакомления с объектной моделью AutoCAD желательно транслировать в Delphi библиотеку типов AutoCAD. Для AutoCAD 2004 - это файл acax16enu.tlb, для более ранних версий - acad.tlb. Для этого в меню project выберете пункт меню Import Type Library. Появится окно для выбора прописанных в системном реестре библиотек типов. Может так случиться, что нужной нам библиотеки мы не найдём. Тогда щёлкните на кнопку Add (добавить) и вручную добавьте один из указанных выше файлов.

В указанном примере я создал отдельную станицу (Palette Page) для объектов AutoCAD. В результате у вас должно появиться три новых компонента: AcadDocument, AcadDatabase, AcadLayerStateManager.

Основным из них является первый компонент AcadDocument. Теперь можете с ним поэкспериментировать. Рекомендую, так же, просмотреть файл AutoCAD_TLB.pas, который был создан при импорте библиотеки типов. В нём вы найдёте много информации по объектной модели AutoCAD, доступной в среде Delphi.

Сразу оговорюсь. Наиболее подробное руководство по объектной модели AutoCAD представлено в книге "AutoCAD 2004. Разработка приложений и адаптация. Наиболее полное руководство" Николая Полещука. В этой книге помимо полного обзора объектной модели AutoCAD представлены основные положения по программированию на Delphi AutoCAD (5-ая глава).

Помимо того, что можно использовать библиотеку типов, можно, имея уже достаточный опыт программирования для системы AutoCAD, осуществлять соединение с AutoCAD через переменную типа Variant, вызывая функцию GetActiveOleObject или CreateOleObject.

Дело в том, что при подключении к AutoCAD первым способом, создаётся обращение только к новому или запущенному документу (напрямую отследить переключение документов не возможно: к сожалению метод OnDocumentActivate не работает так как во встроенном Visual Basic).

В следующей главе мы рассмотрим оба способа связи с AutoCAD и метод обхода несоответствия типов в COM и Visual Basic for AutoCAD.

Часто возникает вопрос, какими средствами лучше пользоваться для программирования под AutoCAD. И однозначно ответить на этот вопрос для человека, не работающего в Си++ достаточно сложно. Конечно, лучшим средством для программирования пол AutoCAD является Object ARX - среда, разработанная для языка программирования Си++, которая позволяет помимо черчения и отслеживания данных в AutoCAD так же создавать новые типы примитивов (с новыми свойствами и методами).

Далее следует вопрос, а что, собственно, вы хотите запрограммировать? Если задача стоит всего лишь в передаче графических данных от вашей программы в AutoCAD и дальнейшее их редактирование, то лучше использовать язык программирования, на котором написана основная часть вашей программы, не прибегая к использованию технологии Object ARX (даже если вы используете Си++).

Кстати говоря, все недостатки объектной модели AutoCAD, предоставляемой вашему компилятору, легко (или не совсем) компенсируются встроенными в AutoCAD средами Visual Basic, Visual Lisp.На протяжении всего изложения кода я буду нередко прибегать к использованию этих языков программирования.

Далее немного оговорюсь о технической направленности излагаемого материала. Будучи инженером-проектировщиком в транспортном строительстве, я конечно же имел целью автоматизировать свою работу в AutoCAD, поэтому в основном далее будут предлагаться задачи именно по этому направлению. Но я уверен, что специалистам и в других областях будет интересно познакомиться с предлагаемым материалом.

Присоединяемся к AutoCAD из Delphi.

doc_3783_p2.zip [ZIP / 0 байт]Материалы к этой главе (432,268 байт).[/file]

В нашем первом примере будем использовать библиотеку типов AutoCAD_TLB, подгружая её вручную без использования компонентов TAcadDocument.

Для примера простого приложения для AutoCAD создадим в Delphi обычное приложение (File>New>Application). В разделе uses вручную допишем модуль AutoCAD_TLB, ComObj.

Далее напишем функцию, которая будет отвечать за связь с AutoCAD.

Function GetAcadApplication(Visible: Boolean): IAcadApplication;
var
v : OleVariant;
begin
Try
// пытаемся присоединиться к уже запущенной копии AutoCAD
v := GetActiveOleObject(\'AutoCAD.Application\');
Except
// если не получилось присоединиться, то запускаем новую копию AutoCAD
v:= CreateOleObject(\'AutoCAD.Application\');
end;
// приводим переменную типа OleVariant к типу IAcadApplication
Result := IDispatch(v) as IAcadApplication;
// далее проверяем, надо ли делать приложение AutoCAD видимым
if Visible then Result.Visible := True;
end;

Функция возвращает интерфейс приложения AutoCAD, объявленный в модуле AutoCAD_TLB.pas. Стоит отметить, что почти на каждом шагу нам придётся работать с переменными типа OleVariant и постоянно заниматься преобразованием типов.

Теперь можно в любом месте программы присоединиться к запущенной копии AutoCAD или запустить новую.
Далее приведём нехитрый код программы, которая запускает AutoCAD вместе с запуском приложения, в заголовке окна будет выводиться версия AutoCAD.

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, AutoCAD_TLB, ComObj;

type
TForm1 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
AcadApp: IAcadApplication;
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

Function GetAcadApplication(Visible: Boolean): IAcadApplication;
var
v : OleVariant;
begin
Try
// пытаемся присоединиться к уже запущенной копии AutoCAD
v := GetActiveOleObject(\'AutoCAD.Application\');
Except
// если не получилось присоединиться, то запускаем новую копию AutoCAD
v:= CreateOleObject(\'AutoCAD.Application\');
end;
// приводим переменную типа OleVariant к типу IAcadApplication
Result := IDispatch(v) as IAcadApplication;
// далее проверяем, надо ли делать приложение AutoCAD видимым
if Visible then Result.Visible := True;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
// делаем так, что бы наша форма отображалась всегда поверх окна AutoCAD
FormStyle:= fsStayOnTop;
Button1.Caption:= \'Текущий чертёж\';
// присоеденимся к приложению AutoCAD
AcadApp:= GetAcadApplication(true)
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
// при закрытии нашей программы закроем AutoCAD
AcadApp.Quit
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
// В заголовке нашей формы напишем наимонавание текущего чертежа
Caption:= AcadApp.ActiveDocument.Name
end;

end.

Всё работает замечательно. При нажатии кнопки в заголовке нашего приложения отображается наименование текущего чертежа. В Visual Basic for AutoCAD всё гораздо проще - у объекта AcadDocument существует метод Activate, который срабатывает при переключении документов (чертежей) в приложении. В СОМ-структуре AutoCAD почему-то одноимённый метод так не работает. В принципе, он может и не пригодится, когда, например, нам необходимо просто что-то нарисовать в одном чертеже и забыть про все остальные открытые файлы. Но, всё же, проблема актуальна и требует решения.

В таком случае может пригодиться следующая методика. На нашу форму в Delphi поместим компонент Timer. Зададим не очень короткий и не очень длинный интервал (например, 150) и в методе OnTimer запишем код проверки текущего чертежа, например, по названию.

При этом можно использовать компонент AcadDocument со всеми объявленными в нём методами. В предыдущем примере этих методов у нас не было. Рассмотрим код такой программы.

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, OleServer, AutoCAD_TLB, ExtCtrls, ComObj;

type
TForm1 = class(TForm)
// таймер устанавливаем активным
Timer1: TTimer;
// свойство AutoConnect для AcadDocument1 устанавливаем в false
AcadDocument1: TAcadDocument;
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure AcadDocument1ObjectAdded(ASender: TObject;
const Object_: IDispatch);
private
{ Private declarations }
// переменная содержит полное имя текущего документа перед переключение к
// другому
LastDoc: string;
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
v : OleVariant;
begin
Try
// пытаемся присоединиться к уже запущенной копии AutoCAD
v := GetActiveOleObject(\'AutoCAD.Application\');
AcadDocument1.ConnectTo((IDispatch(v) as IAcadApplication).ActiveDocument);
Except
// если не получилось присоединиться, то запускаем новую копию AutoCAD
AcadDocument1.Connect
end;
// сразу заполняем вспомогательную переменную для последующей проверки
LastDoc:= AcadDocument1.Path+\'\\'+AcadDocument1.Name;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
v : OleVariant;
begin
// очень тихо пытаемся проверить полное имя текущего документа, если
// документ переключён, то отсоединяемся и заново присоединяемся к
// текущему (уже другому) документу
try
if LastDoc <> AcadDocument1.Application.ActiveDocument.Name then
try
AcadDocument1.Disconnect;
v := GetActiveOleObject(\'AutoCAD.Application\');
AcadDocument1.ConnectTo((IDispatch(v) as IAcadApplication).ActiveDocument);
// при этом обновляем дополнительную переменную
LastDoc:= AcadDocument1.Path+\'\\'+AcadDocument1.Name;
except
end;
except
end;
Caption:= LastDoc;
end;

// обработчик на создание нового объекта в текущем чертеже пишет
// в командной строке соответствующую строчку и переводит коретку
// на новую строчку (равносильно нажатию ESK в AutoCAD)
procedure TForm1.AcadDocument1ObjectAdded(ASender: TObject;
const Object_: IDispatch);
begin
AcadDocument1.Utility.Prompt(\'Добавлен объект\'+#13);
end;

end.

Данный код приводит в соответствие класс TAcadDocument в СОМ модели AutoCAD к соответствующему классу в Visual Basic for AutoCAD.

По-видимому, требуется небольшое пояснение по поводу "очень тихой проверки имени документа". Такое количество блоков try except end объясняется тем, что при событии, когда пользователь переключит чертежи, по нашему сценарию происходит отсоединение переменной AcadDocument1 от AutoCAD. Дальше всё зависит от промежутка времени, через которое произойдёт очередная попытка проверить имя текущего чертежа. Бедный пользователь замучается закрывать окошки с ошибками (J).

На первый взгляд можно было бы и не заниматься играми с таймером, тем более что есть такое свойство как AcadDocument1.Application.ActiveDocument. Однако, ActiveDocument - это свойство, а не класс (то есть без своих или унаследованных методов), и, самое главное, ссылки на функции и процедуры этого свойства (ActiveDocument: IActiveDocument) не относятся к действительно активному чертежу. В итоге - COM модель "ругается" по каждому вашему действию после переключения документа.

В следующих главах мы рассмотрим некоторые приёмы черчения примитивов в AutoCAD.

Техника черчения в AutoCAD из Delphi.

doc_3783_p3.zip [ZIP / 0 байт]Материалы к этой главе (217,174 байт).[/file]

При черчении всех примитивов используются основные функции с приставкой add, объявлённые в специальных коллекциях: ModelSpace (контейнер объектов в пространстве модели), PaperSpace (контейнер объектов в пространстве текущего листа), Block (именованный набор объектов).

По способу создания объектов их можно разделить на простые и сложные. Простые объекты создаются напрямую одной функцией с заранее подготовленными координатами узловых точек. Сложные объекты, такие, как регионы (Region), твердотельные тела (solid) создаются в СОМ модели поэтапно. Сначала создаются простые примитивы, объединяемые потом в одно сложное.

Заранее извинюсь за применение в изложении материала слов на английском языке, но это необходимо из-за того, что чаще всего программисту и пользователю приходится обращаться к зарубежным справочным материалам.
При создании простых объектов, как уже говорилось, применяются заранее подготовленные координаты узловых точек (Vertex). В любом языке программирования для создания и передачи этих данных необходимо использовать специальный вариантный тип OleVariant.

Дело в том, что определённый в Delphi и некоторых других языках программирования тип Variant может не распознаваться в некоторых операционных средах или при передачи такого типа по протоколам электронных сетей. Тип OleVariant разработан специально для межплатформенной передачи данных.
Если помните, в начале первой главы я рассказывал о файлах с расширением tlb. Эти файлы тоже имеют структуру, предназначенную для межплатформенной передачи данных. Компанией Microsoft в своё время был разработан стандарт СОМ (Component Object Model - модель многокомпонентных объектов), который в последнее время стал основным средством взаимосвязи приложений и операционных сред. При наличии множества стандартов языков программирования вязь приложений между собой была бы достаточно сложной и проблематичной. Стандарт СОМ внедрён в операционные среды, поэтому на сегодня является стандартом взаимосвязи приложений в полной мере этого слова. Такие приложения, как MOffice, AutoCAD, да и сами операционные среды предоставляют программистам доступ к своим ресурсам по средствам так называемых интерфейсов (Interfaces). Такие программы так же называют COM-серверами. Чаще всего описания интерфейсов хранятся в файлах - библиотеках типов (с расширением tlb). В большинстве случаев описание библиотек типов создаётся на языке IDL (Interface Definition Language - язык определения интерфейсов).

Однако, не стоит пугаться, учить этот язык для работы с библиотеками типов не придётся. Все языки программирования, поддерживающие СОМ-модели, распознают этот язык автоматически и генерируют файлы с его помощью автоматически, обрабатывая код на вашем "родном" языке программирования.

Однако, чтобы поближе разобраться с разработкой СОМ-моделью, можно обратиться к многочисленным источникам, написанным специально для освещения этого достаточно объёмного вопроса. Я же вернусь к этому вопросу в следующих главах при разработке своих собственных серверов автоматизации для AutoCAD.

Сейчас же вернёмся непосредственно к созданию примитивов в AutoCAD. Я сразу приведу код небольшой программки, поясняя написанное по-месту.

Для составления всех последующих программ я буду пользоваться шаблоном предыдущей программы.

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, OleServer, AutoCAD_TLB, ExtCtrls, ComObj, StdCtrls;

type
TForm1 = class(TForm)
Timer1: TTimer;
AcadDoc: TAcadDocument;
GroupBox1: TGroupBox;
Label1: TLabel;
Edit1: TEdit;
Label2: TLabel;
Edit2: TEdit;
Edit3: TEdit;
Label3: TLabel;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure AcadDocObjectAdded(ASender: TObject;
const Object_: IDispatch);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
LastDoc: string;
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
v : OleVariant;
begin
//: то же, что и в предыдущем примере
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
v : OleVariant;
begin
//: то же, что и в предыдущем примере
end;

procedure TForm1.AcadDocObjectAdded(ASender: TObject;
const Object_: IDispatch);
begin
//: то же, что и в предыдущем примере
end;

procedure TForm1.Button1Click(Sender: TObject);
var
BeginPoint, EndPoint: OleVariant;
Line: IAcadLine;
Begin
// задаём вариантной переменной тип массива из трёх вещественных чисел
BeginPoint:= VarArrayCreate([0, 2], varDouble);
EndPoint:= VarArrayCreate([0, 2], varDouble);
Try
// начальную точку линии получаем, запросив точку у пользователя
// в качестве первого параметра используем пустой параметр, второй параметр
// функции - строка в командной стоке с запросом точки у пользователя
BeginPoint:= AcadDoc.Utility.GetPoint(EmptyParam, \'Укажите точку начала линии: \');
// конечная точка задаётся нехитрым вычислением координат черезприращения,
// указанные в в соответствующих строчках диалогового окна
EndPoint[0]:= BeginPoint[0]+StrToFloat(Edit1.Text); // координата X
EndPoint[1]:= BeginPoint[1]+StrToFloat(Edit2.Text); // координата Y
EndPoint[2]:= BeginPoint[2]+StrToFloat(Edit3.Text); // координата Z
// функция AddLine возвращает интерфейс IAcadLine постоенного объёкта,
// который мы присваиваем соответствующей переменной
Line:= AcadDoc.ModelSpace.AddLine(BeginPoint, EndPoint);
// теперь с этой линией можно вытворять всё, что разрешает AutoCAD, например
// поменять цвет
Line.color:= acRed;
// поменять толщину линии
Line.Lineweight:= acLnWt040
except
end;
end;

end.

Разберёмся подробнее, что происходит при нажатии кнопки "Начертить от точки". Для задания линии необходимо иметь координаты двух точек.

Важное правило: при задании координат узловых точек любых примитивов обязательно указываются все три координаты, даже если чертится двухмерный объект. Это правило диктует СОМ-модель AutoCAD.
Перед, собственно, присвоением значений координат узловым точкам необходимо определить тип вариантных переменных, указывающих на эти точки с помощью функции VarArrayCreate([0, 2], varDouble). Здесь 0, 2 - индексы крайних элементов создаваемого массива из трёх вещественных, соответственно X, Y, Z. В дальнейшем обращение к этим координатам происходит так же, как и в простом массиве.

Для задания первой точки в примере я воспользовался функцией опроса пользователя GetPoint, возвращающей массив координат указанной пользователем точки в интерактивном режиме.
Вообще, все функции опроса пользователя в интерактивном режиме объявлены в разделе Utility объекта AcadDocument.

Координаты конечной точки отрезка я вычислил через приращения, задаваемые пользователем в соответствующих строчках диалогового окна. Конечно, приведённый выше код достаточно сырой. На практике необходимо осуществить достаточную проверку на возможные ошибки ввода чисел. Так же каждое действие, связанное с переменной документа AutoCAD, необходимо заключать в блок try except end на случай, если пользователь во время ваших действий или запросов решит заняться в AutoCAD чем-нибудь другим или просто отменит вашу команду. При этом нужно осторожно производить все последующие вычисления, связанные с полученными данными из AutoCAD.

Большинство функций добавления объектов возвращают интерфейсы добавляемых объектов, поэтому дальнейшее редактирование таких объектов не предоставляет трудностей. Необходимо только помнить, что не все свойства, объявленные в интерфейсе примитива AutoCAD могут быть использованы в версиях AutoCAD, отличных от той, в которой вы работаете. Так, например, в AutoCAD 2004 добавлено свойство TrueColor, позволяющее применять цвета к объектам в формате RGB (Red Green Blue - красный зелёный синий). Если ваша программа использует это свойство, то необходимо понимать, что в более ранних версиях AutoCAD ваша программа работать не сможет.

Примеры построения простых примитивов, таких, как точка, окружность, эллипс можно посмотреть в справочной литературе по Visual Basic for AutoCAD. Все эти примеры легко переносятся на любой язык программирования. Следующий пример покажет, как можно выполнять такие построения. Обратите внимание на немаловажные детали, такие, как развёртывание окна AutoCAD, если оно свёрнуто, когда вы делаете запрос пользователю (всё-таки терпение пользователя нужно уважать J).

При написании кода построения примитивов в AutoCAD часто приходится задавать координаты узловых точек через переменную типа OleVariant. Для упрощения для этого я внёс небольшую функцию, делающую код программы менее громоздким и более читабельным.

Function GetPoint(X, Y, Z: double): OleVariant;
begin
Result:= VarArrayCreate([0, 2], varDouble);
Result[0]:= x;
Result[1]:= y;
Result[2]:= z;
end;

Построение примитивов в AutoCAD

doc_3783_p4.zip [ZIP / 0 байт]Материалы к этой главе (284,864 байт).[/file]

В этой главе будет разобран пример, в котором мы разберём построение всех основных примитивов AutoCAD. При этом, постараемся разобрать новые свойства примитивов, введённых в AutoCAD 2004.


  Рекомендовать страницу   Обсудить материал Написать редактору  
  Распечатать страницу
 
  Дата публикации: 19.04.2006  

ОБ АЛЬЯНСЕ | НАШИ УСЛУГИ | КАТАЛОГ РЕШЕНИЙ | ИНФОРМАЦИОННЫЙ ЦЕНТР | СТАНЬТЕ СПОНСОРАМИ SILICON TAIGA | ISDEF | КНИГИ И CD | ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ | УПРАВЛЕНИЕ КАЧЕСТВОМ | РОССИЙСКИЕ ТЕХНОЛОГИИ | НАНОТЕХНОЛОГИИ | ЮРИДИЧЕСКАЯ ПОДДЕРЖКА | АНАЛИТИКА | КАРТА САЙТА | КОНТАКТЫ

Дизайн и поддержка: Silicon Taiga   Обратиться по техническим вопросам  
Rambler's Top100 Rambler's Top100