예제 #1
0
def convert_to_svg(input_file, max_dist, min_radius):

    # to handle numpy warnings as errors
    warnings.filterwarnings("error")
    paths, attributes, svg_attributes = spt.svg2paths2(input_file)

    new_paths = []
    for idx, path in enumerate(paths):
        logging.info('=== path {}'.format(idx))
        new_path = spt.Path()
        logging.info(path)
        for jdx, segment in enumerate(path):
            logging.info("   === segment {}".format(jdx))
            logging.info(segment)
            if isinstance(segment, spt.Line):
                # export as is
                new_path.append(segment)
                logging.info("Found line in Path {} segment {}".format(idx, jdx))
            elif isinstance(segment, spt.CubicBezier):
                # approximate cubic Bezier by NB_ARCS
                try:
                    a = _bezier_to_svg_arc(segment, max_dist, min_radius)
                except Warning:
                    logging.info("error in path {} segment {}".format(idx, jdx))
                    logging.info(segment)
                    raise
                new_path  += a
                logging.info("Found Bezier curve in Path {} segment {}".format(idx, jdx))
            else:
                logging.error("segment type {} is not supported".format(type(segment)))
                sys.exit()
        new_paths.append(new_path)

    return new_paths, svg_attributes
예제 #2
0
파일: body.py 프로젝트: korellas/nek-type-a
def svg_load(svg_file, invert=True):
    paths, attributes, svg_attributes = svg2paths2(f'{SVG_PATH}{svg_file}.svg')
    polys = list(map(lambda path: (
        list(map(lambda segment: (segment.start.real, (-1 if invert else 1) * segment.start.imag), path))), paths))
    min_x = reduce(lambda acc, i: min(acc, i[0]), itertools.chain.from_iterable(polys), sys.maxsize)
    max_y = reduce(lambda acc, i: max(acc, i[1]), itertools.chain.from_iterable(polys), -sys.maxsize)
    return polys, min_x, max_y
예제 #3
0
def compact(source, dest, px):
    paths, attributes, svg_attributes = svg2paths2(source)

    if len(paths) == 0:
        return

    # Get global bbox
    bboxes = numpy.array([
        # min_x, max_x, min_y, max_y
        path.bbox() for path in paths
    ])

    min_x, _____, min_y, _____ = numpy.min(bboxes, 0)
    _____, max_x, _____, max_y = numpy.max(bboxes, 0)

    min_x = math.floor(min_x)
    max_x = math.ceil(max_x)
    min_y = math.floor(min_y)
    max_y = math.ceil(max_y)

    # Bulk translate
    translated = [path.translated(complex(-min_x + px, 0)) for path in paths]

    wsvg(paths=translated,
         attributes=attributes,
         svg_attributes=svg_attributes,
         filename=dest)
예제 #4
0
def convert_to_dxf(input_file):
    doc = ezdxf.new("R2010")
    doc.units = units.MM
    msp = doc.modelspace()

    paths, attributes, svg_attributes = spt.svg2paths2(input_file)

    for idx, path in enumerate(paths):
        logging.info('=== path {}'.format(idx))
        logging.info(path)
        for jdx, segment in enumerate(path):
            logging.info("   === segment {}".format(jdx))
            logging.info(segment)
            if isinstance(segment, spt.Line):
                # export as is
                msp.add_line(c2t(segment.start), c2t(segment.end))
                logging.info("Found line in Path {} segment {}".format(idx, jdx))
            elif isinstance(segment, spt.CubicBezier):
                try:
                    a = _bezier_to_dxf_arc(segment)
                except Warning:
                    logging.info("error in path {} segment {}".format(idx, jdx))
                    logging.info(segment)
                    raise
                if isinstance(a, ezdxf.math.ConstructionLine):
                    msp.add_line(a.start, a.end)
                elif isinstance(a, ezdxf.math.ConstructionArc):
                    msp.add_arc(center=a.center, radius=a.radius, start_angle=a.start_angle, end_angle=a.end_angle)
                    logging.info("Found Bezier curve in Path {} segment {}".format(idx, jdx))
                else:
                    logging.error("segment type {} is not supported".format(type(segment)))
            else:
                logging.error("segment type {} is not supported".format(type(segment)))

    return doc
