Найти в Дзене
Одна кнопка

JScript для SCAD++ на примере

Выдохнул... Начну с того, что к программистам я отношения не имею, если вы такие же, то попали по адресу. Рассаживайтесь поудобней буду рассказывать как я пилил скрипт. Пару слов о JScript for SCAD++ SCAD++ можно расширить, если чего то не хватает конкретно для вас. Для этого разработчики предусмотрели пользовательские расширения (скрипты) которые можно использовать при построении и анализе расчетных схем. Скрипт представляет собой определенные инструкции, которые СКАД выполняет после его запуска (создание/модификация элементов, нагрузок, узлов и.т.д.) Полное руководство находится в папке с установленным SCAD++ в файле SCAD_Plugins.pdf Руководство написано очень подробно и на русском языке. Поэтому постараюсь поменьше ссылаться на него. Откройте его и пусть оно будет под рукой если возникнут вопросы. PreProcessor и PostProcessor Все скрипты разделяются на 2 категории. Первая категория это скрипты, которые работают на этапе создания расчетной схемы (PreProcessor). Вторая категория э
Оглавление
LoadingForceElem.rar

Выдохнул...

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

Пару слов о JScript for SCAD++

SCAD++ можно расширить, если чего то не хватает конкретно для вас. Для этого разработчики предусмотрели пользовательские расширения (скрипты) которые можно использовать при построении и анализе расчетных схем. Скрипт представляет собой определенные инструкции, которые СКАД выполняет после его запуска (создание/модификация элементов, нагрузок, узлов и.т.д.)

Полное руководство находится в папке с установленным SCAD++ в файле SCAD_Plugins.pdf

Руководство написано очень подробно и на русском языке. Поэтому постараюсь поменьше ссылаться на него. Откройте его и пусть оно будет под рукой если возникнут вопросы.

PreProcessor и PostProcessor

Все скрипты разделяются на 2 категории. Первая категория это скрипты, которые работают на этапе создания расчетной схемы (PreProcessor). Вторая категория это скрипты, которые работают с результатами расчета (PostProcessor). То есть от того куда мы поместим наш скрип будет зависеть то на каком этапе мы сможем его выполнить.

Папки Pre, PostProcessor хранятся по адресу: C:\ProgramData\SCAD Soft\Plugins\

C:\ProgramData изначально скрыта в Windows. Но если в адресной строке набрать этот путь, то проводник без проблем вас туда проводит

То есть наш скрипт нужно поместить в одну из папок в зависимости от категории и пиктограмма скрипта отобразится в SCAD++

Для отображения панели расширений в SCAD++ нужно нажать кнопку Вид->Панели инструментов->Расширения. После этого появится панелька с расширениями

Пользовательское расширение

Пользовательское расширение представляет собой набор файлов (в том числе скрипт) который лежит структурированно в папке с именем расширения. Пример структуры моего расширения приведу на скрине ниже(ну по сути структура одинакова для всех):

  • Plugin.js-Собственно сам скрипт
  • icon.bmp-Пиктограмма на панели расширений
  • data-Вспомогательная папка о назначении которой расскажу позже

Редактировать будем только Plugin.js и icon.bmp. Остальное нам пока не нужно.

Постановка задачи

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

То что нужно получить
То что нужно получить

Сейчас есть возможность создать эту нагрузку через последовательный выбор каждой пластины. При этом нужно на каждом этапе загружения отслеживать где узел P1 и где P2. Мне бы хотелось, чтобы нагрузки прикладывались сразу на все 4 элемента при выборе 5 узлов.

Этап 1. Схема реализации

Входящими данными для программы является селекция глобальных узлов (5 узлов) которую выполнил пользователь перед запуском скрипта. То есть пользователь выделил 5 узлов и нажал кнопку расширения. Дальнейшую работу берет на себя программа (скрипт).

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

У каждого элемента есть локальные номера узлов, количество которых зависит от вида КЭ. Если стержень-2 узла, Треугольная пластина-3 узла и.т.д. Нумерация каждого из них начинается с единицы. Номера которые отображает SCAD при нажатии на кнопочку "Номера узлов"- глобальные узлы

Этап 2. Сортировка на словах

Для того чтобы загрузить элементы и понимать на какой элемент прикладывать какую нагрузку нужно "выстроить" их в ряд. Тогда появится понимание кого как грузить. Условно раздать узлам фиктивные номера от 1 до 5-ти. В этом нам поможет Пифагор. Так как логика выстраивания их в ряд будет основываться на его научном труде, а именно "Теореме Пифагора": с^2=a^2+b^2. Ниже поясню скрином что я имею ввиду:

Схема для сортировки узлов
Схема для сортировки узлов

Для каждого из узла я строю отрезок, который соединяет узел с началом координат, то есть получаю что-то типа списка списков

[ [длина_отрезка1, номер узла1] , [длина_отрезкаN, номер узлаN] ]

затем отсортировав список списков по длинам отрезков я получу соответствующие отсортированные в ряд номера узлов.

Список-термин программирования, который представляет собой набор элементов разделенных запятой в квадратных скобках. Каждый элемент имеет свой порядковый номер в списке и обращаться к нему можно по этому номеру (индексу) . Элементами списка могут быть как числа, так и строки или даже списки (в моем случае). Нумерация элементов начинается с нуля.
Пара примеров:
[3, 4.5, 5] - Список чисел
["яблоко", "мандарин", "кокос"] -список строк

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

Словари-по сути структурированные списки в виде "ключ : значение". Ключи списка обязательно должны быть уникальными. Значениями могут быть числа, строки, списки, словари и.т.д. Словари обрамляются фигурными скобками. Обращение к элементам словаря обычно происходит по ключу.
Пример словаря:
{"Майкл" : 31}

