» » Создание плагинов для AutoCAD с помощью .NET API (часть 3 – работа со слоями)

 

Создание плагинов для AutoCAD с помощью .NET API (часть 3 – работа со слоями)

Автор: admin от 29-01-2015, 07:47, посмотрело: 1544

Это очередная статья из цикла, посвященного разработке плагинов для AutoCAD. Речь в ней будет идти о базовых операциях со слоями в документе.

public static string disclaimer = "Автор не является профессиональным разработчиком и не обладает глубокими знаниями AutoCAD. Этот пост – просто небольшой рассказ о создании плагина.";

1. Общая информация


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

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

В рамках этой статьи нам потребуются некоторые базовые сведения, которые в основном можно почерпнуть отсюда (зеркало)

1.1. Слой номер ноль

Любой документ AutoCAD всегда содержит в себе как минимум один слой — нулевой (с именем «0»), который невозможно удалить. Этот слой часто оказывается очень полезным — например, при удалении других слоев.

1.2. Текущий слой

Один из слоев документа обязательно должен являться текущим (current). На него помещаются все добавляемые на чертеж объекты (по крайней мере примитивные — с блоками дела обстоят несколько сложнее).

1.3. Свойства слоев

Любой (в том числе нулевой) слой в AutoCAD имеет три свойства:

  • включен ("[b]on[/b]");

  • заморожен ("[b]freeze[/b]");

  • заблокирован ("[b]lock[/b]").


Все эти свойства бинарные (каждое из них можно считать флагом «да/нет»).

Флаг "[b]включен[/b]" отвечает за видимость слоя. Если этот флаг сброшен, то все элементы, расположенные на слое, перестают отображаться на чертеже.

Флаг "[b]заморожен[/b]" также отвечает за видимость слоя. По своему действию он аналогичен флагу «включен». Как указано в документации, это свойство позволяет повысить производительность на очень больших чертежах.
 NB:

Флаг "[b]заблокирован[/b]" отвечает за возможность редактирования слоя. Если этот флаг установлен, то все элементы, расположенные на слое, становятся недоступными для любых изменений (перемещение, удаление и т. п.). Кроме того, на заблокированный слой нельзя добавлять новые элементы.

Свойствами слоев можно управлять из AutoCAD. На расположенном ниже рисунке ядовито-зеленым выделена панель «Слои» (Layers), а фиолетовым выделен выпадающий список слоев, в левой части которого находятся переключатели свойств (лампочка, солнышко, открытый замок — «on», «freeze» и «lock» соответственно).

Создание плагинов для AutoCAD с помощью .NET API (часть 3 – работа со слоями)

 NB:

1.4. Управление слоями

Самые простые действия со слоями были рассмотрены в предыдущем пункте. Для более сложных операций (например, создание или удаление слоя) нужно воспользоваться панелью «Свойства слоев» (Layer Properties), которая вызывается командой [b]LAYER[/b] или щелчком по соответствующей иконке на панели «Слои» (обозначена оранжевым на рисунке в предыдущем подразделе). Вот как выглядит эта панель:

Создание плагинов для AutoCAD с помощью .NET API (часть 3 – работа со слоями)

Особый интерес представляет выделенная рамкой секция кнопок. Первая кнопка в ней создает новый слой, третья — удаляет существующий, если это возможно.

Не может быть удален:

  • нулевой слой;

  • текущий слой;

  • слой, содержащий хотя бы один объект;

  • слой, на который имеется ссылка в определении блока.


Перед удалением слоя необходимо обеспечить выполнение этих условий.

 NB:

На этом с теорией все, можно приступать к практике.

2. Написание плагина


2.1. Создание нового проекта плагина

Этому была посвящена первая статья цикла. В качестве требуемой версии .NET Framework в приведенных ниже примерах указана [b].NET Framework 3.5[/b].


2.2. Добавление ссылок на необходимые библиотеки

В этом примере нам потребуются две библиотеки AutoCAD .NET API: [b]AcMgd.dll[/b] и [b]AcDbMgd.dll[/b] (как всегда, не забываем отключать CopyLocal).

2.3. Добавление нового слоя

