Skip to content

Commit 5e4290a

Browse files
committed
start rearrange structure
seperate logic and procecces for checking only include some check functions for BPS e1_checkIFCIDS_dev.py example is working
1 parent 33f0211 commit 5e4290a

File tree

1 file changed

+135
-70
lines changed

1 file changed

+135
-70
lines changed

bim2sim/tasks/common/check_ifc_ids.py

Lines changed: 135 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -93,34 +93,6 @@ def run(self, ifc_files: [IfcFileClass]):
9393
# checks are domain specific
9494
# Reset class based on domain to run the right check.
9595
# Not pretty but works. This might be refactored in #170
96-
if ifc_file.domain == IFCDomain.hydraulic:
97-
self.logger.info(f"Processing HVAC-IfcCheck") # todo
98-
elif ifc_file.domain == IFCDomain.arch:
99-
self.logger.info(f"Processing BPS-IfcCheck") # todo
100-
self.__class__ = CheckIfcBPS
101-
self.__class__.__init__(self, self.playground)
102-
self.paths = paths # TODO needed in if loop, here need better solution
103-
elif ifc_file.domain == IFCDomain.unknown:
104-
self.logger.info(f"No domain specified for ifc file "
105-
f"{ifc_file.ifc_file_name}, not processing "
106-
f"any checks")
107-
return
108-
else:
109-
self.logger.info(
110-
f"For the Domain {ifc_file.domain} no specific checks are"
111-
f" implemented currently. Just running the basic checks."
112-
f"")
113-
114-
## begin copy form old ifc check (only tempory until new structure is working)
115-
# prepare data for checking (filering)
116-
117-
self.sub_inst = ifc_file.file.by_type(self.sub_inst_cls)
118-
119-
# checking itself
120-
self.error_summary_sub_inst = self.check_inst(
121-
self.validate_sub_inst, self.sub_inst)
122-
123-
## end copy form old ifc check (only tempory until new structure is working)
12496

12597
# check uniqueness of GUIDs
12698
self.all_guids_unique, self.double_guids = CheckLogicBase.run_check_guid_unique(ifc_file)
@@ -141,55 +113,41 @@ def run(self, ifc_files: [IfcFileClass]):
141113
# critical: if loaded IFC is not IFC4
142114
if self.version_error:
143115
self.logger.critical(f"ifc Version is not fitting. Should be IFC4, but here: " + self.ifc_version)
144-
# write reportes self made checks
145-
base_name = f"/{ifc_file.domain.name.upper()}_" \
146-
f"{ifc_file.ifc_file_name[:-4]}"
147-
self._write_errors_to_html_table(base_name, ifc_file.domain)
148116

149-
###### old ifc check, maybe stay here
150-
@staticmethod
151-
def check_inst(validation_function: Callable, elements: list):
152-
"""Uses sb_validation/ports/elements functions in order to check each
153-
one and adds error to dictionary if object has errors. Combines the
154-
(error) return of the specific validation function with the key (mostly
155-
the GlobalID).
117+
# prepare data for checking (filering)
118+
self.sub_inst = ifc_file.file.by_type(self.sub_inst_cls)
156119

157-
Args: validation_function: function that compiles all the
158-
validations to be performed on the object (sb/port/instance) elements:
159-
list containing all objects to be evaluates
120+
if ifc_file.domain == IFCDomain.hydraulic:
121+
self.logger.info(f"Processing HVAC-IfcCheck") # todo
122+
elif ifc_file.domain == IFCDomain.arch:
123+
self.logger.info(f"Processing BPS-IfcCheck") # todo
124+
# checking itself
125+
chlb = CheckLogicBase()
126+
self.error_summary_sub_inst = chlb.check_inst(
127+
chlb.validate_sub_inst, self.sub_inst)
128+
self.paths = paths # TODO needed in if loop, here need better solution
129+
elif ifc_file.domain == IFCDomain.unknown:
130+
self.logger.info(f"No domain specified for ifc file "
131+
f"{ifc_file.ifc_file_name}, not processing "
132+
f"any checks")
133+
return
134+
else:
135+
self.logger.info(
136+
f"For the Domain {ifc_file.domain} no specific checks are"
137+
f" implemented currently. Just running the basic checks."
138+
f"")
160139

161-
Returns:
162-
summary: summarized dictionary of errors, where the key is the
163-
GUID + the ifc_type
140+
## begin copy form old ifc check (only tempory until new structure is working)
164141

165-
"""
166-
summary = {}
167-
for inst in elements:
168-
error = validation_function(inst)
169-
if len(error) > 0:
170-
if hasattr(inst, 'GlobalId'):
171-
key = inst.GlobalId + ' ' + inst.is_a()
172-
else:
173-
key = inst.is_a()
174-
summary.update({key: error})
175-
return summary
176142