예제 #5
0
def load_svg(svg_file, height=None, tol=5, min_length=1.5):
  # Read in the svg file. 
  paths, _, svg_attributes = svgpathtools.svg2paths2(svg_file)

  # Find the smallest bounding box that encapsulates all the SVG elements.
  xmin = float("inf")
  xmax = -1
  ymin = float("inf")
  ymax = -1
  
  for path in paths:
    (x1, x2, y1, y2) = path.bbox()
    if x1 < xmin:
      xmin = x1
    if x2 > xmax:
      xmax = x2
    if y1 < ymin:
      ymin = y1
    if y2 > ymax:
      ymax = y2  
 
  # Calc xmax and ymax of the bbox shifted to box with bottom left corner at 
  # (0, 0) and top right corner at (xmax, ymax).
  xmax -= xmin
  ymax -= ymin

  # If a height is given, calculate the scale factor from bbox dimensions.
  if height:
    scaling_factor = height/ymax
  else:
    scaling_factor = 1.0

  # Translate the SVG paths into robot paths, xmin and ymin as offsets.
  return translate_svg_paths(paths, xmin, ymin, scaling_factor, tol=tol, min_length=min_length)
예제 #6
0
def extract_surface_from_svg(filename):
    paths, attributes, svg_attributes = svg2paths2(filename)
    path = paths[0]
    N = len(path)
    pts = np.zeros((N + 1, 2))
    for i, curve in enumerate(path):
        pts[i, 0] = curve.start.real
        pts[i, 1] = curve.start.imag

    pts[i + 1, 0] = curve.end.real
    pts[i + 1, 1] = curve.end.imag

    # Remove offset and scale
    pts -= pts[0, :]
    pts[:, 0] /= pts[-1, 0]
    maximum = np.max(pts[:, 1])
    pts[:, 1] /= maximum if maximum else 1

    f = interp1d(*pts.T)

    maxes = np.max(pts, axis=0)
    mins = np.min(pts, axis=0)
    x_lim = [mins[0], maxes[0]]
    y_lim = [mins[1], maxes[1]]
    return f, x_lim, y_lim
예제 #7
0
 def __init__(self, filename, error_threshold = .01, min_length = 0.1):
     self.paths, self.attributes, svg_attributes = svg2paths2(filename)
     self.polys = []
     self.miny = self.minx = float("+inf")
     self.maxy = self.maxx = float("-inf")
     self.error_threshold = error_threshold
     self.min_length = min_length
예제 #8
0
파일: svg.py 프로젝트: JarrettR/FlatStack
def parse_svg(filename):
    paths, attributes, svg_attributes = svg2paths2(filename)
    for p, a in zip(paths, attributes):
        #print(a)
        if isJoint(a) == True:
            print('Joint at ', p.bbox())
        else:
            print('Not joint: ', p.bbox())
예제 #9
0
    def parseSVG(self, filename, targetWidth, xOffset, steps_per_seg):

        if (platform.system() == "Windows"):
            call([
                "node",
                "C:/Users/oswald/AppData/Roaming/npm/node_modules/svgo/bin/svgo",
                filename, "-o", self.temp_folder + "/clean.svg"
            ])
        else:
            call(["svgo", filename, "-o", self.temp_folder + "/clean.svg"])

        # Parse the path
        paths, attributes, svg_attrs = svg2paths2(self.temp_folder +
                                                  "/clean.svg")

        # Find the bounding box
        xmin = 100000
        xmax = -10000
        ymin = 10000
        ymax = -10000

        for i in range(len(paths)):
            path = paths[i]
            attribute = attributes[i]
            # A crude check for wether a path should be drawn. Does it have a style defined? This caused trouble elsewhere...
            for seg in path:
                for p in range(steps_per_seg + 1):
                    cp = seg.point(float(p) / float(steps_per_seg))
                    cx = np.real(cp)
                    cy = np.imag(cp)
                    if (cx < xmin): xmin = cx
                    if (cy < ymin): ymin = cy
                    if (cx > xmax): xmax = cx
                    if (cy > ymax): ymax = cy

        # The scaling factor to reach the targetWidth
        scale = targetWidth / (xmax - xmin)

        # Transform the paths to lists of coordinates
        coords = []

        for i in range(len(paths)):
            path = paths[i]
            attribute = attributes[i]
            if ('stroke' in attribute or 'class' in attribute):
                for seg in path:
                    segcoords = []
                    for p in range(steps_per_seg + 1):
                        cp = seg.point(float(p) / float(steps_per_seg))
                        segcoords.append([
                            scale * (np.real(cp) - xmin) + xOffset,
                            scale * (np.imag(cp) - ymin) - scale *
                            ((ymax - ymin) / 2.0)
                        ])
                    coords.append(segcoords)

        return coords
