def sub_divide_cubic_path(sp, flat, i=1):
    """
  Break up a bezier curve into smaller curves, each of which
  is approximately a straight line within a given tolerance
  (the "smoothness" defined by [flat]).

  This is a modified version of cspsubdiv.cspsubdiv(). I rewrote the recursive
  call because it caused recursion-depth errors on complicated line segments.
  """

    while True:
        while True:
            if i >= len(sp):
                return

            p0 = sp[i - 1][1]
            p1 = sp[i - 1][2]
            p2 = sp[i][0]
            p3 = sp[i][1]

            b = (p0, p1, p2, p3)

            if bezier.maxdist(b) > flat:
                break

            i += 1

        one, two = bezier.beziersplitatt(b, 0.5)
        sp[i - 1][2] = one[1]
        sp[i][0] = two[2]
        p = [one[2], one[3], two[1]]
        sp[i:1] = [p]
示例#2
0
def linearize(p, tolerance=0.001):
    """
    This function receives a component of a 'cubicsuperpath' and returns two things:
    The path subdivided in many straight segments, and an array containing the length of each segment.

    We could work with bezier path as well, but bezier arc lengths are (re)computed for each point
    in the deformed object. For complex paths, this might take a while.
    """
    zero = 0.000001
    i = 0
    d = 0
    lengths = []
    while i < len(p) - 1:
        box = pointdistance(p[i][1], p[i][2])
        box += pointdistance(p[i][2], p[i + 1][0])
        box += pointdistance(p[i + 1][0], p[i + 1][1])
        chord = pointdistance(p[i][1], p[i + 1][1])
        if (box - chord) > tolerance:
            b1, b2 = beziersplitatt(
                [p[i][1], p[i][2], p[i + 1][0], p[i + 1][1]], 0.5)
            p[i][2][0], p[i][2][1] = b1[1]
            p[i + 1][0][0], p[i + 1][0][1] = b2[2]
            p.insert(i + 1, [[b1[2][0], b1[2][1]], [b1[3][0], b1[3][1]],
                             [b2[1][0], b2[1][1]]])
        else:
            d = (box + chord) / 2
            lengths.append(d)
            i += 1
    new = [p[i][1] for i in range(0, len(p) - 1) if lengths[i] > zero]
    new.append(p[-1][1])
    lengths = [l for l in lengths if l > zero]
    return new, lengths
示例#3
0
    def process_segment(cmd_proxy, facegroup, delx, dely):
        """Process each segments"""

        segments = []
        if isinstance(cmd_proxy.command,
                      (Curve, Smooth, TepidQuadratic, Quadratic, Arc)):
            prev = cmd_proxy.previous_end_point
            for curve in cmd_proxy.to_curves():
                bez = [prev] + curve.to_bez()
                prev = curve.end_point(cmd_proxy.first_point, prev)
                tees = [
                    t for t in beziertatslope(bez, (dely, delx)) if 0 < t < 1
                ]
                tees.sort()
                if len(tees) == 1:
                    one, two = beziersplitatt(bez, tees[0])
                    segments.append(Curve(*(one[1] + one[2] + one[3])))
                    segments.append(Curve(*(two[1] + two[2] + two[3])))
                elif len(tees) == 2:
                    one, two = beziersplitatt(bez, tees[0])
                    two, three = beziersplitatt(two, tees[1])
                    segments.append(Curve(*(one[1] + one[2] + one[3])))
                    segments.append(Curve(*(two[1] + two[2] + two[3])))
                    segments.append(Curve(*(three[1] + three[2] + three[3])))
                else:
                    segments.append(curve)
        elif isinstance(cmd_proxy.command, (Line, Curve)):
            segments.append(cmd_proxy.command)
        elif isinstance(cmd_proxy.command, ZoneClose):
            segments.append(
                Line(cmd_proxy.first_point.x, cmd_proxy.first_point.y))
        elif isinstance(cmd_proxy.command, (Vert, Horz)):
            segments.append(cmd_proxy.command.to_line(cmd_proxy.end_point))

        for seg in Path([Move(*cmd_proxy.previous_end_point)] +
                        segments).proxy_iterator():
            if isinstance(seg.command, Move): continue
            Motion.makeface(seg.previous_end_point, seg.command, facegroup,
                            delx, dely)
