911x
001825
2023-08-09

Serviço web e API para a análise das fases de construção

Quando se trata de calcular estruturas regulares, a entrada de dados geralmente não é complicada, mas sim demorada. Entrada automática de dados permite poupar tempo valioso. A tarefa descrita no presente artigo trata de considerar os andares de uma casa como fases individuais de construção. A introdução deveria ser realizada utilizando um programa em C# para que o utilizador não tenha de introduzir manualmente os elementos dos pisos individuais.

Requisitos

O seguinte programa é executado nas seguintes condições:

  • Os planos dos pisos são paralelos ao plano xy.
  • O modelo não pode conter elementos que se extendem por vários pisos (por exemplo, uma superfície de fachada com dois ou mais pisos).
  • A fundação e o rés do chão pertencem ao piso zero.
  • Os sólidos não são considerados.
  • Apenas são utilizadas superfícies planas.
  • O eixo z está direccionado na direção da aceleração da gravidade ("para baixo").

Fundamentação teórica

Com base nos requisitos, fica claro que apenas a altura do piso deve ser especificada, providenciando um elemento, como um nó, com a sua coordenada z acima da altura inferior do piso e com um máximo igual ou superior a altura de piso relevante. 
Portanto, o utilizador tem de selecionar uma série de nós que são representativos para a altura do piso. As coordenadas z e, consequentemente, a altura do piso podem ser determinadas através de um ciclo.
A seguir, os pisos são atribuídos a todos os nós através das alturas.
Para as linhas, é possível recorrer aos pisos dos nós. Se uma linha começa num teto e termina no teto que está por cima, deve ser atribuída ao teto superior. Portanto, a linha é atribuída ao piso mais alto que pode ser encontrado nos seus nós.
Uma vez que as barras estão nas linhas e que podem ser atribuídas previamente, a barra tem o mesmo piso que a sua linha.
O mesmo se aplica às superfícies. É determinado o piso mais alto dos nós correspondentes.
Se todos os elementos de um piso tiverem sido atribuídos, as fases de construção podem ser criadas a partir da lista dos pisos.

Memorizado

O programa utiliza como base um modelo do pacote NuGet Dlubal.RFEMWebServiceLibrary. Pode descobrir como instalá-lo aqui:

Primeiro, o modelo ativo é ligado da seguinte forma:


            

...
Configuração de aplicação #region
try
{
    aplicação_informacaoInformação da aplicação;
    try
    {
        ://liga à aplicação RFEM6 ou RSTAB9
        aplicação =new AplicaçãoCliente(ligação, endereço);

    }
    captura (exceção de exceção)
    {
        if (aplicação != zero)
        {
            if (application.State != CommunicationState.Faulted)
            {
                aplicação.Fechar();
            }
            else
            {
                aplicação.Abort();
            }

            aplicação = zero;
        }
    }
    finally
    {
        AplicaçãoInfo = aplicação.get_information();
        Consola.WiteLine("Nome: {0}, Versão:{1}, Tipo: {2}, idioma: {3} ", AplicaçãoInfo.name, AplicaçãoInfo.version, AplicaçãoInfo.type, AplicaçãoInfo.language_name);
    }
    #regiãofinal

    https://www.dlubal.com/pt/modelo-ativo-
    string modelUrl = aplicação.get_active_model();

    ://liga ao modelo RFEM6/RSTAB9
    Modelo do clienteModelo = novo ModelClient(Binding, novo EndpointAdwww(modelUrl));
...


Para um melhor tratamento de erros, é utilizado um bloco "try-catch" em todo o código-fonte na função principal. Dentro deste bloco, a aplicação é ligada primeiro, o que é feito novamente num blocotry-catch. Após a ligação bem-sucedida da aplicação, o modelo atualmente ativo (em primeiro plano no RFEM 6) é ligado através do método get_active_model. Se ocorrer algum problema, o bloco "try-catch" externo entra em ação.
Uma vez que todos os nós, linhas, barras e superfícies têm de ser analisados, faz sentido obter todos os elementos do RFEM. Para obter o número dos respetivos elementos, são lidos primeiro os números dos objetos de todas as categorias. A seguir, os respetivos objetos podem depois ser transferidos através dos seus números:


            

...
int[] node_nums = model.get_all_object_numbers(object_types.E_OBJECT_TYPE_NODE, 0);
int[] linear_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);