예제 #10
0
    def __init__(self, filepath):
        self._filepath = filepath
        self._paths, self._attrs, self._info = svgpathtools.svg2paths2(
            self._filepath)

        w, x_unit, x_scale = self._parse_by_unit(self._info["width"])
        h, y_unit, y_scale = self._parse_by_unit(self._info["height"])

        self._canvas = {
            "width": w,
            "height": h,
            "x_unit": x_unit,
            "y_unit": y_unit,
            "x_scale": x_scale,
            "y_scale": y_scale,
            "zoom_x": 0,
            "zoom_y": 0,
            "zoom_width": w,
            "zoom_height": h,
        }

        if "viewBox" in self._info:
            try:
                (x_min, y_min, box_width,
                 box_height) = re.split(r"\s*,\s*|\s+",
                                        self._info["viewBox"].strip())
                self._canvas["zoom_x"] = float(x_min)
                self._canvas["zoom_y"] = float(y_min)
                self._canvas["zoom_width"] = float(box_width)
                self._canvas["zoom_height"] = float(box_height)
                self._canvas["x_scale"] *= self._canvas[
                    "width"] / self._canvas["zoom_width"]
                self._canvas["y_scale"] *= self._canvas[
                    "height"] / self._canvas["zoom_height"]
            except:
                pass

        if self.enable_transform:
            i = 0
            root = ET.parse(self._filepath).getroot()
            for g in root.findall("svg:g",
                                  {'svg': 'http://www.w3.org/2000/svg'}):
                self._attrs[i]["transform"] = g.attrib.get("transform",
                                                           "").strip()
                i += 1

            self._transform_sequence = []
            for i in range(len(self._attrs)):
                self._transform_sequence.append(
                    self._convert_transform(self._attrs[i]["transform"]))
        else:
            self._transform_sequence = [[]] * len(self._attrs)
예제 #11
0
    def updateFromSvg(self, filename):
        from svgpathtools import svg2paths2

        _, attributes, _ = svg2paths2(filename)

        for i, a in enumerate(attributes):
            if 'id' in a:
                tokens = a['id'].split('_')
                part = Part(a['d'])
                part.ID = tokens[1:]
                self.addPart(tokens[0], part)

        return self
예제 #12
0
def binary_image_to_svg(seg):
    seg = (1 - seg)
    seg = (seg * 255).astype("uint8")
    seg = seg[::-1]
    name = str(uuid.uuid4())
    bmp = name + ".bmp"
    svg = name + ".svg"
    imsave(bmp, seg)
    call(f"potrace -s {bmp}", shell=True)
    paths = svg2paths2(svg)
    os.remove(bmp)
    os.remove(svg)
    return paths
예제 #13
0
def svg_in(svg_location):

    if path.exists(svg_location):

        paths, attributes, svg_attributes = svg2paths2(svg_location)
        ##for i in range(4):
        ##wsvg(p,filename='blocks/b_block_'+str(i)+'.svg')

        ##print(svg_info)
        return [paths, attributes, svg_attributes]

    elif not svg_location.endswith('.svg'):
        sys.exit("invalid filename or extension")
