Beispiel #1
0
def realistic_stitch(start, end):
    """Generate a stitch vector path given a start and end point."""

    end = Point(*end)
    start = Point(*start)

    stitch_length = (end - start).length()
    stitch_center = Point((end.x + start.x) / 2.0, (end[1] + start[1]) / 2.0)
    stitch_direction = (end - start)
    stitch_angle = math.atan2(stitch_direction.y,
                              stitch_direction.x) * (180 / pi)

    stitch_length = max(0, stitch_length - 0.2 * PIXELS_PER_MM)

    # create the path by filling in the length in the template
    path = inkex.Path(stitch_path % stitch_length).to_arrays()

    # rotate the path to match the stitch
    rotation_center_x = -stitch_length / 2.0
    rotation_center_y = stitch_height / 2.0

    path = inkex.Path(path).rotate(stitch_angle,
                                   (rotation_center_x, rotation_center_y))

    # move the path to the location of the stitch
    path = inkex.Path(path).translate(stitch_center.x - rotation_center_x,
                                      stitch_center.y - rotation_center_y)

    return str(path)
Beispiel #2
0
def mesh_to_grid(corners, hlines, vlines):
    """Construct mesh grid with CSP paths."""
    rows = len(corners) - 1
    cols = len(corners[0]) - 1
    gridline_csps = []
    # horizontal
    path = 'M {},{}'.format(*corners[0][0])
    for edge_path in hlines[0]:
        path = ' '.join([path, edge_path])
    gridline_csps.append(inkex.Path(path).to_superpath())
    for i in range(1, rows + 1):
        path = 'M {},{}'.format(*corners[i][-1])
        for edge_path in reversed(hlines[i]):
            path = ' '.join([path, edge_path])
        gridline_csps.append(inkex.Path(path).to_superpath())
    # vertical
    path = 'M {},{}'.format(*corners[-1][0])
    for edge_path in reversed(vlines[0]):
        path = ' '.join([path, edge_path])
    gridline_csps.append(inkex.Path(path).to_superpath())
    for j in range(1, cols + 1):
        path = 'M {},{}'.format(*corners[0][j])
        for edge_path in vlines[j]:
            path = ' '.join([path, edge_path])
        gridline_csps.append(inkex.Path(path).to_superpath())
    return gridline_csps
    def drawCrossHairs(self, layer, x, y, style = None, rad = 10):
        # create crosshair group
        group = etree.SubElement(layer, inkex.addNS('g','svg'))
        
        # add circle (actually diamond...)
        if style:
            circle = etree.SubElement(group,inkex.addNS('path','svg'))
            circle.set('style', style)
            circleLine = [ 
                ['M',[x-rad/2,y]],
                ['L',[x,y-rad/2]],
                ['L',[x+rad/2,y]],
                ['L',[x,y+rad/2]],
                ['Z',[]]
            ]
            circle.set('d', str(inkex.Path(circleLine)))

        # add crosshairs
        crosshairX = etree.SubElement(group,inkex.addNS('path','svg'))
        crosshairY = etree.SubElement(group,inkex.addNS('path','svg'))

        chxLine = [['M',[x,y-rad]],['L',[x,y+rad]]]
        chyLine = [['M',[x-rad,y]],['L',[x+rad,y]]]

        crosshairX.set('d', str(inkex.Path(chxLine))) 
        crosshairX.set('style', 'stroke:#CC0000;stroke-width:1.0px;')
        crosshairY.set('d', str(inkex.Path(chyLine))) 
        crosshairY.set('style', 'stroke:#CC0000;stroke-width:1.0px;')
Beispiel #4
0
    def effect(self):
        zoom = self.svg.unittouu(str(self.options.zoom) + 'px')

        if self.options.randomize:
            imagelist = generate_random_string(self.options.text, zoom)
        else:
            tokens = tokenize(self.options.text)
            imagelist = randomize_input_string(tokens, zoom)

        image = layoutstring(imagelist, zoom)

        if image:
            s = {'stroke': 'none', 'fill': '#000000'}

            new = inkex.PathElement(style=str(inkex.Style(s)),
                                    d=str(inkex.Path(image)))

            layer = self.svg.get_current_layer()
            layer.append(new)

            # compensate preserved transforms of parent layer
            if layer.getparent() is not None:
                mat = (
                    self.svg.get_current_layer().transform *
                    inkex.Transform([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]])).matrix
                new.transform *= -inkex.Transform(mat)
