注释
贡献者
注意: |
合作者作者
我想我们可以请原作者为我们重新授权。很有可能他只是在没有任何特定原因的情况下获得了 GPLv3…:-) |
合作者作者
合作者作者
这些人还有一些用于 SVG 路径线性化的 python 代码: 像这样工作: from svg_compression import *
comp_instance = Compress("test/test_vector.svg")
comp_instance.find_paths() # Extract path coordinates
comp_instance.linearize_paths(curve_fidelity = 10) # Convert paths into polygons
#comp_instance.write(outputfile = "hrv.svg")
#print(comp_instance.linear_coords[0])
for path in comp_instance.linear_coords:
p = path[0]
print("g0 x%s y%s"%(str(p[0]),str(p[1])))
for p in path:
print("g1 x%s y%s"%(str(p[0]),str(p[1])))
我们也可以扔掉大部分库及其依赖项 但是我们应该禁用圆弧线性化,因为我们可以在本地进行圆弧。 |
合作者作者
我已经从库中删除了所有不需要的东西(GPLv3+): import numpy
import svg.path
import lxml.etree as ET
'''
Compress svg figure through a variety of methods
Written July 22, 2014
Author: Gen Del Raye
'''
class SVGcode:
def __init__(self, svg_file):
'''
Read svg from path 'svg_file' (e.g. 'test/test_vector.svg')
'''
#self.filename, self.extension = svg_file.split('.') # Get filename and extension
#assert self.extension == 'svg', 'File must be an svg'
try:
self.figure_data = ET.parse(svg_file) # Parse svg data as xml
except ET.XMLSyntaxError, e:
'''
Large svgs may trigger lxml's 'excessive depth in document' exception
'''
warnings.warn('lxml error: %s - Trying huge xml parser' %(e.message))
huge_parser = ET.XMLParser(huge_tree = True)
self.figure_data = ET.parse(svg_file, parser = huge_parser)
self.root = self.figure_data.getroot() # Root object in svg
def find_paths(self):
'''
Find and parse nodes in the xml that correspond to paths in the svg
'''
tag_prefix = '{*}'
self.path_nodes = self.root.findall('.//%spath' %(tag_prefix))
self.paths = list()
self.paths = [svg.path.parse_path(p.attrib.get('d', 'M 0,0 z')) for p in self.path_nodes]
def linearize_paths(self, curve_fidelity = 10):
'''
Turn svg paths into discrete lines
Inputs:
curve_fidelity(int) - number of lines with which to approximate curves
in svg. Higher values necessitates longer computation time.
'''
self.linear_coords = [self.linearize(p, curve_fidelity) for p in self.paths]
def linearize_line(self, segment, n_interpolate = None):
'''
Turn svg line into set of coordinates by returning
start and end coordinates of the line segment.
n_interpolate is only used for consistency of use
with linearize_curve()
'''
return numpy.array([segment.start, segment.end])
def linearize_curve(self, segment, n_interpolate = 10):
'''
Estimate svg curve (e.g. Bezier, Arc, etc.) using
a set of n discrete lines. n_interpolate sets the
number of discrete lines per curve.
'''
interpolation_pts = numpy.linspace(0, 1, n_interpolate, endpoint = False)[1:]
interpolated = numpy.zeros(n_interpolate + 1, dtype = complex)
interpolated[0] = segment.start
interpolated[-1] = segment.end
for i, pt in enumerate(interpolation_pts):
interpolated[i + 1] = segment.point(pt)
return interpolated
def complex2coord(self, complexnum):
return (complexnum.real, complexnum.imag)
def linearize(self, path, n_interpolate = 10):
segmenttype2func = {'CubicBezier': self.linearize_curve,
'Line': self.linearize_line,
'QuadraticBezier': self.linearize_curve,
'Arc': self.linearize_curve}
'''
More sophisticated linearization option
compared to endpts2line().
Turn svg path into discrete coordinates
with number of coordinates per curve set
by n_interpolate. i.e. if n_interpolate
is 100, each curve is approximated by
100 discrete lines.
'''
segments = path._segments
complex_coords = list()
for segment in segments:
# Output coordinates for each segment, minus last point (because
# point is same as first point of next segment)
segment_type = type(segment).__name__
segment_linearize = segmenttype2func[segment_type]
linearized = segment_linearize(segment, n_interpolate)
complex_coords.extend(linearized[:-1])
# Append last point of final segment to close the polygon
complex_coords.append(linearized[-1])
return [self.complex2coord(complexnum) for complexnum in complex_coords] # Output list of (x, y) tuples
测试.py from svg_gcode import *
comp_instance = SVGcode("test/test_vector.svg")
comp_instance.find_paths() # Extract path coordinates
comp_instance.linearize_paths(curve_fidelity = 10) # Convert paths into polygons
#comp_instance.write(outputfile = "hrv.svg")
#print(comp_instance.linear_coords[0])
for path in comp_instance.linear_coords:
p = path[0]
print("g0 x%s y%s"%(str(p[0]),str(p[1])))
for p in path:
print("g1 x%s y%s"%(str(p[0]),str(p[1])))
print "( ---------- cut-here ---------- )"
仍然需要一些清理,但 100 LoC 已经不错了。事实上,大部分魔法都是在 svg.path 和 numpy 中完成的。 我们还应该根据段长度设置子段数,比如 |
合作者作者
我无法联系到 SVGCompress 的作者对其进行双重许可,所以我最终从头开始编写自己的 SVG2Gcode 转换器,而且它更简单! |
合作者作者
实施的 |
这看起来很容易集成到 bCNC:
https://github.com/vishpat/svg2gcode