Exemple #1
0
    def save_points_as_svg_handler(points, size, image_number):
        # filename like file:///home/gdshen/Pictures/00000.jpg
        filename = os.path.join(project_path, svg_dir, image_number + '.svg')
        paths = []
        for i in range(size):
            start_point_x = points.property(i).property('startPoint').property(
                'X').toInt()
            start_point_y = points.property(i).property('startPoint').property(
                'Y').toInt()
            control_point_x = points.property(i).property(
                'controlPoint').property('X').toInt()
            control_point_y = points.property(i).property(
                'controlPoint').property('Y').toInt()
            target_point_x = points.property(i).property(
                'targetPoint').property('X').toInt()
            target_point_y = points.property(i).property(
                'targetPoint').property('Y').toInt()
            print(start_point_x, start_point_y, control_point_x,
                  control_point_y, target_point_x, target_point_y)
            paths.append(
                Path(
                    QuadraticBezier(complex(start_point_x, start_point_y),
                                    complex(control_point_x, control_point_y),
                                    complex(target_point_x, target_point_y))))

        wsvg(paths=paths, filename=filename)
Exemple #2
0
def save_subplot(path_buffer, output_folder, num):
    """Take all the paths in the buffer and save them to a new file"""
    logging.info(f"Saving sublot {num}")
    paths_to_save, attributes_to_save = tuple(zip(*path_buffer))
    svgpathtools.wsvg(
        paths_to_save, filename=os.path.join(output_folder, f"svg/{num}.svg"),
    )
Exemple #3
0
    def write(self, filename):
        wsvg(self.paths,
             attributes=self.attributes,
             svg_attributes=self.svg_attributes,
             filename=filename)

        return self
Exemple #4
0
    def saveSVG(self, fn):
        pathsCK = self.paths['ck']
        pathsLL0 = self.paths['ll0']

        def getSegment(path):
            return CubicBezier(complex(path['p0'][0], path['p0'][1]),
                               complex(path['c0'][0], path['c0'][1]),
                               complex(path['c1'][0], path['c1'][1]),
                               complex(path['p1'][0], path['p1'][1]))

        # C/K
        ck = Path(getSegment(pathsCK[0]), getSegment(pathsCK[1]),
                  getSegment(pathsCK[2]), getSegment(pathsCK[3]))

        # L/L0
        ll0 = Path(getSegment(pathsLL0[0]))

        paths = [ck, ll0]
        pathAttributes = {
            "stroke-width": self.width,
            "stroke": "#000",
            "fill": "#fff"
        }

        svg_attributes = {"viewBox": "0 0 600 600", "x": "0px", "y": "0px"}

        attributes = [pathAttributes, pathAttributes]
        wsvg(paths,
             attributes=attributes,
             svg_attributes=svg_attributes,
             filename=fn)
def render_svg_color(paths,
                     stroke_colors,
                     stroke_width=4,
                     stroke_linecap='round',
                     fill_mode='none',
                     viewbox=[0, 0, 300, 300],
                     base_dir='./',
                     out_dir='svg_images',
                     out_fname='tmp.svg'):
    '''
    see docs for wsvg: https://www.pydoc.io/pypi/svgpathtools-1.3.3/autoapi/paths2svg/index.html?highlight=wsvg#paths2svg.wsvg
    wsvg(paths=None, colors=None, filename=join, stroke_widths=None, nodes=None, node_colors=None, node_radii=None, openinbrowser=False, timestamp=False, margin_size=0.1, mindim=600, dimensions=None, viewbox=None, text=None, text_path=None, font_size=None, attributes=None, svg_attributes=None)
    '''

    ## render out to svg file
    print('Rendering out to {}'.format(os.path.join(out_dir, out_fname)))

    if not os.path.exists(os.path.join(base_dir, out_dir)):
        os.makedirs(os.path.join(base_dir, out_dir))
    wsvg(paths,
         attributes=[{
             'stroke-width': stroke_width,
             'stroke-linecap': stroke_linecap,
             'stroke': color,
             'fill': fill_mode
         } for color in stroke_colors],
         viewbox=viewbox,
         filename=os.path.join(base_dir, out_dir, out_fname))
Exemple #6
0
def pattern_to_svg(pattern, filename):
    if isinstance(filename, str) or isinstance(filename, unicode):
        output_file = open(filename, "wb")
    else:
        output_file = filename
    paths = []
    colors = []
    scale_factor = 0.1  # scale from cm to mm from pes
    for block in pattern.blocks:
        block_paths = []
        last_stitch = None
        for stitch in block.stitches:
            if "JUMP" in stitch.tags:
                last_stitch = stitch
                continue
            if last_stitch is None:
                last_stitch = stitch
                continue
            block_paths.append(
                Line(start=last_stitch.complex * scale_factor,
                     end=stitch.complex * scale_factor))
            last_stitch = stitch
        if len(block_paths) > 0:
            colors.append(block.tuple_color)
            paths.append(Path(*block_paths))
    dims = overall_bbox(paths)
    mindim = max(dims[1] - dims[0], dims[3] - dims[2])
    print("in pattern to svg, overallbbox", overall_bbox(paths))
    if len(paths) == 0:
        print("warning: pattern did not generate stitches")
        return
    wsvg(paths, colors, filename=output_file, mindim=mindim)
Exemple #7
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)
Exemple #8
0
def convert_file(args):
    print(args)
    input_file = args.infile
    output_file = args.outfile
    min_radius = args.min_radius
    max_dist = args.max_dist

    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 {} min radius {}".format(input_file, output_file, min_radius))

    file_name, file_extension = os.path.splitext(output_file)
    if file_extension == '.svg':
        new_paths, svg_attributes = convert_to_svg(input_file, max_dist, min_radius)

        for idx, path in enumerate(new_paths):
            logging.info('=== new path {}'.format(idx))
            for jdx, segment in enumerate(path):
                logging.info("   === segment {}".format(jdx))
                logging.info(segment)
        spt.wsvg(new_paths, svg_attributes=svg_attributes, filename=output_file)
    elif file_extension == '.dxf':
        raise ValueError("convert to dxf not yet implemented.")
        # doc = convert_to_dxf(input_file, max_dist, min_radius)
        # doc.saveas(output_file)
    logging.info("End")
