Skip to content

Commit 6a7b91c

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 6a7b91c

File tree

1 file changed

+138
-72
lines changed

1 file changed

+138
-72
lines changed

bim2sim/tasks/common/check_ifc_ids.py

Lines changed: 138 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ def __init__(self, playground: Playground):
4646
self.elements: list = []
4747
self.ps_summary: dict = {}
4848
self.ifc_units: dict = {}
49-
self.sub_inst_cls = None # uses for filerting prepare check
49+
# TODO maybe not needed her, because set in logic class
50+
# uses for filerting prepare check
51+
self.sub_inst_cls = None
5052
self.plugin = None
5153

5254
def run(self, ifc_files: [IfcFileClass]):
@@ -93,34 +95,6 @@ def run(self, ifc_files: [IfcFileClass]):
9395
# checks are domain specific
9496
# Reset class based on domain to run the right check.
9597
# 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)
12498

12599
# check uniqueness of GUIDs
126100
self.all_guids_unique, self.double_guids = CheckLogicBase.run_check_guid_unique(ifc_file)
@@ -141,55 +115,40 @@ def run(self, ifc_files: [IfcFileClass]):
141115
# critical: if loaded IFC is not IFC4
142116
if self.version_error:
143117
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)
148-
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).
156118

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
119+
if ifc_file.domain == IFCDomain.hydraulic:
120+
self.logger.info(f"Processing HVAC-IfcCheck") # todo
121+
elif ifc_file.domain == IFCDomain.arch:
122+
self.logger.info(f"Processing BPS-IfcCheck") # todo
123+
# checking itself
124+
chlb = CheckLogicBase()
125+
# prepare data for checking (filering)
126+
self.sub_inst = ifc_file.file.by_type(chlb.sub_inst_cls)
127+
self.error_summary_sub_inst = chlb.check_inst(
128+
chlb.validate_sub_inst, self.sub_inst)
129+
self.paths = paths # TODO needed in if loop, here need better solution
130+
elif ifc_file.domain == IFCDomain.unknown:
131+
self.logger.info(f"No domain specified for ifc file "
132+
f"{ifc_file.ifc_file_name}, not processing "
133+
f"any checks")
134+
return
135+
else:
136+
self.logger.info(
137+
f"For the Domain {ifc_file.domain} no specific checks are"
138+
f" implemented currently. Just running the basic checks."
139+
f"")
160140

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

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
176143

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.
182144

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

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

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

194153
def validate_sub_inst(self, sub_inst: list) -> list:
195154
raise NotImplementedError
@@ -370,7 +329,6 @@ def _write_errors_to_html_table(self, base_name: str, domain: IFCDomain):
370329
webbrowser.open(f"file://{out_file.buffer.name}")
371330

372331

373-
374332
class CheckIfcBPS(CheckIfc):
375333
"""
376334
Check an IFC file, for a number of conditions (missing information,
@@ -449,6 +407,12 @@ class CheckLogicBase():
449407
useful for all checking use cases.
450408
"""
451409

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

543507

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

0 commit comments

Comments
 (0)