def importVtk( filename, object_name=None, object_type=None ): if not object_type: vtkinout_prefs = FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Fem/InOutVtk" ) object_type = vtkinout_prefs.GetInt("ImportObject", 0) if not object_name: object_name = os.path.splitext(os.path.basename(filename))[0] if object_type == 0: # vtk result object importVtkVtkResult(filename, object_name) elif object_type == 1: # FEM mesh object importVtkFemMesh(filename, object_name) elif object_type == 2: # FreeCAD result object importVtkFCResult(filename, object_name) else: Console.PrintError( "Error, wrong parameter in VTK import pref: {}\n" .format(object_type) )
def render(self, context): Console.PrintMessage("render\n") self.width = context.width self.depth = context.depth self.height = context.height self.hole_style = context.hole_style self.holes_offset = context.holes_offset self.doc = context.doc self.brick = context.brick self.top_datum_plane = context.top_datum_plane self.top_inside_datum_plane = context.top_inside_datum_plane self.front_inside_datum_plane = context.front_inside_datum_plane self.back_inside_datum_plane = context.back_inside_datum_plane self.left_inside_datum_plane = context.left_inside_datum_plane self.right_inside_datum_plane = context.right_inside_datum_plane self.xy_plane = context.xy_plane body_pad_sketch = self._render_body_pad_and_fillets() # TODO: support side rib variation for modern 2x1 tile and technic bricks with non-offset holes # TODO: 0.25 fillet on inner corners self._render_body_pocket(body_pad_sketch) # TODO: determine a replacement for internal ribs if side studs exist with holes self._render_tubes_or_sticks(body_pad_sketch)
def render(self, context): Console.PrintMessage("render\n") self.doc = context.doc self.brick = context.brick self.width = context.width self.depth = context.depth self.style = context.top_studs_style self.width_count = context.top_studs_width_count self.depth_count = context.top_studs_depth_count self.top_datum_plane = context.top_datum_plane self.top_inside_datum_plane = context.top_inside_datum_plane initial_width_offset = (self.width - self.width_count) * DIMS_STUD_SPACING / 2 initial_depth_offset = (self.depth - self.depth_count) * DIMS_STUD_SPACING / 2 self._render_top_studs_outside(initial_width_offset, initial_depth_offset) # Only render inner pocket if closed studs AND studs are not offset if self.style == TopStudStyle.CLOSED and initial_width_offset == 0 and initial_depth_offset == 0: self._render_top_studs_inside(initial_width_offset, initial_depth_offset)
def accept(self): # Verify the active document actDoc = FreeCAD.ActiveDocument if not actDoc: self.errorBox("No Open Document\n") return False Console.PrintMessage("Accepted" + '\n') docName = actDoc.Label docDir = FreeCAD.ActiveDocument.FileName.replace( docName + ".fcstd", "") partList = FreeCADGui.Selection.getSelection() # Verify at least one part is selected if not partList: self.errorBox("Select at Least One Part Object") return False stlParts = docDir + docName + ".stl" Mesh.export(partList, stlParts) self.pos = self.GetXYZPos(partList) #Console.PrintMessage(str(self.pos) + '\n') retVal = self.sliceParts(self.Vars.readMisc("CuraPath"), stlParts) if retVal is True: self.errorBox("Slice Failed!\n Check log file\n" + logFile) return False else: return True
def Enable(): global observer observer = selObserver3DView(); # add the listener, 0 forces to resolve the links Gui.Selection.addObserver(observer, 0) #print("3D view link selection mode is now enabled") FCC.PrintMessage("3D view link selection mode is now ENABLED\n")
def convertToDwg(dxffilename, dwgfilename): """Convert a DXF file to a DWG file. If the converter is found it is used, otherwise the conversion fails. Parameters ---------- dxffilename : str The input DXF file dwgfilename : str The output DWG file Returns ------- str The same `dwgfilename` file path. """ import os, subprocess teigha = getTeighaConverter() if teigha: indir = os.path.dirname(dxffilename) outdir = os.path.dirname(dwgfilename) basename = os.path.basename(dxffilename) cmdline = ('"%s" "%s" "%s" "ACAD2000" "DWG" "0" "1" "%s"' % (teigha, indir, outdir, basename)) FCC.PrintMessage(translate("ImportDWG", "Converting: ") + cmdline + "\n") subprocess.call(cmdline, shell=True) # os.system(cmdline) return dwgfilename return None
def createConfig(name, description): group = getConfGroup() if not group: # create a group Configurations to store various config tables assy = Asm4.getAssembly() if assy: group = assy.newObject('App::DocumentObjectGroup', 'Configurations') else: FCC.PrintWarnin('No assembly container here, quitting\n') return # Create the document conf = group.newObject('Spreadsheet::Sheet', name) headerRow = str(int(OBJECTS_START_ROW) - 1) #conf.set(HEADER_CELL, 'Assembly4 configuration table') conf.set(HEADER_CELL, ASM4_CONFIG_TYPE) conf.set(DESCRIPTION_CELL, str(description)) conf.set(OBJECT_NAME_COL + headerRow, 'ObjectName') conf.set(OBJECT_VISIBLE_COL + headerRow, 'Visible') conf.set(OBJECT_ASM_TYPE_COL + headerRow, 'Assembly Type') conf.set(OFFSET_POS_X_COL + headerRow, 'Pos. X') conf.set(OFFSET_POS_Y_COL + headerRow, 'Pos. Y') conf.set(OFFSET_POS_Z_COL + headerRow, 'Pos. Z') conf.set(OFFSET_ROT_YAW_COL + headerRow, 'Rot. Yaw') conf.set(OFFSET_ROT_PITCH_COL + headerRow, 'Rot. Pitch') conf.set(OFFSET_ROT_ROLL_COL + headerRow, 'Rot. Roll') return conf
def Activated(self): #Handle single selected App::Link selectedLink = None parentAssembly = None selection = Asm4.getSelectedLink() if not selection: # This shouldn't happen FCC.PrintWarning( "This is not an error message you are supposed to see, something went wrong\n" ) return else: parent = selection.getParentGeoFeatureGroup() # only handle if the parent is at the root of the document: if parent and parent.TypeId == 'App::Part' and parent.getParentGeoFeatureGroup( ) is None: # only accept Asm4 Models as assemblies # this is self-imposed, works also without an Asm4 Model if parent.Name == 'Model': # launch the UI in the task panel Gui.Control.showDialog(placeLinkUI()) else: Asm4.warningBox( 'Please select a link in the assembly Model') else: Asm4.warningBox('Please select a link in the assembly Model.') return
def run_gmsh_with_geo(self): comandlist = [self.gmsh_bin, "-", self.temp_file_geo] # print(comandlist) try: p = subprocess.Popen(comandlist, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, error = p.communicate() if sys.version_info.major >= 3: # output = output.decode("utf-8") error = error.decode("utf-8") # stdout is still cut at some point # but the warnings are in stderr and thus printed :-) # print(output) # print(error) except Exception: error = "Error executing: {}\n".format(" ".join(comandlist)) Console.PrintError(error) self.error = True # workaround # filter useless gmsh warning in the regard of unknown element MSH type 15 # https://forum.freecadweb.org/viewtopic.php?f=18&t=33946 useless_warning = ("Warning : Unknown element type for UNV export " "(MSH type 15) - output file might be invalid") new_err = error.replace(useless_warning, "") # remove empty lines, https://stackoverflow.com/a/1140967 new_err = "".join( [s for s in new_err.splitlines(True) if s.strip("\r\n")]) return new_err
def accept(self): if self.Apply(): # highlight in the 3D window the object we placed self.finish() else: FCC.PrintWarning("Problem in selections\n") return
def accept(self): if self.onApply(): if self.selectedDatum: self.selectedDatum.ViewObject.ShowLabel = False self.finish() else: FCC.PrintWarning("Problem in selections\n")
def get_FemMeshObjectOrder( fem_mesh_obj ): """ Gets element order. Element order counting based on number of nodes on edges. Edge with 2 nodes -> linear elements, Edge with 3 nodes -> quadratic elements, and so on. No edges in mesh -> not determined. (Is this possible? Seems to be a very degenerate case.) If there are edges with different number of nodes appearing, return list of orders. """ presumable_order = None edges = fem_mesh_obj.FemMesh.Edges if edges != (): edges_length_set = list({len(fem_mesh_obj.FemMesh.getElementNodes(e)) for e in edges}) # only need set to eliminate double entries if len(edges_length_set) == 1: presumable_order = edges_length_set[0] - 1 else: presumable_order = [el - 1 for el in edges_length_set] else: Console.PrintMessage( "Found no edges in mesh: Element order determination does not work without them.\n" ) return presumable_order
def decodeName(name): """Decode encoded name. Parameters ---------- name : str The string to decode. Returns ------- tuple (string) A tuple containing the decoded `name` in 'utf8', otherwise in 'latin1'. If it fails it returns the original `name`. """ try: decodedName = (name.decode("utf8")) except UnicodeDecodeError: try: decodedName = (name.decode("latin1")) except UnicodeDecodeError: FCC.PrintError( translate( "importOCA", "OCA error: " "couldn't determine character encoding") + "\n") decodedName = name return decodedName
def RestoreObject(doc, obj): # parse App::Part containers, and only those if obj.TypeId == 'App::Part': SaveSubObjects(conf, obj) parentObj, objFullName = obj.Parents[0] #objName = App.ActiveDocument.Name + '.' + parentObj.Name + '.' + objFullName objName = parentObj.Name + '.' + objFullName row = GetObjectRow(doc, objName) if row is None: FCC.PrintMessage('No data for object "' + objName + '" in configuration "' + doc.Name + '"\n') return vis = doc.get( OBJECT_VISIBLE_COL + row ) obj.ViewObject.Visibility = vis asm = str(doc.get( OBJECT_ASM_TYPE_COL + row )) if asm == 'Asm4EE': x = doc.get( OFFSET_POS_X_COL + row ) y = doc.get( OFFSET_POS_Y_COL + row ) z = doc.get( OFFSET_POS_Z_COL + row ) yaw = doc.get( OFFSET_ROT_YAW_COL + row ) pitch = doc.get( OFFSET_ROT_PITCH_COL + row ) roll = doc.get( OFFSET_ROT_ROLL_COL + row ) position = App.Vector(x, y, z) rotation = App.Rotation(yaw, pitch, roll) offset = App.Placement(position, rotation) obj.AttachmentOffset = offset
def onApply(self): # get the name of the part to attach to: # it's either the top level part name ('Model') # or the provided link's name. if self.parentList.currentText() == 'Parent Assembly': a_Link = 'Parent Assembly' a_Part = None elif self.parentList.currentIndex() > 1: parent = self.parentTable[ self.parentList.currentIndex() ] a_Link = parent.Name a_Part = parent.LinkedObject.Document.Name else: a_Link = None a_Part = None # the attachment LCS's name in the parent # check that something is selected in the QlistWidget if self.attLCSlist.selectedItems(): a_LCS = self.attLCStable[ self.attLCSlist.currentRow() ].Name else: a_LCS = None # check that all of them have something in if a_Link and a_LCS : # <<LinkName>>.Placement.multiply( <<LinkName>>.<<LCS.>>.Placement ) # expr = '<<'+ a_Part +'>>.Placement.multiply( <<'+ a_Part +'>>.<<'+ a_LCS +'.>>.Placement )' Asm4.placeObjectToLCS(self.selectedFastener, a_Link, a_Part, a_LCS) # highlight the selected fastener in its new position Gui.Selection.clearSelection() Gui.Selection.addSelection( self.activeDoc.Name, 'Model', self.selectedFastener.Name +'.') else: FCC.PrintWarning("Problem in selections\n") return
def export(objectslist, filename): "called when freecad exports a file" if len(objectslist) != 1: Console.PrintError("This exporter can only export one object.\n") return obj = objectslist[0] if not obj.isDerivedFrom("Fem::FemMeshObject"): Console.PrintError("No FEM mesh object selected.\n") return femnodes_mesh = obj.FemMesh.Nodes femelement_table = meshtools.get_femelement_table(obj.FemMesh) z88_element_type = get_z88_element_type(obj.FemMesh, femelement_table) f = pyopen(filename, "w") write_z88_mesh_to_file(femnodes_mesh, femelement_table, z88_element_type, f) f.close()
def _render_side_studs_inside(self, label, plane, count, inverted): Console.PrintMessage("render_side_studs_inside({},{})\n".format(label, count)) # side studs pocket side_studs_inside_pocket_sketch = self.brick.newObject("Sketcher::SketchObject", label + "_side_studs_inside_pocket_sketch") side_studs_inside_pocket_sketch.Support = (plane, '') side_studs_inside_pocket_sketch.MapMode = 'FlatFace' add_inner_circle_with_flats_to_sketch(side_studs_inside_pocket_sketch, DIMS_STUD_OUTER_RADIUS, DIMS_STUD_INNER_RADIUS, DIMS_STUD_FLAT_THICKNESS, 0, DIMS_SIDE_STUD_CENTRE_HEIGHT) self.doc.recompute() # create array if needed if count > 1: geometry_indices = [range(0, len(side_studs_inside_pocket_sketch.Geometry) - 1)] side_studs_inside_pocket_sketch.addRectangularArray(geometry_indices, Vector(DIMS_STUD_SPACING, 0, 0), False, count, 1, True) self.doc.recompute() side_studs_inside_pocket = self.brick.newObject("PartDesign::Pocket", label + "_side_studs_inside_pocket") side_studs_inside_pocket.Type = POCKET_TYPE_DIMENSION side_studs_inside_pocket.Profile = side_studs_inside_pocket_sketch side_studs_inside_pocket.Reversed = inverted side_studs_inside_pocket.Length = DIMS_RIBBED_SIDE_THICKNESS + DIMS_STUD_INSIDE_HOLE_TOP_OFFSET self.doc.recompute() side_studs_inside_pocket_sketch.ViewObject.Visibility = False
def readResult(dat_input): Console.PrintMessage( "Read ccx results from dat file: {}\n".format(dat_input)) dat_file = pyopen(dat_input, "r") eigenvalue_output_section_found = False mode_reading = False results = [] for line in dat_file: if EIGENVALUE_OUTPUT_SECTION in line: # Found EIGENVALUE_OUTPUT_SECTION eigenvalue_output_section_found = True if eigenvalue_output_section_found: try: mode = int(line[0:7]) mode_frequency = float(line[39:55]) m = {} m["eigenmode"] = mode m["frequency"] = mode_frequency results.append(m) mode_reading = True except Exception: if mode_reading: # Conversion error after mode reading started, so it's the end of section eigenvalue_output_section_found = False mode_reading = False dat_file.close() return results
def get_gmsh_command(self): from platform import system 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: output = p1.stdout.read() if sys.version_info.major >= 3: output = output.decode("utf-8") gmsh_path = output.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") Console.PrintError(error_message) raise GmshError(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") Console.PrintError(error_message) raise GmshError(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" Console.PrintMessage(" " + self.gmsh_bin + "\n")
def _parse_side_studs(self, side_studs): style = side_studs["style"] if style not in (SideStudStyle.NONE, SideStudStyle.OPEN, SideStudStyle.HOLE): raise Exception( "side_studs[\"style\"] must be: " "SideStudStyle.NONE|SideStudStyle.OPEN|SideStudStyle.HOLE") if style != SideStudStyle.NONE and self.height < 3: Console.PrintMessage( "side_studs[\"style\"] set to SideStudStyle.NONE as " "dimensions[\"width\"] < 3\n") style = SideStudStyle.NONE front = bool(side_studs["front"]) back = bool(side_studs["back"]) left = bool(side_studs["left"]) right = bool(side_studs["right"]) if style != SideStudStyle.NONE and not front and not back and not left and not right: Console.PrintMessage( "side_studs[\"style\"] set to SideStudStyle.NONE as " "none of Front, Back, Left, Right are True\n") style = SideStudStyle.NONE self.side_studs_style = style if self.side_studs_style == SideStudStyle.NONE: Console.PrintMessage("Side Studs: NONE\n") else: self.side_studs_front = front self.side_studs_back = back self.side_studs_left = left self.side_studs_right = right Console.PrintMessage("Side Studs: {0} {1}{2}{3}{4}\n".format( "OPEN" if self.side_studs_style == SideStudStyle.OPEN else "HOLE", "FRONT " if self.side_studs_front else "", "BACK" if self.side_studs_back else "", "LEFT " if self.side_studs_left else "", "RIGHT " if self.side_studs_right else ""))
def calculate_global_placement(child: object, placements: Placement = []) -> Placement: placements.append(child.Placement) in_list = child.InList num_in = len(in_list) if num_in == 0: global_placement = Placement() placements.reverse() # Reverse list in order of parent to child. for placement in placements: global_placement *= placement return global_placement if num_in > 1: Console.PrintWarning( f'{child.Label} has more than 1 parent. Choosing 1st.\n') parent = in_list[0] Console.PrintMessage(f'{parent.Label} ({parent.TypeId})\n') return calculate_global_placement(parent, placements)
def observerDisable(): global Asm4_3DselObserver Gui.Selection.removeObserver(Asm4_3DselObserver) setButton(3,False) # only print to Console if the Asm4_3DselObserver was there if Asm4_3DselObserver: FCC.PrintMessage("Asm4 3D view selection mode is now DISABLED\n") Asm4_3DselObserver = None
def render(self): context = BrickContext() try: context.width = self.width context.depth = self.depth context.height = self.height context.top_studs_style = self.top_studs_style if self.top_studs_style != TopStudStyle.NONE: context.top_studs_width_count = self.top_studs_width_count context.top_studs_depth_count = self.top_studs_depth_count context.side_studs_style = self.side_studs_style if self.side_studs_style != SideStudStyle.NONE: context.side_studs_front = self.side_studs_front context.side_studs_back = self.side_studs_back context.side_studs_left = self.side_studs_left context.side_studs_right = self.side_studs_right context.pins_style = self.pins_style if self.pins_style != PinStyle.NONE: context.pins_front = self.pins_front context.pins_back = self.pins_back context.pins_left = self.pins_left context.pins_right = self.pins_right context.pins_offset = self.pins_offset context.hole_style = self.hole_style if self.hole_style != HoleStyle.NONE: context.holes_offset = self.holes_offset context.doc = activeDocument() context.brick = context.doc.addObject("PartDesign::Body", "brick") self._create_datum_planes(context) BodyRenderer().render(context) if self.top_studs_style != TopStudStyle.NONE: TopStudsRenderer().render(context) if self.side_studs_style != SideStudStyle.NONE: SideStudsRenderer().render(context) if self.pins_style != PinStyle.NONE: PinsRenderer().render(context) if self.hole_style != HoleStyle.NONE: HolesRenderer().render(context) context.brick.Tip.ViewObject.Visibility = True except Exception as inst: Console.PrintError(inst) finally: del context
def get_heated_bed_creation_kwargs(): selection_objects = Gui.Selection.getSelectionEx() try: frame, axis = find_frame_and_axis_in_selection(selection_objects) return get_heated_bed_frame_axis_attachment_kwargs(frame, axis) except AttachmentError as reason: log_message_template = '{}. Placing heated bed in default position.\n' Console.PrintMessage(log_message_template.format(reason)) return {}
def observerEnable(): # remove any selection filters Gui.Selection.removeSelectionGate() global Asm4_3DselObserver Asm4_3DselObserver = selObserver3DView(); # add the listener, 0 forces to resolve the links Gui.Selection.addObserver(Asm4_3DselObserver, 0) setButton(3,True) FCC.PrintMessage("Asm4 3D view selection mode is now ENABLED\n")
def _get_axis_creation_kwargs(axis_orientation): selection_objects = Gui.Selection.getSelectionEx() try: frame, face = find_frame_and_face_in_selection(selection_objects) return get_axis_frame_attachment_kwargs(frame, face, axis_orientation) except AttachmentError as reason: log_message_template = '{}. Placing axis in default position.\n' Console.PrintMessage(log_message_template.format(reason)) return get_default_axis_creation_kwargs(axis_orientation)
def write_dict_list_to_csv(dict_list, columns, filename): try: with open(filename, 'w') as csv_file: writer = csv.DictWriter(csv_file, fieldnames=columns) writer.writeheader() for row in dict_list: writer.writerow(row) except IOError as e: Console.PrintError(str(e))
def get_extruder_creation_kwargs(): selection_objects = Gui.Selection.getSelectionEx() try: axis, face = find_axis_and_face_in_selection(selection_objects) return get_extruder_axis_attachment_kwargs(axis, face) except AttachmentError as reason: log_message_template = '{}. Placing extruder in default position.\n' Console.PrintMessage(log_message_template.format(reason)) return {}
def writeMisc(self, key, val): grp = FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/CuraEngine") pt = self.getParamType(key) if pt is "string": grp.SetString(key, val) elif pt is "float": grp.SetFloat(key, val) Console.PrintMessage("Setting " + key + " to " + str(val) + '\n')
def accept(self): """ Executed upon clicking "OK" button in FreeCAD Tasks panel. """ Console.PrintMessage('Saving cut list as "{}".\n'.format( self.save_file_name)) write_dict_list_to_csv(self.cut_list_table_rows, self.columns, self.save_file_name) FreeCADGui.Control.closeDialog()