Exemple #9
0
def pngtosvg( data, filename, crosshatch, numlines ):
	newpaths = []
	for y in range(0,data.height):
		for x in range(0,data.width):
			if (data.pixels[data.width*y + x][1] != 0):
				newpaths = newpaths + svgbox( [x,y], crosshatch, data.pixels[data.width*y + x][0], numlines)
	wsvg( newpaths, filename=filename.split('.')[0] + '.svg')
Exemple #10
0
def visualize_pen_transits(paths, svg_file):
    # We will construct a new image by storing (path, attribute)
    # pairs in this list.
    parts = list()

    last_end = None
    for i, path in enumerate(paths):
        start = path.start
        end = path.end

        # Generate a color based on how far along in the plot we are.
        frac = i / (len(paths) - 1)
        color = generate_color(frac, 1.0, 1.0)

        if last_end is not None:
            # If this isn't our first path, add a line between the end of
            # the last path and the start of this one.
            parts.append(
                (
                    svgpathtools.Line(last_end, start),
                    {
                        "stroke": "black",
                        "fill": "none",
                    },
                )
            )

        last_end = end

        # Also draw a faded, colorized version of this path.
        parts.append((path, {"stroke": color, "fill": "none", "opacity": "0.5"}))

    new_paths, new_attrs = zip(*parts)
    svgpathtools.wsvg(new_paths, attributes=new_attrs, filename=svg_file)
Exemple #11
0
 def export_portrait(self, filename):
     wsvg(self.portrait.get_paths(),
          attributes=self.portrait.get_attributes({
              'skin':
              rgb2hex(self.skin_color),
              'body':
              rgb2hex(change_value(self.skin_color, -0.1))
          }),
          filename=filename)
Exemple #12
0
 def write(self, filename):
     colors = []
     paths = []
     paths, attrs = zip(*self.paths)
     assert len(self.paths) != 0
     svgpathtools.wsvg(paths,
                       svg_attributes=self.svg_attrs,
                       attributes=attrs,
                       filename=filename)
Exemple #13
0
def run_optimizer(
    input_file,
    output_file,
    vis_output,
    runtime,
    greedy,
    noopt,
    merge_paths,
    origin_x,
    origin_y,
):
    paths = load_paths(input_file)

    initial_cost = cost_of_route(paths)
    print("Initial cost: {}".format(initial_cost))

    if noopt:
        route = paths
    else:
        path_graph = PathGraph(paths, origin=origin_x + (origin_y * 1j))
        greedy_solution = list(greedy_walk(path_graph))
        greedy_route = get_route_from_solution(greedy_solution, path_graph)

        greedy_cost = cost_of_route(greedy_route)
        print("Cost after greedy optimization: {}".format(greedy_cost))

        if not greedy:
            vrp_solution = vrp_solver(path_graph, greedy_solution, runtime)
            vrp_route = get_route_from_solution(vrp_solution, path_graph)
            vrp_cost = cost_of_route(vrp_route)
            print(
                "Cost after VRP optimization: {} "
                "(may be slightly off due to numeric precision)".format(vrp_cost)
            )

            route = vrp_route
        else:
            route = greedy_route

        if output_file is None:
            output_file = splitext(input_file)[0] + "-optimized.svg"

        if merge_paths is not False:
            if merge_paths is None:
                threshold = DEFAULT_MERGE_THRESHOLD
            else:
                threshold = merge_paths
            print("Routes before merging: {}".format(len(route)))
            route = join_close_paths(route, threshold)
            print("Routes after merging: {}".format(len(route)))

        print("Writing results to {}".format(output_file))
        wsvg(route, filename=output_file)

    if vis_output is not None:
        print("Writing visualization to {}".format(vis_output))
        visualize_pen_transits(route, vis_output)
 def save_subplot(path_buffer, num):
     """Take all the paths in the buffer and save them to a new file"""
     print(f"Saving sublot {num}")
     paths_to_save, attributes_to_save = tuple(zip(*path_buffer))
     attributes_to_save = add_fill(attributes_to_save)
     svgpathtools.wsvg(
         paths_to_save,
         attributes=attributes_to_save,
         filename=os.path.join(output_folder, f"{num}.svg"),
     )
Exemple #15
0
def compoundPath2simplePath(srcDir, desDir):
    svgFiles = sorted(glob.glob(srcDir + "*.svg"))

    svg_attribute = {u'height': u'256px', u'width': u'256px'}

    for svgFileName in svgFiles:
        svgFile = get_path_strings(svgFileName)
        svgMList = svgFile[0].split('M')
        svgMList = svgMList[1:]
        svgMList = ['M' + MEle for MEle in svgMList]
        svgPathList = [parse_path(MEle) for MEle in svgMList]
        wsvg(svgPathList, svg_attributes=svg_attribute, filename=desDir + '/' + svgFileName)
Exemple #16
0
def generate_face():
    height = 24.5
    folder = './input'

    eyepaths = get_paths_from_directory(folder + '/eyes/', 'EYES')
    nosepaths = get_paths_from_directory(folder + '/nose/', 'NOSE')
    mouthpaths = get_paths_from_directory(folder + '/mouth/', 'MOUTH')

    facepaths = align_components(eyepaths, nosepaths, mouthpaths, height)
    filename = 'output/' + uuid.uuid4().hex + '.svg'

    wsvg(facepaths, dimensions=('275mm', '195mm'), stroke_widths=[1]*2000, filename=filename, viewbox="0 0 27.5 19.5")

    return filename
Exemple #17
0
    def save(self, filename):
        pathAttributes = {
            "stroke-width": self.width,
            "stroke": "#000",
            "fill": "#fff"
        }

        svg_attributes = {"viewBox": "0 0 600 600", "x": "0px", "y": "0px"}

        attributes = [pathAttributes, pathAttributes]
        wsvg(self.paths,
             attributes=attributes,
             svg_attributes=svg_attributes,
             filename=filename)
Exemple #18
0
def json2svg(fname):
    path = []
    pts = [(0, 0)]
    data = json.load(open(fname, 'r'))

    for x_step, y_step, up in data:
        x, y = pts[-1]
        x_next, y_next = x + x_step, y + y_step
        if not up:
            line = Line(x + y * 1j, x_next + y_next * 1j)
            path.append(line)
        pts.append((x_next, y_next))
    paths = [Path(*path)]
    out = '{}.svg'.format(fname.rsplit('.', 1)[0])
    wsvg(paths, filename=out)
    return out
