Beispiel #1
0
def createSVG(filename, tool, points):
  # Generate the paths
  allPoints = list()
  paths = list()
  t = Template(PATH_TEMPLATE)
  for point in points:
    allPoints.extend(point)
    path = Path()
    lx, ly = point[0]
    pc = 0
    for p in point[1:]:
      l = mkLine(lx, ly, p[0], p[1])
      if l is not None:
        path.append(l)
        pc = pc + 1
      lx = p[0]
      ly = p[1]
    path.closed = True
    paths.append(t.safe_substitute({ 'strokeWidth': tool, 'path': path.d() }))
    print "Generated path with %d points." % pc
  # Build the final output
  v = { 
    'xmin': min([ x for x, y in allPoints ]) - (tool / 2),
    'ymin': min([ y for x, y in allPoints ]) - (tool / 2),
    'xmax': max([ x for x, y in allPoints ]) + (tool / 2),
    'ymax': max([ y for x, y in allPoints ]) + (tool / 2)
    }
  v['width'] = abs(v['xmax'] - v['xmin'])
  v['height'] = abs(v['ymax'] - v['ymin'])
  v['path'] = "\n".join(paths)
  out = Template(SVG_TEMPLATE).substitute(v).strip()
  # And write the file
  with open(filename, "w") as svg:
    svg.write(out)
Beispiel #2
0
def parse_polygon(points: str) -> Path:
    coordinates = [tuple(map(float, c.split(','))) for c in points.split()]
    path = Path()
    for a, b in pairwise(coordinates):
        path.append(Line(complex(*a), complex(*b)))
    return path
Beispiel #3
0
    def remove_redundant_lines(self):
        lines_bucketed_by_slope_intersect = defaultdict(list)
        paths = self.svg_node.getElementsByTagName('path')
        overall_index = 0
        for path_index, path in enumerate(paths):
            path_text = path.attributes['d'].value
            path_obj = parse_path(path_text)
            for line_index, line in enumerate(path_obj):
                slope, intersect = _get_slope_intersect(line.start, line.end)

                # TODO: float inaccuracy and rounding may cause collinear lines to end up in separate buckets in rare
                # cases, so this is not quite correct. Would be better to put lines into *2* nearest buckets in each
                # dimension to avoid edge cases.
                if slope is not None:
                    slope = round(slope, ndigits=3)
                intersect = round(intersect, ndigits=3)
                lines_bucketed_by_slope_intersect[(slope, intersect)].append({
                    'overall_index': overall_index,
                    'path_index': path_index,
                    'line_index': line_index,
                    'line': line,
                })
                overall_index += 1

        to_remove = {}
        to_update = {}
        for slope_intersect, lines in lines_bucketed_by_slope_intersect.items():
            for i in range(20):
                if SvgProcessor._pairwise_overlap_check(lines, to_update, to_remove):
                    print 'Re-running pairwise overlap check because of updated/merged line'
                    continue
                break
            else:
                raise Exception(
                    'Exceeded the max number of pairwise overlap check passes. Something is probably wrong.'
                )

        # Reconstruct the paths, but excluding/updating the lines we just identified
        i = 0
        removed = 0
        removed_length = 0
        kept = 0
        kept_length = 0
        for path_index, path in enumerate(paths):
            path_text = path.attributes['d'].value
            path_obj = parse_path(path_text)

            filtered_path = Path()

            for line_index, line in enumerate(path_obj):
                if i in to_remove:
                    assert path_index == to_remove[i][0]
                    assert line_index == to_remove[i][1]
                    removed += 1
                    removed_length += line.length()
                elif i in to_update:
                    assert path_index == to_update[i][0]
                    assert line_index == to_update[i][1]
                    replacement_line = to_update[i][2]

                    filtered_path.append(replacement_line)
                    kept += 1
                    kept_length += replacement_line.length()
                else:
                    filtered_path.append(line)
                    kept += 1
                    kept_length += line.length()
                i += 1

            # Update the path data with the filtered path data
            path.attributes['d'] = filtered_path.d()

        print 'Removed {} lines ({} length) and kept {} lines ({} length)'.format(
            removed,
            removed_length,
            kept,
            kept_length,
        )

        return [to_remove[k][2] for k in to_remove], [to_update[k][2] for k in to_update]
Beispiel #4
0
SVG2 = '''  </g>
</svg>
'''

svgpath1 = '''<path
       style="fill:none;fill-rule:evenodd;stroke:#{0:02x}{1:02x}{2:02x};stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
       d="'''
svgpath2 = ''' Z"/>
'''

print(SVG1)
for p in paths:
	path     = parse_path(p.attrib["d"])
	start    = None
	myrange  = list(frange(0, 1, decimal.Decimal('0.01')))
	mycolors = list(red.range_to(blue, len(myrange)))
	
	for i, px in enumerate(myrange):
		new_path = Path()
		if start is None:
			start = path.point(float(px))
		else:
			end   = path.point(float(px))
			new_path.append(Line(start, end))
			start = end
			color = mycolors[i]
			r = int(color.red * 255)
			g = int(color.green * 255)
			b = int(color.blue * 255)
			print((svgpath1 + new_path.d() + svgpath2).format(clamp(r), clamp(g), clamp(b)))
print(SVG2)
Beispiel #5
0
'''

svgpath1 = '''<path
       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
       d="'''
svgpath2 = ''' Z"/>
'''

print(SVG1)
for p in paths:
    new_path = Path()
    path = parse_path(p.attrib["d"])
    start = None
    for command in path:
        if type(command) == Line:
            new_path.append(command)
            start = command.end
            ##print(command)
        else:
            not_line_path = Path(command)
            for px in list(frange(0, 1, decimal.Decimal(factor))):
                if start is None:
                    start = not_line_path.point(float(px))
                else:
                    end = not_line_path.point(float(px))
                    new_command = Line(start, end)
                    new_path.append(new_command)
                    ##print(new_command)
                    start = end

    new_path_str = new_path.d()