예제 #14
0
    def parseSVG(self, filename, targetWidth, xOffset, steps_per_seg):

        call(["svgo", filename, "-o", self.temp_folder + "/clean.svg"])

        # Parse the path
        paths, attributes, svg_attrs = svg2paths2(self.temp_folder +
                                                  "/clean.svg")

        viewBox = map(float, svg_attrs[u'viewBox'].split(' '))

        # Find the bounding box
        xmin = 100000
        xmax = -10000
        ymin = 10000
        ymax = -10000

        for i in range(len(paths)):
            path = paths[i]
            attribute = attributes[i]
            # A crude check for wether a path should be drawn. Does it have a style defined? This caused trouble elsewhere...
            for seg in path:
                for p in range(steps_per_seg + 1):
                    cp = seg.point(float(p) / float(steps_per_seg))
                    cx = np.real(cp)
                    cy = np.imag(cp)
                    if (cx < xmin): xmin = cx
                    if (cy < ymin): ymin = cy
                    if (cx > xmax): xmax = cx
                    if (cy > ymax): ymax = cy

        # The scaling factor to reach the targetWidth
        scale = targetWidth / (xmax - xmin)

        # Transform the paths to lists of coordinates
        coords = []

        for i in range(len(paths)):
            path = paths[i]
            attribute = attributes[i]
            # A crude check for wether a path should be drawn. Does it have a style defined?
            for seg in path:
                segcoords = []
                for p in range(steps_per_seg + 1):
                    cp = seg.point(float(p) / float(steps_per_seg))
                    segcoords.append([
                        scale * (np.real(cp) - xmin) + xOffset, scale *
                        (np.imag(cp) - ymin) - scale * ((ymax - ymin) / 2.0)
                    ])
                coords.append(segcoords)

        return coords
예제 #15
0
 def loadSvg(self):
     paths, attributes, svg_attributes = svg2paths2(self.filepath)
     self.view_box = svg_attributes['viewBox'].split(" ")
     # min_x min_y max_x max_y
     for index, item in enumerate(self.view_box):
         self.view_box[index] = float(item)
     self.view_box_height = self.view_box[-1]
     self.view_box_width = self.view_box[-2]
     if len(paths) > 0:
         self.path = paths[0]
     else:
         print("Hey, your svg file does not have path elements!")
     self.length = self.path.length()
     self.knot_nums = len(self.path)
예제 #16
0
def binary_image_to_svg2(mask):
    """
    same as binary_image_to_svg, but use `pypotrace`
    instead of calling `potrace` from shell
    it is more convenient and faster, this way
    """
    import potrace
    bmp = potrace.Bitmap(mask)
    bmp.trace()
    xml = bmp.to_xml()
    fo = StringIO()
    fo.write(xml)
    fo.seek(0)
    paths = svg2paths2(fo)
    return paths
예제 #17
0
def load_map_svg(path, map_type):
    # geojson is a metric map so let's set the properties accordingly -- at least the map type
    map_properties = {'map_type':map_type}
    
    # Update: You can now also extract the svg-attributes by setting
    # return_svg_attributes=True, or with the convenience function svg2paths2
    paths, attributes, svg_attributes = svg2paths2(path)
    
    # map attributes to remove non-essential attributes
    attributes = map(lambda x: {'id':x['id'], 'name':x['name'], 'sm_sk_type':x['smart_skema_type'], 'feat_type':x['smart_skema_type'],
                                'descriptn':x['description']}, attributes)
    
    #features = [ ({attr1:"", attr2:"", ...}, shaplyGeometry), ..., {'Feature':{attr1:"", attr2:"", ...}, 'Geom':shaplyGeometry} ]
    shapelyGeoms = []
    
    # split curves if the ratio of the curve radius and the base (start to end) diameter is greater than the parameter c
    # 0c=0.01
    
    for p in paths:
        # we unpack each complex number representing a point into its components
        d_path = [(p.point(0).real,p.point(0).imag)]
        
        for s in p:
            sp = s.bpoints()
            if isinstance(s, Line):
                d_path.append((sp[1].real,sp[1].imag))
     
            elif isinstance(s, QuadraticBezier):
                segments = simplify_qcurve_simple(sp[0], sp[1], sp[2], segments = [])
                points = map(lambda x: (x['end'].real,x['end'].imag), segments)
                d_path.extend(points)
                
            elif isinstance(s, CubicBezier):
                segments = simplify_ccurve_simple(sp[0], sp[1], sp[2], sp[3], segments = [])
                points = map(lambda x: (x['end'].real,x['end'].imag), segments)
                d_path.extend(points)
        
        shapelyGeoms.append(point_list2shapely(d_path))
    
    # features = map( lambda x, y: {"attributes":x, "geometry":y}, attributes, shapelyGeoms)
    features = [{"attributes":x, "geometry":y} for (x, y) in zip(attributes, shapelyGeoms)]
    print ("map loaded")
    
    # map loaded, so return the data
    return map_properties, features
    
