def process3D_ObjectsViaOpenSCADShape(ObjList, Operation, maxmeshpoints=None): import FreeCAD import Mesh import Part params = FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/OpenSCAD") if False: # disabled due to issue 1292 import MeshPart meshes = [MeshPart.meshFromShape(obj.Shape,params.GetFloat(\ 'meshmaxlength',1.0), params.GetFloat('meshmaxarea',0.0),\ params.GetFloat('meshlocallen',0.0),\ params.GetFloat('meshdeflection',0.0)) for obj in ObjList] else: meshes = [Mesh.Mesh(obj.Shape.tessellate(params.GetFloat(\ 'meshmaxlength',1.0))) for obj in ObjList] if max(mesh.CountPoints for mesh in meshes) < \ (maxmeshpoints or params.GetInt('tempmeshmaxpoints', 5000)): stlmesh = meshoptempfile(Operation, meshes) sh = Part.Shape() sh.makeShapeFromMesh(stlmesh.Topology, 0.1) solid = Part.Solid(sh) solid = solid.removeSplitter() if solid.Volume < 0: solid.complement() return solid
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 read_in_stl_files_and_resave_as_single_step(read_folder, write_folder): try: os.mkdir(write_folder) except: pass list_of_solid_parts = [] for file in os.listdir(read_folder): if file.endswith(".stl"): #print('reading in ' ,os.path.join(read_folder, file)) # only for stp model =Part.Shape() # model.read(os.path.join("stl_files", file)) #obj = Mesh.open(os.path.join(read_folder, file)) obj = Mesh.Mesh(os.path.join(read_folder, file)) #print('opening ' ,os.path.join(read_folder, file)) #Mesh.export(obj,os.path.join(write_folder,file)) shape = Part.Shape() shape.makeShapeFromMesh(obj.Topology, 0.05) solid = Part.makeSolid(shape) list_of_solid_parts.append(solid) compound_obj = Part.makeCompound(list_of_solid_parts) compound_obj.exportStep(os.path.join(write_folder, file))
def points2shape(document, name, points): """ :param document: string, FreeCAD.activeDocument() :param name: string, reference object :param points: tuple of numbers, coordinate list (x, y, z) :return Part::Feature """ total = len(points) if total < 3: return x0, y0, z0 = points[0] pl = FreeCAD.Placement() pl.Base = FreeCAD.Vector(x0, y0, z0) edges = [] x1, y1, z1 = x0, y0, z0 for i in range(1, total): x2, y2, z2 = points[i] edges += [Part.Line(Base.Vector(x1, y1, z1), Base.Vector(x2, y2, z2))] x1, y1, z1 = x2, y2, z2 edges += [Part.Line(Base.Vector(x1, y1, z1), Base.Vector(x0, y0, z0))] obj = document.addObject("Part::Feature", name) obj.Shape = Part.Shape(edges) obj.Placement = pl document.recompute() print("Shape " + obj.Name + ": " + str(obj.Placement)) return obj
def process(self): if not any(socket.is_linked for socket in self.outputs): return verts_s = self.inputs[0].sv_get(deepcopy=False) faces_s = self.inputs[1].sv_get(deepcopy=False) solids = [] faces = [] for verts, faces in zip(*mlr([verts_s, faces_s])): tri_faces = ensure_triangles(verts, faces, True) faces_t = [] for f in tri_faces: faces_t.append([verts[c] for c in f]) mesh = Mesh.Mesh(faces_t) shape = Part.Shape() shape.makeShapeFromMesh(mesh.Topology, self.precision) if self.refine_solid: shape = shape.removeSplitter() solid = Part.makeSolid(shape) solids.append(solid) self.outputs['Solid'].sv_set(solids)
def makeJoint(radius = 1.0, height = 1.25, width = 1.75, thickness = 0.1): # vertices on outer edge V1 = Base.Vector(-radius, -height, -width/2) # lower left V2 = Base.Vector(-radius, 0, -width/2) V3 = Base.Vector(0, radius, -width/2) # top V4 = Base.Vector(radius, 0, -width/2) V5 = Base.Vector(radius, -height, -width/2) # lower right # vertices on inner edge # keep numbering in same direction around loop V6 = Base.Vector(radius-thickness, -height, -width/2) # lower left V7 = Base.Vector(radius-thickness, 0, -width/2) V8 = Base.Vector(0, radius-thickness, -width/2) # top V9 = Base.Vector(-radius+thickness, 0, -width/2) VA = Base.Vector(-radius+thickness, -height, -width/2) # lower right # create edge segments L1 = Part.LineSegment(V1, V2) C1 = Part.Arc(V2, V3, V4) L2 = Part.LineSegment(V4, V5) L3 = Part.LineSegment(V5, V6) L4 = Part.LineSegment(V6, V7) C2 = Part.Arc(V7, V8, V9) L5 = Part.LineSegment(V9, VA) L6 = Part.LineSegment(VA, V1) thickness = Part.Shape([L1, C1, L2, L3, L4, C2, L5, L6]) W = Part.Wire(thickness.Edges) F = Part.Face(W) P = F.extrude(Base.Vector(0, 0, width)) return P
def boxes(filename): import sys sys.path.append("/usr/lib/freecad/lib/") import FreeCAD, Part shape = Part.Shape() shape.read(filename) shapes = shape.childShapes() boxes = [] # if name == "SR319-20x55-ASSEMBLY": shapes = shapes[0].childShapes()[-3:-2] if name == "SR319-SERVO": shapes = [shape] elif name == "SR319-FEET": shapes = [shape] elif name == "SR319-HOE": shapes = [shape] elif name == "SR319-BODY": shapes = [shape] elif name == "SR319-CAM": shapes = [shape] elif name == "SR319-AIY": shapes = [shape] else: shapes = [] for c in shapes: boxes.append({ "size": "%f %f %f" % (c.BoundBox.XLength / 1000.0, c.BoundBox.YLength / 1000.0, c.BoundBox.ZLength / 1000.0), "pose": "%f %f %f 0 0 0" % (c.BoundBox.Center.x / 1000.0, c.BoundBox.Center.y / 1000.0, c.BoundBox.Center.z / 1000.0), "xyz": "%f %f %f" % (c.BoundBox.Center.x / 1000.0, c.BoundBox.Center.y / 1000.0, c.BoundBox.Center.z / 1000.0), "rpy": "0 0 0" }) return boxes
def open_stp_and_resave_geometry_as_seperate_stl_bodies(filenames): os.system('mkdir stl_files') for filename in filenames: short_filename, extension = os.path.splitext(filename) model = Part.Shape() model.read(filename) module_counter = 1 remaining_solids = [] for solid in model.Solids: print(' looking at soild with a volume of ' + str(solid.Volume)) #if len(solid.Faces)==6: #common_solid = solid.common(slice) #if common_solid.Volume !=0 : #common_solid.exportStep('stl_files/'+short_filename+'_'+str(module_counter)+'.stp') #common_solid.exportSt('stl_files/'+short_filename+'_'+str(module_counter)+'.stl') #module_counter=module_counter+1 #remaining_solids.append(common_solid) #common_solid_compound = Part.makeCompound(remaining_solids) #common_solid_compound.exportStl('stl_modules/lithium-lead-all.stl') return list_of_stl_files_for_each_stp_file
def process3D_ObjectsViaOpenSCAD(doc, ObjList, Operation): import FreeCAD, Mesh, Part params = FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/OpenSCAD") if False: # disabled due to issue 1292 import MeshPart meshes = [MeshPart.meshFromShape(obj.Shape,params.GetFloat(\ 'meshmaxlength',1.0), params.GetFloat('meshmaxarea',0.0),\ params.GetFloat('meshlocallen',0.0),\ params.GetFloat('meshdeflection',0.0)) for obj in ObjList] else: meshes = [Mesh.Mesh(obj.Shape.tessellate(params.GetFloat(\ 'meshmaxlength',1.0))) for obj in ObjList] if max(mesh.CountPoints for mesh in meshes) < \ params.GetInt('tempmeshmaxpoints',5000): stlmesh = meshoptempfile(Operation, meshes) sh = Part.Shape() sh.makeShapeFromMesh(stlmesh.Topology, 0.1) solid = Part.Solid(sh) obj = doc.addObject('Part::Feature', Operation) #non parametric objec solid = solid.removeSplitter() if solid.Volume < 0: solid.complement() obj.Shape = solid #.removeSplitter() if FreeCAD.GuiUp: for index in ObjList: index.ViewObject.hide() return (obj)
def __init__(self, obj, name="valve", fileName='ballDN15.stp', ports='0:0:0'): #obj.Proxy = self super(AnyThing, self).__init__(obj) # define common properties obj.PType = "Any" # define specific properties obj.addProperty( "App::PropertyString", "FileName", "AnyThing", "The file of the shape (inside ./shapes)").FileName = fileName portslist = list() if ports: for port in ports.split('/'): portslist.append( FreeCAD.Vector([float(i) for i in port.split(":")])) obj.Ports = portslist if fileName: s = Part.Shape() path = join(dirname(abspath(__file__)), "shapes", fileName) if exists(path): s.read(path) obj.Shape = s else: FreeCAD.Console.PrintError("%s file doesn't exist" % fileName)
def find_tor_radius_from_files(directory, prefix): """Finds the radius, i.e. distance from the origin to the closest point on any of the files with the given prefix, in the given directory.""" print "reading files with prefix", prefix, "in directory", directory, "to find radius..." current_max = 0.0 origin = Base.Vector(0.0, 0.0, 0.0) counter = 0 #go through every stl file with given prefix and find distance from origin for stl_file in os.listdir(directory): if stl_file.endswith(".stl") and stl_file.lower().startswith( prefix.lower()): print "reading", stl_file #return a shape: try: obj = Mesh.Mesh(os.path.join(directory, stl_file)) shape = Part.Shape() shape.makeShapeFromMesh(obj.Topology, 0.05) #solid = Part.makeSolid(shape) try: for vertex in shape.Vertexes: dist = vertex.Point.x if dist > current_max: current_max = dist except: print "failed to find vertex in shape. vertexes for", stl_file counter += 1 except: print "failed to read file", os.path.join( directory, stl_file) + ". Continuing..." print counter, "files read. Tor radius read:", current_max return float(current_max)
def execute(self, obj): import Part shapes_collection = [] # ADDITIONS a_shape = self.get_addition_shape(obj) if a_shape: shapes_collection.append(a_shape) # FILLING f_shape = self.get_fill_shape(obj) if f_shape: shapes_collection.append(f_shape) # create object positive shape if len(shapes_collection) > 0: obj.Shape = Part.makeCompound(shapes_collection) else: obj.Shape = Part.Shape() # VOID vs = self.get_void_shape(obj) # create object negative shape if vs: obj.VoidShape = vs
def execute(self, fp): # refresh properties back to linked SubGrids every time the Star gets recomputed # determine number of SubGrids fp.N = len(fp.SubList) # set size of Stargrid attribute fp.StarGrid = [0] * N # compile all SubGrid Poles and Weights into StarGrid attribute for n in range(N): #set size of single SubGrid StarGrid_n = [0] * 36 for i in range(36): # set Pole/Weight format [Base.Vector(), Float] StarGrid_n_i = [0, 0] StarGrid_n_i[0] = fp.SubList[n].Poles[i] StarGrid_n_i[1] = fp.SubList[n].Weights[i] StarGrid_n[i] = StarGrid_n_i fp.StarGrid[n] = StarGrid_n # a specific Pole is now addressed as StarGrid[n][i][0] # a specific Weight is now addresses as StarGrid[n][i][1] fp.Legs = [] self.StarRow2_SubLoop(fp, fp.N) self.StarDiag3_SubLoop(fp, fp.N) self.StarRow3_SubLoop(fp, fp.N) self.StarDiag4_SubLoop(fp, fp.N) self.StarDiag4_squish(fp, N) self.StarRow4_SubLoop(fp, fp.N) self.StarCenter(fp, fp.N) fp.Shape = Part.Shape(fp.Legs)
def execute(self, obj): pl = obj.Placement if obj.Base: if obj.isDerivedFrom("Mesh::Feature"): m = None if obj.Base.isDerivedFrom("Part::Feature"): base = obj.Base.Shape.copy() base = self.processSubShapes(obj, base, pl) if base: import Mesh m = Mesh.Mesh(base.tessellate(1)) elif obj.Base.isDerivedFrom("Mesh::Feature"): m = obj.Base.Mesh.copy() if m: if not pl.isNull(): m.Placement = pl obj.Mesh = m else: base = None if obj.Base.isDerivedFrom("Part::Feature"): base = obj.Base.Shape.copy() elif obj.Base.isDerivedFrom("Mesh::Feature"): import Part base = Part.Shape() base.makeShapeFromMesh(obj.Base.Mesh.Topology, 0.05) base = base.removeSplitteR() if base: base = self.processSubShapes(obj, base, pl) self.applyShape(obj, base, pl)
def Process_comp_outline(doc,comp_outline,comp_height): """Process_comp_outline(doc,comp_outline,comp_height)->part shape Create solid component shape base on its outline""" vertex_index=-1; #presume no vertex out_shape=[] if comp_outline==[]: #force 0.2mm circle shape for components without place outline definition comp_outline.append([0.0,0.0,0.0]) comp_outline.append([0.1,0.0,360.0]) for point in comp_outline: vertex=Base.Vector(point[0],point[1],0) vertex_index+=1 if vertex_index>0: if point[2]!=0 and point[2]!=360: out_shape.append(Part.Arc(prev_vertex,mid_point(prev_vertex,vertex,point[2]),vertex)) FreeCAD.Console.PrintMessage("mid point "+str(mid_point)+"\n") elif point[2]==360: per_point=Per_point(prev_vertex,vertex) out_shape.append(Part.Arc(per_point,mid_point(per_point,vertex,point[2]/2),vertex)) out_shape.append(Part.Arc(per_point,mid_point(per_point,vertex,-point[2]/2),vertex)) else: out_shape.append(Part.LineSegment(prev_vertex,vertex)) prev_vertex=vertex out_shape=Part.Shape(out_shape) out_shape=Part.Wire(out_shape.Edges) out_shape=Part.Face(out_shape) out_shape=out_shape.extrude(Base.Vector(0,0,comp_height)) #Part.show(out_shape) return out_shape
def execute(self, obj): pl = obj.Placement filename = self.getFile(obj) if filename and obj.Part and self.reload and obj.ReferenceMode in [ "Normal", "Transient" ]: self.parts = self.getPartsList(obj) if self.parts: zdoc = zipfile.ZipFile(filename) if zdoc: if obj.Part in self.parts: if self.parts[obj.Part][1] in zdoc.namelist(): f = zdoc.open(self.parts[obj.Part][1]) shapedata = f.read() f.close() import Part shape = Part.Shape() if sys.version_info.major >= 3: shapedata = shapedata.decode("utf8") shape.importBrepFromString(shapedata) obj.Shape = shape if not pl.isIdentity(): obj.Placement = pl else: print("Part not found in file") self.reload = False
def getShape(obj): "gets a shape from an IfcOpenShell object" #print "retrieving shape from obj ",obj.id import Part sh = Part.Shape() try: sh.importBrepFromString(obj.mesh.brep_data) #sh = Part.makeBox(2,2,2) except: print "Error: malformed shape" return None if not sh.Solids: # try to extract a solid shape if sh.Faces: try: if DEBUG: print "Malformed solid. Attempting to fix..." shell = Part.makeShell(sh.Faces) if shell: solid = Part.makeSolid(shell) if solid: sh = solid except: if DEBUG: print "failed to retrieve solid from object ", obj.id else: if DEBUG: print "object ", obj.id, " doesn't contain any face" m = obj.matrix mat = FreeCAD.Matrix(m[0], m[3], m[6], m[9], m[1], m[4], m[7], m[10], m[2], m[5], m[8], m[11], 0, 0, 0, 1) sh.Placement = FreeCAD.Placement(mat) # if DEBUG: print "getting Shape from ",obj #print "getting shape: ",sh,sh.Solids,sh.Volume,sh.isValid(),sh.isNull() #for v in sh.Vertexes: print v.Point return sh
def oval(pm, tn, y, z): """ Return an oval wire with given perimeter *pm* and thickness *tn*, centered at 0, *y*, *z*. The oval plane is parallel to the xy plane and the oval has its long axis parallel to y axis. """ # half thickness htn = 0.5 * tn # half width of flat part hfw = 0.25 * (pm - pi * tn) # control points p1 = Base.Vector(-hfw, htn + y, z) p2 = Base.Vector(+hfw, htn + y, z) p3 = Base.Vector(+htn + hfw, y, z) p4 = Base.Vector(+hfw, -htn + y, z) p5 = Base.Vector(-hfw, -htn + y, z) p6 = Base.Vector(-htn - hfw, y, z) # return oval wire return Part.Wire( Part.Shape([ Part.Line(p1, p2), Part.Arc(p2, p3, p4), Part.Line(p4, p5), Part.Arc(p5, p6, p1) ]).Edges)
def process_mesh_file(fname, ext): import Mesh, Part fullname = fname + '.' + ext filename = os.path.join(pathName, fullname) objname = os.path.split(fname)[1] mesh1 = doc.getObject(objname) #reuse imported object if not mesh1: Mesh.insert(filename) mesh1 = doc.getObject(objname) if mesh1 is not None: if gui: mesh1.ViewObject.hide() sh = Part.Shape() sh.makeShapeFromMesh(mesh1.Mesh.Topology, 0.1) solid = Part.Solid(sh) obj = doc.addObject('Part::Feature', "Mesh") #ImportObject(obj,mesh1) #This object is not mutable from the GUI #ViewProviderTree(obj.ViewObject) solid = solid.removeSplitter() if solid.Volume < 0: #sh.reverse() #sh = sh.copy() solid.complement() obj.Shape = solid #.removeSplitter() else: #mesh1 is None FreeCAD.Console.PrintError('Mesh not imported %s.%s %s\n' % \ (objname,ext,filename)) import Part obj = doc.addObject('Part::Feature', "FailedMeshImport") obj.Shape = Part.Compound([]) return (obj)
def onChanged(self,obj,prop): if prop == "Height": for child in obj.Group: if Draft.getType(child) in ["Wall","Structure"]: if not child.Height.Value: #print("Executing ",child.Label) child.Proxy.execute(child) elif prop == "Placement": if hasattr(self,"oldPlacement"): if self.oldPlacement: deltap = obj.Placement.Base.sub(self.oldPlacement.Base) if deltap.Length == 0: deltap = None deltar = self.oldPlacement.Rotation.multiply(obj.Placement.Rotation) #print "Rotation",deltar.Axis,deltar.Angle if deltar.Angle < 0.0001: deltar = None for child in obj.Group: if ((not hasattr(child,"MoveWithHost")) or child.MoveWithHost) and hasattr(child,"Placement"): #print "moving ",child.Label if deltap: child.Placement.move(deltap) if deltar: #child.Placement.Rotation = child.Placement.Rotation.multiply(deltar) - not enough, child must also move # use shape methods to obtain a correct placement import Part,math shape = Part.Shape() shape.Placement = child.Placement shape.rotate(DraftVecUtils.tup(obj.Placement.Base), DraftVecUtils.tup(deltar.Axis), math.degrees(deltar.Angle)) child.Placement = shape.Placement
def execute(self, selfobj): from PartOMagic.Gui.Utils import screen if selfobj.Tip is not None: selfobj.Shape = transformCopy_Smart( screen(selfobj.Tip).Shape, selfobj.Placement) else: selfobj.Shape = Part.Shape()
def getShape(obj): "gets a shape from an IfcOpenShell object" import StringIO, Part sh = Part.Shape() sh.importBrep(StringIO.StringIO(obj.mesh.brep_data)) if not sh.Solids: # try to extract a solid shape if sh.Faces: try: if DEBUG: print "Malformed solid. Attempting to fix..." shell = Part.makeShell(sh.Faces) if shell: solid = Part.makeSolid(shell) if solid: sh = solid except: if DEBUG: print "failed to retrieve solid from object ", obj.id else: if DEBUG: print "object ", obj.id, " doesn't contain any face" m = obj.matrix mat = FreeCAD.Matrix(m[0], m[3], m[6], m[9], m[1], m[4], m[7], m[10], m[2], m[5], m[8], m[11], 0, 0, 0, 1) sh.Placement = FreeCAD.Placement(mat) # if DEBUG: print "getting Shape from ",obj return sh
def execute(self, fp): listOfShapes = [] for i in range(len(fp.shapeList)): listOfShapes.append(fp.shapeList[i].Shape) if len(listOfShapes) > 0: fp.Shape = Part.makeCompound(listOfShapes) else: fp.Shape = Part.Shape()
def execute(self, obj): """ Create compound part at recompute. """ shape = CfdTools.makeShapeFromReferences(obj.ShapeRefs, False) if shape is None: shape = Part.Shape() if not CfdTools.isSameGeometry(shape, obj.Shape): obj.Shape = shape self.updateBoundaryColors(obj)
def execute(self, fp): l = len(fp.Geometry) if (l == 0): fp.Shape = Part.Shape() elif (l == 1): fp.Shape = fp.Geometry[0].toShape() else: fp.Shape = Part.Compound([g.toShape() for g in fp.Geometry])
def getPlanWithLine(line): """Function to make a plane along Normal plan""" import Part plan = FreeCAD.DraftWorkingPlane w = plan.getNormal() part = Part.Shape(line) out = part.extrude(w) return out
def getDefaultTopTransition(contour, pos, defaultTransitionLength): """Generate default transitionEnd if no custom reference is provided""" line = geom.wireFromPrim( Part.LineSegment(Vector(pos.x + defaultTransitionLength, -150, pos.z), Vector(pos.x + defaultTransitionLength, 150, pos.z))) (d, vs, es) = line.Shape.distToShape(contour.Shape) if d < 1e-5 and len(vs) > 1: return Part.Wire(Part.Shape([Part.LineSegment(vs[0][0], vs[1][0])]))
def __init__(self, path): """ Get a Part object from a path and set self.__shape with the FreeCAD Part object @param {string} path File path """ self.__shape = Part.Shape() self.__shape.read(path) self.__shape.tessellate(1)
def readSurface(path): obj = Part.Shape() obj.read(path) srf = obj.Faces[0] return srf
def get_elebase_sh(corner_min, size, baseheight, tm): from FreeCAD import Vector as vec from MeshPart import meshFromShape from Part import makeLine # scaled place on orgin place_for_mesh = FreeCAD.Vector(-corner_min.x - size[0], -corner_min.y - size[1], 0.00) # SRTM data resolution is 30 m = 30'000 mm in the usa # rest of the world is 90 m = 90'000 mm # it makes no sense to use values smaller than 90'000 mm pt_distance = 100000 say(corner_min) # y is huge!, but this is ok! say(size) # base area surface mesh with heights # Version new pn1 = vec(0, 0, 0) pn2 = vec(pn1.x + size[0] * 2, pn1.y, 0) pn3 = vec(pn1.x + size[0] * 2, pn1.y + size[1] * 2, 0) pn4 = vec(pn1.x, pn1.y + size[1] * 2, 0) ln1 = makeLine(pn1, pn2) ln2 = makeLine(pn2, pn3) ln3 = makeLine(pn3, pn4) ln4 = makeLine(pn4, pn1) wi = Part.Wire([ln1, ln2, ln3, ln4]) fa = Part.makeFace([wi], "Part::FaceMakerSimple") msh = meshFromShape(fa, LocalLength=pt_distance) # move to corner_min to retrieve the heights msh.translate( corner_min.x, corner_min.y, 0, ) # move mesh points z-koord for pt_msh in msh.Points: # say(pt_msh.Index) # say(pt_msh.Vector) pt_tm = tm.toGeographic(pt_msh.Vector.x, pt_msh.Vector.y) height = get_height_single(pt_tm[0], pt_tm[1]) # mm # say(height) pt_msh.move(FreeCAD.Vector(0, 0, height)) # move mesh back centered on origin msh.translate( -corner_min.x - size[0], -corner_min.y - size[1], -baseheight, ) # create Shape from Mesh sh = Part.Shape() sh.makeShapeFromMesh(msh.Topology, 0.1) return sh