aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2016-05-22 20:57:09 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2016-05-22 20:57:09 +0200
commit2f8be93a2b0bfe4a5fe1607a224ec4b61bf87790 (patch)
treee77f2e7cee7c28ac68801a211629a8db6c7f2265
downloadfreecad-boxer-2f8be93a2b0bfe4a5fe1607a224ec4b61bf87790.tar.gz
freecad-boxer-2f8be93a2b0bfe4a5fe1607a224ec4b61bf87790.tar.bz2
freecad-boxer-2f8be93a2b0bfe4a5fe1607a224ec4b61bf87790.tar.xz
freecad-boxer-2f8be93a2b0bfe4a5fe1607a224ec4b61bf87790.zip
o Initial import.
-rw-r--r--.gitignore1
-rw-r--r--Boxer.py242
-rw-r--r--Init.py1
-rw-r--r--InitGui.py27
4 files changed, 271 insertions, 0 deletions
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())