Exemple #19
0
def segment_svg(svg_file, output_file, segment_size=8):
    paths, _ = svgpathtools.svg2paths(svg_file)

    lines = []

    for path in paths:
        for cp in path.continuous_subpaths():
            last_pos = None
            segments = int(cp.length() / segment_size)
            for frac in np.linspace(0., 1., segments):
                pos = cp.point(frac)
                if last_pos:
                    lines.append(svgpathtools.Line(last_pos, pos))
                last_pos = pos

    svgpathtools.wsvg(lines, filename=output_file)
Exemple #20
0
def run_optimizer(input_file, output_file, vis_output, noopt, merge_paths):
    paths, attributes, svg_attributes = svg2paths(input_file, return_svg_attributes=True)

    initial_cost = cost_of_route(paths)
    print('Initial cost: {}'.format(initial_cost))

    if noopt:
        route = paths
    else:
        path_graph = PathGraph(paths)
        greedy_solution = list(greedy_walk(path_graph))
        greedy_route = get_route_from_solution(greedy_solution, path_graph)

        greedy_cost = cost_of_route(greedy_route)
        print('Cost after greedy optimization: {}'.format(greedy_cost))

        route = greedy_route

        if merge_paths is not False:
            if merge_paths is None:
                threshold = DEFAULT_MERGE_THRESHOLD
            else:
                threshold = merge_paths
            print('Routes before merging: {}'.format(len(route)))
            route = join_close_paths(route, threshold)
            print('Routes after merging: {}'.format(len(route)))

    if output_file is None:
        output_file = splitext(input_file)[0] + '-optimized.svg'

    print('Writing results to {}'.format(output_file))

    svg_attributes["debug"] = False

    wsvg(
        route, 
        filename=output_file,
        # margin_size,
        # dimensions,
        # viewbox,
        # attributes = attributes,
        svg_attributes=svg_attributes,
    )

    if vis_output is not None:
        print('Writing visualization to {}'.format(vis_output))
        visualize_pen_transits(route, vis_output)
Exemple #21
0
def generate_svg(i, m1, m2, n1):
    sf = superformula(m1, m2, n1)
    polar_pts = [(ang, sf(ang)) for ang in np.arange(0, 2*math.pi, 0.1)]
    carte_pts = [pol2cart(ang, rho) for ang, rho in polar_pts]

    # so the figure closes
    carte_pts.append(carte_pts[0])

    path = []
    for (x1, y1), (x2, y2) in zip(carte_pts, carte_pts[1:]):
        seg = Line(x1+y1*1j, x2+y2*1j)
        path.append(seg)
    paths = [Path(*path)]

    fname = 'generated/{}.svg'.format(i)
    wsvg(paths, filename=fname)
    return fname
Exemple #22
0
def displaySVGPaths_transects(ring_list, data_transects, transect_angles, skipped_angle_indices, fn=None):
    if not fn:
        filename = opt.output_directory + ring_list[0].svgname
    else:
        filename = fn

    transectPaths = []
    for tran_index in range(len(data_transects)):
        tran_path = Path()
        for seg_index in range(len(data_transects[tran_index]) - 1):
            start_pt = data_transects[tran_index][seg_index]
            end_pt = data_transects[tran_index][seg_index + 1]
            tran_path.append(Line(start_pt,end_pt))
        transectPaths.append(tran_path)

    ringPaths = [r.path for r in ring_list]
    ringColors = [r.color for r in ring_list]
    pathList = ringPaths + transectPaths
    colors = ringColors + ['black']*len(transectPaths)
    transect_nodes = [item for sublist in data_transects for item in sublist] # flatten data_transects
    nodes = transect_nodes + [ring_list[0].center]
    node_colors = ['purple']*len(transect_nodes) + ['blue']
    text = ['%.3f' % theta for idx, theta in enumerate(transect_angles)
            if idx not in skipped_angle_indices]
    text += ['skipped %.3f' % transect_angles[idx]
             for idx in skipped_angle_indices]
    text_path = []
    for tr in data_transects:
        end = tr[-1]
        last_seg = Line(tr[-2], tr[-1])
        u = last_seg.unit_tangent(1)
        text_path.append(Path(Line(end + 10*u, end + 100*u)))

    # handle skipped transects
    bdry_ring = max(ring_list, key=lambda ring: ring.maxR)
    bdry_length = bdry_ring.path.length()
    for idx in skipped_angle_indices:
        s = bdry_length * transect_angles[idx]
        T = inv_arclength(bdry_ring.path,  s)
        u = bdry_ring.path.normal(T)
        end = bdry_ring.path.point(T)
        text_path.append(Line(end + 10*u, end + 100*u))

    wsvg(pathList, colors, nodes=nodes, node_colors=node_colors, text=text,
         text_path=text_path, filename=filename+'_transects.svg')
def toolPathSVG(svgPath, repetitions):
    paths, attributes = svg2paths(svgPath)

    offset_distances = []
    mult = 3
    for k in range(1, 1 + repetitions, 2):
        if k > 1:
            mult = 2
        offset_distances.append(-mult * k)
    # offset_distances = [-3*k for k in range(1, 1 + repetitions,2)]
    attrs = []
    allPaths = []

    idx = 0
    for path in paths:
        offset_paths = []
        idx += 1

        for distances in offset_distances:
            newcurve = offset_curve(path, distances)
            # _, attributes = newcurve.
            # if newcurve.length() < 230 :
            #     break

            # newcurve = parse_path(newcurve.d())
            # print(type(newcurve))

            if newcurve.area() < path.area() / 50:
                # attrs.append(idx)
                break

            offset_paths.append(newcurve)

            idx += 1
        allPaths.append(path)
        for of in offset_paths:
            allPaths.append(of)
        attrs.append(idx - 1)

    # shownPath = paths + offset_paths
    shownPath = allPaths

    wsvg(shownPath, filename=svgPath)
    return attrs
def convert_font():
    cwd = pathlib.Path.cwd()

    for root, dirs, files in os.walk('{}/exports'.format(cwd)):
        for name in files:
            source = os.path.join(root, name)
            target = 'fonts/{}.min.svg'.format(name.split('.')[0])
            print(source)

            try:
                paths, attr = svg2paths(source)
            except Exception as e:
                print(e)
                continue

            try:
                xmin, xmax, ymin, ymax = bounding_box(paths)
            except Exception as e:
                print(e)
                continue

            dx = xmax - xmin
            dy = ymax - ymin

            viewbox = '{} {} {} {}'.format(xmin, ymin, dx, dy)

            attr = {'viewBox': viewbox, 'preserveAspectRatio': 'xMidYMid meet'}

            wsvg(paths=paths, svg_attributes=attr, filename=source)

            doc = SaxDocument(source)
            d = doc.get_pathd_and_matrix()[0]
            g = Group()

            dwg = svgwrite.Drawing(target)
            dwg.viewbox(minx=xmin, miny=ymin, width=dx, height=dy)
            dwg.add(g)
            g.scale(sx=1, sy=-1)
            g.translate(tx=0, ty=-dy - ymin * 2)
            g.add(dwg.path(d))
            dwg.save()

            generate_pdf(target)
