diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py
index c098f9371..d140a8dd6 100644
--- a/src/Mod/Arch/ArchCommands.py
+++ b/src/Mod/Arch/ArchCommands.py
@@ -192,6 +192,23 @@ def removeComponents(objectsList,host=None):
if o in a:
a.remove(o)
h.Objects = a
+
+def makeComponent(baseobj=None,name="Component"):
+ '''makeComponent([baseobj]): creates an undefined, non-parametric Arch
+ component from the given base object'''
+ obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
+ obj.Label = translate("Arch",name)
+ ArchComponent.Component(obj)
+ if FreeCAD.GuiUp:
+ ArchComponent.ViewProviderComponent(obj.ViewObject)
+ if baseobj:
+ import Part
+ if baseobj.isDerivedFrom("Part::Feature"):
+ obj.Shape = baseobj.Shape
+ obj.Placement = baseobj.Placement
+ elif isinstance(baseobj,Part.Shape):
+ obj.Shape = baseobj
+ return obj
def fixWindow(obj):
'''fixWindow(object): Fixes non-DAG problems in windows
@@ -1114,6 +1131,29 @@ class _ToggleIfcBrepFlag:
def Activated(self):
for o in FreeCADGui.Selection.getSelection():
toggleIfcBrepFlag(o)
+
+
+class _CommandComponent:
+ "the Arch Component command definition"
+ def GetResources(self):
+ return {'Pixmap' : 'Arch_Component',
+ 'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_Component","Component"),
+ 'Accel': "C, M",
+ 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Component","Creates an undefined architectural component")}
+
+ def IsActive(self):
+ return not FreeCAD.ActiveDocument is None
+
+ def Activated(self):
+ sel = FreeCADGui.Selection.getSelection()
+ if sel:
+ FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create Component"))
+ FreeCADGui.addModule("Arch")
+ FreeCADGui.Control.closeDialog()
+ for o in sel:
+ FreeCADGui.doCommand("Arch.makeComponent(FreeCAD.ActiveDocument."+o.Name+")")
+ FreeCAD.ActiveDocument.commitTransaction()
+ FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
@@ -1128,3 +1168,4 @@ if FreeCAD.GuiUp:
FreeCADGui.addCommand('Arch_IfcExplorer',_CommandIfcExplorer())
FreeCADGui.addCommand('Arch_Survey',_CommandSurvey())
FreeCADGui.addCommand('Arch_ToggleIfcBrepFlag',_ToggleIfcBrepFlag())
+ FreeCADGui.addCommand('Arch_Component',_CommandComponent())
diff --git a/src/Mod/Arch/ArchComponent.py b/src/Mod/Arch/ArchComponent.py
index 93adf7ac0..a5f229ec7 100644
--- a/src/Mod/Arch/ArchComponent.py
+++ b/src/Mod/Arch/ArchComponent.py
@@ -40,6 +40,7 @@ if FreeCAD.GuiUp:
else:
def translate(ctxt,txt):
return txt
+
def addToComponent(compobject,addobject,mod=None):
'''addToComponent(compobject,addobject,mod): adds addobject
@@ -132,8 +133,8 @@ class SelectionTaskPanel:
FreeCADGui.Selection.removeObserver(FreeCAD.ArchObserver)
del FreeCAD.ArchObserver
return True
-
-
+
+
class ComponentTaskPanel:
'''The default TaskPanel for all Arch components'''
def __init__(self):
@@ -289,6 +290,7 @@ class Component:
"The default Arch Component object"
def __init__(self,obj):
obj.addProperty("App::PropertyLink","Base","Arch",translate("Arch","The base object this component is built upon"))
+ obj.addProperty("App::PropertyLink","CloneOf","Arch",translate("Arch","The object this component is cloning"))
obj.addProperty("App::PropertyLinkList","Additions","Arch",translate("Arch","Other shapes that are appended to this object"))
obj.addProperty("App::PropertyLinkList","Subtractions","Arch",translate("Arch","Other shapes that are subtracted from this object"))
obj.addProperty("App::PropertyString","Description","Arch",translate("Arch","An optional description for this component"))
@@ -316,6 +318,17 @@ class Component:
def onChanged(self,obj,prop):
pass
+ def clone(self,obj):
+ "if this object is a clone, sets the shape. Returns True if this is the case"
+ if hasattr(obj,"CloneOf"):
+ if obj.CloneOf:
+ if Draft.getType(obj.CloneOf) == Draft.getType(obj):
+ pl = obj.Placement
+ obj.Shape = obj.CloneOf.Shape.copy()
+ obj.Placement = pl
+ return True
+ return False
+
def getSiblings(self,obj):
"returns a list of objects with the same type and same base as this object"
if not hasattr(obj,"Base"):
@@ -642,6 +655,10 @@ class ViewProviderComponent:
def updateData(self,obj,prop):
return
+
+ def getIcon(self):
+ import Arch_rc
+ return ":/icons/Arch_Component.svg"
def onChanged(self,vobj,prop):
if prop == "Visibility":
diff --git a/src/Mod/Arch/ArchEquipment.py b/src/Mod/Arch/ArchEquipment.py
index 3add4e60d..4b8914f66 100644
--- a/src/Mod/Arch/ArchEquipment.py
+++ b/src/Mod/Arch/ArchEquipment.py
@@ -248,6 +248,10 @@ class _Equipment(ArchComponent.Component):
self.hideSubobjects(obj,prop)
def execute(self,obj):
+
+ if self.clone(obj):
+ return
+
pl = obj.Placement
if obj.Base:
if obj.isDerivedFrom("Mesh::Feature"):
diff --git a/src/Mod/Arch/ArchFrame.py b/src/Mod/Arch/ArchFrame.py
index 1baa5bc2f..3e00ac1d4 100644
--- a/src/Mod/Arch/ArchFrame.py
+++ b/src/Mod/Arch/ArchFrame.py
@@ -90,6 +90,10 @@ class _Frame(ArchComponent.Component):
obj.Role = Roles
def execute(self,obj):
+
+ if self.clone(obj):
+ return
+
if not obj.Base:
return
if not obj.Base.Shape:
diff --git a/src/Mod/Arch/ArchPanel.py b/src/Mod/Arch/ArchPanel.py
index 78c75ed13..38e122d53 100644
--- a/src/Mod/Arch/ArchPanel.py
+++ b/src/Mod/Arch/ArchPanel.py
@@ -265,6 +265,9 @@ class _Panel(ArchComponent.Component):
def execute(self,obj):
"creates the panel shape"
+
+ if self.clone(obj):
+ return
import Part, DraftGeomUtils
diff --git a/src/Mod/Arch/ArchRebar.py b/src/Mod/Arch/ArchRebar.py
index f3e982799..4f1bcd953 100644
--- a/src/Mod/Arch/ArchRebar.py
+++ b/src/Mod/Arch/ArchRebar.py
@@ -158,6 +158,10 @@ class _Rebar(ArchComponent.Component):
return None,None
def execute(self,obj):
+
+ if self.clone(obj):
+ return
+
if len(obj.InList) != 1:
return
if Draft.getType(obj.InList[0]) != "Structure":
diff --git a/src/Mod/Arch/ArchRoof.py b/src/Mod/Arch/ArchRoof.py
index 645b57cba..13b455a9e 100644
--- a/src/Mod/Arch/ArchRoof.py
+++ b/src/Mod/Arch/ArchRoof.py
@@ -35,19 +35,28 @@ __title__="FreeCAD Roof"
__author__ = "Yorik van Havre", "Jonathan Wiedemann"
__url__ = "http://www.freecadweb.org"
-def makeRoof(baseobj=None,facenr=1, angles=[45.,], run = [], idrel = [0,],thickness = [1.,], overhang=[2.,], name="Roof"):
+def makeRoof(baseobj=None,facenr=0, angles=[45.,], run = [], idrel = [0,],thickness = [1.,], overhang=[2.,], name="Roof"):
'''makeRoof(baseobj,[facenr],[angle],[name]) : Makes a roof based on a closed wire.
face from an existing object. You can provide a list of angles, run, idrel, thickness,
overhang for each edges in the wire to define the roof shape. The default for angle is 45
and the list is automatically complete to match with number of edges in the wire.'''
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
obj.Label = translate("Arch",name)
+ w = None
_Roof(obj)
if FreeCAD.GuiUp:
_ViewProviderRoof(obj.ViewObject)
if baseobj:
obj.Base = baseobj
if obj.Base.isDerivedFrom("Part::Feature"):
+ if (facenr == 0) and obj.Base.Shape.Solids:
+ # the base shape is a solid and facenr hasn't been set:
+ # assume its shape is copied over
+ if FreeCAD.GuiUp:
+ obj.Base.ViewObject.hide()
+ else:
+ # set facenr to 1
+ facenr = 1
if (obj.Base.Shape.Faces and obj.Face):
w = obj.Base.Shape.Faces[obj.Face-1].Wires[0]
elif obj.Base.Shape.Wires:
@@ -509,6 +518,10 @@ class _Roof(ArchComponent.Component):
print("PROFIL " + str(i) + " : End calculs")
def execute(self,obj):
+
+ if self.clone(obj):
+ return
+
import Part, math, DraftGeomUtils
pl = obj.Placement
self.baseface = None
diff --git a/src/Mod/Arch/ArchSpace.py b/src/Mod/Arch/ArchSpace.py
index 2f2837a4e..762b4c728 100644
--- a/src/Mod/Arch/ArchSpace.py
+++ b/src/Mod/Arch/ArchSpace.py
@@ -236,6 +236,10 @@ class _Space(ArchComponent.Component):
obj.Role = Roles
def execute(self,obj):
+
+ if self.clone(obj):
+ return
+
self.getShape(obj)
def onChanged(self,obj,prop):
diff --git a/src/Mod/Arch/ArchStairs.py b/src/Mod/Arch/ArchStairs.py
index c36ff29aa..31f6e3e14 100644
--- a/src/Mod/Arch/ArchStairs.py
+++ b/src/Mod/Arch/ArchStairs.py
@@ -130,7 +130,10 @@ class _Stairs(ArchComponent.Component):
def execute(self,obj):
"constructs the shape of the stairs"
-
+
+ if self.clone(obj):
+ return
+
import Part
self.steps = []
self.pseudosteps = []
diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py
index 0a2636381..dd15ad164 100644
--- a/src/Mod/Arch/ArchStructure.py
+++ b/src/Mod/Arch/ArchStructure.py
@@ -577,6 +577,9 @@ class _Structure(ArchComponent.Component):
"creates the structure shape"
import Part, DraftGeomUtils
+
+ if self.clone(obj):
+ return
normal,length,width,height = self.getDefaultValues(obj)
diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py
index 12dc747df..bbce19072 100644
--- a/src/Mod/Arch/ArchWall.py
+++ b/src/Mod/Arch/ArchWall.py
@@ -402,6 +402,9 @@ class _Wall(ArchComponent.Component):
def execute(self,obj):
"builds the wall shape"
+
+ if self.clone(obj):
+ return
import Part, DraftGeomUtils
pl = obj.Placement
diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py
index a91d41c2e..830aafd9a 100644
--- a/src/Mod/Arch/ArchWindow.py
+++ b/src/Mod/Arch/ArchWindow.py
@@ -636,6 +636,10 @@ class _Window(ArchComponent.Component):
def execute(self,obj):
+
+ if self.clone(obj):
+ return
+
import Part, DraftGeomUtils
pl = obj.Placement
base = None
diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py
index c45bcce85..655001bae 100644
--- a/src/Mod/Arch/InitGui.py
+++ b/src/Mod/Arch/InitGui.py
@@ -75,7 +75,7 @@ class ArchWorkbench(Workbench):
"Arch_SectionPlane","Arch_Space","Arch_Stairs",
"Arch_Panel","Arch_Equipment",
"Arch_Frame","Arch_CutPlane","Arch_Add","Arch_Remove","Arch_Survey"]
- self.utilities = ["Arch_SplitMesh","Arch_MeshToShape",
+ self.utilities = ["Arch_Component","Arch_SplitMesh","Arch_MeshToShape",
"Arch_SelectNonSolidMeshes","Arch_RemoveShape",
"Arch_CloseHoles","Arch_MergeWalls","Arch_Check",
"Arch_IfcExplorer","Arch_ToggleIfcBrepFlag","Arch_3Views",
diff --git a/src/Mod/Arch/Resources/Arch.qrc b/src/Mod/Arch/Resources/Arch.qrc
index 10a0487d2..733740346 100644
--- a/src/Mod/Arch/Resources/Arch.qrc
+++ b/src/Mod/Arch/Resources/Arch.qrc
@@ -53,6 +53,7 @@
icons/Arch_CutPlane.svgicons/Arch_Bimserver.svgicons/Git.svg
+ icons/Arch_Component.svgui/archprefs-base.uiui/archprefs-defaults.uiui/archprefs-import.ui
diff --git a/src/Mod/Arch/Resources/icons/Arch_Component.svg b/src/Mod/Arch/Resources/icons/Arch_Component.svg
new file mode 100644
index 000000000..82c6c6d7a
--- /dev/null
+++ b/src/Mod/Arch/Resources/icons/Arch_Component.svg
@@ -0,0 +1,96 @@
+
+
+
+
diff --git a/src/Mod/Arch/Resources/ui/archprefs-import.ui b/src/Mod/Arch/Resources/ui/archprefs-import.ui
index bafd51c26..912c2c8b4 100644
--- a/src/Mod/Arch/Resources/ui/archprefs-import.ui
+++ b/src/Mod/Arch/Resources/ui/archprefs-import.ui
@@ -6,8 +6,8 @@
00
- 503
- 526
+ 463
+ 516
@@ -26,12 +26,83 @@
IFC import
+
+
+
+
+
+ Import IFC objects as
+
+
+
+
+
+
+ Specifies what kind of objects will be created in FreeCAD
+
+
+ ifcImportMode
+
+
+ Mod/Arch
+
+
+
+ Parametric Arch objects
+
+
+
+
+ Non-parametric Arch objects
+
+
+
+
+ Simple Part shapes
+
+
+
+
+ One compound per floor
+
+
+
+
+
+
+
+
+
+
+
+ Root element:
+
+
+
+
+
+
+ Only subtypes of this element will be imported. Keep value as "IfcProduct" to import all building elements.
+
+
+ IfcProduct
+
+
+ ifcRootElement
+
+
+ Mod/Arch
+
+
+
+
+
- Check this to display debug messages while importing IFC files
+ Show verbose information during import and export of IFC filesShow debug messages
@@ -86,6 +157,29 @@
+
+
+
+
+
+ Check this to retrieve object colors.
+
+
+ Read colors
+
+
+ true
+
+
+ ifcReadColors
+
+
+ Mod/Arch
+
+
+
+
+
@@ -125,6 +219,17 @@
IFC export
+
+
+
+
+
+ "Show debug messages" option above will apply to export too
+
+
+
+
+
@@ -250,6 +355,11 @@
QCheckBoxGui/PrefWidgets.h
+
+ Gui::PrefComboBox
+ QComboBox
+ Gui/PrefWidgets.h
+ Gui::PrefLineEditQLineEdit
diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py
index f856b0a42..3bc6e687f 100644
--- a/src/Mod/Arch/importIFC.py
+++ b/src/Mod/Arch/importIFC.py
@@ -246,24 +246,36 @@ def explore(filename=None):
return
-def open(filename,skip=[]):
+def open(filename,skip=[],only=[],root=None):
"opens an IFC file in a new document"
docname = os.path.splitext(os.path.basename(filename))[0]
doc = FreeCAD.newDocument(docname)
doc.Label = docname
- doc = insert(filename,doc.Name,skip)
+ doc = insert(filename,doc.Name,skip,only,root)
return doc
-def insert(filename,docname,skip=[]):
- "imports the contents of an IFC file"
+def insert(filename,docname,skip=[],only=[],root=None):
+ """insert(filename,docname,skip=[],only=[],root=None): imports the contents of an IFC file.
+ skip can contain a list of ids of objects to be skipped, only can restrict the import to
+ certain object ids (will also get their children) and root can be used to
+ import only the derivates of a certain element type (default = ifcProduct)."""
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
DEBUG = p.GetBool("ifcDebug",False)
PREFIX_NUMBERS = p.GetBool("ifcPrefixNumbers",False)
- SKIP = p.GetString("ifcSkip","")
+ SKIP = p.GetString("ifcSkip","").split(",")
SEPARATE_OPENINGS = p.GetBool("ifcSeparateOpenings",False)
+ ROOT_ELEMENT = p.GetString("ifcRootElement","IfcProduct")
+ if root:
+ ROOT_ELEMENT = root
+ MERGE_MODE = p.GetInt("ifcImportMode",0)
+ if MERGE_MODE > 0:
+ SEPARATE_OPENINGS = False
+ READ_COLORS = p.GetBool("ifcReadColors",True)
+ if not SEPARATE_OPENINGS:
+ SKIP.append("IfcOpeningElement")
try:
import ifcopenshell
@@ -271,13 +283,15 @@ def insert(filename,docname,skip=[]):
FreeCAD.Console.PrintError("IfcOpenShell was not found on this system. IFC support is disabled\n")
return
- if DEBUG: print "opening ",filename,"..."
+ if DEBUG: print "Opening ",filename,"...",
try:
doc = FreeCAD.getDocument(docname)
except:
doc = FreeCAD.newDocument(docname)
FreeCAD.ActiveDocument = doc
+ if DEBUG: print "done."
+
global ifcfile # keeping global for debugging purposes
if isinstance(filename,unicode):
import sys #workaround since ifcopenshell currently can't handle unicode filenames
@@ -293,15 +307,19 @@ def insert(filename,docname,skip=[]):
sites = ifcfile.by_type("IfcSite")
buildings = ifcfile.by_type("IfcBuilding")
floors = ifcfile.by_type("IfcBuildingStorey")
- products = ifcfile.by_type("IfcProduct")
+ products = ifcfile.by_type(ROOT_ELEMENT)
openings = ifcfile.by_type("IfcOpeningElement")
annotations = ifcfile.by_type("IfcAnnotation")
+
+ if DEBUG: print "Building relationships table...",
# building relations tables
objects = {} # { id:object, ... }
additions = {} # { host:[child,...], ... }
subtractions = [] # [ [opening,host], ... ]
properties = {} # { host:[property, ...], ... }
+ colors = {} # { id:(r,g,b) }
+ shapes = {} # { id:shaoe } only used for merge mode
for r in ifcfile.by_type("IfcRelContainedInSpatialStructure"):
additions.setdefault(r.RelatingStructure.id(),[]).extend([e.id() for e in r.RelatedElements])
for r in ifcfile.by_type("IfcRelAggregates"):
@@ -312,101 +330,239 @@ def insert(filename,docname,skip=[]):
for obj in r.RelatedObjects:
if r.RelatingPropertyDefinition.is_a("IfcPropertySet"):
properties.setdefault(obj.id(),[]).extend([e.id() for e in r.RelatingPropertyDefinition.HasProperties])
+ if READ_COLORS:
+ for r in ifcfile.by_type("IfcStyledItem"):
+ if r.Item and r.Styles[0].is_a("IfcPresentationStyleAssignment"):
+ if r.Styles[0].Styles[0].is_a("IfcSurfaceStyle"):
+ if r.Styles[0].Styles[0].Styles[0].is_a("IfcSurfaceStyleRendering"):
+ if r.Styles[0].Styles[0].Styles[0].SurfaceColour:
+ c = r.Styles[0].Styles[0].Styles[0].SurfaceColour
+ for p in ifcfile.by_type("IfcProduct"):
+ if p.Representation:
+ for it in p.Representation.Representations:
+ if it.Items:
+ if it.Items[0].id() == r.Item.id():
+ colors[p.id()] = (c.Red,c.Green,c.Blue)
+ elif it.Items[0].is_a("IfcBooleanResult"):
+ if (it.Items[0].FirstOperand.id() == r.Item.id()):
+ colors[p.id()] = (c.Red,c.Green,c.Blue)
+ if only: # only import a list of IDs and their children
+ ids = []
+ while only:
+ currentid = only.pop()
+ ids.append(currentid)
+ if currentid in additions.keys():
+ only.extend(additions[currentid])
+ products = [ifcfile[currentid] for currentid in ids]
+
+ if DEBUG: print "done."
+
count = 0
+ from FreeCAD import Base
+ progressbar = Base.ProgressIndicator()
+ progressbar.start("Importing IFC objects...",len(products))
# products
for product in products:
+
pid = product.id()
guid = product.GlobalId
ptype = product.is_a()
+ if DEBUG: print count,"/",len(products)," creating object ",pid," : ",ptype,
name = product.Name or str(ptype[3:])
if PREFIX_NUMBERS: name = "ID" + str(pid) + " " + name
obj = None
baseobj = None
brep = None
-
- if (ptype == "IfcOpeningElement") and (not SEPARATE_OPENINGS): continue
- if pid in skip: continue # user given id skip list
- if ptype in SKIP: continue # preferences-set type skip list
+
+ if pid in skip: # user given id skip list
+ if DEBUG: print " skipped."
+ continue
+ if ptype in SKIP: # preferences-set type skip list
+ if DEBUG: print " skipped."
+ continue
+
try:
cr = ifcopenshell.geom.create_shape(settings,product)
brep = cr.geometry.brep_data
except:
- pass
+ pass # IfcOpenShell will yield an error if a given product has no shape, but we don't care
+
if brep:
+ if DEBUG: print " ",str(len(brep)/1000),"k ",
+
shape = Part.Shape()
shape.importBrepFromString(brep)
+
shape.scale(1000.0) # IfcOpenShell always outputs in meters
+
if not shape.isNull():
- baseobj = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_body")
- baseobj.Shape = shape
- for freecadtype,ifctypes in typesmap.iteritems():
- if ptype in ifctypes:
- obj = getattr(Arch,"make"+freecadtype)(baseobj=baseobj,name=name)
+ if MERGE_MODE > 0:
+ if ptype == "IfcSpace": # do not add spaces to compounds
+ if DEBUG: print "skipping space ",pid
+ else:
+ shapes[pid] = shape
+ if DEBUG: print shape.Solids
+ baseobj = shape
+ else:
+ baseobj = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_body")
+ baseobj.Shape = shape
+ else:
+ if DEBUG: print "null shape ",
+ if not shape.isValid():
+ if DEBUG: print "invalid shape. Skipping"
+ continue
+
+ else:
+ if DEBUG: print " no brep "
+
+ if MERGE_MODE == 0:
+
+ # full Arch objects
+ for freecadtype,ifctypes in typesmap.items():
+ if ptype in ifctypes:
+ obj = getattr(Arch,"make"+freecadtype)(baseobj=baseobj,name=name)
+ obj.Label = name
+ # setting role
+ try:
+ r = ptype[3:]
+ tr = dict((v,k) for k, v in translationtable.iteritems())
+ if r in tr.keys():
+ r = tr[r]
+ # remove the "StandardCase"
+ if "StandardCase" in r:
+ r = r[:-12]
+ obj.Role = r
+ except:
+ pass
+ # setting uid
+ if hasattr(obj,"IfcAttributes"):
+ a = obj.IfcAttributes
+ a["IfcUID"] = str(guid)
+ obj.IfcAttributes = a
+ break
+ if not obj:
+ obj = baseobj
+ if obj:
+ sols = str(baseobj.Shape.Solids) if hasattr(baseobj,"Shape") else "[]"
+ if DEBUG: print sols
+ objects[pid] = obj
+
+ elif MERGE_MODE == 1:
+
+ # non-parametric Arch objects
+ if ptype in ["IfcSite","IfcBuilding","IfcBuildingStorey"]:
+ for freecadtype,ifctypes in typesmap.items():
+ if ptype in ifctypes:
+ obj = getattr(Arch,"make"+freecadtype)(baseobj=None,name=name)
+ obj.Label = name
+ objects[pid] = obj
+ elif baseobj:
+ obj = Arch.makeComponent(baseobj,name=name)
obj.Label = name
- # setting role
- try:
- r = ptype[3:]
- tr = dict((v,k) for k, v in translationtable.iteritems())
- if r in tr.keys():
- r = tr[r]
- # remove the "StandardCase"
- if "StandardCase" in r:
- r = r[:-12]
- obj.Role = r
- except:
- pass
- # setting uid
+ objects[pid] = obj
+
+ elif MERGE_MODE == 2:
+
+ # Part shapes
+ if ptype in ["IfcSite","IfcBuilding","IfcBuildingStorey"]:
+ for freecadtype,ifctypes in typesmap.items():
+ if ptype in ifctypes:
+ obj = getattr(Arch,"make"+freecadtype)(baseobj=None,name=name)
+ obj.Label = name
+ objects[pid] = obj
+ elif baseobj:
+ obj = FreeCAD.ActiveDocument.addObject("Part::Feature",name)
+ obj.Label = name
+ obj.Shape = shape
+
+
+ if obj:
+
+ # properties
+ if pid in properties:
if hasattr(obj,"IfcAttributes"):
a = obj.IfcAttributes
- a["IfcUID"] = str(guid)
+ for p in properties[pid]:
+ o = ifcfile[p]
+ if o.is_a("IfcPropertySingleValue"):
+ a[o.Name] = str(o.NominalValue)
obj.IfcAttributes = a
- break
- if not obj:
- obj = baseobj
- if obj:
- sh = baseobj.Shape.ShapeType if hasattr(baseobj,"Shape") else "None"
- sols = str(baseobj.Shape.Solids) if hasattr(baseobj,"Shape") else ""
- pc = str(int((float(count)/(len(products)+len(annotations))*100)))+"% "
- if DEBUG: print pc,"creating object ",pid," : ",ptype, " with shape: ",sh," ",sols
- objects[pid] = obj
- # properties
- if pid in properties:
- if hasattr(obj,"IfcAttributes"):
- a = obj.IfcAttributes
- for p in properties[pid]:
- o = ifcfile[p]
- if o.is_a("IfcPropertySingleValue"):
- a[o.Name] = str(o.NominalValue)
- obj.IfcAttributes = a
+ # color
+ if FreeCAD.GuiUp and (pid in colors):
+ if DEBUG: print " setting color: ",colors[pid]
+ obj.ViewObject.ShapeColor = colors[pid]
+
+ # if DEBUG is on, recompute after each shape
+ if DEBUG: FreeCAD.ActiveDocument.recompute()
+
count += 1
-
+ progressbar.next()
+
+ progressbar.stop()
FreeCAD.ActiveDocument.recompute()
- if DEBUG: print "Processing relationships..."
+ if MERGE_MODE == 3:
+
+ if DEBUG: print "Joining shapes..."
+
+ for host,children in additions.items():
+ if ifcfile[host].is_a("IfcBuildingStorey"):
+ compound = []
+ for c in children:
+ if c in shapes.keys():
+ compound.append(shapes[c])
+ del shapes[c]
+ if c in additions.keys():
+ for c2 in additions[c]:
+ if c2 in shapes.keys():
+ compound.append(shapes[c2])
+ del shapes[c2]
+ if compound:
+ name = ifcfile[host].Name or "Floor"
+ if PREFIX_NUMBERS: name = "ID" + str(host) + " " + name
+ obj = FreeCAD.ActiveDocument.addObject("Part::Feature",name)
+ obj.Label = name
+ obj.Shape = Part.makeCompound(compound)
+ if shapes: # remaining shapes
+ obj = FreeCAD.ActiveDocument.addObject("Part::Feature","Unclaimed")
+ obj.Shape = Part.makeCompound(shapes.values())
- # subtractions
- if SEPARATE_OPENINGS:
- for subtraction in subtractions:
- if (subtraction[0] in objects.keys()) and (subtraction[1] in objects.keys()):
- #print objects[subtraction[0]].Name, objects[subtraction[1]].Name
- Arch.removeComponents(objects[subtraction[0]],objects[subtraction[1]])
-
- # additions
- for host,children in additions.iteritems():
- if host in objects.keys():
- cobs = [objects[child] for child in children if child in objects.keys()]
- if cobs:
- Arch.addComponents(cobs,objects[host])
-
- FreeCAD.ActiveDocument.recompute()
+ else:
- # cleaning bad shapes
- for obj in objects.values():
- if obj.isDerivedFrom("Part::Feature"):
- if obj.Shape.isNull():
- Arch.rebuildArchShape(obj)
+ if DEBUG: print "Processing relationships..."
+
+ # subtractions
+ if SEPARATE_OPENINGS:
+ for subtraction in subtractions:
+ if (subtraction[0] in objects.keys()) and (subtraction[1] in objects.keys()):
+ if DEBUG: print "subtracting ",objects[subtraction[0]].Name, " from ", objects[subtraction[1]].Name
+ Arch.removeComponents(objects[subtraction[0]],objects[subtraction[1]])
+ if DEBUG: FreeCAD.ActiveDocument.recompute()
+
+ # additions
+ for host,children in additions.items():
+ if host in objects.keys():
+ cobs = [objects[child] for child in children if child in objects.keys()]
+ if cobs:
+ if DEBUG and (len(cobs) > 10) and ( not(Draft.getType(objects[host]) in ["Site","Building","Floor"])):
+ # avoid huge fusions
+ print "more than 10 shapes to add: skipping."
+ else:
+ if DEBUG: print "adding ",cobs, " to ", objects[host].Name
+ Arch.addComponents(cobs,objects[host])
+ if DEBUG: FreeCAD.ActiveDocument.recompute()
+
+ FreeCAD.ActiveDocument.recompute()
+
+ if DEBUG: print "Cleaning..."
+
+ # cleaning bad shapes
+ for obj in objects.values():
+ if obj.isDerivedFrom("Part::Feature"):
+ if obj.Shape.isNull():
+ Arch.rebuildArchShape(obj)
FreeCAD.ActiveDocument.recompute()
@@ -433,10 +589,11 @@ def insert(filename,docname,skip=[]):
count += 1
FreeCAD.ActiveDocument.recompute()
-
+
if FreeCAD.GuiUp:
import FreeCADGui
FreeCADGui.SendMsgToActiveView("ViewFit")
+ print "Finished importing."
return doc
@@ -552,7 +709,7 @@ def export(exportList,filename):
elif ifctype == "IfcBuilding":
args = args + ["ELEMENT",None,None,None]
elif ifctype == "IfcBuildingStorey":
- args = args + ["ELEMENT",None]
+ args = args + ["ELEMENT",obj.Placement.Base.z]
# creating the product
product = getattr(ifcfile,"create"+ifctype)(*args)
@@ -580,22 +737,26 @@ def export(exportList,filename):
for key in obj.IfcAttributes:
if not (key in ["IfcUID","FlagForceBrep"]):
r = obj.IfcAttributes[key].strip(")").split("(")
- tp = r[0]
- val = "(".join(r[1:])
- val = val.strip("'")
- val = val.strip('"')
- if DEBUG: print " property ",key," : ",str(val), " (", str(tp), ")"
- if tp in ["IfcLabel","IfcText","IfcIdentifier"]:
- val = str(val)
- elif tp == "IfcBoolean":
- if val == ".T.":
- val = True
- else:
- val = False
- elif tp == "IfcInteger":
- val = int(val)
+ if len(r) == 1:
+ tp = "IfcText"
+ val = r[0]
else:
- val = float(val)
+ tp = r[0]
+ val = "(".join(r[1:])
+ val = val.strip("'")
+ val = val.strip('"')
+ if DEBUG: print " property ",key," : ",str(val), " (", str(tp), ")"
+ if tp in ["IfcLabel","IfcText","IfcIdentifier"]:
+ val = str(val)
+ elif tp == "IfcBoolean":
+ if val == ".T.":
+ val = True
+ else:
+ val = False
+ elif tp == "IfcInteger":
+ val = int(val)
+ else:
+ val = float(val)
props.append(ifcfile.createIfcPropertySingleValue(str(key),None,ifcfile.create_entity(str(tp),val),None))
if props:
pset = ifcfile.createIfcPropertySet(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'PropertySet',None,props)
@@ -781,8 +942,11 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess
for fcface in fcsolid.Faces:
for e in fcface.Edges:
if not isinstance(e.Curve,Part.Line):
- curves = True
+ if e.curvatureAt(e.FirstParameter+(e.LastParameter-e.FirstParameter)/2) > 0.0001:
+ curves = True
+ break
if curves:
+ shapetype = "triangulated"
tris = fcsolid.tessellate(tessellation)
for tri in tris[1]:
pts = [ifcfile.createIfcCartesianPoint(tuple(tris[0][i])) for i in tri]
@@ -791,6 +955,7 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess
face = ifcfile.createIfcFace([bound])
faces.append(face)
else:
+ shapetype = "brep"
for fcface in fcsolid.Faces:
loops = []
verts = [v.Point for v in Part.Wire(DraftGeomUtils.sortEdges(fcface.OuterWire.Edges)).Vertexes]
@@ -820,7 +985,6 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess
shell = ifcfile.createIfcClosedShell(faces)
shape = ifcfile.createIfcFacetedBrep(shell)
shapes.append(shape)
- shapetype = "brep"
if shapes:
diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py
index 124c532a4..834586a9c 100644
--- a/src/Mod/Draft/Draft.py
+++ b/src/Mod/Draft/Draft.py
@@ -2430,6 +2430,13 @@ def clone(obj,delta=None):
if (len(obj) == 1) and obj[0].isDerivedFrom("Part::Part2DObject"):
cl = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Clone2D")
cl.Label = "Clone of " + obj[0].Label + " (2D)"
+ elif (len(obj) == 1) and hasattr(obj[0],"IfcAttributes"):
+ # arch objects can be clones
+ import Arch
+ cl = getattr(Arch,"make"+obj[0].Proxy.Type)()
+ cl.Label = "Clone of " + obj[0].Label
+ cl.CloneOf = obj[0]
+ return cl
else:
cl = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Clone")
cl.Label = "Clone of " + obj[0].Label