示例#1
0
    def effect(self):
        # Check we have enough objects selected
        count = len(self.selected)
        if count < 2:
            inkex.errormsg(_("Please select at least two objects."))

        # The step in scale between each object
        xstep = (self.options.xfinish - self.options.xstart)/(count - 1)
        if self.options.ysame:
            ystep = xstep
        else:
            ystep = (self.options.yfinish - self.options.ystart)/(count - 1)

        # Starting scales
        xscale = self.options.xstart
        if self.options.ysame:
            yscale = xscale
        else:
            yscale = self.options.ystart

        # Sort selected objects by z order, lowest first
        id_list = self.selected.keys()
        id_list = pathmodifier.zSort(self.document.getroot(), id_list)

        # Scale each object
        for id in id_list:
            # No scaling actually happening
            if xscale == 1.0 and yscale == 1.0:
                xscale += xstep
                yscale += ystep
                continue

            # Get node and current transformations
            node = self.selected[id]
            transform = node.get('transform')

            # Scale the object as desired
            if transform:
                if xscale == yscale:
                    transform += ' scale(%f)' % (xscale)
                else:
                    transform += ' scale(%f, %f)' % (xscale, yscale)
            else:
                if xscale == yscale:
                    transform = 'scale(%f)' % (xscale)
                else:
                    transform = 'scale(%f, %f)' % (xscale, yscale)
            node.set('transform', transform)

            # Change the scale ready for the next object
            xscale += xstep
            yscale += ystep
示例#2
0
    def effect(self):
        # Check we have enough objects selected
        count = len(self.selected)
        if count < 2:
            inkex.errormsg(_("Please select at least two objects."))

        # The step in scale between each object
        xstep = (self.options.xfinish - self.options.xstart) / (count - 1)
        if self.options.ysame:
            ystep = xstep
        else:
            ystep = (self.options.yfinish - self.options.ystart) / (count - 1)

        # Starting scales
        xscale = self.options.xstart
        if self.options.ysame:
            yscale = xscale
        else:
            yscale = self.options.ystart

        # Sort selected objects by z order, lowest first
        id_list = self.selected.keys()
        id_list = pathmodifier.zSort(self.document.getroot(), id_list)

        # Scale each object
        for id in id_list:
            # No scaling actually happening
            if xscale == 1.0 and yscale == 1.0:
                xscale += xstep
                yscale += ystep
                continue

            # Get node and current transformations
            node = self.selected[id]
            transform = node.get('transform')

            # Scale the object as desired
            if transform:
                if xscale == yscale:
                    transform += ' scale(%f)' % (xscale)
                else:
                    transform += ' scale(%f, %f)' % (xscale, yscale)
            else:
                if xscale == yscale:
                    transform = 'scale(%f)' % (xscale)
                else:
                    transform = 'scale(%f, %f)' % (xscale, yscale)
            node.set('transform', transform)

            # Change the scale ready for the next object
            xscale += xstep
            yscale += ystep
    def prepareSelectionList(self):

        idList = self.options.ids
        idList = pathmodifier.zSort(self.document.getroot(), idList)
        id = idList[-1]
        self.patterns = {id: self.selected[id]}

        if self.options.duplicate:
            self.patterns = self.duplicateNodes(self.patterns)
        self.expandGroupsUnlinkClones(self.patterns, True, True)
        self.objectsToPaths(self.patterns)
        del self.selected[id]

        self.skeletons = self.selected
        self.expandGroupsUnlinkClones(self.skeletons, True, False)
        self.objectsToPaths(self.skeletons)
    def prepareSelectionList(self):

        idList=self.options.ids
        idList=pathmodifier.zSort(self.document.getroot(),idList)
        id = idList[-1]
        self.patterns={id:self.selected[id]}

        if self.options.duplicate:
            self.patterns=self.duplicateNodes(self.patterns)
        self.expandGroupsUnlinkClones(self.patterns, True, True)
        self.objectsToPaths(self.patterns)
        del self.selected[id]

        self.skeletons=self.selected
        self.expandGroupsUnlinkClones(self.skeletons, True, False)
        self.objectsToPaths(self.skeletons)
示例#5
0
 def restack_z_order(self):
     parentnode = None
     objects = []
     if len(self.selected) == 1:
         firstobject = self.selected[self.options.ids[0]]
         if firstobject.tag == inkex.addNS('g', 'svg'):
             parentnode = firstobject
             for child in parentnode.iterchildren(reversed=False):
                 objects.append(child)
     else:
         parentnode = self.current_layer
         for id_ in zSort(self.document.getroot(), self.selected.keys()):
             objects.append(self.selected[id_])
     if self.options.zsort == "rev":
         objects.reverse()
     elif self.options.zsort == "rand":
         random.shuffle(objects)
     if parentnode is not None:
         for item in objects:
             parentnode.append(item)
示例#6
0
 def restack_z_order(self):
     parentnode = None
     objects = []
     if len(self.selected) == 1:
         firstobject = self.selected[self.options.ids[0]]
         if firstobject.tag == inkex.addNS('g', 'svg'):
             parentnode = firstobject
             for child in parentnode.iterchildren(reversed=False):
                 objects.append(child)
     else:
         parentnode = self.current_layer
         for id_ in zSort(self.document.getroot(), self.selected.keys()):
             objects.append(self.selected[id_])
     if self.options.zsort == "rev":
         objects.reverse()
     elif self.options.zsort == "rand":
         random.shuffle(objects)
     if parentnode is not None:
         for item in objects:
             parentnode.append(item)