Beispiel #5
0
 def flatten_bezier(self):
     layerPath = '//svg:g[@inkscape:groupmode="layer"][@inkscape:label="Edge.Cuts"]'
     for layer in self.document.getroot().xpath(layerPath, namespaces=inkex.NSS):
         nodePath = 'descendant::svg:path'
         for node in layer.xpath(nodePath, namespaces=inkex.NSS):
             if node.tag == inkex.addNS('path','svg'):
                 d = node.get('d')
                 p = inkex.Path(d).to_superpath()
                 bezier.cspsubdiv(p, 0.01)
                 np = []
                 for sp in p:
                     first = True
                     for csp in sp:
                         cmd = 'L'
                         if first:
                             cmd = 'M'
                         first = False
                         np.append([cmd, [csp[1][0], csp[1][1]]])
                         node.set('d', str(inkex.Path(np)))
Beispiel #6
0
def fuse_subpaths(path_node):
    """Fuse subpaths of a path. Should only be used on unstroked paths"""
    path = path_node.path.to_arrays()

    if len(path) == 0:
        return

    i = 0
    initial_point = [path[i][1][-2], path[i][1][-1]]
    prev_end = initial_point[:]
    return_stack = []
    while i < len(path):
        # Remove any terminators: they are redundant
        if path[i][0] == "Z":
            path.remove(["Z", []])
            continue

        if path[i][0] == 'V':
            prev_end[0] = path[i][1][0]
            i += 1
            continue
        elif path[i][0] == 'H':
            prev_end[1] = path[i][1][0]
            i += 1
            continue
        elif path[1][0] != 'M' or i == 0:
            prev_end = path[i][1][-2:]
            i += 1
            continue

        # This element begins a new path - it should be a moveto
        assert (path[i][0] == 'M')

        # Swap it for a lineto
        path[i][0] = 'L'
        # If the old subpath has not been closed yet, close it
        if prev_end != initial_point:
            path.insert(i, ['L', initial_point])
            i += 1

        # Set the initial point of this subpath
        initial_point = path[i][1][-2:]

        # Append this point to the return stack
        return_stack.append(initial_point)
    # end while

    # Now pop the entire return stack
    while return_stack:
        el = ['L', return_stack.pop()]
        path.insert(i, el)
        i += 1

    path_d = str(inkex.Path(path))
    path_node.set("d", path_d)
 def plot_beam(self, beam: List[Ray], node: inkex.ShapeElement) -> None:
     path = inkex.Path()
     if len(beam) > 0:
         path += [Move(beam[0].origin[0], beam[0].origin[1])]
         for ray in beam:
             p1 = ray.origin + ray.travel * ray.direction
             path += [Line(p1[0], p1[1])]
     element = self._beam_layer.add(inkex.PathElement())
     # Need to convert to path to get the correct style for inkex.Use
     element.style = node.to_path_element().style
     element.path = path
Beispiel #8
0
 def process_path(self, element, matrix):
     """Apply the transformation to the selected path"""
     point = element.path.to_absolute().transform(
         element.composed_transform()).to_superpath()
     for subs in point:
         for csp in subs:
             csp[0] = self.project_point(csp[0], matrix)
             csp[1] = self.project_point(csp[1], matrix)
             csp[2] = self.project_point(csp[2], matrix)
     element.path = inkex.Path(point).transform(
         -element.composed_transform())
Beispiel #9
0
 def plot_beam(beam: List[Tuple[Ray, float]],
               node: inkex.ShapeElement) -> None:
     path = inkex.Path()
     if len(beam) > 0:
         path += [Move(beam[0][0].origin[0], beam[0][0].origin[1])]
         for ray, t in beam:
             p1 = ray.origin + t * ray.direction
             path += [Line(p1[0], p1[1])]
     element = node.getparent().add(inkex.PathElement())
     element.style = node.get("style")
     element.path = path.transform(-node.composed_transform())
Beispiel #10
0
 def plot_beam(self, beam: List[Tuple[Ray, float]],
               node: inkex.ShapeElement) -> None:
     path = inkex.Path()
     if len(beam) > 0:
         path += [Move(beam[0][0].origin[0], beam[0][0].origin[1])]
         for ray, t in beam:
             p1 = ray.origin + t * ray.direction
             path += [Line(p1[0], p1[1])]
     svg = self.document.getroot()
     element = svg.add(inkex.PathElement())
     element.style = node.get("style")
     element.path = path
    def parsePath(self, node, transforms, names):
        name = ""
        for n in names:
            name = n + "_" + name
        name = name + node.get("id")

        m2 = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
        for t in transforms:
            m = inkex.Transform(t).matrix
            m2 = inkex.Transform(m2) * inkex.Transform(m)

        m = inkex.Transform(node.get("transform")).matrix
        m2 = inkex.Transform(m2) * inkex.Transform(m)

        color = self.get_color(node)

        path = str(inkex.Path(inkex.Path(node.get('d')).to_arrays()))
        subpaths = path.split('M')

        for i in range(1, len(subpaths)):
            subpaths[i] = 'M ' + str.rstrip(subpaths[i])
            closed = subpaths[i][-1] in ['Z', 'z']

            csp = inkex.Path(subpaths[i]).to_arrays()
            csp = inkex.Path(csp).transform(m2).to_arrays()

            if closed:
                self.closed2curves(csp)
            else:
                self.opened2curves(csp)

            vertices = self.cast2spine(csp, closed)

            if len(vertices) >= 9 and closed or len(
                    vertices) >= 6 and not closed:
                self.path2json(name + "_" + str(i), closed, color, vertices)
            else:
                inkex.debug("skipping " + name + "_" + str(i) +
                            ": vertex count < 6 (" + str(len(vertices)) + ")")
