### ===================================================================================================================
### CLASS: RefWallOOP
### ===================================================================================================================
# Copyright ©VIIA 2024
### ===================================================================================================================
### 1. Import modules
### ===================================================================================================================
# General imports
from typing import Dict, Union, Optional, List
# References for functions and classes in the rhdhv_fem package
from rhdhv_fem.shapes import Wall
from rhdhv_fem.fem_math import fem_perpendicular_vectors, fem_is_close
from rhdhv_fem.shapes.surfaces.roof import Roof
from rhdhv_fem.fem_config import Config
# References for functions and classes in the viiaPackage
from viiapackage.viiaGeneral import _viia_find_upper_floor_of_wall
from viiapackage.reference_approach.reference_wall.current_wall import CurrentWall
from viiapackage.reference_approach.reference_wall.ref_wall import RefWall
### ===================================================================================================================
### 2. Ref wall oop class
### ===================================================================================================================
[docs]class RefWallOOP(RefWall):
""" Class for the data of the reference walls. These are compared to the current wall."""
# Class property for the current wall referenced
current_wall: CurrentWall = None
[docs] def __init__(self, wall: Wall, measures: str, segment_width: float, segment_nr: Optional[int] = None):
"""
Input:
- wall (Wall): Object reference of the wall from the reference object. Should be an instance of Wall class.
- measures (str): All the measures in string format that have been applied to the object.
- segment_width (float): Width of the wall between two lateral supporting walls, in [m]. In case of no
segmentations due to supporting walls, the total width of the wall is used.
- segment_nr (int): Number of the segment of the wall (starting at 1). Default value None, which is the case
if the wall is not split.
"""
# Name
if segment_nr:
name = f'{wall.name} (Segment {segment_nr})'
else:
name = wall.name
# Segments
self.__segment_nr = segment_nr
# Openings
if wall.openings is None:
self.__openings = 0
else:
self.__openings = len(wall.openings)
# Size of openings
self.__size_of_openings = self.calc_size_of_openings(wall)
# Wall vector
self.__wall_vector = wall.contour.get_normal_vector()
# Floor spanning direction
self.__floor_spanning_direction = self.calc_floor_spanning_direction(wall)
# Roof spanning direction
self.__roof_spanning_direction = self.calc_roof_spanning_direction(wall)
# Overburden load
self.__overburden_load = self.calc_overburden_load(wall)
super().__init__(wall=wall, measures=measures, name=name, width=segment_width)
@property
def score_thickness(self) -> float:
""" Method of 'RefWallOOP' to calculate score for comparison of the thickness of the walls."""
return max([100 - abs((self.thickness - self.current_wall.thickness / 1E3) /
self.current_wall.thickness / 1E3) * 100, 0])
@property
def score_width(self) -> float:
""" Method of 'RefWallOOP' to calculate score for comparison of the total length of the walls."""
return max([100 - abs((self.width - self.current_wall.width) / self.current_wall.width) * 100, 0])
@property
def score_height(self) -> float:
""" Method of 'RefWallOOP' to calculate score for comparison of the total height of the walls."""
return max([100 - abs((self.height - self.current_wall.height) / self.current_wall.height) * 100, 0])
@property
def score_density(self) -> float:
""" Method of 'RefWallOOP' to calculate score for comparison of the density of the walls."""
return max([100 - abs((self.density - self.current_wall.density) / self.current_wall.density) * 100, 0])
@property
def score_material(self) -> float:
""" Method of 'RefWallOOP' to calculate score for comparison of the material of the walls."""
# Check if materials are the same (and lin_check)
if self.current_wall.material in self.material:
if ('LIN' in self.current_wall.material) == ('LIN' in self.material):
return 100
return 50
return 0
@property
def score_wall_type(self) -> float:
""" Method of 'RefWallOOP' to calculate score for comparison of the wall-type (inner or facade) of the walls."""
if self.wall_type == self.current_wall.wall_type:
return 100
return 0
@property
def openings(self) -> int:
""" Method of 'RefWallOOP' to calculate the number of opening of each wall."""
return self.__openings
@property
def score_openings(self) -> float:
""" Method of 'RefWallOOP' to calculate score for comparison of the opening of the walls."""
if self.openings == self.current_wall.openings:
return 100
return 0
[docs] def calc_size_of_openings(self, wall) -> List[list]:
""" Method of 'RefWallOOP' to calculate the size of the opening(s) of each wall."""
opening_dimensions = []
if wall.openings:
for opening in wall.openings:
wall_opening_min_max = opening.get_min_max()
width = max([abs(wall_opening_min_max['x-max'] - wall_opening_min_max['x-min']),
abs(wall_opening_min_max['y-max'] - wall_opening_min_max['y-min'])])
height = abs(wall_opening_min_max['z-max'] - wall_opening_min_max['z-min'])
opening_dimensions.append([round(width, 2), round(height, 2)])
return opening_dimensions
@property
def size_of_openings(self) -> List[list]:
""" Method of 'RefWallOOP' to calculate the number of opening of each wall."""
return self.__size_of_openings
@property
def score_opening_size(self) -> float:
""" Method of 'RefWallOOP' to calculate score for comparison of the size of the opening of the walls."""
if self.current_wall.openings > 0:
if all(directions in self.size_of_openings for directions in self.current_wall.size_of_openings):
return 100
elif any(directions in self.size_of_openings for directions in self.current_wall.size_of_openings):
return 50
return 0
@property
def wall_vector(self):
""" Method of 'RefWallOOP' to determine the vector of the current wall."""
return self.__wall_vector
@property
def floor_spanning_direction(self) -> list:
""" Method of 'RefWallOOP' to determine the spanning direction of the floors."""
return self.__floor_spanning_direction
[docs] def calc_floor_spanning_direction(self, wall) -> list:
""" Method of 'RefWallOOP' to determine the spanning direction of the connected floors compared to the wall."""
#Connected floors
connected_floors = [floor for floor in _viia_find_upper_floor_of_wall(wall) if ('DUMMY' not in floor.name)]
floor_spanning_direction = []
if len(connected_floors) > 0:
for floor in connected_floors:
if 'BETON' in floor.name:
floor_spanning_direction.append('Perpendicular')
else:
floor_x_axis = floor.element_x_axis
floor_spanning_direction.append('Parallel' if fem_perpendicular_vectors(
floor_x_axis.vector, self.wall_vector) else 'Perpendicular')
return floor_spanning_direction
@property
def score_floor_spanning(self) -> float:
""" Method of 'RefWallOOP' to calculate score for comparison of the floor spanning compared to the walls."""
if self.current_wall.floor_spanning_direction in self.floor_spanning_direction:
return 100
return 0
@property
def roof_spanning_direction(self):
""" Method of 'RefWallOOP' to determine the spanning direction of the floors."""
return self.__roof_spanning_direction
[docs] def calc_roof_spanning_direction(self, wall) -> list:
""" Method of 'RefWallOOP' to determine the spanning direction of the connected roof compared to the wall."""
# Connected roofs
connected_roofs = [
shape for shape in wall.project.collections.shapes if
(shape is not wall and isinstance(shape, Roof) and wall.get_connecting_lines(shape))]
roof_spanning_direction = []
if len(connected_roofs) > 0:
for roof in connected_roofs:
roof_x_axis = roof.element_x_axis
roof_spanning_direction.append('Parallel' if fem_perpendicular_vectors(
roof_x_axis.vector, self.wall_vector) else 'Perpendicular')
return roof_spanning_direction
@property
def score_roof_spanning(self) -> float:
""" Method of 'RefWallOOP' to calculate score for comparison of the roof spanning compared to the walls."""
if self.current_wall.roof_spanning_direction in self.roof_spanning_direction:
return 100
return 0
@property
def overburden_load(self) -> float:
""" Method of 'RefWallOOP' to determine the spanning direction of the floor compared to the current wall."""
return self.__overburden_load
[docs] def calc_overburden_load(self, wall) -> float:
""" Method of 'RefWallOOP' to determine the spanning direction of the floor compared to the current wall."""
#Connected floors
connected_floors = [floor for floor in _viia_find_upper_floor_of_wall(wall) if ('DUMMY' not in floor.name)]
# Connected roofs
connected_roofs = [
shape for shape in wall.project.collections.shapes if
(shape is not wall and isinstance(shape, Roof) and wall.get_connecting_lines(shape))]
ov_load = 0
if len(connected_floors) > 0 and 'Perpendicular' in self.floor_spanning_direction:
for floor in connected_floors:
floor_min_max = floor.contour.get_min_max()
width = abs(floor_min_max['x-max'] - floor_min_max['x-min'])
length = abs(floor_min_max['y-max'] - floor_min_max['y-min'])
floor_weight = floor.geometry.geometry_model.thickness * floor.material.mass_density * 9.81
if list(map(abs, self.wall_vector)) == [1.0, 0.0, 0.0]:
ov_load += (floor_weight * width / 4) / 1000 if 'BETON' in floor.name else \
(floor_weight * width / 2) / 1000
elif list(map(abs, self.wall_vector)) == [0.0, 1.0, 0.0]:
ov_load += (floor_weight * length / 4) / 1000 if 'BETON' in floor.name else \
(floor_weight * length / 2) / 1000
if len(connected_roofs) > 0 and 'Perpendicular' in self.roof_spanning_direction:
for roof in connected_roofs:
roof_min_max = roof.contour.get_min_max()
width = abs(roof_min_max['x-max'] - roof_min_max['x-min'])
length = abs(roof_min_max['y-max'] - roof_min_max['y-min'])
roof_weight = roof.geometry.geometry_model.thickness * roof.material.mass_density * 9.81
if list(map(abs, self.wall_vector)) == [1.0, 0.0, 0.0]:
ov_load += (roof_weight * width) / 1000
elif list(map(abs, self.wall_vector)) == [0.0, 1.0, 0.0]:
ov_load += (roof_weight * length) / 1000
return ov_load
@property
def score_ov_load(self) -> float:
""" Method of 'RefWallOOP' to calculate score for comparison of the overburden loads of the walls."""
current_wall_overburden_load = self.current_wall.overburden_load
if fem_is_close(self.current_wall.overburden_load, 0):
current_wall_overburden_load = 1/(10**Config.CHECK_PRECISION)
return max([100 - abs((self.overburden_load - current_wall_overburden_load) /
current_wall_overburden_load) * 100, 0])
@property
def score(self) -> float:
""" Method of 'RefWallOOP' to calculate total score for comparison of the current wall and reference wall."""
scores = [score for score in [
self.score_thickness, self.score_width, self.score_height, self.score_density, self.score_openings,
self.score_material, self.score_wall_type, self.score_floor_spanning, self.score_roof_spanning,
self.score_ov_load] if score is not None]
return sum(scores) / len(scores)
[docs] def to_report(self) -> Dict[str, Union[str, float]]:
""" Method of 'RefWallOOP' to convert data for the report."""
return {
'Object part': self.objectpart,
'Wall name': self.name,
'Layer': self.layer,
'Wall ID': self.wall_id,
'Material': self.material,
'Density [kg/m3]': self.density,
'Thickness [mm]': self.thickness * 1000,
'Width [m]': self.width,
'Height [m]': self.height,
'Wall type': self.wall_type,
'Measures in object part': self.measures,
'Openings': self.openings,
'Size of Openings': self.size_of_openings,
'Floor Spanning': self.floor_spanning_direction,
'Roof Spanning': self.roof_spanning_direction,
'Overburden Load': self.overburden_load}
[docs] def to_score(self) -> Dict[str, Union[str, float]]:
""" Method of 'RefWallOOP' to score the wall."""
return {
'Score: thickness': self.score_thickness,
'Score: width': self.score_width,
'Score: height': self.score_height,
'Score: density': self.score_density,
'Score: material': self.score_material,
'Score: wall type': self.score_wall_type,
'Score: openings': self.score_openings,
'Score: opening size': self.score_opening_size,
'Score: floor spanning': self.score_floor_spanning,
'Score: roof spanning': self.score_roof_spanning,
'Score: ov load': self.score_ov_load,
'Total Score': self.score}
[docs] def to_table(self) -> Dict[str, Union[str, float]]:
""" Method of 'RefWallOOP' to convert data for a table."""
return {
'objectpart': self.objectpart,
'name': self.name,
'layer': self.layer,
'wall_ID': self.wall_id,
'material': self.material,
'density': self.density,
'thickness': self.thickness,
'width': self.width,
'height': self.height,
'wall_type': self.wall_type}
### ===================================================================================================================
### 3. End of script
### ===================================================================================================================