示例#7
0
    def alignAlongPath(self):
        ###convert object(line) to path? or determine wether object is path or not

        #This is used by object arrangement algorithm
        xNotY = True
        ascending = True
        if self.options.detect == 'left':
            xNotY = True
            ascending = True
        elif self.options.detect == 'right':
            xNotY = True
            ascending = False
        elif self.options.detect == 'top':
            xNotY = False
            ascending = True
        elif self.options.detect == 'bottom':
            xNotY = False
            ascending = False

        #Sorting selection to determine lowest (path)
        zOrderedList = pathmodifier.zSort(self.document.getroot(),
                                          self.options.ids)
        #Compute centers
        self.centers = self.computeCenters(zOrderedList[1:],
                                           self.options.placetext)
        if len(self.centers) > 0:
            #Ordering objects that should be placed on path
            self.orderObjects(xNotY, ascending)
            #Computing offsets from path's  start point which are similar to distances between objects
            offsets = self.computeOffsets(self.options.usedistance,
                                          self.options.distance,
                                          self.options.distbetween)
            #Computing where objects should be placed
            orderedObjListPositions = self.computePointsXY(
                zOrderedList[0], offsets, self.options.offset)
            #Traslating and rotating objects
            if orderedObjListPositions:
                self.translateObjects(orderedObjListPositions,
                                      self.options.orient)
            else:
                inkex.debug("Nothing was changed.")
示例#8
0
 def getTotElements(self):
   self.tot_el = 0
   self.collection = None
   if len( self.selected ) == 0:
     return False
   if len( self.selected ) > 1:
     # multiple selection
     if self.options.zsort:
         sorted_ids = zSort(self.document.getroot(),self.selected.keys())
     else:
         sorted_ids = self.options.ids
     self.collection = list(sorted_ids)
     for i in sorted_ids:
       path = '//*[@id="%s"]' % i
       self.collection[self.tot_el] = self.document.xpath(path, namespaces=inkex.NSS)[0]
       self.tot_el += 1
   else:
     # must be a group
     self.collection = self.selected[ self.options.ids[0] ]
     for i in self.collection:
       self.tot_el += 1
示例#9
0
    def effect(self):

        # get user-entered params
        x_scale = self.options.x_scale
        y_scale = self.options.y_scale

        t_start = self.options.t_start
        t_end = self.options.t_end
        n_steps = self.options.n_steps
        fps = self.options.fps
        dt = self.options.dt

        x_eqn = self.options.x_eqn
        y_eqn = self.options.y_eqn

        x_size_eqn = self.options.x_size_eqn
        y_size_eqn = self.options.y_size_eqn

        theta_eqn = self.options.theta_eqn

        # get doc root
        svg = self.document.getroot()
        doc_w = self.unittouu(svg.get('width'))
        doc_h = self.unittouu(svg.get('height'))

        # get selected items and validate
        selected = pathmodifier.zSort(self.document.getroot(),
                                      self.selected.keys())

        if not selected:
            inkex.errormsg(
                'Exactly two objects must be selected: a rect and a template. See "help" for details.'
            )
            return
        elif len(selected) != 2:
            inkex.errormsg(
                'Exactly two objects must be selected: a rect and a template. See "help" for details.'
            )
            return

        # rect
        rect = self.selected[selected[0]]

        if not rect.tag.endswith('rect'):
            inkex.errormsg('Bottom object must be rect. See "help" for usage.')
            return

        # object
        obj = self.selected[selected[1]]

        if not (obj.tag.endswith('path') or obj.tag.endswith('g')):
            inkex.errormsg(
                'Template object must be path or group of paths. See "help" for usage.'
            )
            return
        if obj.tag.endswith('g'):
            children = obj.getchildren()
            if not all([ch.tag.endswith('path') for ch in children]):
                msg = 'All elements of group must be paths, but they are: '
                msg += ', '.join(['{}'.format(ch) for ch in children])
                inkex.errormsg(msg)
                return
            objs = children
            is_group = True
        else:
            objs = [obj]
            is_group = False

        # get rect params
        w = float(rect.get('width'))
        h = float(rect.get('height'))

        x_rect = float(rect.get('x'))
        y_rect = float(rect.get('y'))

        # lower left corner
        x_0 = x_rect
        y_0 = y_rect + h

        # get object path(s)
        obj_ps = [simplepath.parsePath(obj_.get('d')) for obj_ in objs]
        n_segs = [len(obj_p_) for obj_p_ in obj_ps]
        obj_p = sum(obj_ps, [])

        # compute travel parameters
        if not n_steps:
            # compute dt
            if dt == 0:
                dt = 1. / fps
            ts = np.arange(t_start, t_end, dt)
        else:
            ts = np.linspace(t_start, t_end, n_steps)

        # compute xs, ys, stretches, and rotations in arbitrary coordinates
        xs = np.nan * np.zeros(len(ts))
        ys = np.nan * np.zeros(len(ts))
        x_sizes = np.nan * np.zeros(len(ts))
        y_sizes = np.nan * np.zeros(len(ts))
        thetas = np.nan * np.zeros(len(ts))

        for ctr, t in enumerate(ts):
            xs[ctr] = eval(x_eqn)
            ys[ctr] = eval(y_eqn)
            x_sizes[ctr] = eval(x_size_eqn)
            y_sizes[ctr] = eval(y_size_eqn)
            thetas[ctr] = eval(theta_eqn) * pi / 180

        # ensure no Infs
        if np.any(np.isinf(xs)):
            raise Exception('Inf detected in x(t), please remove.')
            return
        if np.any(np.isinf(ys)):
            raise Exception('Inf detected in y(t), please remove.')
            return
        if np.any(np.isinf(x_sizes)):
            raise Exception('Inf detected in x_size(t), please remove.')
            return
        if np.any(np.isinf(y_sizes)):
            raise Exception('Inf detected in y_size(t), please remove.')
            return
        if np.any(np.isinf(thetas)):
            raise Exception('Inf detected in theta(t), please remove.')
            return

        # convert to screen coordinates
        xs *= (w / x_scale)
        xs += x_0

        ys *= (-h / y_scale)  # neg sign to invert y for inkscape screen
        ys += y_0

        # get obj center
        b_box = simpletransform.refinedBBox(
            cubicsuperpath.CubicSuperPath(obj_p))
        c_x = 0.5 * (b_box[0] + b_box[1])
        c_y = 0.5 * (b_box[2] + b_box[3])

        # get rotation anchor
        if any([k.endswith('transform-center-x') for k in obj.keys()]):
            k_r_x = [
                k for k in obj.keys() if k.endswith('transform-center-x')
            ][0]
            k_r_y = [
                k for k in obj.keys() if k.endswith('transform-center-y')
            ][0]
            r_x = c_x + float(obj.get(k_r_x))
            r_y = c_y - float(obj.get(k_r_y))
        else:
            r_x, r_y = c_x, c_y

        paths = []

        # compute new paths
        for x, y, x_size, y_size, theta in zip(xs, ys, x_sizes, y_sizes,
                                               thetas):

            path = deepcopy(obj_p)

            # move to origin
            simplepath.translatePath(path, -x_0, -y_0)

            # move rotation anchor accordingly
            r_x_1 = r_x - x_0
            r_y_1 = r_y - y_0

            # scale
            simplepath.scalePath(path, x_size, y_size)

            # scale rotation anchor accordingly
            r_x_2 = r_x_1 * x_size
            r_y_2 = r_y_1 * y_size

            # move to final location
            simplepath.translatePath(path, x, y)

            # move rotation anchor accordingly
            r_x_3 = r_x_2 + x
            r_y_3 = r_y_2 + y

            # rotate
            simplepath.rotatePath(path, -theta, cx=r_x_3, cy=r_y_3)

            paths.append(path)

        parent = self.current_layer
        group = inkex.etree.SubElement(parent, inkex.addNS('g', 'svg'), {})

        for path in paths:

            if is_group:
                group_ = inkex.etree.SubElement(group, inkex.addNS('g', 'svg'),
                                                {})
                path_components = split(path, n_segs)

                for path_component, child in zip(path_components, children):
                    attribs = {k: child.get(k) for k in child.keys()}

                    attribs['d'] = simplepath.formatPath(path_component)

                    child_copy = inkex.etree.SubElement(
                        group_, child.tag, attribs)

            else:
                attribs = {k: obj.get(k) for k in obj.keys()}

                attribs['d'] = simplepath.formatPath(path)

                obj_copy = inkex.etree.SubElement(group, obj.tag, attribs)
