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
Dos requisitos anteriores, segue-se que apenas a altura do piso tem de ser especificada e um elemento, como um nó, deve então encontrar-se com a sua coordenada z acima da altura inferior do piso e até um máximo ou igual à altura atual do piso troca de dados.
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 com base nas alturas.
Para as linhas, podem ser utilizados os 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 se encontram nas linhas e que podem ser atribuídas antes das mesmas, 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.
Integrador
O programa utiliza como base um modelo do pacote NuGet Dlubal.RFEMWebServiceLibrary. Pode descobrir como instalá-lo aqui:
https://github.com/Dlubal-Software/Dlubal_CSharp_ClientPrimeiro, o modelo ativo é ligado da seguinte forma:
- code.csharp#
...
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 = nulo;
- }
- }
- 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));
...
- /código#
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 aplicação ser ligada com sucesso, 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:
- code.csharp#
...
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("");
...
- /código#
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 (campo/vetor incluindo elementos) é do tipo local_objeto e 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. Segue-se um ciclo através dos objetos selecionados e, assim que um elemento é do tipo de nó, é realizada uma pesquisa entre os nós para este nó e a sua coordenada z é introduzida na matriz andar_alturas. A matriz é aumentada por um elemento para cada coordenada encontrada:
- code.csharp#
...
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;
...
- /código#
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 utilizando Inverter. Inicialmente, definiu-se que a fundação e o rés do chão contavam como um piso; razão pela qual o primeiro elemento nos vãos dos pisos foi removido.
Em seguida, os restantes elementos, tais como linhas, barras e superfícies são transferidos:
- code.csharp#
...
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("");
...
- /código#
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, desde a parte inferior do edifício até ao topo, 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:
- code.csharp#
...
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;
}
}
}
...
- /código#
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). O comentário é utilizado aqui porque é para ser avaliado o número do piso, mas não as coordenadas z no texto seguinte.
Isto é evidente quando observamos o ciclo sobre as linhas:
- code.csharp#
...
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])
}
...
- /código#
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. O número do piso deste nó é retirado 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:
- code.csharp#
...
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]);
}
...
- /código#
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:
- code.csharp#
...
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;
}
}
...
- /código#
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.
Conclusão
Devido à versatilidade da interface Serviço web e API, é possível automatizar várias entradas manuais complexas. 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.