def fillSvg(svg_path, svg_d, width=750, height=750):
    p = parse_path(svg_d)

    intersections = []
    for i in range(height, 0, -5):
        newline = Line(complex(0, i), complex(100000, i))
        intersect = p.intersect(newline)
        # print(intersect)
        indiv_sections = []
        if (intersect):
            for (T1, seg1, t1), (T2, seg2, t2) in intersect:
                point = p.point(T1)
                if point:
                    point_tuple = (point.real, point.imag)
                    # print(point_tuple)
                    indiv_sections.append(point_tuple)
            # p.append(newline)

            print(indiv_sections)

            pairs = list(
                zip(indiv_sections, indiv_sections[1:] + indiv_sections[:1]))

            del pairs[1::2]

            for pair in pairs:
                x0 = pair[0][0]
                x1 = pair[1][0]
                y = pair[0][1]
                # print("( "+ x0 + ", " + y + "), (" + x1 + ", " + y + ")")
                betweenLine = Line(complex(x0, y), complex(x1, y))
                p.append(betweenLine)

    disvg(p)
Esempio n. 2
0
def _report_unfixable_kinks(_path,_kink_list):
    mes = ("\n%s kinks have been detected at that cannot be smoothed.\n"
           "To ignore these kinks and fix all others, run this function "
           "again with the second argument 'ignore_unfixable_kinks=True' "
           "The locations of the unfixable kinks are at the beginnings of "
           "segments: %s" % (len(_kink_list), _kink_list))
    disvg(_path, nodes=[_path[idx].start for idx in _kink_list])
    raise Exception(mes)
Esempio n. 3
0
def display2rings4user(green_index,red_index,ring_list,mode=None):
    from options4rings import try_to_open_svgs_in_browser, colordict
    filename = 'temporary_4manualSorting.svg'
    save_location = os_path.join(getcwd(),filename)
    center = ring_list[0].center
    boundary_ring = max(ring_list,key=lambda r: r.maxR)
    green='#00FF00';red='#FF0000';bdry_col=colordict['boundary']
    if mode==None or mode=='b':
        disp_paths = [ring_list[green_index].path,ring_list[red_index].path]
        disp_path_colors = [green,red] #['green', 'red']
        disp_paths+= [ring_list[index].path for index in xrange(len(ring_list)) if index not in [green_index,red_index]]
        disp_path_colors += ['black']*(len(ring_list)-2)
    elif mode=='g': #just display green ring (and boundary and center)
        if boundary_ring == ring_list[green_index]:
            disp_paths = [boundary_ring.path]
            disp_path_colors = [green]
        else:
            disp_paths = [ring_list[green_index].path, boundary_ring.path]
            disp_path_colors = [green,'black']
    elif mode=='r': #just display green ring (and boundary and center)
        if boundary_ring == ring_list[red_index]:
            disp_paths = [boundary_ring.path]
            disp_path_colors = [red]
        else:
            disp_paths = [ring_list[red_index].path, boundary_ring.path]; disp_path_colors = [red,'black']
    elif mode=='b+':
        if boundary_ring == ring_list[green_index] or boundary_ring == ring_list[red_index]:
            disp_paths = [ring_list[green_index].path,ring_list[red_index].path]
            disp_path_colors = [green,red]
        else:
            disp_paths = [ring_list[green_index].path,ring_list[red_index].path,boundary_ring.path]
            disp_path_colors = [green,red,bdry_col]
    elif mode=='rb':
        assert boundary_ring != ring_list[green_index] and boundary_ring != ring_list[red_index]
        disp_paths = [ring_list[green_index].path,ring_list[red_index].path,boundary_ring.path]
        disp_path_colors = [ring_list[green_index].color, ring_list[red_index].color, bdry_col]
    else:
        Exception("There is no such setting, 'mode=%s'."%mode)

    if mode=='db':
        disvg(disp_paths + [Line(center-1, center+1)],
              disp_path_colors + [colordict['center']],
              filename=filename, openinbrowser=try_to_open_svgs_in_browser)
    else:
        disvg(disp_paths, disp_path_colors, nodes=[center],
              node_colors=[colordict['center']], filename=filename,
              openinbrowser=try_to_open_svgs_in_browser)
    print('SVG displaying rings at question saved (temporarily) as:\n' + save_location)