Consola.WiteLine("1. Obter todos os nós:"); nó[] nds = novo nó[node_nums.Length]; for (int i = 0; i < node_nums.Length; ++i) { nds[i] = model.get_node(node_nums[i]); se ((i%10)==0) Consola.Wite("+"); } Consola.WsiteLine(""); ...

Para dar ao utilizador uma visão geral da duração do processo, é escrito um "+" na consola a cada 10 elementos.
Antes de transferir os outros elementos, a altura do piso é determinada no próximo passo. Primeiro, tem de ler os objetos selecionados. A matriz transferida (matriz/vetor com elementos) do tipo local_objeto contém todos os objetos selecionados com o seu tipo e número. Desta forma, os nós podem ser filtrados num ciclo. Uma vez que todos os nós já estão disponíveis, é possível determinar as coordenadas z desses nós no mesmo ciclo. Existe um ciclo que percorre os objetos selecionados e, assim que um elemento é do tipo de nó, o nó é pesquisado nos nós e a sua coordenada z é introduzida na matriz andares_heights. Por cada coordenada encontrada, é adicionado um elemento à matriz:


            

...
Consola.WiteLine("2. Obter os nós selecionados");
https://www.dlubal.com/pt/produtos selecionados
Object_location[] obj_locs = model.get_all_selected_objects();

https://www.dlubal.com/pt
duplo[] piso_heights = novo duplo[1];
folearning (object_location obj em obj_locs)
{
	if (obj.type == Object_types.E_OBJECT_TYPE_NODE)
	{
		for (int i = 0; i < nds.Length; ++i)
		{
			if (nds[i].no == obj.no)
			{
				basis_heights[flow_heights.Length - 1] = nds[i].coordinate_3;
				Array.Resize(ref basis_heights, basis_heights.Length + 1);
				rotura;
			}
		}
	}
}
Array.Resize(ref basis_heights, basis_heights.Length - 1);

https://www.dlubal.com/pt
https://www.dlubal.com/pt/eixo-z- é negativo, o valor mais positivo é o solo
Array.Sort(chapa_alturas);
Array.Reverso(chão_alturas);
//#o solo e o primeiro nível são um, remover a primeira entrada
duplo[] tmp_arr = novo duplo[flow_heights.Length - 1];
Array.Copy(flow_heights, 1, tmp_arr, 0, surface_heights.Length - 1);

andar_alturas = zero;
andar_alturas = tmp_arr;
...


Uma vez que as coordenadas z não estão na ordem correta, a matriz é primeiro ordenada por tamanho. A coordenada z, no entanto, está na direção negativa e, portanto, a ordenação tem de ser invertida através de Inverter. Inicialmente, foi determinado que a fundação e a laje do rés do chão contas como um piso, pelo que o primeiro elemento nas alturas do piso é removido.
Num próximo passo, os elementos restantes, tais como linhas, barras e superfícies são transferidos:


            

...

Consola.WiteLine("3. Obter todas as linhas:"); linha[] lns = nova linha[line_nums.Length]; for (int i = 0; i < linear_nums.Length; ++i) { lns[i] = model.get_line(line_nums[i]); se ((i % 10) == 0) Consola.Wite("+"); } Consola.WsiteLine(""); https://www.dlubal.com/pt Consola.WiteLine("4. Obter todas as barras:"); barra[] mems = nova barra[member_nums.Length]; for (int i = 0; i < Member_nums.Length; ++i) { mems[i] = model.get_member(member_nums[i]); se ((i % 10) == 0) Consola.Wite("+"); } Consola.WsiteLine("");

Consola.WiteLine("5. Obter todas as superfícies:"); superfície[] srfs = nova superfície[surface_nums.Length]; for (int i = 0; i < surface_nums.Length; ++i) { srfs[i] = model.get_surface(surface_nums[i]); se ((i % 10) == 0) Consola.Wite("+"); } Consola.WsiteLine(""); ...