Exemple #25
0
 def save_svgpathtools(self, filename):
     lines = []
     for x, y, _ in self.lines:
         for i in range(len(x) - 1):
             lines.append(
                 svg.Line(x[i] + y[i] * -1j, x[i + 1] + y[i + 1] * -1j))
     line_colors = [
         color for x, _, color in self.lines for _ in range(len(x))
     ]
     text_path = []
     for x, y, _, _, _ in self.texts:
         for i in range(len(x)):
             text_path.append(
                 svg.Line(x[i] + y[i] * -1j, x[i] + 1.0 + y[i] * -1j))
     text = [text for x, _, text, _, _ in self.texts for _ in range(len(x))]
     svg.wsvg(lines,
              line_colors,
              stroke_widths=[0.01] * len(lines),
              text=text,
              text_path=text_path,
              font_size=[0.1] * len(text),
              filename=filename)
Exemple #26
0
def main(filename: str):
    paths, attributes, svg_attributes = svgpathtools.svg2paths(
        filename, return_svg_attributes=True)
    print("svg2paths ->", svg_attributes)

    # Let's print out the first path object and the color it was in the SVG
    # We'll see it is composed of two CubicBezier objects and, in the SVG file it
    # came from, it was red
    for k, path in enumerate(paths):
        attribs = attributes[k]

        path_id = attribs.get('id', None)

        print("============= path %s =================" % path_id)
        print(path)
        print(attribs)

    # and output
    svgpathtools.wsvg(paths,
                      attributes=attributes,
                      svg_attributes=svg_attributes,
                      filename="out.svg")
Exemple #27
0
def json2svg(jsonfile, outfile=None):
    with open(jsonfile) as f: obj = json.load(f)
    svg_attributes = make_svg_attributes(obj['imagePath'])
    attributes = []
    paths = []

    for shape in obj['shapes']:
        path = get_path(shape['points'])
        attr = make_attributes(shape['label'])
        paths.append(path)
        attributes.append(attr)

    paths.reverse()
    attributes.reverse()
    outfile = outfile or os.path.splitext(jsonfile)[0] + '.svg'
    svg.wsvg(
        paths=paths,
        filename=outfile,
        attributes=attributes,
        svg_attributes=svg_attributes,
    )
    print('Wrote to {}'.format(outfile))
Exemple #28
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,
    )
Exemple #29
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,
    )
Exemple #30
0
 def save_svg(self, filename):
     lines = [
         svg.Line(start[0] + start[1] * 1j, end[0] + end[1] * 1j)
         for [start, end], _ in self.lines
     ]
     line_colors = [color for [_, _], color in self.lines]
     nodes = [point[0] + point[1] * 1j for point, _ in self.nodes]
     node_colors = [color for _, color in self.nodes]
     text_path = [
         svg.Line(coordinate[0] + coordinate[1] * 1j,
                  coordinate[0] + 100.0 + coordinate[1] * 1j)
         for coordinate, _, _, _ in self.texts
     ]
     text = [text for _, text, _, _ in self.texts]
     svg.wsvg(lines,
              line_colors,
              stroke_widths=[1.0] * len(lines),
              nodes=nodes,
              node_colors=node_colors,
              node_radii=[2.5] * len(nodes),
              text=text,
              text_path=text_path,
              font_size=[5] * len(text),
              filename=filename)
Exemple #31
0
def render_svg(svg, width=None, height=None):
    drawing = wsvg(
        paths=svg.paths,
        attributes=svg.attributes,
        paths2Drawing=True,
    )
    fd = StringIO()
    drawing.write(fd)
    fo = BytesIO()
    svg2png(bytestring=fd.getvalue(),
            write_to=fo,
            output_width=width,
            output_height=height)
    fo.seek(0)
    return imread(fo, format="png")