Esempio n. 4
0
def dis(paths,colors=None,nodes=None,node_colors=None,node_radii=None,
        lines=None,line_colors=None,
        filename=os_path.join(getcwd(),'temporary_displaySVGPaths.svg'),
        openInBrowser=True,stroke_width=opt.stroke_width_default,
        margin_size=0.1):
    """This is the same as disvg, but with openInBrowser=True by default"""
    if lines and paths:
        stroke_widths = [stroke_width] * len(paths + lines)
    elif paths:
        stroke_widths = [stroke_width] * len(paths)
    elif lines:
        stroke_widths = [stroke_width] * len(lines)
    else:
        stroke_widths = None
    disvg(paths + lines, colors + line_colors,
          nodes=nodes, node_colors=node_colors, node_radii=node_radii,
          filename=filename, openinbrowser=openInBrowser,
          stroke_widths=stroke_widths, margin_size=margin_size)
Esempio n. 5
0
def translate_path_demo(path, tol=5, min_length=5):
    max_depth = 0
    done = False
    while not done:
        print max_depth
        # List of Line objects in the current path
        current_path = []
        for seg in path:
            if isinstance(seg, svgpathtools.Line):
                current_path.append(seg)
            else:  # Bezier curves and arcs.
                approx_path, done = approximate_with_line_segs(
                    seg, tol, min_length, 0, max_depth)
                current_path += approx_path
        # save an svg
        svgpathtools.disvg([path] + current_path,
                           filename=("bez_demo_" + str(max_depth) + ".svg"))
        # TODO: add some nodes - different color for the last ones generated?
        max_depth += 1
Esempio n. 6
0
def normalvf(paths, cols, l=None, sw=.1):
    """This will display the normal vector field for the collections of curves,
    `paths` (and red disks on singular points), which can be useful when
    checking an svg for issues with orientation, smoothness, curvature, etc."""
    if not l:
        l = min(p.length() for p in paths) / 20
        print('l = ', l)
    normals = []
    singular_pts = []
    for p in paths:
        for t in np.linspace(0, 1, 100):
            try:
                normals.append(Line(p.point(t), p.point(t) + l * p.normal(t)))
            except:
                singular_pts.append(p.point(t))
    paths2disp = paths + normals
    try:
        colors = [att['stroke'] for att in cols] + ['purple'] * len(normals)
    except:
        colors = cols + ['purple'] * len(normals)
    disvg(paths2disp, colors, nodes=singular_pts,
          stroke_widths=[sw] * len(paths2disp))
def color_map(geo_code_dict, df, team_and_color):
    #recolor and create output svg
    output = open("output.svg", "w")
    output.write(
        "<!DOCTYPE html><html><body><svg width=\"543\" height=\"228\">")

    #fill in primary color
    i = 0
    for code in geo_code_dict:
        geo_code_dict[code]['stroke'] = "#000000"
        geo_code_dict[code]['stroke-width'] = "0.5"

        color = team_and_color[df['Favorite Team'][i]]
        #change color saturation according to percentage

        #rgb_color = webcolors.hex_to_rgb(team_and_color[df['Favorite Team'][i]])
        #hsv_color = colorsys.rgb_to_hsv(rgb_color[0],rgb_color[1],rgb_color[2])
        #lst = list(hsv_color)
        #lst[1] = lst[1] * ((df['Percentage'][i])/100)
        #hsv_color = tuple(lst)
        #rgb_color = hsv_to_rgb(hsv_color[0],hsv_color[1],hsv_color[2])
        #lst = list(rgb_color)
        #lst[0] = int(rgb_color[0])
        #lst[1] = int(rgb_color[1])
        #lst[2] = int(rgb_color[2])
        #rgb_color = tuple(lst)
        #color = webcolors.rgb_to_hex(rgb_color)

        geo_code_dict[code]['fill'] = color
        output.write("<path d=\"%s\" stroke=\"%s\" stroke-width=\"%s\" fill=\"%s\"></path>" % \
                     (geo_code_dict[code]['d'], geo_code_dict[code]['stroke'], geo_code_dict[code]['stroke-width'], geo_code_dict[code]['fill']))
        i = i + 1

    output.write("</svg></body></html>")
    output.close()
    #output final svg map
    paths, attributes = svg2paths('output.svg')
    disvg(paths, filename='output.svg', attributes=attributes)