Para ordenar os elementos em pisos individuais, são criadas primeiro listas bidimensionais. A lista nds_flow_numbers tem os pisos como primeira dimensão e os números dos nós do piso como segunda dimensão. Em primeiro lugar, o loop seguinte percorre todos os nós e tem um sub-loop que percorre toda a altura dos pisos. Para cada nó, o programa verifica de baixo para cima no edifício se a coordenada Z se encontra dentro da altura do piso. Devido a imprecisões numéricas, foi subtraída uma tolerância de 1 mm:


            

...
https://www.dlubal.com/pt/apoio-ao-cliente
Consola.WiteLine("6. Percorra os nós e obtenha o seu piso");
for (int i = 0; i < nds.Length; ++i)
{
	for (int j = 0; j < steel_heights.Length; ++j)
	{
		if (nds[i].coordinate_3 >= basis_heights[j] - 0,001)
		{
			nds[i].comment = j.ToString();
			https://www.dlubal.com/pt/produtos/modulos-no-rstab-8.aspx
			nds_flow_numbers[j].Add(nds[i].no);
			https://model.set_node(nds[i]);
			rotura;
		}
	}
}
...


Assim que um nó estiver dentro da região especificada, o número do piso é introduzido como comentário e o número do nó é adicionado à lista. Neste momento, também seria possível transferir o comentário para o RFEM (comentado). A razão pela qual o comentário é utilizado é porque a seguir não são as coordenadas z que devem ser avaliadas, mas sim o número do piso. Isto é evidente quando observamos o ciclo sobre as linhas:


            

