Введение: в данной статье продолжим серию по работе с Dynamo for Civil 3D и посвятим её теме работы с текстом (объекты типа MText и Text) по той причине, что стандартных нодов по работе с ними довольно мало, а получение отдельных свойств возможно лишь через транзакции к базе данных чертежа.
1. Где встречаются операции по работе с текстом?
Сперва давайте представим ряд ситуаций, где может понадобится работать с текстом как с отдельными примитивами (все эти ситуации мы рассмотрим в данной статье)
- редактирование топоосновы с большим числом примитивов AutoCAD (текст, отрезки, штриховки);
- простановка текстовых меток/обозначений (в особенности, на листах);
- корректировка положения меток относительно объектов Civil 3D
По существу первые 2, это основные ситуации; остальное уже отдельные варианты. В остальном желательно использовать определения атрибута блока (для точечных объектов), либо вовсе запихивать текст в атрибутику (наборы характеристик/object data).
Для первого примера задача будет изменить все текстовые метки, сделав надписи строчными. Для этого нам потребуется сперва получить экземпляры текста в список, затем получить их содержимое, разбить содержимое на под-объекты к которым будем применять операции преобразования и записать изменения в объекты.
2. Выборка содержимого
Выбрать содержимое можно по разному - от прямого Select Objects до более универсального - All objects On Layer/Of Type. В случае с топоосновами, которые имеют жесткое именование слоев удобен первый случай:
Каждый из вариантов требует в идеале дополнительной проверки на формат данных (принадлежность слою, типу объекта)
3. Получение значения текста и формирование нового списка
А вот тут начинается уже интересное. Базовых нодов для чтения текста не предусмотрено (есть только для создания и получения некоторых геометрических параметров).
Для получения содержимого текста необходимо обращаться к базе данных чертежа при помощи транзакции.
Суть заключается в том, что в состав "шаблона для Python Script" вставляется конструкция следующего вида:
item_handle = <<InputItem>>.Handle
item_id = db.GetObjectId(False,Handle(int(item_handle, 16)),0);
_item = t.GetObject(item_id,OpenMode.ForRead)
И уже далее в зависимости от типа "_item" получают его свойства, в нашем случае - содержимое текста получается методом TextString.
4. Процедура обновления содержимого текста
По существу, процесс мало отличается от запроса значений текста - только теперь добавляется процесс завершения транзакции t.Commit() и изменение варианта чтения БД чертежа с чтения на запись OpenMode.ForWrite:
5. Изменение поворота текста для красивой ориентации на ВЭ
Не секрет, что на стадии оформления чертежей, приходиться прибегать к повороту ВЭ, из-за чего текст на них становится нечитаемым (необходимо его доворачивать). На этот счет - можно предложить решение почти с тем же кодом, что у нас есть, только с небольшим дополнением.
В качестве объекта, относительно которого будет задаваться вращение будем использовать трассы, тем более что она зачастую и используется как объект для вывода листов при помощи стандартного функционала Civil 3D:
Менять правда, мы будем не для каждого ВЭ (создавая копии слоев), а сразу для всей модели - под ближайшую же трассу
Первым действием мы "обнулим" повороты для всего текста - сделав значение "0". Затем, для каждого из объектов текста мы найдем значение точки пересечения перпендикуляра, опущенного из точки текста на трассу и выявим наименьшее расстояние - значит этот текст принадлежит данной трассе, после чего вычислим угол поворота текста и запишем в список необходимый гол поворота. И после того, как мы пройдемся по всем объектам текста - в рамка одной транзакции запишем изменения в чертеж.
5.1 Обнуление всего текста
Здесь используется почти та же конструкций что выше, только мы меняем угол поворота - TextItem.Rotation. При этом метод принимает на вход значение в радианах, а не в градусах - следует иметь это в виду.
5.2 Текущая точка местоположения текста
Базовые ноды получения геометрии объекта здесь не подойдут - для получения геометрии объектов текста придется снова делать транзакцию, причем для Text нужно получать элемент "Position", а для MText - "Location". Возвращаемое значение имеет тип Point 3D, от которого мы получаем координаты и сводим к X,Y:
5.3 Получение угла поворота текста относительно ближайшей трассы
Здесь у нас будет жирный Python скрипт, в котором мы для каждого текста получим расстояние от него до всех трасс, выберем наименьшее расстояние и для него вычислим угол поворота трассы относительно направления OX, на который и повернем наш текст.
В качестве метода определения положения текста относительно трассы будем использовать метод API: StationOffsetAcceptOutOfRange, который позволяет продолжать выполнение кода, если точка лежит за пределами трассы
Возвращаемый угол поворота в рамках другого нода-скрипта прописывается в объект-текста. Внутрянка нода точно такая же, как в случае задания для поворота значения 0 градусов выше
6. Итоги и заключение
Попробую показать результат применения скрипта. Вот так было "до":
Для устранения наложения текста можно внести в тело метода GetCoordsOfText доп. опцию проверки, есть ли наложение с каким-либо занесенным в список точек текстом:
А сам метод, который сдвинет текст на верные координаты вписать в структура скрипта вот так:
Хотя честно сказать. хоть счетчик показывает выполнение действий для всех "пересекающихся сущностей", но реально изменяется только ~ 25%. Почему так, я пока не разобрался ... это будет тогда следующая статья - на тему устранения наложений объектов друг на друга.
Вдобавок, надо похоже вносить исключение на величину угла поворота текста - так как работает это всё тоже не однозначно.
Сама текущая версия скрипта доступа по ссылке с названием "Roads_RotateTextOnViewport2.dyn".
#autodesk #civil 3d #dynamo #text #mtext #text intersection #ironpython #мтекст #текст autocad