Arch: General improvements

* Removed roundings in exported objects
* Added toggleIfcBrepFlag command to force export as BREP
* Prepared Arch objects for Materials and custom IFC attributes
* Supported latest developement version of IfcOpenShell
* Cleanup of IFC exporter
* Export of Arch Sites as IfcSite
* Export of Groups as IfcGroup
This commit is contained in:
Yorik van Havre 2014-07-15 15:13:30 -03:00
parent d456cd21f9
commit 7f387eabc1
9 changed files with 304 additions and 261 deletions

View File

@ -600,7 +600,7 @@ def check(objectslist,includehidden=False):
def getTuples(data,scale=1,placement=None,normal=None,close=True): def getTuples(data,scale=1,placement=None,normal=None,close=True):
"""getTuples(data,[scale,placement,normal,close]): returns a tuple or a list of tuples from a vector """getTuples(data,[scale,placement,normal,close]): returns a tuple or a list of tuples from a vector
or from the vertices of a shape. Scale can indicate a scale factor""" or from the vertices of a shape. Scale can indicate a scale factor"""
rnd = True rnd = False
import Part import Part
if isinstance(data,FreeCAD.Vector): if isinstance(data,FreeCAD.Vector):
if placement: if placement:
@ -944,8 +944,26 @@ def survey(callback=False):
FreeCAD.SurveyObserver.selection.extend(newsels) FreeCAD.SurveyObserver.selection.extend(newsels)
def toggleIfcBrepFlag(obj):
"""toggleIfcBrepFlag(obj): toggles the IFC brep flag of the given object, forcing it
to be exported as brep geometry or not."""
if not hasattr(obj,"IfcAttributes"):
FreeCAD.Console.PrintMessage(translate("Arch","Object doesn't have settable IFC Attributes"))
else:
d = obj.IfcAttributes
if "ForceBrep" in d.keys():
if d["ForceBrep"] == "True":
d["ForceBrep"] = "False"
FreeCAD.Console.PrintMessage(translate("Arch","Disabling Brep force flag of object")+" "+obj.Label+"\n")
else:
d["ForceBrep"] = "True"
FreeCAD.Console.PrintMessage(translate("Arch","Enabling Brep force flag of object")+" "+obj.Label+"\n")
else:
d["ForceBrep"] = "True"
FreeCAD.Console.PrintMessage(translate("Arch","Enabling Brep force flag of object")+" "+obj.Label+"\n")
obj.IfcAttributes = d
# command definitions ############################################### # command definitions ###############################################
class _CommandAdd: class _CommandAdd:
@ -1183,6 +1201,21 @@ class _CommandSurvey:
FreeCADGui.doCommand("Arch.survey()") FreeCADGui.doCommand("Arch.survey()")
class _ToggleIfcBrepFlag:
"the Toggle IFC Brep flag command definition"
def GetResources(self):
return {'Pixmap' : 'Arch_ToggleIfcBrepFlag',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_ToggleIfcBrepFlag","Toggle IFC Brep flag"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_ToggleIfcBrepFlag","Force an object to be exported as Brep or not")}
def IsActive(self):
return bool(FreeCADGui.Selection.getSelection())
def Activated(self):
for o in FreeCADGui.Selection.getSelection():
toggleIfcBrepFlag(o)
if FreeCAD.GuiUp: if FreeCAD.GuiUp:
FreeCADGui.addCommand('Arch_Add',_CommandAdd()) FreeCADGui.addCommand('Arch_Add',_CommandAdd())
FreeCADGui.addCommand('Arch_Remove',_CommandRemove()) FreeCADGui.addCommand('Arch_Remove',_CommandRemove())
@ -1194,3 +1227,4 @@ if FreeCAD.GuiUp:
FreeCADGui.addCommand('Arch_Check',_CommandCheck()) FreeCADGui.addCommand('Arch_Check',_CommandCheck())
FreeCADGui.addCommand('Arch_IfcExplorer',_CommandIfcExplorer()) FreeCADGui.addCommand('Arch_IfcExplorer',_CommandIfcExplorer())
FreeCADGui.addCommand('Arch_Survey',_CommandSurvey()) FreeCADGui.addCommand('Arch_Survey',_CommandSurvey())
FreeCADGui.addCommand('Arch_ToggleIfcBrepFlag',_ToggleIfcBrepFlag())

View File

