diff --git a/trunk/freecad/PartsLibrary.FCMacro b/trunk/freecad/PartsLibrary.FCMacro new file mode 100644 index 00000000..3c7a9b67 --- /dev/null +++ b/trunk/freecad/PartsLibrary.FCMacro @@ -0,0 +1,452 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +#*************************************************************************** +#* * +#* Copyright (c) 2013 Yorik van Havre * +#* * +#* This program is free software; you can redistribute it and/or modify * +#* it under the terms of the GNU Lesser General Public License (LGPL) * +#* as published by the Free Software Foundation; either version 2 of * +#* the License, or (at your option) any later version. * +#* for detail see the LICENCE text file. * +#* * +#* This program is distributed in the hope that it will be useful, * +#* but WITHOUT ANY WARRANTY; without even the implied warranty of * +#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +#* GNU Library General Public License for more details. * +#* * +#* You should have received a copy of the GNU Library General Public * +#* License along with this program; if not, write to the Free Software * +#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +#* USA * +#* * +#*************************************************************************** +from __future__ import print_function + +__title__="FreeCAD Parts Library Macro" +__author__ = "Yorik van Havre" +__url__ = "http://www.freecadweb.org" + +''' +FreeCAD Parts Library import macro + +INSTALLATION + +This script is made to be used as a FreeCAD macro, and to be placed +inside your macros folder (default is $HOME/.FreeCAD on mac/linux, +C:/Users/youruser/Application Data/FreeCAD on windows). + +After it is installed on the above location, it will be available +in the macros menu. On first run, it will ask you for the location +of your library. + +USAGE + +This macro adds a browser window to the FreeCAD interface, from +which you can browse and install items from the library. + +ADVANCED USE + +The update, config, and push buttons all rely on git, and need the +python-git package installed. Once that is done, and provided the +library is a git repository (ie. you cloned it with git instead of +just downloading it), the above mentioned buttons will be enabled. + +The "update" button will simply update your local library with the +latest contents from the online repository. + +CONTRIBUTING + +When cloning the official FreeCAD Parts library, you will usually +not have write permission to it, and therefore cannot push to it. + +The best way to proceed is, instead of cloning the FreeCAD library +directly, to fork it first (for example using the github "fork" +button), then clone that foked repo instead, where you will have +the correct permissions. + +Once you pushed some contents there, you can make a pull request on +the official repo to have it merged. + +If you create a folder named Private in your library, it won't be +considered when pushing, so you can place private Parts there. +''' + + +import FreeCAD, FreeCADGui, Part, zipfile, tempfile, Mesh, os, subprocess +from PySide import QtGui, QtCore + +param = FreeCAD.ParamGet('User parameter:Plugins/parts_library') +s = param.GetString('destination') +#print('User parameter:Plugins/partlib : destination : ',s) + +if s: + LIBRARYPATH = s +else: + folderDialog = QtGui.QFileDialog.getExistingDirectory(None,QtGui.QApplication.translate("PartsLibrary", "Location of your existing Parts library", None, QtGui.QApplication.UnicodeUTF8)) + param.SetString('destination',folderDialog) + LIBRARYPATH = param.GetString('destination') + +class ExpFileSystemModel(QtGui.QFileSystemModel): + "a custom QFileSystemModel that displays freecad file icons" + def __init__(self): + QtGui.QFileSystemModel.__init__(self) + + def data(self, index, role): + if index.column() == 0 and role == QtCore.Qt.DecorationRole: + if index.data().lower().endswith('.fcstd'): + return QtGui.QIcon(':icons/freecad-doc.png') + elif index.data().lower() == "private": + return QtGui.QIcon.fromTheme("folder-lock") + return super(ExpFileSystemModel, self).data(index, role) + +class ExpDockWidget(QtGui.QDockWidget): + "a library explorer dock widget" + + def __init__(self,LIBRARYPATH): + QtGui.QDockWidget.__init__(self) + + self.setObjectName("PartsLibrary") + + # setting up a directory model that shows only fcstd, step and brep + self.dirmodel = ExpFileSystemModel() + self.dirmodel.setRootPath(LIBRARYPATH) + self.dirmodel.setNameFilters(["*.fcstd","*.FcStd","*.FCSTD","*.stp","*.STP","*.step","*.STEP", "*.brp", "*.BRP", "*.brep", "*.BREP"]) + self.dirmodel.setNameFilterDisables(0) + + self.folder = QtGui.QTreeView() + self.folder.setModel(self.dirmodel) + self.folder.clicked[QtCore.QModelIndex].connect(self.clicked) + self.folder.doubleClicked[QtCore.QModelIndex].connect(self.doubleclicked) + # Don't show columns for size, file type, and last modified + self.folder.setHeaderHidden(True) + self.folder.hideColumn(1) + self.folder.hideColumn(2) + self.folder.hideColumn(3) + self.folder.setRootIndex(self.dirmodel.index(LIBRARYPATH)) + + self.preview = QtGui.QLabel() + self.preview.setFixedHeight(128) + + self.updatebutton = QtGui.QPushButton() + icon = QtGui.QIcon.fromTheme("emblem-synchronizing") + self.updatebutton.setIcon(icon) + self.updatebutton.clicked.connect(self.updatelibrary) + self.updatebutton.hide() + + self.configbutton = QtGui.QPushButton() + icon = QtGui.QIcon.fromTheme("emblem-system") + self.configbutton.setIcon(icon) + self.configbutton.clicked.connect(self.setconfig) + self.configbutton.hide() + + self.formatLabel = QtGui.QLabel() + self.formatLabel.hide() + + self.savebutton = QtGui.QPushButton() + icon = QtGui.QIcon.fromTheme("document-save") + self.savebutton.setIcon(icon) + self.savebutton.clicked.connect(self.addtolibrary) + self.savebutton.hide() + + self.pushbutton = QtGui.QPushButton() + icon = QtGui.QIcon.fromTheme("document-export") + self.pushbutton.setIcon(icon) + self.pushbutton.clicked.connect(self.pushlibrary) + self.pushbutton.hide() + + self.prevbutton = QtGui.QPushButton() + self.prevbutton.clicked.connect(self.showpreview) + self.prevbutton.setStyleSheet("text-align: left;") + + self.optbutton = QtGui.QPushButton() + self.optbutton.clicked.connect(self.showoptions) + self.optbutton.setStyleSheet("text-align: left;") + + self.fcstdCB = QtGui.QCheckBox('FCStd') + self.fcstdCB.setCheckState(QtCore.Qt.Checked) + self.fcstdCB.setEnabled(False) + self.fcstdCB.hide() + self.stepCB = QtGui.QCheckBox('STEP') + self.stepCB.setCheckState(QtCore.Qt.Checked) + self.stepCB.hide() + self.stlCB = QtGui.QCheckBox('STL') + self.stlCB.setCheckState(QtCore.Qt.Checked) + self.stlCB.hide() + + container = QtGui.QWidget() + grid = QtGui.QGridLayout() + grid.setSpacing(10) + + grid.addWidget(self.folder,0,0,1,2) + grid.addWidget(self.prevbutton,1,0,1,2) + grid.addWidget(self.preview,2,0,1,2) + grid.addWidget(self.optbutton,3,0,1,2) + + grid.addWidget(self.updatebutton,4,0,1,1) + grid.addWidget(self.configbutton,4,1,1,1) + grid.addWidget(self.formatLabel,5,0,1,2) + grid.addWidget(self.fcstdCB,6,0,1,2) + grid.addWidget(self.stepCB,7,0,1,2) + grid.addWidget(self.stlCB,8,0,1,2) + grid.addWidget(self.savebutton,9,0,1,1) + grid.addWidget(self.pushbutton,9,1,1,1) + + global repo + repo = None + try: + import git + except: + FreeCAD.Console.PrintWarning("python-git not found. Git-related functions will be disabled\n") + else: + try: + repo = git.Repo(LIBRARYPATH) + except: + FreeCAD.Console.PrintWarning("Your library is not a valid Git repository. Git-related functions will be disabled\n") + else: + if not repo.remotes: + FreeCAD.Console.PrintWarning("No remote repository set. Git-related functions will be disabled\n") + repo = None + if not repo: + self.updatebutton.setEnabled(False) + #self.configbutton.setEnabled(False) + self.pushbutton.setEnabled(False) + + self.retranslateUi() + container.setLayout(grid) + self.setWidget(container) + + def retranslateUi(self): + self.setWindowTitle(QtGui.QApplication.translate("PartsLibrary", "Parts Library", None, QtGui.QApplication.UnicodeUTF8)) + self.updatebutton.setText(QtGui.QApplication.translate("PartsLibrary", "Update from Git", None, QtGui.QApplication.UnicodeUTF8)) + self.configbutton.setText(QtGui.QApplication.translate("PartsLibrary", "Config", None, QtGui.QApplication.UnicodeUTF8)) + self.formatLabel.setText(QtGui.QApplication.translate("PartsLibrary", "Add to library", None, QtGui.QApplication.UnicodeUTF8)) + self.savebutton.setText(QtGui.QApplication.translate("PartsLibrary", "Save", None, QtGui.QApplication.UnicodeUTF8)) + self.pushbutton.setText(QtGui.QApplication.translate("PartsLibrary", "Push to Git", None, QtGui.QApplication.UnicodeUTF8)) + self.optbutton.setText(QtGui.QApplication.translate("PartsLibrary", "Options ⏷", None, QtGui.QApplication.UnicodeUTF8)) + self.prevbutton.setText(QtGui.QApplication.translate("PartsLibrary", "Preview ⏶", None, QtGui.QApplication.UnicodeUTF8)) + + def clicked(self, index): + path = self.dirmodel.filePath(index) + if path.lower().endswith(".fcstd"): + zfile=zipfile.ZipFile(path) + files=zfile.namelist() + # check for meta-file if it's really a FreeCAD document + if files[0] == "Document.xml": + image="thumbnails/Thumbnail.png" + if image in files: + image=zfile.read(image) + thumbfile = tempfile.mkstemp(suffix='.png')[1] + thumb = open(thumbfile,"wb") + thumb.write(image) + thumb.close() + im = QtGui.QPixmap(thumbfile) + self.preview.setPixmap(im) + return + self.preview.clear() + + def doubleclicked(self, index): + path = self.dirmodel.filePath(index) + if path.lower().endswith(".stp") or path.lower().endswith(".step") or path.lower().endswith(".brp") or path.lower().endswith(".brep"): + Part.show(Part.read(path)) + elif path.lower().endswith(".fcstd"): + FreeCADGui.ActiveDocument.mergeProject(path) + FreeCADGui.SendMsgToActiveView("ViewFit") + + def addtolibrary(self): + fileDialog = QtGui.QFileDialog.getSaveFileName(None,u"Choose category and set a filename without extension", LIBRARYPATH) + if fileDialog != '': + #filename = fileDialog[0].split("/")[-1] + #if filename.split(".")[-1].lowercase == "fcstd" or "stl + FCfilename = fileDialog[0] + ".fcstd" + FreeCAD.ActiveDocument.saveCopy(FCfilename) + if self.stepCB.isChecked() or self.stlCB.isChecked(): + toexport = [] + objs = FreeCAD.ActiveDocument.Objects + for obj in objs : + if obj.ViewObject.Visibility == True : + toexport.append(obj) + if self.stepCB.isChecked() : + STEPfilename = fileDialog[0] + ".step" + Part.export(toexport,STEPfilename) + if self.stlCB.isChecked() : + STLfilename = fileDialog[0] + ".stl" + Mesh.export(toexport,STLfilename) + + def pushlibrary(self): + modified_files = [f for f in repo.git.diff("--name-only").split("\n") if (f and (f != 'PartsLibrary.FCMacro'))] + #print(modified_files) + untracked_files = [f for f in repo.git.ls_files("--other","--exclude-standard").split("\n") if f] + #print(untracked_files) + import ArchServer + d = ArchServer._ArchGitDialog() + d.label.setText(str(len(modified_files)+len(untracked_files))+" new and modified file(s)") + d.lineEdit.setText("Changed " + str(modified_files)) + d.checkBox.hide() + d.radioButton.hide() + d.radioButton_2.hide() + r = d.exec_() + if r: + for o in modified_files + untracked_files: + repo.git.add(o) + repo.git.commit(m=d.lineEdit.text()) + if d.checkBox.isChecked(): + repo.git.push() + + def updatelibrary(self): + repo.git.pull() + + def setconfig(self): + d = ConfigDialog() + if repo: + d.lineEdit.setText(repo.remote().url) + if hasattr(repo.remote(),"pushurl"): + d.lineEdit_2.setText(repo.remote().pushurl) + else: + d.lineEdit_2.setText(repo.remote().url) + else: + d.groupBox.setEnabled(False) + d.groupBox_2.setEnabled(False) + r = d.exec_() + + def showoptions(self): + controls = [self.updatebutton,self.configbutton,self.formatLabel, + self.fcstdCB,self.stepCB,self.stlCB,self.savebutton,self.pushbutton] + tree = [self.preview] + if self.updatebutton.isVisible(): + for c in controls: + c.hide() + for c in tree: + c.show() + self.optbutton.setText(QtGui.QApplication.translate("PartsLibrary", "Options ⏷", None, QtGui.QApplication.UnicodeUTF8)) + else: + for c in controls: + c.show() + for c in tree: + c.hide() + self.optbutton.setText(QtGui.QApplication.translate("PartsLibrary", "Options ⏶", None, QtGui.QApplication.UnicodeUTF8)) + + def showpreview(self): + if self.preview.isVisible(): + self.preview.hide() + self.prevbutton.setText(QtGui.QApplication.translate("PartsLibrary", "Preview ⏷", None, QtGui.QApplication.UnicodeUTF8)) + else: + self.preview.show() + self.prevbutton.setText(QtGui.QApplication.translate("PartsLibrary", "Preview ⏶", None, QtGui.QApplication.UnicodeUTF8)) + + + +class ConfigDialog(QtGui.QDialog): + def __init__(self): + QtGui.QDialog.__init__(self) + self.setObjectName("GitConfig") + self.resize(420, 250) + self.verticalLayout = QtGui.QVBoxLayout(self) + self.verticalLayout.setObjectName("verticalLayout") + + self.groupBox_3 = QtGui.QGroupBox(self) + self.groupBox_3.setObjectName("groupBox_3") + self.horizontalLayout_3 = QtGui.QHBoxLayout(self.groupBox_3) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.lineEdit_3 = QtGui.QLineEdit(self.groupBox_3) + self.lineEdit_3.setObjectName("lineEdit_3") + self.horizontalLayout_3.addWidget(self.lineEdit_3) + self.pushButton_3 = QtGui.QPushButton(self.groupBox_3) + self.pushButton_3.setObjectName("pushButton_3") + self.horizontalLayout_3.addWidget(self.pushButton_3) + self.verticalLayout.addWidget(self.groupBox_3) + + self.groupBox = QtGui.QGroupBox(self) + self.groupBox.setObjectName("groupBox") + self.horizontalLayout = QtGui.QHBoxLayout(self.groupBox) + self.horizontalLayout.setObjectName("horizontalLayout") + self.lineEdit = QtGui.QLineEdit(self.groupBox) + self.lineEdit.setObjectName("lineEdit") + self.horizontalLayout.addWidget(self.lineEdit) + self.pushButton = QtGui.QPushButton(self.groupBox) + self.pushButton.setObjectName("pushButton") + self.horizontalLayout.addWidget(self.pushButton) + self.verticalLayout.addWidget(self.groupBox) + + self.groupBox_2 = QtGui.QGroupBox(self) + self.groupBox_2.setObjectName("groupBox_2") + self.verticalLayout_2 = QtGui.QVBoxLayout(self.groupBox_2) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.lineEdit_2 = QtGui.QLineEdit(self.groupBox_2) + self.lineEdit_2.setObjectName("lineEdit_2") + self.verticalLayout_2.addWidget(self.lineEdit_2) + self.label = QtGui.QLabel(self.groupBox_2) + self.label.setObjectName("label") + self.verticalLayout_2.addWidget(self.label) + self.verticalLayout.addWidget(self.groupBox_2) + + self.buttonBox = QtGui.QDialogButtonBox(self) + self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok) + self.buttonBox.setObjectName("buttonBox") + self.verticalLayout.addWidget(self.buttonBox) + + self.retranslateUi() + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), self.accept) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), self.reject) + QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL("clicked()"), self.setdefaulturl) + QtCore.QObject.connect(self.pushButton_3, QtCore.SIGNAL("clicked()"), self.changepath) + QtCore.QMetaObject.connectSlotsByName(self) + + librarypath = FreeCAD.ParamGet('User parameter:Plugins/parts_library').GetString('destination','') + self.lineEdit_3.setText(librarypath) + + def retranslateUi(self): + self.setWindowTitle(QtGui.QApplication.translate("PartsLibrary", "Parts library configuration", None, QtGui.QApplication.UnicodeUTF8)) + self.groupBox.setTitle(QtGui.QApplication.translate("PartsLibrary", "Pull server (where you get your updates from)", None, QtGui.QApplication.UnicodeUTF8)) + self.lineEdit.setToolTip(QtGui.QApplication.translate("PartsLibrary", "Enter the URL of the pull server here", None, QtGui.QApplication.UnicodeUTF8)) + self.pushButton.setToolTip(QtGui.QApplication.translate("PartsLibrary", "Use the official FreeCAD-library repository", None, QtGui.QApplication.UnicodeUTF8)) + self.pushButton.setText(QtGui.QApplication.translate("PartsLibrary", "use official", None, QtGui.QApplication.UnicodeUTF8)) + self.groupBox_2.setTitle(QtGui.QApplication.translate("PartsLibrary", "Push server (where you push your changes to)", None, QtGui.QApplication.UnicodeUTF8)) + self.lineEdit_2.setToolTip(QtGui.QApplication.translate("PartsLibrary", "Enter the URL of the push server here", None, QtGui.QApplication.UnicodeUTF8)) + self.label.setText(QtGui.QApplication.translate("PartsLibrary", "Warning: You need write permission on this server", None, QtGui.QApplication.UnicodeUTF8)) + self.groupBox_3.setTitle(QtGui.QApplication.translate("PartsLibrary", "Library path", None, QtGui.QApplication.UnicodeUTF8)) + self.lineEdit_3.setToolTip(QtGui.QApplication.translate("PartsLibrary", "Enter the path to your parts library", None, QtGui.QApplication.UnicodeUTF8)) + self.pushButton_3.setToolTip(QtGui.QApplication.translate("PartsLibrary", "Browse to your path library", None, QtGui.QApplication.UnicodeUTF8)) + self.pushButton_3.setText(QtGui.QApplication.translate("PartsLibrary", "...", None, QtGui.QApplication.UnicodeUTF8)) + + def setdefaulturl(self): + self.lineEdit.setText("https://github.com/FreeCAD/FreeCAD-library.git") + + def changepath(self): + librarypath = FreeCAD.ParamGet('User parameter:Plugins/parts_library').GetString('destination','') + np = QtGui.QFileDialog.getExistingDirectory(self,"Location of your existing Parts library",librarypath) + if np: + self.lineEdit_3.setText(np) + + def accept(self): + if repo: + cw = repo.remote().config_writer + if self.lineEdit.text(): + cw.set("url", str(self.lineEdit.text())) + if self.lineEdit_2.text(): + cw.set("pushurl", str(self.lineEdit_2.text())) + if hasattr(cw,"release"): + cw.release() + if self.lineEdit_3.text(): + FreeCAD.ParamGet('User parameter:Plugins/parts_library').SetString('destination',self.lineEdit_3.text()) + QtGui.QDialog.accept(self) + +if QtCore.QDir(LIBRARYPATH).exists(): + m = FreeCADGui.getMainWindow() + w = m.findChild(QtGui.QDockWidget,"PartsLibrary") + if w: + if hasattr(w,"isVisible"): + if w.isVisible(): + w.hide() + else: + w.show() + else: + # something went wrong with our widget... Recreate it + del w + m.addDockWidget(QtCore.Qt.RightDockWidgetArea,ExpDockWidget(LIBRARYPATH)) + else: + m.addDockWidget(QtCore.Qt.RightDockWidgetArea,ExpDockWidget(LIBRARYPATH)) +else: + print("Library path ", LIBRARYPATH, "not found.") diff --git a/trunk/freecad/contenitore.py b/trunk/freecad/contenitore.py new file mode 100644 index 00000000..af62920a --- /dev/null +++ b/trunk/freecad/contenitore.py @@ -0,0 +1,35 @@ +import FreeCAD as App +import FreeCADGui +import FreeCAD +import Part +import math + +class Contenitore: + def __init__(self,obj, unitsX=20, unitsY=30,unitsZ=3): + obj.addProperty("App::PropertyFloat","unitsX","Box","Size in X direction.").unitsX = unitsX + obj.addProperty("App::PropertyFloat","unitsY","Box","Size in Y direction.").unitsY = unitsY + obj.addProperty("App::PropertyFloat","unitsZ","Box","Size in Z direction.").unitsZ = unitsZ + obj.Proxy = self + + def execute(self, fp): + '''Print a short message when doing a recomputation, this method is mandatory''' + fp.Shape = Contenitore.buildshape(fp.unitsX, fp.unitsY, fp.unitsZ) + + @staticmethod + def buildshape( unitsX, unitsY, unitsZ): + wall=1.5 + + # box + l=unitsX + w=unitsY + height=unitsZ + c1=Part.makeBox(l, w, height,FreeCAD.Vector(-l/2.0,-w/2.0,0)) + c2=Part.makeBox(l+2*wall, w+2*wall, height+wall,FreeCAD.Vector(-(l+2*wall)/2.0,-(w+2*wall)/2.0,-wall)) + d1=c2.cut(c1) + return d1 + + +a=FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Box") +Contenitore(a) +a.ViewObject.Proxy=0 # just set it to something different from None (this assignment is needed to run an internal notification) +FreeCAD.ActiveDocument.recompute() diff --git a/trunk/freecad/lego.py b/trunk/freecad/lego.py new file mode 100644 index 00000000..8457830d --- /dev/null +++ b/trunk/freecad/lego.py @@ -0,0 +1,102 @@ +import FreeCAD as App +import FreeCADGui +import FreeCAD +import Part +import math + +class Lego: + def __init__(self,obj, unitsX=4, unitsY=2,unitsZ=1,modifier=1): + obj.addProperty("App::PropertyInteger","unitsX","Lego","Size in knobs in X direction.").unitsX = unitsX + obj.addProperty("App::PropertyInteger","unitsY","Lego","Size in knobs in Y direction.").unitsY = unitsY + obj.addProperty("App::PropertyInteger","unitsZ","Lego","Size in knobs in Z direction.").unitsZ = unitsZ + obj.addProperty("App::PropertyInteger","modifier","Lego","Variant No ").modifier = modifier + obj.Proxy = self + + def execute(self, fp): + '''Print a short message when doing a recomputation, this method is mandatory''' + fp.Shape = Lego.buildshape(fp.unitsX, fp.unitsY, fp.unitsZ, fp.modifier) + + @staticmethod + def buildshape( unitsX, unitsY, unitsZ, modifier): + gap=0.1 + gaps=2*gap + unitSize = 8 + height_U=3.2 # 9.6 + knobHeight=1.8 + knobRadius=4.9/2 + wall=1.35 # 1.5 guessed + upWall=1.2 # 5.5 guessed + supportthickness=0.6 # 0.15x4 or 0.20x3 + maxsupportlayerthickness=0.15 + supportdistance=4 # 4x4=16mm^2, printer option + cylRadius = (unitSize*math.sqrt(2)-2*knobRadius)/2 #0000003,2568542494923801952067548968388 + #cylWall = round(3.25685,5) + cylWall = 0.8 + + # box + l=unitSize*unitsX-gaps + w=unitSize*unitsY-gaps + height=height_U*unitsZ + c1=Part.makeBox(l, w, height,FreeCAD.Vector(-l/2.0,-w/2.0,0)) + c2=Part.makeBox(l-gaps-2*wall, w-gaps-2*wall, height,FreeCAD.Vector(-(l-gaps-2*wall)/2.0,-(w-gaps-2*wall)/2.0,-1*upWall)) + d1=c1.cut(c2) + shape1=d1 + + # knobs + knobs=Part.Shape() + knob=Part.makeCylinder(knobRadius,knobHeight+upWall/2,FreeCAD.Vector(0,0,height-upWall/2.0)) + for x in range(unitsX): + for y in range(unitsY): + newknob=knob.copy() + newknob.translate((x*unitSize, y*unitSize, 0)) + if knobs.isNull(): + knobs=newknob + else: + knobs=knobs.fuse(newknob) + knobs.translate(((1-unitsX)*unitSize/2, (1-unitsY)*unitSize/2, 0)) + + # Cylinder + if ((unitsX > 1) and (unitsY > 1)): + cyl=Part.makeCylinder(cylRadius,height-upWall/2).cut(Part.makeCylinder(cylRadius-cylWall,height)) + cyl.translate((0,0,0))#upWall/8)) + cyls=Part.Shape() + for x in range(unitsX-1): + for y in range(unitsY-1): + newcyl=cyl.copy() + newcyl.translate((x*unitSize, y*unitSize, 0)) + if cyls.isNull(): + cyls=newcyl + else: + cyls=cyls.fuse(newcyl) + cyls.translate(((2-unitsX)*unitSize/2, (2-unitsY)*unitSize/2, 0)) + + # Modifier bits: + # 0.. 0: flat; 1: with knobs + # 1.. 0: flat; 1: with cylinders on the bottom site + # 2.. 0: + # 3.. 0: + # 4.. 0: + # 5.. 0: + # 6.. 0: + # 7.. 0: + + if (modifier & 1) == 0: # Without knobs + pass + + if (modifier & 1) == 1: # With knobs + newknobs=knobs.copy() + #newknobs.translate((0,0,0)) + shape1=shape1.fuse(newknobs) + + if (modifier & 2) == 0: + pass + + if (modifier & 2) == 2: + shape1=shape1.fuse(cyls) + + return shape1 + +a=FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Lego") +Lego(a) +a.ViewObject.Proxy=0 # just set it to something different from None (this assignment is needed to run an internal notification) +FreeCAD.ActiveDocument.recompute() diff --git a/trunk/freecad/start_bolts.FCMacro b/trunk/freecad/start_bolts.FCMacro new file mode 100644 index 00000000..b2e57013 --- /dev/null +++ b/trunk/freecad/start_bolts.FCMacro @@ -0,0 +1,2 @@ +import BOLTS +BOLTS.show_widget()