1149x
001825
2024-09-04

Веб-сервис и API для расчёта стадий строительства

При расчёте обычных конструкций, ввод данных зачастую не сложен, но занимает много времени. Экономьте своё драгоценное время с помощью автоматизированного ввода данных. Задача, описанная в данной статье, состоит в том, чтобы рассмотреть этажи дома как отдельные стадии строительства. Данные вводятся с помощью программы C#, поэтому пользователю не нужно вводить элементы отдельных этажей вручную.

Предпосылка

Следующая программа работает при следующих условиях:

  • Плоскости этажа параллельны плоскости xy.
  • Модель не должна содержать элементы, занимающие несколько этажей (например, поверхность фасада, занимающая два или более этажа)
  • Фундамент и цокольный этаж относятся к нулевому этажу,
  • Тела не учитываются.
  • Используются только плоские поверхности.
  • Ось z направлена в направлении ускорения свободного падения (вниз).

Теоретические основы

Из предыдущих требований следует, что должна быть задана только высота этажа, а затем элемент, например узел, должен своей координатой z находиться выше нижней высоты этажа и доходить до максимальной высоты или равной текущей высоте этажа..

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

Далее этажи присваиваются всем узлам на основе их высоты.

Для линий можно использовать этажи узлов. Если линия начинается на потолке и заканчивается на потолке, который находится выше, то она должна быть придана верхнему потолку. Таким образом, линия присваивается самому высокому этажу, который можно найти в ваших узлах.

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

То же самое относится к поверхностям. Определяется самый высокий этаж соответствующих узлов.

После придания всех элементов этажа, стадии строительства можно создать прямо из списка этажей.

Интегратор

В качестве основы программа использует шаблон из пакета Dlubal.RFEMWebServiceLibrary NuGet. Здесь вы узнаете, как его установить:

https://github.com/Dlubal-Software/Dlubal_CSharp_Client

Сначала активная модель подключается следующим образом:

  1. code.cshamp#

...

  1. region Параметры программы

