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
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
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)
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
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)
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
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
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())
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
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)
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
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
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")
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
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)
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
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
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)
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")
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
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)
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, )
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)
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, )
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
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]
# 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
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)
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])
# 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)