import FreeCAD import FreeCADGui as Gui import Part vec = FreeCAD.Vector vec2 = FreeCAD.Base.Vector2d def wire(e1,e2): """ w = wire(edge_1,edge_2) returns a valid wire, or None """ w = Part.Wire([e1,e2]) if w.isValid(): return w else: print("Failed to build wire") return None def longest_edge(e1,e2): """ long_edge = longest_edge(e1,e2) """ if e1.Length > e2.Length: return e1 else: return e2 def longest_segment(e,p): """ long_edge = longest_segment(Edge, Parameter) returns the longest part of edge e split at parameter p """ w = e.split(p) return longest_edge(w.Edges[0],w.Edges[1]) def join_2_edges(e1,e2): d,pts,info = e1.distToShape(e2) if d < 1e-7: # edges are touching for i in info: if (i[0] == "Vertex") and (i[3] == "Vertex"): # Contact type : end to end return (e1,e2) elif (i[0] == "Edge") and (i[3] == "Vertex"): # Contact type : edge to end return (longest_segment(e1,i[2]),e2) elif (i[0] == "Vertex") and (i[3] == "Edge"): # Contact type : end to edge return (e1,longest_segment(e2,i[5])) elif (i[0] == "Edge") and (i[3] == "Edge"): # Contact type : edge to edge return (longest_segment(e1,i[2]),longest_segment(e2,i[5])) else: # No contact : must add a join curve for pt,i in zip(pts,info): l = Part.makeLine(pt[0],pt[1]) if (i[0] == "Vertex") and (i[3] == "Vertex"): # Contact type : end to end return (e1,l,e2) elif (i[0] == "Edge") and (i[3] == "Vertex"): # Contact type : edge to end return (longest_segment(e1,i[2]),l,e2) elif (i[0] == "Vertex") and (i[3] == "Edge"): # Contact type : end to edge return (e1,l,longest_segment(e2,i[5])) elif (i[0] == "Edge") and (i[3] == "Edge"): # Contact type : edge to edge return (longest_segment(e1,i[2]),l,longest_segment(e2,i[5])) def join_multi_edges(edgelist,closed=False): good_edges = list() last = edgelist[0] remaining = edgelist[1:] res = [] while len(remaining) > 0: rejected = list() closest_dist = 1e50 closest_edge = None # closest_pts = None # closest_info = None for e in remaining: d,p,i = e.distToShape(last) if closest_dist > d: closest_dist = d if closest_edge: rejected.append(closest_edge) closest_edge = e # closest_pts = p # closest_info = i else: rejected.append(e) res = join_2_edges(last,closest_edge) #print(last.distToShape(closest_edge)) last = res[-1] good_edges.extend(res[:-1]) remaining = rejected if res: good_edges.append(res[-1]) se = Part.sortEdges(good_edges) wires = list() for group in se: print("Wire has %d edges"%len(group)) wires.append(Part.Wire(group)) if closed: for w in wires: if not w.isClosed(): ov = w.OrderedVertexes d,p,i = ov[0].distToShape(ov[-1]) w.add(Part.makeLine(p[0][0],p[0][1])) return Part.Compound(wires) def run(closed=False): s = Gui.Selection.getSelection() ori_edges = s[0].Shape.Edges return join_multi_edges(ori_edges, closed) def show(closed = False): Part.show(run(closed))