Exemple #32
0
def invTransect(T, sorted_ring_list, warnifnotunique=True):
    """Finds a transect that ends at T.  In the case there are more than one, if
    warnifnotunique=True, user will be warned, but this may slow down transect
    generation.
    Output: list of tuples (pt, ring_idx, seg_idx, t)"""
    cur_ring = sorted_ring_list[-1]
    cur_idx = len(sorted_ring_list) - 2
    init_t,init_seg = pathT2tseg(cur_ring.path,T)
    init_seg_idx = cur_ring.path.index(init_seg)
    transect_info = [(cur_ring.point(T),
                      len(sorted_ring_list) - 1,
                      init_seg_idx,
                      init_t)]
    cur_pt = transect_info[-1][0]

    while cur_idx > 0:

        # #DEBUG
        # if cur_pt == (53.13478144019948+284.79773905194884j):
        #     bla=1
        # #end of debug

        # Find all rings this transect segment could be coming from
        test_rings = []
        r_idx = cur_idx - 1
        while r_idx >= 0:
            r = sorted_ring_list[r_idx]
            test_rings.append((r_idx, r))
            if r.path.isclosed():
                break
            r_idx -= 1

        test_ring_results = []
        for r_idx, test_ring in test_rings:
            args = (cur_pt, test_ring.path, cur_ring)
            inward_segt_list = isPointOutwardOfPath(*args, justone=False)

            for seg_idx, t in inward_segt_list:
                test_ring_results.append((r_idx, seg_idx, t))

            # # if the user asked for that
            # if len(inward_segt_list) > 1 and warnifnotunique:
            #         warn("The transect ending at T=%s is likely not unique." % T)

        # sort choices by distance to cur_pt
        def dist(res_):
            r_idx_, seg_idx_, t_ = res_
            new_pt_ = sorted_ring_list[r_idx_].path[seg_idx_].point(t_)
            return abs(cur_pt - new_pt_)
        sorted_results = sorted(test_ring_results, key=dist)

        # Find the closest result such that the transect does not go through
        # any other rings on it's way to cur_pt
        for res in sorted_results:
            wr_idx, wseg_idx, wt = res
            new_pt = sorted_ring_list[wr_idx].path[wseg_idx].point(wt)
            tr_line = Line(new_pt, cur_pt)

            winner = not any(r.path.intersect(tr_line)
                             for ri, r in test_rings if ri != wr_idx)
            if winner:
                break
        else:
            if opt.skip_transects_that_dont_exist:
                bdry_ring = sorted_ring_list[-1]
                s_rel = bdry_ring.path.length(T1=T) / bdry_ring.path.length()
                from os import path as os_path
                fn = sorted_ring_list[0].svgname + "_partial_transect_%s.svg" % s_rel
                fn = os_path.join(opt.output_directory, fn)
                wsvg([r.path for r in sorted_ring_list],
                      nodes=[tr[0] for tr in transect_info], filename=fn)
                warn("\nNo transect exists ending at relative arc "
                     "length %s.  An svg displaying this partial transect has"
                     "been saved to:\n%s\n" % (s_rel, fn))
                return []
            elif opt.accept_transect_crossings:
                wr_idx, wseg_idx, wt = sorted_results[0]
            else:
                disvg([r.path for r in sorted_ring_list],
                      nodes=[tr[0] for tr in transect_info]) # DEBUG line
                bdry_ring = sorted_ring_list[-1]
                s_rel = bdry_ring.path.length(T1=T) / bdry_ring.path.length()
                raise Exception("No transect exists ending at relative arc "
                                "length %s." % s_rel)

        # Record the closest choice
        transect_info.append((sorted_ring_list[wr_idx].path[wseg_idx].point(wt),
                              cur_idx,
                              wseg_idx,
                              wt))
        cur_ring = sorted_ring_list[wr_idx]
        cur_pt = transect_info[-1][0]
        cur_idx = wr_idx

        #Erroneous Termination
        if cur_idx < 0 and sorted_ring_list.index(cur_ring) != 0:
            disvg([r.path for r in sorted_ring_list],
                  nodes=[tr[0] for tr in transect_info]) # DEBUG line
            bdry_ring = sorted_ring_list[-1]
            s_rel = bdry_ring.path.length(T1=T) / bdry_ring.path.length()
            raise Exception("Something went wrong finding inverse transect at "
                            "relative arc length %s." % s_rel)
    return transect_info
