def assemble(self): App.ActiveDocument = App.getDocument(self.name) shape = App.ActiveDocument.ActiveObject.Shape App.ActiveDocument = App.getDocument("PrinterAssembly") App.ActiveDocument.addObject("Part::Feature", self.name).Shape = shape # Color Part # Get the feature and move it into position objs = App.ActiveDocument.getObjectsByLabel(self.name) shape = objs[-1] # Rotate into correct orientation rotateAngle = 90 rotateCenter = App.Vector(0, 0, 0) rotateAxis = App.Vector(1, 0, 0) Draft.rotate([shape], rotateAngle, rotateCenter, axis=rotateAxis, copy=False) rotateAngle = -90 rotateCenter = App.Vector(0, 0, 0) rotateAxis = App.Vector(0, 0, 1) Draft.rotate([shape], rotateAngle, rotateCenter, axis=rotateAxis, copy=False) # Define shifts and move the into place xShift = -gv.zRodSpacing / 2 + gv.zEndstopBodyThickness + gv.zRodDiaL / 2 yShift = gv.extruderNozzleStandoff - gv.zRodStandoff zShift = gv.zRodSupportLength App.ActiveDocument = App.getDocument("PrinterAssembly") Draft.move([shape], App.Vector(xShift, yShift, zShift), copy=False) App.ActiveDocument.recompute() if shape not in gv.zAxisParts: gv.zAxisParts.append(shape)
def assemble(self): App.ActiveDocument = App.getDocument("xRodBottom") xRodBottom = App.ActiveDocument.Pad.Shape App.ActiveDocument = App.getDocument("PrinterAssembly") App.ActiveDocument.addObject('Part::Feature', 'xRodBottom').Shape = xRodBottom # Define shifts and move into place xshift = -gv.xRodLength / 2 yshift = (gv.extruderNozzleStandoff - gv.zRodStandoff - gv.xEndZRodHolderFaceThickness - gv.xEndZRodHolderMaxNutFaceToFace / 2 - gv.xMotorMountPlateThickness - gv.xRodClampThickness - gv.xRodDiaMax / 2) zshift = 0 App.ActiveDocument = App.getDocument("PrinterAssembly") Draft.move([App.ActiveDocument.getObject("xRodBottom")], App.Vector(xshift, yshift, zshift), copy=False) App.ActiveDocument.recompute() # Add to xAxisParts xrb = App.ActiveDocument.getObject("xRodBottom") if xrb not in gv.xAxisParts: gv.xAxisParts.append(xrb)
def get_gmsh_command(self): self.gmsh_bin = None gmsh_std_location = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Gmsh").GetBool("UseStandardGmshLocation") if gmsh_std_location: if system() == "Windows": gmsh_path = FreeCAD.getHomePath() + "bin/gmsh.exe" FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Gmsh").SetString("gmshBinaryPath", gmsh_path) self.gmsh_bin = gmsh_path elif system() == "Linux": p1 = subprocess.Popen(['which', 'gmsh'], stdout=subprocess.PIPE) if p1.wait() == 0: gmsh_path = p1.stdout.read().split('\n')[0] elif p1.wait() == 1: error_message = "GMSH binary gmsh not found in standard system binary path. Please install gmsh or set path to binary in FEM preferences tab GMSH.\n" FreeCAD.Console.PrintError(error_message) raise Exception(error_message) self.gmsh_bin = gmsh_path else: error_message = "No standard location implemented for your operating system. Set GMHS binary path in FEM preferences.\n" FreeCAD.Console.PrintError(error_message) raise Exception(error_message) else: if not self.gmsh_bin: self.gmsh_bin = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Gmsh").GetString("gmshBinaryPath", "") if not self.gmsh_bin: # in prefs not set, we will try to use something reasonable if system() == "Linux": self.gmsh_bin = "gmsh" elif system() == "Windows": self.gmsh_bin = FreeCAD.getHomePath() + "bin/gmsh.exe" else: self.gmsh_bin = "gmsh" print(' ' + self.gmsh_bin)
def insert(filename,docname): "called when freecad imports a file" global doc global pathName groupname = os.path.splitext(os.path.basename(filename))[0] try: doc=FreeCAD.getDocument(docname) except NameError: doc=FreeCAD.newDocument(docname) #importgroup = doc.addObject("App::DocumentObjectGroup",groupname) if filename.lower().endswith('.scad'): tmpfile=callopenscad(filename) if workaroundforissue128needed(): pathName = '' #https://github.com/openscad/openscad/issues/128 #pathName = os.getcwd() #https://github.com/openscad/openscad/issues/128 else: pathName = os.path.dirname(os.path.normpath(filename)) processcsg(tmpfile) try: os.unlink(tmpfile) except OSError: pass else: pathName = os.path.dirname(os.path.normpath(filename)) processcsg(filename)
def main(): shape = Part.Shape() #shape_formats = ['.brp', '.igs', '.stp'] if in_ext in mesh_formats: print("Opening mesh file: ", in_f) Mesh.open(in_f) o = FreeCAD.getDocument("Unnamed").findObjects()[0] #print("dir: ", dir(o)) if out_ext in mesh_formats: print("Exporting to mesh file: ", out_f) Mesh.export([o], out_f) else: # TODO This is not optimizing the resulting amount of faces! # see http://www.freecadweb.org/wiki/index.php?title=Mesh_to_Part shape.makeShapeFromMesh(o.Mesh.Topology, 0.05) # tolerance for sewing exportParametric(shape, out_f, out_ext) elif out_ext in mesh_formats: print("Opening parametric file: ", in_f) Part.open(in_f) o = FreeCAD.getDocument("Unnamed").findObjects()[0] print("Exporting to mesh file: ", out_f) Mesh.export([o], out_f) else: # Parametric -> Parametric print("Opening parametric file: ", in_f) shape.read(in_f) exportParametric(shape, out_f, out_ext)
def assemble(self): App.ActiveDocument=App.getDocument(self.name) shape = App.ActiveDocument.ActiveObject.Shape App.ActiveDocument=App.getDocument("PrinterAssembly") Gui.ActiveDocument=Gui.getDocument("PrinterAssembly") App.ActiveDocument.addObject('Part::Feature',self.name).Shape= shape #Color Part # Gui.ActiveDocument.getObject(self.name).ShapeColor = (gv.printedR,gv.printedG,gv.printedB,gv.printedA) #Get the feature and move it into position objs = App.ActiveDocument.getObjectsByLabel(self.name) shape = objs[-1] #Rotate into correct orientation rotateAngle = 180 rotateCenter = App.Vector(0,0,0) rotateAxis = App.Vector(0,0,1) Draft.rotate([shape],rotateAngle,rotateCenter,axis = rotateAxis,copy=False) #Define shifts and move the left clamp into place xShift = 0 yShift = ( gv.extruderDepth - gv.extruderEdgeToCenterLine) zShift = (-gv.xCarriageBushingHolderOR + gv.xCarriageMountHoleVertOffset - (gv.extruderMountAngleWidth-gv.extruderMountAngleThickness)/2 ) App.ActiveDocument=App.getDocument("PrinterAssembly") Draft.move([shape],App.Vector(xShift, yShift, zShift),copy=False) App.ActiveDocument.recompute() if shape not in gv.xAxisParts: gv.xAxisParts.append(shape)
def addSelection(self,docname,objname,subname,pnt): i = self.i_active_ref if i < 0: #not selecting any reference return if i > 0 and self.auto_next: prevref = LinkFromStr( self.refLines[i-1].text(), self.obj.Document ) if prevref[0].Name == objname and subname == '': # whole object was selected by double-clicking # its subelement was already written to line[i-1], so we decrease i to overwrite the lineRefChanged i -= 1 if i > len(self.refLines)-1: # all 4 references have been selected, finish assert(self.auto_next) self.i_active_ref = -1 self.updateRefButtons() return if i > -1: # assign the selected reference if objname == self.obj.Name: self.form.message.setText(_translate('AttachmentEditor',"Ignored. Can't attach object to itself!",None)) return if App.getDocument(docname).getObject(objname) in getAllDependent(self.obj): self.form.message.setText(_translate('AttachmentEditor',"{obj1} depends on object being attached, can't use it for attachment",None).format(obj1= objname)) return self.refLines[i].setText( StrFromLink(App.getDocument(docname).getObject(objname), subname) ) self.lineRefChanged(i,'') if self.auto_next: i += 1 self.i_active_ref = i self.updateRefButtons()
def _test_file( self, testFile_basename, solution = None ): testFile = os.path.join( test_assembly_path, testFile_basename + '.fcstd' ) debugPrint(1, testFile_basename ) stats.n_attempted += 1 #if testFile == 'tests/testAssembly11-Pipe_assembly.fcstd': # print('Skipping known fail') # continue doc = FreeCAD.open(testFile) t_start_solver = time.time() constraintSystem = solveConstraints( doc, solver_name = 'dof_reduction_solver', use_cache = self.use_cache, showFailureErrorDialog=False ) if solution: self.check_solution( constraintSystem, solution ) stats.t_solver += time.time() - t_start_solver if self.use_cache: debugPrint(1,'\n\n') X_org = constraintSystem.variableManager.X t_start_cache = time.time() #cache.debugMode = 1 constraintSystem = solveConstraints( doc, solver_name = 'dof_reduction_solver', use_cache = self.use_cache ) self.assertTrue( numpy.allclose( X_org , constraintSystem.variableManager.X ), 'Cache solution differs from originial solution: %s != %s' % ( X_org , constraintSystem.variableManager.X ) ) #cache.debugMode = 0 stats.t_cache += time.time() - t_start_cache constraintSystem.update() stats.n_solved += 1 FreeCAD.closeDocument( doc.Name ) debugPrint(1,'\n\n\n')
def Activated(self): #So we can open the save-as dialog mw = FreeCADGui.getMainWindow() cqCodePane = mw.findChild(QtGui.QPlainTextEdit, "cqCodePane") #Try to keep track of the previous path used to open as a convenience to the user if self.previousPath is None: self.previousPath = "/home/" filename = QtGui.QFileDialog.getSaveFileName(mw, mw.tr("Save CadQuery Script As"), self.previousPath, mw.tr("CadQuery Files (*.py)")) self.previousPath = filename[0] #Make sure the user didn't click cancel if filename[0]: #Close the 3D view for the original script if it's open try: docname = os.path.splitext(os.path.basename(cqCodePane.file.path))[0] FreeCAD.closeDocument(docname) except: #Assume that there was no 3D view to close pass #Save the file before closing the original and the re-rendering the new one ExportCQ.save(filename[0]) CadQueryExecuteScript().Activated()
def assemble(self): App.ActiveDocument=App.getDocument(self.name) shape = App.ActiveDocument.ActiveObject.Shape App.ActiveDocument=App.getDocument("PrinterAssembly") App.ActiveDocument.addObject('Part::Feature',self.name).Shape= shape #Color Part #Get the feature and move it into position objs = App.ActiveDocument.getObjectsByLabel(self.name) shape = objs[-1] #Rotate into correct orientation # rotateAngle = 0 # rotateCenter = App.Vector(0,0,0) # rotateAxis = App.Vector(1,0,0) # Draft.rotate([shape],rotateAngle,rotateCenter,axis = rotateAxis,copy=False) #Define shifts and move the left clamp into place xShift = +gv.zRodSpacing/2 yShift = gv.extruderNozzleStandoff - gv.zRodStandoff zShift = 0 App.ActiveDocument=App.getDocument("PrinterAssembly") Draft.move([shape],App.Vector(xShift, yShift, zShift),copy=False) App.ActiveDocument.recompute() if shape not in gv.xAxisParts: gv.zAxisParts.append(shape)
def Activated(self): FreeCAD.Console.PrintMessage(self.exFile + "\r\n") #So we can open the "Open File" dialog mw = FreeCADGui.getMainWindow() #Start off defaulting to the Examples directory module_base_path = module_locator.module_path() exs_dir_path = os.path.join(module_base_path, 'Examples') #We need to close any file that's already open in the editor window CadQueryCloseScript().Activated() #Append this script's directory to sys.path sys.path.append(os.path.dirname(exs_dir_path)) #We've created a library that FreeCAD can use as well to open CQ files ImportCQ.open(os.path.join(exs_dir_path, self.exFile)) docname = os.path.splitext(os.path.basename(self.exFile))[0] FreeCAD.newDocument(docname) #Execute the script CadQueryExecuteScript().Activated() #Get a nice view of our model FreeCADGui.activeDocument().activeView().viewAxometric() FreeCADGui.SendMsgToActiveView("ViewFit")
def Activated(self): #Grab our code editor so we can interact with it mw = FreeCADGui.getMainWindow() cqCodePane = mw.findChild(QtGui.QPlainTextEdit, "cqCodePane") #Clear the old render before re-rendering clearActiveDocument() #Save our code to a tempfile and render it tempFile = tempfile.NamedTemporaryFile(delete=False) tempFile.write(cqCodePane.toPlainText().encode('utf-8')) tempFile.close() docname = os.path.splitext(os.path.basename(cqCodePane.file.path))[0] #If the matching 3D view has been closed, we need to open a new one try: FreeCAD.getDocument(docname) except: FreeCAD.newDocument(docname) #We import this way because using execfile() causes non-standard script execution in some situations imp.load_source('temp_module', tempFile.name) msg = QtGui.QApplication.translate( "cqCodeWidget", "Executed ", None, QtGui.QApplication.UnicodeUTF8) FreeCAD.Console.PrintMessage(msg + cqCodePane.file.path + "\r\n")
def makeSnapshotWithGui(): from PyQt4 import QtGui import FreeCADGui def getMainWindow(): toplevel = QtGui.qApp.topLevelWidgets() for i in toplevel: if i.metaObject().className() == "Gui::MainWindow": return i raise Exception("No main window found") mw=getMainWindow() mw.hide() #mw.showMinimized() # Create a test geometry and add it to the document obj=Part.makeCone(10,8,10) doc = FreeCAD.newDocument() Part.show(obj) # switch off animation so that the camera is moved to the final position immediately view = FreeCADGui.getDocument(doc.Name).activeView() view.setAnimationEnabled(False) view.viewAxometric() view.fitAll() view.saveImage('crystal.png',800,600,'Current') FreeCAD.closeDocument(doc.Name) # close the application QtGui.qApp.quit()
def onOpen(self): "opens the reference file" if hasattr(self,"Object") and self.Object: if self.Object.File: FreeCAD.openDocument(self.Object.File)
def add_part(base,params,doc): if isinstance(base,freecad.BaseFunction): module = importlib.import_module("BOLTS.freecad.%s.%s" % (base.collection,base.module_name)) module.__dict__[base.name](params,doc) elif isinstance(base,freecad.BaseFcstd): #copy part to doc src_doc = FreeCAD.openDocument(base.path) src_obj = src_doc.getObject(base.objectname) if src_obj is None: raise MalformedBaseError("No object %s found" % base.objectname) #maps source name to destination object srcdstmap = {} dst_obj = copy_part_recursive(src_obj,doc,srcdstmap) #set parameters for obj_name,proptoparam in base.proptoparam.iteritems(): for prop,param in proptoparam.iteritems(): setattr(srcdstmap[obj_name],prop,params[param]) #finish presentation dst_obj.touch() doc.recompute() FreeCADGui.getDocument(doc.Name).getObject(dst_obj.Name).Visibility = True FreeCAD.setActiveDocument(doc.Name) FreeCAD.closeDocument(src_doc.Name)
def __init__(self,object): # the panel has a tree widget that contains categories # for the subcomponents, such as additions, subtractions. # the categories are shown only if they are not empty. form_class, base_class = uic.loadUiType(FreeCAD.getHomePath() + "Mod/Fem/MechanicalAnalysis.ui") self.CalculixBinary = FreeCAD.getHomePath() +'bin/ccx.exe' self.TempDir = FreeCAD.ActiveDocument.TransientDir.replace('\\','/') + '/FemAnl_'+ object.Uid[-4:] if not os.path.isdir(self.TempDir): os.mkdir(self.TempDir) self.obj = object self.formUi = form_class() self.form = QtGui.QWidget() self.formUi.setupUi(self.form) #self.params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem") self.Calculix = QtCore.QProcess() self.Timer = QtCore.QTimer() self.Timer.start(300) self.OutStr = '' #Connect Signals and Slots QtCore.QObject.connect(self.formUi.toolButton_chooseOutputDir, QtCore.SIGNAL("clicked()"), self.chooseOutputDir) QtCore.QObject.connect(self.formUi.pushButton_generate, QtCore.SIGNAL("clicked()"), self.run) QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("started()"), self.calculixStarted) QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("finished(int)"), self.calculixFinished) QtCore.QObject.connect(self.Timer, QtCore.SIGNAL("timeout()"), self.UpdateText) self.update()
def assemble(self): App.ActiveDocument=App.getDocument(self.name) shape = App.ActiveDocument.ActiveObject.Shape App.ActiveDocument=App.getDocument("PrinterAssembly") App.ActiveDocument.addObject('Part::Feature',self.name).Shape= shape #Color Part #Get the feature and move it into position objs = App.ActiveDocument.getObjectsByLabel(self.name) shape = objs[-1] # #Rotate into correct orientation # rotateAngle = 0 # rotateCenter = App.Vector(0,0,0) # rotateAxis = App.Vector(1,0,0) # Draft.rotate([shape],rotateAngle,rotateCenter,axis = rotateAxis,copy=False) #Define shifts and move the left clamp into place xShift = -gv.crossBarLength/2 yShift = +gv.yRodLength/2 - gv.frameWidth/2 zShift = -gv.yRodStandoff - gv.frameHeight/2 App.ActiveDocument=App.getDocument("PrinterAssembly") Draft.move([shape],App.Vector(xShift, yShift, zShift),copy=False) App.ActiveDocument.recompute()
def on_addButton_clicked(self, checked): if FreeCAD.activeDocument() is None: FreeCAD.newDocument() items = self.ui.partsTree.selectedItems() if len(items) < 1: return data = items[0].data(0, 32).toPyObject() if not isinstance(data, BOLTSClass): return params = {} #read parameters from widgets for key in self.param_widgets: params[key] = self.param_widgets[key].getValue() params = data.parameters.collect(params) params['standard'] = data.name params['name'] = data.naming.template % \ tuple(params[k] for k in data.naming.substitute) lengths = {"Length (mm)": "mm", "Length (in)": "in"} for key, tp in data.parameters.types.iteritems(): if tp in lengths: params[key] = FreeCAD.Units.translateUnit( "%g %s" % (params[key], lengths[tp])) #add part self.repo.freecad.getbase[data.id].add_part(params, FreeCAD.ActiveDocument)
def __init__(self, l = 10): """Create a frame. l is the vector's length""" #-- Store the vector length self.l = l #-- Create the Freecad Object self.obj = FreeCAD.ActiveDocument.addObject("Part::Compound","Frame") #-- Build the frame self.x_axis = svector(1, 0, 0, l = l).color("red") self.x_axis.label = "X axis" self.y_axis = svector(0, 1, 0, l = l).color("green") self.y_axis.label = "Y axis" self.z_axis = svector(0, 0, 1, l = l).color("blue") self.z_axis.label = "Z axis" self.origin = sphere(r = 0.5) self.origin.label = "Origin" #-- Creat the compound object self.obj.Links = [self.x_axis.obj, self.y_axis.obj, self.z_axis.obj, self.origin.obj] #-- Default display mode self.obj.ViewObject.DisplayMode = 'Shaded' FreeCAD.activeDocument().recompute() return
def setActiveContainer(cnt): '''setActiveContainer(cnt): sets active container. To set no active container, supply ActiveDocument. None is not accepted.''' cnt = screen(cnt) import FreeCAD as App import FreeCADGui as Gui if hasattr(App, "ActiveContainer"): App.setActiveContainer(cnt) return if not isContainer(cnt): raise NotAContainerError("Can't make '{feat}' active as container, because it's not a container (or an unknown type of container)." .format(feat= cnt.Label)) if cnt.isDerivedFrom("Part::BodyBase"): Gui.ActiveDocument.ActiveView.setActiveObject("pdbody", cnt) part = None else: part = cnt Gui.ActiveDocument.ActiveView.setActiveObject("pdbody", None) if part: if part.isDerivedFrom("App::Document"): part = None Gui.ActiveDocument.ActiveView.setActiveObject("part", part)
def testIssue3245_2(self): self.Doc2 = FreeCAD.newDocument("Issue3245") ActiveSketch = self.Doc2.addObject('Sketcher::SketchObject','Sketch') ActiveSketch.Placement = App.Placement(App.Vector(0.000000,0.000000,0.000000),App.Rotation(0.000000,0.000000,0.000000,1.000000)) ActiveSketch.MapMode = "Deactivated" geoList = [] geoList.append(Part.LineSegment(App.Vector(-23.574591,42.399727,0),App.Vector(81.949776,42.399727,0))) geoList.append(Part.LineSegment(App.Vector(81.949776,42.399727,0),App.Vector(81.949776,-19.256901,0))) geoList.append(Part.LineSegment(App.Vector(81.949776,-19.256901,0),App.Vector(-23.574591,-19.256901,0))) geoList.append(Part.LineSegment(App.Vector(-23.574591,-19.256901,0),App.Vector(-23.574591,42.399727,0))) ActiveSketch.addGeometry(geoList,False) conList = [] conList.append(Sketcher.Constraint('Coincident',0,2,1,1)) conList.append(Sketcher.Constraint('Coincident',1,2,2,1)) conList.append(Sketcher.Constraint('Coincident',2,2,3,1)) conList.append(Sketcher.Constraint('Coincident',3,2,0,1)) conList.append(Sketcher.Constraint('Horizontal',0)) conList.append(Sketcher.Constraint('Horizontal',2)) conList.append(Sketcher.Constraint('Vertical',1)) conList.append(Sketcher.Constraint('Vertical',3)) ActiveSketch.addConstraint(conList) ActiveSketch.addConstraint(Sketcher.Constraint('DistanceX',0,1,0,2,105.524367)) ActiveSketch.setExpression('Constraints[8]', u'10 + 10') ActiveSketch.addConstraint(Sketcher.Constraint('DistanceY',3,1,3,2,61.656628)) ActiveSketch.setDatum(9,App.Units.Quantity('5.000000 mm')) ActiveSketch.delConstraint(8) values = d = {key: value for (key, value) in self.Doc2.Sketch.ExpressionEngine} self.Doc2.recompute() self.failUnless(len(values) == 0) FreeCAD.closeDocument("Issue3245")
def assemble(self): App.ActiveDocument = App.getDocument(self.name) shape = App.ActiveDocument.ActiveObject.Shape App.ActiveDocument = App.getDocument("PrinterAssembly") Gui.ActiveDocument = Gui.getDocument("PrinterAssembly") App.ActiveDocument.addObject("Part::Feature", self.name).Shape = shape # Color Part # Gui.ActiveDocument.getObject(self.name).ShapeColor = (gv.printedR,gv.printedG,gv.printedB,gv.printedA) # Get the feature and move it into position objs = App.ActiveDocument.getObjectsByLabel(self.name) shape = objs[-1] # Rotate into correct orientation rotateAngle = 180 rotateCenter = App.Vector(0, 0, 0) rotateAxis = App.Vector(0, 0, 1) Draft.rotate([shape], rotateAngle, rotateCenter, axis=rotateAxis, copy=False) # Define shifts and move the left clamp into place xShift = 0 yShift = gv.yRodLength / 2 zShift = -gv.yRodStandoff App.ActiveDocument = App.getDocument("PrinterAssembly") Draft.move([shape], App.Vector(xShift, yShift, zShift), copy=False) App.ActiveDocument.recompute() if shape not in gv.yAxisParts: gv.yAxisParts.append(shape)
def assemble(self): App.ActiveDocument=App.getDocument("xEndIdlerPlate") shape = App.ActiveDocument.ActiveObject.Shape App.ActiveDocument=App.getDocument("PrinterAssembly") Gui.ActiveDocument=Gui.getDocument("PrinterAssembly") App.ActiveDocument.addObject('Part::Feature','xEndIdlerPlate').Shape= shape #Color Part change colors to metal #Gui.ActiveDocument.getObject("xEndIdlerPlate").ShapeColor = (gv.printedR,gv.printedG,gv.printedB,gv.printedA) #Rotate into correct orientation rotateAngle = -90 rotateCenter = App.Vector(0,0,0) rotateAxis = App.Vector(1,0,0) Draft.rotate([App.ActiveDocument.xEndIdlerPlate],rotateAngle,rotateCenter,axis = rotateAxis,copy=False) #Define shifts and move the left clamp into place xShift = gv.xRodLength/2-gv.xRodClampPocketDepth yShift = (gv.extruderNozzleStandoff - gv.zRodStandoff - gv.xEndZRodHolderFaceThickness - gv.xEndZRodHolderMaxNutFaceToFace/2 - gv.xMotorMountPlateThickness) zShift = gv.xMotorMountPlateWidth+ (gv.xRodSpacing-gv.xMotorMountPlateWidth)/2 App.ActiveDocument=App.getDocument("PrinterAssembly") Draft.move([App.ActiveDocument.xEndIdlerPlate],App.Vector(xShift, yShift, zShift),copy=False) App.ActiveDocument.recompute() shape = App.ActiveDocument.xEndIdlerPlate if shape not in gv.xAxisParts: gv.xAxisParts.append(shape)
def setTipo(l,w): 'arg1=length,arg2=width' import FreeCAD fpTipo=FreeCAD.activeDocument().tipo fpTipo.length=l fpTipo.width=w FreeCAD.activeDocument().recompute()
def assemble(self): App.ActiveDocument=App.getDocument(self.name) shape = App.ActiveDocument.ActiveObject.Shape App.ActiveDocument=App.getDocument("PrinterAssembly") App.ActiveDocument.addObject('Part::Feature',self.name).Shape= shape #Color Part #Get the feature and move it into position objs = App.ActiveDocument.getObjectsByLabel(self.name) shape = objs[-1] #Rotate into correct orientation rotateAngle = 180 rotateCenter = App.Vector(0,0,0) rotateAxis = App.Vector(1,0,0) Draft.rotate([shape],rotateAngle,rotateCenter,axis = rotateAxis,copy=False) #Rotate into correct orientation rotateAngle = 90 rotateCenter = App.Vector(0,0,0) rotateAxis = App.Vector(0,0,1) Draft.rotate([shape],rotateAngle,rotateCenter,axis = rotateAxis,copy=False) #Define shifts and move the left clamp into place xShift = gv.yMotorPulleyDia/2 yShift = 0 zShift = gv.PBBHStandoff App.ActiveDocument=App.getDocument("PrinterAssembly") Draft.move([shape],App.Vector(xShift, yShift, zShift),copy=False) App.ActiveDocument.recompute() if shape not in gv.yAxisParts: gv.yAxisParts.append(shape)
def assemble(self): App.ActiveDocument=App.getDocument(self.name) shape = App.ActiveDocument.ActiveObject.Shape App.ActiveDocument=App.getDocument("PrinterAssembly") Gui.ActiveDocument=Gui.getDocument("PrinterAssembly") App.ActiveDocument.addObject('Part::Feature',self.name).Shape= shape #Color Part Gui.ActiveDocument.getObject(self.name).ShapeColor = (gv.frameR,gv.frameG,gv.frameB,gv.frameA) #Get the feature and move it into position objs = App.ActiveDocument.getObjectsByLabel(self.name) shape = objs[-1] #Rotate into correct orientation rotateAngle = 90 rotateCenter = App.Vector(0,0,0) rotateAxis = App.Vector(1,0,0) Draft.rotate([shape],rotateAngle,rotateCenter,axis = rotateAxis,copy=False) #Define shifts and move the left clamp into place xShift = -(gv.zRodSpacing+gv.frameWidth)/2 yShift = gv.extruderNozzleStandoff+gv.frameHeight/2 zShift = (-gv.yRodStandoff + gv.vertBarLength + gv.frameWidth/2) App.ActiveDocument=App.getDocument("PrinterAssembly") Draft.move([shape],App.Vector(xShift, yShift, zShift),copy=False) App.ActiveDocument.recompute()
def _resume(): """do not call! resume a suspend by calling .release method on keeper object returned by suspend.""" global suspend_counter if suspend_counter == 0: return suspend_counter -= 1 if suspend_counter == 0: App.addDocumentObserver(observerInstance)
def assemble(self): App.ActiveDocument=App.getDocument("xRodTop") xRodTop = App.ActiveDocument.Pad.Shape App.ActiveDocument=App.getDocument("PrinterAssembly") App.ActiveDocument.addObject('Part::Feature','xRodTop').Shape=xRodTop #Define shifts and move into place xShift = -gv.xRodLength/2 yShift = (gv.extruderNozzleStandoff - gv.zRodStandoff - gv.xEndZRodHolderFaceThickness - gv.xEndZRodHolderMaxNutFaceToFace/2 - gv.xMotorMountPlateThickness - gv.xRodClampThickness - gv.xRodDiaMax/2 ) zShift = gv.xRodSpacing App.ActiveDocument=App.getDocument("PrinterAssembly") Draft.move([App.ActiveDocument.xRodTop],App.Vector(xShift, yShift, zShift),copy=False) App.ActiveDocument.recompute() xrt = App.ActiveDocument.xRodTop if xrt not in gv.xAxisParts: gv.xAxisParts.append(xrt)
def __init__(self,mainSec,flapSec,tol=10.**-5,FREECADPATH='/usr/lib/freecad/lib'): import sys sys.path.append(FREECADPATH) import FreeCAD import Draft mainSec=self.unique(mainSec,tol) flapSec=self.unique(flapSec,tol) Mmin=mainSec[:,0].argmin() Fmin=flapSec[:,0].argmin() mainTop=mainSec[0:Mmin+1,:] mainBot=mainSec[Mmin:,:] flapTop=flapSec[0:Fmin+1,:] flapBot=flapSec[Fmin:,:] FreeCAD.newDocument('flap2igs') objs=[] # self.mainObj=self.getSpline(mainSec) # self.flapObj=self.getSpline(flapSec) # objs.append(self.mainObj) # objs.append(self.flapObj) # self.cutObj=Draft.cut(self.boundaryObj,self.mainObj) # self.cutObj=Draft.cut(self.boundaryObj,self.mainObj) objs.append(self.getSpline(mainTop)) objs.append(self.getSpline(mainBot)) objs.append(self.getSpline(flapTop)) objs.append(self.getSpline(flapBot)) objs=self.closeTE(objs,mainSec) objs=self.closeTE(objs,flapSec) self.objs=objs
def testIssue3245(self): self.Doc2 = FreeCAD.newDocument("Issue3245") self.Doc2.addObject('Sketcher::SketchObject','Sketch') self.Doc2.Sketch.Placement = App.Placement(App.Vector(0.000000,0.000000,0.000000),App.Rotation(0.000000,0.000000,0.000000,1.000000)) self.Doc2.Sketch.MapMode = "Deactivated" self.Doc2.Sketch.addGeometry(Part.LineSegment(App.Vector(-1.195999,56.041161,0),App.Vector(60.654316,56.382877,0)),False) self.Doc2.Sketch.addConstraint(Sketcher.Constraint('PointOnObject',0,1,-2)) self.Doc2.Sketch.addConstraint(Sketcher.Constraint('Horizontal',0)) self.Doc2.Sketch.addGeometry(Part.LineSegment(App.Vector(0.512583,32.121155,0),App.Vector(60.654316,31.779440,0)),False) self.Doc2.Sketch.addConstraint(Sketcher.Constraint('Horizontal',1)) self.Doc2.Sketch.addGeometry(Part.LineSegment(App.Vector(0.170867,13.326859,0),App.Vector(61.679455,13.326859,0)),False) self.Doc2.Sketch.addConstraint(Sketcher.Constraint('PointOnObject',2,1,-2)) self.Doc2.Sketch.addConstraint(Sketcher.Constraint('Horizontal',2)) self.Doc2.Sketch.addConstraint(Sketcher.Constraint('PointOnObject',1,1,-2)) self.Doc2.Sketch.addConstraint(Sketcher.Constraint('DistanceX',0,1,0,2,60.654316)) self.Doc2.Sketch.setExpression('Constraints[6]', u'60') self.Doc2.Sketch.addConstraint(Sketcher.Constraint('DistanceX',1,1,1,2,60.654316)) self.Doc2.Sketch.setExpression('Constraints[7]', u'65') self.Doc2.Sketch.addConstraint(Sketcher.Constraint('DistanceX',2,1,2,2,61.679455)) self.Doc2.Sketch.setExpression('Constraints[8]', u'70') self.Doc2.recompute() self.Doc2.Sketch.delGeometry(2) values = d = {key: value for (key, value) in self.Doc2.Sketch.ExpressionEngine} self.failUnless(values['Constraints[4]'] == u'60') self.failUnless(values['Constraints[5]'] == u'65') FreeCAD.closeDocument("Issue3245")
# You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Navigation indicator for FreeCAD.""" import Tux_rc import FreeCAD as App import FreeCADGui as Gui from PySide import QtGui from PySide import QtCore timer = QtCore.QTimer() mw = Gui.getMainWindow() statusBar = mw.statusBar() p = App.ParamGet("User parameter:Tux/NavigationIndicator") pView = App.ParamGet("User parameter:BaseApp/Preferences/View") t0 = "Navigation style not recognized." t1 = str("""<p align='center'><b>OpenInventor</b> navigation style</p> <table> <tr> <th><small>Select</small></th> <th><small>Zoom</small></th> <th><small>Zoom</small></th> <th><small>Rotate</small></th> <th><small>Pan</small></th> </tr> <tr> <td align='center'><img src=':/icons/NavigationOpenInventor_Select.svg'></td>
__title__ = "ImportNURBS" __author__ = "Keith Sloan (KeithSloan52)" __license__ = "LGPL 2.1" __doc__ = "FreeCAD workbench to add importer of 3DM Files" import FreeCAD FreeCAD.addImportType("3DM (*.3dm)", "freecad.importNURBS.import3DM")
bpl_dicke = 250 dach_dicke = 300 haus_anzahl = 4 # init of some values needed haus_summe = haus_anzahl * (haus_b + trennwand_dicke) reihenhaus_laenge = haus_summe - trennwand_dicke + 2 * seitenwand_dicke hbase_x = base_x # local x-base of every house, start with global x-base # *************************************************************************** # get doc name and export file name, create a new document doc_name = os.path.splitext(os.path.basename(str(__file__)))[0] export_file = os.path.join(os.path.expanduser('~'), 'Desktop', doc_name) doc_obj = FreeCAD.newDocument(doc_name) # the container site = Arch.makeSite([], name="ETH-Reihenhaus") raeume_site = Arch.makeSite([], name="ETH-Reihenhaus") raeume_building = Arch.makeBuilding([], name="Reihenhaus_Raeume") Arch.addComponents(raeume_building, raeume_site) # the materials, windows, doors and spaces do not get a material brick = Arch.makeMaterial('Backstein') concrete = Arch.makeMaterial('Beton') brick.Color = (1.0, 0.502, 0.0, 0.0) concrete.Color = (0.439, 1.0, 0.439, 0.0) # *************************************************************************** # lets start with geometry creation
def Initialize(self): """This function is executed when FreeCAD starts""" #import Sw2R #import PlateSurface #import Birail #import paramVector #import SurfaceEdit # TODO changes module names to lower_with_underscore #import lineFP # cleaned #import bezierCurve stablelist = list() try: from freecad.Curves import graphics marker = graphics.Marker([App.Vector()]) from freecad.Curves import gordon_profile_FP stablelist = [] App.Console.PrintMessage("Pivy.graphics interaction library enabled\n") except: App.Console.PrintWarning("Pivy.graphics interaction library is not available on this computer\n") from freecad.Curves import lineFP # cleaned from freecad.Curves import curveExtendFP # TODO use basisSpline from freecad.Curves import JoinCurves from freecad.Curves import splitCurves_2 # cleaned from freecad.Curves import Discretize # cleaned from freecad.Curves import approximate from freecad.Curves import ParametricBlendCurve # cleaned from freecad.Curves import ParametricComb from freecad.Curves import ZebraTool from freecad.Curves import TrimFace from freecad.Curves import GeomInfo from freecad.Curves import ExtractShapes # cleaned from freecad.Curves import IsoCurve from freecad.Curves import Sketch_On_Surface from freecad.Curves import Sweep2Rails #from freecad.Curves import hooks from freecad.Curves import curveOnSurfaceFP from freecad.Curves import blendSurfaceFP from freecad.Curves import parametricSolid # cleaned from freecad.Curves import ProfileSketch from freecad.Curves import pasteSVG from freecad.Curves import pipeshellProfileFP from freecad.Curves import pipeshellFP from freecad.Curves import gordonFP from freecad.Curves import toConsole from freecad.Curves import mixed_curve from freecad.Curves import curve_to_script from freecad.Curves import sublink_edit from freecad.Curves import adjacent_faces from freecad.Curves import interpolate from freecad.Curves import comp_spring from freecad.Curves import ReflectLinesFP from freecad.Curves import segmentSurfaceFP from freecad.Curves import OrientedSketchFP from freecad.Curves import HQRuledSurfaceFP from freecad.Curves import multiLoftFP from freecad.Curves import HelicalSweepFP #import sectionSketch #if hasattr(Part.BezierSurface,"extendByLength"): #import ExtendSurfaceFP stablelist.extend(["line","gordon_profile","mixed_curve","extend","join","split","Discretize","Approximate","Interpolate","ParametricBlendCurve","ParametricComb","ZebraTool","Trim","GeomInfo","extract","solid","IsoCurve","SoS","sw2r","profileSupportCmd","cos","blendSurface","pasteSVG","profile","pipeshell","gordon","segment_surface","to_console","SublinkEditor","comp_spring","ReflectLines","oriented_sketch","hq_ruled_surface","MultiLoft","HelicalSweep"]) #if hasattr(Part.BezierSurface,"extendByLength"): #stablelist.append("extend_surface") self.appendToolbar("Curves",stablelist) self.appendMenu("Curves",stablelist) self.appendMenu("Curves",["bspline_to_console"])
obj = doc.addObject("Part::Feature", self.name + "_adafruit_DS3231_rtc") obj.Shape = self.adafruit_DS3231_rtc obj.Label = self.name + "_adafruit_DS3231_rtc" obj.ViewObject.ShapeColor = tuple([0.0, 0.0, 1.0]) obj = doc.addObject("Part::Feature", self.name + "_topdisk") obj.Shape = self.topdisk obj.Label = self.name + "_topdisk" obj.ViewObject.ShapeColor = tuple([1.0, 1.0, 1.0]) obj = doc.addObject("Part::Feature", self.name + "_guide1") obj.Shape = self.guide1 obj.Label = self.name + "_guide1" obj.ViewObject.ShapeColor = tuple([1.0, 1.0, 1.0]) obj = doc.addObject("Part::Feature", self.name + "_guide2") obj.Shape = self.guide2 obj.Label = self.name + "_guide2" obj.ViewObject.ShapeColor = tuple([1.0, 1.0, 1.0]) obj = doc.addObject("Part::Feature", self.name + "_guide3") obj.Shape = self.guide3 obj.Label = self.name + "_guide3" obj.ViewObject.ShapeColor = tuple([1.0, 1.0, 1.0]) if __name__ == '__main__': doc = App.newDocument("ComputerAssembly") App.setActiveDocument("ComputerAssembly") o = Base.Vector(0, 0, 0) ca = ComputerAssembly("CA", o) ca.show() Gui.SendMsgToActiveView("ViewFit")
def __init__(self): self.ac = "FreeCAD.DraftWorkingPlane.alignToPointAndAxis" self.param = FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Draft") self.states = []
def doStretch(self): """Do the actual stretching once the points are selected.""" commitops = [] if self.displacement: if self.displacement.Length > 0: _doc = "FreeCAD.ActiveDocument." # print("displacement: ", self.displacement) # TODO: break this section into individual functions # depending on the type of object (wire, curve, sketch, # rectangle, etc.) that is selected, and use variables # with common strings to avoid repeating # the same information every time, for example, the `_doc` # variable. # This is necessary to reduce the number of indentation levels # and make the code easier to read. for ops in self.ops: tp = utils.getType(ops[0]) _rot = ops[0].Placement.Rotation localdisp = _rot.inverted().multVec(self.displacement) if tp in ["Wire", "BSpline", "BezCurve"]: pts = [] for i in range(len(ops[1])): if ops[1][i] is False: pts.append(ops[0].Points[i]) else: pts.append(ops[0].Points[i].add(localdisp)) pts = str(pts).replace("Vector ", "FreeCAD.Vector") _cmd = _doc + ops[0].Name + ".Points=" + pts commitops.append(_cmd) elif tp in ["Sketch"]: baseverts = [ ops[0].Shape.Vertexes[i].Point for i in range(len(ops[1])) if ops[1][i] ] for i in range(ops[0].GeometryCount): j = 0 while True: try: p = ops[0].getPoint(i, j) except ValueError: break else: p = ops[0].Placement.multVec(p) r = None for bv in baseverts: if DraftVecUtils.isNull(p.sub(bv)): _cmd = _doc _cmd += ops[0].Name _cmd += ".movePoint" _cmd += "(" _cmd += str(i) + ", " _cmd += str(j) + ", " _cmd += "FreeCAD." + str( localdisp) + ", " _cmd += "True" _cmd += ")" commitops.append(_cmd) r = bv break if r: baseverts.remove(r) j += 1 elif tp in ["Rectangle"]: p1 = App.Vector(0, 0, 0) p2 = App.Vector(ops[0].Length.Value, 0, 0) p3 = App.Vector(ops[0].Length.Value, ops[0].Height.Value, 0) p4 = App.Vector(0, ops[0].Height.Value, 0) if ops[1] == [False, True, True, False]: optype = 1 elif ops[1] == [False, False, True, True]: optype = 2 elif ops[1] == [True, False, False, True]: optype = 3 elif ops[1] == [True, True, False, False]: optype = 4 else: optype = 0 # print("length:", ops[0].Length, # "height:", ops[0].Height, # " - ", ops[1], # " - ", self.displacement) done = False if optype > 0: v1 = ops[0].Placement.multVec(p2).sub( ops[0].Placement.multVec(p1)) a1 = round(self.displacement.getAngle(v1), 4) v2 = ops[0].Placement.multVec(p4).sub( ops[0].Placement.multVec(p1)) a2 = round(self.displacement.getAngle(v2), 4) # check if the displacement is along one # of the rectangle directions if a1 == 0: # 0 degrees if optype == 1: if ops[0].Length.Value >= 0: d = ops[ 0].Length.Value + self.displacement.Length else: d = ops[ 0].Length.Value - self.displacement.Length _cmd = _doc _cmd += ops[0].Name + ".Length=" + str(d) commitops.append(_cmd) done = True elif optype == 3: if ops[0].Length.Value >= 0: d = ops[ 0].Length.Value - self.displacement.Length else: d = ops[ 0].Length.Value + self.displacement.Length _cmd = _doc + ops[0].Name _cmd += ".Length=" + str(d) _pl = _doc + ops[0].Name _pl += ".Placement.Base=FreeCAD." _pl += str(ops[0].Placement.Base.add( self.displacement)) commitops.append(_cmd) commitops.append(_pl) done = True elif a1 == 3.1416: # pi radians, 180 degrees if optype == 1: if ops[0].Length.Value >= 0: d = ops[ 0].Length.Value - self.displacement.Length else: d = ops[ 0].Length.Value + self.displacement.Length _cmd = _doc + ops[0].Name _cmd += ".Length=" + str(d) commitops.append(_cmd) done = True elif optype == 3: if ops[0].Length.Value >= 0: d = ops[ 0].Length.Value + self.displacement.Length else: d = ops[ 0].Length.Value - self.displacement.Length _cmd = _doc + ops[0].Name _cmd += ".Length=" + str(d) _pl = _doc + ops[0].Name _pl += ".Placement.Base=FreeCAD." _pl += str(ops[0].Placement.Base.add( self.displacement)) commitops.append(_cmd) commitops.append(_pl) done = True elif a2 == 0: # 0 degrees if optype == 2: if ops[0].Height.Value >= 0: d = ops[ 0].Height.Value + self.displacement.Length else: d = ops[ 0].Height.Value - self.displacement.Length _cmd = _doc + ops[0].Name _cmd += ".Height=" + str(d) commitops.append(_cmd) done = True elif optype == 4: if ops[0].Height.Value >= 0: d = ops[ 0].Height.Value - self.displacement.Length else: d = ops[ 0].Height.Value + self.displacement.Length _cmd = _doc + ops[0].Name _cmd += ".Height=" + str(d) _pl = _doc + ops[0].Name _pl += ".Placement.Base=FreeCAD." _pl += str(ops[0].Placement.Base.add( self.displacement)) commitops.append(_cmd) commitops.append(_pl) done = True elif a2 == 3.1416: # pi radians, 180 degrees if optype == 2: if ops[0].Height.Value >= 0: d = ops[ 0].Height.Value - self.displacement.Length else: d = ops[ 0].Height.Value + self.displacement.Length _cmd = _doc + ops[0].Name _cmd += ".Height=" + str(d) commitops.append(_cmd) done = True elif optype == 4: if ops[0].Height.Value >= 0: d = ops[ 0].Height.Value + self.displacement.Length else: d = ops[ 0].Height.Value - self.displacement.Length _cmd = _doc + ops[0].Name _cmd += ".Height=" + str(d) _pl = _doc + ops[0].Name _pl += ".Placement.Base=FreeCAD." _pl += str(ops[0].Placement.Base.add( self.displacement)) commitops.append(_cmd) commitops.append(_pl) done = True if not done: # otherwise create a wire copy and stretch it instead _msg( translate("draft", "Turning one Rectangle into a Wire")) pts = [] opts = [p1, p2, p3, p4] for i in range(4): if ops[1][i] == False: pts.append(opts[i]) else: pts.append(opts[i].add(self.displacement)) pts = str(pts).replace("Vector ", "FreeCAD.Vector") _cmd = "Draft.makeWire" _cmd += "(" + pts + ", closed=True)" _format = "Draft.formatObject" _format += "(w, " _format += _doc + ops[0].Name _format += ")" _hide = _doc + ops[0].Name + ".ViewObject.hide()" commitops.append("w = " + _cmd) commitops.append(_format) commitops.append(_hide) # BUG: at this step the produced wire # doesn't seem to be in the correct position # compared to the original rectangle. # The base placement needs to be adjusted # just like with the other objects. for par in ops[0].InList: if hasattr(par, "Base") and par.Base == ops[0]: _base = _doc + par.Name + ".Base = w" commitops.append(_base) else: _pl = _doc + ops[0].Name _pl += ".Placement.Base=FreeCAD." _pl += str(ops[0].Placement.Base.add( self.displacement)) commitops.append(_pl) if commitops: commitops.append("FreeCAD.ActiveDocument.recompute()") Gui.addModule("Draft") self.commit(translate("draft", "Stretch"), commitops) self.finish()
def addPoint(self, point): """Add point to defined selection rectangle.""" if self.step == 1: # first rctangle point _msg( translate("draft", "Pick opposite point " "of selection rectangle")) self.ui.setRelative() self.rectracker.setorigin(point) self.rectracker.on() if self.planetrack: self.planetrack.set(point) self.step = 2 elif self.step == 2: # second rectangle point _msg(translate("draft", "Pick start point of displacement")) self.rectracker.off() nodes = [] self.ops = [] for sel in self.sel: o = sel[0] vispla = sel[1] tp = utils.getType(o) if tp in ["Wire", "BSpline", "BezCurve"]: np = [] iso = False for p in o.Points: p = o.Placement.multVec(p) p = vispla.multVec(p) isi = self.rectracker.isInside(p) np.append(isi) if isi: iso = True nodes.append(p) if iso: self.ops.append([o, np]) elif tp in ["Rectangle"]: p1 = App.Vector(0, 0, 0) p2 = App.Vector(o.Length.Value, 0, 0) p3 = App.Vector(o.Length.Value, o.Height.Value, 0) p4 = App.Vector(0, o.Height.Value, 0) np = [] iso = False for p in [p1, p2, p3, p4]: p = o.Placement.multVec(p) p = vispla.multVec(p) isi = self.rectracker.isInside(p) np.append(isi) if isi: iso = True nodes.append(p) if iso: self.ops.append([o, np]) elif tp in ["Sketch"]: np = [] iso = False for p in o.Shape.Vertexes: p = vispla.multVec(p.Point) isi = self.rectracker.isInside(p) np.append(isi) if isi: iso = True nodes.append(p) if iso: self.ops.append([o, np]) else: p = o.Placement.Base p = vispla.multVec(p) if self.rectracker.isInside(p): self.ops.append([o]) nodes.append(p) for n in nodes: nt = trackers.editTracker(n, inactive=True) nt.on() self.nodetracker.append(nt) self.step = 3 elif self.step == 3: # first point of displacement line _msg(translate("draft", "Pick end point of displacement")) self.displacement = point # print("first point:", point) self.node = [point] self.step = 4 elif self.step == 4: # print("second point:", point) self.displacement = point.sub(self.displacement) self.doStretch() if self.point: self.ui.redraw()
def execute(self, fp): if fp.OD>fp.OD2: if fp.thk>fp.OD/2: fp.thk=fp.OD/2.1 if fp.thk2>fp.OD2/2: fp.thk2=fp.OD2/2.1 if fp.calcH or fp.Height==0: fp.Height=3*(fp.OD-fp.OD2) fp.Profile=str(fp.OD)+"x"+str(fp.OD2) if fp.conc: fp.Shape = Part.makeCone(fp.OD/2,fp.OD2/2,fp.Height).cut(Part.makeCone(fp.OD/2-fp.thk,fp.OD2/2-fp.thk2,fp.Height)) fp.Ports=[FreeCAD.Vector(),FreeCAD.Vector(0,0,float(fp.Height))] else: C=Part.makeCircle(fp.OD/2,FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,1)) c=Part.makeCircle(fp.OD2/2,FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,1)) c.translate(FreeCAD.Vector((fp.OD-fp.OD2)/2,0,fp.Height)) sol=Part.makeLoft([c,C],True) #planeFaces=[f for f in sol.Faces if type(f.Surface)==Part.Plane] #fp.Shape= sol.makeThickness(planeFaces,-fp.thk,1.e-3) C=Part.makeCircle(fp.OD/2-fp.thk,FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,1)) c=Part.makeCircle(fp.OD2/2-fp.thk2,FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,1)) c.translate(FreeCAD.Vector((fp.OD-fp.OD2)/2,0,fp.Height)) fp.Shape=sol.cut(Part.makeLoft([c,C],True)) fp.Ports=[FreeCAD.Vector(),FreeCAD.Vector((fp.OD-fp.OD2)/2,0,float(fp.Height))]
def purge(self,fp): group=FreeCAD.activeDocument().getObjectsByLabel(fp.Group)[0] for o in group.OutList: if hasattr(o,'PType') and o.PType in ['Pipe','Elbow']: FreeCAD.activeDocument().removeObject(o.Name)
def export(exportList,filename,colors=None): """export(exportList,filename,colors=None): Called when freecad exports a file. exportList is a list of objects, filename is the .obj file to export (a .mtl file with same name will also be created together), and optionally colors can be a dict containing ["objectName:colorTuple"] pairs for use in non-GUI mode.""" import codecs outfile = codecs.open(filename,"wb",encoding="utf8") ver = FreeCAD.Version() outfile.write("# FreeCAD v" + ver[0] + "." + ver[1] + " build" + ver[2] + " Arch module\n") outfile.write("# http://www.freecadweb.org\n") offsetv = 1 offsetvn = 1 objectslist = Draft.get_group_contents(exportList, walls=True, addgroups=True) objectslist = Arch.pruneIncluded(objectslist) filenamemtl = filename[:-4] + ".mtl" materials = [] outfile.write("mtllib " + os.path.basename(filenamemtl) + "\n") for obj in objectslist: if obj.isDerivedFrom("Part::Feature") or obj.isDerivedFrom("Mesh::Feature") or obj.isDerivedFrom("App::Link"): hires = None if FreeCAD.GuiUp: visible = obj.ViewObject.isVisible() if obj.ViewObject.DisplayMode == "HiRes": # check if high-resolution object is available if hasattr(obj,"HiRes"): if obj.HiRes: if obj.HiRes.isDerivedFrom("Mesh::Feature"): m = obj.HiRes.Mesh else: m = obj.HiRes.Shape hires = m.copy() hires.Placement = obj.Placement.multiply(m.Placement) if not hires: if hasattr(obj,"CloneOf"): if obj.CloneOf: if hasattr(obj.CloneOf,"HiRes"): if obj.CloneOf.HiRes: if obj.CloneOf.HiRes.isDerivedFrom("Mesh::Feature"): m = obj.CloneOf.HiRes.Mesh else: m = obj.CloneOf.HiRes.Shape hires = m.copy() hires.Placement = obj.Placement.multiply(obj.CloneOf.Placement).multiply(m.Placement) else: visible = True if visible: if hires: vlist,vnlist,elist,flist = getIndices(obj,hires,offsetv,offsetvn) else: if hasattr(obj,"Shape") and obj.Shape: vlist,vnlist,elist,flist = getIndices(obj,obj.Shape,offsetv,offsetvn) elif hasattr(obj,"Mesh") and obj.Mesh: vlist,vnlist, elist,flist = getIndices(obj,obj.Mesh,offsetv,offsetvn) if vlist is None: FreeCAD.Console.PrintError("Unable to export object "+obj.Label+". Skipping.\n") else: offsetv += len(vlist) offsetvn += len(vnlist) outfile.write("o " + obj.Name + "\n") # write material m = False if hasattr(obj,"Material"): if obj.Material: if hasattr(obj.Material,"Material"): outfile.write("usemtl " + obj.Material.Name + "\n") materials.append(obj.Material) m = True if not m: if colors: if obj.Name in colors: color = colors[obj.Name] if color: if isinstance(color[0],tuple): # this is a diffusecolor. For now, use the first color - #TODO: Support per-face colors color = color[0] #print("found color for obj",obj.Name,":",color) mn = Draft.getrgb(color,testbw=False)[1:] outfile.write("usemtl color_" + mn + "\n") materials.append(("color_" + mn,color,0)) elif FreeCAD.GuiUp: if hasattr(obj.ViewObject,"ShapeColor") and hasattr(obj.ViewObject,"Transparency"): mn = Draft.getrgb(obj.ViewObject.ShapeColor,testbw=False)[1:] outfile.write("usemtl color_" + mn + "\n") materials.append(("color_" + mn,obj.ViewObject.ShapeColor,obj.ViewObject.Transparency)) # write geometry for v in vlist: outfile.write("v" + v + "\n") for vn in vnlist: outfile.write("vn" + vn + "\n") for e in elist: outfile.write("l" + e + "\n") for f in flist: outfile.write("f" + f + "\n") outfile.close() FreeCAD.Console.PrintMessage(translate("Arch","Successfully written") + " " + decode(filename) + "\n") if materials: outfile = pythonopen(filenamemtl,"w") outfile.write("# FreeCAD v" + ver[0] + "." + ver[1] + " build" + ver[2] + " Arch module\n") outfile.write("# http://www.freecadweb.org\n") kinds = {"AmbientColor":"Ka ","DiffuseColor":"Kd ","SpecularColor":"Ks ","EmissiveColor":"Ke ","Transparency":"Tr "} done = [] # store names to avoid duplicates for mat in materials: if isinstance(mat,tuple): if not mat[0] in done: outfile.write("newmtl " + mat[0] + "\n") outfile.write("Kd " + str(mat[1][0]) + " " + str(mat[1][1]) + " " + str(mat[1][2]) + "\n") outfile.write("Tr " + str(mat[2]/100) + "\n") done.append(mat[0]) else: if not mat.Name in done: outfile.write("newmtl " + mat.Name + "\n") for prop in kinds: if prop in mat.Material: outfile.write(kinds[prop] + mat.Material[prop].strip("()").replace(',',' ') + "\n") done.append(mat.Name) outfile.write("# Material Count: " + str(len(materials))) outfile.close() FreeCAD.Console.PrintMessage(translate("Arch","Successfully written") + ' ' + decode(filenamemtl) + "\n")
def __init__(self, obj=None, prop=None, material=None, card_path=''): """Initializes, optionally with an object name and a material property name to edit, or directly with a material dictionary.""" self.obj = obj self.prop = prop self.material = material self.customprops = [] self.internalprops = [] self.groups = [] self.directory = FreeCAD.getResourceDir() + "Mod/Material" self.materials = {} self.cards = {} self.icons = {} self.card_path = card_path # load the UI file from the same directory as this script self.widget = FreeCADGui.PySideUic.loadUi( os.path.dirname(__file__) + os.sep + "materials-editor.ui") self.widget.setWindowIcon(QtGui.QIcon(":/icons/preview-rendered.svg")) # restore size and position p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Material") w = p.GetInt("MaterialEditorWidth", 441) h = p.GetInt("MaterialEditorHeight", 626) self.widget.resize(w, h) # additional UI fixes and tweaks widget = self.widget buttonURL = widget.ButtonURL buttonDeleteProperty = widget.ButtonDeleteProperty buttonAddProperty = widget.ButtonAddProperty standardButtons = widget.standardButtons buttonOpen = widget.ButtonOpen buttonSave = widget.ButtonSave comboMaterial = widget.ComboMaterial treeView = widget.treeView # create preview svg slots self.widget.PreviewRender = QtSvg.QSvgWidget( ":/icons/preview-rendered.svg") self.widget.PreviewRender.setMaximumWidth(64) self.widget.PreviewRender.setMinimumHeight(64) self.widget.topLayout.addWidget(self.widget.PreviewRender) self.widget.PreviewVector = QtSvg.QSvgWidget( ":/icons/preview-vector.svg") self.widget.PreviewVector.setMaximumWidth(64) self.widget.PreviewVector.setMinimumHeight(64) self.widget.topLayout.addWidget(self.widget.PreviewVector) self.updatePreviews(mat=material) buttonURL.setIcon(QtGui.QIcon(":/icons/internet-web-browser.svg")) buttonDeleteProperty.setEnabled(False) standardButtons.button(QtGui.QDialogButtonBox.Ok).setAutoDefault(False) standardButtons.button( QtGui.QDialogButtonBox.Cancel).setAutoDefault(False) self.updateCardsInCombo() # TODO allow to enter a custom property by pressing Enter in the lineedit # currently closes the dialog standardButtons.rejected.connect(self.reject) standardButtons.accepted.connect(self.accept) buttonOpen.clicked.connect(self.openfile) buttonSave.clicked.connect(self.savefile) buttonURL.clicked.connect(self.openProductURL) comboMaterial.currentIndexChanged[int].connect(self.chooseMaterial) buttonAddProperty.clicked.connect(self.addCustomProperty) buttonDeleteProperty.clicked.connect(self.deleteCustomProperty) treeView.clicked.connect(self.onClickTree) model = QtGui.QStandardItemModel() treeView.setModel(model) treeView.setUniformRowHeights(True) treeView.setItemDelegate(MaterialsDelegate()) # init model self.implementModel() # update the editor with the contents of the property, if we have one d = None if self.prop and self.obj: d = FreeCAD.ActiveDocument.getObject(self.obj).getPropertyByName( self.prop) elif self.material: d = self.material if d: self.updateMatParamsInTree(d) self.widget.ComboMaterial.setCurrentIndex(0) # set after tree params to the none material if self.card_path: # we need the index of this path index = self.widget.ComboMaterial.findData(self.card_path) self.chooseMaterial(index)
def tup2nvect(tup): """convert a tuple to a normalized vector""" v = FreeCAD.Vector(*tup) v.normalize() return v
def run(self): """run(): Runs a nesting operation. Returns a list of lists of shapes, each primary list being one filled container, or None if the operation failed.""" # reset abort mechanism and variables self.running = True self.progress = 0 starttime = datetime.now() # general conformity tests print("Executing conformity tests ... ",end="") if not self.container: print("Empty container. Aborting") return if not self.shapes: print("Empty shapes. Aborting") return if not isinstance(self.container,Part.Face): print("Container is not a face. Aborting") return normal = self.container.normalAt(0,0) for s in self.shapes: if not self.update(): return if len(s.Faces) != 1: print("One of the shapes does not contain exactly one face. Aborting") return # check if all faces correctly oriented (same normal) if s.Faces[0].normalAt(0,0).getAngle(normal) > TOLERANCE: # let pass faces with inverted normal if s.Faces[0].normalAt(0,0).getAngle(normal)-math.pi > TOLERANCE: print("One of the face doesn't have the same orientation as the container. Aborting") return # TODO # allow to use a non-rectangular container # manage margins/paddings # allow to prevent or force specific rotations for a piece # LONG-TERM TODO # add genetic algo to swap pieces, and check if the result is better # track progresses step = 100.0/(len(self.shapes)*len(ROTATIONS)) # store hashCode together with the face so we can change the order # and still identify the original face, so we can calculate a transform afterwards self.indexedfaces = [[shape.hashCode(),shape] for shape in self.shapes] # build a clean copy so we don't touch the original faces = list(self.indexedfaces) # replace shapes by their face faces = [[f[0],f[1].Faces[0]] for f in faces] # order by area faces = sorted(faces,key=lambda face: face[1].Area) # discretize non-linear edges and remove holes nfaces = [] for face in faces: if not self.update(): return nedges = [] allLines = True for edge in face[1].OuterWire.OrderedEdges: if isinstance(edge.Curve,(Part.LineSegment,Part.Line)): nedges.append(edge) else: allLines = False last = edge.Vertexes[0].Point for i in range(DISCRETIZE): s = float(i+1)/DISCRETIZE par = edge.FirstParameter + (edge.LastParameter-edge.FirstParameter)*s new = edge.valueAt(par) nedges.append(Part.LineSegment(last,new).toShape()) last = new f = Part.Face(Part.Wire(nedges)) if not f.isValid(): if allLines: print("Invalid face found in set. Aborting") else: print("Face distretizing failed. Aborting") return nfaces.append([face[0],f]) faces = nfaces # container for sheets with a first, empty sheet sheets = [[]] print("Everything OK (",datetime.now()-starttime,")") # main loop facenumber = 1 facesnumber = len(faces) #print("Vertices per face:",[len(face[1].Vertexes) for face in faces]) while faces: print("Placing piece",facenumber,"/",facesnumber,"Area:",FreeCAD.Units.Quantity(faces[-1][1].Area,FreeCAD.Units.Area).getUserPreferred()[0],": ",end="") face = faces.pop() boc = self.container.BoundBox # this stores the available solutions for each rotation of a piece # contains [sheetnumber,face,xlength] lists, # face being [hascode,transformed face] and xlength # the X size of all boundboxes of placed pieces available = [] # this stores the possible positions on a blank # sheet, in case we need to create a new one initials = [] # this checks if the piece don't fit in the container unfit = True for rotation in ROTATIONS: if not self.update(): return self.progress += step print(rotation,", ",end="") hashcode = face[0] rotface = face[1].copy() if rotation: rotface.rotate(rotface.CenterOfMass,normal,rotation) bof = rotface.BoundBox rotverts = self.order(rotface) #for i,v in enumerate(rotverts): # Draft.makeText([str(i)],point=v) basepoint = rotverts[0] # leftmost point of the rotated face basecorner = boc.getPoint(0) # lower left corner of the container # See if the piece fits in the container dimensions if (bof.XLength < boc.XLength) and (bof.YLength < boc.YLength): unfit = False # Get the fit polygon of the container # that is, the polygon inside which basepoint can # circulate, and the face still be fully inside the container v1 = basecorner.add(basepoint.sub(bof.getPoint(0))) v2 = v1.add(FreeCAD.Vector(0,boc.YLength-bof.YLength,0)) v3 = v2.add(FreeCAD.Vector(boc.XLength-bof.XLength,0,0)) v4 = v3.add(FreeCAD.Vector(0,-(boc.YLength-bof.YLength),0)) binpol = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1])) initials.append([binpol,[hashcode,rotface],basepoint]) # check for available space on each existing sheet for sheetnumber,sheet in enumerate(sheets): # Get the no-fit polygon for each already placed face in # current sheet. That is, a polygon in which basepoint # cannot be, if we want our face to not overlap with the # placed face. # To do this, we "circulate" the face around the placed face if not self.update(): return nofitpol = [] for placed in sheet: pts = [] for placedvert in self.order(placed[1],right=True): fpts = [] for i,rotvert in enumerate(rotverts): if not self.update(): return facecopy = rotface.copy() facecopy.translate(placedvert.sub(rotvert)) # test if all the points of the face are outside the # placed face (except the base point, which is coincident) outside = True faceverts = self.order(facecopy) for vert in faceverts: if (vert.sub(placedvert)).Length > TOLERANCE: if placed[1].isInside(vert,TOLERANCE,True): outside = False break # also need to test for edge intersection, because even # if all vertices are outside, the pieces could still # overlap if outside: for e1 in facecopy.OuterWire.Edges: for e2 in placed[1].OuterWire.Edges: if not self.update(): return if True: # Draft code (SLOW) p = DraftGeomUtils.findIntersection(e1,e2) if p: p = p[0] p1 = e1.Vertexes[0].Point p2 = e1.Vertexes[1].Point p3 = e2.Vertexes[0].Point p4 = e2.Vertexes[1].Point if (p.sub(p1).Length > TOLERANCE) and (p.sub(p2).Length > TOLERANCE) \ and (p.sub(p3).Length > TOLERANCE) and (p.sub(p4).Length > TOLERANCE): outside = False break else: # alt code: using distToShape (EVEN SLOWER!) p = e1.distToShape(e2) if p: if p[0] < TOLERANCE: # allow vertex-to-vertex intersection if (p[2][0][0] != "Vertex") or (p[2][0][3] != "Vertex"): outside = False break if outside: fpts.append([faceverts[0],i]) #Draft.makeText([str(i)],point=faceverts[0]) # reorder available solutions around a same point if needed # ensure they are in the correct order idxs = [p[1] for p in fpts] if (0 in idxs) and (len(faceverts)-1 in idxs): slicepoint = len(fpts) last = len(faceverts) for p in reversed(fpts): if p[1] == last-1: slicepoint -= 1 last -= 1 else: break fpts = fpts[slicepoint:]+fpts[:slicepoint] #print(fpts) pts.extend(fpts) # create the polygon if len(pts) < 3: print("Error calculating a no-fit polygon. Aborting") return pts = [p[0] for p in pts] pol = Part.Face(Part.makePolygon(pts+[pts[0]])) if not pol.isValid(): # fix overlapping edges overlap = True while overlap: overlap = False for i in range(len(pol.OuterWire.Edges)-1): if not self.update(): return v1 = DraftGeomUtils.vec(pol.OuterWire.OrderedEdges[i]) v2 = DraftGeomUtils.vec(pol.OuterWire.OrderedEdges[i+1]) if abs(v1.getAngle(v2)-math.pi) <= TOLERANCE: overlap = True ne = Part.LineSegment(pol.OuterWire.OrderedEdges[i].Vertexes[0].Point, pol.OuterWire.OrderedEdges[i+1].Vertexes[-1].Point).toShape() pol = Part.Face(Part.Wire(pol.OuterWire.OrderedEdges[:i]+[ne]+pol.OuterWire.OrderedEdges[i+2:])) break if not pol.isValid(): # trying basic OCC fix pol.fix(0,0,0) if pol.isValid(): if pol.ShapeType == "Face": pol = Part.Face(pol.OuterWire) # discard possible inner holes elif pol.Faces: # several faces after the fix, keep the biggest one a = 0 ff = None for f in pol.Faces: if f.Area > a: a = f.Area ff = f if ff: pol = ff else: print("Unable to fix invalid no-fit polygon. Aborting") Part.show(pol) return if not pol.isValid(): # none of the fixes worked. Epic fail. print("Invalid no-fit polygon. Aborting") Part.show(pol.OuterWire) for p in sheet: Part.show(p[1]) Part.show(facecopy) #for i,p in enumerate(faceverts): # Draft.makeText([str(i)],point=p) return if pol.isValid(): nofitpol.append(pol) #Part.show(pol) # Union all the no-fit pols into one if len(nofitpol) == 1: nofitpol = nofitpol[0] elif len(nofitpol) > 1: b = nofitpol.pop() for n in nofitpol: if not self.update(): return b = b.fuse(n) nofitpol = b # remove internal edges (discard edges shared by 2 faces) lut = {} for f in fitpol.Faces: for e in f.Edges: h = e.hashCode() if h in lut: lut[h].append(e) else: lut[h] = [e] edges = [e[0] for e in lut.values() if len(e) == 1] try: pol = Part.Face(Part.Wire(edges)) except Exception: # above method can fail sometimes. Try a slower method w = DraftGeomUtils.findWires(edges) if len(w) == 1: if w[0].isClosed(): try: pol = Part.Face(w[0]) except Exception: print("Error merging polygons. Aborting") try: Part.show(Part.Wire(edges)) except Exception: for e in edges: Part.show(e) return # subtract the no-fit polygon from the container's fit polygon # we then have the zone where the face can be placed if nofitpol: fitpol = binpol.cut(nofitpol) else: fitpol = binpol.copy() # check that we have some space on this sheet if (fitpol.Area > 0) and fitpol.Vertexes: # order the fitpol vertexes by smallest X # and try to place the piece, making sure it doesn't # intersect with already placed pieces fitverts = sorted([v.Point for v in fitpol.Vertexes],key=lambda v: v.x) for p in fitverts: if not self.update(): return trface = rotface.copy() trface.translate(p.sub(basepoint)) ok = True for placed in sheet: if ok: for vert in trface.Vertexes: if placed[1].isInside(vert.Point,TOLERANCE,False): ok = False break if ok: for e1 in trface.OuterWire.Edges: for e2 in placed[1].OuterWire.Edges: p = DraftGeomUtils.findIntersection(e1,e2) if p: p = p[0] p1 = e1.Vertexes[0].Point p2 = e1.Vertexes[1].Point p3 = e2.Vertexes[0].Point p4 = e2.Vertexes[1].Point if (p.sub(p1).Length > TOLERANCE) and (p.sub(p2).Length > TOLERANCE) \ and (p.sub(p3).Length > TOLERANCE) and (p.sub(p4).Length > TOLERANCE): ok = False break if not ok: break if ok: rotface = trface break else: print("Couldn't determine location on sheet. Aborting") return # check the X space occupied by this solution bb = rotface.BoundBox for placed in sheet: bb.add(placed[1].BoundBox) available.append([sheetnumber,[hashcode,rotface],bb.XMax,fitpol]) if unfit: print("One face doesn't fit in the container. Aborting") return if available: # order by smallest X size and take the first one available = sorted(available,key=lambda sol: sol[2]) print("Adding piece to sheet",available[0][0]+1) sheets[available[0][0]].append(available[0][1]) #Part.show(available[0][3]) else: # adding to the leftmost vertex of the binpol sheet = [] print("Creating new sheet, adding piece to sheet",len(sheets)) # order initial positions by smallest X size initials = sorted(initials,key=lambda sol: sol[1][1].BoundBox.XLength) hashcode = initials[0][1][0] face = initials[0][1][1] # order binpol vertexes by X coord verts = sorted([v.Point for v in initials[0][0].Vertexes],key=lambda v: v.x) face.translate(verts[0].sub(initials[0][2])) sheet.append([hashcode,face]) sheets.append(sheet) facenumber += 1 print("Run time:",datetime.now()-starttime) self.results.append(sheets) return sheets
def move(self): info = self.info part = info.Part obj = self.assembly.Object pla = utils.roundPlacement(self.viewObject.DraggingPlacement) updatePla = True rollback = [] if self.moveElement: updatePla = False # obtain the placement of an unoffseted element in assembly coordinate offset = utils.getElementPlacement( self.element.getSubObject('', transform=False)) self.element.Offset = utils.roundPlacement( offset.inverse().multiply(pla)) self.element.recompute(True) return elif not info.Subname.startswith('Face') and utils.isDraftWire(part): updatePla = False if info.Subname.startswith('Vertex'): idx = utils.draftWireVertex2PointIndex(part, info.Subname) if idx is None: logger.error('Invalid draft wire vertex {} {}', info.Subname, info.PartName) return change = [idx] else: change = utils.edge2VertexIndex(part, info.Subname, True) if change[0] is None or change[1] is None: logger.error('Invalid draft wire edge {} {}', info.Subname, info.PartName) return movement = self.Movement points = part.Points for idx in change: pt = points[idx] rollback.append((info.PartName, part, (idx, pt))) points[idx] = movement.multVec(pt) part.Points = points elif info.Subname.startswith('Vertex') and utils.isDraftCircle(part): updatePla = False a1 = part.FirstAngle a2 = part.LastAngle r = part.Radius rollback.append((info.PartName, part, (r, a1, a2))) pt = info.Placement.inverse().multVec(pla.Base) part.Radius = pt.Length if a1 != a2: pt.z = 0 a = math.degrees(FreeCAD.Vector(1, 0, 0).getAngle(pt)) if info.Subname.endswith('1'): part.FirstAngle = a else: part.LastAngle = a elif self.fixedTransform: fixed = self.fixedTransform movement = self.Movement if fixed.Shape: # fixed position, so reset translation movement.Base = FreeCAD.Vector() if not utils.isVertex(fixed.Shape): yaw, _, _ = movement.Rotation.toEuler() # when dragging with a fixed axis, we align the dragger Z # axis with that fixed axis. So we shall only keep the yaw # among the euler angles movement.Rotation = FreeCAD.Rotation(yaw, 0, 0) pla = self.draggerPlacement.multiply(movement) if updatePla: # obtain and update the part placement pla = pla.multiply(self.offsetInv) setPlacement(info.Part, pla) rollback.append((info.PartName, info.Part, info.Placement.copy())) if QtGui.QApplication.keyboardModifiers() == QtCore.Qt.ShiftModifier: return if not gui.AsmCmdManager.AutoRecompute or \ QtGui.QApplication.keyboardModifiers()==QtCore.Qt.ControlModifier: # AsmCmdManager.AutoRecompute means auto re-solve the system. The # recompute() call below is only for updating linked element and # stuff obj.recompute(True) return # calls solver.solve(obj) and redirect all the exceptions message # to logger only. from . import solver if not logger.catch('solver exception when moving part', solver.solve, self.objs, dragPart=info.Part, rollback=rollback): obj.recompute(True) if gui.AsmCmdManager.Trace: pos = self.TracePosition if not self.tracePoint.isEqual(pos, 1e-5): try: # check if the object is deleted self.trace.Name except Exception: self.trace = None if not self.trace: self.trace = FreeCAD.ActiveDocument.addObject( 'Part::Polygon', 'AsmTrace') self.trace.Nodes = [self.tracePoint] self.tracePoint = pos self.trace.Nodes = {-1: pos} self.trace.recompute() # self.draggerPlacement, which holds the intended dragger placement, is # updated by the above solver call through the following chain, # solver.solve() -> (triggers dependent objects recompute when done) # Assembly.execute() -> # ViewProviderAssembly.onExecute() -> # AsmMovingPart.update() return self.draggerPlacement
import FreeCAD, FreeCADGui FreeCAD.open(FreeCAD.getResourceDir() + "examples/ArchDetail.FCStd") FreeCADGui.activeDocument().sendMsgToViews("ViewFit")
def accept(self): import Draft import Arch import Part import FreeCADGui if self.form.groupNewDocument.isChecked() or (FreeCAD.ActiveDocument is None): doc = FreeCAD.newDocument() if self.form.projectName.text(): doc.Label = self.form.projectName.text() FreeCAD.ActiveDocument = doc if not FreeCAD.ActiveDocument: FreeCAD.Console.PrintError( translate("BIM", "No active document, aborting.") + "\n") site = None outline = None if self.form.groupSite.isChecked(): site = Arch.makeSite() site.Label = self.form.siteName.text() site.Address = self.form.siteAddress.text() site.Longitude = self.form.siteLongitude.value() site.Latitude = self.form.siteLatitude.value() if hasattr(site, "NorthDeviation"): site.NorthDeviation = self.form.siteDeviation.value() elif hasattr(site, "Declination"): site.Declination = self.form.siteDeviation.value() site.Elevation = FreeCAD.Units.Quantity( self.form.siteElevation.text()).Value human = None if self.form.addHumanFigure.isChecked(): humanshape = Part.Shape() humanpath = os.path.join(os.path.dirname(__file__), "geometry", "human figure.brep") humanshape.importBrep(humanpath) human = FreeCAD.ActiveDocument.addObject("Part::Feature", "Human") human.Shape = humanshape human.Placement.move(FreeCAD.Vector(500, 500, 0)) if self.form.groupBuilding.isChecked(): building = Arch.makeBuilding() if site: site.Group = [building] building.Label = self.form.buildingName.text() building.BuildingType = self.form.buildingUse.currentText() buildingWidth = FreeCAD.Units.Quantity( self.form.buildingWidth.text()).Value buildingLength = FreeCAD.Units.Quantity( self.form.buildingLength.text()).Value distVAxes = FreeCAD.Units.Quantity( self.form.distVAxes.text()).Value distHAxes = FreeCAD.Units.Quantity( self.form.distHAxes.text()).Value levelHeight = FreeCAD.Units.Quantity( self.form.levelHeight.text()).Value color = self.form.lineColor.property("color").getRgbF()[:3] if buildingWidth and buildingLength: outline = Draft.makeRectangle(buildingLength, buildingWidth, face=False) outline.Label = translate("BIM", "Building Outline") outline.ViewObject.DrawStyle = "Dashed" outline.ViewObject.LineColor = color outline.ViewObject.LineWidth = self.form.lineWidth.value() * 2 grp = FreeCAD.ActiveDocument.addObject( "App::DocumentObjectGroup") grp.Label = translate("BIM", "Building Layout") building.addObject(grp) grp.addObject(outline) if self.form.buildingName.text(): buildingname = self.form.buildingName.text() if sys.version_info.major == 2: buildingname = unicode(buildingname) outtext = Draft.makeText( [buildingname], point=FreeCAD.Vector( Draft.getParam("textheight", 0.20) * 0.3, -Draft.getParam("textheight", 0.20) * 1.43, 0)) outtext.Label = translate("BIM", "Building Label") outtext.ViewObject.TextColor = color grp.addObject(outtext) if human: grp.addObject(human) axisV = None if self.form.countVAxes.value() and distVAxes: axisV = Arch.makeAxis(num=self.form.countVAxes.value(), size=distVAxes, name="vaxis") axisV.Label = translate("BIM", "Vertical Axes") axisV.ViewObject.BubblePosition = "Both" axisV.ViewObject.LineWidth = self.form.lineWidth.value() axisV.ViewObject.FontSize = Draft.getParam("textheight", 0.20) axisV.ViewObject.BubbleSize = Draft.getParam( "textheight", 0.20) * 1.43 axisV.ViewObject.LineColor = color if outline: axisV.setExpression('Length', outline.Name + '.Height * 1.1') axisV.setExpression( 'Placement.Base.y', outline.Name + '.Placement.Base.y - ' + axisV.Name + '.Length * 0.05') axisV.setExpression('Placement.Base.x', outline.Name + '.Placement.Base.x') axisH = None if self.form.countHAxes.value() and distHAxes: axisH = Arch.makeAxis(num=self.form.countHAxes.value(), size=distHAxes, name="haxis") axisH.Label = translate("BIM", "Horizontal Axes") axisH.ViewObject.BubblePosition = "Both" axisH.ViewObject.NumberingStyle = "A,B,C" axisH.ViewObject.LineWidth = self.form.lineWidth.value() axisH.ViewObject.FontSize = Draft.getParam("textheight", 0.20) axisH.ViewObject.BubbleSize = Draft.getParam( "textheight", 0.20) * 1.43 axisH.Placement.Rotation = FreeCAD.Rotation( FreeCAD.Vector(0, 0, 1), 90) axisH.ViewObject.LineColor = color if outline: axisH.setExpression('Length', outline.Name + '.Length * 1.1') axisH.setExpression( 'Placement.Base.x', outline.Name + '.Placement.Base.x + ' + axisH.Name + '.Length * 0.945') axisH.setExpression('Placement.Base.y', outline.Name + '.Placement.Base.y') if axisV and axisH: axisG = Arch.makeAxisSystem([axisH, axisV]) axisG.Label = translate("BIM", "Axes") grp.addObject(axisG) else: if axisV: grp.addObject(axisV) if axisH: grp.addObject(axisH) if self.form.countLevels.value() and levelHeight: h = 0 alabels = [] for i in range(self.form.countLevels.value()): lev = Arch.makeFloor() lev.Label = translate("BIM", "Level") + " " + str(i) alabels.append(lev.Label) lev.Height = levelHeight lev.Placement.move(FreeCAD.Vector(0, 0, h)) h += levelHeight building.addObject(lev) if self.form.levelsWP.isChecked(): prx = Draft.makeWorkingPlaneProxy(FreeCAD.Placement()) prx.Placement.move(FreeCAD.Vector(0, 0, h)) lev.addObject(prx) if self.form.levelsAxis.isChecked(): axisL = Arch.makeAxis(num=self.form.countLevels.value(), size=levelHeight, name="laxis") axisL.Label = translate("BIM", "Level Axes") axisL.ViewObject.BubblePosition = "None" axisL.ViewObject.LineWidth = self.form.lineWidth.value() axisL.ViewObject.FontSize = Draft.getParam( "textheight", 0.20) axisL.Placement.Rotation = FreeCAD.Rotation( FreeCAD.Vector(0.577350269189626, -0.5773502691896257, 0.5773502691896257), 120) axisL.ViewObject.LineColor = color axisL.ViewObject.LabelOffset.Rotation = FreeCAD.Rotation( FreeCAD.Vector(1, 0, 0), 90) axisL.Labels = alabels axisL.ViewObject.ShowLabel = True if outline: axisL.setExpression('Length', outline.Name + '.Length * 1.1') axisL.setExpression( 'Placement.Base.x', outline.Name + '.Placement.Base.x + ' + axisL.Name + '.Length * 0.945') axisL.setExpression('Placement.Base.y', outline.Name + '.Placement.Base.y') grp.addObject(axisL) axisL.ViewObject.LabelOffset.Base = FreeCAD.Vector( -axisL.Length.Value + Draft.getParam("textheight", 0.20) * 0.43, 0, Draft.getParam("textheight", 0.20) * 0.43) self.form.hide() FreeCAD.ActiveDocument.recompute() if outline: FreeCADGui.Selection.clearSelection() FreeCADGui.Selection.addSelection(outline) FreeCADGui.SendMsgToActiveView("ViewSelection") FreeCADGui.Selection.clearSelection() if hasattr(FreeCADGui, "Snapper"): FreeCADGui.Snapper.show() return True
def __init__(self): FreeCAD.addDocumentObserver(self)
def saveTemplate(self): """saves the contents of the current file as a template""" d = FreeCAD.ActiveDocument if not d: d = FreeCAD.newDocument() # build list of useful settings to store values = {} if hasattr(FreeCAD, "DraftWorkingPlane"): values["wpposition"] = str(FreeCAD.DraftWorkingPlane.position) values["wpu"] = str(FreeCAD.DraftWorkingPlane.u) values["wpv"] = str(FreeCAD.DraftWorkingPlane.v) values["wpaxis"] = str(FreeCAD.DraftWorkingPlane.axis) values["unit"] = str( FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Units").GetInt( "UserSchema", 0)) values["textsize"] = str( FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Draft").GetFloat( "textheight", 10)) values["textfont"] = str( FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Draft").GetString( "textfont", "Sans")) values["dimstyle"] = str( FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Draft").GetInt( "dimsymbol", 0)) values["arrowsize"] = str( FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Draft").GetFloat( "arrowsize", 5)) values["decimals"] = str( FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Units").GetInt( "Decimals", 2)) values["grid"] = str( FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Draft").GetFloat( "gridSpacing", 10)) values["squares"] = str( FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Draft").GetInt( "gridEvery", 10)) values["linewidth"] = str( FreeCAD.ParamGet("User parameter:BaseApp/Preferences/View").GetInt( "DefautShapeLineWidth", 2)) values["colFace"] = str( FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/View").GetUnsigned( "DefaultShapeColor", 4294967295)) values["colLine"] = str( FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/View").GetUnsigned( "DefaultShapeLineColor", 255)) values["colHelp"] = str( FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Arch").GetUnsigned( "ColorHelpers", 674321151)) values["colConst"] = str( FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Draft").GetUnsigned( "constructioncolor", 746455039)) d.Meta = values from PySide import QtCore, QtGui filename = QtGui.QFileDialog.getSaveFileName( QtGui.QApplication.activeWindow(), translate("BIM", "Save template file"), None, "FreeCAD file (*.FCStd)") if filename: filename = filename[0] if not filename.lower().endswith(".FCStd"): filename += ".FCStd" d.saveCopy(filename) FreeCAD.Console.PrintMessage( translate("BIM", "Template saved successfully") + "\n") self.reject()
def __init__(self, moveInfo, element, moveElement): hierarchy = moveInfo.HierarchyList info = moveInfo.ElementInfo self.objs = [h.Assembly for h in reversed(hierarchy)] self.assembly = resolveAssembly(info.Parent) self.viewObject = self.assembly.Object.ViewObject self.info = info self.element = element self.undos = None self.trace = None self.tracePoint = None self.moveElement = moveElement self.sels = [] view = self.viewObject.Document.ActiveView shape = None if hasattr(view, 'addObjectOnTop'): self.view = view else: self.view = None if element: if self.view: self.sels.append((moveInfo.SelObj, moveInfo.SelSubname)) view.addObjectOnTop(*self.sels[0]) logger.debug('group on top {}.{}', moveInfo.SelObj.Name, moveInfo.SelSubname) shape = element.getSubObject('') # whether to move element itself or its owner part if moveElement: self.bbox = shape.BoundBox # Place the dragger at element's current (maybe offseted) shape # center point in assembly coordinate self.draggerPlacement = utils.getElementPlacement(shape) return # if we are not moving the element, but its owner part, transform # the element shape to part's coordinate space shape.Placement = shape.Placement.multiply( info.Placement.inverse()) if self.view: sub = moveInfo.SelSubname[:-len(info.SubnameRef)] if isinstance(info.Part, tuple): sub += '2.{}.{}.'.format(info.Part[0].Name, info.Part[1]) else: sub += '2.{}.'.format(info.Part.Name) self.sels.append((moveInfo.SelObj, sub)) logger.debug('group on top {}.{}', moveInfo.SelObj.Name, sub) view.addObjectOnTop(*self.sels[-1]) fixed = Constraint.getFixedTransform(self.assembly.getConstraints()) fixed = fixed.get(info.Part, None) self.fixedTransform = fixed if not shape: if fixed and fixed.Shape: shape = fixed.Shape else: shape = info.Shape rot = utils.getElementRotation(shape) if not rot: # in case the shape has no normal, like a vertex, just use an empty # rotation, which means having the same rotation as the owner part. rot = FreeCAD.Rotation() hasBound = True if not utils.isVertex(shape): self.bbox = shape.BoundBox else: bbox = info.Object.ViewObject.getBoundingBox() if bbox.isValid(): self.bbox = bbox else: logger.warn('empty bounding box of part {}', info.PartName) self.bbox = FreeCAD.BoundBox(0, 0, 0, 5, 5, 5) hasBound = False pos = utils.getElementPos(shape) if not pos: if hasBound: pos = self.bbox.Center else: pos = shape.Placement.Base pla = FreeCAD.Placement(pos, rot) self.offset = pla.copy() self.offsetInv = pla.inverse() self.draggerPlacement = info.Placement.multiply(pla)
def savePreset(self): from PySide import QtCore, QtGui import Arch res = QtGui.QInputDialog.getText(None, translate("BIM", "Save preset"), translate("BIM", "Preset name:"), QtGui.QLineEdit.Normal, "DefaultProject") if res[1]: name = res[0] presetdir = os.path.join(FreeCAD.getUserAppDataDir(), "BIM") if not os.path.isdir(presetdir): os.mkdir(presetdir) groups = [] for i in range(self.form.groupsList.count()): groups.append(self.form.groupsList.item(i).text()) s = "# FreeCAD BIM Project setup preset " + name + "\n" s += "groupNewDocument=" + str( int(self.form.groupNewDocument.isChecked())) + "\n" s += "projectName=" + self.form.projectName.text() + "\n" s += "groupSite=" + str(int( self.form.groupSite.isChecked())) + "\n" s += "siteName=" + self.form.siteName.text() + "\n" s += "siteAddress=" + self.form.siteAddress.text() + "\n" s += "siteLongitude=" + str(self.form.siteLongitude.value()) + "\n" s += "siteLatitude=" + str(self.form.siteLatitude.value()) + "\n" s += "siteDeviation=" + str(self.form.siteDeviation.value()) + "\n" s += "siteElevation=" + self.form.siteElevation.text() + "\n" s += "groupBuilding=" + str( int(self.form.groupBuilding.isChecked())) + "\n" s += "buildingName=" + self.form.buildingName.text() + "\n" s += "buildingUse=" + str( self.form.buildingUse.currentIndex()) + "\n" s += "buildingLength=" + self.form.buildingLength.text() + "\n" s += "buildingWidth=" + self.form.buildingWidth.text() + "\n" s += "countVAxes=" + str(self.form.countVAxes.value()) + "\n" s += "distVAxes=" + self.form.distVAxes.text() + "\n" s += "countHAxes=" + str(self.form.countHAxes.value()) + "\n" s += "distHAxes=" + self.form.distHAxes.text() + "\n" s += "countLevels=" + str(self.form.countLevels.value()) + "\n" s += "levelHeight=" + self.form.levelHeight.text() + "\n" s += "lineWidth=" + str(self.form.lineWidth.value()) + "\n" s += "lineColor=" + str( self.form.lineColor.property("color").getRgbF()[:3]) + "\n" s += "groups=" + ";;".join(groups) + "\n" s += "levelsWP=" + str(int(self.form.levelsWP.isChecked())) + "\n" s += "levelsAxis=" + str(int( self.form.levelsAxis.isChecked())) + "\n" s += "addHumanFigure=" + str( int(self.form.addHumanFigure.isChecked())) + "\n" f = open(os.path.join(presetdir, name + ".txt"), "w") f.write(s) f.close() self.fillPresets()
def loadTemplate(self): """loads the contents of a template into the current file""" import FreeCADGui from PySide import QtCore, QtGui filename = QtGui.QFileDialog.getOpenFileName( QtGui.QApplication.activeWindow(), translate("BIM", "Open template file"), None, "FreeCAD file (*.FCStd)") if filename: filename = filename[0] if FreeCAD.ActiveDocument: d = FreeCAD.ActiveDocument td = FreeCAD.openDocument(filename, True) #hidden tname = td.Name values = td.Meta FreeCAD.closeDocument(tname) d.mergeProject(filename) FreeCADGui.ActiveDocument = FreeCADGui.getDocument( d.Name) # fix b/c hidden doc else: d = FreeCAD.openDocument(filename) FreeCAD.ActiveDocument = d values = d.Meta bimunit = 0 if hasattr(FreeCAD, "DraftWorkingPlane"): from FreeCAD import Vector if "wppos" in values: FreeCAD.DraftWorkingPlane.position = eval( values["wpposition"]) if "wpu" in values: FreeCAD.DraftWorkingPlane.u = eval(values["wpu"]) if "wpv" in values: FreeCAD.DraftWorkingPlane.v = eval(values["wpv"]) if "wpaxis" in values: FreeCAD.DraftWorkingPlane.axis = eval(values["wpaxis"]) if "unit" in values: FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Units").SetInt( "UserSchema", int(values["unit"])) if hasattr(FreeCAD.Units, "setSchema"): FreeCAD.Units.setSchema(int(values["unit"])) bimunit = [0, 2, 3, 3, 1, 5, 0, 4][int(values["unit"])] if "textsize" in values: FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Draft").SetFloat( "textheight", float(values["textsize"])) if hasattr(FreeCADGui, "draftToolBar"): FreeCADGui.draftToolBar.fontsizeButton.setValue( float(values["textsize"])) if "textfont" in values: FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Draft").SetString( "textfont", values["textfont"]) if "dimstyle" in values: FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Draft").SetInt( "dimsymbol", int(values["dimstyle"])) if "arrowsize" in values: FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Draft").SetFloat( "arrowsize", float(values["arrowsize"])) if "decimals" in values: FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Units").SetInt( "Decimals", int(values["decimals"])) if "grid" in values: FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Draft").SetFloat( "gridSpacing", float(values["grid"])) if "squares" in values: FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Draft").SetInt( "gridEvery", int(values["squares"])) if hasattr(FreeCADGui, "Snapper"): FreeCADGui.Snapper.setGrid() if "linewidth" in values: FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/View").SetInt( "DefautShapeLineWidth", int(values["linewidth"])) if hasattr(FreeCADGui, "draftToolBar"): FreeCADGui.draftToolBar.widthButton.setValue( int(values["linewidth"])) if "colFace" in values: FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/View").SetUnsigned( "DefaultShapeColor", int(values["colFace"])) if "colLine" in values: FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/View").SetUnsigned( "DefaultShapeLineColor", int(values["colLine"])) if "colHelp" in values: FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Arch").SetUnsigned( "ColorHelpers", int(values["colHelp"])) if "colConst" in values: FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft" ).SetUnsigned("constructioncolor", int(values["colConst"])) # set the status bar widgets mw = FreeCADGui.getMainWindow() if mw: st = mw.statusBar() statuswidget = st.findChild(QtGui.QToolBar, "BIMStatusWidget") if statuswidget: statuswidget.unitLabel.setText( statuswidget.unitsList[bimunit]) # change the unit of the nudge button nudgeactions = statuswidget.nudge.menu().actions() if bimunit in [2, 3, 5, 7]: nudgelabels = statuswidget.nudgeLabelsI else: nudgelabels = statuswidget.nudgeLabelsM for i in range(len(nudgelabels)): nudgeactions[i].setText(nudgelabels[i]) if not "auto" in statuswidget.nudge.text().replace( "&", "").lower(): statuswidget.nudge.setText( FreeCAD.Units.Quantity( statuswidget.nudge.text().replace( "&", "")).UserString) FreeCAD.Console.PrintMessage( translate( "BIM", "Template successfully loaded into current document") + "\n") self.reject()
import FreeCAD as App from draftutils.messages import _msg, _wrn, _err, _log from draftutils.translate import translate # TODO: move the functions that require the graphical interface # This module should not import any graphical commands; those should be # in gui_utils if App.GuiUp: import FreeCADGui as Gui import Draft_rc # The module is used to prevent complaints from code checkers (flake8) True if Draft_rc else False param = App.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") ARROW_TYPES = ["Dot", "Circle", "Arrow", "Tick", "Tick-2"] arrowtypes = ARROW_TYPES ANNOTATION_STYLE = { "FontName": ("font", param.GetString("textfont", "Sans")), "FontSize": ("str", str(param.GetFloat("textheight", 100))), "LineSpacing": ("float", 1), "ScaleMultiplier": ("float", 1), "ShowUnit": ("bool", False), "UnitOverride": ("str", ""), "Decimals": ("int", 2), "ShowLines": ("bool", True), "LineWidth": ("int", param.GetInt("linewidth", 1)), "LineColor": ("color", param.GetInt("color", 255)),
def getPreset(self, preset): import Arch from PySide import QtGui pfile = os.path.join(FreeCAD.getUserAppDataDir(), "BIM", preset + ".txt") if os.path.exists(pfile): f = open(pfile, "r") buf = f.read() f.close() lines = buf.split("\n") for line in lines: if line: if line[0] != "#": s = line.split("=") if s[0] == "groupNewDocument": self.form.groupNewDocument.setChecked( bool(int(s[1]))) elif s[0] == "projectName": self.form.projectName.setText(s[1]) elif s[0] == "groupSite": self.form.groupSite.setChecked(bool(int(s[1]))) elif s[0] == "siteName": self.form.siteName.setText(s[1]) elif s[0] == "siteAddress": self.form.siteAddress.setText(s[1]) elif s[0] == "siteLongitude": self.form.siteLongitude.setValue(float(s[1])) elif s[0] == "siteLatitude": self.form.siteLatitude.setValue(float(s[1])) elif s[0] == "siteDeviation": self.form.siteDeviation.setValue(float(s[1])) elif s[0] == "siteElevation": self.form.siteElevation.setText(s[1]) elif s[0] == "groupBuilding": self.form.groupBuilding.setChecked(bool(int(s[1]))) elif s[0] == "buildingName": self.form.buildingName.setText(s[1]) elif s[0] == "buildingUse": self.form.buildingUse.setCurrentIndex(int(s[1])) elif s[0] == "buildingLength": self.form.buildingLength.setText(s[1]) elif s[0] == "buildingWidth": self.form.buildingWidth.setText(s[1]) elif s[0] == "countVAxes": self.form.countVAxes.setValue(int(s[1])) elif s[0] == "distVAxes": self.form.distVAxes.setText(s[1]) elif s[0] == "countHAxes": self.form.countHAxes.setValue(int(s[1])) elif s[0] == "distHAxes": self.form.distHAxes.setText(s[1]) elif s[0] == "countLevels": self.form.countLevels.setValue(int(s[1])) elif s[0] == "levelHeight": self.form.levelHeight.setText(s[1]) elif s[0] == "lineWidth": self.form.lineWidth.setValue(int(s[1])) elif s[0] == "lineColor": col = tuple([ float(t) for t in s[1].strip("(").strip(")").split(",") ]) col = QtGui.QColor.fromRgbF(*col) self.form.lineColor.setProperty("color", col) elif s[0] == "groups": groups = s[1].split(";;") self.form.groupsList.clear() self.form.groupsList.addItems(groups) elif s[0] == "levelsWP": self.form.levelsWP.setChecked(bool(int(s[1]))) elif s[0] == "levelsAxis": self.form.levelsAxis.setChecked(bool(int(s[1]))) elif s[0] == "addHumanFigure": self.form.addHumanFigure.setChecked(bool(int( s[1])))
def get_dimension(self): # Dimension # 3D cfMesh and snappyHexMesh, and 2D by conversion, while in future cfMesh may support 2D directly if self.dimension != '3D' and self.dimension != '2D': FreeCAD.Console.PrintError('Invalid element dimension. Setting to 3D.') self.dimension = '3D' print(' ElementDimension: ' + self.dimension) # Check for 2D boundaries twoDPlanes = [] analysis_obj = CfdTools.getParentAnalysisObject(self.mesh_obj) if not analysis_obj: analysis_obj = FemGui.getActiveAnalysis() if analysis_obj: boundaries = CfdTools.getCfdBoundaryGroup(analysis_obj) for b in boundaries: if b.BoundarySettings['BoundaryType'] == 'constraint' and \ b.BoundarySettings['BoundarySubtype'] == 'twoDBoundingPlane': twoDPlanes.append(b.Name) if self.dimension == '2D': self.two_d_settings['ConvertTo2D'] = True if len(twoDPlanes) != 2: raise RuntimeError("For 2D meshing, two separate, parallel, 2D bounding planes must be present as " "boundary conditions in the CFD analysis object.") doc_name = str(analysis_obj.Document.Name) fFObjName = twoDPlanes[0] bFObjName = twoDPlanes[1] frontObj = FreeCAD.getDocument(doc_name).getObject(fFObjName) backObj = FreeCAD.getDocument(doc_name).getObject(bFObjName) fShape = frontObj.Shape bShape = backObj.Shape if len(fShape.Faces) == 0 or len(bShape.Faces) == 0: raise RuntimeError("A 2D bounding plane is empty.") else: allFFacesPlanar = True allBFacesPlanar = True for faces in fShape.Faces: if not isinstance(faces.Surface, Part.Plane): allFFacesPlanar = False break for faces in bShape.Faces: if not isinstance(faces.Surface, Part.Plane): allBFacesPlanar = False break if allFFacesPlanar and allBFacesPlanar: A1 = fShape.Faces[0].Surface.Axis A1.multiply(1.0/A1.Length) A2 = bShape.Faces[0].Surface.Axis A2.multiply(1.0/A2.Length) if (A1-A2).Length <= 1e-6 or (A1+A2).Length <= 1e-6: if len(frontObj.Shape.Vertexes) == len(backObj.Shape.Vertexes) and \ len(frontObj.Shape.Vertexes) > 0 and \ abs(frontObj.Shape.Area) > 0 and \ abs(frontObj.Shape.Area - backObj.Shape.Area)/abs(frontObj.Shape.Area) < 1e-6: self.two_d_settings['Distance'] = fShape.distToShape(bShape)[0]/1000 else: raise RuntimeError("2D bounding planes do not match up.") else: raise RuntimeError("2D bounding planes are not aligned.") else: raise RuntimeError("2D bounding planes need to be flat surfaces.") case = CfdCaseWriterFoam.CfdCaseWriterFoam(analysis_obj) case.settings = {} case.settings['createPatchesFromSnappyBaffles'] = False case.setupPatchNames() keys = list(case.settings['createPatches'].keys()) frontPatchIndex = keys.index(frontObj.Label) self.two_d_settings['FrontFaceList'] = case.settings['createPatches'][keys[frontPatchIndex]]['PatchNamesList'] backPatchIndex = keys.index(backObj.Label) self.two_d_settings['BackFaceList'] = case.settings['createPatches'][keys[backPatchIndex]]['PatchNamesList'] self.two_d_settings['BackFace'] = self.two_d_settings['BackFaceList'][0] else: self.two_d_settings['ConvertTo2D'] = False if len(twoDPlanes): raise RuntimeError("2D bounding planes can not be used in 3D mesh")
def get_param(param, default=None): """Return a parameter value from the current parameter database. The parameter database is located in the tree :: 'User parameter:BaseApp/Preferences/Mod/Draft' In the case that `param` is `'linewidth'` or `'color'` it will get the values from the View parameters :: 'User parameter:BaseApp/Preferences/View/DefaultShapeLineWidth' 'User parameter:BaseApp/Preferences/View/DefaultShapeLineColor' Parameters ---------- param : str A string that indicates a parameter in the parameter database. default : optional It indicates the default value of the given parameter. It defaults to `None`, in which case it will use a specific value depending on the type of parameter determined with `get_param_type`. Returns ------- int, or str, or float, or bool Depending on `param` and its type, by returning `ParameterGrp.GetInt`, `ParameterGrp.GetString`, `ParameterGrp.GetFloat`, `ParameterGrp.GetBool`, or `ParameterGrp.GetUnsinged`. """ draft_params = "User parameter:BaseApp/Preferences/Mod/Draft" view_params = "User parameter:BaseApp/Preferences/View" p = App.ParamGet(draft_params) v = App.ParamGet(view_params) t = getParamType(param) # print("getting param ",param, " of type ",t, " default: ",str(default)) if t == "int": if default is None: default = 0 if param == "linewidth": return v.GetInt("DefaultShapeLineWidth", default) return p.GetInt(param, default) elif t == "string": if default is None: default = "" return p.GetString(param, default) elif t == "float": if default is None: default = 0 return p.GetFloat(param, default) elif t == "bool": if default is None: default = False return p.GetBool(param, default) elif t == "unsigned": if default is None: default = 0 if param == "color": return v.GetUnsigned("DefaultShapeLineColor", default) return p.GetUnsigned(param, default) else: return None
def findbestmatchingrotation(r1): import FreeCAD vangl = \ (1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 11.25, 12.0, 13.0, 14.0, 15.0, 16.0, (180.0/11.0), 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 22.5, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, (360.0/11.0), 33.0, 33.75, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0,(540.0/11.0), 50.0, 51.0, (360.0/7.0), 52.0, 53.0, 54.0, 55.0, 56.0, 56.25, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0,(720.0/11.0), 66.0, 67.0, 67.5, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 78.75, 79.0, 80.0, 81.0,(900.0/11.0), 82.0, 83.0, 84.0, 85.0, 86.0, 87.0, 88.0, 89.0, 90.0, 91.0, 92.0, 93.0, 94.0, 95.0, 96.0, 97.0, 98.0,(1080.0/11.0), 99.0, 100.0, 101.0, 101.25, 102.0, (720.0/7.0), 103.0, 104.0, 105.0, 106.0, 107.0, 108.0, 109.0, 110.0, 111.0, 112.0, 112.5, 113.0, 114.0, (1260.0/11), 115.0, 116.0, 117.0, 118.0, 119.0, 120.0, 121.0, 122.0, 123.0, 123.75, 124.0, 125.0, 126.0, 127.0, 128.0, 129.0, 130.0,(1440.0/11.0), 131.0, 132.0, 133.0, 134.0, 135.0, 136.0, 137.0, 138.0, 139.0, 140.0, 141.0, 142.0, 143.0, 144.0, 145.0, 146.0, 146.25, 147.0, (1620.0/11.0), 148.0, 149.0, 150.0, 151.0, 152.0, 153.0, 154.0, (1080.0/7.0), 155.0, 156.0, 157.0, 157.5, 158.0, 159.0, 160.0, 161.0, 162.0, 163.0, (1800.0/11.0), 164.0, 165.0, 166.0, 167.0, 168.0, 168.75, 169.0, 170.0, 171.0, 172.0, 173.0, 174.0, 175.0, 176.0, 177.0,178.0, 179.0,180.0, -179.0, -178.0, -177.0, -176.0, -175.0, -174.0, -173.0, -172.0, -171.0, -170.0, -169.0, -168.75, -168.0, -167.0, -166.0, -165.0, -164.0, (-1800.0/11.0), -163.0, -162.0, -161.0, -160.0, -159.0, -158.0, -157.5, -157.0, -156.0, -155.0, (-1080.0/7.0), -154.0, -153.0, -152.0, -151.0, -150.0, -149.0, -148.0, (-1620.0/11.0), -147.0, -146.25, -146.0, -145.0, -144.0, -143.0, -142.0, -141.0, -140.0, -139.0,-138.0, -137.0, -136.0, -135.0, -134.0, -133.0, -132.0, -131.0, (-1440/11.0), -130.0, -129.0, -128.0,-127.0, -126.0, -125.0, -124.0, -123.75, -123.0, -122.0, -121.0, -120.0, -119.0, -118.0, -117.0, -116.0, -115.0,(-1260.0/11.0), -114.0, -113.0, -112.5, -112.0, -111.0, -110.0, -109.0, -108.0, -107.0, -106.0, -105.0,-104.0, -103.0,(-720.0/7.0), -102.0, -101.25, -101.0, -100.0, -99.0, (-1080.0/11.0), -98.0, -97.0, -96.0, -95.0, -94.0, -93.0, -92.0, -91.0, -90.0, -89.0, -88.0, -87.0, -86.0, -85.0, -84.0, -83.0, -82.0,(-900.0/11.0), -81.0, -80.0, -79.0, -78.75, -78.0, -77.0, -76.0, -75.0, -74.0, -73.0, -72.0, -71.0, -70.0, -69.0, -68.0, -67.5, -67.0, -66.0, (-720.0/11.0), -65.0, -64.0, -63.0, -62.0, -61.0, -60.0, -59.0, -58.0, -57.0, -56.25, -56.0, -55.0, -54.0, -53.0, -52.0,(-360.0/7.0), -51.0, -50.0, (-540.0/11.0), -49.0, -48.0, -47.0, -46.0, -45.0, -44.0, -43.0, -42.0, -41.0, -40.0, -39.0, -38.0, -37.0, -36.0, -35.0, -34.0, -33.75, -33.0,(-360.0/11.0), -32.0, -31.0, -30.0, -29.0, -28.0, -27.0, -26.0, -25.0, -24.0, -23.0, -22.5, -22.0, -21.0, -20.0, -19.0, -18.0, -17.0,(-180.0/11.0), -16.0, -15.0, -14.0, -13.0, -12.0, -11.25, -11.0, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.0, -3.0, -2.0, -1.0) def tup2nvect(tup): """convert a tuple to a normalized vector""" v = FreeCAD.Vector(*tup) v.normalize() return v def wkaxes(): """well known axes for rotations""" vtupl = ((1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (1, 0, 1), (0, 1, 1), (-1, 1, 0), (-1, 0, 1), (0, 1, -1), (1, 1, 1), (1, 1, -1), (1, -1, 1), (-1, 1, 1)) return tuple(tup2nvect(tup) for tup in vtupl) bestrot = FreeCAD.Rotation() dangle = comparerotations(r1, bestrot) for axis in wkaxes(): for angle in vangl: for axissign in (1.0, -1.0): r2 = FreeCAD.Rotation(axis * axissign, angle) dangletest = comparerotations(r1, r2) if dangletest < dangle: bestrot = r2 dangle = dangletest return (bestrot, dangle)
def createGeometry(self, obj): import Part, DraftGeomUtils # getting default values height = width = length = 1 if hasattr(obj, "Length"): if obj.Length: length = obj.Length if hasattr(obj, "Width"): if obj.Width: width = obj.Width if hasattr(obj, "Height"): if obj.Height: height = obj.Height # creating base shape pl = obj.Placement base = None if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if hasattr(obj, "Tool"): if obj.Tool: try: base = obj.Tool.Shape.copy().makePipe( obj.Base.Shape.copy()) except: FreeCAD.Console.PrintError( str( translate( "Arch", "Error: The base shape couldn't be extruded along this tool object" ))) return if not base: if obj.Normal == Vector(0, 0, 0): p = FreeCAD.Placement(obj.Base.Placement) normal = p.Rotation.multVec(Vector(0, 0, 1)) else: normal = Vector(obj.Normal) normal = normal.multiply(height) base = obj.Base.Shape.copy() if base.Solids: pass elif base.Faces: base = base.extrude(normal) elif (len(base.Wires) == 1): if base.Wires[0].isClosed(): base = Part.Face(base.Wires[0]) base = base.extrude(normal) elif obj.Base.isDerivedFrom("Mesh::Feature"): if obj.Base.Mesh.isSolid(): if obj.Base.Mesh.countComponents() == 1: sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh) if sh.isClosed() and sh.isValid() and sh.Solids: base = sh else: if obj.Normal == Vector(0, 0, 0): normal = Vector(0, 0, 1) else: normal = Vector(obj.Normal) normal = normal.multiply(height) l2 = length / 2 or 0.5 w2 = width / 2 or 0.5 v1 = Vector(-l2, -w2, 0) v2 = Vector(l2, -w2, 0) v3 = Vector(l2, w2, 0) v4 = Vector(-l2, w2, 0) base = Part.makePolygon([v1, v2, v3, v4, v1]) base = Part.Face(base) base = base.extrude(normal) base = self.processSubShapes(obj, base) if base: # applying axes pts = self.getAxisPoints(obj) apl = self.getAxisPlacement(obj) if pts: fsh = [] for i in range(len(pts)): if hasattr(obj, "Exclude"): if i in obj.Exclude: continue sh = base.copy() if apl: sh.Placement.Rotation = apl.Rotation sh.translate(pts[i]) fsh.append(sh) obj.Shape = Part.makeCompound(fsh) # finalizing else: if base: if not base.isNull(): if base.isValid() and base.Solids: if base.Volume < 0: base.reverse() if base.Volume < 0: FreeCAD.Console.PrintError( str( translate("Arch", "Couldn't compute a shape"))) return base = base.removeSplitter() obj.Shape = base if not DraftGeomUtils.isNull(pl): obj.Placement = pl
def action(self,arg): "scene event handler" if arg["Type"] == "SoKeyboardEvent" and arg["State"] == "DOWN": if arg["Key"] == "ESCAPE": self.finish() elif arg["Key"] == "a": self.finish() elif arg["Key"] == "o": self.finish(closed=True) elif arg["Key"] == "i": if Draft.getType(self.obj) == "Circle": self.arcInvert() elif arg["Type"] == "SoLocation2Event": #mouse movement detection self.point,ctrlPoint,info = DraftTools.getPoint(self,arg)# causes problems when mouseover bezcurves if self.editing != None: self.trackers[self.editing].set(self.point) #FreeCAD.Console.PrintMessage(self.ghost) self.updateGhost(obj=self.obj,idx=self.editing,pt=self.point) if hasattr(self.obj.ViewObject,"Selectable"): if self.ui.addButton.isChecked(): self.obj.ViewObject.Selectable = True else: self.obj.ViewObject.Selectable = False DraftTools.redraw3DView() elif arg["Type"] == "SoMouseButtonEvent" and arg["State"] == "DOWN": if arg["Button"] == "BUTTON1": self.ui.redraw() if self.editing == None: # USECASE: User click on one of the editpoints or another object ep = None selobjs = self.getSelection() if selobjs == None: return if self.ui.addButton.isChecked():# still quite raw # USECASE: User add a new point to the object for info in selobjs: if Draft.getType(self.obj) == "Wire" and 'Edge' in info["Component"]: pt = FreeCAD.Vector(info["x"],info["y"],info["z"]) self.addPointToWire(pt, int(info["Component"][4:])) elif self.point: pt = self.point if "x" in info:# prefer "real" 3D location over working-plane-driven one if possible pt = FreeCAD.Vector(info["x"],info["y"],info["z"]) self.addPointToCurve(pt,info) self.removeTrackers() self.editpoints = [] self.setEditPoints(self.obj) self.resetTrackers() return ep = self.lookForClickedNode(selobjs,tolerance=20) if ep == None: return if self.ui.delButton.isChecked(): # still quite raw # USECASE: User delete a point of the object self.delPoint(ep) # don't do tan/sym on DWire/BSpline! self.removeTrackers() self.editpoints = [] self.setEditPoints(self.obj) self.resetTrackers() return if Draft.getType(self.obj) == "BezCurve": # USECASE: User change the continuity of a Bezcurve point if self.ui.sharpButton.isChecked(): return self.smoothBezPoint(ep, 'Sharp') elif self.ui.tangentButton.isChecked(): return self.smoothBezPoint(ep, 'Tangent') elif self.ui.symmetricButton.isChecked(): return self.smoothBezPoint(ep, 'Symmetric') self.ui.pointUi() self.ui.isRelative.show() self.editing = ep self.trackers[self.editing].off() self.finalizeGhost() self.ghost = self.initGhost(self.obj) '''if hasattr(self.obj.ViewObject,"Selectable"): self.obj.ViewObject.Selectable = False''' self.node.append(self.trackers[self.editing].get()) FreeCADGui.Snapper.setSelectMode(False) else: #if self.editing != None: # USECASE: Destination point of editing is clicked self.finalizeGhost() self.trackers[self.editing].on() #if hasattr(self.obj.ViewObject,"Selectable"): # self.obj.ViewObject.Selectable = True FreeCADGui.Snapper.setSelectMode(True) self.numericInput(self.trackers[self.editing].get())
def write_mesh_case(self): """ Collect case settings, and finally build a runnable case. """ FreeCAD.Console.PrintMessage("Populating mesh dictionaries in folder {}\n".format(self.meshCaseDir)) if self.mesh_obj.MeshUtility == "cfMesh": self.cf_settings['ClMax'] = self.clmax*self.scale if len(self.cf_settings['BoundaryLayers']) > 0: self.cf_settings['BoundaryLayerPresent'] = True else: self.cf_settings['BoundaryLayerPresent'] = False if len(self.cf_settings["InternalRegions"]) > 0: self.cf_settings['InternalRefinementRegionsPresent'] = True else: self.cf_settings['InternalRefinementRegionsPresent'] = False elif self.mesh_obj.MeshUtility == "snappyHexMesh": bound_box = self.part_obj.Shape.BoundBox bC = 5 # Number of background mesh buffer cells x_min = (bound_box.XMin - bC*self.clmax)*self.scale x_max = (bound_box.XMax + bC*self.clmax)*self.scale y_min = (bound_box.YMin - bC*self.clmax)*self.scale y_max = (bound_box.YMax + bC*self.clmax)*self.scale z_min = (bound_box.ZMin - bC*self.clmax)*self.scale z_max = (bound_box.ZMax + bC*self.clmax)*self.scale cells_x = int(math.ceil(bound_box.XLength/self.clmax) + 2*bC) cells_y = int(math.ceil(bound_box.YLength/self.clmax) + 2*bC) cells_z = int(math.ceil(bound_box.ZLength/self.clmax) + 2*bC) snappy_settings = self.snappy_settings snappy_settings['BlockMesh'] = { "xMin": x_min, "xMax": x_max, "yMin": y_min, "yMax": y_max, "zMin": z_min, "zMax": z_max, "cellsX": cells_x, "cellsY": cells_y, "cellsZ": cells_z } inside_x = self.mesh_obj.PointInMesh.get('x')*self.scale inside_y = self.mesh_obj.PointInMesh.get('y')*self.scale inside_z = self.mesh_obj.PointInMesh.get('z')*self.scale shape_face_names_list = [] for i in self.mesh_obj.ShapeFaceNames: shape_face_names_list.append(i) snappy_settings['ShapeFaceNames'] = tuple(shape_face_names_list) snappy_settings['EdgeRefinementLevel'] = self.mesh_obj.EdgeRefinement snappy_settings['PointInMesh'] = { "x": inside_x, "y": inside_y, "z": inside_z } snappy_settings['CellsBetweenLevels'] = self.mesh_obj.CellsBetweenLevels if self.mesh_obj.NumberCores <= 1: self.mesh_obj.NumberCores = 1 snappy_settings['ParallelMesh'] = False else: snappy_settings['ParallelMesh'] = True snappy_settings['NumberCores'] = self.mesh_obj.NumberCores if len(self.snappy_settings["InternalRegions"]) > 0: self.snappy_settings['InternalRefinementRegionsPresent'] = True else: self.snappy_settings['InternalRefinementRegionsPresent'] = False elif self.mesh_obj.MeshUtility == "gmsh": if platform.system() == "Windows": exe = os.path.join(FreeCAD.getHomePath(), 'bin', 'gmsh.exe') else: exe = subprocess.check_output(["which", "gmsh"], universal_newlines=True).rstrip('\n') self.gmsh_settings['Executable'] = CfdTools.translatePath(exe) self.gmsh_settings['ShapeFile'] = self.temp_file_shape self.gmsh_settings['HasLengthMap'] = False if self.ele_length_map: self.gmsh_settings['HasLengthMap'] = True self.gmsh_settings['LengthMap'] = self.ele_length_map self.gmsh_settings['NodeMap'] = {} for e in self.ele_length_map: ele_nodes = (''.join((str(n+1) + ', ') for n in self.ele_node_map[e])).rstrip(', ') self.gmsh_settings['NodeMap'][e] = ele_nodes self.gmsh_settings['ClMax'] = self.clmax self.gmsh_settings['ClMin'] = self.clmin sols = (''.join((str(n+1) + ', ') for n in range(len(self.mesh_obj.Part.Shape.Solids)))).rstrip(', ') self.gmsh_settings['Solids'] = sols self.gmsh_settings['BoundaryFaceMap'] = {} # Write one boundary per face for i in range(len(self.mesh_obj.Part.Shape.Faces)): self.gmsh_settings['BoundaryFaceMap']['face'+str(i)] = i+1 self.gmsh_settings['MeshFile'] = self.temp_file_mesh # Perform initialisation here rather than __init__ in case of path changes self.template_path = os.path.join(CfdTools.get_module_path(), "data", "defaultsMesh") mesh_region_present = False if self.mesh_obj.MeshUtility == "cfMesh" and len(self.cf_settings['MeshRegions']) > 0 or \ self.mesh_obj.MeshUtility == "snappyHexMesh" and len(self.snappy_settings['MeshRegions']) > 0: mesh_region_present = True self.settings = { 'Name': self.part_obj.Name, 'MeshPath': self.meshCaseDir, 'FoamRuntime': CfdTools.getFoamRuntime(), 'TranslatedFoamPath': CfdTools.translatePath(CfdTools.getFoamDir()), 'MeshUtility': self.mesh_obj.MeshUtility, 'MeshRegionPresent': mesh_region_present, 'CfSettings': self.cf_settings, 'SnappySettings': self.snappy_settings, 'GmshSettings': self.gmsh_settings, 'TwoDSettings': self.two_d_settings } TemplateBuilder.TemplateBuilder(self.meshCaseDir, self.template_path, self.settings) # Update Allmesh permission - will fail silently on Windows fname = os.path.join(self.meshCaseDir, "Allmesh") import stat s = os.stat(fname) os.chmod(fname, s.st_mode | stat.S_IEXEC) FreeCAD.Console.PrintMessage("Successfully wrote meshCase to folder {}\n".format(self.meshCaseDir))