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):
"""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"""
rnd = True
rnd = False
import Part
if isinstance(data,FreeCAD.Vector):
if placement:
@ -944,8 +944,26 @@ def survey(callback=False):
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 ###############################################
class _CommandAdd:
@ -1183,6 +1201,21 @@ class _CommandSurvey:
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:
FreeCADGui.addCommand('Arch_Add',_CommandAdd())
FreeCADGui.addCommand('Arch_Remove',_CommandRemove())
@ -1194,3 +1227,4 @@ if FreeCAD.GuiUp:
FreeCADGui.addCommand('Arch_Check',_CommandCheck())
FreeCADGui.addCommand('Arch_IfcExplorer',_CommandIfcExplorer())
FreeCADGui.addCommand('Arch_Survey',_CommandSurvey())
FreeCADGui.addCommand('Arch_ToggleIfcBrepFlag',_ToggleIfcBrepFlag())

View File

@ -25,6 +25,11 @@ __title__="FreeCAD Arch Component"
__author__ = "Yorik van Havre"
__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
from FreeCAD import Vector
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::PropertyString","Description","Arch","An optional description 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
self.Type = "Component"
self.Subvolume = None
@ -633,8 +640,7 @@ class ViewProviderComponent:
return
def getDisplayModes(self,vobj):
modes=["Detailed"]
return modes
return []
def setDisplayMode(self,mode):
return mode
@ -659,8 +665,6 @@ class ViewProviderComponent:
if Draft.getType(s) == "Roof":
continue
c.append(s)
if hasattr(self.Object,"Fixtures"):
c.extend(self.Object.Fixtures)
if hasattr(self.Object,"Armatures"):
c.extend(self.Object.Armatures)
if hasattr(self.Object,"Tool"):
@ -679,7 +683,8 @@ class ViewProviderComponent:
def unsetEdit(self,vobj,mode):
FreeCADGui.Control.closeDialog()
return False
class 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

View File