Beispiel #12
0
def mesh_to_outline(corners, hlines, vlines):
    """Construct mesh outline as CSP path."""
    outline_csps = []
    path = 'M {},{}'.format(*corners[0][0])
    for edge_path in hlines[0]:
        path = ' '.join([path, edge_path])
    for edge_path in vlines[-1]:
        path = ' '.join([path, edge_path])
    for edge_path in reversed(hlines[-1]):
        path = ' '.join([path, edge_path])
    for edge_path in reversed(vlines[0]):
        path = ' '.join([path, edge_path])
    outline_csps.append(inkex.Path(path).to_superpath())
    return outline_csps
Beispiel #13
0
def draw_poly(pts, face, st, name, parent):
    """Draw polygone"""
    style = {'stroke': '#000000', 'stroke-width': str(st.th), 'stroke-linejoin': st.linejoin,
             'stroke-opacity': st.s_opac, 'fill': st.fill, 'fill-opacity': st.f_opac}
    path = inkex.Path()
    for facet in face:
        if not path:  # for first point
            path.append(Move(pts[facet - 1][0], -pts[facet - 1][1]))
        else:
            path.append(Line(pts[facet - 1][0], -pts[facet - 1][1]))
    path.close()

    poly = parent.add(inkex.PathElement())
    poly.label = name
    poly.style = style
    poly.path = path
    def effect(self):
        clippingLineSegments = None
        pathTag = inkex.addNS('path', 'svg')
        groupTag = inkex.addNS('g', 'svg')
        self.error_messages = []
        for id in self.options.ids:  # the selection, top-down
            node = self.svg.selected[id]
            if node.tag == pathTag:
                path = self.fixVHbehaviour(node)
                if clippingLineSegments is None:  # first path is the clipper
                    #(clippingLineSegments, errors) = self.simplepathToLineSegments(node.path.to_arrays())
                    (clippingLineSegments,
                     errors) = self.simplepathToLineSegments(path)
                    self.error_messages.extend(
                        ['{}: {}'.format(id, err) for err in errors])
                else:
                    # do all the work!
                    #segmentsToClip, errors = self.simplepathToLineSegments(node.path.to_arrays())
                    segmentsToClip, errors = self.simplepathToLineSegments(
                        path)
                    self.error_messages.extend(
                        ['{}: {}'.format(id, err) for err in errors])
                    clippedSegments = self.clipLineSegments(
                        segmentsToClip, clippingLineSegments)
                    if len(clippedSegments) != 0:
                        path = str(
                            inkex.Path(
                                self.linesgmentsToSimplePath(clippedSegments)))
                        node.set('d', path)
                    else:
                        # don't put back an empty path(?)  could perhaps put move, move?
                        inkex.errormsg(
                            'Object {} clipped to nothing, will not be updated.'
                            .format(node.get('id')))
            elif node.tag == groupTag:  # we don't look inside groups for paths
                inkex.errormsg(
                    'Group object {} will be ignored. Please ungroup before running the script.'
                    .format(id))
            else:  # something else
                inkex.errormsg(
                    'Object {} is not of type path ({}), and will be ignored. Current type "{}".'
                    .format(id, pathTag, node.tag))

        for error in self.error_messages:
            inkex.errormsg(error)
Beispiel #15
0
def flip(sp, cb, param):
    # print('flip before +' + str(sp))
    p = inkex.Path(sp)
    cb(p, param)
    del sp[:]

    prev = Vector2d()
    prev_prev = Vector2d()
    first = Vector2d()

    for i, seg in enumerate(p):
        if i == 0:
            first = seg.end_point(first, prev)
        cps = []
        for cp in seg.control_points(first, prev, prev_prev):
            prev_prev = prev
            prev = cp
            cps.extend(cp)
        sp.append([seg.letter, cps])
