예제 #1
0
    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)
예제 #2
0
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)
예제 #3
0
    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)
예제 #4
0
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
예제 #5
0
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
예제 #6
0
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)
예제 #7
0
    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)
예제 #8
0
    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)
            ]
예제 #9
0
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
예제 #10
0
    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)
예제 #11
0
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))
예제 #12
0
    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))
예제 #13
0
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)
예제 #14
0
    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))
예제 #15
0
    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
예제 #16
0
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
예제 #17
0
 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)
예제 #18
0
 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 = []
예제 #19
0
    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)
예제 #20
0
 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()
예제 #21
0
    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)
예제 #22
0
 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)
예제 #23
0
    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)
예제 #24
0
    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
예제 #25
0
 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
예제 #26
0
    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
예제 #27
0
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")
예제 #28
0
 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')
예제 #29
0
    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
예제 #30
0
 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]))