177-
@staticmethod
178-
def apply_validation_function(fct: bool, err_name: str, error: list):
179-
"""
180-
Function to apply a validation to an instance, space boundary or
181-
port, it stores the error to the list of errors.
182143

183-
Args:
184-
fct: validation function to be applied
185-
err_name: string that define the error
186-
error: list of errors
144+
## end copy form old ifc check (only tempory until new structure is working)
187145

188-
"""
189-
if not fct:
190-
error.append(err_name)
146+
# write reportes self made checks
147+
base_name = f"/{ifc_file.domain.name.upper()}_" \
148+
f"{ifc_file.ifc_file_name[:-4]}"
149+
self._write_errors_to_html_table(base_name, ifc_file.domain)
191150

192-
###### old ifc check, maybe stay here
193151

194152
def validate_sub_inst(self, sub_inst: list) -> list:
195153
raise NotImplementedError
@@ -370,7 +328,6 @@ def _write_errors_to_html_table(self, base_name: str, domain: IFCDomain):
370328
webbrowser.open(f"file://{out_file.buffer.name}")
371329

372330

373-
374331
class CheckIfcBPS(CheckIfc):
375332
"""
376333
Check an IFC file, for a number of conditions (missing information,
@@ -449,6 +406,12 @@ class CheckLogicBase():
449406
useful for all checking use cases.
450407
"""
451408

409+
def __init__(self):
410+
# used for preparing data for checking, is filder keyword
411+
self.sub_inst_cls = 'IfcRelSpaceBoundary'
412+
self.plugin = bps
413+
self.space_ndicator = True
414+
452415
def run_check_guid_unique(ifc_file) -> (bool, dict):
453416
"""check the uniqueness of the guids of the IFC file
454417
@@ -541,6 +504,108 @@ def run_check_ifc_version(ifc: ifcos.file) -> (bool, str):
541504
return (version_error, schema)
542505

543506

507+
###### old ifc check, maybe stay here
508+
@staticmethod
509+
def check_inst(validation_function: Callable, elements: list):
510+
"""Uses sb_validation/ports/elements functions in order to check each
511+
one and adds error to dictionary if object has errors. Combines the
512+
(error) return of the specific validation function with the key (mostly
513+
the GlobalID).
514+
515+
Args: validation_function: function that compiles all the
516+
validations to be performed on the object (sb/port/instance) elements:
517+
list containing all objects to be evaluates
518+
519+
Returns:
520+
summary: summarized dictionary of errors, where the key is the
521+
GUID + the ifc_type
522+
523+
"""
524+
summary = {}
525+
for inst in elements:
526+
error = validation_function(inst)
527+
if len(error) > 0:
528+
if hasattr(inst, 'GlobalId'):
529+
key = inst.GlobalId + ' ' + inst.is_a()
530+
else:
531+
key = inst.is_a()
532+
summary.update({key: error})
533+
return summary
534+
535+
@staticmethod
536+
def apply_validation_function(fct: bool, err_name: str, error: list):
537+
"""
538+
Function to apply a validation to an instance, space boundary or
539+
port, it stores the error to the list of errors.
540+
541+
Args:
542+
fct: validation function to be applied
543+
err_name: string that define the error
544+
error: list of errors
545+
546+
"""
547+
if not fct:
548+
error.append(err_name)
549+
550+
###### old ifc check, maybe stay here
551+
552+
@staticmethod
553+
def _check_rel_space(bound: entity_instance):
554+
"""
555+
Check that the space boundary relating space exists and has the
556+
correct class.
557+
558+
Args:
559+
bound: Space boundary IFC instance
560+
561+
Returns:
562+
True: if check succeeds
563+
False: if check fails
564+
"""
565+
return any(
566+
[bound.RelatingSpace.is_a('IfcSpace') or
567+
bound.RelatingSpace.is_a('IfcExternalSpatialElement')])
568+
569+
@staticmethod
570+
def _check_rel_building_elem(bound: entity_instance):
571+
"""
572+
Check that the space boundary related building element exists and has
573+
the correct class.
574+
575+
Args:
576+
bound: Space boundary IFC instance
577+
578+
Returns:
579+
True: if check succeeds
580+
False: if check fails
581+
"""
582+
if bound.RelatedBuildingElement is not None:
583+
return bound.RelatedBuildingElement.is_a('IfcElement')
584+
585+
def validate_sub_inst(self, bound: entity_instance) -> list:
586+
"""
587+
Validation function for a space boundary that compiles all validation
588+
functions.
589+
590+
Args:
591+
bound: ifc space boundary entity
592+
593+
Returns:
594+
error: list of errors found in the ifc space boundaries
595+
"""
596+
error = []
597+
self.apply_validation_function(self._check_rel_space(bound),
598+
'RelatingSpace - '
599+
'The space boundary does not have a '
600+
'relating space associated', error)
601+
self.apply_validation_function(self._check_rel_building_elem(bound),
602+
'RelatedBuildingElement - '
603+
'The space boundary does not have a '
604+
'related building element associated',
605+
error)
606+
return error
607+
608+
544609
class CheckLogicBPS(CheckLogicBase):
545610
"""Provides additional logic for ifc files checking regarding BPS."""
546611

0 commit comments

Comments
 (0)