Beispiel #16
0
def draw(stack):  # draw a character based on a tree stack
    state = stack.pop(0)
    # print state,

    image, width, height = load_path(font + syntax[state][0])  # load the image
    if stack[0] != "[":  # terminal stack element
        if len(syntax[state]) == 1:  # this state is a terminal node
            return image, width, height
        else:
            substack = generate(state)  # generate random substack
            return draw(substack)  # draw random substack
    else:
        # inkex.debug("[")
        stack.pop(0)
        images = []  # list of daughter images
        nodes = []  # list of daughter names
        while stack[0] != "]":  # for all nodes in stack
            newstate = stack[0]  # the new state
            newimage, width, height = draw(stack)  # draw the daughter state
            if newimage:
                tfimage = mxfm(newimage, width, height,
                               stack)  # maybe transform daughter state
                images.append([tfimage, width,
                               height])  # list of daughter images
                nodes.append(newstate)  # list of daughter nodes
            else:
                # inkex.debug(("recurse on",newstate,"failed")) # this should never happen
                return None, 0, 0
        rule = findrule(state, nodes)  # find the rule for this subtree

        for i in range(0, len(images)):
            currimg, width, height = images[i]

            if currimg:
                # box = inkex.Path(currimg).bounding_box()
                dx = rule[i][1] * units
                dy = rule[i][2] * units
                # newbox = ((box[0]+dx),(box[1]+dy),(box[2]+dx),(box[3]+dy))
                currimg = (inkex.Path(currimg).translate(dx, dy)).to_arrays()
                image = combinePaths(image, currimg)

        stack.pop(0)
        return image, width, height
Beispiel #17
0
    def createRoundedRect(parent, bbox, corner_radii):
        x, y, w, h = bbox
        tl, tr, br, bl = corner_radii

        pathEl = etree.SubElement(parent, inkex.addNS("path", "svg"))
        d = []

        if tl > 0:
            d.append(["M", [x + tl, y]])
        else:
            d.append(["M", [x, y]])

        if tr > 0:
            d.append(["L", [x + w - tr, y]])
            d.append(["Q", [x + w, y, x + w, y + tr]])
        else:
            d.append(["L", [x + w, y]])

        if br > 0:
            d.append(["L", [x + w, y + h - br]])
            d.append(["Q", [x + w, y + h, x + w - br, y + h]])
        else:
            d.append(["L", [x + w, y + h]])

        if bl > 0:
            d.append(["L", [x + bl, y + h]])
            d.append(["Q", [x, y + h, x, y + h - bl]])
        else:
            d.append(["L", [x, y + h]])

        if tl > 0:
            d.append(["L", [x, y + tl]])
            d.append(["Q", [x, y, x + tl, y]])
        else:
            d.append(["L", [x, y]])
            d.append(["z", []])

        pathEl.set("d", str(inkex.Path(d)))

        return pathEl
Beispiel #18
0
    def snap_path_pos(self, elem, parent_transform=None):
        path = elem.original_path.to_arrays()
        transform = elem.transform * Transform(parent_transform)
        bbox = elem.bounding_box()
        min_xy, max_xy = bbox.minimum, bbox.maximum

        fractional_offset = min_xy[0] - round(min_xy[0]), min_xy[1] - round(
            min_xy[1]) - self.document_offset
        fractional_offset = transform_dimensions(transform,
                                                 fractional_offset[0],
                                                 fractional_offset[1],
                                                 inverse=True)

        for i in range(len(path)):
            self.transform_path_node(-Transform(translate=fractional_offset),
                                     path, i)

        path = str(inkex.Path(path))
        if elem.get('inkscape:original-d'):
            elem.set('inkscape:original-d', path)
        else:
            elem.set('d', path)
Beispiel #19
0
def layoutstring(imagelist,
                 zoom):  # layout string of letter-images using optical kerning
    kernlist = []
    length = zoom
    for entry in imagelist:
        if entry == " ":  # leaving room for " " space characters
            length = length + (zoom * render_alphabetsoup_config.space)
        else:
            image, width, height = entry
            length = length + width + zoom  # add letter length to overall length
            kernlist.append(optikern(
                image, width, zoom))  # append kerning data for this image

    workspace = None

    position = zoom
    for i in range(0, len(kernlist)):
        while imagelist[i] == " ":
            position = position + (zoom * render_alphabetsoup_config.space)
            imagelist.pop(i)
        image, width, height = imagelist[i]

        # set the kerning
        if i == 0:
            kern = 0  # for first image, kerning is zero
        else:
            kerncompare = []  # kerning comparison array
            for j in range(0, len(kernlist[i][0])):
                kerncompare.append(kernlist[i][0][j] + kernlist[i - 1][1][j])
            kern = min(kerncompare)

        position = position - kern  # move position back by kern amount
        thisimage = copy.deepcopy(image)
        thisimage = (inkex.Path(thisimage).translate(position, 0)).to_arrays()
        workspace = combinePaths(workspace, thisimage)
        position = position + width + zoom  # advance position by letter width

    return workspace