Этап 3. Сортировка на деле

Для сортировки в JScript используется метод sort. То есть он меняет местами элементы списка по возрастанию. То есть если приметить к списку [5, 4.5, 3] метод sort результат будет [3, 4.5, 5].

делается это так: [5, 4.5, 3].sort()

В нашем случае список списков. То есть сортировать нужно по первому элементу вложенного списка. Чтобы до него добраться при вызове метода я говорю методу, что сортировать нужно особенным образом (применяя функцию compare, которую я описал отдельно и которая проводит сортировку именно по первому вложенному элементу). Выглядит эта функция вот так:

Функция сортировки по первому вложенному элементу списка
Функция сортировки по первому вложенному элементу списка

Этап принятия

На этом этапе нужно понять что у нас есть все исходные данные. Отсортированные имена узлов. Имена элементов, которые нам отдаст SCAD++ при запросе скриптом, наши значения нагрузок (которые были у нас изначально и не имеют отношения к логике программы). Ну а дальше в бой!

Hello World

Говорят именно так должна называться и выглядеть первая программа. Чтобы не нарушать эту традицию я выложу по ссылке расширение, которое вы можете сразу запустить и убедиться в работоспособности скрипта. Так же использовать его позже как шаблон своих будущих программ.

1. Разархивировать
2. Папку HW положить в папку: C:\ProgramData\SCAD Soft\Plugins\PreProcessor
3. В режиме "создания расчетной схемы" вывести панель "Расширения". И нажать кнопку Обновить.
4. Нажать на пиктограмму "HW"
Выполнится скрипт, который выведет сообщение "Привет Мир"

Вернемся к нашей программе

Логика есть. Заготовка-шаблон есть. Нужно собрать все в одно целое.

Многофункциональная кнопка.

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

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

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

Небольшое отступление. Вся активная часть программы будет располагаться в функции Plugin_Execute файла Plugin.js
То есть все что мы туда напишем будет выполнено при нажатии на кнопку.

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

Логика разделения функции в зависимости от количества выбранных узлов
Логика разделения функции в зависимости от количества выбранных узлов

На JScript это будет выглядеть так:

Логика разделения функции в зависимости от количества выбранных узлов
Логика разделения функции в зависимости от количества выбранных узлов

1. Cоздали пустой словарь selection.

2. Наполнили значение ключа ListNode (список выделенных узлов).

3. Проверили что не пустой (!=null). Если пустой, то ушли в режим 1.

1 режим

Не хотелось бы на нем зацикливаться. Скажу лишь, что его функционал заключается в том, чтобы создать текстовый файл с 4-мя строками в папке data.

1 строка - F1 (Погонная нагрузка 1)
2 строка - F2 (Погонная нагрузка 2)
3 строка - F3 (Погонная нагрузка 3)
4 строка - L (Номер загружения)

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

Получение исходных данных по нагрузкам
Получение исходных данных по нагрузкам

Тут мы читаем построчно файл config.txt и помещаем в переменные данные для нагрузок.

2 режим

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

Тут нужно пояснить, что для чтения данных из схемы используется объект model, а для редактирования схемы объект editor. Эти два объекта мы получим в самом начале программы и в дальнейшем будем через них взаимодействовать со схемой. Получение объектов привожу на скрине ниже:

Получение объектов model и editor
Получение объектов model и editor

Объявили словом var переменную model и передали ей объект методом GeTModel. То же с переменной editor.

Теперь если нам нужно что-то прочитать из схемы, то мы обращаемся к объекту model. Если что-то изменить, то к объекту editor.

К объекту editor можно обратиться только в режиме создания расчетной схемы (из PreProccesor)

В следующем листинге я закомментировал основные шаги, поэтому расписывать подробно не буду. В двух словах. Создаю пустой список lst_node, который последовательно (в цикле for) наполняю списками [длина; номер_узла]. Добавление в список элемента осуществляется методом push. Затем сортирую список по длинам и получаю отсортированный список списков вида: [ [leni,nodei] , [lenn,noden] ], то есть второй элемент каждого из вложенного списка это номер узла, а последовательность этих узлов задана позицией во внешнем списке.

Получение и сортировка номеров узлов
Получение и сортировка номеров узлов

В следующем листинге я показал как осуществляется задание нагрузки на один из элементов.

Тут храним глобальные номера узлов (которые отображает SCAD++)
Номера получаем из списка lst_node созданного ранее. Для индексного обращения к элементам списка используются квадратные скобки.
var node1_global=lst_node[0][1]
var node2_global=lst_node[1][1]

Далее получаем функцией get_num_elem номер элемента которому принадлежит и 1 и 2 узел. Листинг функции get_num_elem приведу ниже.

var num_el=get_num_elem(model,node1_global,node2_global)

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

var node1_local=0
var node2_local=0

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

for (i in info_el.ListNode.toArray())
{
if (info_el.ListNode.toArray()[i]==node1_global)
{node1_local=i*1+1}
if (info_el.ListNode.toArray()[i]==node2_global)
{node2_local=i*1+1}
}

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

Эту же операцию проделываю с оставшимися узлами.

Нагрузка на элементы
Нагрузка на элементы
Функция get_num_elem, осуществляет поиск элемента по номерам узлов
Функция get_num_elem, осуществляет поиск элемента по номерам узлов

Заключение

Расширение можно скачать по этой ссылке

Спасибо всем кто помог разобраться (поддержке SCAD++ и программистам канала bablofil, которые отвечали на глупые вопросы)