### ===================================================================================================================
### Functionality for layers
### ===================================================================================================================
# Copyright ©VIIA 2024
### ===================================================================================================================
### 1. Import modules
### ===================================================================================================================
# General imports
from __future__ import annotations
from typing import TYPE_CHECKING, Optional, List, Union
import re
# References for functions and classes in the rhdhv_fem package
from rhdhv_fem.groups import Layer
# References for functions and classes in the viiaPackage
if TYPE_CHECKING:
from viiapackage.viiaStatus import ViiaProject
### ===================================================================================================================
### 2. Function to create layers for VIIA
### ===================================================================================================================
[docs]def viia_create_layer(project: ViiaProject, name: str, shapes: Optional[List] = None) -> Layer:
"""
Function to create a layer in the class 'Layer' and add it to the project. The VIIA naming convention is applied.
Only layers with names 'F', 'N0', 'N1' etc. and 'B1', 'B2' etc. are allowed.
Input:
- project (obj): Project object containing collections of fem objects and project variables.
- name (str): Name of the layer.
- shapes (list): List of shapes that belong the layer that is created. Default None.
Output:
- Returns the object created in the 'Layer' class.
- The Layer is added to the project collections.
"""
if re.match('^N', name) and all(char.isdigit() for char in name[1:]):
name = f'N{int(name[1:])}'
elif re.match('^B', name) and all(char.isdigit() for char in name[1:]):
name = f'B{int(name[1:])}'
elif name == 'F':
pass
else:
raise ValueError(f"ERROR: Name for the layer '{name}' does not comply to naming convention VIIA.")
# Check if layer already exists
layer = project.find(description=name, collection='layers')
if isinstance(layer, list):
layer = layer[0]
# Create layer if it does not exist
if layer is None:
return project.create_layer(name=name, shapes=shapes)
# Add shapes to layer
if shapes:
layer.add_shapes(shapes)
return layer
### ===================================================================================================================
### 3. Function to get (specific) layers for VIIA
### ===================================================================================================================
[docs]def viia_get_layers(project: ViiaProject, names: bool = False) -> Union[List[Layer], List[str]]:
"""
This function gets the layers from the project and orders them following the VIIA naming convention. Layers start
with the foundation (layer 'F'), basements in reverse order (the deepest one has the highest number), (layer 'B2',
'B1'), and the normal building layers starting with the ground floor (layer 'N0', 'N1' etc.).
Input:
- project (obj): Project object reference containing collections of fem objects and project variables.
- names (bool): Optional input to get the names of the layers in the list. Default value False, returning a list
with the layer objects ordered.
Output:
- Returns list of layers ordered for VIIA from bottom up as list of layer objects or layer names.
"""
layer_dictionary = {layer.name: layer for layer in project.collections.layers}
if names:
return \
sorted([key for key in layer_dictionary.keys() if 'F' in key]) + \
sorted([key for key in layer_dictionary.keys() if 'B' in key], reverse=True) + \
sorted([key for key in layer_dictionary.keys() if 'N' in key])
return \
sorted([value for key, value in layer_dictionary.items() if 'F' in key], key=lambda x: x.name) + \
sorted([value for key, value in layer_dictionary.items() if 'B' in key], key=lambda x: x.name, reverse=True) + \
sorted([value for key, value in layer_dictionary.items() if 'N' in key], key=lambda x: x.name)
[docs]def viia_get_top_layer(project: ViiaProject, name: bool = False) -> Union[Layer, str]:
"""
This function determines the top layer of the structure, following VIIA naming convention.
Input:
- project (obj): Project object reference containing collections of fem objects and project variables.
- name (bool): Optional input to get the name of the layer. Default value False, returning the layer object.
Output:
- Returns the top layer of the building as layer object or the name of that layer as string.
"""
if name:
return viia_get_layers(project=project)[-1].name
return viia_get_layers(project=project)[-1]
def viia_get_ground_floor_layer(project: ViiaProject) -> Optional[Layer]:
"""
This function finds the ground floor layer ('N0'), following VIIA naming convention.
Input:
- project (obj): Project object reference containing collections of fem objects and project variables.
Output:
- Returns the ground floor layer of the building as layer object, if it is present.
"""
for layer in project.collections.layers:
if layer.name == 'N0':
return layer
return None
[docs]def viia_get_highest_layer(
project: ViiaProject, layer1: Layer, layer2: Layer, name: bool = False) -> Union[Layer, str]:
"""
This function determines the highest layer of the two layers received, following VIIA naming convention.
Input:
- project (obj): Project object reference containing collections of fem objects and project variables.
- layer1 (obj): Object reference of the first layer.
- layer2 (obj): Object reference of the second layer.
- name (bool): Optional input to get the name of that layer. Default value False, returning the layer object.
Output:
- Returns the highest layer or name of the requested layer objects.
"""
if not isinstance(layer1, Layer) or not isinstance(layer2, Layer):
raise ValueError("ERROR: Comparing two layers requires to provide to layer objects.")
layers = viia_get_layers(project=project)
if layers.index(layer1) < layers.index(layer2):
if name:
return layer2.name
return layer2
if name:
return layer1.name
return layer1
### ===================================================================================================================
### 4. Function to check if layers in the model comply for usage in viiaPackage
### ===================================================================================================================
[docs]def viia_check_layers(project: ViiaProject) -> True:
"""
This function checks if the layers comply. It checks if the required layers are present, and if no layers are
missing between others.
Input:
- project (obj): Project object reference containing collections of fem objects and project variables.
Output:
- Returns True if the layers in the model comply.
- Raises error if any layer is missing.
"""
# Get layers from project, ordered for VIIA naming convention
layers = viia_get_layers(project=project, names=True)
# Check if first layer is the foundation layer
if layers[0] != 'F':
raise ValueError("ERROR: The foundation is missing, please add foundation layer to your model.")
# Check for basements
i = 1
if len(layers) > i and 'B' in layers[i]:
layer = int(layers[i].replace('B', ''))
i += 1
while layer > 1:
if 'B' not in layers[i] or int(layers[i].replace('B', '')) != layer - 1:
raise ValueError(f"ERROR: The basement layer B{layer - 1} is missing, please add layer to your model.")
layer -= 1
i += 1
# Check for ground level
if len(layers) > i and 'N0' != layers[i]:
raise ValueError(f"ERROR: The ground layer N0 is missing, please add layer to your model.")
# Check for layers up
i += 1
layer = 1
while len(layers) > i:
if int(layers[i].replace('N', '')) != layer:
raise ValueError(f"ERROR: The layer N{layer} is missing, please add layer to your model.")
layer += 1
i += 1
return True
### ===================================================================================================================
### 5. End of script
### ===================================================================================================================