From 43b7b9834d6c3d0d8550c1ef1b5ad1cfb621b7cc Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sun, 5 Aug 2012 19:03:27 -0300 Subject: [PATCH] Arch: Walls and Structs can now be created directly from meshes --- src/Mod/Arch/ArchCommands.py | 77 +++++++++++++++++++++++++---------- src/Mod/Arch/ArchStructure.py | 15 +++---- src/Mod/Arch/ArchWall.py | 33 +++++++++------ src/Mod/Arch/ArchWindow.py | 9 +--- 4 files changed, 86 insertions(+), 48 deletions(-) diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py index d6b3a96fe..44dd537c2 100644 --- a/src/Mod/Arch/ArchCommands.py +++ b/src/Mod/Arch/ArchCommands.py @@ -43,6 +43,22 @@ def getStringList(objects): result += "]" return result +def getDefaultColor(objectType): + '''getDefaultColor(string): returns a color value for the given object + type (Wall, Structure, Window)''' + p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") + if objectType == "Wall": + c = p.GetUnsigned("WallColor") + elif objectType == "Structure": + c = p.GetUnsigned("StructureColor") + else: + c = p.GetUnsigned("WindowsColor") + r = float((c>>24)&0xFF)/255.0 + g = float((c>>16)&0xFF)/255.0 + b = float((c>>8)&0xFF)/255.0 + result = (r,g,b,1.0) + return result + def addComponents(objectsList,host): '''addComponents(objectsList,hostObject): adds the given object or the objects from the given list as components to the given host Object. Use this for @@ -308,6 +324,41 @@ def getCutVolume(cutplane,shapes): cutnormal = DraftVecUtils.neg(cutnormal) invcutvolume = cutface.extrude(cutnormal) return cutface,cutvolume,invcutvolume + +def getShapeFromMesh(mesh): + import Part, MeshPart + if mesh.isSolid() and (mesh.countComponents() == 1): + # use the best method + faces = [] + for f in mesh.Facets: + p=f.Points+[f.Points[0]] + pts = [] + for pp in p: + pts.append(FreeCAD.Vector(pp[0],pp[1],pp[2])) + faces.append(Part.Face(Part.makePolygon(pts))) + shell = Part.makeShell(faces) + solid = Part.Solid(shell) + solid = solid.removeSplitter() + return solid + + faces = [] + segments = mesh.getPlanarSegments(0.001) # use rather strict tolerance here + for i in segments: + if len(i) > 0: + wires = MeshPart.wireFromSegment(mesh, i) + if wires: + faces.append(makeFace(wires)) + try: + se = Part.makeShell(faces) + except: + return None + else: + try: + solid = Part.Solid(se) + except: + return se + else: + return solid def meshToShape(obj,mark=True): @@ -315,36 +366,18 @@ def meshToShape(obj,mark=True): mark is True (default), non-solid objects will be marked in red''' name = obj.Name - import Part, MeshPart, DraftGeomUtils if "Mesh" in obj.PropertiesList: faces = [] mesh = obj.Mesh plac = obj.Placement - segments = mesh.getPlanarSegments(0.001) # use rather strict tolerance here - print len(segments)," segments ",segments - for i in segments: - print "treating",segments.index(i),i - if len(i) > 0: - wires = MeshPart.wireFromSegment(mesh, i) - print "wire done" - print wires - if wires: - faces.append(makeFace(wires)) - print "done facing" - print "faces",faces - - try: - se = Part.makeShell(faces) - solid = Part.Solid(se) - except: - raise - else: - if solid.isClosed(): + solid = getShapeFromMesh(mesh) + if solid: + if solid.isClosed() and solid.isValid(): FreeCAD.ActiveDocument.removeObject(name) newobj = FreeCAD.ActiveDocument.addObject("Part::Feature",name) newobj.Shape = solid newobj.Placement = plac - if not solid.isClosed(): + if (not solid.isClosed()) or (not solid.isValid()): if mark: newobj.ViewObject.ShapeColor = (1.0,0.0,0.0,1.0) return newobj diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py index d249a8a83..175bd5f94 100644 --- a/src/Mod/Arch/ArchStructure.py +++ b/src/Mod/Arch/ArchStructure.py @@ -44,12 +44,7 @@ def makeStructure(baseobj=None,length=1,width=1,height=1,name=str(translate("Arc obj.Width = width obj.Height = height obj.Length = length - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - c = p.GetUnsigned("StructureColor") - r = float((c>>24)&0xFF)/255.0 - g = float((c>>16)&0xFF)/255.0 - b = float((c>>8)&0xFF)/255.0 - obj.ViewObject.ShapeColor = (r,g,b,1.0) + obj.ViewObject.ShapeColor = ArchCommands.getDefaultColor("Structure") return obj def makeStructuralSystem(objects,axes): @@ -171,7 +166,13 @@ class _Structure(ArchComponent.Component): elif (len(base.Wires) == 1): if base.Wires[0].isClosed(): base = Part.Face(base.Wires[0]) - base = base.extrude(normal) + base = base.extrude(normal) + elif obj.Base.isDerivedFrom("Mesh::Feature"): + if obj.Mesh.isSolid(): + if obj.Mesh.countComponents() == 1: + sh = ArchCommands.getShapeFromMesh(obj.Mesh) + if sh.isClosed() and sh.isValid() and sh.Solids: + base = sh else: if obj.Normal == Vector(0,0,0): normal = Vector(0,0,1) diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 4983d77e7..b74f9415b 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -21,7 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils +import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils,ArchCommands from FreeCAD import Vector from PyQt4 import QtCore from DraftTools import translate @@ -37,17 +37,16 @@ def makeWall(baseobj=None,width=None,height=None,align="Center",name=str(transla obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name) _Wall(obj) _ViewProviderWall(obj.ViewObject) - if baseobj: obj.Base = baseobj - if width: obj.Width = width - if height: obj.Height = height + if baseobj: + obj.Base = baseobj + if width: + obj.Width = width + if height: + obj.Height = height obj.Align = align - if obj.Base: obj.Base.ViewObject.hide() - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - c = p.GetUnsigned("WallColor") - r = float((c>>24)&0xFF)/255.0 - g = float((c>>16)&0xFF)/255.0 - b = float((c>>8)&0xFF)/255.0 - obj.ViewObject.ShapeColor = (r,g,b,1.0) + if obj.Base: + obj.Base.ViewObject.hide() + obj.ViewObject.ShapeColor = ArchCommands.getDefaultColor("Wall") return obj def joinWalls(walls): @@ -357,7 +356,7 @@ class _Wall(ArchComponent.Component): # computing shape base = None if obj.Base.isDerivedFrom("Part::Feature"): - if not obj.Base.Shape.isNull(): + if obj.Base.isValid() and (not obj.Base.Shape.isNull()): base = obj.Base.Shape.copy() if base.Solids: pass @@ -380,7 +379,17 @@ class _Wall(ArchComponent.Component): if sh: base = sh else: + base = None FreeCAD.Console.PrintError(str(translate("Arch","Error: Invalid base object"))) + elif obj.Base.isDerivedFrom("Mesh::Feature"): + if obj.Base.Mesh.isSolid(): + if obj.Base.Mesh.countComponents() == 1: + sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh) + if sh.isClosed() and sh.isValid() and sh.Solids and (not sh.isNull()): + base = sh + else: + FreeCAD.Console.PrintWarning("This mesh is an invalid solid") + obj.Base.ViewObject.show() if base: for app in obj.Additions: diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index 9c540e7be..5a78ce627 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -21,7 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils +import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils,ArchCommands from FreeCAD import Vector from PyQt4 import QtCore,QtGui from DraftTools import translate @@ -49,12 +49,7 @@ def makeWindow(baseobj=None,width=None,name=str(translate("Arch","Window"))): if obj.Base: obj.Base.ViewObject.DisplayMode = "Wireframe" obj.Base.ViewObject.hide() - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - c = p.GetUnsigned("WindowColor") - r = float((c>>24)&0xFF)/255.0 - g = float((c>>16)&0xFF)/255.0 - b = float((c>>8)&0xFF)/255.0 - obj.ViewObject.ShapeColor = (r,g,b,1.0) + obj.ViewObject.ShapeColor = ArchCommands.getDefaultColor("Window") return obj def makeDefaultWindowPart(obj):