Source code for viiapackage.pictures.result_pictures.helper_functions.get_plot_shapes

### ===================================================================================================================
###  FUNCTION: Get shapes for the result picture
### ===================================================================================================================
# Copyright ©VIIA 2024

### ===================================================================================================================
###   1. Import modules
### ===================================================================================================================

# General imports
from __future__ import annotations
from copy import deepcopy
from typing import TYPE_CHECKING, List, Union, Dict

# References for functions and classes in the rhdhv_fem package
from rhdhv_fem.shapes import Shapes, Reinforcements
from rhdhv_fem.connections import Connections, Interface
from rhdhv_fem.materials import Timber, ReinforcementSteel
from rhdhv_fem.fem_math import fem_parallel_vectors, fem_horizontal_vector_in_plane

# References for functions and classes in the viiaPackage
if TYPE_CHECKING:
    from viiapackage.viiaStatus import ViiaProject


### ===================================================================================================================
###   2. Function to get the shapes for the result picture based on the scope
### ===================================================================================================================
#
[docs]def viia_update_plot_config(project: ViiaProject, current_config: dict, component: str): """ Helper function to update the result plot config with the correct dnb file name.""" result_plot_config = deepcopy(current_config) result_plot_config.update({ 'component': component, 'output_filename': current_config['output_filename'].replace('SXXX', f'{project.name}_v{project.version}') + '.dnb', 'output_block_name': current_config['output_filename'].replace('SXXX_', '')}) return result_plot_config
[docs]def viia_get_scope_shape_sets(project: ViiaProject, scope: str, pic_type: str) \ -> Union[Dict[str, List[Shapes]], Dict[str, Dict[str, List[Union[Shapes, Connections]]]]]: """ This function collects the required shape-sets for the result pictures based on the scope definition. For example the 'NoRoof' scope will hide the roof shapes for the result pictures. Input: - project (obj): VIIA project object containing collections of fem objects and project variables. - scope (str): The scope that defines the selection of shapes to be visible on the result picture. Select from 'building', 'noroof', 'floors-interstorey', 'walls-storey', 'beams-material-storey', 'columns-material-storey', 'floors-material-storey', 'interfaces-storey', 'floors-timber-storey', 'roofs-timber' or 'reinforcements-storey'. Output: - Returns list of shapes, or dictionary with subdivisions for different sets of shapes or connections. In the last case multiple pictures are to be generated based on scope. """ def lines_material_storey(lines_layer: Dict[str, List[Shapes]]): shapes = {} for layer, lines in lines_layer.items(): shapes_material = {} for line in lines: line_mat = line.material.name.split('-DENSIT')[0] if line_mat not in shapes_material: shapes_material[line_mat] = [] shapes_material[line_mat].append(line) shapes[layer] = shapes_material return shapes def surfaces_material_storey(surfaces_layer: Dict[str, List[Shapes]]): shapes = {} for layer, surfaces in surfaces_layer.items(): # Group shapes by material shapes_material = {} for surface in surfaces: # For timber floor, make a distinction of plate or others, since plate has a higher capacity if isinstance(surface.material, Timber) and 'PLATEN' not in surface.material.name: material_key = 'LIN-HOUT' elif isinstance(surface.material, Timber) and 'PLATEN' in surface.material.name: material_key = 'PLATEN' # Additional line for reinforcement elif isinstance(surface.material, ReinforcementSteel): material_key = 'WAPENING' else: material_key = surface.material.name.split('-DENSIT')[0] # Check if key already present in shapes[layer]. If not, make new key in shapes[layer] if material_key not in shapes_material: shapes_material[material_key] = [] shapes_material[material_key].append(surface) # For loop to split shape sets by geometry if required shapes_material_geometry = {} for original_key, shape_set in shapes_material.items(): shape_geometries = set([shape.geometry.name for shape in shape_set]) # Check if only one shape geometry is present if len(shape_geometries) == 1: shapes_material_geometry[original_key] = shape_set continue # Check if this shape set has timber shapes if isinstance(shape_set[0].material, Timber): shapes_material_geometry[original_key] = shape_set continue # If multiple shape geometries, and no timber floors, split up shape set by geometry # Make a unique key per shape geometry for shape_geometry in shape_geometries: material_geometry_key = original_key + '-' + shape_geometry shapes_material_geometry[material_geometry_key] = [] # Add shape in original shape set to the right new key for shape in shape_set: shapes_material_geometry[original_key + '-' + shape.geometry.name].append(shape) shapes[layer] = shapes_material_geometry return shapes # Check input if not isinstance(scope, str): raise ValueError("ERROR: Scope to select the shapes for the result picture should be a string.") scope = scope.lower() if scope == 'building': # All shapes in the building return {'building': [shape for shape in project.collections.shapes if not isinstance(shape, Reinforcements)]} elif 'reinforcements-storey' in scope: # All shapes and reinforcements in the building per layer reinforcement_layer = {layer.name: layer.reinforcements for layer in project.viia_get_layers() if layer.name[0] == 'N'} return surfaces_material_storey(surfaces_layer=reinforcement_layer) elif 'noroof' in scope: # All shapes excluding the roof shapes (instances of Roof class) return {'no_roof': [ shape for shape in project.collections.shapes if shape not in project.collections.roofs and not isinstance(shape, Reinforcements)]} elif 'noroof' not in scope and 'mode' in scope: # All shapes excluding the roof shapes (instances of Roof class) return {scope: [shape for shape in project.collections.shapes if not isinstance(shape, Reinforcements)]} elif 'floors-interstorey' in scope: # Collect the floors per layer, excluding foundation and basements return {layer.name: layer.floors for layer in project.viia_get_layers() if layer.name[0] == 'N'} elif 'walls-storey' in scope and 'CrackWidth' in pic_type or 'Static' in pic_type: # Collect the walls per layer, excluding foundation and basements return {layer.name: layer.walls for layer in project.viia_get_layers() if layer.name[0] == 'N'} elif 'walls-storey' in scope and 'Dynamic' in pic_type: # Collect the walls per layer, excluding foundation and basements shape_sets = {} for layer in project.viia_get_layers(): if layer.name[0] == 'N': shape_sets[layer.name] = {} shape_x = [ wall for wall in layer.walls if fem_parallel_vectors( vector_1=fem_horizontal_vector_in_plane( surface=[node.coordinates for node in wall.get_nodes()], precision=project.check_precision), vector_2=[1.0, 0, 0], precision=project.check_precision)] shape_y = [ wall for wall in layer.walls if fem_parallel_vectors( vector_1=fem_horizontal_vector_in_plane( surface=[node.coordinates for node in wall.get_nodes()], precision=project.check_precision), vector_2=[0, 1.0, 0], precision=project.check_precision)] shape_sets[layer.name][f'{layer.name}_x'] = shape_x shape_sets[layer.name][f'{layer.name}_y'] = shape_y return shape_sets elif 'beams-material-storey' in scope: # Collect the beams per layer, excluding foundation and basements # Sub-divide for different beam materials beams_layer = {layer.name: layer.beams for layer in project.viia_get_layers() if layer.name[0] == 'N'} return lines_material_storey(lines_layer=beams_layer) elif 'columns-material-storey' in scope: # Collect the columns per layer, excluding foundation and basements # Sub-divide for different column materials columns_layer = {layer.name: layer.columns for layer in project.viia_get_layers() if layer.name[0] == 'N'} return lines_material_storey(lines_layer=columns_layer) elif 'floors-material-storey' in scope: # Collect the floors per layer, excluding foundation and basements # Sub-divide for different floor materials floors_layer = {layer.name: layer.floors for layer in project.viia_get_layers() if layer.name[0] == 'N'} return surfaces_material_storey(surfaces_layer=floors_layer) elif 'floors-timber-storey' in scope: # Collect the timber floors per layer, excluding foundation and basements # Sub-divide per timber material floors_layer = {layer.name: layer.floors for layer in project.viia_get_layers() if layer.name[0] == 'N'} timber_floors = {} for layer, floors in floors_layer.items(): timber_floors[layer] = {} for floor in floors: if isinstance(floor.material, Timber): # For timber floors, make a distinction of plate or others, since plate has a higher capacity key = 'PLATEN' if 'PLATEN' in floor.name else 'LIN-HOUT' if key not in timber_floors[layer]: timber_floors[layer][key] = [] timber_floors[layer][key].append(floor) return timber_floors elif 'roofs-timber' in scope: # Collect the roofs per timber material timber_roofs = {'roof': {}} for roof in project.collections.roofs: if isinstance(roof.material, Timber): # For timber roofs, make a distinction of plate or others, since plate has a higher capacity key = 'PLATEN' if 'PLATEN' in roof.name else 'LIN-HOUT' if key not in timber_roofs['roof']: timber_roofs['roof'][key] = [] timber_roofs['roof'][key].append(roof) return timber_roofs elif 'roofs-material-storey' in scope: # Collect the roofs per layer, excluding foundation and basements # Sub-divide for different floor materials roofs_layer = {layer.name: layer.roofs for layer in project.viia_get_layers() if layer.name[0] == 'N'} return surfaces_material_storey(surfaces_layer=roofs_layer) elif 'interfaces-storey' in scope: connections_layer = { layer.name: layer.get_connections() for layer in project.viia_get_layers()} # Filter for interfaces only for layer, connections in connections_layer.items(): for connection in reversed(connections): if not isinstance(connection, Interface): connections.remove(connection) # Filter connections only in this layer or connecting to lower layer ordered_layers = [layer for layer, connections in connections_layer.items()] for enum, connection_layer in enumerate(connections_layer.items()): if enum == len(connections_layer) - 1: break for connection in reversed(connection_layer[1]): # Check if there are any connection between basement/foundation with the N0 level. if enum + 1 < len(ordered_layers): if ordered_layers[enum + 1] != 'N0' and connection_layer[0] in ['F', 'B']: if connection.connecting_shapes['source_connecting_shape'].layer.name == 'N0' or \ connection.connecting_shapes['target_connecting_shape'].layer.name == 'N0': connection_layer[1].remove(connection) # Check if the layer of the connecting shapes is at a higher level or not. if connection.connecting_shapes['source_connecting_shape'].layer.name == \ ordered_layers[enum + 1] or \ connection.connecting_shapes['target_connecting_shape'].layer.name == \ ordered_layers[enum + 1]: connection_layer[1].remove(connection) # Filter line and point interfaces connection_sets_line = {} connection_sets_point = {} for layer, connections in connections_layer.items(): for connection in connections: # Collect only line interfaces if 'LIJN' in connection.name: if f'{layer}_LIJN' not in connection_sets_line: connection_sets_line[f'{layer}_LIJN'] = [] connection_sets_line[f'{layer}_LIJN'].append(connection) elif 'PUNT' in connection.name: if f'{layer}_PUNT' not in connection_sets_point: connection_sets_point[f'{layer}_PUNT'] = [] connection_sets_point[f'{layer}_PUNT'].append(connection) if 'line' in scope.lower(): return connection_sets_line elif 'point' in scope.lower(): return connection_sets_point else: raise ValueError(f"ERROR: You need to specify if {scope} is a point interface or line interface.") raise NotImplementedError(f"ERROR: '{scope}' is not a recognised result scope definition.")
### =================================================================================================================== ### 3. End of script ### ===================================================================================================================