912x
001825
2023-08-09

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

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

Предпосылка

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

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

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

Согласно требованиям ' ясно, что должна быть указана только высота этажа, при этом элемент, например узел, координата z которого находится выше высоты нижнего этажа и не превышает соответствующую высоту этажа.
Потому пользователь должен выбрать последовательность узлов, репрезентативных для высоты этажа. Координаты z и, следовательно, высоты этажа можно задать с помощью цикла.
Далее с помощью высот присваиваются всем узлам этажи.
Для линий можно вернуться к этажам узлов. Если линия начинается на потолке и заканчивается на потолке, который находится выше, то она должна быть придана верхнему потолку. Таким образом, линия присваивается самому высокому этажу, который можно найти в ваших узлах.
Поскольку стержни лежат на линиях и их можно присвоить заранее, стержень имеет то же перекрытие, что и его линия.
То же самое относится к поверхностям. Определяется самый высокий этаж соответствующих узлов.
После придания всех элементов этажа, стадии строительства можно создать прямо из списка этажей.

Запоминающийся

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

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


            

...
#region Параметры программы
try
{
    application_informationApplicationInfo;
    try
    {
        //соединяется с приложением RFEM6 или RSTAB9
        приложение = новое ApplicationClient (Привязка, Адрес);

    }
    Поймать (исключение)
    {
        if (приложение != ноль)
        {
            if (application.State != CommunicationState.Faulted)
            {
                приложение.Закрыть();
            }
            else
            {
                application.Abort();
            }

            применение = ноль;
        }
    }
    finally
    {
        ApplicationInfo = применением.get_information ();
        Консоль.WiteLine("Название: {0}, Версия:{1}, Тип: {2}, язык: {3} ",ApplicationInfo.name,ApplicationInfo.version,ApplicationInfo.type,ApplicationInfo.language_name);
    }
    #конецобласти

    //получить активную модель
    строка modelUrl = применением.get_active_model();

    //соединяется с моделью RFEM6/RSTAB9
    ModelClient model =new ModelClient(Binding,new EndpointAddress(modelUrl));
...


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


            

...
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 

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


            

...
Консоль.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;
...


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


            

...
//получить все линии
Консоль.WiteLine("3. Получить все линии:");
линия[] lns = новая линия[line_nums.Length];
для (int i = 0; i 

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


            

...
//цикл по узлам и установка их этажа
Консоль.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]);
			разрыв;
		}
	}
}
...


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


            

...
//цикл по линиям, получение их узлов и задание их основания
Консоль.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]);

}
...


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


            

...
//цикл по стержням, получение их линий и задание их перекрытий
Консоль.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]);

}
...


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


            

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

При создании элементов в программе RFEM дополнительно применяется блок begin_modification/finish_modification, который позволяет максимизировать скорость передачи данных. В случае возникновения проблем затем обеспечивает защиту дополнительный блок try-catch, который в случае разрыва вызывает функцию отмены, тем самым правильно завершая обработку. Важным примечанием относительно переноса является то, что подлежащие передаче элементы, такие как продолжить_на_construction_stage, могут быть переданы только в том случае, если соответствующее свойство «Заданный» было установлено на «true» (continue_on_construction_stageStecification). Не все элементы имеют такое свойство «Заданное», но там, где оно доступно, его необходимо учитывать.

Заключение

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


Автор

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

Скачивания