示例#10
0
文件: interp.py 项目: onc4hy/inkscape
    def effect(self):
        exponent = self.options.exponent
        if exponent >= 0:
            exponent = 1.0 + exponent
        else:
            exponent = 1.0 / (1.0 - exponent)
        steps = [1.0 / (self.options.steps + 1.0)]
        for i in range(self.options.steps - 1):
            steps.append(steps[0] + steps[-1])
        steps = [step**exponent for step in steps]

        paths = {}
        styles = {}

        if self.options.zsort:
            # work around selection order swapping with Live Preview
            sorted_ids = pathmodifier.zSort(self.document.getroot(),
                                            self.selected.keys())
        else:
            # use selection order (default)
            sorted_ids = self.options.ids

        for id in sorted_ids:
            node = self.selected[id]
            if node.tag == inkex.addNS('path', 'svg'):
                paths[id] = cubicsuperpath.parsePath(node.get('d'))
                styles[id] = simplestyle.parseStyle(node.get('style'))
                trans = node.get('transform')
                if trans:
                    simpletransform.applyTransformToPath(
                        simpletransform.parseTransform(trans), paths[id])
            else:
                sorted_ids.remove(id)

        for i in range(1, len(sorted_ids)):
            start = copy.deepcopy(paths[sorted_ids[i - 1]])
            end = copy.deepcopy(paths[sorted_ids[i]])
            sst = copy.deepcopy(styles[sorted_ids[i - 1]])
            est = copy.deepcopy(styles[sorted_ids[i]])
            basestyle = copy.deepcopy(sst)
            if basestyle.has_key('stroke-width'):
                basestyle['stroke-width'] = self.tweenstyleunit(
                    'stroke-width', sst, est, 0)

            #prepare for experimental style tweening
            if self.options.style:
                dostroke = True
                dofill = True
                styledefaults = {
                    'opacity': '1.0',
                    'stroke-opacity': '1.0',
                    'fill-opacity': '1.0',
                    'stroke-width': '1.0',
                    'stroke': 'none',
                    'fill': 'none'
                }
                for key in styledefaults.keys():
                    sst.setdefault(key, styledefaults[key])
                    est.setdefault(key, styledefaults[key])
                isnotplain = lambda x: not (x == 'none' or x[:1] == '#')
                if isnotplain(sst['stroke']) or isnotplain(
                        est['stroke']) or (sst['stroke'] == 'none'
                                           and est['stroke'] == 'none'):
                    dostroke = False
                if isnotplain(sst['fill']) or isnotplain(
                        est['fill']) or (sst['fill'] == 'none'
                                         and est['fill'] == 'none'):
                    dofill = False
                if dostroke:
                    if sst['stroke'] == 'none':
                        sst['stroke-width'] = '0.0'
                        sst['stroke-opacity'] = '0.0'
                        sst['stroke'] = est['stroke']
                    elif est['stroke'] == 'none':
                        est['stroke-width'] = '0.0'
                        est['stroke-opacity'] = '0.0'
                        est['stroke'] = sst['stroke']
                if dofill:
                    if sst['fill'] == 'none':
                        sst['fill-opacity'] = '0.0'
                        sst['fill'] = est['fill']
                    elif est['fill'] == 'none':
                        est['fill-opacity'] = '0.0'
                        est['fill'] = sst['fill']

            if self.options.method == 2:
                #subdivide both paths into segments of relatively equal lengths
                slengths, stotal = csplength(start)
                elengths, etotal = csplength(end)
                lengths = {}
                t = 0
                for sp in slengths:
                    for l in sp:
                        t += l / stotal
                        lengths.setdefault(t, 0)
                        lengths[t] += 1
                t = 0
                for sp in elengths:
                    for l in sp:
                        t += l / etotal
                        lengths.setdefault(t, 0)
                        lengths[t] += -1
                sadd = [k for (k, v) in lengths.iteritems() if v < 0]
                sadd.sort()
                eadd = [k for (k, v) in lengths.iteritems() if v > 0]
                eadd.sort()

                t = 0
                s = [[]]
                for sp in slengths:
                    if not start[0]:
                        s.append(start.pop(0))
                    s[-1].append(start[0].pop(0))
                    for l in sp:
                        pt = t
                        t += l / stotal
                        if sadd and t > sadd[0]:
                            while sadd and sadd[0] < t:
                                nt = (sadd[0] - pt) / (t - pt)
                                bezes = cspbezsplitatlength(
                                    s[-1][-1][:], start[0][0][:], nt)
                                s[-1][-1:] = bezes[:2]
                                start[0][0] = bezes[2]
                                pt = sadd.pop(0)
                        s[-1].append(start[0].pop(0))
                t = 0
                e = [[]]
                for sp in elengths:
                    if not end[0]:
                        e.append(end.pop(0))
                    e[-1].append(end[0].pop(0))
                    for l in sp:
                        pt = t
                        t += l / etotal
                        if eadd and t > eadd[0]:
                            while eadd and eadd[0] < t:
                                nt = (eadd[0] - pt) / (t - pt)
                                bezes = cspbezsplitatlength(
                                    e[-1][-1][:], end[0][0][:], nt)
                                e[-1][-1:] = bezes[:2]
                                end[0][0] = bezes[2]
                                pt = eadd.pop(0)
                        e[-1].append(end[0].pop(0))
                start = s[:]
                end = e[:]
            else:
                #which path has fewer segments?
                lengthdiff = numsegs(start) - numsegs(end)
                #swap shortest first
                if lengthdiff > 0:
                    start, end = end, start
                #subdivide the shorter path
                for x in range(abs(lengthdiff)):
                    maxlen = 0
                    subpath = 0
                    segment = 0
                    for y in range(len(start)):
                        for z in range(1, len(start[y])):
                            leng = bezlenapprx(start[y][z - 1], start[y][z])
                            if leng > maxlen:
                                maxlen = leng
                                subpath = y
                                segment = z
                    sp1, sp2 = start[subpath][segment - 1:segment + 1]
                    start[subpath][segment - 1:segment + 1] = cspbezsplit(
                        sp1, sp2)
                #if swapped, swap them back
                if lengthdiff > 0:
                    start, end = end, start

            #break paths so that corresponding subpaths have an equal number of segments
            s = [[]]
            e = [[]]
            while start and end:
                if start[0] and end[0]:
                    s[-1].append(start[0].pop(0))
                    e[-1].append(end[0].pop(0))
                elif end[0]:
                    s.append(start.pop(0))
                    e[-1].append(end[0][0])
                    e.append([end[0].pop(0)])
                elif start[0]:
                    e.append(end.pop(0))
                    s[-1].append(start[0][0])
                    s.append([start[0].pop(0)])
                else:
                    s.append(start.pop(0))
                    e.append(end.pop(0))

            if self.options.dup:
                steps = [0] + steps + [1]
            #create an interpolated path for each interval
            group = inkex.etree.SubElement(self.current_layer,
                                           inkex.addNS('g', 'svg'))
            for time in steps:
                interp = []
                #process subpaths
                for ssp, esp in zip(s, e):
                    if not (ssp or esp):
                        break
                    interp.append([])
                    #process superpoints
                    for sp, ep in zip(ssp, esp):
                        if not (sp or ep):
                            break
                        interp[-1].append([])
                        #process points
                        for p1, p2 in zip(sp, ep):
                            if not (sp or ep):
                                break
                            interp[-1][-1].append(interppoints(p1, p2, time))

                #remove final subpath if empty.
                if not interp[-1]:
                    del interp[-1]

                #basic style tweening
                if self.options.style:
                    basestyle['opacity'] = tweenstylefloat(
                        'opacity', sst, est, time)
                    if dostroke:
                        basestyle['stroke-opacity'] = tweenstylefloat(
                            'stroke-opacity', sst, est, time)
                        basestyle['stroke-width'] = self.tweenstyleunit(
                            'stroke-width', sst, est, time)
                        basestyle['stroke'] = tweenstylecolor(
                            'stroke', sst, est, time)
                    if dofill:
                        basestyle['fill-opacity'] = tweenstylefloat(
                            'fill-opacity', sst, est, time)
                        basestyle['fill'] = tweenstylecolor(
                            'fill', sst, est, time)
                attribs = {
                    'style': simplestyle.formatStyle(basestyle),
                    'd': cubicsuperpath.formatPath(interp)
                }
                new = inkex.etree.SubElement(group, inkex.addNS('path', 'svg'),
                                             attribs)
