svg2gcode/svg/svg.py

changeset 3
a519e3ac3849
parent 2
660ce16822a9
child 12
a90b8113be25
equal deleted inserted replaced
2:660ce16822a9 3:a519e3ac3849
30 svg_ns = '{http://www.w3.org/2000/svg}' 30 svg_ns = '{http://www.w3.org/2000/svg}'
31 31
32 # Regex commonly used 32 # Regex commonly used
33 number_re = r'[-+]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][-+]?\d+)?' 33 number_re = r'[-+]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][-+]?\d+)?'
34 unit_re = r'em|ex|px|in|cm|mm|pt|pc|%' 34 unit_re = r'em|ex|px|in|cm|mm|pt|pc|%'
35 point_re = r'(?:\d+(?:\.\d*)?|\.\d+),(?:\d+(?:\.\d*)?|\.\d+)'
35 36
36 # Unit converter 37 # Unit converter
37 unit_convert = { 38 unit_convert = {
38 None: 1, # Default unit (same as pixel) 39 None: 1, # Default unit (same as pixel)
39 'px': 1, # px: pixel. Default SVG unit 40 'px': 1, # px: pixel. Default SVG unit
496 for seg in self.segments(precision): 497 for seg in self.segments(precision):
497 ret.append(simplify_segment(seg, precision)) 498 ret.append(simplify_segment(seg, precision))
498 499
499 return ret 500 return ret
500 501
502
503 class Polygon(Transformable):
504 '''SVG <polygon>'''
505 # class Path handles the <polygon> tag
506 tag = 'polygon'
507
508 def __init__(self, elt=None):
509 Transformable.__init__(self, elt)
510 if elt is not None:
511 self.style = elt.get('style')
512 self.parse(elt.get('points'))
513
514 def parse(self, pathstr):
515 """Parse path string and build elements list"""
516
517 pathlst = re.findall(point_re, pathstr)
518
519 #pathlst.reverse()
520
521 current_pt = None
522 start_pt = None
523 while pathlst:
524 coord = pathlst.pop().split(",")
525 pt = Point(coord[0], coord[1])
526
527 if start_pt:
528 current_pt = pt
529 l = Segment(start_pt, current_pt)
530 self.items.append(l)
531 start_pt = current_pt
532 else:
533 start_pt = pt
534 self.items.append(MoveTo(pt))
535
536 def __str__(self):
537 return '\n'.join(str(x) for x in self.items)
538
539 def __repr__(self):
540 return '<Polygon ' + self.id + '>'
541
542 def segments(self, precision=0):
543 '''Return a list of segments, each segment is ended by a MoveTo.
544 A segment is a list of Points'''
545 ret = []
546 # group items separated by MoveTo
547 for moveTo, group in itertools.groupby(self.items,
548 lambda x: isinstance(x, MoveTo)):
549 # Use only non MoveTo item
550 if not moveTo:
551 # Generate segments for each relevant item
552 seg = [x.segments(precision) for x in group]
553 # Merge all segments into one
554 ret.append(list(itertools.chain.from_iterable(seg)))
555
556 return ret
557
558 def simplify(self, precision):
559 '''Simplify segment with precision:
560 Remove any point which are ~aligned'''
561 ret = []
562 for seg in self.segments(precision):
563 ret.append(simplify_segment(seg, precision))
564
565 return ret
566
567
501 class Ellipse(Transformable): 568 class Ellipse(Transformable):
502 '''SVG <ellipse>''' 569 '''SVG <ellipse>'''
503 # class Ellipse handles the <ellipse> tag 570 # class Ellipse handles the <ellipse> tag
504 tag = 'ellipse' 571 tag = 'ellipse'
505 572

mercurial