Coverage for bim2sim/plugins/PluginEnergyPlus/bim2sim_energyplus/task/ep_ifc_validation.py: 0%
127 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-12 17:09 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-12 17:09 +0000
1import json
3from bim2sim.tasks.base import ITask
6class IfcValidation(ITask):
7 """
8 Validate IFC file, focussing on energy modeling (use of space boundaries).
10 See run method for further details.
11 """
13 reads = ('ifc_files', )
15 def __init__(self, playground):
16 super().__init__(playground)
17 self.error_summary = {}
18 self.bounds = []
19 self.id_list = []
21 def run(self, ifc_files):
22 """
23 IFC file validation for EnergyPlus. No longer maintained.
25 This function holds an IFC file validation for EnergyPlus, but is no
26 longer used. This task is replaced by the CheckIFC class in the
27 common task section. For building performance simulation workflows
28 like EnergyPlus, the common CheckIfc class executes the BEPS specific
29 CheckIfcBPS methods.
31 Args:
32 ifc_files: input ifc files.
33 """
34 self.bounds = []
35 self.id_list = []
36 for ifc in ifc_files:
38 self.bounds.extend(ifc.by_type('IfcRelSpaceBoundary'))
39 self.id_list.extend([e.GlobalId for e in ifc.by_type("IfcRoot")])
41 self._check_space_boundaries()
42 self._write_errors_to_json()
43 self._evaluate_checks()
45 def _check_space_boundaries(self):
46 """ Perform space boundary validation and add errors to error summary."""
47 self.logger.info("Check syntax of IfcRelSpaceBoundary")
48 for bound in self.bounds:
49 sbv = SpaceBoundaryValidation(bound, self.id_list)
50 if len(sbv.error) > 0:
51 self.error_summary.update({bound.GlobalId: sbv.error})
53 def _write_errors_to_json(self):
54 """write error summary to json file for export."""
55 with open(str(self.paths.root) + "/export/" + 'ifc_SB_error_summary.json', 'w+') as fp:
56 json.dump(self.error_summary, fp, indent="\t")
57 self.logger.info("All tests done!")
59 def _evaluate_checks(self):
60 """Add error summary to logging."""
61 if len(self.error_summary) == 0:
62 self.logger.info(
63 "All %d IfcRelSpaceBoundary entities PASSED the syntax validation process." % len(self.bounds))
64 else:
65 self.logger.warning("%d out of %d IfcRelSpaceBoundary entities FAILED the syntax validation process. \n"
66 "Occuring sets of errors: %s \n"
67 "See ifc_SB_error_summary.json for further information on the errors."
68 % (len(self.error_summary),
69 len(self.bounds),
70 set(tuple(s) for s in [vals for key, vals in self.error_summary.items()])))
73class SpaceBoundaryValidation:
74 """
75 Validate IFC Space Boundaries for use in EnergyPlus
76 """
77 def __init__(self, bound, id_list):
78 self.error = []
79 self.bound = bound
80 self.id_list = id_list
81 self._validate_space_boundaries()
83 def _validate_space_boundaries(self):
84 self._apply_validation_function(self._check_unique(), 'GlobalId')
85 self._apply_validation_function(self._check_level(), '2ndLevel')
86 self._apply_validation_function(self._check_description(), 'Description')
87 self._apply_validation_function(self._check_rel_space(), 'RelatingSpace')
88 self._apply_validation_function(self._check_rel_building_elem(), 'RelatedBuildingElement')
89 self._apply_validation_function(self._check_conn_geom(), 'ConnectionGeometry')
90 self._apply_validation_function(self._check_phys_virt_bound(), 'PhysicalOrVirtualBoundary')
91 self._apply_validation_function(self._check_int_ext_bound(), 'InternalOrExternalBoundary')
92 self._apply_validation_function(self._check_on_relating_elem(), 'SurfaceOnRelatingElement')
93 self._apply_validation_function(self._check_on_related_elem(), 'SurfaceOnRelatedElement')
94 self._apply_validation_function(self._check_basis_surface(), 'BasisSurface')
95 self._apply_validation_function(self._check_inner_boundaries(), 'InnerBoundaries')
96 if hasattr(self.bound.ConnectionGeometry.SurfaceOnRelatingElement.OuterBoundary, 'Segments'):
97 self._apply_validation_function(self._check_outer_boundary_composite(), 'OuterBoundaryCompositeCurve')
98 self._apply_validation_function(self._check_segments(), 'Segments')
99 self._apply_validation_function(self._check_segments_poly(), 'SegmentsPolyline')
100 self._apply_validation_function(self._check_segments_poly_coord(), 'SegmentsPolylineCoordinates')
101 else:
102 self._apply_validation_function(self._check_outer_boundary_poly(), 'OuterBoundaryPolyline')
103 self._apply_validation_function(self._check_outer_boundary_poly_coord(), 'OuterBoundaryPolylineCoordinates')
104 self._apply_validation_function(self._check_plane_position(), 'Position')
105 self._apply_validation_function(self._check_location(), 'Location')
106 self._apply_validation_function(self._check_axis(), 'Axis')
107 self._apply_validation_function(self._check_refdirection(), 'RefDirection')
108 self._apply_validation_function(self._check_location_coord(), 'LocationCoordinates')
109 self._apply_validation_function(self._check_axis_dir_ratios(), 'AxisDirectionRatios')
110 self._apply_validation_function(self._check_refdirection_dir_ratios(), 'RefDirectionDirectionRatios')
112 def _apply_validation_function(self, fct, err_name):
113 if not fct:
114 self.error.append(err_name)
116 def _check_unique(self):
117 return self.id_list.count(self.bound.GlobalId) == 1
119 def _check_level(self):
120 return self.bound.Name == "2ndLevel"
122 def _check_description(self):
123 return self.bound.Description in {'2a', '2b'}
125 def _check_rel_space(self):
126 return any(
127 [self.bound.RelatingSpace.is_a('IfcSpace') or self.bound.RelatingSpace.is_a('IfcExternalSpatialElement')])
129 def _check_rel_building_elem(self):
130 if self.bound.RelatedBuildingElement is not None:
131 return self.bound.RelatedBuildingElement.is_a('IfcBuildingElement')
133 def _check_conn_geom(self):
134 return self.bound.ConnectionGeometry.is_a('IfcConnectionSurfaceGeometry')
136 def _check_phys_virt_bound(self):
137 return self.bound.PhysicalOrVirtualBoundary.upper() in {'PHYSICAL', 'VIRTUAL'}
139 def _check_int_ext_bound(self):
140 return self.bound.InternalOrExternalBoundary.upper() in {'INTERNAL',
141 'EXTERNAL',
142 'EXTERNAL_EARTH',
143 'EXTERNAL_FIRE',
144 'EXTERNAL_WATER'
145 }
147 def _check_on_relating_elem(self):
148 return self.bound.ConnectionGeometry.SurfaceOnRelatingElement.is_a('IfcCurveBoundedPlane')
150 def _check_on_related_elem(self):
151 return self.bound.ConnectionGeometry.SurfaceOnRelatedElement is None
153 def _check_basis_surface(self):
154 return self.bound.ConnectionGeometry.SurfaceOnRelatingElement.BasisSurface.is_a('IfcPlane')
156 def _check_outer_boundary_composite(self):
157 return self.bound.ConnectionGeometry.SurfaceOnRelatingElement.OuterBoundary.is_a('IfcCompositeCurve')
159 def _check_outer_boundary_poly(self):
160 return self._check_poly_points(self.bound.ConnectionGeometry.SurfaceOnRelatingElement.OuterBoundary)
162 def _check_outer_boundary_poly_coord(self):
163 return all(self.bound.ConnectionGeometry.SurfaceOnRelatingElement.OuterBoundary)
165 def _check_inner_boundaries(self):
166 return (self.bound.ConnectionGeometry.SurfaceOnRelatingElement.InnerBoundaries is None) or \
167 (i.is_a('IfcCompositeCurve')
168 for i in self.bound.ConnectionGeometry.SurfaceOnRelatingElement.InnerBoundaries)
170 def _check_segments(self):
171 return (s.is_a('IfcPolyline')
172 for s in self.bound.ConnectionGeometry.SurfaceOnRelatingElement.OuterBoundary.Segments)
174 def _check_segments_poly(self):
175 return all(self._check_poly_points(s.ParentCurve)
176 for s in self.bound.ConnectionGeometry.SurfaceOnRelatingElement.OuterBoundary.Segments)
178 def _check_segments_poly_coord(self):
179 return all(self._check_poly_points_coord(s.ParentCurve)
180 for s in self.bound.ConnectionGeometry.SurfaceOnRelatingElement.OuterBoundary.Segments)
182 def _check_plane_position(self):
183 return self.bound.ConnectionGeometry.SurfaceOnRelatingElement.BasisSurface.Position.is_a('IfcAxis2Placement3D')
185 def _check_poly_points(self, polyline):
186 return polyline.is_a('IfcPolyline')
188 def _check_location(self):
189 return self.bound.ConnectionGeometry.SurfaceOnRelatingElement.BasisSurface.Position.Location.is_a(
190 'IfcCartesianPoint')
192 def _check_axis(self):
193 return self.bound.ConnectionGeometry.SurfaceOnRelatingElement.BasisSurface.Position.Axis.is_a('IfcDirection')
195 def _check_refdirection(self):
196 return self.bound.ConnectionGeometry.SurfaceOnRelatingElement.BasisSurface.Position.RefDirection.is_a(
197 'IfcDirection')
199 def _check_coords(self, points):
200 return points.is_a('IfcCartesianPoint') and 1 <= len(points.Coordinates) <= 4
202 def _check_dir_ratios(self, dir_ratios):
203 return 2 <= len(dir_ratios.DirectionRatios) <= 3
205 def _check_poly_points_coord(self, polyline):
206 return all(self._check_coords(p) for p in polyline.Points)
208 def _check_location_coord(self):
209 return self._check_coords(self.bound.ConnectionGeometry.SurfaceOnRelatingElement.BasisSurface.Position.Location)
211 def _check_axis_dir_ratios(self):
212 return self._check_dir_ratios(self.bound.ConnectionGeometry.SurfaceOnRelatingElement.BasisSurface.Position.Axis)
214 def _check_refdirection_dir_ratios(self):
215 return self._check_dir_ratios(
216 self.bound.ConnectionGeometry.SurfaceOnRelatingElement.BasisSurface.Position.RefDirection)