Beispiel #20
0
    def makeface(last, segment, facegroup, delx, dely):
        """translate path segment along vector"""
        elem = facegroup.add(inkex.PathElement())

        npt = segment.translate([delx, dely])

        # reverse direction of path segment
        if isinstance(segment, Curve):
            rev = Curve(npt.x3, npt.y3, npt.x2, npt.y2, last[0] + delx,
                        last[1] + dely)
        elif isinstance(segment, Line):
            rev = Line(last[0] + delx, last[1] + dely)
        else:
            raise RuntimeError("Unexpected segment type {}".format(
                type(segment)))

        elem.path = inkex.Path([
            Move(last[0], last[1]),
            segment,
            npt.to_line(Vector2d()),
            rev,
            ZoneClose(),
        ])
Beispiel #21
0
def mesh_corners(meshgradient):
    """Return list of mesh patch corners, patch paths."""
    rows = len(meshgradient)
    cols = len(meshgradient[0])
    # first corner of mesh gradient
    corner_x = float(meshgradient.get('x', '0.0'))
    corner_y = float(meshgradient.get('y', '0.0'))
    # init corner and meshpatch lists
    corners = [[None for _ in range(cols + 1)] for _ in range(rows + 1)]
    corners[0][0] = [corner_x, corner_y]
    meshpatch_csps = []
    for meshrow in range(rows):
        for meshpatch in range(cols):
            # get start point for current meshpatch edges
            if meshrow == 0:
                first_corner = corners[meshrow][meshpatch]
            if meshrow > 0:
                first_corner = corners[meshrow][meshpatch + 1]
            # parse path of meshpatch edges
            path = 'M {},{}'.format(*first_corner)
            for edge in meshgradient[meshrow][meshpatch]:
                path = ' '.join([path, edge.get('path')])
            csp = inkex.Path(path).to_superpath()
            # update corner list with current meshpatch
            if meshrow == 0:
                corners[meshrow][meshpatch + 1] = csp[0][1][1]
                corners[meshrow + 1][meshpatch + 1] = csp[0][2][1]
                if meshpatch == 0:
                    corners[meshrow + 1][meshpatch] = csp[0][3][1]
            if meshrow > 0:
                corners[meshrow][meshpatch + 1] = csp[0][0][1]
                corners[meshrow + 1][meshpatch + 1] = csp[0][1][1]
                if meshpatch == 0:
                    corners[meshrow + 1][meshpatch] = csp[0][2][1]
            # append to list of meshpatch csp
            meshpatch_csps.append(csp)
    return corners, meshpatch_csps
Beispiel #22
0
def mesh_to_faces(corners, hlines, vlines):
    """Construct mesh faces with CSP paths."""
    rows = len(corners) - 1
    cols = len(corners[0]) - 1
    face_csps = []
    for row in range(rows):
        for col in range(cols):
            # init new face
            face = []
            # init edge paths
            edge_t = hlines[row][col]
            edge_b = hlines[row + 1][col]
            edge_l = vlines[col][row]
            edge_r = vlines[col + 1][row]
            # top edge, first
            if row == 0:
                path = 'M {},{}'.format(*corners[row][col])
                path = ' '.join([path, edge_t])
                face.append(inkex.Path(path).to_superpath()[0])
            else:
                path = 'M {},{}'.format(*corners[row][col + 1])
                path = ' '.join([path, edge_t])
                face.append(reverse_path(inkex.Path(path).to_superpath())[0])
            # right edge
            path = 'M {},{}'.format(*corners[row][col + 1])
            path = ' '.join([path, edge_r])
            join_path(face, -1, inkex.Path(path).to_superpath(), 0)
            # bottom edge
            path = 'M {},{}'.format(*corners[row + 1][col + 1])
            path = ' '.join([path, edge_b])
            join_path(face, -1, inkex.Path(path).to_superpath(), 0)
            # left edge
            if col == 0:
                path = 'M {},{}'.format(*corners[row + 1][col])
                path = ' '.join([path, edge_l])
                join_path(face, -1, inkex.Path(path).to_superpath(), 0)
            else:
                path = 'M {},{}'.format(*corners[row][col])
                path = ' '.join([path, edge_l])
                join_path(face, -1,
                          reverse_path(inkex.Path(path).to_superpath()), 0)
            # append face to output list
            face_csps.append(face)
    return face_csps