Exemple #33
0
def fix_svg(ring_list, center, svgfile):

    # Discard inappropriately short rings
    from options4rings import appropriate_ring_length_minimum
    opt.basic_output_on.dprint("\nChecking for inappropriately short "
                               "rings...",'nr')
    tmp_len = len(ring_list)
    short_rings = [idx for idx, ring in enumerate(ring_list) if
                   ring.path.length() < appropriate_ring_length_minimum]
    opt.basic_output_on.dprint("Done (%s inappropriately short rings "
                               "found)."%len(short_rings))
    if short_rings:
        if opt.create_svg_highlighting_inappropriately_short_rings:
            opt.basic_output_on.dprint("\nCreating svg highlighting "
                                       "inappropriately short rings...",'nr')
            paths = [parse_path(r.string) for r in ring_list]
            colors = [r.color for r in ring_list]
            nodes = [ring_list[idx].path.point(0.5) for idx in short_rings]
            center_line = [Line(center-1,center+1)]
            tmp = svgfile[0:len(svgfile)-4] + "_short-rings.svg"
            shortrings_svg_filename = os_path.join(opt.output_directory, tmp)
            disvg(paths + [center_line], colors + [opt.colordict['center']],
                  nodes=nodes, filename=shortrings_svg_filename)
            args = appropriate_ring_length_minimum, shortrings_svg_filename
            mes = ("Done.  SVG created highlighting short rings by placing a "
                   "node at each short ring's midpoint.  Note: since these "
                   "rings are all under {} pixels in length, they may be hard "
                   "to see and may even be completely covered by the node.  "
                   "SVG file saved to:\n{}").format(*args)
            opt.basic_output_on.dprint(mes)

        if opt.dont_remove_closed_inappropriately_short_rings:
            shortest_ring_length = min([r.path.length() for r in
                                        [ring_list[k] for k in short_rings if
                                         ring_list[k].isClosed()]])
            open_short_rings = [idx for idx in short_rings if
                                not ring_list[idx].isClosed()]
            num_short_and_closed = len(short_rings)-len(open_short_rings)
            if num_short_and_closed:
                sug_tol = (opt.tol_isNear * shortest_ring_length /
                           opt.appropriate_ring_length_minimum)
                warn("{} inappropriately short closed rings detected (and not "
                     "removed as "
                     "dont_remove_closed_inappropriately_short_rings = True). "
                     " You should probably decrease tol_isNear to something "
                     "less than {} and restart this file."
                     "".format(num_short_and_closed, sug_tol))
            short_rings = open_short_rings

        if opt.remove_inappropriately_short_rings:
            opt.basic_output_on.dprint("\nRemoving inappropriately short "
                                       "rings...",'nr')
            ring_list = [ring for idx,ring in enumerate(ring_list) if
                         idx not in short_rings]
            opt.basic_output_on.dprint("Done (%s inappropriately short rings "
                                       "removed)."%(tmp_len - len(ring_list)))
        else:
            warn("{} inappropriately short rings were found, but "
                 "remove_inappropriately_short_rings is set to False."
                 "".format(len(ring_list)))
        print("")


    # Remove very short segments from rings
    def _remove_seg(path, _seg_idx, _newjoint):
        _new_path = [x for x in path]
        pathisclosed = path[-1].end == path[0].start

        # stretch next segment
        if _seg_idx != len(path) - 1 or pathisclosed:
            old_bpoints = _new_path[(_seg_idx + 1) % len(path)].bpoints()
            new_bpoints = (_newjoint,) + old_bpoints[1:]
            _new_path[(_seg_idx + 1) % len(path)] = bezier_segment(*new_bpoints)

        # stretch previous segment
        if _seg_idx != 0 or pathisclosed:
            old_bpoints = _new_path[(_seg_idx - 1) % len(path)].bpoints()
            new_bpoints = old_bpoints[:-1] + (_newjoint,)
            _new_path[(_seg_idx - 1) % len(path)] = bezier_segment(*new_bpoints)

        # delete the path to be removed
        del _new_path[_seg_idx]
        return _new_path



    if opt.min_relative_segment_length:
        for r_idx, r in enumerate(ring_list):
            min_seg_length = r.path.length() * opt.min_relative_segment_length
            new_path = [s for s in r.path]
            its = 0
            flag = False
            while its < len(r.path):
                its += 1
                for seg_idx, seg in enumerate(new_path):
                    if seg.length() < min_seg_length:
                        flag = True
                        if seg == new_path[-1] and not r.path.isclosed():
                            newjoint = seg.end
                        elif seg == new_path[0].start and not r.path.isclosed():
                            newjoint = seg.start
                        else:
                            newjoint = seg.point(0.5)
                        new_path = _remove_seg(new_path, seg_idx, newjoint)
                        break
                else:
                    break
            if flag:
                ring_list[r_idx].path = Path(*new_path)

    # Close approximately closed rings
    for r in ring_list:
        r.fixClosure()

    # Palette check
    from svg2rings import palette_check
    ring_list = palette_check(ring_list)

    # Check for and fix inconsistencies in closedness of rings
    from svg2rings import closedness_consistency_check
    ring_list = closedness_consistency_check(ring_list)

    # Remove self-intersections in open rings
    if opt.remove_self_intersections:
        rsi_start_time = current_time()
        fixable_count = 0
        print("Checking for self-intersections...")
        bad_rings = []
        for r_idx, r in enumerate(ring_list):
            if r.path.end == r.path.start:
                continue
            first_half = r.path.cropped(0, 0.4)
            second_half = r.path.cropped(0.6, 1)
            middle_peice = r.path.cropped(0.4, 0.6)
            inters = first_half.intersect(second_half)
            if inters:
                if len(inters) > 1:
                    Ts = [info1[0] for info1, info2 in inters]
                    bad_rings.append((r_idx, Ts))
                    continue
                else:
                    fixable_count += 1
                T1, seg1, t1 = inters[0][0]
                T2, seg2, t2 = inters[0][1]
                if not opt.force_remove_self_intersections:
                    print("Self-intersection detected!")
                    greenpart = first_half.cropped(0, T1)
                    redpart = second_half.cropped(T2, 1)

                new_path = [seg for seg in first_half.cropped(T1, 1)]
                new_path += [seg for seg in middle_peice]
                new_path += [seg for seg in second_half.cropped(0, T2)]
                new_path = Path(*new_path)

                if opt.force_remove_self_intersections:
                    dec = True
                else:
                    print("Should I remove the red and green sections?")
                    disvg([greenpart, new_path, redpart],
                          ['green', 'blue', 'red'],
                          nodes=[seg1.point(t1)])
                    dec = inputyn()

                if dec:
                    r.path = new_path
                    print("Path cropped.")
                else:
                    print("OK... I hope things work out for you.")
        if bad_rings:
            paths = [r.path for r in ring_list]
            colors = [r.color for r in ring_list]
            center_line = Line(center-1, center+1)
            nodes = []
            for r_idx, Ts in bad_rings:
                for T in Ts:
                    nodes.append(ring_list[r_idx].path.point(T))
                colors[r_idx] = opt.colordict['safe2']
            node_colors = [opt.colordict['safe1']] * len(nodes)

            tmp = svgfile[0:len(svgfile)-4] + "_SelfIntersections.svg"
            fixed_svg_filename = os_path.join(opt.output_directory, tmp)
            disvg(paths + [center_line],
                  colors + [opt.colordict['center']],
                  nodes=nodes,
                  node_colors=node_colors,
                  filename=fixed_svg_filename)
            tmp_mes = (
                "Some rings contained multiple self-intersections, you better "
                "take a look.  They must be fixed manually (in Inkscape or "
                "Adobe Illustrator). An svg has been output highlighting the "
                "rings which must be fixed manually (and the points where the "
                "self-intersections occur).  Fix the highlighted rings and "
                "replace your old svg with the fixed one (the colors/circles "
                "used to highlight the intersections will be fixed/removed "
                "automatically).\n Output svg saved to:\n"
                "{}".format(fixed_svg_filename))
            raise Exception(tmp_mes)

        et = format_time(current_time()-rsi_start_time)
        print("Done fixing self-intersections ({} detected in {})."
              "".format(fixable_count, et))


    # Check that all rings are smooth (search for kinks and round them)
    if opt.smooth_rings:
        print("Smoothing paths...")
        bad_rings = []
        for r_idx, r in enumerate(ring_list):
            args = (r.path, opt.maxjointsize, opt.tightness, True)
            r.path = smoothed_path(*args)
            still_kinky_list = kinks(r.path)
            if still_kinky_list:
                bad_rings.append((r_idx, still_kinky_list))

        # If unremovable kinks exist, tell user to remove them manually
        if opt.ignore_unremovable_kinks or not bad_rings:
            opt.rings_may_contain_unremoved_kinks = False
        else:
            paths = [r.path for r in ring_list]
            colors = [r.color for r in ring_list]
            center_line = Line(center-1, center+1)
            nodes = []
            for r_idx, kink_indices in bad_rings:
                for idx in kink_indices:
                    kink = ring_list[r_idx].path[idx].start
                    nodes.append(kink)
                colors[r_idx] = opt.colordict['safe2']
            node_colors = [opt.colordict['safe1']] * len(nodes)

            tmp = svgfile[0:len(svgfile)-4] + "_kinks.svg"
            fixed_svg_filename = os_path.join(opt.output_directory, tmp)
            disvg(paths + [center_line],
                  colors + [opt.colordict['center']],
                  nodes=nodes,
                  node_colors=node_colors,
                  filename=fixed_svg_filename)
            raise Exception("Some rings contained kinks which could not be "
                            "removed automatically.  "
                            "They must be fixed manually (in inkscape or "
                            "adobe illustrator). An svg has been output "
                            "highlighting the rings which must be fixed "
                            "manually (and the points where the "
                            "kinks occur).  Fix the highlighted "
                            "rings and replace your old svg with the fixed "
                            "one (the colors/circles used to highlight the "
                            "kinks will be fixed/removed automatically).\n"
                            "Output svg saved to:\n"
                            "%s" % fixed_svg_filename)
        print("Done smoothing paths.")


    # Check for overlapping ends in open rings
    if opt.check4overlappingends:
        print("Checking for overlapping ends (that do not intersect)...")
        bad_rings = []
        for r_idx, r in enumerate(ring_list):
            if r.path.isclosed():
                continue
            startpt = r.path.start
            endpt = r.path.end
            path_wo_start = r.path.cropped(.1, 1)
            path_wo_end = r.path.cropped(0, .9)
            start_is_outwards = isPointOutwardOfPath(startpt, path_wo_start)
            end_is_outwards = isPointOutwardOfPath(endpt, path_wo_end)
            if start_is_outwards:
                bad_rings.append((r_idx, 0, start_is_outwards))
            if end_is_outwards:
                bad_rings.append((r_idx, 1, end_is_outwards))

        if bad_rings:
            paths = [r.path for r in ring_list]
            colors = [r.color for r in ring_list]
            center_line = Line(center-1, center+1)
            for r_idx, endbin, segts in bad_rings:
                colors[r_idx] = opt.colordict['safe2']

            # indicator lines
            indicator_lines = []
            for r_idx, endbin, segts in bad_rings:
                bad_path = ring_list[r_idx].path
                endpt = bad_path.point(endbin)
                for bad_seg_idx, bad_t in segts:
                    bad_pt = bad_path[bad_seg_idx].point(bad_t)
                    indicator_lines.append(Line(bad_pt, endpt))
            indicator_cols = [opt.colordict['safe1']] * len(indicator_lines)

            tmp = svgfile[0:len(svgfile)-4] + "_OverlappingEnds.svg"
            fixed_svg_filename = os_path.join(opt.output_directory, tmp)
            disvg(paths + [center_line] + indicator_lines,
                  colors + [opt.colordict['center']] + indicator_cols,
                  filename=fixed_svg_filename)
            bad_ring_count = len(set(x[0] for x in bad_rings))
            tmp_mes = (
                "Detected {} rings with overlapping (but not intersecting) "
                "ends.  They must be fixed manually (e.g. in Inkscape or "
                "Adobe Illustrator).  An svg has been output highlighting the "
                "rings which must be fixed manually.  Fix the highlighted "
                "rings, remove the,indicator lines added, and replace your "
                "old svg with the fixed one (the colors used to highlight the "
                "intersections will be fixed automatically).\nIf the "
                "indicator lines do not appear to be normal to the ring, this "
                "is possibly caused by a very short path segment.  In this "
                "case, you may want to try increasing "
                "min_relative_segment_length in options and running again.\n"
                "Output svg saved to:\n"
                "{}".format(bad_ring_count, fixed_svg_filename))
            raise Exception(tmp_mes)
        print("Done checking for overlapping ends.")


    # Trim paths with high curvature (i.e. curly) ends
    if opt.remove_curly_ends:
        print("Trimming high curvature ends...")
        for ring in ring_list:
            if ring.isClosed():
                continue

            # 90 degree turn in distance of opt.tol_isNear
            tol_curvature = 2**.5 / opt.tol_isNear  #####Tolerance

            # Find any points within tol_isNear of start and end that have
            # curvature equal to tol_curvature, later we'll crop them off
            from svgpathtools import real, imag
            from svgpathtools.polytools import polyroots01
            def icurvature(seg, kappa):
                """returns a list of t-values such that 0 <= t<= 1 and
                seg.curvature(t) = kappa."""
                z = seg.poly()
                x, y = real(z), imag(z)
                dx, dy = x.deriv(), y.deriv()
                ddx, ddy = dx.deriv(), dy.deriv()

                p = kappa**2*(dx**2 + dy**2)**3 - (dx*ddy - ddx*dy)**2
                return polyroots01(p)

            # For first segment
            startseg = ring.path[0]
            ts = icurvature(startseg, tol_curvature)
            ts = [t for t in ts if startseg.length(t1=t) < opt.tol_isNear]
            if ts:
                T0 = ring.path.t2T(0, max(ts))
            else:
                T0 = 0

            # For last segment
            endseg = ring.path[-1]
            ts = icurvature(endseg, tol_curvature)
            ts = [t for t in ts if endseg.length(t0=t) < opt.tol_isNear]
            if ts:
                T1 = ring.path.t2T(-1, min(ts))
            else:
                T1 = 1

            # crop (if necessary)
            if T0 != 0 or T1 != 1:
                ring.path = ring.path.cropped(T0, T1)

        print("Done trimming.")


    # Check that there are no rings end outside the boundary ring (note
    # intersection removal in next step makes this sufficient)
    print("Checking for rings outside boundary ring...")
    boundary_ring = max([r for r in ring_list if r.isClosed()],
                        key=lambda rgn: rgn.maxR)
    outside_mark_indices = []
    for idx, r in enumerate(ring_list):
        if r is not boundary_ring:
            pt_outside_bdry = center + 2*boundary_ring.maxR
            if not ptInsideClosedPath(r.path[0].start,
                                      pt_outside_bdry,
                                      boundary_ring.path):
                outside_mark_indices.append(idx)
    if outside_mark_indices:
        ring_list = [r for i,r in enumerate(ring_list)
                     if i not in outside_mark_indices]
        warn("%s paths were found outside the boundary path and will be "
             "ignored." % len(outside_mark_indices))
    print("Done removing rings outside of boundary ring.")


    # Remove intersections (between distinct rings)
    if opt.rings_may_contain_intersections:
        print("Removing intersections (between distinct rings)...")
        from noIntersections4rings import remove_intersections_from_rings
        opt.basic_output_on.dprint("Now attempting to find and remove all "
                               "intersections from rings (this will take a "
                               "long time)...")
        intersection_removal_start_time = current_time()

        ring_list, intersection_count, overlappingClosedRingPairs = \
            remove_intersections_from_rings(ring_list)

        if not overlappingClosedRingPairs:
            tot_ov_time = format_time(current_time() - intersection_removal_start_time)
            opt.basic_output_on.dprint("Done (in just %s). Found and removed %s "
                                   "intersections." % (tot_ov_time,
                                                       intersection_count))
        else:
            # fixed_paths = [parse_path(r.string) for r in ring_list]
            fixed_paths = [r.path for r in ring_list]
            fixed_colors = [r.color for r in ring_list]
            center_line = Line(center-1, center+1)
            nodes = []
            for i, j in overlappingClosedRingPairs:
                fixed_colors[i] = opt.colordict['safe1']
                fixed_colors[j] = opt.colordict['safe2']
                inters = pathXpathIntersections(ring_list[i].path,ring_list[j].path)
                nodes += [inter[0].point(inter[2]) for inter in inters]

            tmp = svgfile[0:len(svgfile)-4] + "_ClosedRingsOverlap.svg"
            fixed_svg_filename = os_path.join(opt.output_directory, tmp)
            disvg(fixed_paths + [center_line],
                  fixed_colors + [opt.colordict['center']],
                  nodes=nodes,
                  filename=fixed_svg_filename)
            raise Exception("Found %s pair(s) over overlapping closed rings.  "
                            "They must be fixed manually (in inkscape or "
                            "adobe illustrator). An svg has been output "
                            "highlighting the rings which must be separated "
                            "manually (and the points where they intersect).  "
                            "Fix the highlighted rings and replace your old "
                            "svg with the fixed one (the colors/circles used "
                            "to highlight the intersections will be "
                            "fixed/removed automatically).\n"
                            "Output svg saved to:\n"
                            "%s" % (len(overlappingClosedRingPairs),
                                    fixed_svg_filename))


    # Output a fixed SVG that is (hopefully) how this SVG would be if humans
    # were perfect
    from options4rings import create_fixed_svg
    if create_fixed_svg:
        opt.basic_output_on.dprint("Now creating a fixed svg file...", 'nr')
        fixed_paths = [r.path for r in ring_list]
        fixed_colors = [r.color for r in ring_list]
        center_line = Line(center - 1, center + 1)

        tmp = svgfile[0:len(svgfile)-4] + "_fixed.svg"
        fixed_svg_filename = os_path.join(opt.output_directory, tmp)
        wsvg(fixed_paths + [center_line],
              fixed_colors + [opt.colordict['center']],
              filename=fixed_svg_filename)
        opt.basic_output_on.dprint("Done.  SVG file saved to:\n"
                                   "%s" % fixed_svg_filename)