示例#11
0
    def effect(self):

        if len(self.options.ids) < 1 and len(self.options.ids) > 1:
            inkex.errormsg("This extension requires only one selected paths.")
            return
        #liste des chemins, preparation
        idList = self.options.ids
        idList = pathmodifier.zSort(self.document.getroot(), idList)
        id = idList[-1]
        idpoint = id + '-' + str(random.randint(
            1, 99))  #id du paterns creer a partir du chemin selectionner
        idpointMark = id + '-' + str(random.randint(1, 99))

        for id, node in self.selected.iteritems():
            if node.tag == inkex.addNS('path', 'svg'):
                style = simplestyle.parseStyle(
                    node.get('style'))  #je recupere l'ancien style
                style['stroke'] = '#00ff00'  #je modifie la valeur
                if self.options.autoMask == True:
                    style['display'] = 'none'
                node.set('style',
                         simplestyle.formatStyle(style))  #j'applique la modifi

                #gestion du skelete (le chemin selectionner)
                self.skeletons = self.selected
                self.expandGroupsUnlinkClones(self.skeletons, True, False)
                self.objectsToPaths(self.skeletons)

                for skelnode in self.skeletons.itervalues(
                ):  #calcul de la longeur du chemin
                    self.curSekeleton = cubicsuperpath.parsePath(
                        skelnode.get('d'))
                    for comp in self.curSekeleton:
                        self.skelcomp, self.lengths = linearize(comp)
                        longeur = sum(self.lengths)

                distance = self.unittouu(self.options.space)
                taille = self.unittouu(self.options.diamlong)
                MaxCopies = max(1, int(round((longeur + distance) / distance)))

                NbCopies = self.options.nrepeat  #nombre de copie desirer a integrer dans les choix a modifier pour ne pas depasser les valeurs maxi

                if NbCopies > MaxCopies:
                    NbCopies = MaxCopies  #on limitte le nombre de copie au maxi possible sur le chemin

                if self.options.autoRepeat:  #gestion du calcul auto
                    NbCopies = MaxCopies

                if self.options.autoOffset:  #gestion du decallage automatique
                    tOffset = ((longeur -
                                (NbCopies - 1) * distance) / 2) - taille / 2
                else:
                    tOffset = self.unittouu(self.options.toffset)

                #gestion du paterns
                labelpoint = 'Point: ' + idpoint + ' Nbr:' + str(
                    NbCopies) + ' longueur:' + str(
                        round(self.uutounit(longeur, 'mm'), 2)) + 'mm'
                addDot(self, idpoint, labelpoint, self.options.diamlong,
                       self.options.typePoint, 0)  #creation du cercle de base
                self.patterns = {
                    idpoint: self.getElementById(idpoint)
                }  #ajout du point dans le paterns de base

                bbox = simpletransform.computeBBox(self.patterns.values())
                #liste des chemins, fin de preparation

                if distance < 0.01:
                    exit(
                        _("The total length of the pattern is too small :\nPlease choose a larger object or set 'Space between copies' > 0"
                          ))
                for id, node in self.patterns.iteritems():

                    if node.tag == inkex.addNS('path',
                                               'svg') or node.tag == 'path':
                        d = node.get('d')
                        p0 = cubicsuperpath.parsePath(d)
                        newp = []
                        for skelnode in self.skeletons.itervalues():
                            self.curSekeleton = cubicsuperpath.parsePath(
                                skelnode.get('d'))
                            for comp in self.curSekeleton:
                                p = copy.deepcopy(p0)
                                self.skelcomp, self.lengths = linearize(comp)
                                #!!!!>----> TODO: really test if path is closed! end point==start point is not enough!
                                self.skelcompIsClosed = (
                                    self.skelcomp[0] == self.skelcomp[-1])

                                xoffset = self.skelcomp[0][0] - bbox[
                                    0] + tOffset
                                yoffset = self.skelcomp[0][1] - (bbox[2] +
                                                                 bbox[3]) / 2
                                if self.options.textInfos:
                                    addText(self, xoffset, yoffset, labelpoint)
                                width = distance * NbCopies
                                if not self.skelcompIsClosed:
                                    width -= distance

                                new = []
                                for sub in p:  #creation du nombre de patern
                                    for i in range(0, NbCopies, 1):
                                        new.append(
                                            copy.deepcopy(sub)
                                        )  #realise une copie de sub pour chaque nouveau element du patern
                                        offset(sub, distance, 0)
                                p = new
                                for sub in p:
                                    offset(sub, xoffset, yoffset)
                                for sub in p:  #une fois tous creer, on les mets en place
                                    for ctlpt in sub:  #pose le patern sur le chemin
                                        self.applyDiffeo(
                                            ctlpt[1], (ctlpt[0], ctlpt[2]))

                                newp += p

                        node.set('d', cubicsuperpath.formatPath(newp))
                    else:
                        inkex.errormsg(
                            "This extension need a path, not groups.")

        if self.options.autoMark:
            if self.options.typeMark == "markFraction":
                Fraction = self.options.nrepeat2  #en mode fraction 1= au debut et a la fin, 2= un demi, 3= 1/3 etc
                distance = (width) / Fraction  #distance inter point
                NbrMark = max(1, int(round((width + distance) / distance)))
                infos = " Marquage 1/" + str(Fraction)
                couleur = '#ff0000'
            else:
                Repeat = self.options.nrepeat2  #en mode fraction 1= au debut et a la fin, 2= un demi, 3= 1/3 etc
                NbrMark = max(1, int(round((NbCopies / Repeat))))
                distance = distance * Repeat  #distance inter point
                infos = " Marquage tous les " + str(Repeat) + " points"
                couleur = '#ffaa00'

            labelMark = "Mark: " + idpoint + infos
            addMark(self, 0, 0, idpointMark, labelMark, self.options.diamlong,
                    couleur)
            self.patternsMark = {
                idpointMark: self.getElementById(idpointMark)
            }  #ajout du point dans le paterns de base

            bbox = simpletransform.computeBBox(self.patternsMark.values())
            #liste des chemins, fin de preparation
            if distance < 0.01:
                exit(
                    _("The total length of the pattern is too small :\nPlease choose a larger object or set 'Space between copies' > 0"
                      ))
            for id, node in self.patternsMark.iteritems():

                if node.tag == inkex.addNS('path',
                                           'svg') or node.tag == 'path':
                    d = node.get('d')
                    p0 = cubicsuperpath.parsePath(d)
                    newp = []
                    for skelnode in self.skeletons.itervalues():
                        self.curSekeleton = cubicsuperpath.parsePath(
                            skelnode.get('d'))
                        for comp in self.curSekeleton:
                            p = copy.deepcopy(p0)
                            self.skelcomp, self.lengths = linearize(comp)
                            #!!!!>----> TODO: really test if path is closed! end point==start point is not enough!
                            self.skelcompIsClosed = (
                                self.skelcomp[0] == self.skelcomp[-1])
                            # a tester si les point au dessus sont utilisable pour positionner les autres a upoi ressemble skelcomp ??
                            xoffset = self.skelcomp[0][0] - bbox[
                                0] + tOffset + taille / 2
                            yoffset = self.skelcomp[0][1] - (bbox[2] +
                                                             bbox[3]) / 2

                            width = distance * NbrMark
                            if not self.skelcompIsClosed:
                                width -= distance

                            new = []
                            for sub in p:  #creation du nombre de patern
                                for i in range(0, NbrMark, 1):
                                    new.append(
                                        copy.deepcopy(sub)
                                    )  #realise une copie de sub pour chaque nouveau element du patern
                                    offset(sub, distance, 0)
                            p = new
                            for sub in p:
                                offset(sub, xoffset, yoffset)
                            for sub in p:  #une fois tous creer, on les mets en place
                                for ctlpt in sub:  #pose le patern sur le chemin
                                    self.applyDiffeo(ctlpt[1],
                                                     (ctlpt[0], ctlpt[2]))

                            newp += p

                    node.set('d', cubicsuperpath.formatPath(newp))
                else:
                    inkex.errormsg("This extension need a path, not groups.")