Esempio n. 8
0
def wsvg(paths=None,
         colors=None,
         filename=os.path.join(os.getcwd(), 'disvg_output.svg'),
         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,
         svgwrite_debug=False,
         paths2Drawing=False):
    #NB: this code is originally from <https://github.com/mathandy/svgpathtools>.
    # Thanks tho @mathandy
    """Convenience function; identical to disvg() except that
    openinbrowser=False by default.  See disvg() docstring for more info."""
    return disvg(paths,
                 colors=colors,
                 filename=filename,
                 stroke_widths=stroke_widths,
                 nodes=nodes,
                 node_colors=node_colors,
                 node_radii=node_radii,
                 openinbrowser=openinbrowser,
                 timestamp=timestamp,
                 margin_size=margin_size,
                 mindim=mindim,
                 dimensions=dimensions,
                 viewbox=viewbox,
                 text=text,
                 text_path=text_path,
                 font_size=font_size,
                 attributes=attributes,
                 svg_attributes=svg_attributes,
                 svgwrite_debug=svgwrite_debug,
                 paths2Drawing=paths2Drawing)
Esempio n. 9
0
import weirdvector as wv
from svgpathtools import Path, Line, wsvg, disvg

s = [0, 0.5, 0.8, 0.3, 1]
s = wv.fractalize_mult(s,s)
s = wv.fractalize_mult(s,s)

path = [Line(100+100j, 200+200j)]
for i in range(len(s)):
    path.push(Line(i*100+s[i]*2000j, (i+1)*100+s[i]*2000j)

disvg(path, filename="svgtest.svg")
Esempio n. 10
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)
Esempio n. 11
0
try:
    paths, attributes = svgpathtools.svg2paths(args.filename)
except FileNotFoundError as e:
    print(e)
    exit(1)


def invert_y(c):  # I feel like there should be a better way
    return numpy.real(c) - numpy.imag(c) * 1j


if args.showsvg:
    color_list = 'krgbcym'
    color_list *= int(len(paths) / len(color_list)) + 1
    color_list = color_list[:len(paths)]
    svgpathtools.disvg(paths, color_list)
    exit(0)

try:
    if not args.test:
        robot = Root(args.name)
    else:
        robot = Turtle()
    robot.wait_for_connect()
    time.sleep(1)

    segments = numpy.linspace(0, 1, args.approximate + 1)

    for path in paths:
        for element in path:
            if args.verbose:
Esempio n. 12
0
def generate_unsorted_transects(ring_list, center):
    from options4rings import basic_output_on, warnings_output_on, N_transects, unsorted_transect_debug_output_folder, unsorted_transect_debug_on, colordict
    from misc4rings import transect_from_angle, normalLineAt_t_toInnerSeg_intersects_withOuter
    from andysSVGpathTools import pathlistXlineIntersections
    from andysmod import Timer
    import operator
    from random import uniform

    #Find outer boundary ring
    for r in ring_list:
        if r.color == colordict['boundary']:
            boundary_ring = r
            break
    else:
        warnings_output_on.dprint("[Warning:] Having trouble finding outer boundary - it should be color %s.  Will now search for a ring of a similar color and if one is found, will use that.\n"%colordict['boundary'])
        from misc4rings import closestColor
        for r in ring_list:
            if colordict['boundary'] == closestColor(r.color,colordict):
                boundary_ring = r
                basic_output_on.dprint("Found a ring of color %s, using that one."%r.color)
                break
        else:
            warnings_output_on.dprint("[Warning:] Outer boundary could not be found by color (or similar color).  This is possibly caused by the outer boundary ring not being closed - in this case you'd be able to see a (possibly quite small) gap between it's startpoint and endpoint. Using the ring of greatest maximum radius as the boundary ring (and hoping if there is a gap none of the transects hit it).\n")
            keyfcn = lambda x: x.maxR
            boundary_ring = max(ring_list,key=keyfcn)

    #Find transects
    from time import time as current_time
    from andysmod import format_time
    tr_gen_start_time = current_time()
    data = []
    data_indices = []
    angles = []
    for dummy_index in range(N_transects): #dummy_index only used to create loop
        #estimate time remaining
        if dummy_index != 0:
            total_elapsed_time = current_time() - tr_gen_start_time
            estimated_time_remaining = (N_transects - dummy_index)*total_elapsed_time/dummy_index
            timer_str = 'Transect %s of %s || Est. Remaining Time = %s || Elapsed Time = %s'%(dummy_index+1,N_transects,format_time(estimated_time_remaining),format_time(total_elapsed_time))
            overwrite_progress = True
        else:
            timer_str = 'transect %s of %s'%(dummy_index+1,N_transects)
            overwrite_progress = False
            print('')

        #generate current transect
        with Timer(timer_str, overwrite=overwrite_progress):
            if unsorted_transect_debug_on:
                print('')
            test_angle = uniform(0, 1)