Beispiel #23
0
    def exportEdgeCut(self, kicad_mod=False):
        x0 = 0
        y0 = 0
        mirror = 1.0

        line_type = "fp_line" if kicad_mod else "gr_line"

        kicad_edgecut_string = ""

        i = 0
        layerPath = '//svg:g[@inkscape:groupmode="layer"]'

        if (self.options.autoflatten):
            self.flatten_bezier()

        for layer in self.document.getroot().xpath(layerPath, namespaces=inkex.NSS):
            i += 1

            label_attrib_name = "{%s}label" % layer.nsmap['inkscape']
            if label_attrib_name not in layer.attrib:
                continue

            layer_name = (layer.attrib[label_attrib_name])

            if layer_name != "Edge.Cuts":
                continue

            layer_trans = layer.get('transform')
            if layer_trans:
                layer_m = Transform(layer_trans).matrix
            else:
                layer_m = IDENTITY_MATRIX

            nodePath = ('//svg:g[@inkscape:groupmode="layer"][%d]/descendant::svg:path') % i
            for node in self.document.getroot().xpath(nodePath, namespaces=inkex.NSS):
                d = node.get('d')
                p = inkex.Path(d).to_arrays()

                points = []
                if p:
                    #sanity check
                    if p[0][0] == 'M':
                        t = node.get('transform')
                        if t:
                            m = Transform(t).matrix
                            trans = (Transform(layer_m)*Transform(m)).matrix
                        else:
                            trans = layer_m

                        for path in p:
                            if path[0] != "Z":
                                x = (path[1][0])
                                y = (path[1][1])
                                xy = Transform(trans).apply_to_point([x,y])
                                points.append(self.coordToKicad([(xy[0]-x0), xy[1]*mirror-y0]))

                        points_count = len(points)
                        points.append(points[0])

                        for x in range (0, points_count):
                            kicad_edgecut_string = kicad_edgecut_string + ("(%s (start %f %f) (end %f %f) (layer Edge.Cuts) (width 0.1))\n"  % (line_type, points[x][0],points[x][1],points[x+1][0],points[x+1][1]))

        return kicad_edgecut_string
Beispiel #24
0
 def dxf_path_to_point(self, layer, p):
     bbox = inkex.Path(p).bounding_box() or inkex.BoundingBox(0, 0)
     x, y = bbox.center
     self.dxf_point(layer, x, y)
Beispiel #25
0
    def effect(self):
        paths = []
        for node in self.svg.selection.filter(inkex.PathElement):
            paths.append(node)
        if len(paths) < 2:
            raise inkex.AbortExtension("Need at least 2 paths selected")

        for path in paths:
            path.apply_transform()

        pts = [node.path.to_superpath() for node in paths]

        for n1 in range(0, len(paths)):
            for n2 in range(n1 + 1, len(paths)):
                verts = []
                for i in range(0, min(map(len, pts))):
                    comp = []
                    for j in range(0, min(len(pts[n1][i]), len(pts[n2][i]))):
                        comp.append([pts[n1][i][j][1][-2:], pts[n2][i][j][1][-2:]])
                    verts.append(comp)

                if self.options.mode.lower() == 'lines':
                    line = []
                    for comp in verts:
                        for n, v in enumerate(comp):
                            line += [('M', v[0])]
                            line += [('L', v[1])]
                    ele = inkex.PathElement()
                    paths[0].xpath('..')[0].append(ele)
                    ele.set('d', str(inkex.Path(line)))
                    style = {
                        'fill': 'none',
                        'stroke': '#000000',
                        'stroke-opacity': 1,
                        'stroke-width': self.svg.unittouu('1px'),
                    }
                    ele.set('style', str(inkex.Style(style)))
                elif self.options.mode.lower() == 'polygons':
                    g = inkex.Group()
                    style = {
                        'fill': '#000000',
                        'fill-opacity': 0.3,
                        'stroke': '#000000',
                        'stroke-opacity': 0.6,
                        'stroke-width': self.svg.unittouu('2px'),
                    }
                    g.set('style', str(inkex.Style(style)))
                    paths[0].xpath('..')[0].append(g)
                    for comp in verts:
                        for n, v in enumerate(comp):
                            nn = n + 1
                            if nn == len(comp):
                                nn = 0
                            line = []
                            line += [('M', comp[n][0])]
                            line += [('L', comp[n][1])]
                            line += [('L', comp[nn][1])]
                            line += [('L', comp[nn][0])]
                            line += [('L', comp[n][0])]
                            ele = inkex.PathElement()
                            g.append(ele)
                            ele.set('d', str(inkex.Path(line)))