Exemple #34
0
def find_ring_areas(sorted_ring_list, center, svgfile):

    # This codeblock creates a one pixel by one pixel square Ring object to
    # act as the core - it is recorded in CP. note: perimeter should be found
    # as a path and treated at a ring already
    csd = centerSquare(center)
    csd_path = parse_path(csd)
    if not isCCW(csd_path, center):
        csd_path = reversePath(csd_path)

    # path_string, color, brooke_tag, center
    center_square = Ring(csd, colordict['center'], 'not recorded', Radius(center), csd_path)

    # Converts the sorted_ring_list into a CP_Boolset of
    # complete rings each containing their IRs
    completeRing_CPB = CP_BoolSet()
    innerRing = center_square
    innerRing_index = -1
    for ring_index, ring in enumerate(sorted_ring_list):
        # when next closed ring found create CompleteRing object,
        # then set all inbetween rings to be IRs
        if ring.isClosed():
            completeRing_CPB.append(CompleteRing(innerRing, ring))
            for inc_ring in sorted_ring_list[innerRing_index+1:ring_index]:
                ir = IncompleteRing(inc_ring)
                ir.set_inner(innerRing)
                ir.set_outer(ring)
                completeRing_CPB.cpUpdate(CompleteRing(ir.innerCR_ring, ir.outerCR_ring, ir))
            innerRing = ring
            innerRing_index = ring_index

    # Check (once again) that the last sort-suggested
    # boundary is closed and correctly colored
    bdry_ring = sorted_ring_list[-1]
    if bdry_ring.color != colordict['boundary'] or not bdry_ring.isClosed():

        ###DEBUG Why is this necessary?  Isn't this fixed earlier?
        if sorted_ring_list[-1] == max(sorted_ring_list, key=lambda r: r.maxR):
            sorted_ring_list[-1].color = colordict['boundary']
        else:
            raise Exception("Last ring in sorted sorted_ring_list was not "
                            "closed... this should be outer perimeter.")

    # identify the center square created earlier as the core
    completeRing_CPB[0].isCore = True
    basic_output_on.dprint("All complete_ring objects created and all "
                           "incomple_ring objects created (and stored inside "
                           "the appropriate complete_ring object).")

    # complete the incomplete rings
    CP_start_time = start_time_ring_completion = current_time()
    for count,cp in enumerate(completeRing_CPB):
        if count:
            CP_start_time = current_time()
        try:
            cp.completeIncompleteRings()
        except:
            if outputTroubledCPs:
                paths = ([cp.inner.path, cp.outer.path] +
                         [ir.ring.path for ir in cp.ir_boolset] +
                         [sorted_ring_list[-1].path])
                path_colors = ([cp.inner.color, cp.outer.color] +
                               [ir.ring.color for ir in cp.ir_boolset] +
                               [colordict['boundary']])
                center_line = Line(cp.inner.center-1,cp.inner.center+1)
                svgname = os_path.join(output_directory_debug,"trouble_"+svgfile)
                disvg(paths,path_colors,lines=[center_line],filename=svgname)
                print("Simplified SVG created containing troublesome section "
                      "(troublesome incomplete ring colored {}) and saved "
                      "to:\n{}".format(colordict['safe1'], svgname))
            raise

        mes = ("{}/{} complete rings finished. This CP = {} | Total ET = {}"
               "".format(count + 1,
                len(completeRing_CPB),
                format_time(current_time()-CP_start_time),
                format_time(current_time()-start_time_ring_completion)))
        showCurrentFilesProgress.dprint(mes)

    outputFile = os_path.join(output_directory, svgfile + '_completeRing_info.csv')
    with open(outputFile, "wt") as out_file:
        out_file.write("complete ring index, type, # of IRs contained, minR, "
                       "maxR, aveR, area, area Ignoring IRs\n")
        cp_index = 0
        for cp in completeRing_CPB:
            cp_index += 1
            out_file.write(cp.info(cp_index,colordict) + '\n')

    # Create SVG showing areas (i.e. showing completed paths)
    if create_SVG_showing_area_paths:
        basic_output_on.dprint("Attempting to create SVG showing completed "
                               "paths used for area computation...", 'nr')
        svgpaths = []
        svgcolors = []
        for cp in completeRing_CPB:
            svgpaths.append(cp.inner.path)
            svgcolors.append(cp.inner.color)
            for ir in cp.ir_boolset:
                svgpaths.append(ir.completed_path)
                svgcolors.append(ir.ring.color)
            if cp.outer.color == colordict['boundary']:
                svgpaths.append(cp.outer.path)
                svgcolors.append(cp.outer.color)

        tmp = svgfile[0:len(svgfile)-4] + "_area_paths" + ".svg"
        svgname = os_path.join(output_directory_debug, tmp)
        wsvg(svgpaths, svgcolors, filename=svgname)
        basic_output_on.dprint("Done.")