#                        test_angle = 0.408
            angles.append(test_angle)
            transect = [center]
            transect_rings = ['core']
            unused_ring_indices = range(len(ring_list)) #used to keep track of which rings I've used and thus don't need to be checked in the future

            # Find first transect segment (from core/center)
            # normal line to use to find intersections (from center to boundary ring)
            nl2bdry, seg_outer, t_outer = transect_from_angle(test_angle, center, boundary_ring.path, 'debug')
            #make normal line a little longer
            nl2bdry = Line(nl2bdry.start, nl2bdry.start + 1.5*(nl2bdry.end-nl2bdry.start))
            tmp = pathlistXlineIntersections(nl2bdry, [ring_list[i].path for i in unused_ring_indices])
            (tl,path_index,seg,tp) = min(tmp, key=operator.itemgetter(0)) #(tl,path_index,seg,tp)

            transect.append(nl2bdry.point(tl))
            transect_rings.append(unused_ring_indices[path_index])
            del unused_ring_indices[path_index]

            #now for the rest of the transect
            num_rings_checked = 0
            while (ring_list[transect_rings[-1]] != boundary_ring and 
                   num_rings_checked < len(ring_list)):  # < is correct, already did first
                num_rings_checked += 1
                inner_path = ring_list[transect_rings[-1]].path
                inner_t = tp
                inner_seg = seg
                
                # normal line to use to find intersections (from center to boundary ring)
                nl2bdry, seg_outer, t_outer = normalLineAt_t_toInnerSeg_intersects_withOuter(inner_t, inner_seg, boundary_ring.path, center, 'debug') 
                # make normal line a little longer
                nl2bdry = Line(nl2bdry.start,nl2bdry.start + 1.5*(nl2bdry.end-nl2bdry.start)) 
                
                normal_line_intersections = pathlistXlineIntersections(nl2bdry, [ring_list[i].path for i in unused_ring_indices])
                try:
                    # (tl,path_index,seg,tp)
                    tl, path_index, seg, tp = min(normal_line_intersections,
                                                  key=operator.itemgetter(0))
                except ValueError:
                    raise
                if unsorted_transect_debug_on:
                    from andysmod import format001
                    inner_path_index = transect_rings[-1]
                    used_ring_paths = [r.path for i,r in enumerate(ring_list) if i not in unused_ring_indices+[inner_path_index]]
                    used_ring_colors = ['black']*len(used_ring_paths)
                    unused_ring_paths = [ring_list[i].path for i in unused_ring_indices]
                    unused_ring_colors = [ring_list[i].color for i in unused_ring_indices]
                    transect_so_far = Path(*[Line(transect[i-1],transect[i]) for i in range(1,len(transect))])
                    paths = used_ring_paths + unused_ring_paths + [transect_so_far] +[inner_path] + [nl2bdry]
                    colors = used_ring_colors + unused_ring_colors + ['green']+['blue'] + ['black']

                    nodes_so_far = transect[1:-1]
                    potential_nodes = [nl2bdry.point(tltmp) for (tltmp,path_indextmp,segtmp,tptmp) in normal_line_intersections]
                    nodes = nodes_so_far + potential_nodes
                    node_colors = ['red']*len(nodes_so_far) + ['purple']*len(potential_nodes)
                    save_name = unsorted_transect_debug_output_folder+'unsorted_transect_debug_%s.svg'%format001(3,len(transect))
                    disvg(paths,colors,nodes=nodes,node_colors=node_colors,center=center,filename=save_name,openInBrowser=False)
                    print("Done with %s out of (at most) %s transect segments"%(len(transect),len(ring_list)))
                transect.append(nl2bdry.point(tl))
                transect_rings.append(unused_ring_indices[path_index])
                del unused_ring_indices[path_index]
            data.append(transect)
            data_indices.append(transect_rings)
    return data, data_indices, angles
