00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 import FreeCAD,FreeCADGui,Part,Draft,MeshPart,Component
00025 from draftlibs import fcgeo,fcvec
00026 from FreeCAD import Vector
00027 from PyQt4 import QtCore
00028
00029 __title__="FreeCAD Arch Commands"
00030 __author__ = "Yorik van Havre"
00031 __url__ = "http://free-cad.sourceforge.net"
00032
00033
00034
00035 def addComponents(objectsList,host):
00036 '''addComponents(objectsList,hostObject): adds the given object or the objects
00037 from the given list as components to the given host Object. Use this for
00038 example to add windows to a wall, or to add walls to a cell or floor.'''
00039 if not isinstance(objectsList,list):
00040 objectsList = [objectsList]
00041 tp = Draft.getType(host)
00042 if tp in ["Cell","Floor","Building","Site"]:
00043 c = host.Components
00044 for o in objectsList:
00045 if not o in c:
00046 c.append(o)
00047 host.Components = c
00048 elif tp in ["Wall","Structure"]:
00049 a = host.Additions
00050 for o in objectsList:
00051 if not o in a:
00052 if hasattr(o,"Shape"):
00053 a.append(o)
00054 host.Additions = a
00055 elif tp in ["SectionPlane"]:
00056 a = host.Objects
00057 for o in objectsList:
00058 if not o in a:
00059 if hasattr(o,"Shape"):
00060 a.append(o)
00061 host.Objects = a
00062
00063 def removeComponents(objectsList,host=None):
00064 '''removeComponents(objectsList,[hostObject]): removes the given component or
00065 the components from the given list from their parents. If a host object is
00066 specified, this function will try adding the components as holes to the host
00067 object instead.'''
00068 if not isinstance(objectsList,list):
00069 objectsList = [objectsList]
00070 if host:
00071 if Draft.getType(host) in ["Wall","Structure"]:
00072 s = host.Subtractions
00073 for o in objectsList:
00074 if not o in s:
00075 s.append(o)
00076 host.Subtractions = s
00077 else:
00078 for o in objectsList:
00079 if o.InList:
00080 h = o.InList[0]
00081 tp = Draft.getType(h)
00082 if tp in ["Cell","Floor","Building","Site"]:
00083 c = h.Components
00084 if o in c:
00085 c.remove(o)
00086 h.Components = c
00087 o.ViewObject.show()
00088 elif tp in ["Wall","Structure"]:
00089 a = h.Additions
00090 s = h.Subtractions
00091 if o in a:
00092 a.remove(o)
00093 h.Additions = a
00094 o.ViewObject.show()
00095 elif o in s:
00096 s.remove(o)
00097 h.Subtractions = s
00098 o.ViewObject.show()
00099 elif tp in ["SectionPlane"]:
00100 a = h.Objects
00101 if o in a:
00102 a.remove(o)
00103 h.Objects = a
00104
00105 def splitMesh(obj,mark=True):
00106 '''splitMesh(object,[mark]): splits the given mesh object into separated components.
00107 If mark is False, nothing else is done. If True (default), non-manifold components
00108 will be painted in red.'''
00109 if not obj.isDerivedFrom("Mesh::Feature"): return []
00110 basemesh = obj.Mesh
00111 comps = basemesh.getSeparateComponents()
00112 nlist = []
00113 if comps:
00114 basename = obj.Name
00115 FreeCAD.ActiveDocument.removeObject(basename)
00116 for c in comps:
00117 newobj = FreeCAD.ActiveDocument.addObject("Mesh::Feature",basename)
00118 newobj.Mesh = c
00119 if mark and (not(c.isSolid()) or c.hasNonManifolds()):
00120 newobj.ViewObject.ShapeColor = (1.0,0.0,0.0,1.0)
00121 nlist.append(newobj)
00122 return nlist
00123 return [obj]
00124
00125 def meshToShape(obj,mark=True):
00126 '''meshToShape(object,[mark]): turns a mesh into a shape, joining coplanar facets. If
00127 mark is True (default), non-solid objects will be marked in red'''
00128 if "Mesh" in obj.PropertiesList:
00129 faces = []
00130 mesh = obj.Mesh
00131 plac = obj.Placement
00132 segments = mesh.getPlanes(0.001)
00133 print len(segments)," segments ",segments
00134 for i in segments:
00135 print "treating",segments.index(i),i
00136 if len(i) > 0:
00137 wires = MeshPart.wireFromSegment(mesh, i)
00138 print "wire done"
00139 print wires
00140 if len(wires) > 1:
00141
00142 print "inner wires found"
00143 ext = None
00144 max_length = 0
00145
00146 for i in range(len(wires)):
00147 wires[i] = fcgeo.removeInterVertices(wires[i])
00148 for w in wires:
00149
00150
00151 if w.BoundBox.DiagonalLength > max_length:
00152 max_length = w.BoundBox.DiagonalLength
00153 ext = w
00154 print "exterior wire",ext
00155 wires.remove(ext)
00156
00157
00158 for w in wires:
00159 print "reversing",w
00160
00161 print "reversed"
00162
00163 wires.insert(0, ext)
00164 print "done sorting", wires
00165 faces.append(Part.Face(wires))
00166 print "done facing"
00167 print "faces",faces
00168
00169 shell=Part.Compound(faces)
00170 solid = Part.Solid(Part.Shell(faces))
00171 name = obj.Name
00172 if solid.isClosed():
00173 FreeCAD.ActiveDocument.removeObject(name)
00174 newobj = FreeCAD.ActiveDocument.addObject("Part::Feature",name)
00175 newobj.Shape = solid
00176 newobj.Placement = plac
00177 if not solid.isClosed():
00178 newobj.ViewObject.ShapeColor = (1.0,0.0,0.0,1.0)
00179 return newobj
00180 return None
00181
00182 def removeShape(objs,mark=True):
00183 '''takes an arch object (wall or structure) built on a cubic shape, and removes
00184 the inner shape, keeping its length, width and height as parameters.'''
00185 if not isinstance(objs,list):
00186 objs = [objs]
00187 for obj in objs:
00188 if fcgeo.isCubic(obj.Shape):
00189 dims = fcgeo.getCubicDimensions(obj.Shape)
00190 if dims:
00191 name = obj.Name
00192 tp = Draft.getType(obj)
00193 print tp
00194 if tp == "Structure":
00195 FreeCAD.ActiveDocument.removeObject(name)
00196 import Structure
00197 str = Structure.makeStructure(length=dims[1],width=dims[2],height=dims[3],name=name)
00198 str.Placement = dims[0]
00199 elif tp == "Wall":
00200 FreeCAD.ActiveDocument.removeObject(name)
00201 import Wall
00202 length = dims[1]
00203 width = dims[2]
00204 v1 = Vector(length/2,0,0)
00205 v2 = fcvec.neg(v1)
00206 v1 = dims[0].multVec(v1)
00207 v2 = dims[0].multVec(v2)
00208 line = Draft.makeLine(v1,v2)
00209 wal = Wall.makeWall(line,width=width,height=dims[3],name=name)
00210 else:
00211 if mark:
00212 obj.ViewObject.ShapeColor = (1.0,0.0,0.0,1.0)
00213
00214
00215
00216
00217 class CommandAdd:
00218 "the Arch Add command definition"
00219 def GetResources(self):
00220 return {'Pixmap' : 'Arch_Add',
00221 'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_Add","Add component"),
00222 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Add","Adds the selected components to the active object")}
00223
00224 def IsActive(self):
00225 if len(FreeCADGui.Selection.getSelection()) > 1:
00226 return True
00227 else:
00228 return False
00229
00230 def Activated(self):
00231 sel = FreeCADGui.Selection.getSelection()
00232 host = sel.pop()
00233 FreeCAD.ActiveDocument.openTransaction("Grouping")
00234 addComponents(sel,host)
00235 FreeCAD.ActiveDocument.commitTransaction()
00236
00237
00238 class CommandRemove:
00239 "the Arch Add command definition"
00240 def GetResources(self):
00241 return {'Pixmap' : 'Arch_Remove',
00242 'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_Remove","Remove component"),
00243 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Remove","Remove the selected components from their parents, or create a hole in a component")}
00244
00245 def IsActive(self):
00246 if FreeCADGui.Selection.getSelection():
00247 return True
00248 else:
00249 return False
00250
00251 def Activated(self):
00252 sel = FreeCADGui.Selection.getSelection()
00253 FreeCAD.ActiveDocument.openTransaction("Ungrouping")
00254 if Draft.getType(sel[-1]) in ["Wall","Structure"]:
00255 host = sel.pop()
00256 removeComponents(sel,host)
00257 else:
00258 removeComponents(sel)
00259 FreeCAD.ActiveDocument.commitTransaction()
00260
00261
00262 class CommandSplitMesh:
00263 "the Arch SplitMesh command definition"
00264 def GetResources(self):
00265 return {'Pixmap' : 'Arch_SplitMesh',
00266 'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_SplitMesh","Split Mesh"),
00267 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_SplitMesh","Splits selected meshes into independent components")}
00268
00269 def IsActive(self):
00270 if len(FreeCADGui.Selection.getSelection()):
00271 return True
00272 else:
00273 return False
00274
00275 def Activated(self):
00276 if FreeCADGui.Selection.getSelection():
00277 sel = FreeCADGui.Selection.getSelection()
00278 FreeCAD.ActiveDocument.openTransaction("Split Mesh")
00279 for obj in sel:
00280 n = obj.Name
00281 nobjs = splitMesh(obj)
00282 if len(nobjs) > 1:
00283 g = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup",n)
00284 for o in nobjs:
00285 g.addObject(o)
00286 FreeCAD.ActiveDocument.commitTransaction()
00287
00288
00289 class CommandMeshToShape:
00290 "the Arch MeshToShape command definition"
00291 def GetResources(self):
00292 return {'Pixmap' : 'Arch_MeshToShape',
00293 'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_MeshToShape","Mesh to Shape"),
00294 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_MeshToPart","Turns selected meshes into Part Shape objects")}
00295
00296 def IsActive(self):
00297 if FreeCADGui.Selection.getSelection():
00298 return True
00299 else:
00300 return False
00301
00302 def Activated(self):
00303 if FreeCADGui.Selection.getSelection():
00304 f = FreeCADGui.Selection.getSelection()[0]
00305 g = None
00306 if f.isDerivedFrom("App::DocumentObjectGroup"):
00307 g = f
00308 FreeCADGui.Selection.clearSelection()
00309 for o in f.OutList:
00310 FreeCADGui.Selection.addSelection(o)
00311 else:
00312 if f.InList:
00313 if f.InList[0].isDerivedFrom("App::DocumentObjectGroup"):
00314 g = f.InList[0]
00315 FreeCAD.ActiveDocument.openTransaction("Mesh to Shape")
00316 for obj in FreeCADGui.Selection.getSelection():
00317 newobj = meshToShape(obj)
00318 if g and newobj:
00319 g.addObject(newobj)
00320 FreeCAD.ActiveDocument.commitTransaction()
00321
00322 class CommandSelectNonSolidMeshes:
00323 "the Arch SelectNonSolidMeshes command definition"
00324 def GetResources(self):
00325 return {'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_SelectNonSolidMeshes","Select non-manifold meshes"),
00326 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_SelectNonSolidMeshes","Selects all non-manifold meshes from the document or from the selected groups")}
00327
00328 def Activated(self):
00329 msel = []
00330 if FreeCADGui.Selection.getSelection():
00331 for o in FreeCADGui.Selection.getSelection():
00332 if o.isDerivedFrom("App::DocumentObjectGroup"):
00333 msel.extend(o.OutList)
00334 if not msel:
00335 msel = FreeCAD.ActiveDocument.Objects
00336 sel = []
00337 for o in msel:
00338 if o.isDerivedFrom("Mesh::Feature"):
00339 if (not o.Mesh.isSolid()) or o.Mesh.hasNonManifolds():
00340 sel.append(o)
00341 if sel:
00342 FreeCADGui.Selection.clearSelection()
00343 for o in sel:
00344 FreeCADGui.Selection.addSelection(o)
00345
00346 class CommandRemoveShape:
00347 "the Arch RemoveShape command definition"
00348 def GetResources(self):
00349 return {'Pixmap' : 'Arch_RemoveShape',
00350 'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_RemoveShape","Remove Shape from Arch"),
00351 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_RemoveShape","Removes cubic shapes from Arch components")}
00352
00353 def IsActive(self):
00354 if FreeCADGui.Selection.getSelection():
00355 return True
00356 else:
00357 return False
00358
00359 def Activated(self):
00360 sel = FreeCADGui.Selection.getSelection()
00361 removeShape(sel)
00362
00363 FreeCADGui.addCommand('Arch_Add',CommandAdd())
00364 FreeCADGui.addCommand('Arch_Remove',CommandRemove())
00365 FreeCADGui.addCommand('Arch_SplitMesh',CommandSplitMesh())
00366 FreeCADGui.addCommand('Arch_MeshToShape',CommandMeshToShape())
00367 FreeCADGui.addCommand('Arch_SelectNonSolidMeshes',CommandSelectNonSolidMeshes())
00368 FreeCADGui.addCommand('Arch_RemoveShape',CommandRemoveShape())