...
https://www.dlubal.com/pt/apoio-ao-cliente
Consola.WiteLine("7. Percorra as linhas e obtenha o seu piso");
for (int i = 0; i < lns.Length; ++i)
{
	

int[] ln_node_nums = lns[i].definition_nodes; Int32 piso_máx = 0; https://www.dlubal.com/pt/apoio-ao-cliente for (int j = 0; j SMALLERTLAN ln_node_nums.Length; ++j) { https://www.dlubal.com/pt/apoio-ao-cliente for (int l = 0; l SMALLERTTHA nds.Length; ++l) { if (nds[l].no == ln_node_nums[j]) { Int32 piso = Int32.Parse(nds[l].comment); if (piso > piso_máx) { piso_máx = piso; rotura; } } } } https://www.dlubal.com/pt lns[i].comment = basis_max.ToString(); lns_flow_numbers[flow_max].Add(lns[i].no); ''/model.set_line(lns[i]'') } ...

O loop passa por todas as linhas e tem um sub-loop, que passa por todos os nós da linha. Dentro deste sub-loop, existe outro loop a percorrer todos os nós para encontrar o nó que corresponde ao número do nó a partir da linha. Fora deste nó, é lido o número do piso a partir do comentário. Conforme já mencionado nas bases teóricas, basta determinar o número do piso mais alto. Este número é então armazenado como número do piso no comentário da linha e o número da linha é inserido na lista.
As barras recebem os mesmos números de piso das linhas nas quais se encontram. Assim, é necessário um ciclo sobre todas as barras com um sub- ciclo sobre todas as linhas. Assim que o número da linha corresponder ao número da barra, a barra obtém a altura do piso como um comentário e o número é adicionado à lista:


            

...
https://www.dlubal.com/pt/barras-tor5
Consola.WiteLine("8. Percorra as barras e obtenha os seus pisos");
for (int i = 0; i < mems.Length; ++i)
{
	https://www.dlubal.com/pt
	int mem_ln_num = mems[i].line;

	https://www.dlubal.com/pt/apoio-ao-cliente
	for (int j = 0; j < lns.Length; ++j)
	{
		if (lns[j].no == mem_ln_num)
		{
			mems[i].comment = lns[j].comment;
			mems_flow_numbers[Int32.Parse(lns[j].comment)].Add(mems[i].no);
			rotura;
		}
	}

}
https://www.dlubal.com/pt/superfícies, obter as suas linhas e definir o seu piso
Consola.WiteLine("9. Percorra as superfícies e obtenha o seu piso");
for (int i = 0; i < srfs.Length; ++i)
{
	https://www.dlubal.com/pt
	int[] srf_line_nums = srfs[i].limite_lines;
	Int32 piso_máx = 0;
	https://www.dlubal.com/pt/linhas-de-superficie
	for (int j = 0; j < srf_line_nums.Length; ++j)
	{
		https://www.dlubal.com/pt/apoio-ao-cliente
		for (int l = 0; l SMALLERTTHA lns.Length; ++l)
		{
			if (lns[l].no == srf_line_nums[j])
			{
				Int32 piso = Int32.Parse(lns[l].comment);
				if (piso > piso_máx)
				{
					piso_máx = piso;
					rotura;
				}
			}
		}

	}
	https://www.dlubal.com/pt
	srfs[i].comment = basis_max.ToString();
	srfs_flow_numbers[flow_max].Add(srfs[i].no);

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

}
...


O procedimento nas superfícies é idêntico ao das linhas. Existe um ciclo sobre as superfícies com o ciclo parcial sobre as suas linhas de contorno. O piso mais alto a partir da linha de contorno torna-se o número do piso da superfície.
Após ordenar todos os elementos pelos pisos, é necessário criar as fases de construção. É criada uma fase de construção para cada piso, pelo que é feito um loop sobre a altura do piso:


            

...
Consola.WiteLine("10. Definir fases de construção");
try
{
	model.begin_modification("definir fases de construção");
	https://www.dlubal.com/pt
	for (int i = 0; i < steel_heights.Length; ++i)
	{
		construção_stage cstg = novo construção_stage();

		cstg.no = i + 1;
		cstg. continue_on_construction_stage = i;
		cstg. continue_on_construction_stageSpecification = verdadeiro;

		cstg.are_members_enabled_to_modify = verdadeiro;
		cstg.are_members_enabled_to_modifySpecified = verdadeiro;
		cstg.added_members = mems_structure_numbers[i].ToArray();
		cstg.active_members = cstg.added_members;

		cstg.are_surfaces_enabled_to_modify = verdadeiro;
		cstg.are_surfaces_enabled_to_modifySpecified = verdadeiro;
		cstg.added_surfaces = srfs_flow_numbers[i].ToArray();
		cstg.active_surfaces = cstg.added_surfaces;

		cstg.name = "chão" + i;
		cstg.user_ Defined_name_enabled = verdadeiro;
		cstg.user_ Defined_name_enabledSpecification = verdadeiro;

		model.set_construction_stage(cstg);

	}
}
captura (exceção de exceção)
{
	model.cancel_modification();
	Consola.WsiteLine("Acontece algo ao criar a geometria" + excessão.Message);
	arrasto;
}
finally
{
	try
	{
		model.finish_modification();
	}
	captura (exceção de exceção)
	{
		Consola.WritELine("Acontece algo ao terminar a criação da geometria" + excessão.Message);
		arrasto;
	}
}
...


Para criar elementos no RFEM, é utilizado adicionalmente um bloco begin_modification/finish_modification de forma a maximizar a velocidade de transferência. Se surgirem problemas, um bloco "try-catch" adicional providencia proteção, o qual chama cancel_modification no caso de uma interrupção, terminando assim o processamento corretamente. Uma nota importante sobre a transferência é que elementos a serem transferidos, tais como continue_on_construction_stage, só podem ser transferidos se a correspondente propriedade "Specified" tiver sido definida como "true" ( continue_on_construction_stageSpecified). Nem todos os elementos têm esta propriedade "especificada", mas deve ser considerada, caso esteja disponível.

Resumo

Devido à versatilidade da interface Serviço web e API, é possível automatizar um número de entradas que seriam muito demoradas se fossem feitas manualmente. No presente exemplo, a entrada para o módulo Análise das fases de construção é automatizada, o que também serve como marcador de posição para muitos outros módulos e opções. Assim sendo, existem apenas alguns limites para a sua criatividade para soluções que poupam tempo e seguirão-se muitos exemplos.


Autor

O Eng. Günthel opera na área do apoio técnico para clientes.

Downloads