Arch: IFC browser - fixes #1384

Arch -> Utilities -> IFC Explorer
This opens a browser window that displays the contents of an IFC file
in a more readable manner than a text editor.
This commit is contained in:
Yorik van Havre 2014-02-07 10:57:34 -02:00
parent 70091e57c2
commit 4e722e2cda
7 changed files with 213 additions and 12 deletions

View File

@ -925,6 +925,20 @@ class _CommandCheck:
FreeCADGui.Selection.addSelection(i[0])
class _CommandIfcExplorer:
"the Arch Ifc Explorer command definition"
def GetResources(self):
return {'Pixmap' : 'IFC',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_IfcExplorer","Ifc Explorer"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Check","Explore the contents of an Ifc file")}
def Activated(self):
if hasattr(self,"dialog"):
del self.dialog
import importIFC
self.dialog = importIFC.explore()
class _CommandFixture:
# OBSOLETE - To be removed
"the Arch Fixture command definition"
@ -958,4 +972,5 @@ if FreeCAD.GuiUp:
FreeCADGui.addCommand('Arch_RemoveShape',_CommandRemoveShape())
FreeCADGui.addCommand('Arch_CloseHoles',_CommandCloseHoles())
FreeCADGui.addCommand('Arch_Check',_CommandCheck())
FreeCADGui.addCommand('Arch_IfcExplorer',_CommandIfcExplorer())
#FreeCADGui.addCommand('Arch_Fixture',_CommandFixture())

File diff suppressed because one or more lines are too long

View File

