diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py index d70807cf536e..0171aa38d6a9 100644 --- a/src/Mod/Arch/ArchCommands.py +++ b/src/Mod/Arch/ArchCommands.py @@ -208,6 +208,10 @@ def makeComponent(baseobj=None,name="Component",delete=False): obj.Placement = baseobj.Placement if delete: FreeCAD.ActiveDocument.removeObject(baseobj.Name) + else: + obj.Base = baseobj + if FreeCAD.GuiUp: + baseobj.ViewObject.hide() elif isinstance(baseobj,Part.Shape): obj.Shape = baseobj return obj @@ -897,7 +901,45 @@ def rebuildArchShape(objects=None): print "Failed" FreeCAD.ActiveDocument.recompute() + +def getExtrusionData(shape): + """getExtrusionData(shape): returns a base face and an extrusion vector + if this shape can be described as a perpendicular extrusion, or None if not.""" + if shape.isNull(): + return None + if not shape.Solids: + return None + if len(shape.Faces) < 5: + return None + # build faces list with normals + faces = [] + for f in shape.Faces: + faces.append([f,f.normalAt(0,0)]) + # find opposite normals pairs + pairs = [] + for i1, f1 in enumerate(faces): + for i2, f2 in enumerate(faces): + if f1[0].hashCode() != f2[0].hashCode(): + if round(f1[1].getAngle(f2[1]),8) == 3.14159265: + pairs.append([i1,i2]) + if not pairs: + return None + for p in pairs: + hc = [faces[p[0]][0].hashCode(),faces[p[1]][0].hashCode()] + ok = True + # check if other normals are all at 90 degrees + for f in faces: + if f[0].hashCode() not in hc: + if round(f[1].getAngle(faces[p[0]][1]),8) != 1.57079633: + ok = False + if ok: + return [faces[p[0]][0],faces[p[1]][0].CenterOfMass.sub(faces[p[0]][0].CenterOfMass)] + return None + + # command definitions ############################################### + + class _CommandAdd: "the Arch Add command definition" def GetResources(self): @@ -1053,6 +1095,7 @@ def Activated(self): for o in sel: FreeCADGui.Selection.addSelection(o) + class _CommandRemoveShape: "the Arch RemoveShape command definition" def GetResources(self): @@ -1067,6 +1110,7 @@ def Activated(self): sel = FreeCADGui.Selection.getSelection() removeShape(sel) + class _CommandCloseHoles: "the Arch CloseHoles command definition" def GetResources(self): @@ -1083,6 +1127,7 @@ def Activated(self): if s: o.Shape = s + class _CommandCheck: "the Arch Check command definition" def GetResources(self): @@ -1146,8 +1191,8 @@ def IsActive(self): def Activated(self): for o in FreeCADGui.Selection.getSelection(): toggleIfcBrepFlag(o) - - + + class _CommandComponent: "the Arch Component command definition" def GetResources(self): diff --git a/src/Mod/Arch/ArchComponent.py b/src/Mod/Arch/ArchComponent.py index 921bebb03eb3..dd93a88dddfd 100644 --- a/src/Mod/Arch/ArchComponent.py +++ b/src/Mod/Arch/ArchComponent.py @@ -306,7 +306,8 @@ def __init__(self,obj): obj.Role = Roles def execute(self,obj): - return + if obj.Base: + obj.Shape = obj.Base.Shape def __getstate__(self): return self.Type @@ -378,7 +379,13 @@ def getProfiles(self,obj,noplacement=False): wires = [] n,l,w,h = self.getDefaultValues(obj) if obj.Base: - if obj.Base.isDerivedFrom("Part::Feature"): + if obj.Base.isDerivedFrom("Part::Extrusion"): + if obj.Base.Base: + base = obj.Base.Base.Shape.copy() + if noplacement: + base.Placement = FreeCAD.Placement() + return [base] + elif obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape: base = obj.Base.Shape.copy() if noplacement: @@ -469,6 +476,9 @@ def getProfiles(self,obj,noplacement=False): def getExtrusionVector(self,obj,noplacement=False): "Returns an extrusion vector of this component, if applicable" n,l,w,h = self.getDefaultValues(obj) + if obj.Base: + if obj.Base.isDerivedFrom("Part::Extrusion"): + return obj.Base.Dir if Draft.getType(obj) == "Structure": if l > h: v = n.multiply(l) diff --git a/src/Mod/Arch/Resources/ui/archprefs-import.ui b/src/Mod/Arch/Resources/ui/archprefs-import.ui index 3d311aa0b5e6..ff3472389f1e 100644 --- a/src/Mod/Arch/Resources/ui/archprefs-import.ui +++ b/src/Mod/Arch/Resources/ui/archprefs-import.ui @@ -137,6 +137,26 @@ + + + + + + If this is checked, the importer will try to detect extrusions. This might slow things down... + + + Detect extrusions + + + ifcGetExtrusions + + + Mod/Arch + + + + + diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py index 16d573e44e7d..2f83d198be95 100644 --- a/src/Mod/Arch/importIFC.py +++ b/src/Mod/Arch/importIFC.py @@ -270,11 +270,13 @@ def insert(filename,docname,skip=[],only=[],root=None): SKIP = p.GetString("ifcSkip","").split(",") SEPARATE_OPENINGS = p.GetBool("ifcSeparateOpenings",False) ROOT_ELEMENT = p.GetString("ifcRootElement","IfcProduct") + GET_EXTRUSIONS = p.GetBool("ifcGetExtrusions",False) if root: ROOT_ELEMENT = root MERGE_MODE = p.GetInt("ifcImportMode",0) if MERGE_MODE > 0: SEPARATE_OPENINGS = False + GET_EXTRUSIONS = False if not SEPARATE_OPENINGS: SKIP.append("IfcOpeningElement") @@ -418,13 +420,25 @@ def insert(filename,docname,skip=[],only=[],root=None): if DEBUG: print shape.Solids baseobj = shape else: - baseobj = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_body") - baseobj.Shape = shape + if GET_EXTRUSIONS: + ex = Arch.getExtrusionData(shape) + if ex: + print "extrusion ", + baseface = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_footprint") + baseface.Shape = ex[0] + baseobj = FreeCAD.ActiveDocument.addObject("Part::Extrusion",name+"_body") + baseobj.Base = baseface + baseobj.Dir = ex[1] + if FreeCAD.GuiUp: + baseface.ViewObject.hide() + if not baseobj: + 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 + if DEBUG: print "invalid shape ", + #continue else: if DEBUG: print " no brep ", @@ -436,6 +450,8 @@ def insert(filename,docname,skip=[],only=[],root=None): if ptype in ifctypes: obj = getattr(Arch,"make"+freecadtype)(baseobj=baseobj,name=name) obj.Label = name + if FreeCAD.GuiUp and baseobj: + baseobj.ViewObject.hide() # setting role try: r = ptype[3:] @@ -455,7 +471,7 @@ def insert(filename,docname,skip=[],only=[],root=None): obj.IfcAttributes = a break if not obj: - obj = Arch.makeComponent(baseobj,name=name,delete=True) + obj = Arch.makeComponent(baseobj,name=name) if obj: sols = str(obj.Shape.Solids) if hasattr(obj,"Shape") else "[]" if DEBUG: print sols @@ -469,7 +485,7 @@ def insert(filename,docname,skip=[],only=[],root=None): if ptype in ifctypes: obj = getattr(Arch,"make"+freecadtype)(baseobj=None,name=name) elif baseobj: - obj = Arch.makeComponent(baseobj,name=name) + obj = Arch.makeComponent(baseobj,name=name,delete=True) elif MERGE_MODE == 2: @@ -545,7 +561,7 @@ def insert(filename,docname,skip=[],only=[],root=None): 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 + if DEBUG: print "subtracting ",objects[subtraction[0]].Label, " from ", objects[subtraction[1]].Label Arch.removeComponents(objects[subtraction[0]],objects[subtraction[1]]) if DEBUG: FreeCAD.ActiveDocument.recompute() @@ -558,14 +574,12 @@ def insert(filename,docname,skip=[],only=[],root=None): # avoid huge fusions print "more than 10 shapes to add: skipping." else: - if DEBUG: print "adding ",cobs, " to ", objects[host].Name + if DEBUG: print "adding ",len(cobs), " object(s) to ", objects[host].Label 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"):