try
{

  1. application_informationApplicationInfo;
  2. try
  3. {
  4. //соединяется с приложением RFEM6 или RSTAB9
  5. приложение = новое ApplicationClient (Привязка, Адрес);
  1. }
  2. Поймать (исключение)
  3. {
  4. if (приложение != ноль)
  5. {
  6. if (application.State != CommunicationState.Faulted)
  7. {
  8. приложение.Закрыть();
  9. }
  10. else
  11. {
  12. application.Abort();
  13. }
  1. заявка = пустая;
  2. }
  3. }
  4. finally
  5. {
  6. ApplicationInfo = применением.get_information ();
  7. Консоль.WiteLine("Название: {0}, Версия:{1}, Тип: {2}, язык: {3} ",ApplicationInfo.name,ApplicationInfo.version,ApplicationInfo.type,ApplicationInfo.language_name);
  8. }
  9. #конецобласти
  1. //получить активную модель
  2. строка modelUrl = применением.get_active_model();
  1. //соединяется с моделью RFEM6/RSTAB9
  2. ModelClient model =new ModelClient(Binding,new EndpointAddress(modelUrl));

...

  1. /код#

Для лучшей обработки ошибок, в исходном коде используется блок try-catch. Внутри этого блока приложение сначала подключается, что также выполняется в блоке try-catch. После успешного подключения приложения, текущая активная модель (на переднем плане в RFEM 6) подключается с помощью метода get_active_model. Если возникают какие-либо проблемы, вступает в силу внешний блок try-catch.

Поскольку необходимо рассчитать все узлы, линии, стержни и поверхности, имеет смысл взять все элементы из программы RFEM. Чтобы получить количество соответствующих элементов, сначала считываются номера объектов всех категорий. Далее соответствующие объекты могут быть переданы с помощью их номеров:

  1. code.cshamp#

...
int[] node_nums = model.get_all_object_numbers(object_types.E_OBJECT_TYPE_NODE, 0);
int[]line_nums = model.get_all_object_numbers(object_types.E_OBJECT_TYPE_LINE, 0);
int[] Member_nums = model.get_all_object_numbers(object_types.E_OBJECT_TYPE_MEMBER, 0);
int[] Surface_nums = model.get_all_object_numbers(object_types.E_OBJECT_TYPE_SURFACE, 0);

//получить все узлы
Консоль.WiteLine("1. Получить все узлы:");
узел[] nds = новый узел[node_nums.Length];
для (int i = 0; i {
nds [i] = model.get_node (node_nums [i]);
если ((i%10)==0)
Консоль.Запись("+");

}
Консоль.WiteLine("");
...

  1. /код#

Для того, чтобы пользователь мог получить представление о продолжительности процесса, в консоли записывается «+» после каждых 10 элементов.

Перед передачей других элементов, в следующем шаге задаются высоты этажа. Сначала необходимо считать выбранные объекты. Переданный массив (поле/вектор, включая элементы) имеет тип объект_локация и содержит все выбранные объекты с их типом и количеством. Таким образом, узлы можно отфильтровать в цикле. Поскольку все узлы уже доступны, можно определить z-координаты этих узлов в том же цикле. Выбранные объекты циклически просматриваются, и, как только элемент относится к типу узлов, выполняется поиск данного узла среди всех остальных узлов, а затем его координата z вводится в массив surface_heights. Для каждой найденной координаты массив будет расширен элементом:

  1. code.cshamp#

...
Консоль.WiteLine("2. Получить выбранные узлы");
//получить все выбранные объекты
объект_локации [] obj_locs = model.get_all_selected_objects ();

//получить все выбранные номера узлов
двойной[] этажа_heights = новый двойной[1];
forach (object_location obj в obj_locs)
{
if (obj.type == objject_types.E_OBJECT_TYPE_NODE)
{
для (int i = 0; i < nds.Length; ++i)
{
if (nds[i].no == obj.no)
{
этажа_высота [этажа_heights.Length - 1] = nds [i].coordinate_3;
Array.Resize(ref этажа_heights, этажа_heights.Length + 1);
разрыв;
}
}
}
}
Array.Resize(ref этажа_heights, этажа_heights.Length - 1);

//сортировать массив
//ось z отрицательна, наиболее положительное значение измельчено
Array.Sort(floor_heights);
Array.Reverse(floor_heights);
//цокольный и цокольный уровень представляют собой один уровень, удалите первую запись
двойной[] tmp_arr = новый двойной[этаж_высота.Length - 1];
Array.Copy(floor_heights, 1, tmp_arr, 0,pol_heights.Length - 1);

этажа_высота = ноль;
этажа_heights = tmp_arr;
...

  1. /код#

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

Затем передаются оставшиеся элементы, такие как линии, стержни и поверхности:

  1. code.cshamp#

...
//получить все линии
Консоль.WiteLine("3. Получить все линии:");
линия[] lns = новая линия[line_nums.Length];
для (int i = 0; i {
lns[i] = model.get_line(line_nums[i]);
if ((i % 10) == 0)
Консоль.Запись("+");
}
Консоль.WiteLine("");

//получить все стержни
Консоль.WiteLine("4. Получить все стержни:");
стержень[] mems = новый стержень [member_nums.Length];
для (int i = 0; i < Member_nums.Length; ++i)
{
mems [i] = model.get_member (member_nums [i]);
if ((i % 10) == 0)
Консоль.Запись("+");
}
Консоль.WiteLine("");

//получить все поверхности
Консоль.WiteLine("5. Получить все поверхности:");
Surface[] srfs = новая поверхность [surface_nums.Length];
для (int i = 0; i < Surface_nums.Length; ++i)
{
srfs [i] = model.get_surface (surface_nums [i]);
if ((i % 10) == 0)
Консоль.Запись("+");
}
Консоль.WiteLine("");
...

  1. /код#

Чтобы отсортировать элементы по отдельным этажам, сначала создаются двумерные списки. В списке nds_этаж_numbers в качестве первого измерения указаны этажи, а во втором - номера узлов этажа. Прежде всего, следующий цикл проходит по всем узлам и имеет подчиненный цикл, который проходит по всем высотам этажа. Для каждого узла программа проверяет, лежит ли координата Z в пределах высоты этажа, снизу вверх. Из-за численных неточностей был вычтен допуск 1 мм:

  1. code.cshamp#

...
//цикл по узлам и установка их этажа
Консоль.WiteLine("6. Перебрать узлы и получить их основание");
для (int i = 0; i < nds.Length; ++i)
{
для (int j = 0; j
{
if (nds[i].coordinate_3 >= этажа_heights[j] - 0,001)
{
nds[i].comment = j.ToString();
//Console.WiteLine("node" + nds[i] + " перекрытие " + j + ";" + nds[i].coordinate_3 + ";" + (этаж_heights[j] - 0,001));
nds_этаж_numbers[j].Add(nds[i].no);
//model.set_node(nds[i]);
разрыв;
}
}
}
...

  1. /код#

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

Это очевидно, если посмотреть на цикл по линиям:

  1. code.cshamp#

...
//цикл по линиям, получение их узлов и задание их основания
Консоль.WiteLine("7. Запустить линии и получить их пол");
для (int i = 0; i < lns.Length; ++i)
{
//получить узлы линии
int[] ln_node_nums = lns[i].definition_nodes;
Int32 этажа_max = 0;
//цикл по узлам линии
для (int j = 0; j)
{
//цикл по узлам
для (int l = 0; l SMALLERTTHN nds.Length; ++l)
{
if (nds [l] .no == ln_node_nums [j])
{
Int32 этажа = Int32.Parse(nds[l].comment);
if (floor > Этаж_макс.)
{
этажа_макс. = перекрытие;
разрыв;
}
}
}

}
//задать максимальный этаж в линии
lns[i].comment = surface_max.ToString();
lns_этаж_numbers[этаж_max].Add(lns[i].no);
//model.set_line(lns[i]);

}
...

  1. /код#

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

Как уже упоминалось в теоретических основах, достаточно задать самый высокий номер этажа. Данный номер затем сохраняется как номер этажа в комментарии линии, а номер линии вставляется в список.

Стержням присваиваются те же номера этажей, что и линиям, на которых они лежат. Таким образом, требуется цикл по всем стержням с частичным циклом по всем линиям. Как только номер линии будет соответствовать номеру стержня, стержень получит в качестве комментария высоту этажа, а номер будет добавлен в список:

  1. code.cshamp#

...
//цикл по стержням, получение их линий и задание их перекрытий
Консоль.WiteLine("8. Перебрать стержни и получить их основание");
для (int i = 0; i < mems.Length; ++i)
{
//получить номер линии стержня
int mem_ln_num = mems [i] .line;

//цикл по линиям
для (int j = 0; j < lns.Length; ++j)
{
if (lns [j] .no == mem_ln_num)
{
mems[i].comment = lns[j].comment;
mems_этажное_numbers[Int32.Parse (lns [j].comment)].Add (mems [i].no);
разрыв;
}
}

}
//цикл по поверхностям, получение их линий и задание их основания
Консоль.WiteLine("9. Перебрать поверхности и получить их покрытие");
для (int i = 0; i < srfs.Length; ++i)
{
//получить линии поверхности
int[] srf_line_nums = srfs[i].border_lines;
Int32 этажа_max = 0;
//цикл по линиям поверхности
для (int j = 0; j < srf_line_nums.Length; ++j)
{
//цикл по линиям
для (int l = 0; l SMALLERTHAN lns.Length; ++l)
{
if (lns [l] .no == srf_line_nums [j])
{
Int32 этажа = Int32.Parse(lns[l].comment);
if (floor > Этаж_макс.)
{
этажа_макс. = перекрытие;
разрыв;
}
}
}

}
//ввод максимального этажа в поверхности
srfs[i].comment = этажа_макс.ToString ();
srfs_этаж_numbers[этаж_max].Add(srfs [i].no);

//model.set_surface(srfs[i]);

}
...

  1. /код#

Процедура для поверхностей аналогична для линий. Существует цикл по поверхностям с суб-контуром по их граничным линиям. Самый высокий этаж от граничной линии становится номером этажа поверхности.

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

  1. code.cshamp#

...
Консоль.WiteLine("10. Задать стадии строительства");
try
{
model.begin_modification("задать стадии строительства");
//создать стадии строительства
для (int i = 0; i {
Construction_stage cstg = новая Construction_stage();

cstg.no = i + 1;
cstg.continue_on_construction_stage = i;
cstg.continue_on_construction_stageSspecificed = true;

cstg.are_members_enabled_to_modify = true;
cstg.are_members_enabled_to_modifyStecification = true;
cstg.adned_members = mems_этаж_numbers[i].ToArray ();
cstg.active_members = cstg.adned_members;

cstg.are_surfaces_enabled_to_modify = true;
cstg.are_surfaces_enabled_to_modifyStecification = true;
cstg.adned_surfaces = srfs_этаж_numbers[i].ToArray ();
cstg.active_surfaces = cstg.adned_surfaces;

cstg.name = "этаж" + i;
cstg.user_specific_name_enabled = true;
cstg.user_specific_name_enabledStecification = true;

model.set_construction_stage (cstg);

}
}
Поймать (исключение)
{
model.cancel_modification();
Консоль.WiteLine("Ошибка при создании геометрии" + исключение.Сообщение);
кидать ;
}
finally
{
try
{
model.finish_modification ()
}
Поймать (исключение)
{
Консоль.WiteLine("Ошибка при завершении создания геометрии" + исключение.Сообщение);
кидать ;
}
}
...

  1. /код#

При создании элементов в программе RFEM дополнительно применяется блок begin_modification/finish_modification, который позволяет максимизировать скорость передачи данных. В случае возникновения проблем затем обеспечивает защиту дополнительный блок try-catch, который в случае разрыва вызывает функцию отмены, тем самым правильно завершая обработку.

Важным примечанием относительно переноса является то, что подлежащие передаче элементы, такие как продолжить_на_construction_stage, могут быть переданы только в том случае, если соответствующее свойство «Заданный» было установлено на «true» (continue_on_construction_stageStecification). Не все элементы имеют такое свойство «Заданное», но там, где оно доступно, его необходимо учитывать.

Заключение

Благодаря универсальности интерфейса веб-сервис и API можно автоматизировать ряд сложных записей, вручную вводимых вручную. В нашем примере автоматизирован ввод данных для аддона Расчёт стадий строительства, который также служит в качестве основы для многих других аддонов и опций. Таким образом, у вас есть лишь некоторые ограничения для вашей креативности в процессе поиска экономичных решений, и мы покажем и другие примеры.


Автор

Г-н Гюнтель осуществляет техническую поддержку пользователей Dlubal Software.

Скачивания


;