Beispiel #26
0
    def generate(self):
        opts = self.options
        d = self.to_document_units(opts.diameter, opts.diameter_unit)
        f = self.to_document_units(opts.focal_length, opts.focal_length_unit)
        e = self.to_document_units(opts.edge_thickness,
                                   opts.edge_thickness_unit)
        optical_index = opts.optical_index

        lens_path = []
        if opts.lens_type == 'plano_con':
            # Radius of curvature from Lensmaker's equation
            roc = (optical_index - 1) * abs(f)
            if 2 * roc < d:
                inkex.utils.errormsg(
                    "Focal length is too short or diameter is too large.")
                return None
            elif (roc**2 - (d / 2)**2)**.5 - roc < -e and f < 0:
                inkex.utils.errormsg("Edge thickness is too small.")
                return None
            else:
                sweep = 1 if f < 0 else 0
                # see arc_to_path in inkex/paths.py for description of
                # parameters
                lens_path = arc_to_path([-d / 2, 0],
                                        [roc, roc, 0., 0, sweep, +d / 2, 0])
                lens_path += [
                    [[+d / 2, 0], [+d / 2, 0], [+d / 2, -e]],
                    [[+d / 2, -e], [+d / 2, -e], [-d / 2, -e]],
                    [[+d / 2, -e], [-d / 2, -e], [-d / 2, +e]],
                ]
                # no need to close the path correctly as it's done after
        elif opts.lens_type == 'bi_con':
            roc = (optical_index - 1) * abs(f) \
                  * (1 + (1 - e / f / optical_index) ** .5)
            if 2 * roc < d:
                inkex.utils.errormsg(
                    "Focal length is too short or diameter is too large.")
                return None
            elif (roc**2 - (d / 2)**2)**.5 - roc < -e / 2 and f < 0:
                inkex.utils.errormsg("Edge thickness is too small.")
                return None
            else:
                sweep = 1 if f < 0 else 0
                lens_path = arc_to_path([-d / 2, 0],
                                        [roc, roc, 0., 0, sweep, +d / 2, 0])
                lens_path += [
                    [[+d / 2, 0], [+d / 2, 0], [+d / 2, -e]],
                    [[+d / 2, -e], [+d / 2, -e], [+d / 2, -e]],
                ]
                lens_path += arc_to_path([+d / 2, -e],
                                         [roc, roc, 0., 0, sweep, -d / 2, -e])
                lens_path += [
                    [[-d / 2, -e], [-d / 2, -e], [-d / 2, 0]],
                    [[-d / 2, -e], [-d / 2, 0], [-d / 2, 0]],
                ]

        lens = inkex.PathElement()
        lens.style = self.style
        closed_path = inkex.Path(inkex.CubicSuperPath([lens_path]))
        closed_path.close()
        lens.path = closed_path.transform(Transform('rotate(90)'))
        set_description(lens, f"optics:glass:{optical_index}")
        yield lens
