def test65(self): '''Verify splitEdgeAt.''' # split a line segment e = PathGeom.splitEdgeAt( Part.Edge(Part.LineSegment(Vector(), Vector(2, 4, 6))), Vector(1, 2, 3)) self.assertLine(e[0], Vector(), Vector(1, 2, 3)) self.assertLine(e[1], Vector(1, 2, 3), Vector(2, 4, 6)) # split an arc p1 = Vector(10, -10, 1) p2 = Vector(0, 0, 1) p3 = Vector(10, 10, 1) arc = Part.Edge(Part.Arc(p1, p2, p3)) e = PathGeom.splitEdgeAt(arc, p2) o = 10 * math.sin(math.pi / 4) p12 = Vector(10 - o, -o, 1) p23 = Vector(10 - o, +o, 1) self.assertCurve(e[0], p1, p12, p2) self.assertCurve(e[1], p2, p23, p3) # split a helix p1 = Vector(10, -10, 0) p2 = Vector(0, 0, 5) p3 = Vector(10, 10, 10) h = PathGeom.arcToHelix(arc, 0, 10) self.assertCurve(h, p1, p2, p3) e = PathGeom.splitEdgeAt(h, p2) o = 10 * math.sin(math.pi / 4) p12 = Vector(10 - o, -o, 2.5) p23 = Vector(10 - o, +o, 7.5) self.assertCurve(e[0], p1, p12, p2) self.assertCurve(e[1], p2, p23, p3)
def extendWire(feature, wire, length): '''extendWire(wire, length) ... return a closed Wire which extends wire by length''' try: off2D = wire.makeOffset2D(length) except Exception as e: msg = "\nThe selected face cannot be used.\nYou must select the bottom face of the pocket area.\nextendWire() in PathPocketShape.py" PathLog.error(e) PathLog.error(msg) return False else: endPts = endPoints(wire) edges = [ e for e in off2D.Edges if Part.Circle != type(e.Curve) or not includesPoint(e.Curve.Center, endPts) ] wires = [Part.Wire(e) for e in Part.sortEdges(edges)] offset = selectOffsetWire(feature, wires) ePts = endPoints(offset) l0 = (ePts[0] - endPts[0]).Length l1 = (ePts[1] - endPts[0]).Length edges = wire.Edges if l0 < l1: edges.append(Part.Edge(Part.LineSegment(endPts[0], ePts[0]))) edges.extend(offset.Edges) edges.append(Part.Edge(Part.LineSegment(endPts[1], ePts[1]))) else: edges.append(Part.Edge(Part.LineSegment(endPts[1], ePts[0]))) edges.extend(offset.Edges) edges.append(Part.Edge(Part.LineSegment(endPts[0], ePts[1]))) return Part.Wire(edges)
def discretize(self): p1 = [] p2 = [] n = len(self.profiles) - 1 #gr = int(1.0 * self.railSamples / n) + 1 #self.railSamples = gr * n for i in range(self.railSamples): pts1 = [] pts2 = [] t = 1.0 * n * i / (self.railSamples - 1) # Get the good matrices from the birail t1 = self.birail.paramCurves[0].value(t).y t2 = self.birail.paramCurves[1].value(t).y m1 = self.birail.matrixAt(t1,0) m2 = self.birail.matrixAt(t2,1) for ri in range(self.profileSamples): # Pick a point on interpolating curves e1 = Part.Edge(self.interpoCurves[0][ri]) pt1 = e1.valueAt(t) #u1) e2 = Part.Edge(self.interpoCurves[1][ri]) pt2 = e2.valueAt(t) #u2) v = FreeCAD.Vector(self.transvec) v.multiply(- t * self.fac) pts1.append(m1.multiply(pt1.add(v))) pts2.append(m2.multiply(pt2.add(v))) p1.append(pts1) p2.append(pts2) self.results = (p1,p2)
def extendWire(feature, wire, length): '''extendWire(wire, length) ... return a closed Wire which extends wire by length''' PathLog.track(length) if length and length != 0: off2D = wire.makeOffset2D(length) endPts = endPoints(wire) if endPts: edges = [e for e in off2D.Edges if Part.Circle != type(e.Curve) or not includesPoint(e.Curve.Center, endPts)] wires = [Part.Wire(e) for e in Part.sortEdges(edges)] offset = selectOffsetWire(feature, wires) ePts = endPoints(offset) if ePts and len(ePts) > 1: l0 = (ePts[0] - endPts[0]).Length l1 = (ePts[1] - endPts[0]).Length edges = wire.Edges if l0 < l1: edges.append(Part.Edge(Part.LineSegment(endPts[0], ePts[0]))) edges.extend(offset.Edges) edges.append(Part.Edge(Part.LineSegment(endPts[1], ePts[1]))) else: edges.append(Part.Edge(Part.LineSegment(endPts[1], ePts[0]))) edges.extend(offset.Edges) edges.append(Part.Edge(Part.LineSegment(endPts[0], ePts[1]))) return Part.Wire(edges) return None
def edgesForCommands(cmds, startPt): edges = [] lastPt = startPt for cmd in cmds: if cmd.Name in movecommands: pt = pointFromCommand(cmd, lastPt) if cmd.Name in movestraight: edges.append(Part.Edge(Part.LineSegment(lastPt, pt))) elif cmd.Name in movearc: center = lastPt + pointFromCommand(cmd, FreeCAD.Vector( 0, 0, 0), 'I', 'J', 'K') A = lastPt - center B = pt - center d = -B.x * A.y + B.y * A.x if d == 0: # we're dealing with half a circle here angle = getAngle(A) + math.pi / 2 if cmd.Name in movecw: angle -= math.pi else: C = A + B angle = getAngle(C) R = (lastPt - center).Length ptm = center + FreeCAD.Vector(math.cos(angle), math.sin(angle), 0) * R edges.append(Part.Edge(Part.Arc(lastPt, ptm, pt))) lastPt = pt return edges
def extendWire(feature, wire, length): '''extendWire(wire, length) ... return a closed Wire which extends wire by length''' try: off2D = wire.makeOffset2D(length) except Exception as e: PathLog.error("extendWire(): wire.makeOffset2D()") PathLog.error(e) return False else: endPts = endPoints(wire) edges = [e for e in off2D.Edges if not isinstance(e.Curve, Part.Circle) or not includesPoint(e.Curve.Center, endPts)] wires = [Part.Wire(e) for e in Part.sortEdges(edges)] offset = selectOffsetWire(feature, wires) ePts = endPoints(offset) try: l0 = (ePts[0] - endPts[0]).Length except Exception as ee: PathLog.error("extendWire(): (ePts[0] - endPts[0]).Length") PathLog.error(ee) return False else: l1 = (ePts[1] - endPts[0]).Length edges = wire.Edges if l0 < l1: edges.append(Part.Edge(Part.LineSegment(endPts[0], ePts[0]))) edges.extend(offset.Edges) edges.append(Part.Edge(Part.LineSegment(endPts[1], ePts[1]))) else: edges.append(Part.Edge(Part.LineSegment(endPts[1], ePts[0]))) edges.extend(offset.Edges) edges.append(Part.Edge(Part.LineSegment(endPts[0], ePts[1]))) return Part.Wire(edges)
def test65(self): """Verify splitEdgeAt.""" e = PathGeom.splitEdgeAt(Part.Edge(Part.LineSegment(Vector(), Vector(2, 4, 6))), Vector(1, 2, 3)) self.assertLine(e[0], Vector(), Vector(1,2,3)) self.assertLine(e[1], Vector(1,2,3), Vector(2,4,6)) # split an arc p1 = Vector(10,-10,1) p2 = Vector(0,0,1) p3 = Vector(10,10,1) arc = Part.Edge(Part.Arc(p1, p2, p3)) e = PathGeom.splitEdgeAt(arc, p2) o = 10*math.sin(math.pi/4) p12 = Vector(10 - o, -o, 1) p23 = Vector(10 - o, +o, 1) self.assertCurve(e[0], p1, p12, p2) self.assertCurve(e[1], p2, p23, p3) # split a helix p1 = Vector(10,-10,0) p2 = Vector(0,0,5) p3 = Vector(10,10,10) h = PathGeom.arcToHelix(arc, 0, 10) self.assertCurve(h, p1, p2, p3) e = PathGeom.splitEdgeAt(h, p2) o = 10*math.sin(math.pi/4) p12 = Vector(10 - o, -o, 2.5) p23 = Vector(10 - o, +o, 7.5) pf = e[0].valueAt((e[0].FirstParameter + e[0].LastParameter)/2) pl = e[1].valueAt((e[1].FirstParameter + e[1].LastParameter)/2) self.assertCurve(e[0], p1, p12, p2) self.assertCurve(e[1], p2, p23, p3)
def splitEdgeAt(cls, edge, pt): """(edge, pt) Returns a list of 2 edges, forming the original edge split at the given point. The results are undefined if the Vector representing the point is not part of the edge.""" # I could not get the OCC parameterAt and split to work ... # pt HAS to be on the edge, otherwise the results are undefined p1 = edge.valueAt(edge.FirstParameter) p2 = pt p3 = edge.valueAt(edge.LastParameter) edges = [] if type(edge.Curve) == Part.Line or type( edge.Curve) == Part.LineSegment: # it's a line return [ Part.Edge(Part.LineSegment(p1, p2)), Part.Edge(Part.LineSegment(p2, p3)) ] elif type(edge.Curve) == Part.Circle: # it's an arc return cls.splitArcAt(edge, pt) else: # it's a helix arc = cls.helixToArc(edge, 0) aes = cls.splitArcAt(arc, Vector(pt.x, pt.y, 0)) return [ cls.arcToHelix(aes[0], p1.z, p2.z), cls.arcToHelix(aes[1], p2.z, p3.z) ]
def cleanedges(splines, precision): '''cleanedges([splines],precision). Convert BSpline curves, Beziers, to arcs that can be used for cnc paths. Returns Lines as is. Filters Circle and Arcs for over 180 degrees. Discretizes Ellipses. Ignores other geometry. ''' edges = [] for spline in splines: if geomType(spline) == "BSplineCurve": arcs = spline.Curve.toBiArcs(precision) for i in arcs: edges.append(Part.Edge(i)) elif geomType(spline) == "BezierCurve": newspline = spline.Curve.toBSpline() arcs = newspline.toBiArcs(precision) for i in arcs: edges.append(Part.Edge(i)) elif geomType(spline) == "Ellipse": edges = curvetowire(spline, 1.0) # fixme hardcoded value elif geomType(spline) == "Circle": arcs = filterArcs(spline) for i in arcs: edges.append(Part.Edge(i)) elif geomType(spline) == "Line": edges.append(spline) elif geomType(spline) == "LineSegment": edges.append(spline) else: pass return edges
def loopWires(self, wires): for i in wires: for j in i.Edges: if j.Curve.__class__.__name__ == "Line": x1 = round(j.Vertexes[0].X, 2) y1 = round(j.Vertexes[0].Y, 2) x2 = round(j.Vertexes[1].X, 2) y2 = round(j.Vertexes[1].Y, 2) if not [x1, y1, x2, y2] in self.dataOut["lines"] or not [ x2, y2, x1, y1 ] in self.dataOut["lines"]: self.dataOut["lines"].append([x1, y1, x2, y2]) self.exportClass.addLine(x1, y1, x2, y2) else: continue elif j.Curve.__class__.__name__ == "BSplineCurve": newData = j.Curve.toBiArcs(0.001) newWires = [Part.Wire([Part.Edge(p) for p in newData])] self.loopWires(newWires) elif j.Curve.__class__.__name__ == "Hyperbola": newData = j.toNurbs() newWires = [ Part.Wire([Part.Edge(p) for p in newData.Edges]) ] self.loopWires(newWires) else: # circle/arc c = j.Curve xs = round(c.Center.x, 2) ys = round(c.Center.y, 2) r = round(c.Radius, 2) if (round(j.FirstParameter, 2) == 6.28 and j.LastParameter == 0) or (j.FirstParameter == 0 and round( j.LastParameter, 2) == 6.28): # circle if not [xs, ys, r] in self.dataOut["circles"]: self.dataOut["circles"].append([xs, ys, r]) self.exportClass.addCircle(xs, ys, r) else: # arc x1 = round(j.Vertexes[0].X, 2) y1 = round(j.Vertexes[0].Y, 2) x2 = round(j.Vertexes[1].X, 2) y2 = round(j.Vertexes[1].Y, 2) if self.exportClass.programName == 'eagle': [curve, start, stop] = edgeGetArcAngle(j) else: start = degrees(j.FirstParameter) stop = degrees(j.LastParameter) curve = start - stop if not [x1, y1, x2, y2, curve, xs, ys, r, start, stop ] in self.dataOut["arcs"]: self.dataOut["arcs"].append([ x1, y1, x2, y2, curve, xs, ys, r, start, stop ]) self.exportClass.addArc(x1, y1, x2, y2, curve, xs, ys, r, start, stop)
def flipEdge(edge): '''flipEdge(edge) Flips given edge around so the new Vertexes[0] was the old Vertexes[-1] and vice versa, without changing the shape. Currently only lines, line segments, circles and arcs are supported.''' if Part.Line == type(edge.Curve) and not edge.Vertexes: return Part.Edge( Part.Line(edge.valueAt(edge.LastParameter), edge.valueAt(edge.FirstParameter))) elif Part.Line == type(edge.Curve) or Part.LineSegment == type(edge.Curve): return Part.Edge( Part.LineSegment(edge.Vertexes[-1].Point, edge.Vertexes[0].Point)) elif Part.Circle == type(edge.Curve): # Create an inverted circle circle = Part.Circle(edge.Curve.Center, -edge.Curve.Axis, edge.Curve.Radius) # Rotate the circle appropriately so it starts at edge.valueAt(edge.LastParameter) circle.rotate( FreeCAD.Placement( circle.Center, circle.Axis, 180 - math.degrees(edge.LastParameter + edge.Curve.AngleXU))) # Now the edge always starts at 0 and LastParameter is the value range arc = Part.Edge(circle, 0, edge.LastParameter - edge.FirstParameter) return arc elif type(edge.Curve) in [Part.BSplineCurve, Part.BezierCurve]: if type(edge.Curve) == Part.BSplineCurve: spline = edge.Curve else: spline = edge.Curve.toBSpline() mults = spline.getMultiplicities() weights = spline.getWeights() knots = spline.getKnots() poles = spline.getPoles() perio = spline.isPeriodic() ratio = spline.isRational() degree = spline.Degree ma = max(knots) mi = min(knots) knots = [ma + mi - k for k in knots] mults.reverse() weights.reverse() poles.reverse() knots.reverse() flipped = Part.BSplineCurve() flipped.buildFromPolesMultsKnots(poles, mults, knots, perio, degree, weights, ratio) return Part.Edge(flipped) global OddsAndEnds # pylint: disable=global-statement OddsAndEnds.append(edge) PathLog.warning( translate('PathGeom', "%s not support for flipping") % type(edge.Curve))
def test75(self): '''Flip a B-spline''' spline = Part.BSplineCurve() spline.interpolate([Vector(1,2,3), Vector(-3,0,7), Vector(-3,1,9), Vector(1, 3, 5)]) edge = Part.Edge(spline) self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) edge = Part.Edge(Part.BSplineCurve([Vector(-8,4,0), Vector(1,-5,0), Vector(5,11,0), Vector(12,-5,0)], weights=[2,3,5,7])) self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge))
def makeWire(pts): edges = [] first = pts[0] last = pts[0] for p in pts[1:]: edges.append(Part.Edge(Part.LineSegment(last, p))) last = p edges.append(Part.Edge(Part.LineSegment(last, first))) return Part.Wire(edges)
def test71(self): '''Flip a line segment.''' edge = Part.Edge(Part.LineSegment(Vector(0, 0, 0), Vector(3, 2, 1))) self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) edge = Part.Edge(Part.LineSegment(Vector(4, 2, 1), Vector(-3, -7, 9))) self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) edge = Part.makeLine(Vector(1, 0, 3), Vector(3, 2, 1)) self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge))
def edgeForCmd(cls, cmd, startPoint): """(cmd, startPoint). Returns an Edge representing the given command, assuming a given startPoint.""" endPoint = cls.commandEndPoint(cmd, startPoint) if (cmd.Name in cls.CmdMoveStraight) or (cmd.Name in cls.CmdMoveRapid): if cls.pointsCoincide(startPoint, endPoint): return None return Part.Edge(Part.LineSegment(startPoint, endPoint)) if cmd.Name in cls.CmdMoveArc: center = startPoint + cls.commandEndPoint(cmd, Vector(0, 0, 0), 'I', 'J', 'K') A = cls.xy(startPoint - center) B = cls.xy(endPoint - center) d = -B.x * A.y + B.y * A.x if d == 0: # we're dealing with half a circle here angle = cls.getAngle(A) + math.pi / 2 if cmd.Name in cls.CmdMoveCW: angle -= math.pi else: C = A + B angle = cls.getAngle(C) R = A.Length #print("arc: p1=(%.2f, %.2f) p2=(%.2f, %.2f) -> center=(%.2f, %.2f)" % (startPoint.x, startPoint.y, endPoint.x, endPoint.y, center.x, center.y)) #print("arc: A=(%.2f, %.2f) B=(%.2f, %.2f) -> d=%.2f" % (A.x, A.y, B.x, B.y, d)) #print("arc: R=%.2f angle=%.2f" % (R, angle/math.pi)) if startPoint.z == endPoint.z: midPoint = center + FreeCAD.Vector(math.cos(angle), math.sin(angle), 0) * R return Part.Edge(Part.Arc(startPoint, midPoint, endPoint)) # It's a Helix #print('angle: A=%.2f B=%.2f' % (cls.getAngle(A)/math.pi, cls.getAngle(B)/math.pi)) if cmd.Name in cls.CmdMoveCW: cw = True else: cw = False angle = cls.diffAngle(cls.getAngle(A), cls.getAngle(B), 'CW' if cw else 'CCW') height = endPoint.z - startPoint.z pitch = height * math.fabs(2 * math.pi / angle) if angle > 0: cw = not cw #print("Helix: R=%.2f h=%.2f angle=%.2f pitch=%.2f" % (R, height, angle/math.pi, pitch)) helix = Part.makeHelix(pitch, height, R, 0, not cw) helix.rotate(Vector(), Vector(0, 0, 1), 180 * cls.getAngle(A) / math.pi) e = helix.Edges[0] helix.translate(startPoint - e.valueAt(e.FirstParameter)) return helix.Edges[0] return None
def edgeForCmd(cmd, startPoint): """edgeForCmd(cmd, startPoint). Returns an Edge representing the given command, assuming a given startPoint.""" endPoint = commandEndPoint(cmd, startPoint) if (cmd.Name in CmdMoveStraight) or (cmd.Name in CmdMoveRapid): if pointsCoincide(startPoint, endPoint): return None return Part.Edge(Part.LineSegment(startPoint, endPoint)) if cmd.Name in CmdMoveArc: center = startPoint + commandEndPoint(cmd, Vector(0,0,0), 'I', 'J', 'K') A = xy(startPoint - center) B = xy(endPoint - center) d = -B.x * A.y + B.y * A.x if isRoughly(d, 0, 0.005): PathLog.debug("Half circle arc at: (%.2f, %.2f, %.2f)" % (center.x, center.y, center.z)) # we're dealing with half a circle here angle = getAngle(A) + math.pi/2 if cmd.Name in CmdMoveCW: angle -= math.pi else: C = A + B angle = getAngle(C) PathLog.debug("Arc (%8f) at: (%.2f, %.2f, %.2f) -> angle=%f" % (d, center.x, center.y, center.z, angle / math.pi)) R = A.Length PathLog.debug("arc: p1=(%.2f, %.2f) p2=(%.2f, %.2f) -> center=(%.2f, %.2f)" % (startPoint.x, startPoint.y, endPoint.x, endPoint.y, center.x, center.y)) PathLog.debug("arc: A=(%.2f, %.2f) B=(%.2f, %.2f) -> d=%.2f" % (A.x, A.y, B.x, B.y, d)) PathLog.debug("arc: R=%.2f angle=%.2f" % (R, angle/math.pi)) if isRoughly(startPoint.z, endPoint.z): midPoint = center + Vector(math.cos(angle), math.sin(angle), 0) * R PathLog.debug("arc: (%.2f, %.2f) -> (%.2f, %.2f) -> (%.2f, %.2f)" % (startPoint.x, startPoint.y, midPoint.x, midPoint.y, endPoint.x, endPoint.y)) return Part.Edge(Part.Arc(startPoint, midPoint, endPoint)) # It's a Helix #print('angle: A=%.2f B=%.2f' % (getAngle(A)/math.pi, getAngle(B)/math.pi)) if cmd.Name in CmdMoveCW: cw = True else: cw = False angle = diffAngle(getAngle(A), getAngle(B), 'CW' if cw else 'CCW') height = endPoint.z - startPoint.z pitch = height * math.fabs(2 * math.pi / angle) if angle > 0: cw = not cw #print("Helix: R=%.2f h=%.2f angle=%.2f pitch=%.2f" % (R, height, angle/math.pi, pitch)) helix = Part.makeHelix(pitch, height, R, 0, not cw) helix.rotate(Vector(), Vector(0,0,1), 180 * getAngle(A) / math.pi) e = helix.Edges[0] helix.translate(startPoint - e.valueAt(e.FirstParameter)) return helix.Edges[0] return None
def extendEdge(self, feature, e0, direction): if isinstance(e0.Curve, Part.Line) or isinstance(e0.Curve, Part.LineSegment): e2 = e0.copy() off = self.length.Value * direction e2.translate(off) e2 = PathGeom.flipEdge(e2) e1 = Part.Edge(Part.LineSegment(e0.valueAt(e0.LastParameter), e2.valueAt(e2.FirstParameter))) e3 = Part.Edge(Part.LineSegment(e2.valueAt(e2.LastParameter), e0.valueAt(e0.FirstParameter))) wire = Part.Wire([e0, e1, e2, e3]) self.wire = wire return wire return extendWire(feature, Part.Wire([e0]), self.length.Value)
def __init__(self, ruledSurf): self.ruled = ruledSurf s = ruledSurf.Surface v0 = ruledSurf.ParameterRange[2] v1 = ruledSurf.ParameterRange[3] c1 = s.vIso(v0) c2 = s.vIso(v1) self.rails = (Part.Edge(c1),Part.Edge(c2)) self.normTan = False self.normBin = False self.normNor = True self.paramCurves = []
def validate(self): c2d = None if (not self.edge == None) and (not self.face == None): c2d = self.face.curveOnSurface(self.edge) if not isinstance(c2d, tuple): # print("curveOnSurface failed") try: newface = self.face.Surface.toShape() newedges = newface.project([self.edge]).Edges e0 = newedges[0] c2d = newface.curveOnSurface(e0) # if projection created several edges, # we need to join them into a single BSpline curve. if len(newedges) > 1: c = c2d[0].toBSpline(c2d[1], c2d[2]) for e in newedges[1:]: c2d, fp, lp = newface.curveOnSurface(e) bs = c2d.toBSpline(fp, lp) c.join(bs) c2d = [c, c.FirstParameter, c.LastParameter] print("CurveOnSurface projection fallback : OK.") except Part.OCCError: print("CurveOnSurface projection fallback : Failed.") if isinstance(c2d, tuple): self.curve2D = c2d[0] self.firstParameter = c2d[1] self.lastParameter = c2d[2] self.edgeOnFace = self.curve2D.toShape(self.face, self.firstParameter, self.lastParameter) if isinstance(self.edgeOnFace, Part.Edge): self.isValid = True else: self.isValid = False self.edgeOnFace = Part.Edge(self.edge.Curve, self.firstParameter, self.lastParameter) else: e = self.face.project([self.edge]).Edges[0] self.isValid = False self.firstParameter = self.edge.FirstParameter self.lastParameter = self.edge.LastParameter self.edgeOnFace = Part.Edge(self.edge.Curve, self.firstParameter, self.lastParameter) if self._closed: curve = self.edgeOnFace.Curve.copy() curve.setPeriodic() self.edgeOnFace = curve.toShape() print("edgeOnFace is periodic : %s" % curve.isPeriodic()) # self.edgeOnFace.Placement = self.face.Placement return (self.isValid)
def addPointToCurve(self,point,info=None): import Part if not (Draft.getType(self.obj) in ["BSpline","BezCurve"]): return pts = self.obj.Points if Draft.getType(self.obj) == "BezCurve": if not info['Component'].startswith('Edge'): return # clicked control point edgeindex = int(info['Component'].lstrip('Edge'))-1 wire=self.obj.Shape.Wires[0] bz=wire.Edges[edgeindex].Curve param=bz.parameter(point) seg1=wire.Edges[edgeindex].copy().Curve seg2=wire.Edges[edgeindex].copy().Curve seg1.segment(seg1.FirstParameter,param) seg2.segment(param,seg2.LastParameter) if edgeindex == len(wire.Edges): #we hit the last segment, we need to fix the degree degree=wire.Edges[0].Curve.Degree seg1.increase(degree) seg2.increase(degree) edges=wire.Edges[0:edgeindex]+[Part.Edge(seg1),Part.Edge(seg2)]\ + wire.Edges[edgeindex+1:] pts = edges[0].Curve.getPoles()[0:1] for edge in edges: pts.extend(edge.Curve.getPoles()[1:]) if self.obj.Closed: pts.pop() c=self.obj.Continuity # assume we have a tangent continuity for an arbitrarily split # segment, unless it's linear cont = 1 if (self.obj.Degree >= 2) else 0 self.obj.Continuity = c[0:edgeindex]+[cont]+c[edgeindex:] else: if (Draft.getType(self.obj) in ["BSpline"]): if (self.obj.Closed == True): curve = self.obj.Shape.Edges[0].Curve else: curve = self.obj.Shape.Curve uNewPoint = curve.parameter(point) uPoints = [] for p in self.obj.Points: uPoints.append(curve.parameter(p)) for i in range(len(uPoints)-1): if ( uNewPoint > uPoints[i] ) and ( uNewPoint < uPoints[i+1] ): pts.insert(i+1, self.invpl.multVec(point)) break # DNC: fix: add points to last segment if curve is closed if ( self.obj.Closed ) and ( uNewPoint > uPoints[-1] ) : pts.append(self.invpl.multVec(point)) self.obj.Points = pts FreeCAD.ActiveDocument.recompute() self.resetTrackers()
def test50(self): """Orient an already oriented wire""" p0 = Vector() p1 = Vector(1, 2, 3) p2 = Vector(2, 3, 4) pts = [p0, p1, p2] e0 = Part.Edge(Part.LineSegment(p0, p1)) e1 = Part.Edge(Part.LineSegment(p1, p2)) wire = PathOpTools.orientWire(Part.Wire([e0, e1])) wirePts = wireMarkers(wire) self.assertPointsMatch(wirePts, pts)
def getLocalProfile(self, pro): m1 = self.birail.matrixAt(pro.Rail1Param,0) m2 = self.birail.matrixAt(pro.Rail2Param,1) FreeCAD.Console.PrintMessage('\nMatrix 1\n%s\n'%str(m1)) FreeCAD.Console.PrintMessage('\nMatrix 2\n%s\n'%str(m2)) # Not sure it will work on Curve Poles ----v pts = pro.realCurve.Curve.getPoles() c1 = pro.realCurve.Curve.copy() c2 = pro.realCurve.Curve.copy() for i in range(len(pts)): #np = m1.inverse().multiply(p) c1.setPole(i+1, m1.inverse().multiply(pts[i])) c2.setPole(i+1, m2.inverse().multiply(pts[i])) pro.localCurve1 = Part.Edge(c1, pro.FirstParameter, pro.LastParameter) pro.localCurve2 = Part.Edge(c2, pro.FirstParameter, pro.LastParameter)
def test66(self): '''Split arc real world sample''' af = Vector(421.55, 378.41, 1) am = Vector(459.51, 372.61, 1) al = Vector(491.75, 351.75, 1) arc = Part.Edge(Part.ArcOfCircle(af, am, al)) ac = arc.Curve.Center s = Vector(434.54, 378.26, 1) head, tail = PathGeom.splitEdgeAt(arc, s) # make sure the arcs connect as they should self.assertCoincide(arc.valueAt(arc.FirstParameter), head.valueAt(head.FirstParameter), 0.005) self.assertCoincide(s, head.valueAt(head.LastParameter), 0.005) self.assertCoincide(s, tail.valueAt(tail.FirstParameter), 0.005) i = arc.valueAt(arc.LastParameter) j = tail.valueAt(tail.LastParameter) print("(%.2f, %.2f, %.2f) vs. (%.2f, %.2f, %.2f)" % (i.x, i.y, i.z, j.x, j.y, j.z)) self.assertCoincide(arc.valueAt(arc.LastParameter), tail.valueAt(tail.LastParameter), 0.005) # make sure the radii match self.assertRoughly(arc.Curve.Radius, head.Curve.Radius, 0.001) self.assertRoughly(arc.Curve.Radius, tail.Curve.Radius, 0.001) # also, all arcs should have the same center self.assertCoincide(arc.Curve.Center, head.Curve.Center, 0.001) self.assertCoincide(arc.Curve.Center, tail.Curve.Center, 0.001)
def orderAndFlipEdges(self, inputEdges): PathLog.track("entry(%.2f, %.2f, %.2f), exit(%.2f, %.2f, %.2f)" % (self.entry.x, self.entry.y, self.entry.z, self.exit.x, self.exit.y, self.exit.z)) self.edgesOrder = [] outputEdges = [] p0 = self.entry lastP = p0 edges = copy.copy(inputEdges) while edges: # print("(%.2f, %.2f, %.2f) %d %d" % (p0.x, p0.y, p0.z)) for e in copy.copy(edges): p1 = e.valueAt(e.FirstParameter) p2 = e.valueAt(e.LastParameter) if PathGeom.pointsCoincide(p1, p0): outputEdges.append((e, False)) edges.remove(e) lastP = None p0 = p2 debugEdge(e, ">>>>> no flip") break elif PathGeom.pointsCoincide(p2, p0): flipped = PathGeom.flipEdge(e) if not flipped is None: outputEdges.append((flipped, True)) else: p0 = None cnt = 0 for p in reversed(e.discretize(Deflection=0.01)): if not p0 is None: outputEdges.append((Part.Edge(Part.LineSegment(p0, p)), True)) cnt = cnt + 1 p0 = p PathLog.info("replaced edge with %d straight segments" % cnt) edges.remove(e) lastP = None p0 = p1 debugEdge(e, ">>>>> flip") break else: debugEdge(e, "<<<<< (%.2f, %.2f, %.2f)" % (p0.x, p0.y, p0.z)) if lastP == p0: self.edgesOrder.append(outputEdges) self.edgesOrder.append(edges) print('input edges:') for e in inputEdges: debugEdge(e, ' ', False) print('ordered edges:') for e, flip in outputEdges: debugEdge(e, ' %c ' % ('<' if flip else '>'), False) print('remaining edges:') for e in edges: debugEdge(e, ' ', False) raise ValueError("No connection to %s" % (p0)) elif lastP: PathLog.debug("xxxxxx (%.2f, %.2f, %.2f) (%.2f, %.2f, %.2f)" % (p0.x, p0.y, p0.z, lastP.x, lastP.y, lastP.z)) else: PathLog.debug("xxxxxx (%.2f, %.2f, %.2f) -" % (p0.x, p0.y, p0.z)) lastP = p0 PathLog.track("-") return outputEdges
def __init__(self,name,origin): self.name = name if not isinstance(origin,Base.Vector): raise RuntimeError("origin is not a Vector") self.origin = origin ox = origin.x oy = origin.y oz = origin.z boardthick = Base.Vector(0,0,self._boardthickness) padthick = Base.Vector(0,0,self._padThick) self.board = Part.makePlane(self._width,self._length,self.origin).extrude(boardthick) headholeX = self._headerX+ox headholeY = self._headerY+oy headholeRadius = self._headerHoleDia/2.0 self.pads = list() for holePadType in self._headholePadTypes: holeorig = Base.Vector(headholeX,headholeY,oz) self.board = \ self.board.cut(Part.Face(Part.Wire(Part.makeCircle(\ headholeRadius,holeorig))).extrude(boardthick)) if holePadType == 'R': padOrigin = holeorig.add(Base.Vector(-self._padsizeX/2,\ -self._padsizeY/2,\ self._boardthickness)) padsurf = Part.makePlane(self._padsizeX,self._padsizeY,padOrigin) elif holePadType == 'O': padOrigin = holeorig.add(Base.Vector(0,0,self._boardthickness)) S1 = padOrigin.add(Base.Vector(0,self._padsizeY/2,0)) S2 = padOrigin.add(Base.Vector(self._padsizeX/2,0,0)) padsurf = Part.Face(Part.Wire(Part.Edge(Part.Ellipse(S1,S2,padOrigin)))) h = Part.Face(Part.Wire(Part.makeCircle(headholeRadius,holeorig.add(Base.Vector(0,0,self._boardthickness))))).extrude(padthick) self.pads.append(padsurf.extrude(padthick).cut(h)) headholeX += 2.54
def execute(self, obj): edge = _utils.getShape(obj, "Edge", "Edge") curve = curveExtend.getTrimmedCurve(edge) cont_start = 1 if hasattr(obj, "TypeStart"): if obj.TypeStart == "G2 curve": cont_start = 2 cont_end = 1 if hasattr(obj, "TypeEnd"): if obj.TypeEnd == "G2 curve": cont_end = 2 ext = [] if obj.LengthStart > 0: ext.append( curveExtend.extendCurve(curve, 0, obj.LengthStart, cont_start)) if obj.LengthEnd > 0: ext.append( curveExtend.extendCurve(curve, 1, obj.LengthEnd, cont_end)) if not ext == []: if hasattr(obj, "Output"): if obj.Output == "SingleEdge": for c in ext: curve.join(c.toBSpline()) obj.Shape = curve.toShape() else: ext.append(curve) edges = [] for c in ext: edges.append(Part.Edge(c)) w = Part.Wire(Part.__sortEdges__(edges)) w.fixWire() obj.Shape = w
def buildFromTwoPoints(vertex1, vertex2, index, object1, group): if WF.verbose(): App.Console.PrintMessage("running aLP.buildFromTwoPoints !") try: if M_DEBUG: print_msg("\nvertex1 = " + str(vertex1)) print_msg("vertex2 = " + str(vertex2)) vector_a = vertex1 vector_b = vertex2 m_distance = vector_b.sub(vector_a).Length / 2 m_distance = index * (vector_b.sub(vector_a).Length / 1) if M_DEBUG: print_msg("vector_a = " + str(vector_a)) print_msg("vector_b = " + str(vector_b)) print_msg("m_distance = " + str(m_distance)) vector_c = vector_a.add( vector_b.sub(vector_a).normalize().multiply(m_distance)) if M_DEBUG: print_msg("vector_c = " + str(vector_c)) L1 = Part.LineSegment(vector_b, vector_c) edge = Part.Edge(L1) # App.ActiveDocument.openTransaction("Macro AlongLinePoint") # selfobj = makeAlongLinePointFeature(group) # selfobj.AlongEdge = edge [object1, "Vertex1"] # selfobj.Point = vector_c # selfobj.Edge = None # selfobj.Distance = m_distance # selfobj.Proxy.execute(selfobj) except Exception as err: printError_msg(err.args[0], title="Macro AlongLinePoint")
def setProfiles(self, plist): data = [] self.knots1, self.knots2 = [],[] for pro in plist: pts = pro.discretize(100) bspline = Part.BSplineCurve() bspline.approximate(Points = pts, ParamType = 'Chordlength') # 'Uniform' 'Centripetal' bs = Part.Edge(bspline) #, pro.FirstParameter, pro.LastParameter) data.append(self.getContactParams(bs)) sortedProfs = sorted(data,key=itemgetter(0)) # Sort profiles on rail1ContactParam self.profiles = [] for datum in sortedProfs: self.knots1.append(datum[0]) self.knots2.append(datum[1]) p = profile(datum[2]) p.Rail1Param = datum[0] p.Rail2Param = datum[1] p.FirstParameter = datum[3] p.LastParameter = datum[4] self.getLocalProfile(p) self.profiles.append(p) FreeCAD.Console.PrintMessage("\n Profile : %f - %f\n"%(p.Rail1Param,p.Rail2Param)) if len(plist) == 1: self.extend = True FreeCAD.Console.PrintMessage('\n1 Profile given\n') FreeCAD.Console.PrintMessage('\nProfiles sorted\n')
def updateShape(self, pts): """Create shape for display during creation process.""" import Part # Not quite right. draws 1 big bez. sb segmented edges = [] if len(pts) >= 2: # allow lower degree segment poles = pts[1:] else: poles = [] if self.degree: segpoleslst = [poles[x:x+self.degree] for x in range(0, len(poles), (self.degree or 1))] else: segpoleslst = [pts] startpoint = pts[0] for segpoles in segpoleslst: c = Part.BezierCurve() # last segment may have lower degree c.increase(len(segpoles)) c.setPoles([startpoint] + segpoles) edges.append(Part.Edge(c)) startpoint = segpoles[-1] w = Part.Wire(edges) return w
def test42(self): '''Verify ellipsis results in a proper segmentation of G1 commands.''' ellipse = Part.Edge(Part.Ellipse()) cmds = PathGeom.cmdsForEdge(ellipse) # let's make sure all commands are G1 and there are more than 20 of those self.assertGreater(len(cmds), 20) self.assertTrue(all([cmd.Name == 'G1' for cmd in cmds]))