def makeTag(props, tagString, slotWidth): import Part fontdir, font = getFont(props) # test: tagS=Part.makeWireString("34öäüZB", "/usr/share/fonts/truetype/dejavu/", "DejaVuSans-Bold.ttf", 6.0, 0) tagS = Part.makeWireString(unicode(tagString), fontdir, font, props.tagTextSize, 0) # Draft causes problems with GUI #tagShapeString = Draft.makeShapeString(String=unicode(tagString),\ # FontFile=join(fontdir,font),Size=props.tagTextSize,Tracking=0) #tag=tagShapeString.Shape.extrude(FreeCAD.Vector(0,0,props.tagTextHeight)) #tagF = [Part.Face(c) for c in tagS] # does not work for multi wire chars like "4", so I do this: tagF = [] tagFcuts = [] for c in tagS: for ci in c: if not isInside(ci, c): tagF.append(Part.Face(ci)) else: tagFcuts.append(Part.Face(ci)) tagC = Part.Compound(tagF) tagCcuts = Part.Compound(tagFcuts) tagC = tagC.cut(tagCcuts) tag = tagC.extrude(FreeCAD.Vector(0, 0, props.tagTextHeight)) tag.translate( FreeCAD.Vector((slotWidth - tag.BoundBox.XLength) / 2, props.marginBottom, 0)) return tag
def connect(list_of_shapes, tolerance = 0.0): """connect(list_of_shapes, tolerance = 0.0): connects solids (walled objects), shells and wires by throwing off small parts that result when splitting them at intersections. Compounds in list_of_shapes are automatically exploded, so self-intersecting compounds are valid for connect.""" # explode all compounds before GFA. new_list_of_shapes = [] for sh in list_of_shapes: new_list_of_shapes.extend( compoundLeaves(sh) ) list_of_shapes = new_list_of_shapes #test if shapes are compatible for connecting dim = ShapeMerge.dimensionOfShapes(list_of_shapes) if dim == 0: raise TypeError("Cannot connect vertices!") if len(list_of_shapes) < 2: return Part.makeCompound(list_of_shapes) if not generalFuseIsAvailable(): #fallback to legacy result = list_of_shapes[0] for i in range(1, len(list_of_shapes)): result = connect_legacy(result, list_of_shapes[i], tolerance) return result pieces, map = list_of_shapes[0].generalFuse(list_of_shapes[1:], tolerance) ao = GeneralFuseResult(list_of_shapes, (pieces, map)) ao.splitAggregates() #print len(ao.pieces)," pieces total" keepers = [] all_danglers = [] # debug #add all biggest dangling pieces for src in ao.source_shapes: danglers = [piece for piece in ao.piecesFromSource(src) if len(ao.sourcesOfPiece(piece)) == 1] all_danglers.extend(danglers) largest = shapeOfMaxSize(danglers) if largest is not None: keepers.append(largest) touch_test_list = Part.Compound(keepers) #add all intersection pieces that touch danglers, triple intersection pieces that touch duals, and so on for ii in range(2, ao.largestOverlapCount()+1): list_ii_pieces = [piece for piece in ao.pieces if len(ao.sourcesOfPiece(piece)) == ii] keepers_2_add = [] for piece in list_ii_pieces: if ShapeMerge.isConnected(piece, touch_test_list): keepers_2_add.append(piece) if len(keepers_2_add) == 0: break keepers.extend(keepers_2_add) touch_test_list = Part.Compound(keepers_2_add) #merge, and we are done! #print len(keepers)," pieces to keep" return ShapeMerge.mergeShapes(keepers)
def slice(base_shape, tool_shapes, mode, tolerance=0.0): """slice(base_shape, tool_shapes, mode, tolerance = 0.0): functional part of Slice feature. Splits base_shape into pieces based on intersections with tool_shapes. mode is a string. It can be "Standard", "Split" or "CompSolid". "Standard" - return like generalFuse: edges, faces and solids are split, but wires, shells, compsolids get extra segments but remain in one piece. "Split" - wires and shells will be split at intersections, too. "CompSolid" - slice a solid and glue it back together to make a compsolid""" shapes = [base_shape] + [ Part.Compound([tool_shape]) for tool_shape in tool_shapes ] # hack: putting tools into compounds will prevent contamination of result with pieces of tools if len(shapes) < 2: raise ValueError("No slicing objects supplied!") pieces, map = shapes[0].generalFuse(shapes[1:], tolerance) gr = GeneralFuseResult(shapes, (pieces, map)) if mode == "Standard": result = gr.piecesFromSource(shapes[0]) elif mode == "CompSolid": solids = Part.Compound(gr.piecesFromSource(shapes[0])).Solids if len(solids) < 1: raise ValueError("No solids in the result. Can't make compsolid.") elif len(solids) == 1: FreeCAD.Console.PrintWarning( "Part_Slice: only one solid in the result, generating trivial compsolid." ) result = ShapeMerge.mergeSolids(solids, bool_compsolid=True).childShapes() elif mode == "Split": gr.splitAggregates(gr.piecesFromSource(shapes[0])) result = gr.piecesFromSource(shapes[0]) return result[0] if len(result) == 1 else Part.Compound(result)
def createRibCage(proxy, obj, bs): rc = obj.RibCount if rc > 0: ribs = [] for i in range(rc + 1): f = bs.uIso(1.0 / rc * i) ribs.append(f.toShape()) else: ribs = [] for i, j in enumerate(bs.getUKnots()): f = bs.uIso(j) ribs.append(f.toShape()) comp = Part.Compound(ribs) if obj.RibCage == None: obj.RibCage = App.activeDocument().addObject( 'Part::Feature', 'Ribs') obj.RibCage.Shape = comp vob = App.getDocument("Needle").ActiveObject.ViewObject vob.LineColor = (1., 1., 0.) vob.LineWidth = 5.00 mers = [] for i, j in enumerate(bs.getVKnots()): f = bs.vIso(j) mers.append(f.toShape()) comp = Part.Compound(mers) if obj.Meridians == None: obj.Meridians = App.getDocument("Needle").addObject( 'Part::Feature', 'Meridians') obj.Meridians.Shape = comp vob = App.getDocument("Needle").ActiveObject.ViewObject vob.LineColor = (1., 0., 0.4) vob.LineWidth = 5.00
def drawdelaunay(vertices,faces): d=FreeCAD.newDocument("drawdelaunay") points_cloud=[] triang_faces=[] for vt in vertices: o=Part.Vertex(vt) points_cloud.append(o) for ft in faces: eg1 = Part.makeLine(vertices[ft[0]],vertices[ft[2]]) eg2 = Part.makeLine(vertices[ft[2]],vertices[ft[1]]) eg3 = Part.makeLine(vertices[ft[1]],vertices[ft[0]]) wire = Part.Wire([eg1, eg2, eg3]) face = Part.Face(wire) triang_faces.append(face) tu01=Part.Compound(points_cloud) tu02=Part.Compound(triang_faces) # FreeCADGui.showMainWindow() Part.show(tu01) Part.show(tu02) FreeCADGui.SendMsgToActiveView("ViewFit") Gui.activeDocument().activeView().viewTop() Gui.activeDocument().getObject("Shape001").DisplayMode = "Shaded"
def createGeometry(self, fp): import FreeCAD, Part, math, sys #tangle = -twist #openscad uses degrees clockwise if fp.Base and fp.Angle and fp.Height and \ fp.Base.Shape.isValid(): #wire=fp.Base.Shape.Wires[0].transformGeometry(fp.Base.Placement.toMatrix()) solids = [] for faceb in fp.Base.Shape.Faces: #fp.Base.Shape.Faces[0].check() #faceb=fp.Base.Shape.Faces[0] #faceb=fp.Base.Shape.removeSplitter().Faces[0] faceu = faceb.copy() facetransform = FreeCAD.Matrix() facetransform.rotateZ(math.radians(fp.Angle.Value)) facetransform.move(FreeCAD.Vector(0, 0, fp.Height.Value)) faceu.transformShape(facetransform) step = 2 + abs(int( fp.Angle.Value // 90)) #resolution in z direction # print abs(int(fp.Angle.Value // 90)) #resolution in z direction # print step zinc = fp.Height.Value / (step - 1.0) angleinc = math.radians(fp.Angle.Value) / (step - 1.0) spine = Part.makePolygon([(0,0,i*zinc) \ for i in range(step)]) auxspine = Part.makePolygon([(math.cos(i*angleinc),\ math.sin(i*angleinc),i*fp.Height.Value/(step-1)) \ for i in range(step)]) faces = [faceb, faceu] for wire in faceb.Wires: pipeshell = Part.BRepOffsetAPI.MakePipeShell(spine) pipeshell.setSpineSupport(spine) pipeshell.add(wire) # Was before function change # pipeshell.setAuxiliarySpine(auxspine,True,False) if sys.version_info.major < 3: pipeshell.setAuxiliarySpine(auxspine, True, long(0)) else: pipeshell.setAuxiliarySpine(auxspine, True, 0) print(pipeshell.getStatus()) assert (pipeshell.isReady()) #fp.Shape=pipeshell.makeSolid() pipeshell.build() faces.extend(pipeshell.shape().Faces) try: fullshell = Part.Shell(faces) solid = Part.Solid(fullshell) if solid.Volume < 0: solid.reverse() assert (solid.Volume >= 0) solids.append(solid) except Part.OCCError: solids.append(Part.Compound(faces)) fp.Shape = Part.Compound(solids)
def createGeometry(self, fp): import FreeCAD, Part, math, sys if fp.Base and fp.Height and fp.Base.Shape.isValid(): solids = [] for lower_face in fp.Base.Shape.Faces: upper_face = lower_face.copy() face_transform = FreeCAD.Matrix() face_transform.rotateZ(math.radians(fp.Angle.Value)) face_transform.scale(fp.Scale[0], fp.Scale[1], 1.0) face_transform.move(FreeCAD.Vector(0, 0, fp.Height.Value)) upper_face.transformShape( face_transform, False, True) # True to check for non-uniform scaling spine = Part.makePolygon([(0, 0, 0), (0, 0, fp.Height.Value)]) if fp.Angle.Value == 0.0: auxiliary_spine = Part.makePolygon([ (1, 1, 0), (fp.Scale[0], fp.Scale[1], fp.Height.Value) ]) else: num_revolutions = abs(fp.Angle.Value) / 360.0 pitch = fp.Height.Value / num_revolutions height = fp.Height.Value radius = 1.0 if fp.Angle.Value < 0.0: left_handed = True else: left_handed = False auxiliary_spine = Part.makeHelix(pitch, height, radius, 0.0, left_handed) faces = [lower_face, upper_face] for wire1, wire2 in zip(lower_face.Wires, upper_face.Wires): pipe_shell = Part.BRepOffsetAPI.MakePipeShell(spine) pipe_shell.setSpineSupport(spine) pipe_shell.add(wire1) pipe_shell.add(wire2) pipe_shell.setAuxiliarySpine(auxiliary_spine, True, 0) print(pipe_shell.getStatus()) assert (pipe_shell.isReady()) pipe_shell.build() faces.extend(pipe_shell.shape().Faces) try: fullshell = Part.Shell(faces) solid = Part.Solid(fullshell) if solid.Volume < 0: solid.reverse() assert (solid.Volume >= 0) solids.append(solid) except Part.OCCError: solids.append(Part.Compound(faces)) fp.Shape = Part.Compound(solids)
def execute(self, host): shell = makeDomeShape(host.Radius.getValueAs('mm'), host.FrequencyParameter) if host.ShapeType == 'Solid': host.Shape = Part.Solid(shell) elif host.ShapeType == 'Shell': host.Shape = shell elif host.ShapeType == 'Wireframe': host.Shape = Part.Compound(shell.Edges) elif host.ShapeType == 'Vertices': host.Shape = Part.Compound(shell.Vertexes) else: assert (False)
def makeCompound(cls, listOfShapes): """ Create a compound out of a list of shapes """ solids = [s.wrapped for s in listOfShapes] c = FreeCADPart.Compound(solids) return Shape.cast(c)
def applyFeature(baseshape, feature, transforms, mts): if hasattr(feature, 'Proxy') and hasattr(feature.Proxy, 'applyTransformed'): return feature.Proxy.applyTransformed(feature, baseshape, transforms, mts) task = getFeatureShapes(feature) for sign, featureshape in task: actionshapes = [] for transform in transforms: actionshapes.append(shallowCopy(featureshape, transform)) if mts.selfintersections: pass #to fuse the shapes to baseshape one by one else: actionshapes = [ Part.Compound(actionshapes) ] #to fuse all at once, saving for computing intersections between the occurrences of the feature for actionshape in actionshapes: assert (sign != 0) realsign = sign * mts.sign_override if abs(mts.sign_override) == +2: realsign = int(mts.sign_override / 2) if realsign > 0: baseshape = baseshape.fuse(actionshape) elif realsign < 0: baseshape = baseshape.cut(actionshape) if baseshape.isNull(): raise FeatureFailure( 'applying {name} failed - returned shape is null'.format( name=feature.Name)) return baseshape
def execute(self, selfobj): if selfobj.BaseFeature is None: baseshape = Part.Compound([]) else: baseshape = selfobj.BaseFeature.Shape mts = MultiTransformSettings() mts.sign_override = { 'keep': +1, 'invert': -1, 'as additive': +2, 'as subtractive': -2 }[selfobj.SignOverride] mts.selfintersections = selfobj.Selfintersections result = self.applyTransformed(selfobj, baseshape, None, mts) if selfobj.SingleSolid: # not proper implementation, but should do for majority of cases: pick the largest solid. vmax = 0 vmax_solid = None for s in result.Solids: v = s.Volume if v > vmax: vmax = v vmax_solid = s if vmax_solid is None: raise ValueError( "No solids in result. Maybe the result is corrupted because of failed BOP, or all the material was removed in the end." ) result = vmax_solid if selfobj.SingleSolid or len(result.Solids) == 1: result = transformCopy_Smart(result.Solids[0], selfobj.Placement) if selfobj.Refine: result = result.removeSplitter() selfobj.Shape = result
def split_face_with_scales( face: Part.Face, scales: list = [.75, .5], ) -> list: from BOPTools.GeneralFuseResult import GeneralFuseResult s1 = face.copy().scale(scales[0]) s2 = face.copy().scale(scales[1]) center_of_mass = face.CenterOfMass tr1 = center_of_mass.sub(s1.CenterOfMass) s1.Placement.Base = tr1 tr2 = center_of_mass.sub(s2.CenterOfMass) s2.Placement.Base = tr2 area1 = face.cut(s1) area2 = s1.cut(s2) e1, e2 = sorted(face.Edges, key=lambda x: x.Length, reverse=True)[0:2] v1 = e1.CenterOfMass v2 = e2.CenterOfMass poly = Part.makePolygon([v1, center_of_mass, v2]) faces = [] for area in (area1, area2): pieces, map_ = area.generalFuse([poly]) gr = GeneralFuseResult([area, poly], (pieces, map_)) gr.splitAggregates() comp = Part.Compound(gr.pieces) faces.extend(comp.Faces) faces.append(Part.Face(s2)) return faces
def shapeCloud(arr): v = [] for row in arr: for pt in row: v.append(Part.Vertex(pt)) c = Part.Compound(v) return (c)
def booleanFragments(list_of_shapes, mode, tolerance=0.0): """booleanFragments(list_of_shapes, mode, tolerance = 0.0): functional part of BooleanFragments feature. It's just result of generalFuse plus a bit of post-processing. mode is a string. It can be "Standard", "Split" or "CompSolid". "Standard" - return generalFuse as is. "Split" - wires and shells will be split at intersections. "CompSolid" - solids will be extracted from result of generelFuse, and compsolids will be made from them; all other stuff is discarded.""" pieces, map = list_of_shapes[0].generalFuse(list_of_shapes[1:], tolerance) if mode == "Standard": return pieces elif mode == "CompSolid": solids = pieces.Solids if len(solids) < 1: raise ValueError("No solids in the result. Can't make CompSolid.") elif len(solids) == 1: FreeCAD.Console.PrintWarning( "Part_BooleanFragments: only one solid in the result, generating trivial compsolid." ) return ShapeMerge.mergeSolids(solids, bool_compsolid=True) elif mode == "Split": gr = GeneralFuseResult(list_of_shapes, (pieces, map)) gr.splitAggregates() return Part.Compound(gr.pieces) else: raise ValueError("Unknown mode: {mode}".format(mode=mode))
def fuse(lst, name): global doc if printverbose: print "Fuse" if printverbose: print lst if len(lst) == 0: myfuse = doc.addObject("Part::Feature", "emptyfuse") myfuse.Shape = Part.Compound([]) elif len(lst) == 1: return lst[0] # Is this Multi Fuse elif len(lst) > 2: if printverbose: print "Multi Fuse" myfuse = doc.addObject('Part::MultiFuse', name) myfuse.Shapes = lst if gui: for subobj in myfuse.Shapes: subobj.ViewObject.hide() else: if printverbose: print "Single Fuse" myfuse = doc.addObject('Part::Fuse', name) myfuse.Base = lst[0] myfuse.Tool = lst[1] if gui: myfuse.Base.ViewObject.hide() myfuse.Tool.ViewObject.hide() return (myfuse)
def toShape(self): c = [] for u in self.uiso: c.append(u.toShape()) for v in self.viso: c.append(v.toShape()) return(Part.Compound(c))
def crossSection(obj, axis=(1.0, 0.0, 0.0), d=1.0, name=None): """Return cross section of object along axis. Parameters ---------- obj : FreeCAD.App.Document A FreeCAD object. axis : (Default value = (1.0, 0.0, 0.0) d : float (Default value = 1.0) name : str (Default value = None) Returns ------- returnObj """ doc = FreeCAD.ActiveDocument if name is None: name = obj.Name + "_section" wires = list() shape = obj.Shape for i in shape.slice(vec(axis[0], axis[1], axis[2]), d): wires.append(i) returnObj = doc.addObject("Part::Feature", name) returnObj.Shape = Part.Compound(wires) return returnObj
def cutSurfaces(self, fp): edges = list() if len(fp.Surfaces) == 1: vOffset = fp.Surfaces[0].Placement.Base else: bbox = None for obj in fp.Surfaces: if not bbox: bbox = obj.Shape.BoundBox else: bbox = bbox.united(obj.Shape.BoundBox) vOffset = Vector(bbox.XMin, bbox.YMin, bbox.ZMin) vOffset += fp.Position origin = Vector(0, 0, 0) off = origin.distanceToPlane(vOffset, fp.Normal) * -1 for obj in fp.Surfaces: for wire in obj.Shape.slice(fp.Normal, off): edges += wire.Edges if fp.Simplify > 0: edges = self.removeEdgeComplexity(fp, edges) edges = self.removeDoubles(edges) comp = Part.Compound(edges) comp.connectEdgesToWires(False, 1e-7) fp.Shape = comp
def p_intersection_action(p): 'intersection_action : intersection LPAREN RPAREN OBRACE block_list EBRACE' if printverbose: print "intersection" # Is this Multi Common if (len(p[5]) > 2): if printverbose: print "Multi Common" mycommon = doc.addObject('Part::MultiCommon', p[1]) mycommon.Shapes = p[5] if gui: for subobj in mycommon.Shapes: subobj.ViewObject.hide() elif (len(p[5]) == 2): if printverbose: print "Single Common" mycommon = doc.addObject('Part::Common', p[1]) mycommon.Base = p[5][0] mycommon.Tool = p[5][1] if gui: mycommon.Base.ViewObject.hide() mycommon.Tool.ViewObject.hide() elif (len(p[5]) == 1): mycommon = p[5][0] else: # 1 child mycommon = doc.addObject("Part::Feature", "emptyintersection") mycommon.Shape = Part.Compound([]) p[0] = [mycommon] if printverbose: print "End Intersection"
def p_difference_action(p): 'difference_action : difference LPAREN RPAREN OBRACE block_list EBRACE' if printverbose: print "difference" if printverbose: print len(p[5]) if printverbose: print p[5] if (len(p[5]) == 0): #nochild mycut = doc.addObject("Part::Feature", "emptycut") mycut.Shape = Part.Compound([]) elif (len(p[5]) == 1): #single object p[0] = p[5] else: # Cut using Fuse mycut = doc.addObject('Part::Cut', p[1]) mycut.Base = p[5][0] # Can only Cut two objects do we need to fuse extras if (len(p[5]) > 2): if printverbose: print "Need to Fuse Extra First" mycut.Tool = fuse(p[5][1:], 'union') else: mycut.Tool = p[5][1] if gui: mycut.Base.ViewObject.hide() mycut.Tool.ViewObject.hide() if printverbose: print "Push Resulting Cut" p[0] = [mycut] if printverbose: print "End Cut"
def shapeCloud(self): v = [] for row in self.result: for pt in row: v.append(Part.Vertex(pt)) c = Part.Compound(v) return(c)
def mergeSolids(list_of_solids_compsolids, flag_single=False, split_connections=[], bool_compsolid=False): """mergeSolids(list_of_solids, flag_single = False): merges touching solids that share faces. If flag_single is True, it is assumed that all solids touch, and output is a single solid. If flag_single is False, the output is a compound containing all resulting solids. Note. CompSolids are treated as lists of solids - i.e., merged into solids.""" solids = [] for sh in list_of_solids_compsolids: solids.extend(sh.Solids) if flag_single: cs = Part.CompSolid(solids) return cs if bool_compsolid else Part.makeSolid(cs) else: if len(solids) == 0: return Part.Compound([]) groups = splitIntoGroupsBySharing(solids, lambda sh: sh.Faces, split_connections) if bool_compsolid: merged_solids = [Part.CompSolid(group) for group in groups] else: merged_solids = [ Part.makeSolid(Part.CompSolid(group)) for group in groups ] return Part.makeCompound(merged_solids)
def getDrawingMinMaxXY(structure, rebars_list, view_plane): """getDrawingMinMaxXY(Structure, RebarsList, ViewPlane): Returns (min_x, min_y, max_x, max_y) of drawing. """ if view_plane.axis == FreeCAD.Vector(0, -1, 0): pts = [0, 1, 4, 5] elif view_plane.axis == FreeCAD.Vector(0, 1, 0): pts = [2, 3, 6, 7] elif view_plane.axis == FreeCAD.Vector(0, 0, 1): pts = [0, 1, 2, 3] elif view_plane.axis == FreeCAD.Vector(0, 0, -1): pts = [4, 5, 6, 7] elif view_plane.axis == FreeCAD.Vector(1, 0, 0): pts = [1, 2, 5, 6] else: pts = [0, 3, 4, 7] bounding_box = Part.Compound([rebar.Shape for rebar in rebars_list] + [structure.Shape]).BoundBox point = getProjectionToSVGPlane(bounding_box.getPoint(pts[0]), view_plane) min_x = point.x min_y = point.y max_x = point.x max_y = point.y for pt in pts[1:]: point = getProjectionToSVGPlane(bounding_box.getPoint(pt), view_plane) min_x = min(min_x, point.x) min_y = min(min_y, point.y) max_x = max(max_x, point.x) max_y = max(max_y, point.y) return min_x, min_y, max_x, max_y
def _splitInCompound(self, compound, existing_pieces): """Splits aggregates inside compound. Returns None if nothing is split, otherwise returns compound. existing_pieces is a dict. Key is deep hash. Value is tuple (int, shape). It is used to search for if this split piece was already generated, and re-use the old one.""" changed = False new_children = [] for piece in compound.childShapes(): if piece.ShapeType == "Compound": subspl = self._splitInCompound(piece, existing_pieces) if subspl is None: new_children.append(piece) else: new_children.append(subspl) changed = True else: new_pieces = self.makeSplitPieces(piece) changed = changed or len(new_pieces)>1 for new_piece in new_pieces: hash = HashableShape_Deep(new_piece) dummy,ex_piece = existing_pieces.get(hash, (None, None)) if ex_piece is not None: new_children.append(ex_piece) changed = True else: new_children.append(new_piece) existing_pieces[hash] = (-1, new_piece) if changed: return Part.Compound(new_children) else: return None
def view_stl(self, dirname): print "make and view stl file" # merge all the faces from all the parts into a compound face_list = [] for part in self.all_group.Group: shape = part.Shape faces = shape.Faces face_list.extend(faces) print 'making part compound' compound = Part.Compound(face_list) stl_file = os.path.join(dirname, 'design.stl') # testing explicite tessellation MESH_DEVIATION=0.1 print "generating mesh" mesh = Mesh.Mesh( compound.tessellate(MESH_DEVIATION) ) print "mesh name:", stl_file mesh.write(stl_file) # view stl command = ['osgviewer', stl_file] pid = subprocess.Popen(command).pid print "spawned osgviewer with pid = " + str(pid)
def make_stl(self, fileroot): print("make the stl file") # merge all the faces from all the parts into a compound face_list = [] for obj in self.doc.Objects: #print(str(obj)) #print(obj.Name, obj.Label) if str(obj) == "<Part::PartFeature>": shape = obj.Shape faces = shape.Faces face_list.extend(faces) print('making part compound:', len(face_list)) compound = Part.Compound(face_list) stl_file = fileroot + ".stl" # testing explicite tessellation MESH_DEVIATION = 0.1 print("generating mesh") mesh = Mesh.Mesh(compound.tessellate(MESH_DEVIATION)) print("mesh name:", stl_file) mesh.write(stl_file)
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 execute(self, obj): wall_shape = Part.makeBox(obj.Length, obj.Width, obj.Height) shapes = [wall_shape] for child in obj.Group: if hasattr(child, 'Shape'): shapes.append(child.Shape) obj.Shape = Part.Compound(shapes)
def view_stl(self, dirname): print("make and view stl file") # merge all the faces from all the parts into a compound face_list = [] for obj in self.doc.Objects: #print(str(obj)) #print(obj.Name, obj.Label) if str(obj) == "<Part::PartFeature>": shape = obj.Shape faces = shape.Faces face_list.extend(faces) # for part in self.all_group.Group: # shape = part.Shape # faces = shape.Faces # face_list.extend(faces) print('making part compound:', len(face_list)) compound = Part.Compound(face_list) stl_file = os.path.join(dirname, 'design.stl') # testing explicite tessellation MESH_DEVIATION = 0.1 print("generating mesh") mesh = Mesh.Mesh(compound.tessellate(MESH_DEVIATION)) print("mesh name:", stl_file) mesh.write(stl_file) # view stl command = ['osgviewer', stl_file] pid = subprocess.Popen(command).pid print("spawned osgviewer with pid = " + str(pid))
def createFaceMidPointmodel(a): '''create an extented model with facepoints''' fs = a.Shape.Faces pts = [] col = [] col = a.Shape.Edges for f in fs: c = f.CenterOfMass pts.append(c) for v in f.Vertexes: p = v.Point pts.append(p) col.append(Part.makeLine(rf(c), rf(p))) # Points.show(Points.Points(pts)) Part.show(Part.Compound(col)) App.ActiveDocument.ActiveObject.ViewObject.hide() App.ActiveDocument.ActiveObject.ViewObject.PointSize = 6. App.ActiveDocument.ActiveObject.ViewObject.LineWidth = 1. App.ActiveDocument.ActiveObject.Label = "Face Extend for " + a.Label return App.ActiveDocument.ActiveObject