示例#12
0
    def effect(self):

        if len(self.options.ids) < 1 and len(self.options.ids) > 1:
            inkex.errormsg(
                _("This extension requires only one selected paths."))
            return

#liste des chemins, preparation
        idList = self.options.ids
        idList = pathmodifier.zSort(self.document.getroot(), idList)
        id = idList[-1]
        idpoint = id + '-' + str(random.randint(
            1, 99))  #id du paterns creer a partir du chemin selectionner

        for id, node in self.selected.iteritems():
            style = simplestyle.parseStyle(
                node.get('style'))  #je recupere l'ancien style
            style['stroke'] = '#00ff00'  #je modifie la valeur
            node.set('style',
                     simplestyle.formatStyle(style))  #j'applique la modifi

        #gestion du skelte (le chemin selectionner)
        self.skeletons = self.selected
        self.expandGroupsUnlinkClones(self.skeletons, True, False)
        self.objectsToPaths(self.skeletons)

        for skelnode in self.skeletons.itervalues(
        ):  #calcul de la longeur du chemin
            self.curSekeleton = cubicsuperpath.parsePath(skelnode.get('d'))
            for comp in self.curSekeleton:
                self.skelcomp, self.lengths = linearize(comp)
                longeur = sum(self.lengths)

        distance = self.unittouu(self.options.space)
        taille = self.unittouu(self.options.diamlong)

        if self.options.autoRepeat:  #gestion du calcul auto
            nbrRepeat = int(round((longeur) / distance))
        else:
            nbrRepeat = self.options.nrepeat

        if self.options.autoOffset:  #gestion du decallage automatique
            tOffset = ((longeur - (nbrRepeat - 1) * distance) / 2) - taille / 2
        else:
            tOffset = self.unittouu(self.options.toffset)

        #gestion du paterns
        labelpoint = 'Point:' + self.options.diamlong + ' Ecart:' + self.options.space + ' Decallage:' + str(
            round(self.uutounit(tOffset, 'mm'),
                  2)) + 'mm' + ' Nbr:' + str(nbrRepeat) + ' longueur:' + str(
                      round(self.uutounit(longeur, 'mm'), 2)) + 'mm'
        addDot(self, idpoint, labelpoint, self.options.diamlong,
               self.options.typePoint)  #creation du cercle de base
        self.patterns = {
            idpoint: self.getElementById(idpoint)
        }  #ajout du point dans le paterns de base

        bbox = simpletransform.computeBBox(self.patterns.values())
        #liste des chemins, fin de preparation

        if distance < 0.01:
            exit(
                _("The total length of the pattern is too small :\nPlease choose a larger object or set 'Space between copies' > 0"
                  ))

        for id, node in self.patterns.iteritems():

            if node.tag == inkex.addNS('path', 'svg') or node.tag == 'path':
                d = node.get('d')
                p0 = cubicsuperpath.parsePath(d)
                newp = []
                for skelnode in self.skeletons.itervalues():
                    self.curSekeleton = cubicsuperpath.parsePath(
                        skelnode.get('d'))
                    for comp in self.curSekeleton:
                        p = copy.deepcopy(p0)
                        self.skelcomp, self.lengths = linearize(comp)
                        #!!!!>----> TODO: really test if path is closed! end point==start point is not enough!
                        self.skelcompIsClosed = (
                            self.skelcomp[0] == self.skelcomp[-1])

                        length = sum(self.lengths)
                        xoffset = self.skelcomp[0][0] - bbox[0] + tOffset
                        yoffset = self.skelcomp[0][1] - (bbox[2] + bbox[3]) / 2
                        if self.options.textInfos:
                            addText(self, xoffset, yoffset, labelpoint)
                        MaxCopies = max(
                            1, int(round((length + distance) / distance)))
                        NbCopies = nbrRepeat  #nombre de copie desirer a intergrer dans les choix a modifier pour ne pas depasser les valeurs maxi
                        if NbCopies > MaxCopies:
                            NbCopies = MaxCopies  #on limitte le nombre de copie au maxi possible sur le chemin
                        width = distance * NbCopies
                        if not self.skelcompIsClosed:
                            width -= distance

                        new = []
                        for sub in p:  #creation du nombre de patern
                            for i in range(0, NbCopies, 1):
                                new.append(
                                    copy.deepcopy(sub)
                                )  #realise une copie de sub pour chaque nouveau element du patern
                                offset(sub, distance, 0)
                        p = new
                        for sub in p:
                            offset(sub, xoffset, yoffset)
                        for sub in p:  #une fois tous creer, on les mets en place
                            for ctlpt in sub:  #pose le patern sur le chemin
                                self.applyDiffeo(ctlpt[1],
                                                 (ctlpt[0], ctlpt[2]))

                        newp += p

                node.set('d', cubicsuperpath.formatPath(newp))
