Цель данной статьи.
Целью данной статьи является рассмотрение некоторых приемов работы в связке Autocad + C#.
В основном буду опираться на статью «Начало работы с Autocad с помощью C#». В рамках данной статьи будут рассмотрены некоторые замечания по особенностям работы с Autocad с помощью SDK — ObjectARX.
Сразу оговорюсь, что НЕ являюсь квалифицированным программистом, и увлекаюсь программированием только как хобби. Так что в комментариях прошу указать на неточности и ошибки в изложении материала.
0. Несколько слов о .net API и ObjectARX в частности.
Вот что говорит нам .Net Developer Guide (в переводе bushman, см. литературу):
AutoCAD .NET API позволяет вам управлять приложением AutoCAD и файлами чертежей на программном уровне с использованием доступных сборок или библиотек. Эти объекты могут быть доступны для множества различных языков программирования и всевозможных сред разработки программного обеспечения.
Для работы с Autocad можно использовать библиотеки напрямую из Autocad (как это сделано в «Начало работы с Autocad с помощью C#»), либо использовать ObjectARX.
ObjectARX — это большой набор библиотек, предназначенный для разработки приложений для AutoCAD в среде программирования Microsoft Visual C++. Сам AutoCAD разработан с использованием ObjectARX.
«Чистый» ObjectARX предназначен для работы с Autocad с помощью C++, однако часть библиотек предстваляют собой ни что иное, как обертки для классов ObjectARX для работы через .net.
ObjectARX общедоступен и его можно скачать с сайта Autodesk.
Кроме того, по этому же адресу можно скачать обширную документацию по SDK.
Внимание! Необходимо использовать одинаковые версии ObjectARX и Autocad! Совместимость работы библиотеки одной версии с Autocad другой версии не гарантируется. Так что при изменении версии используемого Autocad необходимо перекомпилировать Вашу программу с новыми библиотеками! Кроме того, советую обратить внимание на совместимость различных версий ObjectARX и MS VS! Все описанные ниже примеры написаны для Autocad 2009, соответственно используется ObjectARX 2009, MS Visual Studio 2008.
1. Способы взаимодействия Autocad и C# посредством .Net API.
Существует два основных способа взаимодействия Autocad и C#:
- 1. Программа реализуется в виде отдельного исполняемого файла с работой с файлами Autocad через COM-интерфейсы библиотеки Autocad.Interpop.Common. Данный прием позволяет получить обычный исполняемый exe-файл, который будет работать с dwg-файлами через COM. Данный способ имеет свое право на существование, однако, весьма ограничен функционально из-за малого числа доступных способов «воздействия» на чертеж и не рекомендуется в большинстве случаев.
- 2. В виде расширения (plugin) autocad. Результатом работы будет dll-файл, который подгружается в Autocad командой «netload» и определяет новые команды (операции) и/или новое поведение стандартных операций.
В данной статье будет использовать второй способ.
2. Возможности ObjectARX
Набор библиотек ObjectARX представляет разработчику огромный набор инструментов как для работы чертежами, так и с окнами Autocad.
Основные возможности предоставляемые ObjectARX:
- создание нового файла чертежа;
- редактирование существующих чертежей, которое включает в себя: редактирование примитивов, блоков, словарей чертежа (см. «Начало работы с Autocad с помощью C#»),
- добавление новых команд;
- изменение интерфейса Autocad (добавление новых кнопок, панелей, закладок);
и т.д.
Подробнее о ObjectArx можно почитать в документации (в папке ObjectARXdocs), так же в составе документации по ObjectARX есть примеры (папка ObjectARXsamples).
3. Примеры
Ниже в данной статье будет рассмотрено несколько примеров работы с Autocad и по каждому примеру будут даны небольшие комментарии.
В программах используются 2 библиотеки: AcDbMgd.dll и AcMgd.dll из папки ObjectARXinc-win32. Их необходимо добавить к Reference проекта C#.
Для просмотра результата, необходимо в Autocad вызвать команду «netload» (без кавычек), загрузить получившуюся в результате компиляции dll-сборку и вызвать имя новой команды (addEntity и addBlock соответственно, регистр роли не играет).
3.1. Добавление новых примитивов в существующий чертеж
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
namespace clExample
{
public class clExample
{
[CommandMethod("addEntity")] // название команды, вызываемой в Autocad
public void addEntity()
{
// Сначала получаем БД текущего чертежа
Database dbCurrent = Application.DocumentManager.MdiActiveDocument.Database;
// Для работы, связанной с примитивами рекомендуется использовать транзакции:
using (Transaction trAdding = dbCurrent.TransactionManager.StartTransaction())
{
// создаем новый примитив и определяем его основные свойства
Circle cNewCircle = new Circle();
cNewCircle.Center = new Point3d(0, 0, 0);
cNewCircle.Radius = 100;
cNewCircle.ColorIndex = 5;
// получаем текущее пространство чертежа (может быть модель или лист)
BlockTableRecord btrCurrSpace = trAdding.GetObject
(dbCurrent.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
// добавляем в текущее пространство наш созданный примитив
ObjectId oidCircle = btrCurrSpace.AppendEntity(cNewCircle);
trAdding.AddNewlyCreatedDBObject(cNewCircle, true);
//завершаем транзакцию
trAdding.Commit();
}
}
}
}
Данный пример иллюстрирует основы добавления примитивов на чертеж, работы с их свойствами, работы с базой данных чертежа, добавления нового примитива в чертеж. После запуска команды получим в точке 0,0 симпатичную окружность синего цвета.
2. Создание блока и изменение его свойств
Пример немного посложнее: создадим новый блок и разместим его на чертеже. Для этого добавим новую функцию:
[CommandMethod("createBlock")] // название команды, вызываемой в Autocad
public void createBlock()
{
// сначала получаем БД текущего чертежа
Database dbCurrent = Application.DocumentManager.MdiActiveDocument.Database;
// и его редактор
Editor edCurrent = Application.DocumentManager.MdiActiveDocument.Editor;
// для работы, связанной с примитивами рекомендуется использовать транзакции:
using (Transaction trAdding = dbCurrent.TransactionManager.StartTransaction())
{
// получаем таблицу блоков данного чертежа
BlockTable btTable = (BlockTable)trAdding.GetObject(dbCurrent.BlockTableId, OpenMode.ForRead);
// формируем опции запроса пользователя на ввод имени блока
PromptStringOptions psoOpt = new PromptStringOptions("nВведите имя блока: ");
psoOpt.AllowSpaces = true;
string strBlockName = "";
// далее осуществляется проверка на корректность имени блока
do
{
// формируем запрос с заданными опциями
PromptResult prRes = edCurrent.GetString(psoOpt);
// имя пользователя не введено. Прерываем работу
if (prRes.Status != PromptStatus.OK)
return;
try
{
// проверка на корректность символов в имени блока
SymbolUtilityServices.ValidateSymbolName(
prRes.StringResult,
false
);
// и нет ли блока с таким именем
if (btTable.Has(prRes.StringResult))
edCurrent.WriteMessage("nA block with this name already exists.");
else
// ура, имя блока осилили :)
strBlockName = prRes.StringResult;
}
catch
{
edCurrent.WriteMessage("nInvalid block name.");
}
} while (strBlockName == "");
// создаем ОПРЕДЕЛЕНИЕ блока
// создаем примитивы, которые будет содержать блок
Line lNewLine = new Line();
lNewLine.StartPoint = new Point3d(0, 0, 0);
lNewLine.EndPoint = new Point3d(50, 50, 0);
lNewLine.ColorIndex = 3;
Circle cNewCircle = new Circle();
cNewCircle.Center = new Point3d(0, 0, 0);
cNewCircle.Radius = 100;
cNewCircle.ColorIndex = 5;
// создаем определение аттрибута
AttributeDefinition adAttr = new AttributeDefinition();
adAttr.Position = new Point3d(0, 0, 0);
adAttr.Tag = "ATTRDEF";
// создаем новое определение блока
BlockTableRecord btrRecord = new BlockTableRecord();
btrRecord.Name = strBlockName;
btTable.UpgradeOpen();
// добавляем его в таблицу блоков
ObjectId btrId = btTable.Add(btrRecord);
trAdding.AddNewlyCreatedDBObject(btrRecord, true);
// добавляем в определение блока примитивы
btrRecord.AppendEntity(lNewLine);
trAdding.AddNewlyCreatedDBObject(lNewLine, true);
btrRecord.AppendEntity(cNewCircle);
trAdding.AddNewlyCreatedDBObject(cNewCircle, true);
// и аттрибут
btrRecord.AppendEntity(adAttr);
trAdding.AddNewlyCreatedDBObject(adAttr, true);
// теперь создадим экземпляр блока на чертеже
// получаем пространство модели
BlockTableRecord btrModelSpace = (BlockTableRecord)trAdding.GetObject(
btTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite );
// создаем новый экземпляр блока на основе его определения
BlockReference brRefBlock = new BlockReference(Point3d.Origin, btrId);
// добавляем экземпляр блока в базу данных пространства модели
btrModelSpace.AppendEntity(brRefBlock);
trAdding.AddNewlyCreatedDBObject(brRefBlock, true);
// задаем значение аттрибуета
AttributeReference arAttr = new AttributeReference();
arAttr.SetAttributeFromBlock(adAttr, brRefBlock.BlockTransform);
arAttr.TextString = "Атрибут!";
brRefBlock.AttributeCollection.AppendAttribute(arAttr);
trAdding.AddNewlyCreatedDBObject(arAttr, true);
// закрываем транзакцию
trAdding.Commit();
}
}
Данный пример иллюстрирует процесс создания более сложных объектов — блоков. Процесс создания блоков следующий:
1) создаем определение блока (как элемент таблицы BlockTable) и добавляем его в таблицу блоков (не забываем проверить корректность имени блока);
2) создаем и добавляем в определение блока примитивы и определения атрибутов блока;
3) создаем экземпляр блока (BlockReference) и добавляем его в базу данных того пространства, которое нас интересует (в примере — пространство модели);
4) задаем значения атрибутов.
Все, блок готов.
Злоключение
На этом поспешу закругляться. Всем спасибо за прочтение статьи, и напоминаю: с радостью рассмотрю все замечания, указание ошибок и просто критические комментарии!
Так же прошу в комментариях указать, есть ли смысл писать далее об этой теме и интересует ли эта тема кого-нибудь.
Литература
Блог Kean Walsmley — сборник отличных примеров;
Блог spiderinnet1 — еще один блог с примерами;
Autocad Net developer Guide на русском от bushman — частичный перевод на русский язык Autocad Net developer Guide
Офорум по Autocad .Net — англоязычный форум по Autocad .net. Рассмотрено много примеров.
Форум CadUser — русскоязычный форум. Часто заглядывают и подсказывают настоящие гуру программирования на .net. Чрезвычайно полезный ресурс.
Официальный форум Autocad — еще один англоязычный форум (отсутствие подсветки и разметки синтаксиса просто выламывает глаза).
Autocad Net Developer Giude — основная литература при создании приложения для Autocad.
Автор: n00buK
Статья очень полезна, уже год как забросил ObjectARX в пользу .Net. Частично использовал идеи по вставке блоков. Не могу найти решение задачи – импорт программным путём файлов в формате STEP (*.stp) в AuitoCAD & Revit.