Beispiel #27
0
    def effect(self):
        # Check that elements have been selected
        if not self.svg.selected:
            inkex.errormsg(_("Please select objects!"))
            return

        linestyle = {
            'stroke': '#000000',
            'stroke-width': str(self.svg.unittouu('1px')),
            'fill': 'none',
            'stroke-linecap': 'round',
            'stroke-linejoin': 'round'
        }

        facestyle = {
            'stroke': '#000000',
            'stroke-width': str(self.svg.unittouu('1px')),
            'fill': 'none',
            'stroke-linecap': 'round',
            'stroke-linejoin': 'round'
        }

        parent_group = self.svg.selection.first().getparent()
        trans = parent_group.composed_transform()

        invtrans = None
        if trans:
            invtrans = -trans

        # Recovery of the selected objects
        pts = []
        nodes = []
        seeds = []
        fills = []

        for node in self.svg.selected.values():
            nodes.append(node)
            bbox = node.bounding_box()
            if bbox:
                center_x, center_y = bbox.center
                point = [center_x, center_y]
                if trans:
                    point = trans.apply_to_point(point)
                pts.append(Point(*point))
                if self.options.delaunayFillOptions != "delaunay-no-fill":
                    fills.append(node.style.get('fill', 'none'))
                seeds.append(Point(center_x, center_y))

        # Creation of groups to store the result
        if self.options.diagramType != 'Delaunay':
            # Voronoi
            group_voronoi = parent_group.add(Group())
            group_voronoi.set('inkscape:label', 'Voronoi')
            if invtrans:
                group_voronoi.transform *= invtrans
        if self.options.diagramType != 'Voronoi':
            # Delaunay
            group_delaunay = parent_group.add(Group())
            group_delaunay.set('inkscape:label', 'Delaunay')

        # Clipping box handling
        if self.options.diagramType != 'Delaunay':
            # Clipping bounding box creation
            group_bbox = sum([node.bounding_box() for node in nodes], None)

            # Clipbox is the box to which the Voronoi diagram is restricted
            if self.options.clip_box == 'Page':
                svg = self.document.getroot()
                width = self.svg.unittouu(svg.get('width'))
                height = self.svg.unittouu(svg.get('height'))
                clip_box = (0, width, 0, height)
            else:
                clip_box = (group_bbox.left,
                            group_bbox.right,
                            group_bbox.top,
                            group_bbox.bottom)

            # Safebox adds points so that no Voronoi edge in clip_box is infinite
            safe_box = (2 * clip_box[0] - clip_box[1],
                        2 * clip_box[1] - clip_box[0],
                        2 * clip_box[2] - clip_box[3],
                        2 * clip_box[3] - clip_box[2])
            pts.append(Point(safe_box[0], safe_box[2]))
            pts.append(Point(safe_box[1], safe_box[2]))
            pts.append(Point(safe_box[1], safe_box[3]))
            pts.append(Point(safe_box[0], safe_box[3]))

            if self.options.showClipBox:
                # Add the clip box to the drawing
                rect = group_voronoi.add(Rectangle())
                rect.set('x', str(clip_box[0]))
                rect.set('y', str(clip_box[2]))
                rect.set('width', str(clip_box[1] - clip_box[0]))
                rect.set('height', str(clip_box[3] - clip_box[2]))
                rect.style = linestyle

        # Voronoi diagram generation
        if self.options.diagramType != 'Delaunay':
            vertices, lines, edges = voronoi.computeVoronoiDiagram(pts)
            for edge in edges:
                vindex1, vindex2 = edge[1:]
                if (vindex1 < 0) or (vindex2 < 0):
                    continue  # infinite lines have no need to be handled in the clipped box
                else:
                    segment = self.clip_edge(vertices, lines, edge, clip_box)
                    # segment = [vertices[vindex1],vertices[vindex2]] # deactivate clipping
                    if len(segment) > 1:
                        x1, y1 = segment[0]
                        x2, y2 = segment[1]
                        cmds = [['M', [x1, y1]], ['L', [x2, y2]]]
                        path = group_voronoi.add(PathElement())
                        path.set('d', str(inkex.Path(cmds)))
                        path.style = linestyle

        if self.options.diagramType != 'Voronoi':
            triangles = voronoi.computeDelaunayTriangulation(seeds)
            i = 0
            if self.options.delaunayFillOptions == "delaunay-fill":
                random.seed("inkscape")
            for triangle in triangles:
                pt1 = seeds[triangle[0]]
                pt2 = seeds[triangle[1]]
                pt3 = seeds[triangle[2]]
                cmds = [['M', [pt1.x, pt1.y]],
                        ['L', [pt2.x, pt2.y]],
                        ['L', [pt3.x, pt3.y]],
                        ['Z', []]]
                if self.options.delaunayFillOptions == "delaunay-fill" \
                    or self.options.delaunayFillOptions == "delaunay-fill-random":
                    facestyle = {
                        'stroke': fills[triangle[random.randrange(0, 2)]],
                        'stroke-width': str(self.svg.unittouu('0.005px')),
                        'fill': fills[triangle[random.randrange(0, 2)]],
                        'stroke-linecap': 'round',
                        'stroke-linejoin': 'round'
                    }
                path = group_delaunay.add(PathElement())
                path.set('d', str(inkex.Path(cmds)))
                path.style = facestyle
                i += 1
 def addPathToInkscape(self, path, parent, color):
     elem = parent.add(inkex.PathElement())
     elem.style = {'stroke': color, 'stroke-width': 2, 'fill': 'none'}
     elem.path = inkex.Path(path)
Beispiel #29
0
 def validation_warnings(self):
     repr_point = next(inkex.Path(self.parse_path()).end_points)
     yield PatternWarning(repr_point)
Beispiel #30
0
def draw_crop_scale(stack, zoom):  # draw, crop and scale letter image
    image, width, height = draw(stack)
    bbox = inkex.Path(image).bounding_box()
    image = (inkex.Path(image).translate(-bbox.x.minimum, 0)).to_arrays()
    image = (inkex.Path(image).scale(zoom / units, zoom / units)).to_arrays()
    return image, bbox.width, bbox.height