diff --git a/src/gui_functions.py b/src/gui_functions.py index 0d7bcb32b87285d0e80c20fc358f1fb13193e7b4..6986c6693356e71cc7e6cf7851baf17d1ab55c0b 100644 --- a/src/gui_functions.py +++ b/src/gui_functions.py @@ -120,3 +120,94 @@ def select_idf(self): messageBox(self, "Important", "Valid File not selected") return 0 + +class Infobox(QtWidgets.QWidget): + def __init__(self, pypath, cat): + super(Infobox, self).__init__() + self.path = pypath + self.cat = cat + self.initUI() + + def initUI(self): + windowSetup(self, 285, 410, 600, 500, pypath, + 'Info') + + # creating main layout + self.vbox = QtWidgets.QVBoxLayout(self) + self.setLayout(self.vbox) + + self.textwidget = QtWidgets.QTextBrowser() + self.vbox.addWidget(self.textwidget) + self.textwidget.setFontPointSize(10) + if self.cat == 1: + text = "Consistency checks implemented based on 'A rule-based" \ + " system to automatically validate IFC 2nd level SB' " \ + "(Ying/Lee 2021) \n\n" \ + "CR.1\tChecking the consistency of IfcRelSpaceBoundary2ndLevel: Description/InternalOrExternalBoundary\n" \ + "CR.1.1\tIF Description = “2a†AND InternalOrExternalBoundary = “INTERNALâ€, THEN the object on the other side of the RelatedBuildingElement of the SB must be a space.\n" \ + "CR.1.2\tIF Description = “2a†AND InternalOrExternalBoundary = “EXTERNALâ€, THEN the object on the other side of the RelatedBuildingElement of the SB must be an outdoor environment. \n" \ + "CR.1.3\tIF Description = “2a†AND InternalOrExternalBoundary = “EXTERNAL_EARTHâ€, THEN the object on the other side of the RelatedBuildingElement of the SB must be a site object.\n" \ + "CR.1.4\tIF Description = “2bâ€, THEN the object on the other side of the RelatedBuildingElement of the SB must be a non-shading element.\n" \ + "CR.1.5\tIF Description = “Shadingâ€, THEN the SB should not bound any interior spaces.\n" \ + "CR.1.6\tIF Description = “2a†AND InternalOrExternalBoudary = “INTERNALâ€, THEN CorrespondingBoundary must refer to an IfcRelSpaceBoundary2ndLevel instance.\n\n" \ + "CR.2\tChecking the consistency of IfcRelSpaceBoundary2ndLevel: RelatingSpace/RelatedBuildingElement\n" \ + "CR.2.1\tIF the RelatingSpace of a SB is a space object, THEN the SB must be included by a relevant face of the RelatingSpace.\n" \ + "CR.2.2\tIF the RelatedBuildingElement of a SB is not a virtual element, THEN the SB must be included by a relevant face of the RelatedBuildingElement. Note: IF the RelatedBuildingElement of the SB is a window or a door, THEN the SB must be included by a relevant face of the IfcOpeningElement instance that fills the window or the door.\n\n" \ + "CR.3\tChecking the consistency of IfcRelSpaceBoundary2ndLevel: PhysicalOrVirtualBoundary\n" \ + "CR.3.1\tIF PhysicalOrVirtualBoundary = “PHYSICALâ€, THEN IfcRelSpaceBoundary2ndLevel.RelatedBuildingElement ∈ {IfcVirtualElement, IfcOpeningElement}.\n" \ + "CR.3.2\tIF PhysicalOrVirtualBoundary = “VIRTUALâ€, THEN IfcRelSpaceBoundary2ndLevel.RelatedBuildingElement ∈ {IfcVirtualElement, IfcOpeningElement}.\n\n" \ + "CR.4\tChecking the consistency of IfcRelSpaceBoundary2ndLevel: ParentBoundary\n" \ + "CR.4.1\tIF ParentBoundary of a SB is another SB AND Description != “Shadingâ€, THEN the SB must be included by that SB.\n" \ + "CR.4.2\tIF ParentBoundary of a SB is another SB AND Description = “Shadingâ€, THEN the SB must connect that SB.\n\n" \ + "CR.5\tChecking the consistency of IfcRelSpaceBoundary2ndLevel: CorrespondingBoundary\n" \ + "CR.5.1\tIF CorrespondingBoundary of a SB is another SB, THEN the SB must fully overlap that SB after projecting the SB on the plane where that SB lies." + elif self.cat == 2: + text = "GlobalID\t\tbound.GlobalId must be a global unique ID\n" \ + "Level\t\tbound.Name must be '2ndLevel'('1stLevel') for 2nd (1st) Level Boundaries, but must only be checked for non-IFC4-files\n" \ + "Description\t\tbound.Description must be either '2a' or '2b' for 2ndLevel boundaries\n" \ + "VirtPhys\t\tbound.PhysicalOrVirtualBoundary.upper must be 'PHYSICAL', 'VIRTUAL' or 'NOTDEFINED'\n" \ + "IntExt\t\tbound.InternalOrExternalBoundary.upper must be either 'INTERNAL', 'EXTERNAL', 'EXTERNAL_FIRE', 'EXTERNAL_WATER' or 'EXTERNAL_EARTH'\n" \ + "Space\t\tbound.RelatingSpace must reference an entity of IfcSpace\n" \ + "Element\t\tbound.RelatedBuildingElement must reference an entity of IfcElement (IFC4)\n" \ + "Geometry\t\tbound.ConnectionGeometry must reference an entity of IfcConnectionGeometry (IFC4, but only IfcSurfaceConnection should be provided)\n" \ + "Geo.Related\t\tbound.ConnectionGeometry.SurfaceOnRelatedElement must reference an entity of IfcCurveBoundedPlane (or IfcFaceBasedSurfaceModel (IFC4) which is not supposed to be used anymore) or be 'NULL'\n" \ + "Geo.Relating\t\tbound.ConnectionGeometry.SurfaceOnRelatingElement must reference an entity of IfcCurveBoundedPlane (or IfcFaceBasedSurfaceModel (IFC4) which is not supposed to be used anymore)\n" \ + "Geo.Basis\t\tbound.ConnectionGeometry.SurfaceOnRelatingElement.BasisSurface must reference an entity of IfcPlane\n" \ + "Geo.Inner\t\tbound.ConnectionGeometry.SurfaceOnRelatingElement.InnerBoundaries must be 'NULL'\n" \ + "Geo.PlanePos\t\tbound.ConnectionGeometry.SurfaceOnRelatingElement.BasisSurface.Position must reference an entity of IfcAxis2Placement3D\n" \ + "Geo.RefDir\t\tbound.ConnectionGeometry.SurfaceOnRelatingElement.BasisSurface.Position.RefDirection if set, it must reference an entity of IfcDirection \n" \ + "Geo.Axis\t\tbound.ConnectionGeometry.SurfaceOnRelatingElement.BasisSurface.Position.Axis if set, it must reference an entity of IfcDirection\n" \ + "Geo.Loc\t\tbound.ConnectionGeometry.SurfaceOnRelatingElement.BasisSurface.Position.Location must reference an entity of IfcCartesianPoint\n" \ + "Geo.LocCo\t\tbound.ConnectionGeometry.SurfaceOnRelatingElement.BasisSurface.Position.Location.Coordinates must be at least 1 and less than 4 values in REAL type\n" \ + "Geo.AxDirRat\t\tbound.ConnectionGeometry.SurfaceOnRelatingElement.BasisSurface.Position.Axis.DirectionRatios must be 2 or 3 values in REAL type \n" \ + "Geo.RefDirRat\tbound.ConnectionGeometry.SurfaceOnRelatingElement.BasisSurface.Position.RefDirection.DirectionRatios must be 2 or 3 values in REAL type \n" \ + "Parent\t\tbound.ParentBoundary must reference an entity of 1stLevelBoundary or be 'None', returns 'NE' if non-existent\n" \ + "Corresponding\tbound.CorrespondingBoundary must reference an entity of 2ndLevelBoundary or be 'None', return 'NE' if non-existent. Also checks whether corresponding bounds are referencing each other.\n" \ + "Outer\t\tbound.ConnectionGeometry.SurfaceOnRelatingElement.OuterBoundary must reference an entity of IfcCompositeCurve\n" \ + "Outer.Seg\t\tbound.ConnectionGeometry.SurfaceOnRelatingElement.OuterBoundary.Segments must reference an entity of 'IfcCompositeCurveSegment'\n" \ + "Outer.SegPoly\tbound.ConnectionGeometry.SurfaceOnRelatingElement.OuterBoundary.Segments.ParentCurve must reference an entity of 'IfcPolyline' (check_poly_points)\n" \ + "Outer.SegPolyCo\tbound.ConnectionGeometry.SurfaceOnRelatingElement.OuterBoundary.Segments.ParentCurve.Coordinates must not be 'Null' (check_poly_points_coord)\n" \ + "Outer.Poly\t\tbound.ConnectionGeometry.SurfaceOnRelatingElement.OuterBoundary must reference an entity of 'IfcPolyline' if there are no segments (check_poly_points)\n" \ + "Outer.PolyCo\t\tbound.ConnectionGeometry.SurfaceOnRelatingElement.OuterBoundary.Coordinates (points of polyline) must not be 'Null' if there are no segments\n\n" \ + "See also: https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2/HTML/schema/ifcproductextension/lexical/ifcrelspaceboundary.htm\n\n" \ + "If the space boundaries are not declared as IfcRelSpaceBoundary2ndLevel, IfcRelSpaceBoundary will be checked without considering ParentBoundaries and CorrespondingBoundaries." + elif self.cat == 3: + text = "Surface Normals:\t\tAll surface normals within the IDF " \ + "should point outwards the space.\n" \ + "Collinearity&Coincidence of vertices:\tThe vertices of " \ + "building surfaces must not be coincident or collinear.\n" \ + "Airtightness:\t\t\tThe surfaces within a thermal zone " \ + "should form an airtight shell bounding the zone volume.\n" + + self.textwidget.setText(text) + + self.lGrid = QtWidgets.QGridLayout() + + self.btn_close = QtWidgets.QPushButton('Close') + self.lGrid.addWidget(self.btn_close, 0, 1) + + self.vbox.addLayout(self.lGrid) + self.btn_close.clicked.connect(self.close_about) + + def close_about(self): + self.hide() diff --git a/src/main.py b/src/main.py index 445c9fe025009fc4c52f4c4d758e0a326f6f9805..955450739f11589c87a1f3b025b6b5f7534c3f1a 100644 --- a/src/main.py +++ b/src/main.py @@ -676,6 +676,20 @@ class Window(QtWidgets.QMainWindow): self.export_menu.addAction(self.export_action) self.export_action.triggered.connect(self.func_export) + # Popup infobox + self.info_menu = self.bar.addMenu('Info') + if self.file_type == 'ifc': + self.info_cons_action = QtWidgets.QAction('&Consistency', self) + self.info_menu.addAction(self.info_cons_action) + self.info_cons_action.triggered.connect(self.info_box_c) + self.info_syntax_action = QtWidgets.QAction('&Syntax', self) + self.info_menu.addAction(self.info_syntax_action) + self.info_syntax_action.triggered.connect(self.info_box_s) + elif self.file_type == 'idf': + self.info_idf_action = QtWidgets.QAction('&Validation Rules', self) + self.info_menu.addAction(self.info_idf_action) + self.info_idf_action.triggered.connect(self.info_box_idf) + def func_file_sel(self): if self.file_type == 'ifc': gf.next_window(self, Window(file_type='ifc'), trig_True) @@ -743,6 +757,18 @@ class Window(QtWidgets.QMainWindow): else: pass + def info_box_c(self): + global pypath + gf.next_window(self, gf.Infobox(pypath, 1), False) + + def info_box_s(self): + global pypath + gf.next_window(self, gf.Infobox(pypath, 2), False) + + def info_box_idf(self): + global pypath + gf.next_window(self, gf.Infobox(pypath, 3), False) + class WindowTrsf(QtWidgets.QMainWindow): def __init__(self, parent=None):