From 2f8be93a2b0bfe4a5fe1607a224ec4b61bf87790 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sun, 22 May 2016 20:57:09 +0200 Subject: o Initial import. --- .gitignore | 1 + Boxer.py | 242 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Init.py | 1 + InitGui.py | 27 +++++++ 4 files changed, 271 insertions(+) create mode 100644 .gitignore create mode 100644 Boxer.py create mode 100644 Init.py create mode 100644 InitGui.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d20b64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pyc diff --git a/Boxer.py b/Boxer.py new file mode 100644 index 0000000..b4471bc --- /dev/null +++ b/Boxer.py @@ -0,0 +1,242 @@ +import FreeCAD +from FreeCAD import Base, Vector, Matrix +import Part + +class BoxCfg(object): + def __init__(self): + self._thickness = 10 + self._notches = 10 + self.outerDimmensions(100, 100, 100) + self.calculate() + + @property + def thickness(self): + return self._thickness + + @thickness.setter + def thickness(self, thickness): + self._thickness = thickness + self.calculate() + + @property + def notches(self): + return self._notches + + @notches.setter + def notches(self, notches): + self._notches = notches + self.calculate() + + def outerDimmensions(self, width, height, depth): + self.outerWidth = width + self.outerHeight = height + self.outerDepth = depth + self.calculate() + return self + + @property + def notchDownWidth(self): + return self._notchDownWidth + + def calculate(self): + self.innerWidth = self.outerWidth - 2 * self._thickness + self.innerHeight = self.outerHeight - 2 * self._thickness + self.innerDepth = self.outerDepth - 2 * self._thickness + self._notchDownWidth = self.innerWidth / (self._notches * 2 + 1) + + def prt(self): + print("Box configuration") + print("Outer w/h/d: " + str(self.outerWidth) + "/" + str(self.outerHeight) + "/" + str(self.outerDepth)) + print("Inner w/h/d: " + str(self.innerWidth) + "/" + str(self.innerHeight) + "/" + str(self.innerDepth)) + print("Notch count: " + str(self.notches) + ", low notch width: " + str(self.notchDownWidth)) + +class VGen(object): + def __init__(self, current, dir): + if dir == 'right': + self.x_x = 1 + self.x_y = 0 + self.y_x = 0 + self.y_y = 1 + elif dir == 'left': + self.x_x = -1 + self.x_y = 0 + self.y_x = 0 + self.y_y = -1 + elif dir == 'down': + self.x_x = 0 + self.x_y = -1 + self.y_x = 1 + self.y_y = 0 + elif dir == 'up': + self.x_x = 0 + self.x_y = 1 + self.y_x = -1 + self.y_y = 0 + else: + raise Exception('Bad dir: ' + dir) + + self.current = current + self.list = [] + + def move(self, x, y, z): + self.current = self.current.add(Vector(x, y, z)) + self.list.append(self.current) + + def moveX(self, value): + self.move(self.x_x * value, self.x_y * value, 0) + + def moveY(self, value): + self.move(self.y_x * value, self.y_y * value, 0) + +def line1(cfg, start, dir, inv, include_start): + x = cfg.notchDownWidth + + if inv: + inv = -1 + else: + inv = 1 + + g = VGen(start, dir) + + if include_start: + g.moveX(cfg.thickness) + + g.moveX(x) + for i in range(0, cfg.notches): + g.moveY(-cfg.thickness * inv) + g.moveX(x) + g.moveY(cfg.thickness * inv) + g.moveX(x) + + if include_start: + g.moveX(cfg.thickness) + + return g.list + +def largePolygon(cfg): + v = [Vector(0, 0, 0)] + top = line1(cfg, v[-1], 'right', False, True); v.extend(top) + left = line1(cfg, v[-1], 'down', False, True); v.extend(left) + bottom = line1(cfg, v[-1], 'left', False, True); v.extend(bottom) + right = line1(cfg, v[-1], 'up', False, True); v.extend(right) + return v + +def mediumPolygon(cfg): + v = [Vector(cfg.thickness, 0, 0)] + top = line1(cfg, v[-1], 'right', False, False); v.extend(top) + left = line1(cfg, v[-1], 'down', True, True); v.extend(left) + bottom = line1(cfg, v[-1], 'left', False, False); v.extend(bottom) + right = line1(cfg, v[-1], 'up', True, True); v.extend(right) + return v + +def smallPolygon(cfg): + v = [Vector(cfg.thickness, 0, 0)] + top = line1(cfg, v[-1], 'right', True, False); v.extend(top) + left = line1(cfg, v[-1], 'down', True, False); v.extend(left) + bottom = line1(cfg, v[-1], 'left', True, False); v.extend(bottom) + right = line1(cfg, v[-1], 'up', True, False); v.extend(right) + return v + +def makeBox(doc, cfg): + # front back left + # right top bottom + + # TODO: replace m.move() with a proper translation matrix so it looks assembled + + m = Matrix() + m.move(cfg.outerWidth * -0.55, 0, 0) + s = Part.makePolygon(largePolygon(cfg)) + s.transformShape(m) + doc.addObject("Part::Feature", "Front").Shape = s + + m = Matrix() + m.move(cfg.outerWidth * 0.55, 0, 0) + s = Part.makePolygon(largePolygon(cfg)) + s.transformShape(m) + doc.addObject("Part::Feature", "Back").Shape = s + + m = Matrix() + m.move(cfg.outerWidth * 1.60, 0, 0) + l = Part.makePolygon(mediumPolygon(cfg)) + l.transformShape(m) + doc.addObject("Part::Feature", "Left").Shape = l + + m = Matrix() + m.move(cfg.outerWidth * -0.55, cfg.outerWidth * -1.1, 0) + l = Part.makePolygon(smallPolygon(cfg)) + l.transformShape(m) + doc.addObject("Part::Feature", "Right").Shape = l + + m = Matrix() + m.move(cfg.outerWidth * 0.55, cfg.outerWidth * -1.1, 0) + l = Part.makePolygon(smallPolygon(cfg)) + l.transformShape(m) + doc.addObject("Part::Feature", "Top").Shape = l + + m = Matrix() + m.move(cfg.outerWidth * 1.60, cfg.outerWidth * -1.1, 0) + l = Part.makePolygon(mediumPolygon(cfg)) + l.transformShape(m) + doc.addObject("Part::Feature", "Bottom").Shape = l + +class MakeBoxCommandClass(): + def GetResources(self): + return {#'Pixmap' : os.path.join( iconPath , 'AddWall.svg') , # the name of a svg file available in the resources + 'MenuText': "Make Box" , + 'ToolTip' : "Extends a wall from a side face of metal sheet"} + + def Activated(self): + # TODO: put all objects in a group: + # group = doc.addObject("App::DocumentObjectGroup","Group") + + cfg = BoxCfg().outerDimmensions(300, 100, 50) + cfg.notches = 2 + cfg.thickness = 10 + cfg.prt() + + doc = FreeCAD.ActiveDocument + makeBox(doc, cfg) + + doc.recompute() + Gui.SendMsgToActiveView("ViewFit") + + return + + def IsActive(self): +# if len(Gui.Selection.getSelection()) < 1 or len(Gui.Selection.getSelectionEx()[0].SubElementNames) < 1: +# return False +# selobj = Gui.Selection.getSelection()[0] +# for selFace in Gui.Selection.getSelectionEx()[0].SubObjects: +# if type(selFace) != Part.Face: +# return False +# return True + return FreeCAD.ActiveDocument is not None + +class RemoveBoxCommandClass(): + def GetResources(self): + return { + 'MenuText': "Remove Box", + 'ToolTip' : "Remove the box"} + + def Activated(self): + doc = FreeCAD.ActiveDocument + + def rm(name): + o = getattr(doc, name, None); + if hasattr(doc, name): + doc.removeObject(name) + + rm("Top") + rm("Back") + rm("Left") + rm("Front") + rm("Right") + rm("Bottom") + return + + def IsActive(self): + return FreeCAD.ActiveDocument is not None + +from FreeCAD import Gui +Gui.addCommand('BoxerMakeBox', MakeBoxCommandClass()) +Gui.addCommand('BoxerRemoveBox', RemoveBoxCommandClass()) diff --git a/Init.py b/Init.py new file mode 100644 index 0000000..aabdd25 --- /dev/null +++ b/Init.py @@ -0,0 +1 @@ +print "Caser loaded" diff --git a/InitGui.py b/InitGui.py new file mode 100644 index 0000000..3ca7ce4 --- /dev/null +++ b/InitGui.py @@ -0,0 +1,27 @@ +print "GUI: Caser loaded" + +class BoxerWorkbench (Workbench): + + MenuText = "Boxer" + ToolTip = "Box Maker" +# Icon = + + def Initialize(self): + import Boxer + self.list = ["BoxerMakeBox", "BoxerRemoveBox"] + self.appendToolbar("Boxer Commands", self.list) + + def Activated(self): + return + + def Deactivated(self): + return + + def ContextMenu(self, recipient): + # "recipient" will be either "view" or "tree" + self.appendContextMenu("Boxer", self.list) + + def GetClassName(self): + return "Gui::PythonWorkbench" + +Gui.addWorkbench(BoxerWorkbench()) -- cgit v1.2.3