@ -74,10 +74,10 @@ class ArchWorkbench(Workbench):
"Arch_Window","Arch_Roof","Arch_Axis",
"Arch_SectionPlane","Arch_Space","Arch_Stairs",
"Arch_Frame","Arch_Add","Arch_Remove"]
self.meshtools = ["Arch_SplitMesh","Arch_MeshToShape",
self.utilities = ["Arch_SplitMesh","Arch_MeshToShape",
"Arch_SelectNonSolidMeshes","Arch_RemoveShape",
"Arch_CloseHoles","Arch_MergeWalls"]
self.calctools = ["Arch_Check"]
"Arch_CloseHoles","Arch_MergeWalls","Arch_Check",
"Arch_IfcExplorer"]
# draft tools
self.drafttools = ["Draft_Line","Draft_Wire","Draft_Circle","Draft_Arc","Draft_Ellipse",
@ -103,8 +103,7 @@ class ArchWorkbench(Workbench):
self.appendToolbar(translate("arch","Arch tools"),self.archtools)
self.appendToolbar(translate("arch","Draft tools"),self.drafttools)
self.appendToolbar(translate("arch","Draft mod tools"),self.draftmodtools)
self.appendMenu([translate("arch","&Architecture"),translate("arch","Conversion Tools")],self.meshtools)
self.appendMenu([translate("arch","&Architecture"),translate("arch","Calculation Tools")],self.calctools)
self.appendMenu([translate("arch","&Architecture"),translate("arch","Utilities")],self.utilities)
self.appendMenu(translate("arch","&Architecture"),self.archtools)
self.appendMenu(translate("arch","&Draft"),self.drafttools+self.draftmodtools+self.extramodtools)
self.appendMenu([translate("arch","&Draft"),translate("arch","Context Tools")],self.draftcontexttools)

View File

@ -40,6 +40,7 @@
<file>icons/Arch_Rebar_Tree.svg</file>
<file>icons/Arch_Frame.svg</file>
<file>icons/Arch_Frame_Tree.svg</file>
<file>icons/IFC.svg</file>
<file>ui/archprefs-base.ui</file>
<file>ui/archprefs-import.ui</file>
<file>ui/ParametersWindowDouble.svg</file>

View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg3007"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="New document 4">
<defs
id="defs3009" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="7.7781746"
inkscape:cx="32.615197"
inkscape:cy="37.232031"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:object-nodes="true"
inkscape:snap-smooth-nodes="true"
inkscape:window-width="1920"
inkscape:window-height="1053"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata3012">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
style="color:#000000;fill:#a32187;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 23.493051,22.924165 c -1.538134,0 -3.091954,0.568446 -4.270552,1.747044 L 6.8961342,36.997574 c -2.3571939,2.357194 -2.3571939,6.183909 0,8.541103 L 19.222499,57.865042 c 2.357194,2.357194 6.13538,2.357194 8.492574,0 L 40.041438,45.538677 c 2.357194,-2.357194 2.357194,-6.183909 0,-8.541103 L 27.715073,24.671209 c -1.178597,-1.178598 -2.683889,-1.747044 -4.222022,-1.747044 z m 0,7.424936 c 0.916749,0 1.821047,0.316649 2.523507,1.019109 l 7.327879,7.376408 c 1.404921,1.404921 1.404921,3.642094 0,5.047015 l -7.327879,7.376408 c -1.404921,1.404921 -3.690623,1.404921 -5.095544,0 l -7.327879,-7.376408 c -1.40492,-1.404921 -1.40492,-3.642094 0,-5.047015 l 7.327879,-7.376408 c 0.702461,-0.70246 1.655287,-1.019109 2.572037,-1.019109 z"
id="rect3022-4"
inkscape:connector-curvature="0" />
<path
style="color:#000000;fill:#1b8fa7;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 41.379157,23.102951 c -1.538133,0 -3.091954,0.568446 -4.270552,1.747043 L 24.78224,37.176359 c -2.357194,2.357194 -2.357194,6.18391 0,8.541104 l 12.326365,12.326364 c 2.357194,2.357194 6.13538,2.357194 8.492574,0 L 57.927544,45.717463 c 2.357194,-2.357194 2.357194,-6.18391 0,-8.541104 L 45.601179,24.849994 C 44.422582,23.671397 42.91729,23.102951 41.379157,23.102951 z m 0,7.424936 c 0.916749,0 1.821047,0.316648 2.523507,1.019109 l 7.327879,7.376407 c 1.404921,1.404922 1.404921,3.642094 0,5.047016 l -7.327879,7.376407 c -1.404921,1.404921 -3.690623,1.404921 -5.095544,0 l -7.327879,-7.376407 c -1.404921,-1.404922 -1.404921,-3.642094 0,-5.047016 l 7.327879,-7.376407 c 0.702461,-0.702461 1.655287,-1.019109 2.572037,-1.019109 z"
id="rect3022-4-8"
inkscape:connector-curvature="0" />
<path
style="color:#000000;fill:#004a95;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 22.088093,5.565902 c -1.538133,0 -3.091953,0.5684461 -4.270551,1.7470438 L 5.491177,19.639311 c -2.3571938,2.357194 -2.3571938,6.18391 0,8.541103 l 12.326365,12.326365 c 2.357194,2.357194 6.13538,2.357194 8.492574,0 L 38.636481,28.180414 c 2.357194,-2.357193 2.357194,-6.183909 0,-8.541103 L 26.310116,7.3129458 C 25.131518,6.1343481 23.626227,5.565902 22.088093,5.565902 z m 0,7.424936 c 0.91675,0 1.821048,0.316649 2.523508,1.01911 l 7.327879,7.376407 c 1.404921,1.404921 1.404921,3.642094 0,5.047016 l -7.327879,7.376407 c -1.404921,1.404921 -3.690623,1.404921 -5.095544,0 l -7.327878,-7.376407 c -1.404921,-1.404922 -1.404921,-3.642095 0,-5.047016 l 7.327878,-7.376407 c 0.70246,-0.702461 1.655287,-1.01911 2.572036,-1.01911 z"
id="rect3022-7"
inkscape:connector-curvature="0" />
<path
style="color:#000000;fill:#da0640;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 39.971816,4.6619318 c -1.538133,0 -3.091954,0.5684461 -4.270552,1.7470438 l -5.192602,5.1926024 4.222022,4.173494 2.669095,-2.669095 c 0.702461,-0.702461 1.655288,-1.019109 2.572037,-1.019109 0.916749,0 1.821047,0.316648 2.523508,1.019109 l 7.327878,7.376408 c 1.404921,1.404921 1.404921,3.642094 0,5.047015 l -7.327878,7.376408 c -1.388531,1.38853 -3.63841,1.40466 -5.047016,0.04853 l -4.222023,4.173493 2.474979,2.474979 c 2.357194,2.357194 6.135381,2.357194 8.492574,0 L 56.520203,27.276444 c 2.357194,-2.357194 2.357194,-6.183909 0,-8.541103 L 44.193838,6.4089756 C 43.015241,5.2303779 41.509949,4.6619318 39.971816,4.6619318 z M 26.335168,15.775072 23.374899,18.735341 c -2.357194,2.357194 -2.357194,6.183909 0,8.541103 l 3.88232,3.88232 4.173493,-4.222023 -1.358811,-1.407341 c -1.404922,-1.404921 -1.404922,-3.642094 0,-5.047015 l 0.48529,-0.48529 -4.222023,-4.222023 z"
id="rect3022"
inkscape:connector-curvature="0" />
<path
style="color:#000000;fill:#a32187;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 23.471957,22.908835 c -1.538133,0 -3.091954,0.568446 -4.270551,1.747043 L 6.8750408,36.982243 c -2.3571939,2.357194 -2.3571939,6.18391 0,8.541104 l 2.7661527,2.766152 4.2705515,-4.173493 -0.339703,-0.339703 c -1.404921,-1.404922 -1.404921,-3.642094 0,-5.047016 L 20.89992,31.35288 c 0.702461,-0.702461 1.655288,-1.019109 2.572037,-1.019109 0.916749,0 1.821047,0.316648 2.523508,1.019109 l 0.436761,0.436761 4.270552,-4.124965 -3.008798,-3.008798 c -1.178598,-1.178597 -2.68389,-1.747043 -4.222023,-1.747043 z"
id="rect3022-4-4"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -145,6 +145,14 @@ class IfcSchema:
attrs.reverse()
return attrs
def capitalize(self, name):
"returns a capitalized version of a type"
if name.upper() in self.data.upper():
i1 = self.data.upper().index(name.upper())
i2 = i1 + len(name)
name = self.data[i1:i2]
return name
class IfcFile:
"""
Parses an ifc file given by filename, entities can be retrieved by name and id
@ -291,6 +299,9 @@ class IfcEntity:
def __repr__(self):
return str(self.id) + ' : ' + self.type + ' ' + str(self.attributes)
def getProperties(self):
return self.doc.find('IFCRELDEFINESBYPROPERTIES','RelatedObjects',self)
def getProperty(self,propName):
"finds the value of the given property or quantity in this object, if exists"
propsets = self.doc.find('IFCRELDEFINESBYPROPERTIES','RelatedObjects',self)
@ -322,8 +333,7 @@ class IfcEntity:
class IfcDocument:
"an object representing an IFC document"
def __init__(self,filename,schema="IFC2X3_TC1.exp",debug=False):
DEBUG = debug
def __init__(self,filename,schema="IFC2X3_TC1.exp"):
f = IfcFile(filename,schema)
self.filename = filename
self.data = f.entById
@ -441,6 +451,81 @@ class IfcDocument:
obs.extend(self.getEnt(l))
return obs
return None
def explorer(filename,schema="IFC2X3_TC1.exp"):
"returns a PySide dialog showing the contents of an IFC file"
from PySide import QtCore,QtGui
ifc = IfcDocument(filename,schema)
schema = IfcSchema(schema)
tree = QtGui.QTreeWidget()
tree.setColumnCount(3)
tree.setWordWrap(True)
tree.header().setDefaultSectionSize(60)
tree.header().resizeSection(0,60)
tree.header().resizeSection(1,30)
tree.header().setStretchLastSection(True)
tree.headerItem().setText(0, "ID")
tree.headerItem().setText(1, "")
tree.headerItem().setText(2, "Item and Properties")
bold = QtGui.QFont()
bold.setWeight(75)
bold.setBold(True)
for i in range(1,len(ifc.Entities)):
e = ifc.Entities[i]
item = QtGui.QTreeWidgetItem(tree)
item.setText(0,str(e.id))
if e.type in ["IFCWALL","IFCWALLSTANDARDCASE"]:
item.setIcon(1,QtGui.QIcon(":icons/Arch_Wall_Tree.svg"))
elif e.type in ["IFCCOLUMN","IFCBEAM","IFCSLAB","IFCFOOTING"]:
item.setIcon(1,QtGui.QIcon(":icons/Arch_Structure_Tree.svg"))
elif e.type in ["IFCSITE"]:
item.setIcon(1,QtGui.QIcon(":icons/Arch_Site_Tree.svg"))
elif e.type in ["IFCBUILDING"]:
item.setIcon(1,QtGui.QIcon(":icons/Arch_Building_Tree.svg"))
elif e.type in ["IFCSTOREY"]:
item.setIcon(1,QtGui.QIcon(":icons/Arch_Floor_Tree.svg"))
elif e.type in ["IFCWINDOW"]:
item.setIcon(1,QtGui.QIcon(":icons/Arch_Window_Tree.svg"))
elif e.type in ["IFCROOF"]:
item.setIcon(1,QtGui.QIcon(":icons/Arch_Roof_Tree.svg"))
elif e.type in ["IFCEXTRUDEDAREASOLID","IFCCLOSEDSHELL"]:
item.setIcon(1,QtGui.QIcon(":icons/Tree_Part.svg"))
elif e.type in ["IFCFACE"]:
item.setIcon(1,QtGui.QIcon(":icons/Draft_SwitchMode.svg"))
elif e.type in ["IFCARBITRARYCLOSEDPROFILEDEF","IFCPOLYLOOP"]:
item.setIcon(1,QtGui.QIcon(":icons/Draft_Draft.svg"))
item.setText(2,str(schema.capitalize(e.type)))
item.setFont(2,bold);
for a in e.attributes.keys():
if hasattr(e,a):
if not a.upper() in ["ID", "GLOBALID"]:
v = getattr(e,a)
if isinstance(v,IfcEntity):
t = "Entity #" + str(v.id) + ": " + str(v.type)
elif isinstance(v,list):
t = ""
else:
t = str(v)
t = " " + str(a) + " : " + str(t)
item = QtGui.QTreeWidgetItem(tree)
item.setText(2,str(t))
if isinstance(v,list):
for vi in v:
if isinstance(vi,IfcEntity):
t = "Entity #" + str(vi.id) + ": " + str(vi.type)
else:
t = vi
t = " " + str(t)
item = QtGui.QTreeWidgetItem(tree)
item.setText(2,str(t))
d = QtGui.QDialog()
d.setObjectName("IfcExplorer")
d.setWindowTitle("Ifc Explorer")
d.resize(640, 480)
layout = QtGui.QVBoxLayout(d)
layout.addWidget(tree)
return d
if __name__ == "__main__":
print __doc__

View File

@ -353,7 +353,8 @@ def read(filename):
schema=getSchema()
if schema:
if DEBUG: print "opening",filename,"..."
ifc = ifcReader.IfcDocument(filename,schema=schema,debug=DEBUG)
ifcReader.DEBUG = DEBUG
ifc = ifcReader.IfcDocument(filename,schema=schema)
else:
FreeCAD.Console.PrintWarning(translate("Arch","IFC Schema not found, IFC import disabled.\n"))
return None
@ -995,3 +996,20 @@ def export(exportList,filename):
print "IFC export: object type ", otype, " is not supported yet."
ifc.write()
def explore(filename=None):
"explore the contents of an ifc file in a Qt dialog"
if not filename:
from PySide import QtGui
filename = QtGui.QFileDialog.getOpenFileName(QtGui.qApp.activeWindow(),'IFC files','*.ifc')
if filename:
filename = filename[0]
if filename:
import ifcReader
getConfig()
schema=getSchema()
ifcReader.DEBUG = DEBUG
d = ifcReader.explorer(filename,schema)
d.show()
return d