Esempio n. 13
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
Esempio n. 14
0
    def completeIncompleteRings(self):
        """This fcn takes each ir included in self and makes a closed path to
        use for its area computation."""

        # make sure ir_boolset is sorted (by sort index found in topological sort)
        self.sortIRs()

        if len(self.ir_boolset) == 0:
            return

        # iterate through IRs to complete them one by one, inner-most to outer-most
        for i,ir in enumerate(self.ir_boolset):
            # try all more-inner IRs (and the inner CR) starting with
            # most-outer among them - this is for finding transects.
            # Note: #poten[j] = ir_boolset[j-1].ring for j=1,...,i
            potential_rings = [self.inner] + [x.ring for x in self.ir_boolset[0:i]]

            # Find transects from the endpoints of ir to the next most-Outer
            # of the more-inner acceptable rings
            # Note: the ir's are sorted, but need to make sure each transect
            # is well-defined (i.e. check the potential connecting ir does in
            # fact travel "below" that endpoint)
            # Note: findTransects fcn used below will return
            # (False, False, False, False) for any transects already found
            nextRing2Try_index = i  # note this is right, not i-1 cause potential rings has self.inner at beginning
            while not (ir.transect0found and ir.transect1found) and nextRing2Try_index >= 0:
                nextRing2Try = potential_rings[nextRing2Try_index]
                if nextRing2Try_index == 0:
                    irORcr_2Try = self
                else:
                    irORcr_2Try = self.ir_boolset[nextRing2Try_index-1]

                tmp = ir.findTransects2endpointsFromInnerPath_normal(irORcr_2Try, nextRing2Try.path)
                (irORcr0, tL0, seg0, t0), (irORcr1, tL1, seg1, t1) = tmp

                # check if nextRing2Try is has a transect going to the
                # startpoint, if so we're done with this endpoint
                if tL0 != False:
                    # ring.path.point(T0) is where the transect, tL, meets
                    # this ring
                    T0 = segt2PathT(irORcr0.ORring.path,seg0,t0)

                    # record up-ladder on the ring the transect connects to
                    # (and t-val it connects at)
                    irORcr0.up_ladders.append((ir,T0))

                    # record startpoint down-ladder on this ir and (and t-val
                    # on connecting ring it connects at)
                    ir.down_ladder0 = (irORcr0,T0)
                    if not ir.transect0found:
                        ir.transect0found = True
                else:
                    ir.transect0fails.append(irORcr_2Try)

                # check if nextRing2Try has a transect going to the endpoint,
                # if so we're done with this endpoint
                if tL1 != False:
                    # ring.path.point(T0) is where the transect, tL, meets
                    # this ring
                    T1 = segt2PathT(irORcr1.ORring.path, seg1, t1)

                    # record up-ladder on the ring the transect connects to
                    # (and t-val it connects at)
                    irORcr1.up_ladders.append((ir, T1))

                    # record startpoint down_ladder on this ir and (and t-val
                    # on connecting ring it connects at)
                    ir.down_ladder1 = (irORcr1, T1)

                    if not ir.transect1found:
                        ir.transect1found = True
                else:
                    ir.transect1fails.append(irORcr_2Try)

                # unsuccessful while-loop termination conditions
                if (nextRing2Try_index == 0 and
                    not (ir.transect0found and ir.transect1found)):

                    printPath(ir.ring.path)
                    print(i)
                    colors = ['blue']*(len(self.ir_boolset)+2) + ['red']
                    paths2disp = ([self.inner.path] +
                                 [x.ring.path for x in self.ir_boolset] +
                                 [self.outer.path] +
                                 [ir.ring.path])
                    disvg(paths2disp, colors)
                    raise Exception("Acceptable more-inner ring could not be "
                                    "found.")
                else:
                    nextRing2Try_index -= 1

        # Now that all up/down ladders are set in this CR, iterate through IRs
        # again and create completed_path for each
        for ir in self.ir_boolset:
            try:
                ir.hardComplete()
            except:
                from options4rings import colordict
                # highlight ir in output SVG containing troubled section
                # (see area4rings)
                ir.ring.color = colordict['safe1']
                raise
Esempio n. 15
0
from svgpathtools import svg2paths, disvg, path

paths, attrs = svg2paths("../imgs/indiana_map.svg")

