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,Component
00025 from draftlibs import fcgeo,fcvec
00026 from FreeCAD import Vector
00027 from PyQt4 import QtCore
00028
00029 __title__="FreeCAD Wall"
00030 __author__ = "Yorik van Havre"
00031 __url__ = "http://free-cad.sourceforge.net"
00032
00033 def makeWall(baseobj=None,width=None,height=None,align="Center",name="Wall"):
00034 '''makeWall(obj,[width],[height],[align],[name]): creates a wall based on the
00035 given object'''
00036 obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
00037 Wall(obj)
00038 ViewProviderWall(obj.ViewObject)
00039 if baseobj: obj.Base = baseobj
00040 if width: obj.Width = width
00041 if height: obj.Height = height
00042 obj.Align = align
00043 if obj.Base: obj.Base.ViewObject.hide()
00044 p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
00045 c = p.GetUnsigned("WallColor")
00046 r = float((c>>24)&0xFF)/255.0
00047 g = float((c>>16)&0xFF)/255.0
00048 b = float((c>>8)&0xFF)/255.0
00049 obj.ViewObject.ShapeColor = (r,g,b,1.0)
00050 return obj
00051
00052 class CommandWall:
00053 "the Arch Wall command definition"
00054 def GetResources(self):
00055 return {'Pixmap' : 'Arch_Wall',
00056 'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_Wall","Wall"),
00057 'Accel': "W, A",
00058 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Wall","Creates a wall object from scratch or from a selected object (wire, face or solid)")}
00059
00060 def Activated(self):
00061 sel = FreeCADGui.Selection.getSelection()
00062 if sel:
00063 FreeCAD.ActiveDocument.openTransaction("Wall")
00064 for obj in sel:
00065 makeWall(obj)
00066 FreeCAD.ActiveDocument.commitTransaction()
00067 else:
00068 wall = makeWall()
00069
00070 class Wall(Component.Component):
00071 "The Wall object"
00072 def __init__(self,obj):
00073 Component.Component.__init__(self,obj)
00074 obj.addProperty("App::PropertyLength","Width","Base",
00075 "The width of this wall. Not used if this wall is based on a face")
00076 obj.addProperty("App::PropertyLength","Height","Base",
00077 "The height of this wall. Keep 0 for automatic. Not used if this wall is based on a solid")
00078 obj.addProperty("App::PropertyLength","Length","Base",
00079 "The length of this wall. Not used if this wall is based on a shape")
00080 obj.addProperty("App::PropertyEnumeration","Align","Base",
00081 "The alignment of this wall on its base object, if applicable")
00082 obj.Align = ['Left','Right','Center']
00083 self.Type = "Wall"
00084 obj.Width = 0.1
00085 obj.Length = 1
00086 obj.Height = 0
00087
00088 def execute(self,obj):
00089 self.createGeometry(obj)
00090
00091 def onChanged(self,obj,prop):
00092 if prop in ["Base","Height","Width","Align","Additions","Subtractions"]:
00093 self.createGeometry(obj)
00094
00095 def createGeometry(self,obj):
00096
00097 def getbase(wire):
00098 "returns a full shape from a base wire"
00099 dvec = fcgeo.vec(wire.Edges[0]).cross(normal)
00100 dvec.normalize()
00101 if obj.Align == "Left":
00102 dvec = dvec.multiply(obj.Width)
00103 w2 = fcgeo.offsetWire(wire,dvec)
00104 sh = fcgeo.bind(wire,w2)
00105 elif obj.Align == "Right":
00106 dvec = dvec.multiply(obj.Width)
00107 dvec = fcvec.neg(dvec)
00108 w2 = fcgeo.offsetWire(wire,dvec)
00109 sh = fcgeo.bind(wire,w2)
00110 elif obj.Align == "Center":
00111 dvec = dvec.multiply(obj.Width/2)
00112 w1 = fcgeo.offsetWire(wire,dvec)
00113 dvec = fcvec.neg(dvec)
00114 w2 = fcgeo.offsetWire(wire,dvec)
00115 sh = fcgeo.bind(w1,w2)
00116 if height:
00117 norm = Vector(normal).multiply(height)
00118 sh = sh.extrude(norm)
00119 return sh
00120
00121 pl = obj.Placement
00122
00123
00124 height = normal = None
00125 if obj.Height:
00126 height = obj.Height
00127 else:
00128 for p in obj.InList:
00129 if Draft.getType(p) == "Floor":
00130 height = p.Height
00131 if not height: height = 1
00132 if obj.Normal == Vector(0,0,0):
00133 normal = Vector(0,0,1)
00134 else:
00135 normal = Vector(obj.Normal)
00136
00137
00138 if obj.Base:
00139 if obj.Base.isDerivedFrom("Part::Feature"):
00140 base = obj.Base.Shape.copy()
00141 if base.Solids:
00142 pass
00143 elif base.Faces:
00144 if height:
00145 norm = normal.multiply(height)
00146 base = base.extrude(norm)
00147 elif base.Wires:
00148 temp = None
00149 for wire in obj.Base.Shape.Wires:
00150 sh = getbase(wire)
00151 if temp:
00152 temp = temp.oldFuse(sh)
00153 else:
00154 temp = sh
00155 base = temp
00156 else:
00157 if obj.Length == 0:
00158 return
00159 v1 = Vector(0,0,0)
00160 v2 = Vector(obj.Length,0,0)
00161 w = Part.Wire(Part.Line(v1,v2).toShape())
00162 base = getbase(w)
00163
00164 for app in obj.Additions:
00165 base = base.oldFuse(app.Shape)
00166 app.ViewObject.hide()
00167 for hole in obj.Subtractions:
00168 cut = False
00169 if hasattr(hole,"Proxy"):
00170 if hasattr(hole.Proxy,"Subvolume"):
00171 if hole.Proxy.Subvolume:
00172 print "cutting subvolume",hole.Proxy.Subvolume
00173 base = base.cut(hole.Proxy.Subvolume)
00174 cut = True
00175 if not cut:
00176 if hasattr(obj,"Shape"):
00177 base = base.cut(hole.Shape)
00178 hole.ViewObject.hide()
00179 obj.Shape = base
00180 if not fcgeo.isNull(pl):
00181 obj.Placement = pl
00182
00183 class ViewProviderWall(Component.ViewProviderComponent):
00184 "A View Provider for the Wall object"
00185
00186 def __init__(self,vobj):
00187 Component.ViewProviderComponent.__init__(self,vobj)
00188
00189 def getIcon(self):
00190 return """
00191 /* XPM */
00192 static char * Arch_Wall_xpm[] = {
00193 "16 16 9 1",
00194 " c None",
00195 ". c #543016",
00196 "+ c #6D2F08",
00197 "@ c #954109",
00198 "# c #874C24",
00199 "$ c #AE6331",
00200 "% c #C86423",
00201 "& c #FD7C26",
00202 "* c #F5924F",
00203 " ",
00204 " ",
00205 " # ",
00206 " ***$# ",
00207 " .*******. ",
00208 " *##$****#+ ",
00209 " #**%&&##$#@@ ",
00210 ".$**%&&&&+@@+ ",
00211 "@&@#$$%&&@@+.. ",
00212 "@&&&%#.#$#+..#$.",
00213 " %&&&&+%#.$**$@+",
00214 " @%&+&&&$##@@+",
00215 " @.&&&&&@@@ ",
00216 " @%&&@@ ",
00217 " @+ ",
00218 " "};
00219 """
00220
00221 FreeCADGui.addCommand('Arch_Wall',CommandWall())