----
===== Разработка правила оформления плана =====
==== Введение ====
Программный комплекс [[http://topomatic.ru|Топоматик Робур]] предоставляет пользователю возможность генерировать плоские чертежи топографических планов в популярных обменных форматах. Генерация примитивов на чертеже плана происходит по принципу **[[https://ru.wikipedia.org/wiki/WYSIWYG|What You See Is What You Get]]** («что видишь, то и получишь»). Другими словами, экспортированный чертёж будет максимально похож на визуальное представление плана в окне Робура.
Часто исполнителю необходимо дорабатывать чертёж в соответствии с требованиями к оформлению плана предъявленными заказчиком. Например, требуется заменить типы линий, разбить вставки блоков, изменить цвет определённых примитивов и т.д. Для того, чтобы чертёж экспортировался в соответствии с уникальным требованиями, в программном комплексе Топоматик Робур предусмотрена возможность использования **правил оформления плана**. **Правила оформления плана** применяются при **создании чертежа**.
**Правило оформления плана** - это текстовый файл с расширением **".py"**, который содержит инструкции на диалекте **[[https://ironpython.net/|IronPython]]** языка программирования **[[https://www.python.org/|Python]]**.
Особенностью диалекта **IronPython** является возможность взаимодействия с **библиотеками классов** платформы **.Net** используемыми в программном комплексе **Топоматик Робур**. Более подробную документацию **IronPython** можно изучить пройдя по **[[https://ironpython.net/documentation/|ссылке]]**. В текущей статье мы рассмотрим только те инструкции **IronPython**, которые необходимые для написания **правила оформления плана**.
==== Создание и редактирование правила оформления плана ====
Для создания и редактирования **правила оформления плана** можно воспользоваться любым удобным для вас текстовым редактором, но лучше всего использовать редакторы способные подсвечивать синтаксис кода на языке **Python**, например **[[https://code.visualstudio.com/|VS Code]]** или **[[https://www.sublimetext.com/|Sublime]]**.
==== Применение правила оформления плана ====
Вставьте рамку листа на план с помощью пункта меню "Рисовать" -> "Планшет" -> "Добавить лист".
{{ :developers:tutorial:plan_export_rules:tut_plan_decoration_rule_1.png?nolink |}} {{ :developers:tutorial:plan_export_rules:tut_plan_decoration_rule_2.png?nolink |}}
Выберите пункт меню "Проект" -> "Создать чертёж" -> "План..."
{{ :developers:tutorial:plan_export_rules:tut_plan_decoration_rule_3.png?nolink |}}
Программа предложит вам выбрать на плане лист для формирования чертежа. Выберите лист и подтвердите выбор нажатием клавиши **Enter**. После выбора листа, на экране отобразится мастер **"Создания чертежа планшета"**.
{{ :developers:tutorial:plan_export_rules:tut_plan_decoration_rule_4.png?nolink |}}
В нижней части окна мастера вы увидите флажок **"Применить правило оформления"**. Установив этот флаг, станут активными список используемых **правил оформления плана** и кнопки **Добавить** и **Удалить**.
По умолчанию, в списке правил уже присутствует **правило оформления плана** **"gugk.py"**, изменяющее чертёж плана в соответствии с требованиями кодификатора условных знаков **ГУГК** (Главное Управление Геодезии и Картографии). Правило "**gugk.py**" разработано сотрудниками Топоматик и входит в стандартный пакет установки программных продуктов Робур.
{{ :developers:tutorial:plan_export_rules:tut_plan_decoration_rule_5.png?nolink |}}
С помощью кнопки **Добавить** вы можете добавить одно или несколько правил оформления плана. После нажатия кнопки **ОК** правила оформления будут применены к экспортируемому чертежу.
Правила оформления будут выполняться по очереди, в том порядке, в котором они расположены в списке сверху вниз.
==== Разработка правила оформления плана ====
=== Импорт библиотек классов .Net ===
Создайте текстовый файл с расширением **".py"**. По умолчанию, **правила оформления плана** располагаются в директории ''c:\ProgramData\Topomatic\Robur \16.0\Support\''. Пользовательские правила рекомендуется располагать там, но вы можете расположить их в любом другом доступном месте.
**[[https://learn.microsoft.com/ru-ru/dotnet/standard/class-libraries|Библиотеки классов .Net (DLL сборки)]]** - бинарные файлы с расширением **".dll"**, содержащие описание классов объектов, их состояния и методов взаимодействия с ними.
Для подгрузки **DLL сборок** в **IronPython** служит модуль **clr**
. Его необходимо импортировать с помощью команды ''import''. В теле правила оформления добавьте следующую строку.
import clr
После того как модуль загружен, можно приступить к подгрузке **DLL сборок**. Для этого воспользуемся методом ''clr.AddReference(assembly_name)'' и передадим в него имя сборки без расширения. Предположим, в процессе работы правила вам потребуется прочитать **XML-файл**. Для этого подгрузим сборку **"System.Xml.dll"**. Так же подгрузим сборку **"Topomatic.Dwg.dll"** для работы с примитивами чертежа. Добавьте следующие строки в файл правила.
clr.AddReference("System.Xml")
clr.AddReference("Topomatic.Dwg")
=== Отладка кода ===
Для отладки кода правила оформления, можно отправлять сообщения в окно командной строки:
# Подгрузка библиотеки для доступа к командной строке
clr.AddReference("Topomatic.Cad.View")
# Текст сообщения
msg = "I'm here"
# Отправка сообщения в окно командной строки
Topomatic.Cad.View.ConsoleListner.Current.WriteLine(msg)
=== Глобальные переменные ===
При создании чертежа плана, в среде выполнения **Python** будут проинициализированы переменные, используя которые мы получим доступ к экспортируемому чертежу для последующего изменения его состояния:
^ Переменная ^ Тип ^ Значение ^
| ''__model'' | DwgBlock | Блок пространства модели (Model Space). Основной блок чертежа, содержит примитивы чертежа и ссылки на другие блоки |
| ''__path'' | Строка | Путь к файлу исполняемого в текущий момент **правила оформления плана** |
| ''__scale'' | Вещественное | Масштаб листа, где 1.0 это М1:1000 |
=== Коллекции чертежа ===
Доступ к основным коллекциям элементов чертежа осуществляется с помощью следующих свойств:
# Получение чертежа (Drawing)
drawing = __model.Drawing
# Коллекция примитивов (DwgEntities)
entities = __model.Entities
# Коллекция блоков (DwgBlocks)
blocks = drawing.Blocks
# Коллекция размерных стилей (DwgDimensionStyles)
dimension_styles = drawing.DimensionStyles
# Коллекция слоёв (DwgLayers)
layers = drawing.Layers
# Коллекция типов линий (DwgLinetypes)
linetypes = drawing.Linetypes
# Коллекция текстовых стилей (DwgStyles)
text_styles = drawing.Styles
Подробнее о работе с чертежом можно узнать в разделе руководства **[[developers:tutorial:drawing|Работа с примитивами чертежа]]**.
=== Пример правила оформления ===
Рассмотрим пример правила оформления чертежа плана. В примере выполним следующие действия:
* Импортируем модуль загрузки библиотек .Net и укажем ссылки на необходимые библиотеки
* Импортируем необходимые библиотеки .Net
* В коллекцию текстовых стилей чертежа добавим пользовательский текстовый стиль
* Всем текстовым примитивам чертежа назначим пользовательский текстовый стиль
* В коллекцию слоёв чертежа добавим пользовательский слой
* Изменим слой всех примитивов красного цвета на пользовательский и назначим им цвет "По слою"
* Выведем информацию о ходе выполнения правила оформления в окно командной строки
* Уведомим пользователя о завершении работы правила оформления
# coding: windows-1251
# Импорт модуля подгрузки библиотек .Net
import clr
import dlr
# Добавление ссылок на библиотеки .Net
clr.AddReference("System.Windows.Forms")
clr.AddReference("Topomatic.Cad.Foundation")
clr.AddReference("Topomatic.Cad.View")
clr.AddReference("Topomatic.Dwg")
# В качестве примера взаимодействия с системный библиотеками Windows
# добавим библиотеку Windows Forms и для удобства назначим ей псевдоним
import System.Windows.Forms as win_forms
# Импорт пространств имён начинающихся с Topomatic
import Topomatic
# Импорт перечисления Topomatic.Cad.Foundation.CadColor
# с указанным псевдонимом для удобного доступа в цветовой палитре
import Topomatic.Cad.Foundation.CadColor as cad_colors
# Инициализация переменных
custom_text_style_name = "Custom Text Style"
custom_text_style_font_name = "Arial.ttf"
custom_layer_name = "Custom Layer"
# Определение метода для упрощения процесса отладки
@dlr.params(str)
def report(msg):
"""
Отправка сообщения в окно командной строки.
Аргументы:
msg - строка (str)
"""
Topomatic.Cad.View.ConsoleListner.Current.WriteLine(msg)
# Определение основного метода правила оформления
@dlr.params(Topomatic.Dwg.DwgBlock, str, float)
def execute(model, path, scale):
"""
Основной метод правила.
Аргументы:
model -- Основной блок чертежа (Topomatic.Dwg.DwgBlock),
path -- Путь к файлу исполняемого в текущий момент правила оформления плана (str),
scale -- Масштаб листа (float)
"""
# Отправляем в командную строку сообщение о начале выполнения правила
report("Начало выполнения правила")
# Получаем чертёж необходимые коллекции его элементов
drawing = model.Drawing
entities = model.Entities # Примитивы
layers = drawing.Layers # Слои
text_styles = drawing.Styles # Текстовые стили
# Получаем пользовательский текстовый стиль
text_style = get_or_create_custom_text_style(text_styles)
# Меняем текстовый стиль текстовых примитивов на пользовательский
if text_style is not None:
change_entity_text_style(entities, text_style)
# Получаем пользовательский слой
layer = get_or_create_custom_layer(layers)
# Меняем слой у всех примитивов красного цвета на пользовательский
# и устанавливаем им цвет "По слою"
if layer is not None:
change_entity_layer(entities, layer)
# Сообщаем о завершении работы правила с помощью
# диалогового окна системной библиотеки Windows Forms
win_forms.MessageBox.Show("Правило успешно применено", "Правило оформления чертежа плана",
win_forms.MessageBoxButtons.OK, win_forms.MessageBoxIcon.Information)
# Определение метода для получения пользовательского текстового стиля
@dlr.params(Topomatic.Dwg.DwgStyles)
def get_or_create_custom_text_style(text_styles):
"""
Получение пользовательского текстового стиля.
Аргументы:
text_styles - Коллекция текстовых стилей (Topomatic.Dwg.DwgStyles)
"""
# Отправляем в командную строку сообщение о начале получения текстового стиля
report("Получение пользовательского текстового стиля")
# Получение текстового стиля по имени из коллекции
# Если стиль не обнаружен, то добавляем его и устанавливаем
# значения необходимых параметров
style = text_styles[custom_text_style_name]
if style == None:
style = text_styles.Add(custom_text_style_name, custom_text_style_font_name)
style.Height = 3
style.Ratio = 0.8
# Возвращаем пользовательский текстовый стиль
return style
# Определение метода для изменения текстового стиля текстовых примитивов
@dlr.params(Topomatic.Dwg.DwgEntities, Topomatic.Dwg.DwgStyle)
def change_entity_text_style(entities, text_style):
"""
Изменение текстового стиля текстовых примитивов.
Аргументы:
entities - Коллекция примитивов (Topomatic.Dwg.DwgEntities)
text_style - Текстовый стиль (Topomatic.Dwg.DwgStyle)
"""
# Отправляем в командную строку сообщение о начале получения текстового стиля
report("Изменение текстового стиля текстовых примитивов")
# Проходим по коллекции примитивов и если примитив это
# Текст (DwgText) или Мультитекст (DwgMText),
# то меняем его текстовый стиль на пользовательский
for i in xrange(0, entities.Count - 1):
entity = entities[i]
if (isinstance(entity, Topomatic.Dwg.Entities.DwgText)) or (isinstance(entity, Topomatic.Dwg.Entities.DwgMText)):
entity.Style = text_style
# Определение метода для получения пользовательского слоя
@dlr.params(Topomatic.Dwg.DwgLayers)
def get_or_create_custom_layer(layers):
"""
Получение пользовательского слоя.
Аргументы:
layers - Коллекция слоёв (Topomatic.Dwg.DwgLayers)
"""
# Отправляем в командную строку сообщение о начале получения слоя
report("Получение пользовательского слоя")
# Получение слоя по имени из коллекции
# Если слой не обнаружен, то добавляем его и устанавливаем
# значения красный цвета слоя используя псевдоним cad_colors
layer = layers[custom_layer_name]
if layer == None:
layer = layers.Add(custom_layer_name)
layer.Color = cad_colors.Red
# Возвращаем пользовательский слой
return layer
# Определение метода для изменения слоя у примитивов красного цвета
@dlr.params(Topomatic.Dwg.DwgEntities, Topomatic.Dwg.DwgLayer)
def change_entity_layer(entities, layer):
"""
Изменение слоя примитивов красного цвета на пользовательский и назначение им цвета "По слою".
Аргументы:
entities - Коллекция примитивов (Topomatic.Dwg.DwgEntities)
layer - Слой (Topomatic.Dwg.DwgLayer)
"""
# Отправляем в командную строку сообщение о начале изменения слоя примитивов красного цвета
report("Изменение слоя примитивов красного цвета и назначение им цвета \"По слою\"")
# Проходим по коллекции примитивов и если примитив это
# Текст (DwgText) или Мультитекст (DwgMText), то меняем его текстовый стиль
for i in xrange(0, entities.Count - 1):
entity = entities[i]
if (entity.Color == cad_colors.Red):
entity.Layer = layer
entity.Color = cad_colors.ByLayer
# Точка входа.
# Если переменная '__model' проинициализирована,
# то изменяем чертёж
if (__model != None):
execute(__model, __path, __scale)
else:
raise AssertionError("\"__model\" variable is not defined")