Все присутствующие в документе слои хранятся в списке слоев. Для добавления на чертеж нового слоя достаточно добавить новый элемент в этот список.

Однако несмотря на простоту операции, кода получается довольно много.


После загрузки плагина и выполнения команды «TestCommand» на чертеже должен появиться новый слой:

Создание плагинов для AutoCAD с помощью .NET API (часть 3 – работа со слоями)


В приведенном выше коде использовались две важные конструкции, которые часто встречаются при работе с объектами чертежа:

Теперь, когда мы разобрались с блокировкой документа и транзакциями, можно перейти к разбору остальной части кода.

Во-первых, мы подключаем необходимые пространства имен:

Autodesk.AutoCAD.Runtime — чтобы использовать тип IExtensionApplication и конструкцию CommandMethod;
Autodesk.AutoCAD.DatabaseServices — чтобы использовать типы Document и DocumentLock;
Autodesk.AutoCAD.Runtime — чтобы использовать типы Database, Transaction, LayerTable, OpenMode и LayerTableRecord.

Во-вторых, мы блокируем документ и начинаем транзакцию:

// получаем текущий документ и его БД
Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;
 
// блокируем документ
using (DocumentLock docloc = acDoc.LockDocument())
{
    // начинаем транзакцию
    using (Transaction tr = acCurDb.TransactionManager.StartTransaction())
   {

В-третьих, мы получаем ссылку на таблицу слоев документа:

LayerTable acLyrTbl = tr.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite) as LayerTable;

Метод GetObject() принимает на вход два параметра: Id объекта, который необходимо открыть, и уровень доступа. Узнать Id таблицы слоев документа можно с помощью свойства LayerTableId базы данных этого документа. Поскольку нам необходимо изменить таблицу слоев (добавить в нее новый слой), мы используем уровень доступа «запись» (OpenMode.ForWrite). Наконец, метод GetObject() возвращает значение типа «объект» (object), которое необходимо явно привести к нужному нам типу (LayerTable).

В-четвертых, мы создаем новый слой:

LayerTableRecord acLyrTblRec = new LayerTableRecord();
acLyrTblRec.Name = "HabrLayer";

Слой (а точнее, соответствующая ему запись в таблице слоев документа) имеет тип LayerTableRecord. Его конструктор не принимает никаких значений, поэтому всю инициализацию приходится проводить уже после создания.

В этом примере мы изменили только имя нового слоя, однако при необходимости можно задать и другие параметры, например видимость (свойство IsOff) или доступность для редактирования (свойство IsLocked).

В-пятых, мы заносим новый слой в таблицу слоев документа:

acLyrTbl.Add(acLyrTblRec);

Таблица слоев — это класс, для которого реализован интерфейс IEnumerable. Для добавления нового элемента используется метод Add().

В-шестых, мы добавляем новый слой в БД документа:

tr.AddNewlyCreatedDBObject(acLyrTblRec, true);

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

Важная деталь: функция AddNewlyCreatedDBObject должна вызываться не до, а после добавления слоя в таблицу слоев документа. Если попытаться поменять эти операции местами, то слой не будет добавлен. Стройного логического объяснения этому у меня нет; буду рад, если знающие люди поделятся разгадкой в комментариях.

В-седьмых, мы фиксируем транзакцию:

tr.Commit();

Если какие-либо элементы, открытые во время транзакции с помощью метода GetObject(), были изменены, то для сохранения этих изменений в БД документа необходимо зафиксировать транзакцию, вызвав метод Commit(). В противном случае никакие изменения сохранены не будут, и документ останется в состоянии, которое существовало на момент начала транзакции.

Наконец, мы заканчиваем транзакцию и снимаем блокировку документа:

    }
}

Вот он, важный плюс использования конструкции using! Без нее очень легко забыть вызвать метод Dispose(), тем более что сделать это нужно дважды — для фиксации транзакции и для разблокировки документа. А при использовании конструкции using метод Dispose() вызывается автоматически.

2.4. Установка текущего слоя

Получить текущий слой документа и установить новый можно с помощью свойства Clayer базы данных документа.


2.5. Изменение свойств и переименование слоя