disvg(paths, stroke_widths=[5])
Esempio n. 16
0
def svg2rings(SVGfileLocation):
    global already_warned_having_trouble_extracting_ring_colors
    already_warned_having_trouble_extracting_ring_colors = False

    def getStroke(elem): #get 'stroke' attribute fom xml object
        troubleFlag=False
        stroke = elem.getAttribute('stroke') #sometimes this works
        if stroke=='':
            style = elem.getAttribute('style')
            hexstart = style.find('stroke')
            if hexstart==-1:
                troubleFlag=True
            else:
                temp = style[hexstart:]
                try:
                    stroke = re.search(re.compile('\#[a-fA-F0-9]*'),temp).group()
                except:
                    troubleFlag=True
                    stroke=''

        if troubleFlag:
            global already_warned_having_trouble_extracting_ring_colors
            if not already_warned_having_trouble_extracting_ring_colors:
                already_warned_having_trouble_extracting_ring_colors = True
                opt.warnings_output_on.dprint("Warning: Having trouble extracting hex colors from svg.  Hopefully this will not matter as the palette check will fix the colors.")
        return stroke.upper()




    example_center = r'<line fill="none" stroke="#0000FF" stroke-width="0.15" x1="246.143" y1="380.017" x2="246.765" y2="380.856"/>'

    doc = minidom.parse(SVGfileLocation)  # parseString also exists
    #Find the center
    counter = 0
    centerFound = False
    for elem in doc.getElementsByTagName('line'):
        if getStroke(elem) == colordict['center']:
            center = 0.5*float(elem.getAttribute('x1'))+0.5*float(elem.getAttribute('x2')) + 0.5*float(elem.getAttribute('y1'))*1j +0.5*float(elem.getAttribute('y2'))*1j
            rad = Radius(center)
            centerFound = True
            break
        else:
            counter += 1
    if counter>0 and not centerFound:
        opt.warnings_output_on.dprint("[Warning:] No line objects in the svg were found matching the center color (%s).  Now searching for lines of a color closer to center color than other colors."%counter)
        for elem in doc.getElementsByTagName('line'):
            if closestColor(getStroke(elem),colordict) == colordict['center']:
                center = 0.5*float(elem.getAttribute('x1'))+0.5*float(elem.getAttribute('x2')) + 0.5*float(elem.getAttribute('y1'))*1j +0.5*float(elem.getAttribute('y2'))*1j
                rad = Radius(center)
                centerFound = True
                counter -=1
                break
    if counter>0: #center found but counter>0
        opt.warnings_output_on.dprint("[Warning:] There are %s disconnected lines in this SVG not matching the center color.  They will be ignored."%counter)
    try:
        center.real #test if center exists (should be a complex number object)
    except:
        try:
            if counter == 0:

                #Is there a path with the center color?
                for elem in doc.getElementsByTagName('path')+doc.getElementsByTagName('polyline')+doc.getElementsByTagName('polygon'):
                    if getStroke(elem) == colordict['center']:
                        if elem in doc.getElementsByTagName('path'):
                            obtype = 'path'; pathstr = elem.getAttribute('d')
                        elif elem in doc.getElementsByTagName('polyline'):
                           obtype = 'polyline'; pathstr = polylineStr2pathStr(elem.getAttribute('points'))
                        else:
                            obtype = 'polygon'; pathstr = polylineStr2pathStr(elem.getAttribute('points')) + 'z'
                        centerpath = parse_path(pathstr)
                        start,end = centerpath.point(0.25),centerpath.point(0.75)
                        x1,x2,y1,y2 = start.real,end.real,start.imag,end.imag
                        newelem = r'<line fill="none" stroke="%s" stroke-width="0.05" stroke-miterlimit="10" x1="%s" y1="%s" x2="%s" y2="%s"/>'%(colordict['center'],x1,y1,x2,y2)
                        raise Exception("Center of sample should be marked by line of color %s, but no lines are present in svg.  There is a %s with the center color, however.  Open the svg file in a text editor and you should be able to find '%s' somewhere... replace it with '%s'"%(colordict['center'],obtype,elem,newelem))
                else:
                    for elem in doc.getElementsByTagName('path')+doc.getElementsByTagName('polyline')+doc.getElementsByTagName('polygon'):
                        if closestColor(getStroke(elem),colordict) == colordict['center']:
                            if elem in doc.getElementsByTagName('path'):
                                obtype = 'path'; pathstr = elem.getAttribute('d')
                            elif elem in doc.getElementsByTagName('polyline'):
                                obtype = 'polyline'; pathstr = polylineStr2pathStr(elem.getAttribute('points'))
                            else:
                                obtype = 'polygon'; pathstr = polylineStr2pathStr(elem.getAttribute('points')) + 'z'
                            centerpath = parse_path(pathstr)
                            start,end = centerpath.point(0.25),centerpath.point(0.75)
                            x1,x2,y1,y2 = start.real,end.real,start.imag,end.imag
                            newelem = r'<line fill="none" stroke="%s" stroke-width="0.05" stroke-miterlimit="10" x1="%s" y1="%s" x2="%s" y2="%s"/>'%(colordict['center'],x1,y1,x2,y2)
                            raise Exception("Center of sample should be marked by line of color %s, but no lines are present in svg.  There is a path with color close to the center color, however.  Open the svg file in a text editor and you should be able to find '%s' somewhere... replace it with '%s'"%(colordict['center'],obtype,elem,newelem))

                    else:
                        raise Exception('Center of sample should be marked by line of color %s, but no lines are present in svg.  There were no paths or polylines or polygons of a similar color either.  Looks like you did not mark the center. Open your svg in a text editor and search for something that looks like (with different x1, x2, y1, y2 values) \n%s\n'%(colordict['center'],example_center))
        except:

            raise Exception('No center found searching line element with (color) stroke = %s. Open your svg in a text editor and search for something that looks like (with different x1, x2, y1, y2 values) \n%s\n'%(colordict['center'],example_center))

    #Use minidom to extract path strings from input SVG
    opt.basic_output_on.dprint("Extracting path_strings from SVG... ",'nr')
    path_strings = [(p.getAttribute('d'),getStroke(p),p.parentNode.getAttribute('id'),p.toxml()) for p in doc.getElementsByTagName('path')]
    #Use minidom to extract polyline strings from input SVG, convert to path strings, add to list
    path_strings += [(polylineStr2pathStr(p.getAttribute('points')),getStroke(p),p.parentNode.getAttribute('id'),p.toxml()) for p in doc.getElementsByTagName('polyline')]
    #Use minidom to extract polygon strings from input SVG, convert to path strings, add to list
    path_strings += [(polylineStr2pathStr(p.getAttribute('points'))+'z',getStroke(p),p.parentNode.getAttribute('id'),p.toxml()) for p in doc.getElementsByTagName('polygon')]
    #currently choosing to ignore line objects (assuming... all lines are fixes for non-overlapping mergers?)
    ##Use minidom to extract line strings from input SVG, convert to path strings, and add them to list
    #line_strings = [('M' + p.getAttribute('x1') + ' ' +p.getAttribute('y1') + 'L'+p.getAttribute('x2') + ' ' + p.getAttribute('y2'),getStroke(p), p.parentNode.getAttribute('id')) for p in doc.getElementsByTagName('line')]
    doc.unlink()
    opt.basic_output_on.dprint("Done.")