示例#13
0
    def effect(self):
        exponent = self.options.exponent
        if exponent>= 0:
            exponent = 1.0 + exponent
        else:
            exponent = 1.0/(1.0 - exponent)
        steps = [1.0/(self.options.steps + 1.0)]
        for i in range(self.options.steps - 1):
            steps.append(steps[0] + steps[-1])
        steps = [step**exponent for step in steps]
            
        paths = {}            
        styles = {}

        if self.options.zsort:
            # work around selection order swapping with Live Preview
            sorted_ids = pathmodifier.zSort(self.document.getroot(),self.selected.keys())
        else:
            # use selection order (default)
            sorted_ids = self.options.ids

        for id in sorted_ids:
            node = self.selected[id]
            if node.tag ==inkex.addNS('path','svg'):
                paths[id] = cubicsuperpath.parsePath(node.get('d'))
                styles[id] = simplestyle.parseStyle(node.get('style'))
                trans = node.get('transform')
                if trans:
                    simpletransform.applyTransformToPath(simpletransform.parseTransform(trans), paths[id])
            else:
                sorted_ids.remove(id)

        for i in range(1,len(sorted_ids)):
            start = copy.deepcopy(paths[sorted_ids[i-1]])
            end = copy.deepcopy(paths[sorted_ids[i]])
            sst = copy.deepcopy(styles[sorted_ids[i-1]])
            est = copy.deepcopy(styles[sorted_ids[i]])
            basestyle = copy.deepcopy(sst)
            if basestyle.has_key('stroke-width'):
                basestyle['stroke-width'] = self.tweenstyleunit('stroke-width',sst,est,0)

            #prepare for experimental style tweening
            if self.options.style:
                dostroke = True
                dofill = True
                styledefaults = {'opacity':'1.0', 'stroke-opacity':'1.0', 'fill-opacity':'1.0',
                        'stroke-width':'1.0', 'stroke':'none', 'fill':'none'}
                for key in styledefaults.keys():
                    sst.setdefault(key,styledefaults[key])
                    est.setdefault(key,styledefaults[key])
                isnotplain = lambda x: not (x=='none' or x[:1]=='#')
                if isnotplain(sst['stroke']) or isnotplain(est['stroke']) or (sst['stroke']=='none' and est['stroke']=='none'):
                    dostroke = False
                if isnotplain(sst['fill']) or isnotplain(est['fill']) or (sst['fill']=='none' and est['fill']=='none'):
                    dofill = False
                if dostroke:
                    if sst['stroke']=='none':
                        sst['stroke-width'] = '0.0'
                        sst['stroke-opacity'] = '0.0'
                        sst['stroke'] = est['stroke'] 
                    elif est['stroke']=='none':
                        est['stroke-width'] = '0.0'
                        est['stroke-opacity'] = '0.0'
                        est['stroke'] = sst['stroke'] 
                if dofill:
                    if sst['fill']=='none':
                        sst['fill-opacity'] = '0.0'
                        sst['fill'] = est['fill'] 
                    elif est['fill']=='none':
                        est['fill-opacity'] = '0.0'
                        est['fill'] = sst['fill'] 

                    

            if self.options.method == 2:
                #subdivide both paths into segments of relatively equal lengths
                slengths, stotal = csplength(start)
                elengths, etotal = csplength(end)
                lengths = {}
                t = 0
                for sp in slengths:
                    for l in sp:
                        t += l / stotal
                        lengths.setdefault(t,0)
                        lengths[t] += 1
                t = 0
                for sp in elengths:
                    for l in sp:
                        t += l / etotal
                        lengths.setdefault(t,0)
                        lengths[t] += -1
                sadd = [k for (k,v) in lengths.iteritems() if v < 0]
                sadd.sort()
                eadd = [k for (k,v) in lengths.iteritems() if v > 0]
                eadd.sort()

                t = 0
                s = [[]]
                for sp in slengths:
                    if not start[0]:
                        s.append(start.pop(0))
                    s[-1].append(start[0].pop(0))
                    for l in sp:
                        pt = t
                        t += l / stotal
                        if sadd and t > sadd[0]:
                            while sadd and sadd[0] < t:
                                nt = (sadd[0] - pt) / (t - pt)
                                bezes = cspbezsplitatlength(s[-1][-1][:],start[0][0][:], nt)
                                s[-1][-1:] = bezes[:2]
                                start[0][0] = bezes[2]
                                pt = sadd.pop(0)
                        s[-1].append(start[0].pop(0))
                t = 0
                e = [[]]
                for sp in elengths:
                    if not end[0]:
                        e.append(end.pop(0))
                    e[-1].append(end[0].pop(0))
                    for l in sp:
                        pt = t
                        t += l / etotal
                        if eadd and t > eadd[0]:
                            while eadd and eadd[0] < t:
                                nt = (eadd[0] - pt) / (t - pt)
                                bezes = cspbezsplitatlength(e[-1][-1][:],end[0][0][:], nt)
                                e[-1][-1:] = bezes[:2]
                                end[0][0] = bezes[2]
                                pt = eadd.pop(0)
                        e[-1].append(end[0].pop(0))
                start = s[:]
                end = e[:]
            else:
                #which path has fewer segments?
                lengthdiff = numsegs(start) - numsegs(end)
                #swap shortest first
                if lengthdiff > 0:
                    start, end = end, start
                #subdivide the shorter path
                for x in range(abs(lengthdiff)):
                    maxlen = 0
                    subpath = 0
                    segment = 0
                    for y in range(len(start)):
                        for z in range(1, len(start[y])):
                            leng = bezlenapprx(start[y][z-1], start[y][z])
                            if leng > maxlen:
                                maxlen = leng
                                subpath = y
                                segment = z
                    sp1, sp2 = start[subpath][segment - 1:segment + 1]
                    start[subpath][segment - 1:segment + 1] = cspbezsplit(sp1, sp2)
                #if swapped, swap them back
                if lengthdiff > 0:
                    start, end = end, start
            
            #break paths so that corresponding subpaths have an equal number of segments
            s = [[]]
            e = [[]]
            while start and end:
                if start[0] and end[0]:
                    s[-1].append(start[0].pop(0))
                    e[-1].append(end[0].pop(0))
                elif end[0]:
                    s.append(start.pop(0))
                    e[-1].append(end[0][0])
                    e.append([end[0].pop(0)])
                elif start[0]:
                    e.append(end.pop(0))
                    s[-1].append(start[0][0])
                    s.append([start[0].pop(0)])
                else:
                    s.append(start.pop(0))
                    e.append(end.pop(0))
    
            if self.options.dup:
                steps = [0] + steps + [1]    
            #create an interpolated path for each interval
            group = inkex.etree.SubElement(self.current_layer,inkex.addNS('g','svg'))    
            for time in steps:
                interp = []
                #process subpaths
                for ssp,esp in zip(s, e):
                    if not (ssp or esp):
                        break
                    interp.append([])
                    #process superpoints
                    for sp,ep in zip(ssp, esp):
                        if not (sp or ep):
                            break
                        interp[-1].append([])
                        #process points
                        for p1,p2 in zip(sp, ep):
                            if not (sp or ep):
                                break
                            interp[-1][-1].append(interppoints(p1, p2, time))

                #remove final subpath if empty.
                if not interp[-1]:
                    del interp[-1]

                #basic style tweening
                if self.options.style:
                    basestyle['opacity'] = tweenstylefloat('opacity',sst,est,time)
                    if dostroke:
                        basestyle['stroke-opacity'] = tweenstylefloat('stroke-opacity',sst,est,time)
                        basestyle['stroke-width'] = self.tweenstyleunit('stroke-width',sst,est,time)
                        basestyle['stroke'] = tweenstylecolor('stroke',sst,est,time)
                    if dofill:
                        basestyle['fill-opacity'] = tweenstylefloat('fill-opacity',sst,est,time)
                        basestyle['fill'] = tweenstylecolor('fill',sst,est,time)
                attribs = {'style':simplestyle.formatStyle(basestyle),'d':cubicsuperpath.formatPath(interp)}
                new = inkex.etree.SubElement(group,inkex.addNS('path','svg'), attribs)