@ -35,11 +35,12 @@ __title__="FreeCAD Window"
__author__ = "Yorik van Havre"
__url__ = "http://www.freecadweb.org"
# presets
WindowPartTypes = ["Frame","Solid panel","Glass panel"]
AllowedHosts = ["Wall","Structure","Roof"]
WindowPresets = ["Fixed", "Open 1-pane", "Open 2-pane", "Sash 2-pane",
"Sliding 2-pane", "Simple door", "Glass door"]
Roles = ["Window","Door"]
AllowedHosts = ["Wall","Structure","Roof"]
WindowPresets = ["Fixed", "Open 1-pane", "Open 2-pane", "Sash 2-pane",
"Sliding 2-pane", "Simple door", "Glass door"]
Roles = ["Window","Door"]
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",
"Arch_SelectNonSolidMeshes","Arch_RemoveShape",
"Arch_CloseHoles","Arch_MergeWalls","Arch_Check",
"Arch_IfcExplorer"]
"Arch_IfcExplorer","Arch_ToggleIfcBrepFlag"]
# draft tools
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/Arch_StructuralSystem.svg</file>
<file>icons/Arch_StructuralSystem_Tree.svg</file>
<file>icons/Arch_ToggleIfcBrepFlag.svg</file>
<file>ui/archprefs-base.ui</file>
<file>ui/archprefs-defaults.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.
#sys.path.append("/home/yorik/Sources/build/ifcopenshell-dev")
#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
if not hasattr(IfcImport,"IfcFile"):
if (not hasattr(ifcw,"IfcFile")) and (not hasattr(ifcw,"file")):
print "Wrong version of IfcOpenShell"
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
# Basic functions #################################################################
@ -59,11 +66,6 @@ class _tempEntityHolder:
holder = _tempEntityHolder()
def new():
"""new(): returns a new empty ifc file holder"""
fil = IfcImport.IfcFile()
return fil
def uid():
"""returns a suitable GlobalID"""
u = str(uuid.uuid4())[:22]
@ -82,7 +84,11 @@ def getPropertyNames(entity):
the numbers and names of the pythonproperties available for
this entity"""
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)
return ents
@ -118,7 +124,10 @@ def create(ifcdoc=None,ifcname=None,arguments=[]):
"""create(ifcdoc,ifcname,[arguments]):creates an entity
of the given name in the given document and optionally
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:
ifcdoc.add(entity)
# 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]
if isinstance(arg,tuple):
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)
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 #################################################################
@ -288,7 +154,10 @@ class IfcDocument(object):
Creates an empty IFC document."""
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._org = create(self._fileobject,"IfcOrganization",[None,"",None,None,None])
pno = create(self._fileobject,"IfcPersonAndOrganization",[self._person,self._org,None])
@ -297,7 +166,6 @@ class IfcDocument(object):
axp = self.addPlacement(local=False)
dim0 = create(self._fileobject,"IfcDirection",getTuple((0,1,0)))
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])
dim2 = create(self._fileobject,"IfcSIUnit",[dim1,"LENGTHUNIT","MILLI","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])
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._site = create(self._fileobject,"IfcSite",[uid(),self._owner,"Site",None,None,placement,None,None,"ELEMENT",None,None,None,None,None])
self._relate(self.Project,self._site)
self.Site = None
self._storeyRelations = {}
self.BuildingProducts = []
self.Storeys = []
@ -336,7 +203,11 @@ class IfcDocument(object):
"finds an entity of a given ifctype by name"
objs = self._fileobject.by_type(ifctype)
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(i) == name:
return obj
@ -422,12 +293,24 @@ class IfcDocument(object):
else:
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):
"""addBuilding([placement,name,description]): adds a building"""
if not placement:
placement = self.addPlacement()
bdg = create(self._fileobject,"IfcBuilding",[uid(),self._owner,name,description,None,placement,None,None,"ELEMENT",None,None,None])
self._relate(self._site,bdg)
if not self.Site:
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)
return bdg
@ -435,7 +318,7 @@ class IfcDocument(object):
"""addStorey([building,placement,name,description]): adds a storey"""
if not placement:
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 self.Buildings:
building = self.Buildings[0]
@ -444,7 +327,15 @@ class IfcDocument(object):
self._relate(building,sto)
self.Storeys.append(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):
"""relate(container,entities): relates the given entities to the given
container"""
@ -479,9 +370,12 @@ class IfcDocument(object):
try:
elt = create(self._fileobject,elttype,[uid(),self._owner,name,description,None,placement,prd,None]+extra)
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:
o = IfcImport.Entity(elttype)
if hasattr(ifcw,"Entity"):
o = ifcw.Entity(elttype)
else:
o = ifcw.entity_instance(elttype)
print "supported attributes are: "
print getPropertyNames(o)
except:
@ -660,46 +554,10 @@ class IfcDocument(object):
return brp
# EXAMPLES #################################################################
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"
# EXAMPLE #################################################################
def example():
ifc = IfcDocument("/home/yorik/test2.ifc")
ifc.Name = "Test Project"
ifc.Owner = "Yorik van Havre"

View File

@ -93,13 +93,23 @@ def getConfig():
def getIfcOpenShell():
"locates and imports ifcopenshell"
global IFCOPENSHELL5
global IfcImport
IFCOPENSHELL5 = False
try:
global IfcImport
import IfcImport
except:
FreeCAD.Console.PrintMessage(translate("Arch","Couldn't locate IfcOpenShell\n"))
return False
try:
import ifc_wrapper as IfcImport
except:
FreeCAD.Console.PrintMessage(translate("Arch","Couldn't locate IfcOpenShell\n"))
return False
else:
IFCOPENSHELL5 = True
return True
else:
if hasattr(IfcImport,"IfcFile"):
IFCOPENSHELL5 = True
return True
def read(filename,skip=None):
@ -118,13 +128,6 @@ def read(filename,skip=None):
if getIfcOpenShell() and not FORCE_PYTHON_PARSER:
# use the IfcOpenShell parser
# check for IFcOpenShellVersion
global IFCOPENSHELL5
if hasattr(IfcImport,"IfcFile"):
IFCOPENSHELL5 = True
else:
IFCOPENSHELL5 = False
# preparing IfcOpenShell
if DEBUG: global ifcObjects,ifcParents
ifcObjects = {} # a table to relate ifc id with freecad object
@ -657,16 +660,20 @@ def getShape(obj,objid):
brep_data = None
if IFCOPENSHELL5:
try:
if hasattr(IfcImport,"SEW_SHELLS"):
ss = IfcImport.SEW_SHELLS
else:
ss = 0
if SEPARATE_OPENINGS and hasattr(IfcImport,"DISABLE_OPENING_SUBTRACTIONS"):
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:
brep_data = IfcImport.create_shape(obj,IfcImport.DISABLE_OPENING_SUBTRACTIONS)
brep_data = IfcImport.create_shape(obj,IfcImport.DISABLE_OPENING_SUBTRACTIONS | ss)
else:
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:
brep_data = IfcImport.create_shape(obj)
brep_data = IfcImport.create_shape(obj, ss)
except:
print "Unable to retrieve shape data"
else:
@ -918,22 +925,24 @@ def getWire(entity,placement=None):
def export(exportList,filename):
"called when freecad exports a file"
try:
import IfcImport
import IfcImport as ifcw
except:
FreeCAD.Console.PrintError(translate("Arch","Error: IfcOpenShell is not installed\n"))
print """importIFC: ifcOpenShell is not installed. IFC export is unavailable.
Note: IFC export currently requires an experimental version of IfcOpenShell
available from https://github.com/aothms/IfcOpenShell"""
return
else:
if not hasattr(IfcImport,"IfcFile"):
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"""
try:
import ifc_wrapper as ifcw
except:
FreeCAD.Console.PrintError(translate("Arch","Error: IfcOpenShell is not installed\n"))
print """importIFC: ifcOpenShell is not installed. IFC export is unavailable.
Note: IFC export currently requires an experimental version of IfcOpenShell
available from https://github.com/aothms/IfcOpenShell"""
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
getConfig()
@ -955,20 +964,26 @@ def export(exportList,filename):
objectslist = Draft.getGroupContents(exportList,walls=True,addgroups=True)
objectslist = Arch.pruneIncluded(objectslist)
sites = []
buildings = []
floors = []
groups = {}
others = []
for obj in objectslist:
otype = Draft.getType(obj)
if otype == "Building":
if otype == "Site":
sites.append(obj)
elif otype == "Building":
buildings.append(obj)
elif otype == "Floor":
floors.append(obj)
elif otype == "Group":
groups[obj.Name] = []
else:
others.append(obj)
objectslist = buildings + floors + others
if DEBUG: print "adding ", len(objectslist), " objects"
global unprocessed
unprocessed = []
@ -995,8 +1010,15 @@ def export(exportList,filename):
ifctype = "Footing"
elif ifctype == "Rebar":
ifctype = "ReinforcingBar"
elif ifctype == "Part":
elif ifctype in ["Part","Undefined"]:
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
@ -1013,8 +1035,6 @@ def export(exportList,filename):
ifc.addBuilding( name=name )
elif otype == "Floor":
ifc.addStorey( building=parent, name=name )
else:
print " Skipping (not implemented yet)" # TODO manage groups
elif obj.isDerivedFrom("Part::Feature"):
@ -1027,7 +1047,7 @@ def export(exportList,filename):
parent = ifc.findByName("IfcBuildingStorey",str(parent.Label))
# get representation
if not forcebrep:
if (not forcebrep) and (not brepflag):
gdata = Arch.getIfcExtrusionData(obj,scaling,SEPARATE_OPENINGS)
#if DEBUG: print " extrusion data for ",obj.Label," : ",gdata
if not gdata:
@ -1082,27 +1102,43 @@ def export(exportList,filename):
ifctype = "IfcBuildingElementProxy"
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
if SEPARATE_OPENINGS and gdata:
for o in obj.Subtractions:
print "Subtracting ",o.Label
fdata = Arch.getIfcBrepFacesData(o,scaling,sub=True)
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
spacer = ""
for i in range(36-len(obj.Label)):
spacer += " "
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:
unprocessed.append(obj)
else:
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()
@ -1131,7 +1167,9 @@ def export(exportList,filename):
if unprocessed:
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):