예제 #18
0
def world_plot(request):
    paths, attributes, svg_attributes = svg2paths2(
        'static_resources/worldIndiaHigh.svg')
    country_names = [attribute['title'] for attribute in attributes]
    country_patches = []

    for attribute, path in zip(attributes, paths):
        if attribute['class'] == 'land':
            for path in paths:
                country_xs = []
                country_ys = []
                for line in path:
                    start, end = line
                    country_xs.append(start.real)
                    country_ys.append(end.real)
            country_patches.append([country_xs, country_ys])

    patch = country_patches[0]
    print("Patch: ", patch)

    p = figure(plot_width=500,
               plot_height=500,
               x_axis_location=None,
               y_axis_location=None)
    source = ColumnDataSource(data=dict(x=country_patches[0],
                                        y=country_patches[1]
                                        # name=country_names
                                        ))
    # hover = HoverTool(tooltips=[
    #     ("desc", "@desc"),
    # ])
    # p.add_tools(hover)
    p.grid.grid_line_color = None
    # p.patches(country_patches)
    # p.patches(xs=country_patches[0], ys=country_patches[1], fill_color='white')
    p.patches('x', 'y', source=source, line_width=0.2, fill_color='white')

    # for attribute, path in zip(attributes, paths):
    #     if attribute['class'] == 'land':
    #         print(attribute['title'], path)

    script, div = components(p)
    variables = {'script': script, 'div': div}
    return render(request=request,
                  template_name='world_plot.html',
                  context=variables)
예제 #19
0
def list_paths(args):

    input_file = args.infile

    if input_file == "":
        logging.error("Input file name is missing")
        raise ValueError("Input file are needed")

    logging.info("input file {}".format(input_file))

    paths, attributes, svg_attributes = spt.svg2paths2(input_file)

    for idx, path in enumerate(paths):
        print('=== new path {}'.format(idx))
        for jdx, segment in enumerate(path):
            print("   === segment {}".format(jdx))
            print(segment)

    logging.info("End")
예제 #20
0
def get_points(file, density):
    #TODO: calculate density automatically for target point #
    paths = svgpathtools.svg2paths2(file)
    res = []
    for i, path in enumerate(paths[0]):
        pathpoints = []
        for seg in path._segments:
            count = math.ceil(seg.length() / density)
            frac = 1.0 / count
            for i in range(1, count):
                pathpoints.append(seg.point(frac * i))
        if len(pathpoints) > 0:
            res.append(pathpoints)

    def f(x):
        return x.start

    starts = list(map(lambda i: f(i), paths[0]))
    return res, starts
예제 #21
0
def world_plot(request):
    paths, attributes, svg_attributes = svg2paths2('static_resources/worldIndiaHigh.svg')
    country_names = [attribute['title'] for attribute in attributes]
    country_patches = []

    for attribute, path in zip(attributes, paths):
        if attribute['class'] == 'land':
            for path in paths:
                country_xs = []
                country_ys = []
                for line in path:
                    start, end = line
                    country_xs.append(start.real)
                    country_ys.append(end.real)
            country_patches.append([country_xs, country_ys])

    patch = country_patches[0]
    print("Patch: ", patch)

    p = figure(plot_width=500, plot_height=500, x_axis_location=None, y_axis_location=None)
    source = ColumnDataSource(data=dict(
        x=country_patches[0],
        y=country_patches[1]
        # name=country_names
    ))
    # hover = HoverTool(tooltips=[
    #     ("desc", "@desc"),
    # ])
    # p.add_tools(hover)
    p.grid.grid_line_color = None
    # p.patches(country_patches)
    # p.patches(xs=country_patches[0], ys=country_patches[1], fill_color='white')
    p.patches('x', 'y', source=source, line_width=0.2, fill_color='white')

    # for attribute, path in zip(attributes, paths):
    #     if attribute['class'] == 'land':
    #         print(attribute['title'], path)

    script, div = components(p)
    variables = {'script': script, 'div': div}
    return render(request=request, template_name='world_plot.html', context=variables)