@ -25,6 +25,11 @@ __title__="FreeCAD Arch Component"
__author__ = "Yorik van Havre" __author__ = "Yorik van Havre"
__url__ = "http://www.freecadweb.org" __url__ = "http://www.freecadweb.org"
# Possible roles for IFC objects
Roles = ['Undefined','Beam','Chimney','Column','Covering','Curtain Wall','Door','Foundation',
'Member','Plate','Railing','Ramp','Ramp Flight','Rebar','Pile','Roof','Shading Device','Slab',
'Stair','Stair Flight','Tendon','Wall','Wall Layer','Window']
import FreeCAD,Draft import FreeCAD,Draft
from FreeCAD import Vector from FreeCAD import Vector
if FreeCAD.GuiUp: if FreeCAD.GuiUp:
@ -287,6 +292,8 @@ class Component:
obj.addProperty("App::PropertyLinkList","Subtractions","Arch","Other shapes that are subtracted from this object") obj.addProperty("App::PropertyLinkList","Subtractions","Arch","Other shapes that are subtracted from this object")
obj.addProperty("App::PropertyString","Description","Arch","An optional description for this component") obj.addProperty("App::PropertyString","Description","Arch","An optional description for this component")
obj.addProperty("App::PropertyString","Tag","Arch","An optional tag for this component") obj.addProperty("App::PropertyString","Tag","Arch","An optional tag for this component")
obj.addProperty("App::PropertyMap","IfcAttributes","Arch","Custom IFC properties and attributes")
obj.addProperty("App::PropertyMap","Material","Arch","A material for this object")
obj.Proxy = self obj.Proxy = self
self.Type = "Component" self.Type = "Component"
self.Subvolume = None self.Subvolume = None
@ -633,8 +640,7 @@ class ViewProviderComponent:
return return
def getDisplayModes(self,vobj): def getDisplayModes(self,vobj):
modes=["Detailed"] return []
return modes
def setDisplayMode(self,mode): def setDisplayMode(self,mode):
return mode return mode
@ -659,8 +665,6 @@ class ViewProviderComponent:
if Draft.getType(s) == "Roof": if Draft.getType(s) == "Roof":
continue continue
c.append(s) c.append(s)
if hasattr(self.Object,"Fixtures"):
c.extend(self.Object.Fixtures)
if hasattr(self.Object,"Armatures"): if hasattr(self.Object,"Armatures"):
c.extend(self.Object.Armatures) c.extend(self.Object.Armatures)
if hasattr(self.Object,"Tool"): if hasattr(self.Object,"Tool"):
@ -679,7 +683,8 @@ class ViewProviderComponent:
def unsetEdit(self,vobj,mode): def unsetEdit(self,vobj,mode):
FreeCADGui.Control.closeDialog() FreeCADGui.Control.closeDialog()
return False return False
class ArchSelectionObserver: class ArchSelectionObserver:
"""ArchSelectionObserver([origin,watched,hide,nextCommand]): The ArchSelectionObserver """ArchSelectionObserver([origin,watched,hide,nextCommand]): The ArchSelectionObserver
object can be added as a selection observer to the FreeCAD Gui. If watched is given (a object can be added as a selection observer to the FreeCAD Gui. If watched is given (a

View File

@ -35,11 +35,12 @@ __title__="FreeCAD Window"
__author__ = "Yorik van Havre" __author__ = "Yorik van Havre"
__url__ = "http://www.freecadweb.org" __url__ = "http://www.freecadweb.org"
# presets
WindowPartTypes = ["Frame","Solid panel","Glass panel"] WindowPartTypes = ["Frame","Solid panel","Glass panel"]
AllowedHosts = ["Wall","Structure","Roof"] AllowedHosts = ["Wall","Structure","Roof"]
WindowPresets = ["Fixed", "Open 1-pane", "Open 2-pane", "Sash 2-pane", WindowPresets = ["Fixed", "Open 1-pane", "Open 2-pane", "Sash 2-pane",
"Sliding 2-pane", "Simple door", "Glass door"] "Sliding 2-pane", "Simple door", "Glass door"]
Roles = ["Window","Door"] Roles = ["Window","Door"]
def makeWindow(baseobj=None,width=None,height=None,parts=None,name=translate("Arch","Window")): def makeWindow(baseobj=None,width=None,height=None,parts=None,name=translate("Arch","Window")):

File diff suppressed because one or more lines are too long

View File

@ -77,7 +77,7 @@ class ArchWorkbench(Workbench):
self.utilities = ["Arch_SplitMesh","Arch_MeshToShape", self.utilities = ["Arch_SplitMesh","Arch_MeshToShape",
"Arch_SelectNonSolidMeshes","Arch_RemoveShape", "Arch_SelectNonSolidMeshes","Arch_RemoveShape",
"Arch_CloseHoles","Arch_MergeWalls","Arch_Check", "Arch_CloseHoles","Arch_MergeWalls","Arch_Check",
"Arch_IfcExplorer"] "Arch_IfcExplorer","Arch_ToggleIfcBrepFlag"]
# draft tools # draft tools
self.drafttools = ["Draft_Line","Draft_Wire","Draft_Circle","Draft_Arc","Draft_Ellipse", self.drafttools = ["Draft_Line","Draft_Wire","Draft_Circle","Draft_Arc","Draft_Ellipse",

View File

@ -44,6 +44,7 @@
<file>icons/IFC.svg</file> <file>icons/IFC.svg</file>
<file>icons/Arch_StructuralSystem.svg</file> <file>icons/Arch_StructuralSystem.svg</file>
<file>icons/Arch_StructuralSystem_Tree.svg</file> <file>icons/Arch_StructuralSystem_Tree.svg</file>
<file>icons/Arch_ToggleIfcBrepFlag.svg</file>
<file>ui/archprefs-base.ui</file> <file>ui/archprefs-base.ui</file>
<file>ui/archprefs-defaults.ui</file> <file>ui/archprefs-defaults.ui</file>
<file>ui/archprefs-import.ui</file> <file>ui/archprefs-import.ui</file>

View File

@ -0,0 +1,106 @@
<?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="svg2985"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="Arch_MeshToShape.svg">
<defs
id="defs2987">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2993" />
</defs>
<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.703284"
inkscape:cy="30.97307"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1053"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata2990">
<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:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:#001100;stroke-width:1.85461509;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 18.878379,21.506082 -14.6157642,-8.452601 0,33.625092 14.4375222,8.931051 z"
id="path3009-7-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="color:#000000;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:#001100;stroke-width:1.85461509;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="M 35.454793,12.397645 19.05662,21.328693 18.878379,55.649495 35.276551,46.758315 z"
id="path3009-6-0-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="color:#000000;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:#001100;stroke-width:1.85461509;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="M 4.2626148,12.845174 20.482547,4.6317979 35.410233,12.446468 18.700138,21.855965 z"
id="path3029-8-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="color:#000000;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:#001100;stroke-width:1.85461509;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="M 4.8166141,13.298648 18.315926,55.59649"
id="path3055"
inkscape:connector-curvature="0" />
<path
style="color:#000000;fill:none;stroke:#001100;stroke-width:1.85461509;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="M 18.95875,55.59649 35.157924,13.041519 5.7165682,12.784389"
id="path3057"
inkscape:connector-curvature="0" />
<path
style="fill:#001bff;fill-opacity:1;stroke:#000111;stroke-width:1.85461509;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 29.21875 26.75 L 29.21875 59 L 43.71875 59 L 43.8125 35.21875 L 29.21875 26.75 z "
id="path3009-7" />
<path
style="fill:#001bff;fill-opacity:1;stroke:#000111;stroke-width:1.85461509;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 60.40625 26.09375 L 44 35.03125 L 43.875 59 L 60.21875 59 L 60.40625 26.09375 z "
id="path3009-6-0" />
<path
style="fill:#001bff;fill-opacity:1;stroke:#000111;stroke-width:1.85461509;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 29.2042,26.544252 16.219932,-8.213376 14.927686,7.814669 -16.710095,9.409498 z"
id="path3029-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -38,14 +38,21 @@ import sys, uuid, time, math
# third one. # third one.
#sys.path.append("/home/yorik/Sources/build/ifcopenshell-dev") #sys.path.append("/home/yorik/Sources/build/ifcopenshell-dev")
#from ifcwrap import IfcImport #from ifcwrap import IfcImport
import IfcImport
try:
import IfcImport as ifcw
except:
import ifc_wrapper as ifcw
else:
print "error: IfcOpenShell not found!"
sys.exit()
# checking that we got the right importer, with export capabilities # checking that we got the right importer, with export capabilities
if not hasattr(IfcImport,"IfcFile"): if (not hasattr(ifcw,"IfcFile")) and (not hasattr(ifcw,"file")):
print "Wrong version of IfcOpenShell" print "Wrong version of IfcOpenShell"
sys.exit() sys.exit()
PRECISION = 4 # rounding value, in number of digits PRECISION = 8 # rounding value, in number of digits
APPLYFIX = True # if true, the ifcopenshell bug-fixing function is applied when saving files APPLYFIX = True # if true, the ifcopenshell bug-fixing function is applied when saving files
# Basic functions ################################################################# # Basic functions #################################################################
@ -59,11 +66,6 @@ class _tempEntityHolder:
holder = _tempEntityHolder() holder = _tempEntityHolder()
def new():
"""new(): returns a new empty ifc file holder"""
fil = IfcImport.IfcFile()
return fil
def uid(): def uid():
"""returns a suitable GlobalID""" """returns a suitable GlobalID"""
u = str(uuid.uuid4())[:22] u = str(uuid.uuid4())[:22]
@ -82,7 +84,11 @@ def getPropertyNames(entity):
the numbers and names of the pythonproperties available for the numbers and names of the pythonproperties available for
this entity""" this entity"""
ents = {} ents = {}
for i in range(entity.get_argument_count()): if hasattr(entity,"get_argument_count"):
l = entity.get_argument_count()
else:
l = len(entity)
for i in range(l):
ents[i] = entity.get_argument_name(i) ents[i] = entity.get_argument_name(i)
return ents return ents
@ -118,7 +124,10 @@ def create(ifcdoc=None,ifcname=None,arguments=[]):
"""create(ifcdoc,ifcname,[arguments]):creates an entity """create(ifcdoc,ifcname,[arguments]):creates an entity
of the given name in the given document and optionally of the given name in the given document and optionally
gives it an ordered list of arguments""" gives it an ordered list of arguments"""
entity = IfcImport.Entity(ifcname) if hasattr(ifcw,"Entity"):
entity = ifcw.Entity(ifcname)
else:
entity = ifcw.entity_instance(ifcname)
if ifcdoc: if ifcdoc:
ifcdoc.add(entity) ifcdoc.add(entity)
# this is a temporary hack while ifcopenshell has no ref counting # this is a temporary hack while ifcopenshell has no ref counting
@ -129,157 +138,14 @@ def create(ifcdoc=None,ifcname=None,arguments=[]):
arg = arguments[i] arg = arguments[i]
if isinstance(arg,tuple): if isinstance(arg,tuple):
if len(arg) in [2,3]: if len(arg) in [2,3]:
arg = IfcImport.Doubles(arg) if hasattr(ifcw,"Doubles"):
arg = ifcw.Doubles(arg)
else:
arg = ifcw.doubles(arg)
entity.set_argument(i,arg) entity.set_argument(i,arg)
return entity return entity
# Convenience tools #################################################################
def makeOwner(ifcdoc,person,organization="Undefined",application="Undefined",version=0.0):
"""makeOwner(ifcdoc,person,[organization,application,version]):
creates an owner in the given ifc document"""
per = create(ifcdoc,"IfcPerson",[None,None,person,None,None,None,None,None])
org = create(ifcdoc,"IfcOrganization",[None,organization,None,None,None])
pno = create(ifcdoc,"IfcPersonAndOrganization",[per,org,None])
app = create(ifcdoc,"IfcApplication",[org,str(version),application,uid()])
own = create(ifcdoc,"IfcOwnerHistory",[pno,app,None,"ADDED",None,pno,app,now()])
return own
def makePlacement(ifcdoc,reference=None,origin=(0,0,0),xaxis=(1,0,0),zaxis=(0,0,1),local=True):
"""makePlacement(ifcdoc,[reference,origin,xaxis,zaxis]):
creates a local placement in the given ifc document. origin,
xaxis and zaxis can be either a tuple or a 3d vector"""
xvc = create(ifcdoc,"IfcDirection",getTuple(xaxis))
zvc = create(ifcdoc,"IfcDirection",getTuple(zaxis))
ovc = create(ifcdoc,"IfcCartesianPoint",getTuple(origin))
gpl = create(ifcdoc,"IfcAxis2Placement3D",[ovc,zvc,xvc])
if local:
lpl = create(ifcdoc,"IfcLocalPlacement",[reference,gpl])
return lpl
else:
return gpl
def makeContext(ifcdoc,placement=None):
"""makeContext(ifcdoc,[placement]): creates a geometric representation context
in the given ifc document"""
if not placement:
placement = makePlacement(ifcdoc)
rep = create(ifcdoc,"IfcGeometricRepresentationContext",
[None,'Model',3,1.E-05,placement,None])
return rep
def makeProject(ifcdoc,context,owner,name="Default project",description=None):
"""makeProject(ifcdoc,context,owner,[name,description]): creates a project
in the given ifc document"""
# 0: 'GlobalId', 1: 'OwnerHistory', 2: 'Name', 3: 'Description',
# 4: 'ObjectType', 5: 'LongName', 6: 'Phase', 7: 'RepresentationContexts',
# 8: 'UnitsInContext'
dim1 = create(ifcdoc,"IfcDimensionalExponents",[0,0,0,0,0,0,0])
dim2 = create(ifcdoc,"IfcSIUnit",[dim1,"LENGTHUNIT","MILLI","METRE"])
dim3 = create(ifcdoc,"IfcSIUnit",[dim1,"AREAUNIT",None,"SQUARE_METRE"])
dim4 = create(ifcdoc,"IfcSIUnit",[dim1,"VOLUMEUNIT",None,"CUBIC_METRE"])
dim6 = create(ifcdoc,"IfcSIUnit",[dim1,"PLANEANGLEUNIT",None,"RADIAN"])
dim7 = create(ifcdoc,"IfcPlaneAngleMeasure",[1.745E-2])
dim8 = create(ifcdoc,"IfcMeasureWithUnit",[dim7,dim6])
dim9 = create(ifcdoc,"IfcConversionBasedUnit",[dim1,"PLANEANGLEUNIT","DEGREE",dim8])
units = create(ifcdoc,"IfcUnitAssignment",[[dim2,dim3,dim4,dim9]])
pro = create(ifcdoc,"IfcProject",[uid(),owner,name,description,
None,None,None,[context],units])
return pro
def makeSite(ifcdoc,project,owner,placement=None,name="Default site",description=None):
"""makeSite(ifcdoc,project,owner,[placement,name,description]): creates a site
in the given ifc document"""
# 0: 'GlobalId', 1: 'OwnerHistory', 2: 'Name', 3: 'Description',
# 4: 'ObjectType', 5: 'ObjectPlacement', 6: 'Representation', 7: 'LongName',
# 8: 'CompositionType', 9: 'RefLatitude', 10: 'RefLongitude', 11: 'RefElevation',
# 12: 'LandTitleNumber', 13: 'SiteAddress'
if not placement:
placement = makePlacement(ifcdoc)
sit = create(ifcdoc,"IfcSite",[uid(),owner,name,description,None,placement,
None,None,"ELEMENT",None,None,None,None,None])
rel = create(ifcdoc,"IfcRelAggregates",[uid(),owner,'ProjectContainer',
'Project-site relationship',project,[sit]])
return sit
def makeBuilding(ifcdoc,site,owner,placement=None,name="Default building",description=None):
"""makeBuilding(ifcdoc,site,owner,[placement,name,description]): creates a building
in the given ifc document"""
# 0: 'GlobalId', 1: 'OwnerHistory', 2: 'Name', 3: 'Description',
# 4: 'ObjectType', 5: 'ObjectPlacement', 6: 'Representation', 7: 'LongName',
# 8: 'CompositionType', 9: 'ElevationOfRefHeight', 10: 'ElevationOfTerrain', 11: 'BuildingAddress'
if not placement:
placement = makePlacement(ifcdoc)
bdg = create(ifcdoc,"IfcBuilding",[uid(),owner,name,description,
None,placement,None,None,"ELEMENT",None,None,None])
rel = create(ifcdoc,"IfcRelAggregates",[uid(),owner,'SiteContainer',
'Site-Building relationship',site,[bdg]])
return bdg
def makeStorey(ifcdoc,building,owner,placement=None,name="Default storey",description=None):
"""makeStorey(ifcdoc,building,owner,[placement,name,description]): creates a storey
in the given ifc document"""
# 0: 'GlobalId', 1: 'OwnerHistory', 2: 'Name', 3: 'Description',
# 4: 'ObjectType', 5: 'ObjectPlacement', 6: 'Representation', 7: 'LongName',
# 8: 'CompositionType', 9: 'Elevation
if not placement:
placement = makePlacement(ifcdoc)
sto = create(ifcdoc,"IfcBuildingStorey",[uid(),owner,name,description,None,placement,
None,None,"ELEMENT",None])
rel = create(ifcdoc,"IfcRelAggregates",[uid(),owner,'BuildingContainer',
'Building-Stories relationship',building,[sto]])
return sto
def makeWall(ifcdoc,storey,owner,context,shape,placement=None,name="Default wall",description=None):
"""makeWall(ifcdoc,storey,owner,shape,[placement,name,description]): creates a wall
in the given ifc document"""
if not placement:
placement = makePlacement(ifcdoc)
rep = create(ifcdoc,"IfcShapeRepresentation",[context,'Body','SolidModel',[shape]])
prd = create(ifcdoc,"IfcProductDefinitionShape",[None,None,[rep]])
wal = create(ifcdoc,"IfcWallStandardCase",[uid(),owner,name,description,
None,placement,prd,None])
return wal
def makePolyline(ifcdoc,points):
"""makePolyline(ifcdoc,points): creates a polyline with the given
points in the given ifc document"""
pts = [create(ifcdoc,"IfcCartesianPoint",getTuple(p)) for p in points]
pol = create(ifcdoc,"IfcPolyline",[pts])
return pol
def makeExtrusion(ifcdoc,polyline,extrusion,placement=None):
"""makeExtrusion(ifcdoc,polyline,extrusion,[placement]): makes an
extrusion of the given polyline with the given extrusion vector in
the given ifc document"""
if not placement:
placement = makePlacement(ifcdoc,local=False)
value,norm = getValueAndDirection(extrusion)
edir = create(ifcdoc,"IfcDirection",norm)
area = create(ifcdoc,"IfcArbitraryClosedProfileDef",["AREA",None,polyline])
solid = create(ifcdoc,"IfcExtrudedAreaSolid",[area,placement,edir,value])
return solid
def relate(ifcdoc,container,owner,entities):
"""relate(ifcdoc,container,owner,entities): relates the given entities to the given
container"""
if container.is_a("IfcBuildingStorey"):
rel = create(ifcdoc,"IfcRelContainedInSpatialStructure",[uid(),owner,'StoreyLink',
'Storey-content relationship',entities, container])
else:
print "not implemented!"
# IfcDocument Object ################################################################# # IfcDocument Object #################################################################
@ -288,7 +154,10 @@ class IfcDocument(object):
Creates an empty IFC document.""" Creates an empty IFC document."""
def __init__(self,filepath="",name="",owner="",organization="",application="Python IFC exporter",version="0.0"): def __init__(self,filepath="",name="",owner="",organization="",application="Python IFC exporter",version="0.0"):
self._fileobject = IfcImport.IfcFile() if hasattr(ifcw,"IfcFile"):
self._fileobject = ifcw.IfcFile()
else:
self._fileobject = ifcw.file()
self._person = create(self._fileobject,"IfcPerson",[None,None,"",None,None,None,None,None]) self._person = create(self._fileobject,"IfcPerson",[None,None,"",None,None,None,None,None])
self._org = create(self._fileobject,"IfcOrganization",[None,"",None,None,None]) self._org = create(self._fileobject,"IfcOrganization",[None,"",None,None,None])
pno = create(self._fileobject,"IfcPersonAndOrganization",[self._person,self._org,None]) pno = create(self._fileobject,"IfcPersonAndOrganization",[self._person,self._org,None])
@ -297,7 +166,6 @@ class IfcDocument(object):
axp = self.addPlacement(local=False) axp = self.addPlacement(local=False)
dim0 = create(self._fileobject,"IfcDirection",getTuple((0,1,0))) dim0 = create(self._fileobject,"IfcDirection",getTuple((0,1,0)))
self._repcontext = create(self._fileobject,"IfcGeometricRepresentationContext",['Plan','Model',3,1.E-05,axp,dim0]) self._repcontext = create(self._fileobject,"IfcGeometricRepresentationContext",['Plan','Model',3,1.E-05,axp,dim0])
placement = create(self._fileobject,"IfcLocalPlacement",[None,axp])
dim1 = create(self._fileobject,"IfcDimensionalExponents",[0,0,0,0,0,0,0]) dim1 = create(self._fileobject,"IfcDimensionalExponents",[0,0,0,0,0,0,0])
dim2 = create(self._fileobject,"IfcSIUnit",[dim1,"LENGTHUNIT","MILLI","METRE"]) dim2 = create(self._fileobject,"IfcSIUnit",[dim1,"LENGTHUNIT","MILLI","METRE"])
dim3 = create(self._fileobject,"IfcSIUnit",[dim1,"AREAUNIT",None,"SQUARE_METRE"]) dim3 = create(self._fileobject,"IfcSIUnit",[dim1,"AREAUNIT",None,"SQUARE_METRE"])
@ -308,8 +176,7 @@ class IfcDocument(object):
dim9 = create(self._fileobject,"IfcConversionBasedUnit",[dim1,"PLANEANGLEUNIT","DEGREE",dim8]) dim9 = create(self._fileobject,"IfcConversionBasedUnit",[dim1,"PLANEANGLEUNIT","DEGREE",dim8])
units = create(self._fileobject,"IfcUnitAssignment",[[dim2,dim3,dim4,dim9]]) units = create(self._fileobject,"IfcUnitAssignment",[[dim2,dim3,dim4,dim9]])
self.Project = create(self._fileobject,"IfcProject",[uid(),self._owner,None,None,None,None,None,[self._repcontext],units]) self.Project = create(self._fileobject,"IfcProject",[uid(),self._owner,None,None,None,None,None,[self._repcontext],units])
self._site = create(self._fileobject,"IfcSite",[uid(),self._owner,"Site",None,None,placement,None,None,"ELEMENT",None,None,None,None,None]) self.Site = None
self._relate(self.Project,self._site)
self._storeyRelations = {} self._storeyRelations = {}
self.BuildingProducts = [] self.BuildingProducts = []
self.Storeys = [] self.Storeys = []
@ -336,7 +203,11 @@ class IfcDocument(object):
"finds an entity of a given ifctype by name" "finds an entity of a given ifctype by name"
objs = self._fileobject.by_type(ifctype) objs = self._fileobject.by_type(ifctype)
for obj in objs: for obj in objs:
for i in range(obj.get_argument_count()): if hasattr(obj,"get_argument_count"):
l = obj.get_argument_count()
else:
l = len(obj)
for i in range(l):
if obj.get_argument_name(i) == "Name": if obj.get_argument_name(i) == "Name":
if obj.get_argument(i) == name: if obj.get_argument(i) == name:
return obj return obj
@ -422,12 +293,24 @@ class IfcDocument(object):
else: else:
return gpl return gpl
def addSite(self,placement=None,name="Site",description=None,latitude=None,longitude=None,elevation=None,landtitlenumber=None,address=None):
"""makeSite(ifcdoc,project,owner,[placement,name,description]): creates a site
in the given ifc document"""
if self.Site:
return
if not placement:
placement = self.addPlacement()
self.Site = create(self._fileobject,"IfcSite",[uid(),self._owner,str(name),description,None,placement,None,None,"ELEMENT",latitude,longitude,elevation,landtitlenumber,address])
self._relate(self.Project,self.Site)
def addBuilding(self,placement=None,name="Default building",description=None): def addBuilding(self,placement=None,name="Default building",description=None):
"""addBuilding([placement,name,description]): adds a building""" """addBuilding([placement,name,description]): adds a building"""
if not placement: if not placement:
placement = self.addPlacement() placement = self.addPlacement()
bdg = create(self._fileobject,"IfcBuilding",[uid(),self._owner,name,description,None,placement,None,None,"ELEMENT",None,None,None]) if not self.Site:
self._relate(self._site,bdg) self.addSite()
bdg = create(self._fileobject,"IfcBuilding",[uid(),self._owner,str(name),description,None,placement,None,None,"ELEMENT",None,None,None])
self._relate(self.Site,bdg)
self.Buildings.append(bdg) self.Buildings.append(bdg)
return bdg return bdg
@ -435,7 +318,7 @@ class IfcDocument(object):
"""addStorey([building,placement,name,description]): adds a storey""" """addStorey([building,placement,name,description]): adds a storey"""
if not placement: if not placement:
placement = self.addPlacement() placement = self.addPlacement()
sto = create(self._fileobject,"IfcBuildingStorey",[uid(),self._owner,name,description,None,placement,None,None,"ELEMENT",None]) sto = create(self._fileobject,"IfcBuildingStorey",[uid(),self._owner,str(name),description,None,placement,None,None,"ELEMENT",None])
if not building: if not building:
if self.Buildings: if self.Buildings:
building = self.Buildings[0] building = self.Buildings[0]
@ -444,7 +327,15 @@ class IfcDocument(object):
self._relate(building,sto) self._relate(building,sto)
self.Storeys.append(sto) self.Storeys.append(sto)
return sto return sto
def addGroup(self,entities,name="Default group",description=None):
"""addGroup(entities,[name,description]): adds a group with the given entities"""
if not isinstance(entities,list):
entities = [entities]
gro = create(self._fileobject,"IfcGroup",[uid(),self._owner,str(name),description,None])
rel = create(self._fileobject,"IfcRelAssignsToGroup",[uid(),self._owner,str(name)+"-relation",None,entities,"PRODUCT",gro])
return gro
def _relate(self,container,entities): def _relate(self,container,entities):
"""relate(container,entities): relates the given entities to the given """relate(container,entities): relates the given entities to the given
container""" container"""
@ -479,9 +370,12 @@ class IfcDocument(object):
try: try:
elt = create(self._fileobject,elttype,[uid(),self._owner,name,description,None,placement,prd,None]+extra) elt = create(self._fileobject,elttype,[uid(),self._owner,name,description,None,placement,prd,None]+extra)
except: except:
print "unable to create an ",elttype, " with attributes: ",[uid(),self._owner,name,description,None,placement,prd,None]+extra print "unable to create an ",elttype, " with attributes: ",[uid(),self._owner,str(name),description,None,placement,prd,None]+extra
try: try:
o = IfcImport.Entity(elttype) if hasattr(ifcw,"Entity"):
o = ifcw.Entity(elttype)
else:
o = ifcw.entity_instance(elttype)
print "supported attributes are: " print "supported attributes are: "
print getPropertyNames(o) print getPropertyNames(o)
except: except:
@ -660,46 +554,10 @@ class IfcDocument(object):
return brp return brp
# EXAMPLES ################################################################# # EXAMPLE #################################################################
def example1():
"creation of a new file using manual, step-by-step procedure"
f = new()
own = makeOwner(f,"Yorik van Havre")
plac = makePlacement(f)
grep = makeContext(f,plac)
proj = makeProject(f,grep,own)
site = makeSite(f,proj,own)
bldg = makeBuilding(f,site,own)
stor = makeStorey(f,bldg,own)
poly = makePolyline(f,[(0,0,0),(0,200,0),(5000,200,0),(5000,0,0),(0,0,0)])
solid = makeExtrusion(f,poly,(0,0,3500))
wall = makeWall(f,stor,own,grep,solid)
poly2 = makePolyline(f,[(0,200,0),(0,2000,0),(200,2000,0),(200,200,0),(0,200,0)])
solid2 = makeExtrusion(f,poly2,(0,0,3500))
wall2 = makeWall(f,stor,own,grep,solid2)
poly3 = makePolyline(f,[(0,2000,0),(0,2200,0),(5000,2200,0),(5000,2000,0),(0,2000,0)])
solid3 = makeExtrusion(f,poly3,(0,0,3500))
wall3 = makeWall(f,stor,own,grep,solid3)
poly4 = makePolyline(f,[(5000,200,0),(5000,2000,0),(4800,2000,0),(4800,200,0),(5000,200,0)])
solid4 = makeExtrusion(f,poly4,(0,0,3500))
wall4 = makeWall(f,stor,own,grep,solid4)
relate(f,stor,own,[wall,wall2,wall3,wall4])
f.write("/home/yorik/test1.ifc")
print dir(f)
print f.by_type("IfcWallStandardCase")
w = f.by_type("IfcWallStandardCase")[0]
print w
print dir(w)
print w.is_a("IfcWallStandardCase")
def example2():
"creation of a new file using advanced IfcDocument object"
def example():
ifc = IfcDocument("/home/yorik/test2.ifc") ifc = IfcDocument("/home/yorik/test2.ifc")
ifc.Name = "Test Project" ifc.Name = "Test Project"
ifc.Owner = "Yorik van Havre" ifc.Owner = "Yorik van Havre"

View File

@ -93,13 +93,23 @@ def getConfig():
def getIfcOpenShell(): def getIfcOpenShell():
"locates and imports ifcopenshell" "locates and imports ifcopenshell"
global IFCOPENSHELL5
global IfcImport
IFCOPENSHELL5 = False
try: try:
global IfcImport
import IfcImport import IfcImport
except: except:
FreeCAD.Console.PrintMessage(translate("Arch","Couldn't locate IfcOpenShell\n")) try:
return False import ifc_wrapper as IfcImport
except:
FreeCAD.Console.PrintMessage(translate("Arch","Couldn't locate IfcOpenShell\n"))
return False
else:
IFCOPENSHELL5 = True
return True
else: else:
if hasattr(IfcImport,"IfcFile"):
IFCOPENSHELL5 = True
return True return True
def read(filename,skip=None): def read(filename,skip=None):
@ -118,13 +128,6 @@ def read(filename,skip=None):
if getIfcOpenShell() and not FORCE_PYTHON_PARSER: if getIfcOpenShell() and not FORCE_PYTHON_PARSER:
# use the IfcOpenShell parser # use the IfcOpenShell parser
# check for IFcOpenShellVersion
global IFCOPENSHELL5
if hasattr(IfcImport,"IfcFile"):
IFCOPENSHELL5 = True
else:
IFCOPENSHELL5 = False
# preparing IfcOpenShell # preparing IfcOpenShell
if DEBUG: global ifcObjects,ifcParents if DEBUG: global ifcObjects,ifcParents
ifcObjects = {} # a table to relate ifc id with freecad object ifcObjects = {} # a table to relate ifc id with freecad object
@ -657,16 +660,20 @@ def getShape(obj,objid):
brep_data = None brep_data = None
if IFCOPENSHELL5: if IFCOPENSHELL5:
try: try:
if hasattr(IfcImport,"SEW_SHELLS"):
ss = IfcImport.SEW_SHELLS
else:
ss = 0
if SEPARATE_OPENINGS and hasattr(IfcImport,"DISABLE_OPENING_SUBTRACTIONS"): if SEPARATE_OPENINGS and hasattr(IfcImport,"DISABLE_OPENING_SUBTRACTIONS"):
if SEPARATE_PLACEMENTS and hasattr(IfcImport,"DISABLE_OBJECT_PLACEMENT"): if SEPARATE_PLACEMENTS and hasattr(IfcImport,"DISABLE_OBJECT_PLACEMENT"):
brep_data = IfcImport.create_shape(obj,IfcImport.DISABLE_OPENING_SUBTRACTIONS | IfcImport.DISABLE_OBJECT_PLACEMENT) brep_data = IfcImport.create_shape(obj,IfcImport.DISABLE_OPENING_SUBTRACTIONS | IfcImport.DISABLE_OBJECT_PLACEMENT | ss)
else: else:
brep_data = IfcImport.create_shape(obj,IfcImport.DISABLE_OPENING_SUBTRACTIONS) brep_data = IfcImport.create_shape(obj,IfcImport.DISABLE_OPENING_SUBTRACTIONS | ss)
else: else:
if SEPARATE_PLACEMENTS and hasattr(IfcImport,"DISABLE_OBJECT_PLACEMENT"): if SEPARATE_PLACEMENTS and hasattr(IfcImport,"DISABLE_OBJECT_PLACEMENT"):
brep_data = IfcImport.create_shape(obj,IfcImport.DISABLE_OBJECT_PLACEMENT) brep_data = IfcImport.create_shape(obj,IfcImport.DISABLE_OBJECT_PLACEMENT | ss)
else: else:
brep_data = IfcImport.create_shape(obj) brep_data = IfcImport.create_shape(obj, ss)
except: except:
print "Unable to retrieve shape data" print "Unable to retrieve shape data"
else: else:
@ -918,22 +925,24 @@ def getWire(entity,placement=None):
def export(exportList,filename): def export(exportList,filename):
"called when freecad exports a file" "called when freecad exports a file"
try: try:
import IfcImport import IfcImport as ifcw
except: except:
FreeCAD.Console.PrintError(translate("Arch","Error: IfcOpenShell is not installed\n")) try:
print """importIFC: ifcOpenShell is not installed. IFC export is unavailable. import ifc_wrapper as ifcw
Note: IFC export currently requires an experimental version of IfcOpenShell except:
available from https://github.com/aothms/IfcOpenShell""" FreeCAD.Console.PrintError(translate("Arch","Error: IfcOpenShell is not installed\n"))
return print """importIFC: ifcOpenShell is not installed. IFC export is unavailable.
else: Note: IFC export currently requires an experimental version of IfcOpenShell
if not hasattr(IfcImport,"IfcFile"): available from https://github.com/aothms/IfcOpenShell"""
FreeCAD.Console.PrintError(translate("Arch","Error: your IfcOpenShell version is too old\n"))
print """importIFC: The version of ifcOpenShell installed on this system doesn't
have IFC export capabilities. IFC export currently requires an experimental
version of IfcOpenShell available from https://github.com/aothms/IfcOpenShell"""
return return
import ifcWriter
import Arch,Draft if (not hasattr(ifcw,"IfcFile")) and (not hasattr(ifcw,"file")):
FreeCAD.Console.PrintError(translate("Arch","Error: your IfcOpenShell version is too old\n"))
print """importIFC: The version of ifcOpenShell installed on this system doesn't
have IFC export capabilities. IFC export currently requires an experimental
version of IfcOpenShell available from https://github.com/aothms/IfcOpenShell"""
return
import ifcWriter,Arch,Draft
# creating base IFC project # creating base IFC project
getConfig() getConfig()
@ -955,20 +964,26 @@ def export(exportList,filename):
objectslist = Draft.getGroupContents(exportList,walls=True,addgroups=True) objectslist = Draft.getGroupContents(exportList,walls=True,addgroups=True)
objectslist = Arch.pruneIncluded(objectslist) objectslist = Arch.pruneIncluded(objectslist)
sites = []
buildings = [] buildings = []
floors = [] floors = []
groups = {}
others = [] others = []
for obj in objectslist: for obj in objectslist:
otype = Draft.getType(obj) otype = Draft.getType(obj)
if otype == "Building": if otype == "Site":
sites.append(obj)
elif otype == "Building":
buildings.append(obj) buildings.append(obj)
elif otype == "Floor": elif otype == "Floor":
floors.append(obj) floors.append(obj)
elif otype == "Group":
groups[obj.Name] = []
else: else:
others.append(obj) others.append(obj)
objectslist = buildings + floors + others objectslist = buildings + floors + others
if DEBUG: print "adding ", len(objectslist), " objects" if DEBUG: print "adding ", len(objectslist), " objects"
global unprocessed global unprocessed
unprocessed = [] unprocessed = []
@ -995,8 +1010,15 @@ def export(exportList,filename):
ifctype = "Footing" ifctype = "Footing"
elif ifctype == "Rebar": elif ifctype == "Rebar":
ifctype = "ReinforcingBar" ifctype = "ReinforcingBar"
elif ifctype == "Part": elif ifctype in ["Part","Undefined"]:
ifctype = "BuildingElementProxy" ifctype = "BuildingElementProxy"
# getting the "Force BREP" flag
brepflag = False
if hasattr(obj,"IfcAttributes"):
if "ForceBrep" in obj.IfcAttributes.keys():
if obj.IfcAttributes["ForceBrep"] == "True":
brepflag = True
if DEBUG: print "Adding " + obj.Label + " as Ifc" + ifctype if DEBUG: print "Adding " + obj.Label + " as Ifc" + ifctype
@ -1013,8 +1035,6 @@ def export(exportList,filename):
ifc.addBuilding( name=name ) ifc.addBuilding( name=name )
elif otype == "Floor": elif otype == "Floor":
ifc.addStorey( building=parent, name=name ) ifc.addStorey( building=parent, name=name )
else:
print " Skipping (not implemented yet)" # TODO manage groups
elif obj.isDerivedFrom("Part::Feature"): elif obj.isDerivedFrom("Part::Feature"):
@ -1027,7 +1047,7 @@ def export(exportList,filename):
parent = ifc.findByName("IfcBuildingStorey",str(parent.Label)) parent = ifc.findByName("IfcBuildingStorey",str(parent.Label))
# get representation # get representation
if not forcebrep: if (not forcebrep) and (not brepflag):
gdata = Arch.getIfcExtrusionData(obj,scaling,SEPARATE_OPENINGS) gdata = Arch.getIfcExtrusionData(obj,scaling,SEPARATE_OPENINGS)
#if DEBUG: print " extrusion data for ",obj.Label," : ",gdata #if DEBUG: print " extrusion data for ",obj.Label," : ",gdata
if not gdata: if not gdata:
@ -1082,27 +1102,43 @@ def export(exportList,filename):
ifctype = "IfcBuildingElementProxy" ifctype = "IfcBuildingElementProxy"
extra = ["ELEMENT"] extra = ["ELEMENT"]
p = ifc.addProduct( ifctype, representation, storey=parent, placement=placement, name=name, description=descr, extra=extra ) product = ifc.addProduct( ifctype, representation, storey=parent, placement=placement, name=name, description=descr, extra=extra )
if p: if product:
# removing openings # removing openings
if SEPARATE_OPENINGS and gdata: if SEPARATE_OPENINGS and gdata:
for o in obj.Subtractions: for o in obj.Subtractions:
print "Subtracting ",o.Label print "Subtracting ",o.Label
fdata = Arch.getIfcBrepFacesData(o,scaling,sub=True) fdata = Arch.getIfcBrepFacesData(o,scaling,sub=True)
representation = [ifc.addFacetedBrep(f, color=color) for f in fdata] representation = [ifc.addFacetedBrep(f, color=color) for f in fdata]
p2 = ifc.addProduct( "IfcOpeningElement", representation, storey=p, placement=None, name=str(o.Label), description=None) p2 = ifc.addProduct( "IfcOpeningElement", representation, storey=product, placement=None, name=str(o.Label), description=None)
# writing text log # writing text log
spacer = "" spacer = ""
for i in range(36-len(obj.Label)): for i in range(36-len(obj.Label)):
spacer += " " spacer += " "
txt.append(obj.Label + spacer + ifctype) txt.append(obj.Label + spacer + ifctype)
# adding object to group, if any
for g in groups.keys():
group = FreeCAD.ActiveDocument.getObject(g)
if group:
for o in group.Group:
if o.Name == obj.Name:
groups[g].append(product)
else: else:
unprocessed.append(obj) unprocessed.append(obj)
else: else:
if DEBUG: print "Object type ", otype, " is not supported yet." if DEBUG: print "Object type ", otype, " is not supported yet."
# processing groups
for name,entities in groups.iteritems():
if entities:
o = FreeCAD.ActiveDocument.getObject(name)
if o:
if DEBUG: print "Adding group ", o.Label, " with ",len(entities)," elements"
grp = ifc.addGroup( entities, o.Label )
ifc.write() ifc.write()
@ -1131,7 +1167,9 @@ def export(exportList,filename):
if unprocessed: if unprocessed:
print "" print ""
print "WARNING: Some objects were not exported. See importIFC.unprocessed" print "WARNING: " + str(len(unprocessed)) + " objects were not exported (stored in importIFC.unprocessed):"
for o in unprocessed:
print " " + o.Label
def explore(filename=None): def explore(filename=None):