#    #(first attempt to) Check for stray points, if any found, delete them
#    i=0
#    count_popped_points = 0
#    while i < len(path_strings):
#        if path_strings[i][0].count(',')<2:
#            path_strings.pop(i)
#            count_popped_points+=1
#            opt.full_output_on.dprint("Removed a stray point: path_string[%s][0] = %s"%(i,path_strings[i][0]))
#        i +=1
#    opt.basic_output_on.dprint("Removed %s stray points in path_string stage.  Continuing..."%count_popped_points)

    #Convert path_strings to ring objects
    opt.basic_output_on.dprint("Converting path strings to Ring objects.  This could take a minute... ",'nr')
    path2ring_start_time = current_time()
    ring_list = []
    paths_of_unknown_orientation = []
    for i in range(len(path_strings)):
        orig_path = parse_path(path_strings[i][0])
        try: ### DEBUG ONLY (REMOVE ALL OF TRY/EXCEPT)
            orig_path[0]
        except:
            if len(path_strings[i][0].split(','))<3:
                opt.full_output_on.dprint("Found (and skipped) single point path: %s"%path_strings[i][0])
                continue
            else:
                raise

        #fix degenerate segments here
        for index,seg in enumerate(orig_path):
            if abs(seg.start-seg.end) < 1:
                old_end = seg.end
                old_start = seg.start
                opt.full_output_on.dprint("Found degenerate seg in path %s: %s"%(i,seg))
                del orig_path[index]
                if index == len(orig_path): #deleted last path
                    orig_path[-1].end = old_end
                elif index == 0:
                    orig_path[0].start=old_start
                else:
                    orig_path[index].start = orig_path[index-1].end
                opt.full_output_on.dprint("Deleted above degenerate segment and fixed gap.")

        #check for doubled over segments
        nostupidsfound = False
        while not nostupidsfound and len(orig_path)>1:
            for indst in range(len(orig_path)-1):
                if (orig_path[indst] == orig_path[indst+1] or
                    orig_path[indst] == orig_path[indst+1].reversed()):
                    del orig_path[indst+1]
                    opt.warnings_output_on.dprint("[Warning:] "+"stupidsfound"*50)