예제 #22
0
def add_circle(input_file, output_file):
    """
    Adds a circle around the base icon. This will have the effect to invert
    the mask.
    """
    paths, attributes, svg_attributes = svg2paths2(input_file)
    if len(paths) > 1:
        raise NotImplementedError("Can't handle more than one path for now")
    path = paths[0]

    # Scale path down
    new_path = scale_path_to_bbox(path, (6, 6, 42, 42))

    # Add circle
    new_path.append(Arc(24 + 2j, 22 + 22j, 180, 0, 1, 24 + 46j))
    new_path.append(Arc(24 + 46j, 22 + 22j, 180, 0, 1, 24 + 2j))

    wsvg(
        [new_path],
        attributes=attributes,
        svg_attributes=svg_attributes,
        filename=output_file,
    )
예제 #23
0
def colorize(args):
    input_file = args.infile
    output_file = args.outfile

    if input_file == "" or output_file == "":
        logging.error("Input or output file names are missing")
        raise ValueError("Input and output files are needed")

    logging.info("input file {} output file {}".format(input_file, output_file))

    paths, attributes, svg_attributes = spt.svg2paths2(input_file)

    # each segment must be a path in order to assign a color

    new_paths = []
    for path in paths:
        for segment in path:
            new_paths.append(spt.Path(segment))

    nb_segments = len(new_paths)
    col = ['r', 'g', 'b', 'k']
    segment_col = ''.join([col[i % len(col)] for i in range(nb_segments)])

    spt.wsvg(new_paths, colors=segment_col, stroke_widths=[2] * nb_segments, filename=output_file)
예제 #24
0
def extract_base_icon(input_file, output_file):
    """Also scales the shape to use more space in the drawing"""
    center = 24 + 24j
    paths, attributes, svg_attributes = svg2paths2(input_file)
    if len(paths) > 1:
        raise NotImplementedError("Can't handle more than one path for now")
    path = paths[0]
    subpaths = path.continuous_subpaths()
    outer_shape = max(subpaths, key=lambda x: bbox_to_barea(x.bbox()))
    subpaths.remove(outer_shape)

    # Generate a new path with the remaining shapes
    new_path = Path()
    for subpath in subpaths:
        append_subpath(new_path, subpath)

    # Scale path up
    new_path = scale_path_to_bbox(new_path, (2, 2, 46, 46))
    wsvg(
        [new_path],
        attributes=attributes,
        svg_attributes=svg_attributes,
        filename=output_file,
    )
예제 #25
0
inkscape_preferences = '<sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" showgrid="false" inkscape:window-maximized="1" units="in" inkscape:document-units="in" />'

# Import Libraries
import os
import svgpathtools

# Get a list of all the .svg files in current working directory
cwd = os.getcwd()
svg_file_list = []
for file in os.listdir(cwd):
    if file.endswith(".svg"):
        svg_file_list.append(file)

# Parse .svg file then update colors and groups
for svg_file in svg_file_list:
    path_list, path_attribute_list, svg_file_attributes = svgpathtools.svg2paths2(
        svg_file)

    # Ensure .svg was created by Shaper Origin Utilities
    if "shaper:fusionaddin" not in svg_file_attributes:
        print(f'{svg_file} was not created by Shaper Utilities, file skipped.')
        break

    # Create two lists used to group paths when writing .svg file
    exterior_group_list = []
    interior_group_list = []

    # Loop through each path and edit attributes
    for path_dic in path_attribute_list:
        # Update exterior paths attributes and add them to list exterior_group
        if path_dic["shaper:pathType"] == "exterior":
            path_dic["fill"] = exterior_fill_color
예제 #26
0
import math

svg_file = 'orangecounty.svg'
min_length = 1
max_length = 2000
output_size_x = 130
min_segment_length = 0.2
connection_threshold = 0.2
z_high = 1
z_low = 0
accel_xy_mm_s2 = 4000
accel_z_mm_s2 = 2000
feedrate_xy_mm_min = 6000
feedrate_z_mm_s = 6.67

paths, attributes, svg_attributes = svg2paths2(svg_file)

print(f'{len(paths)} paths')

