def split_open_wire(wire, newPoint, edgeIndex): wire1Points = [] wire2Points = [] for index, point in enumerate(wire.Points): if index == edgeIndex: wire1Points.append(wire.Placement.inverse().multVec(newPoint)) wire2Points.append(newPoint) wire2Points.append(wire.Placement.multVec(point)) elif index < edgeIndex: wire1Points.append(point) elif index > edgeIndex: wire2Points.append(wire.Placement.multVec(point)) wire.Points = wire1Points make_wire.make_wire(wire2Points, placement=wire.Placement)
def make_line(first_param, last_param=None): """makeLine(first_param, p2) Creates a line from 2 points or from a given object. Parameters ---------- first_param : Base.Vector -> First point of the line (if p2 == None) Part.LineSegment -> Line is created from the given Linesegment Shape -> Line is created from the give Shape last_param : Base.Vector Second point of the line, if not set the function evaluates the first_param to look for a Part.LineSegment or a Shape """ if last_param: p1 = first_param p2 = last_param else: if hasattr(first_param, "StartPoint") and hasattr(first_param, "EndPoint"): p2 = first_param.EndPoint p1 = first_param.StartPoint elif hasattr(p1,"Vertexes"): p2 = first_param.Vertexes[-1].Point p1 = first_param.Vertexes[0].Point else: _err = "Unable to create a line from the given parameters" App.Console.PrintError(_err + "\n") return obj = make_wire([p1,p2]) return obj
def draftify_shape(shape): nobj = None if DraftGeomUtils.hasCurves(shape): if (len(shape.Edges) == 1): edge = shape.Edges[0] edge_type = DraftGeomUtils.geomType(edge) if edge_type == "Circle": if edge.isClosed(): nobj = make_circle.make_circle(edge) else: first_parameter = edge.FirstParameter last_parameter = edge.LastParameter points = [ edge.Curve.value(first_parameter), edge.Curve.value( (first_parameter + last_parameter) / 2), edge.Curve.value(last_parameter) ] nobj = make_arc_3points.make_arc_3points(points) # TODO: take into consideration trimmed curves and capture the specific # type of BSpline and Bezier that can be converted to a draft object. # elif edge_type == "BSplineCurve": # knots = [edge.Curve.value(p) for p in edge.Curve.getKnots()] # nobj = make_bspline.make_bspline(knots, closed=edge.isClosed()) # elif edge_type == "BezierCurve": # nobj = make_bezcurve.make_bezcurve(edge.Curve.getPoles(), # closed=edge.isClosed()) else: nobj = make_wire.make_wire(shape) return nobj
def split_closed_wire(wire, edgeIndex): wire.Closed = False if edgeIndex == len(wire.Points): make_wire.make_wire([ wire.Placement.multVec(wire.Points[0]), wire.Placement.multVec(wire.Points[-1]) ], placement=wire.Placement) else: make_wire.make_wire([ wire.Placement.multVec(wire.Points[edgeIndex - 1]), wire.Placement.multVec(wire.Points[edgeIndex]) ], placement=wire.Placement) wire.Points = list(reversed(wire.Points[0:edgeIndex])) + list( reversed(wire.Points[edgeIndex:]))
def makeSketchFace(obj): """Make a Draft Wire closed and filled out of a sketch.""" newobj = make_wire.make_wire(obj.Shape, closed=True) if newobj: newobj.Base = obj add_list.append(newobj) if App.GuiUp: obj.ViewObject.Visibility = False return newobj return None
def draftify(objectslist, makeblock=False, delete=True): """draftify(objectslist,[makeblock],[delete]) Turn each object of the given list (objectslist can also be a single object) into a Draft parametric wire. TODO: support more objects Parameters ---------- objectslist : makeblock : bool If makeblock is True, multiple objects will be grouped in a block. delete : bool If delete = False, old objects are not deleted """ import Part import DraftGeomUtils if not isinstance(objectslist, list): objectslist = [objectslist] newobjlist = [] for obj in objectslist: if hasattr(obj, 'Shape'): for cluster in Part.getSortedClusters(obj.Shape.Edges): w = Part.Wire(cluster) if DraftGeomUtils.hasCurves(w): if (len(w.Edges) == 1) and (DraftGeomUtils.geomType( w.Edges[0]) == "Circle"): nobj = make_circle.make_circle(w.Edges[0]) else: nobj = App.ActiveDocument.addObject( "Part::Feature", obj.Name) nobj.Shape = w else: nobj = make_wire.make_wire(w) newobjlist.append(nobj) gui_utils.format_object(nobj, obj) # sketches are always in wireframe mode. In Draft we don't like that! if App.GuiUp: nobj.ViewObject.DisplayMode = "Flat Lines" if delete: App.ActiveDocument.removeObject(obj.Name) if makeblock: return make_block.make_block(newobjlist) else: if len(newobjlist) == 1: return newobjlist[0] return newobjlist
def joinFaces(objectslist, coplanarity=False, checked=False): """Make one big face from selected objects, if possible.""" faces = [] for obj in objectslist: faces.extend(obj.Shape.Faces) # check coplanarity if needed if not checked: coplanarity = DraftGeomUtils.is_coplanar(faces, 1e-3) if not coplanarity: _err(_tr("Faces must be coplanar to be refined")) return None # fuse faces fuse_face = faces.pop(0) for face in faces: fuse_face = fuse_face.fuse(face) face = DraftGeomUtils.concatenate(fuse_face) # to prevent create new object if concatenate fails if face.isEqual(fuse_face): face = None if face: # several coplanar and non-curved faces, # they can become a Draft Wire if (not DraftGeomUtils.hasCurves(face) and len(face.Wires) == 1): newobj = make_wire.make_wire(face.Wires[0], closed=True, face=True) # if not possible, we do a non-parametric union else: newobj = doc.addObject("Part::Feature", "Union") newobj.Shape = face add_list.append(newobj) delete_list.extend(objectslist) return newobj return None
def joinFaces(objectslist): """Make one big face from selected objects, if possible.""" faces = [] for obj in objectslist: faces.extend(obj.Shape.Faces) u = faces.pop(0) for f in faces: u = u.fuse(f) if DraftGeomUtils.isCoplanar(faces): u = DraftGeomUtils.concatenate(u) if not DraftGeomUtils.hasCurves(u): # several coplanar and non-curved faces, # they can become a Draft Wire newobj = make_wire.make_wire(u.Wires[0], closed=True, face=True) else: # if not possible, we do a non-parametric union newobj = doc.addObject("Part::Feature", "Union") newobj.Shape = u add_list.append(newobj) delete_list.extend(objectslist) return newobj return None
def offset(obj, delta, copy=False, bind=False, sym=False, occ=False): """offset(object,delta,[copymode],[bind]) Offset the given wire by applying the given delta Vector to its first vertex. Parameters ---------- obj : delta : Base.Vector or list of Base.Vector If offsetting a BSpline, the delta must not be a Vector but a list of Vectors, one for each node of the spline. copy : bool If copymode is True, another object is created, otherwise the same object gets offsetted. copy : bool If bind is True, and provided the wire is open, the original and the offset wires will be bound by their endpoints, forming a face. sym : bool if sym is True, bind must be true too, and the offset is made on both sides, the total width being the given delta length. """ import Part import DraftGeomUtils newwire = None delete = None if utils.get_type(obj).startswith("Part::") or utils.get_type( obj).startswith("Sketcher::"): copy = True print( "the offset tool is currently unable to offset a non-Draft object directly - Creating a copy" ) def getRect(p, obj): """returns length,height,placement""" pl = obj.Placement.copy() pl.Base = p[0] diag = p[2].sub(p[0]) bb = p[1].sub(p[0]) bh = p[3].sub(p[0]) nb = DraftVecUtils.project(diag, bb) nh = DraftVecUtils.project(diag, bh) if obj.Length.Value < 0: l = -nb.Length else: l = nb.Length if obj.Height.Value < 0: h = -nh.Length else: h = nh.Length return l, h, pl def getRadius(obj, delta): """returns a new radius for a regular polygon""" an = math.pi / obj.FacesNumber nr = DraftVecUtils.rotate(delta, -an) nr.multiply(1 / math.cos(an)) nr = obj.Shape.Vertexes[0].Point.add(nr) nr = nr.sub(obj.Placement.Base) nr = nr.Length if obj.DrawMode == "inscribed": return nr else: return nr * math.cos(math.pi / obj.FacesNumber) newwire = None if utils.get_type(obj) == "Circle": pass elif utils.get_type(obj) == "BSpline": pass else: if sym: d1 = App.Vector(delta).multiply(0.5) d2 = d1.negative() n1 = DraftGeomUtils.offsetWire(obj.Shape, d1) n2 = DraftGeomUtils.offsetWire(obj.Shape, d2) else: if isinstance(delta, float) and (len(obj.Shape.Edges) == 1): # circle c = obj.Shape.Edges[0].Curve nc = Part.Circle(c.Center, c.Axis, delta) if len(obj.Shape.Vertexes) > 1: nc = Part.ArcOfCircle(nc, obj.Shape.Edges[0].FirstParameter, obj.Shape.Edges[0].LastParameter) newwire = Part.Wire(nc.toShape()) p = [] else: newwire = DraftGeomUtils.offsetWire(obj.Shape, delta) if DraftGeomUtils.hasCurves(newwire) and copy: p = [] else: p = DraftGeomUtils.getVerts(newwire) if occ: newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") newobj.Shape = DraftGeomUtils.offsetWire(obj.Shape, delta, occ=True) gui_utils.formatObject(newobj, obj) if not copy: delete = obj.Name elif bind: if not DraftGeomUtils.isReallyClosed(obj.Shape): if sym: s1 = n1 s2 = n2 else: s1 = obj.Shape s2 = newwire if s1 and s2: w1 = s1.Edges w2 = s2.Edges w3 = Part.LineSegment(s1.Vertexes[0].Point, s2.Vertexes[0].Point).toShape() w4 = Part.LineSegment(s1.Vertexes[-1].Point, s2.Vertexes[-1].Point).toShape() newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") newobj.Shape = Part.Face(Part.Wire(w1 + [w3] + w2 + [w4])) else: print("Draft.offset: Unable to bind wires") else: newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") newobj.Shape = Part.Face(obj.Shape.Wires[0]) if not copy: delete = obj.Name elif copy: newobj = None if sym: return None if utils.get_type(obj) == "Wire": if p: newobj = make_wire(p) newobj.Closed = obj.Closed elif newwire: newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") newobj.Shape = newwire else: print("Draft.offset: Unable to duplicate this object") elif utils.get_type(obj) == "Rectangle": if p: length, height, plac = getRect(p, obj) newobj = make_rectangle(length, height, plac) elif newwire: newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") newobj.Shape = newwire else: print("Draft.offset: Unable to duplicate this object") elif utils.get_type(obj) == "Circle": pl = obj.Placement newobj = make_circle(delta) newobj.FirstAngle = obj.FirstAngle newobj.LastAngle = obj.LastAngle newobj.Placement = pl elif utils.get_type(obj) == "Polygon": pl = obj.Placement newobj = make_polygon(obj.FacesNumber) newobj.Radius = getRadius(obj, delta) newobj.DrawMode = obj.DrawMode newobj.Placement = pl elif utils.get_type(obj) == "BSpline": newobj = make_bspline(delta) newobj.Closed = obj.Closed else: # try to offset anyway try: if p: newobj = make_wire(p) newobj.Closed = obj.Shape.isClosed() except Part.OCCError: pass if (not newobj) and newwire: newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") newobj.Shape = newwire if not newobj: print("Draft.offset: Unable to create an offset") if newobj: gui_utils.formatObject(newobj, obj) else: newobj = None if sym: return None if utils.get_type(obj) == "Wire": if obj.Base or obj.Tool: App.Console.PrintWarning("Warning: object history removed\n") obj.Base = None obj.Tool = None obj.Placement = App.Placement( ) # p points are in the global coordinate system obj.Points = p elif utils.get_type(obj) == "BSpline": #print(delta) obj.Points = delta #print("done") elif utils.get_type(obj) == "Rectangle": length, height, plac = getRect(p, obj) obj.Placement = plac obj.Length = length obj.Height = height elif utils.get_type(obj) == "Circle": obj.Radius = delta elif utils.get_type(obj) == "Polygon": obj.Radius = getRadius(obj, delta) elif utils.get_type(obj) == 'Part': print("unsupported object") # TODO newobj = obj if copy and utils.get_param("selectBaseObjects", False): gui_utils.select(newobj) else: gui_utils.select(obj) if delete: App.ActiveDocument.removeObject(delete) return newobj