#                    raise Exception() #you should remove this Exception and everything will run smoothly
            else:
                nostupidsfound = True

        #Now fix the orientation if path is not CCW (w.r.t. center)
        try:
            path_is_ccw = isCCW(orig_path,center)
        except:
            if opt.manually_fix_orientations:
                print("\n[Manually Fix Orientations:] As currently drawn, the "
                      "path starts at the green node/segment and ends at the "
                      "red (if you don't see one of these nodes, it's likely "
                      "cause the path is very short and thus they are on top "
                      "of each other).  Does the path in "
                      "'temporary_4manualOrientation.svg' appear to be drawn "
                      "in a clockwise fashion?")
                if len(orig_path) == 1:
                    disp_paths = [orig_path]
                    disp_path_colors = ['blue']
                elif len(orig_path) == 2:
                    disp_paths = [Path(orig_path[0]),Path(orig_path[1])]
                    disp_path_colors = ['green','red']
                elif len(orig_path) > 2:
                    disp_paths = [Path(orig_path[0]),Path(orig_path[1:-1]),Path(orig_path[-1])]
                    disp_path_colors = ['green','blue','red']
                else:
                    raise Exception("This path is empty... this should never happen.  Tell Andy.")
                for ring in ring_list:
                    disp_paths.append(ring.path)
                    disp_path_colors.append('black')

                nodes = [orig_path[0].start,orig_path[-1].end]+[center]
                node_colors = ['green','red']+[colordict['center']]
                disvg(disp_paths, disp_path_colors, nodes=nodes, node_colors=node_colors, filename='temporary_4manualOrientation.svg')
                path_is_ccw = askUserOrientation() #svg display reverses orientation so a respose of 'yes' means path is actually ccw and thus sets path_is_ccw = True
                if path_is_ccw == 'remove':
                    print("OK, this path will be ignored... moving onto the rest.")
                    continue
#                raise Exception("The manually_fix_orientations feature is not yet setup.  If you need this, ask Andy; it shouldn't take him long.")
            else:
                path_is_ccw = opt.when_orientation_cannot_be_determined_assume_CCW
                paths_of_unknown_orientation.append(path_strings[i])
        if not path_is_ccw:
            path2record = orig_path.reversed()
            opt.full_output_on.dprint("Path %s was not oriented CCW, but is now."%i)
        else:
            path2record = orig_path
        ring_list.append(Ring(path_strings[i][0],path_strings[i][1],path_strings[i][2],rad,path2record,xml=path_strings[i][3]))
        opt.full_output_on.dprint("Ring %s ok"%i)
    if len(paths_of_unknown_orientation)>0:
        from andysmod import ifelse
        fashion = ifelse(opt.when_orientation_cannot_be_determined_assume_CCW,'Counterclockwise','Clockwise')
        ccw_warning = "[Warning:] Unable to determine orientation of %s paths.  This is likely because some paths in this sample are far from being convex.  I assumed that these paths were traced in a %s fashion (to change this assumption, set 'when_orientation_cannot_be_determined_assume_CCW = %s' in options.  If this assumption is false, either the program will crash or the transect will be visibly messed up in the output 'xxx_transects.svg' (where xxx is the input svg's filename sans extension)."%(len(paths_of_unknown_orientation),fashion,not opt.when_orientation_cannot_be_determined_assume_CCW)
        opt.warnings_output_on.dprint(ccw_warning)
    if len(paths_of_unknown_orientation)>1:
        opt.warnings_output_on.dprint("If think you were not consistent tracing in either CCW or CW fashion (or don't get good  output from this file) then set 'manually_fix_orientations = True' in options.")

    #done extracting rings from svg
    opt.basic_output_on.dprint("Done (in %s)."%format_time(current_time()-path2ring_start_time))
    opt.basic_output_on.dprint("Completed extracting rings from SVG. %s rings detected."%len(ring_list))
    return center, ring_list