Для изменения свойств слоя нужно открыть соответствующую запись в таблице слоев.


Перед операцией со слоем нелишним будет убедиться в его существовании с помощью метода Has() таблицы слоев документа.

Если мы загрузим плагин, выполним команду «TestCommand», а затем — команду «NewCommand», то увидим, что созданный нами слой стал скрытым, заблокированным и сменил имя. Теперь никто его не найдет.

Создание плагинов для AutoCAD с помощью .NET API (часть 3 – работа со слоями)


2.6. Удаление слоя

Удаление слоя происходит во многом аналогично изменению. Для соответствующей записи в таблице слоев вызывается метод Erase() следующим образом:

acLyrTblRec.Erase(true);

Однако здесь важно помнить об ограничениях, которые были рассмотрены в первом разделе. Не получится удалить:

  • нулевой слой;

  • текущий слой;

  • слой, содержащий хотя бы один объект;

  • слой, на который имеется ссылка в определении блока.


Если необходимо удалить слой, который в данный момент является текущим, то перед удалением необходимо сделать текущим какой-нибудь другой слой — например, нулевой.

Если необходимо удалить слой, на котором присутствуют какие-либо объекты, то перед удалением слоя необходимо удалить все эти объекты или же перенести их на другой слой.

Более подробно про удаление слоев можно почитать в документации (раздел "Create and Edit AutoCAD Entities > Use Layers, Colors, and Linetypes > Work with Layers > Erase Layers").

А в блоге Kean Walmsley есть шаблон для поиска всех размещенных на слое объектов. На базе этого примера можно написать функцию, удаляющую со слоя все объекты.

В любом случае, перед удалением слоя не лишним будет убедиться в корректности операции, а само удаление обрамить конструкцией try ... catch.


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

В рассмотренном примере метод Purge() вызывается для коллекции, в которой находится только один объект — удаляемый слой. Если на этот слой никто не ссылается, то после вызова метода Purge() он останется в коллекции, и тогда можно приступать к удалению. Если же вызов метода Purge() вернет пустую коллекцию, то на удаляемый слой имеются ссылки — вероятно, это размещенные на нем объекты.

Если мы загрузим плагин и выполним команду «TestCommand», а затем — команду «NewCommand», то увидим, что созданный нами слой удалится с чертежа.

Создание плагинов для AutoCAD с помощью .NET API (часть 3 – работа со слоями)


2.7. Запрет затемнения заблокированных слоев

В завершение хотелось бы рассказать еще об одном параметре, связанном со слоями.

По умолчанию заблокированные слои в AutoCAD отображаются затемненными. Максимально возможное затемнение составляет 90% (как у прямоугольника на рисунке ниже).

Создание плагинов для AutoCAD с помощью .NET API (часть 3 – работа со слоями)


Для изменения степени затемнения служит переменная [b]LAYLOCKFADECTL[/b]. Ее значение устанавливается соответствующим ползунком на панели управления слоями (обведен на рисунке зеленым цветом).

Для изменения значения переменной [b]LAYLOCKFADECTL[/b] внутри плагина можно воспользоваться функцией SetSystemVariable:

Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("LAYLOCKFADECTL", 0);

В результате выполнения этого кода затемнение заблокированных слоев будет отключено.

Перед изменением переменной [b]LAYLOCKFADECTL[/b] стоит сохранить ее текущее значение, чтобы вернуть переменную в исходное состояние после того, как плагин закончит работу.


К сожалению, метод Terminate() не всегда отрабатывает корректно, и исходное значение может не восстановиться. Но мы хотя бы попытались.)

На этом пока все. В следующий раз напишу о создании простых объектов и блоков.

Источник: Хабрахабр

Категория: Программирование

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Добавление комментария

Имя:*
E-Mail:
Комментарий:
Полужирный Наклонный текст Подчеркнутый текст Зачеркнутый текст | Выравнивание по левому краю По центру Выравнивание по правому краю | Вставка смайликов Выбор цвета | Скрытый текст Вставка цитаты Преобразовать выбранный текст из транслитерации в кириллицу Вставка спойлера
Введите два слова, показанных на изображении: *