bounds = [p.bbox() for p in paths]
x_min = min([b[0] for b in bounds])
x_max = max([b[1] for b in bounds])
y_min = min([b[2] for b in bounds])
y_max = max([b[3] for b in bounds])
x_size = x_max - x_min
y_size = y_max - y_min
scale_factor = output_size_x / x_size
print(f'Bounding box: {x_min}, {x_size}, {y_min}, {y_size}')
print(f'New size: {x_size * scale_factor}, {y_size * scale_factor}')

lengths = [p.length() * scale_factor for p in paths]
예제 #27
0
# Cut out single words from scan file and save them as individual files

# 1. import svg file and image
# 2. extract paths and turn into "filled" polygons, calculate bounding boxes
# 3. apply to imag
# 4. binarization
# (optional/todo) 5. further preprocessing: normalization, tilting, ...
# 6. export as new file

pages = glob.glob("./images/*.jpg")
cutouts = glob.glob("./ground-truth/locations/*.svg")
pages.sort()
cutouts.sort()
for page, cutout in zip(pages, cutouts):
    page_number = os.path.splitext(os.path.basename(page))[0]
    paths, attributes, svg_attributes = svg2paths2(cutout)
    scan = cv2.imread(page,
                      cv2.IMREAD_GRAYSCALE)  #directly read in as grayscale
    for path, attribute in zip(paths, attributes):
        #paths, attributes, svg_attributes = svg2paths2('270.svg')
        code = attribute['id']
        #https://github.com/mathandy/svgpathtools/blob/master/svgpathtools/paths2svg.py
        bbox = paths2svg.big_bounding_box(
            path)  #returns (xmin, xmax, ymin, ymax)
        bbox = tuple(map(int, bbox))  #cast to int and convert back to tuple
        scan_crop = scan[bbox[2]:bbox[3], bbox[0]:bbox[1]]

        #binarize
        tresh = threshold_otsu(
            scan_crop
        )  #https://scikit-image.org/docs/stable/api/skimage.filters.html#skimage.filters.threshold_otsu
예제 #28
0
def drawSvg(sX,
            sY,
            xmin,
            ymin,
            name,
            bbox=True,
            flip_svg=False,
            auto_resize=True):
    """
	Draws the svg `name`, with a bounding box if `bbox`, flipped if `flip_svg`
	sX,sY: size (pixels) of the windows in which to draw
	xmin,ymin: top left corner of the window to draw in
	auto_resize: sometimes the broadcasted size of the SVG doesn't correspond to the coordinates of its geometry. This parameter auto resizes the image to its best fitting box +1%width/height if True
	"""
    paths, attributes, svg_attributes = svgpathtools.svg2paths2(name)
    if 'width' in svg_attributes and 'height' in svg_attributes:
        svg_w, svg_h = ceil(
            float(svg_attributes['width'].replace('px', '').replace(
                'pt', '').replace('mm', ''))), ceil(
                    float(svg_attributes['height'].replace('px', '').replace(
                        'pt', '').replace('mm', '')))  # Fix later
    else:
        svg_w, svg_h = 0, 0
        auto_resize = True
    if auto_resize:
        for i in range(len(paths)):
            path, attrib = paths[i], attributes[i]
            for elt in path:
                for t in linspace(0, 1, 5):
                    pt = elt.point(t)
                    svg_w, svg_h = max(svg_w, pt.real), max(svg_h, pt.imag)
        svg_w, svg_h = ceil(svg_w * 1.01), ceil(svg_h * 1.01)
    factX, factY = sX / svg_w, sY / svg_h

    scene = Scene()
    if bbox:
        scene.add(Rectangle([0, 0], [sX, sY]))  # Bounding box

    def flip(elt):  # flip an image vertically, sometimes needed
        if type(elt) is svgpathtools.Line or type(
                elt) is svgpathtools.CubicBezier:
            elt.start = elt.start.real + 1j * (svg_h - elt.start.imag)
            elt.end = elt.end.real + 1j * (svg_h - elt.end.imag)
        if type(elt) is svgpathtools.CubicBezier:
            elt.control1 = elt.control1.real + 1j * (svg_h - elt.control1.imag)
            elt.control2 = elt.control2.real + 1j * (svg_h - elt.control2.imag)
        return elt

    for i in range(len(paths)):
        path, attrib = paths[i], attributes[i]
        for elt in path:
            if flip_svg:
                elt = flip(elt)
            if type(elt) is svgpathtools.Line:
                scene.add(
                    Line([elt.start.real * factX, elt.start.imag * factY],
                         [elt.end.real * factX, elt.end.imag * factY], 3))
            elif type(elt) is svgpathtools.CubicBezier:
                scene.add(
                    CubicBezier(
                        [elt.start.real * factX, elt.start.imag * factY],
                        [elt.end.real * factX, elt.end.imag * factY],
                        [elt.control1.real * factX, elt.control1.imag * factY],
                        [elt.control2.real * factX, elt.control2.imag * factY],
                        4))
            elif type(elt) is svgpathtools.Arc:
                continue  # Not implemented yet
            else:
                print(elt)

    scene.draw(sX, sY, xmin, ymin)