示例#4
0
def compatBezierSplitAtT(b, t):

    if isPython3():
        return bezier.beziersplitatt(b, t)
    else:
        return beziersplitatt(b, t)
示例#5
0
    def effect(self):

        maxL = None
        separateSegs = self.options.separateSegs

        if (self.options.unit != 'perc' and self.options.unit != 'count'):
            maxL = self.options.maxLength * self.svg.unittouu(
                '1' + self.options.unit)

        # ~ inkex.errormsg(_(str(maxL)))
        tolerance = 10**(-1 * self.options.precision)

        selections = self.svg.selected
        pathNodes = self.document.xpath('//svg:path', namespaces=inkex.NSS)

        paths = [(pathNode.get('id'), CubicSuperPath(pathNode.get('d')))
                 for pathNode in pathNodes]

        if (len(paths) > 0):
            for key, cspath in paths:
                parts = getPartsFromCubicSuper(cspath)
                partsSplit = False

                for i, part in enumerate(parts):

                    newSegs = []
                    for j, seg in enumerate(part):
                        segL = bezier.bezierlength(
                            (seg[0], seg[1], seg[2], seg[3]),
                            tolerance=tolerance)

                        if (maxL != None):
                            divL = maxL
                        elif (self.options.unit == 'perc'):
                            divL = segL * self.options.maxLength / 100
                        else:
                            divL = segL / ceil(self.options.maxLength)

                        if (segL > divL):

                            coveredL = 0
                            s = seg
                            s1 = None
                            s2 = DEF_ERR_MARGIN  #Just in case

                            while (not floatCmpWithMargin(segL, coveredL)):
                                if (s == seg):
                                    sL = segL
                                else:
                                    sL = bezier.bezierlength(
                                        (s[0], s[1], s[2], s[3]),
                                        tolerance=tolerance)

                                if (floatCmpWithMargin(segL, coveredL + divL)):
                                    s2 = s
                                    break
                                else:
                                    if (segL > (coveredL + divL)):
                                        t1L = divL
                                    else:
                                        t1L = segL - coveredL

                                    t1 = bezier.beziertatlength(
                                        (s[0], s[1], s[2], s[3]),
                                        l=t1L / sL,
                                        tolerance=tolerance)
                                    s1, s2 = bezier.beziersplitatt(
                                        (s[0], s[1], s[2], s[3]), t1)
                                    coveredL += t1L
                                    newSegs.append(s1)
                                    s = s2
                            newSegs.append(s2)
                        else:
                            newSegs.append(seg)

                    if (len(newSegs) > len(part)):
                        parts[i] = newSegs
                        partsSplit = True

                if (partsSplit or separateSegs):
                    elem = selections[key]
                    if (separateSegs):
                        parent = elem.getparent()
                        idx = parent.index(elem)
                        parent.remove(elem)
                        allSegs = [seg for part in parts for seg in part]
                        idSuffix = 0
                        for seg in allSegs:
                            cspath = getCubicSuperFromParts([[seg]])
                            newElem = copy.copy(elem)
                            oldId = newElem.get('id')
                            newElem.set('d', CubicSuperPath(cspath))
                            newElem.set('id', oldId + str(idSuffix).zfill(5))
                            parent.insert(idx, newElem)
                            idSuffix += 1
                    else:
                        cspath = getCubicSuperFromParts(parts)
                        elem.set('d', CubicSuperPath(cspath))
def splitAtT(seg, t):
    if (ver == 1.0):
        return bezier.beziersplitatt((seg[0], seg[1], seg[2], seg[3]), t)
    else:
        return bezmisc.beziersplitatt((seg[0], seg[1], seg[2], seg[3]), t)