예제 #29
0
                        yield ("MOVE", *normalize_coord(sample, viewbox))
            if "fill" in path_attributes:
                fill = path_attributes["fill"]
                if fill.startswith("#"):
                    yield ("FILL", *bytes.fromhex(normalize_hex(fill)[1:]))
                else:
                    yield ("FILL", *name_to_rgb(fill))
            else:
                yield ("FILL", *DEFAULT_COLOR)


if len(sys.argv) < 2:
    print("usage: svgtoscode [svg]")
    sys.exit(1)

*svg, svg_attributes = svg2paths2(sys.argv[1])

if "viewbox" in svg_attributes:
    viewbox = map(int, svg_attributes["viewbox"].split())
else:
    viewbox = None
    for line in convert(*svg, None):
        if line[0] in {"START", "MOVE"}:
            if viewbox is None:
                viewbox = [line[1], line[2], line[1], line[2]]
            else:
                viewbox = [
                    min(viewbox[0], line[1]),
                    min(viewbox[1], line[2]),
                    max(viewbox[2], line[1]),
                    max(viewbox[3], line[2])
예제 #30
0
# check for 'serif' in the xml and delete it because it seems to ruin things
parser = etree.XMLParser(remove_blank_text=True)
src = etree.parse(svg_file + '.svg', parser)
objectify.deannotate(src, xsi_nil=True)
etree.cleanup_namespaces(src)
etree.ElementTree(src.getroot()).write(svg_file + '.svg', pretty_print=True)

print('working . . .')

# make a directory to hold all the output PNG frames
if not (os.path.isdir(svg_file)):
    os.mkdir(svg_file)

for FRAME in range(num_frames):
    paths, attr, svg_attr = svg2paths2(svg_file + '.svg')
    newpaths = []
    j = 0
    for path in paths:
        #print('\nparsing path of length {}'.format(len(path._segments)))
        path = paths[j]
        path_attr = attr[j]
        pathlist = []
        newpath = Path()
        x = copy.copy(path[0][0])
        cornerstone = wiggle(x)

        for k in range(len(path)):
            segment = path[k]
            prev_segment = pathlist[k - 1] if not k == 0 else None
                    attributes['stroke'] = '#000000'
                    attributes['stroke-linecap'] = 'round'
                    attributes['stroke-linejoin'] = 'round'
                    attributes['stroke-miterlimit'] = '10'
                    attributes['stroke-width'] = '7'
            else:
                assert False, 'Not implemented'

    return attributes


for ground_svg in glob('*/ground.svg'):
    root_dir = '/'.join(ground_svg.split('/')[:-1])
    print(root_dir)

    ground_paths, ground_attributes = svgpathtools.svg2paths(ground_svg)
    ground_paths, ground_attributes = clean_paths(ground_paths,
                                                  ground_attributes)

    for file_svg in glob(root_dir + '/file*.svg'):
        print(file_svg)
        paths, attribute_dicts, svg_attributes = svgpathtools.svg2paths2(
            file_svg)
        paths, attribute_dicts = clean_paths(paths, attribute_dicts)
        paths = paths + ground_paths
        attribute_dicts = attribute_dicts + ground_attributes
        svgpathtools.wsvg(paths,
                          filename=file_svg,
                          attributes=attribute_dicts,
                          svg_attributes=svg_attributes)