From a38a160484489ad74ae73f4008db02aba8624d25 Mon Sep 17 00:00:00 2001 From: Mario Voigt Date: Fri, 2 Sep 2022 03:15:14 +0200 Subject: [PATCH] several fixes and more extensions from 1.1 back again --- .../archimedes_spiral/archimedes_spiral.inx | 2 +- .../buxtronix_living_hinges.inx | 68 + .../buxtronix_living_hinges.py | 448 ++++ .../buxtronix_living_hinges/images/about.png | Bin 0 -> 73693 bytes .../images/cross-lattice.png | Bin 0 -> 1878 bytes .../images/diamond-lattice.png | Bin 0 -> 3805 bytes .../images/diamond-lattice.svg | 143 ++ .../images/straight-lattice.png | Bin 0 -> 852 bytes .../images/wavy-lattice.png | Bin 0 -> 2166 bytes .../buxtronix_living_hinges/meta.json | 21 + .../chip_scratches/chip_scratches.inx | 50 + .../chip_scratches/chip_scratches.py | 733 ++++++ .../fablabchemnitz/chip_scratches/meta.json | 21 + .../ellipse_by_five_points.inx | 16 + .../ellipse_by_five_points.py | 230 ++ .../ellipse_by_five_points/meta.json | 21 + .../fablabchemnitz/fun_shapes/fun_shapes.inx | 16 + .../fablabchemnitz/fun_shapes/fun_shapes.py | 199 ++ .../fablabchemnitz/fun_shapes/meta.json | 21 + .../hatches_and_grains/hatches_and_grains.inx | 81 + .../hatches_and_grains/hatches_and_grains.py | 144 ++ .../locale/fr/LC_MESSAGES/hatches_grains.mo | Bin 0 -> 2279 bytes .../locale/fr/hatches_grains.po | 128 + .../locale/hatches_grains.pot | 110 + .../hatches_and_grains/meta.json | 21 + .../ids_to_text/ids_to_text.inx | 50 + .../fablabchemnitz/ids_to_text/ids_to_text.py | 103 + .../fablabchemnitz/ids_to_text/meta.json | 21 + .../ifs_fractals/ifs_fractals.inx | 80 + .../ifs_fractals/ifs_fractals.py | 72 + .../fablabchemnitz/ifs_fractals/meta.json | 21 + .../insert_paper_template.inx | 30 + .../insert_paper_template.py | 96 + .../insert_paper_template/meta.json | 21 + .../fablabchemnitz/join_paths/join_paths.inx | 109 + .../fablabchemnitz/join_paths/join_paths.py | 429 ++++ .../fablabchemnitz/join_paths/meta.json | 21 + .../living_hinge/living_hinge.inx | 37 + .../living_hinge/living_hinge.py | 264 ++ .../fablabchemnitz/living_hinge/meta.json | 22 + .../move_path_node/move_path_node.inx | 2 +- .../normalize_drawing_scale/meta.json | 20 + .../normalize_drawing_scale.inx | 18 + .../normalize_drawing_scale.py | 100 + extensions/fablabchemnitz/ocr/.gitignore | 129 + extensions/fablabchemnitz/ocr/meta.json | 20 + extensions/fablabchemnitz/ocr/ocr.inx | 145 ++ extensions/fablabchemnitz/ocr/ocr.py | 47 + extensions/fablabchemnitz/ocr/read.png | Bin 0 -> 40578 bytes .../fablabchemnitz/offset_paths/meta.json | 20 + .../offset_paths/offset_paths.inx | 80 + .../offset_paths/offset_paths.py | 153 ++ extensions/fablabchemnitz/open_dir/meta.json | 20 + .../fablabchemnitz/open_dir/open_dir.inx | 14 + .../fablabchemnitz/open_dir/open_dir.py | 36 + .../paths_to_lowlevel_strokes/meta.json | 20 + .../paths_to_lowlevel_strokes.inx | 20 + .../paths_to_lowlevel_strokes.py | 118 + .../fablabchemnitz/polygon_side/meta.json | 21 + .../polygon_side/polygon_side.inx | 22 + .../polygon_side/polygon_side.py | 118 + .../fablabchemnitz/sine_and_lace/meta.json | 21 + .../sine_and_lace/sine_and_lace.inx | 47 + .../sine_and_lace/sine_and_lace.py | 332 +++ .../inkscapeMadeEasy/inkscapeMadeEasy_Base.py | 1307 ++++++++++ .../inkscapeMadeEasy/inkscapeMadeEasy_Draw.py | 2231 +++++++++++++++++ .../inkscapeMadeEasy/inkscapeMadeEasy_Plot.py | 1632 ++++++++++++ .../fablabchemnitz/spirograph/meta.json | 21 + .../fablabchemnitz/spirograph/spirograph.inx | 30 + .../fablabchemnitz/spirograph/spirograph.py | 248 ++ .../fablabchemnitz/unwind_paths/meta.json | 20 + .../unwind_paths/unwind_paths.inx | 68 + .../unwind_paths/unwind_paths.py | 272 ++ .../vektorkollektor/vektorkollektor.inx | 2 +- 74 files changed, 11200 insertions(+), 3 deletions(-) create mode 100644 extensions/fablabchemnitz/buxtronix_living_hinges/buxtronix_living_hinges.inx create mode 100755 extensions/fablabchemnitz/buxtronix_living_hinges/buxtronix_living_hinges.py create mode 100644 extensions/fablabchemnitz/buxtronix_living_hinges/images/about.png create mode 100644 extensions/fablabchemnitz/buxtronix_living_hinges/images/cross-lattice.png create mode 100644 extensions/fablabchemnitz/buxtronix_living_hinges/images/diamond-lattice.png create mode 100644 extensions/fablabchemnitz/buxtronix_living_hinges/images/diamond-lattice.svg create mode 100644 extensions/fablabchemnitz/buxtronix_living_hinges/images/straight-lattice.png create mode 100644 extensions/fablabchemnitz/buxtronix_living_hinges/images/wavy-lattice.png create mode 100644 extensions/fablabchemnitz/buxtronix_living_hinges/meta.json create mode 100644 extensions/fablabchemnitz/chip_scratches/chip_scratches.inx create mode 100644 extensions/fablabchemnitz/chip_scratches/chip_scratches.py create mode 100644 extensions/fablabchemnitz/chip_scratches/meta.json create mode 100644 extensions/fablabchemnitz/ellipse_by_five_points/ellipse_by_five_points.inx create mode 100644 extensions/fablabchemnitz/ellipse_by_five_points/ellipse_by_five_points.py create mode 100644 extensions/fablabchemnitz/ellipse_by_five_points/meta.json create mode 100755 extensions/fablabchemnitz/fun_shapes/fun_shapes.inx create mode 100644 extensions/fablabchemnitz/fun_shapes/fun_shapes.py create mode 100644 extensions/fablabchemnitz/fun_shapes/meta.json create mode 100644 extensions/fablabchemnitz/hatches_and_grains/hatches_and_grains.inx create mode 100644 extensions/fablabchemnitz/hatches_and_grains/hatches_and_grains.py create mode 100644 extensions/fablabchemnitz/hatches_and_grains/locale/fr/LC_MESSAGES/hatches_grains.mo create mode 100644 extensions/fablabchemnitz/hatches_and_grains/locale/fr/hatches_grains.po create mode 100644 extensions/fablabchemnitz/hatches_and_grains/locale/hatches_grains.pot create mode 100644 extensions/fablabchemnitz/hatches_and_grains/meta.json create mode 100644 extensions/fablabchemnitz/ids_to_text/ids_to_text.inx create mode 100644 extensions/fablabchemnitz/ids_to_text/ids_to_text.py create mode 100644 extensions/fablabchemnitz/ids_to_text/meta.json create mode 100644 extensions/fablabchemnitz/ifs_fractals/ifs_fractals.inx create mode 100644 extensions/fablabchemnitz/ifs_fractals/ifs_fractals.py create mode 100644 extensions/fablabchemnitz/ifs_fractals/meta.json create mode 100644 extensions/fablabchemnitz/insert_paper_template/insert_paper_template.inx create mode 100644 extensions/fablabchemnitz/insert_paper_template/insert_paper_template.py create mode 100644 extensions/fablabchemnitz/insert_paper_template/meta.json create mode 100644 extensions/fablabchemnitz/join_paths/join_paths.inx create mode 100644 extensions/fablabchemnitz/join_paths/join_paths.py create mode 100644 extensions/fablabchemnitz/join_paths/meta.json create mode 100644 extensions/fablabchemnitz/living_hinge/living_hinge.inx create mode 100644 extensions/fablabchemnitz/living_hinge/living_hinge.py create mode 100644 extensions/fablabchemnitz/living_hinge/meta.json create mode 100644 extensions/fablabchemnitz/normalize_drawing_scale/meta.json create mode 100644 extensions/fablabchemnitz/normalize_drawing_scale/normalize_drawing_scale.inx create mode 100644 extensions/fablabchemnitz/normalize_drawing_scale/normalize_drawing_scale.py create mode 100644 extensions/fablabchemnitz/ocr/.gitignore create mode 100644 extensions/fablabchemnitz/ocr/meta.json create mode 100644 extensions/fablabchemnitz/ocr/ocr.inx create mode 100755 extensions/fablabchemnitz/ocr/ocr.py create mode 100644 extensions/fablabchemnitz/ocr/read.png create mode 100644 extensions/fablabchemnitz/offset_paths/meta.json create mode 100644 extensions/fablabchemnitz/offset_paths/offset_paths.inx create mode 100644 extensions/fablabchemnitz/offset_paths/offset_paths.py create mode 100644 extensions/fablabchemnitz/open_dir/meta.json create mode 100644 extensions/fablabchemnitz/open_dir/open_dir.inx create mode 100644 extensions/fablabchemnitz/open_dir/open_dir.py create mode 100644 extensions/fablabchemnitz/paths_to_lowlevel_strokes/meta.json create mode 100644 extensions/fablabchemnitz/paths_to_lowlevel_strokes/paths_to_lowlevel_strokes.inx create mode 100644 extensions/fablabchemnitz/paths_to_lowlevel_strokes/paths_to_lowlevel_strokes.py create mode 100644 extensions/fablabchemnitz/polygon_side/meta.json create mode 100755 extensions/fablabchemnitz/polygon_side/polygon_side.inx create mode 100644 extensions/fablabchemnitz/polygon_side/polygon_side.py create mode 100644 extensions/fablabchemnitz/sine_and_lace/meta.json create mode 100644 extensions/fablabchemnitz/sine_and_lace/sine_and_lace.inx create mode 100644 extensions/fablabchemnitz/sine_and_lace/sine_and_lace.py create mode 100644 extensions/fablabchemnitz/spirograph/inkscapeMadeEasy/inkscapeMadeEasy_Base.py create mode 100644 extensions/fablabchemnitz/spirograph/inkscapeMadeEasy/inkscapeMadeEasy_Draw.py create mode 100644 extensions/fablabchemnitz/spirograph/inkscapeMadeEasy/inkscapeMadeEasy_Plot.py create mode 100644 extensions/fablabchemnitz/spirograph/meta.json create mode 100644 extensions/fablabchemnitz/spirograph/spirograph.inx create mode 100644 extensions/fablabchemnitz/spirograph/spirograph.py create mode 100644 extensions/fablabchemnitz/unwind_paths/meta.json create mode 100644 extensions/fablabchemnitz/unwind_paths/unwind_paths.inx create mode 100644 extensions/fablabchemnitz/unwind_paths/unwind_paths.py diff --git a/extensions/fablabchemnitz/archimedes_spiral/archimedes_spiral.inx b/extensions/fablabchemnitz/archimedes_spiral/archimedes_spiral.inx index 5c9a594..7ecc55e 100644 --- a/extensions/fablabchemnitz/archimedes_spiral/archimedes_spiral.inx +++ b/extensions/fablabchemnitz/archimedes_spiral/archimedes_spiral.inx @@ -17,7 +17,7 @@ - + diff --git a/extensions/fablabchemnitz/buxtronix_living_hinges/buxtronix_living_hinges.inx b/extensions/fablabchemnitz/buxtronix_living_hinges/buxtronix_living_hinges.inx new file mode 100644 index 0000000..1731336 --- /dev/null +++ b/extensions/fablabchemnitz/buxtronix_living_hinges/buxtronix_living_hinges.inx @@ -0,0 +1,68 @@ + + + Buxtronix Living Hinges + fablabchemnitz.de.buxtronix_living_hinges + + + images/straight-lattice.png + 20 + 2.0 + 0.0 + + + + images/diamond-lattice.png + 20 + 4.0 + 0.5 + + + + images/cross-lattice.png + 20 + 6.0 + + + + images/wavy-lattice.png + 29 + 4.0 + + + + + images/about.png + + + + 100 + 100 + + + + + + + + false + + all + + + + + + + + diff --git a/extensions/fablabchemnitz/buxtronix_living_hinges/buxtronix_living_hinges.py b/extensions/fablabchemnitz/buxtronix_living_hinges/buxtronix_living_hinges.py new file mode 100755 index 0000000..49b70f9 --- /dev/null +++ b/extensions/fablabchemnitz/buxtronix_living_hinges/buxtronix_living_hinges.py @@ -0,0 +1,448 @@ +#!/usr/bin/env python3 + +import inkex +cut_colour = '#ff0000' +engrave_colour = '#0000ff' + +class Generator(object): + """A generic generator, subclassed for each different lattice style.""" + + def __init__(self, x, y, width, height, stroke_width, svg, e_length, p_spacing): + self.x = x + self.y = y + self.width = width + self.height = height + self.stroke_width = stroke_width + self.svg = svg + self.canvas = self.svg.get_current_layer() + self.e_length = e_length + self.e_height = 0 # Provided by sub-classes. + self.p_spacing = p_spacing + self.fixed_commands = "" + + def draw_one(self, x, y): + return "M %f,%f %s" % (x, y, self.fixed_commands) + + def parameter_text(self): + return "length: %.f spacing: %.1f" % ( + self.e_length, + self.p_spacing, + ) + + def draw_swatch(self): + border = self.canvas.add(inkex.PathElement()) + # Curve radius + cr = self.svg.unittouu('10mm') + # Swatch padding + sp = self.svg.unittouu('30mm') + # Handle length + hl = cr/2 + path_command = ( + 'm %f,%f l %f,%f c %f,%f %f,%f %f,%f' + 'l %f,%f c %f,%f %f,%f %f,%f ' + 'l %f,%f c %f,%f %f,%f %f,%f ' + 'l %f,%f c %f,%f %f,%f %f,%f ') % ( + cr, 0, + + self.width - 2*cr, 0, + + hl, 0, + cr, cr-hl, + cr, cr, + + 0, self.height - 2*cr + 1.5*sp, + + 0, cr/2, + 0-cr+hl, cr, + 0-cr, cr, + + 0-self.width + 2*cr, 0, + + 0-hl, 0, + 0-cr, 0-cr+hl, + 0-cr, 0-cr, + + 0, 0-self.height - 1.5*sp + 2*cr, + + 0, 0-hl, + cr-hl, 0-cr, + cr, 0-cr + ) + + style = { + "stroke": cut_colour, + "stroke-width": str(self.stroke_width), + "fill": "none", + } + border.update(**{"style": style, "inkscape:label": "lattice_border", "d": path_command}) + + c = self.canvas.add(inkex.Circle( + style=str(inkex.Style(style)), + cx=str(cr), + cy=str(cr), + r=str(self.svg.unittouu('4mm')))) + + self.y += sp + + text_style = { + 'fill': engrave_colour, + 'font-size': '9px', + 'font-family': 'sans-serif', + 'text-anchor': 'middle', + 'text-align': 'center', + } + text = self.canvas.add( + inkex.TextElement( + style=str(inkex.Style(text_style)), + x=str(self.x + self.width/2), + y=str(self.y - sp/2))) + text.text = "Style: %s" % self.name + + text_style['font-size'] = "3px" + text = self.canvas.add( + inkex.TextElement( + style=str(inkex.Style(text_style)), + x=str(self.x + self.width/2), + y=str(self.y - sp/4))) + text.text = self.parameter_text() + + text = self.canvas.add( + inkex.TextElement( + style=str(inkex.Style(text_style)), + x=str(self.x + self.width/2), + y=str(self.y +self.height + sp/4))) + text.text = "https://github.com/buxtronix/living-hinge" + + def generate(self, swatch): + if swatch: + self.draw_swatch() + # Round width/height to integer number of patterns. + self.e_length = self.width / max(round(self.width / self.e_length), 1.0) + self.e_height = self.height / max(round(self.height / self.e_height), 1.0) + self.prerender() + style = { + "stroke": cut_colour, + "stroke-width": str(self.stroke_width), + "fill": "none", + } + path_command = "" + y = self.y + while y < self.y + self.height: + x = self.x + while x < self.x + self.width: + path_command = "%s %s " % (path_command, self.draw_one(x, y)) + x += self.e_length + y += self.e_height + + link = self.canvas.add(inkex.PathElement()) + link.update(**{"style": style, "inkscape:label": "lattice", "d": path_command}) + link.insert(0, inkex.Desc("%s hinge %s" % (self.name, self.parameter_text()))) + +class StraightLatticeGenerator(Generator): + def __init__(self, *args, **kwargs): + super(StraightLatticeGenerator, self).__init__(*args) + self.link_gap = kwargs['link_gap'] + self.e_height = 2 * self.p_spacing + self.name = "straight" + + def prerender(self): + self.e_height = 2 * self.p_spacing + w = self.e_length + lg = self.link_gap + + if lg < 0.1: + # Single line for 0 height gap. + self.fixed_commands = " m %f,%f h %f m %f,%f h %f m %f,%f h %f" % ( + 0, self.e_height / 2, + w * 2 / 5, + + 0 - w / 5, 0 - self.e_height / 2, + w * 3 / 5, + + 0 - w / 5, self.e_height / 2, + w * 2 / 5, + ) + else: + self.fixed_commands = ( + " m %f,%f h %f v %f h %f" + " m %f,%f h %f v %f h %f v %f" + " m %f,%f h %f v %f h %f " + ) % ( + 0, + self.e_height / 2, + w * 2 / 5, + lg, + 0 - w * 2 / 5, + w / 8, + 0 - lg - self.e_height / 2, + w * 3 / 4, + lg, + 0 - w * 3 / 4, + 0 - lg, + w * 7 / 8, + lg + self.e_height / 2, + 0 - w * 2 / 5, + 0 - lg, + w * 2 / 5, + ) + + def parameter_text(self): + text = super(StraightLatticeGenerator, self).parameter_text() + return "%s element_height: %.1f" % (text, self.link_gap) + + +class DiamondLatticeGenerator(Generator): + def __init__(self, *args, **kwargs): + super(DiamondLatticeGenerator, self).__init__(*args) + self.e_height = self.p_spacing + self.diamond_curve = kwargs['diamond_curve'] + self.name = "diamond" + + def prerender(self): + h = self.e_height + w = self.e_length + # Diamond curve + dc = 0-self.diamond_curve + # Horiz handle length. + hhl = abs(dc * w * 0.2) + # Endpoint horiz handle length + ehhl = hhl if dc > 0 else 0 + # Vert handle length + vhl = abs(dc * h / 8) if dc < 0 else 0 + # Left + self.fixed_commands = " m %f,%f c %f,%f %f,%f %f,%f c %f,%f %f,%f %f,%f " % ( + 0, h / 4, + + hhl, 0, + w * 0.4 - ehhl, h / 4 - vhl, + w * 0.4, h / 4, + + 0 - ehhl, vhl, + 0 - (w * 0.4 - hhl), h / 4, + 0 - w * 0.4, h / 4, + ) + + # Bottom + self.fixed_commands = "%s m %f,%f c %f,%f %f,%f %f,%f s %f,%f %f,%f " % ( + self.fixed_commands, + w * 0.1, h / 4, + + ehhl, 0 - vhl, + w * 0.4 - hhl, 0 - h / 4, + w * 0.4, 0 - h / 4, + + w * 0.4 - ehhl, h / 4 - vhl, + w * 0.4, h / 4, + ) + + # Top + self.fixed_commands = "%s m %f,%f c %f,%f %f,%f %f,%f s %f,%f %f,%f " % ( + self.fixed_commands, + 0 - w * 0.8, 0 - h, + + ehhl, vhl, + w * 0.4 - hhl, h / 4, + w * 0.4, h / 4, + + w * 0.4 - ehhl, 0 - h / 4 + vhl, + w * 0.4, 0 - h / 4, + ) + + # Right + self.fixed_commands = "%s m %f,%f c %f,%f %f,%f %f,%f c %f,%f %f,%f %f,%f " % ( + self.fixed_commands, + w * 0.1, h *0.75, + + 0 - hhl, 0, + (0 - w * 0.4) + ehhl, 0 - h / 4 + vhl, + 0 - w * 0.4, 0 - h / 4, + + ehhl, 0 - vhl, + w * 0.4 - hhl, 0 - h / 4, + w * 0.4, 0 - h / 4, + ) + + def draw_one(self, x, y): + return "M %f,%f %s" % (x, y, self.fixed_commands) + + def parameter_text(self): + text = super(DiamondLatticeGenerator, self).parameter_text() + return "%s curve: %.1f" % (text, self.diamond_curve) + + +class CrossLatticeGenerator(Generator): + def __init__(self, *args): + super(CrossLatticeGenerator, self).__init__(*args) + self.e_height = self.p_spacing + self.name = "cross" + + def prerender(self): + l = self.e_length + h = self.e_height + self.fixed_commands = ( + "m %f,%f l %f,%f l %f,%f m %f,%f l %f,%f" + "m %f,%f l %f,%f l %f,%f l %f,%f " + "m %f,%f l %f,%f l %f,%f l %f,%f " + "m %f,%f l %f,%f l %f,%f m %f,%f l %f,%f" + ) % ( + # Left + 0, h * 0.5, + l * 0.2, 0, + l * 0.2, 0 - h * 0.3, + 0 - l * 0.2, h * 0.3, + l * 0.2, h * 0.3, + # Top + 0 - l * 0.3, 0 - h * 0.5, + l * 0.2, 0 - h * 0.3, + l * 0.4, 0, + l * 0.2, h * 0.3, + # Bottom + 0, h * 0.4, + 0 - l * 0.2, h * 0.3, + 0 - l * 0.4, 0, + 0 - l * 0.2, 0 - h * 0.3, + # Right + l * 0.5, 0 - h * 0.5, + l * 0.2, h * 0.3, + 0 - l * 0.2, h * 0.3, + l * 0.2, 0 - h * 0.3, + l * 0.2, 0, + ) + + +class WavyLatticeGenerator(Generator): + def __init__(self, *args, **kwargs): + super(WavyLatticeGenerator, self).__init__(*args) + self.e_height = self.p_spacing + self.name = "wavy" + + def prerender(self): + h = self.e_height + w = self.e_length + self.fixed_commands = ( + " m %f,%f h %f c %f,%f %f,%f %f,%f h %f " + "m %f,%f h %f c %f,%f %f,%f %f,%f h %f " + ) % ( + 0, h, # Start of element (left) + w * 0.1, # Short horiz line. + + w * 0.1, 0, # Control 1 + w * 3 / 40, 0 - h / 2, # Control 2 + w * 0.2, 0 - h / 2, # Curve top. + + w * 0.175, # Top horiz line. + + 0 - w * 0.1, 0 - h / 2, # Move to higher line. + w * 0.3, # Long higher horiz line. + + w / 5, 0, # Control 1 + w / 10, h, # Control 2 + w * 0.25, h, # Curve down. + + w * 0.075, # End horiz line. + ) + + +class BuxtronixLivingHinges(inkex.EffectExtension): + """ + Extension to create laser cut bend lattices. + """ + + def add_arguments(self, pars): + pars.add_argument("--tab", help="Bend pattern to generate") + pars.add_argument("--unit", help="Units for dimensions") + pars.add_argument("--swatch", type=inkex.Boolean, help="Draw as a swatch card") + + pars.add_argument("--width", type=float, default=300, help="Width of pattern") + pars.add_argument("--height", type=float, default=100, help="Height of pattern") + + pars.add_argument("--sl_length", type=int, default=20, help="Length of links") + pars.add_argument("--sl_gap", type=float, default=0.5, help="Gap between links") + pars.add_argument("--sl_spacing", type=float, default=20, help="Spacing of links") + + pars.add_argument("--dl_curve", type=float, default=0.5, help="Curve of diamonds") + pars.add_argument("--dl_length", type=float, default=24, help="Length of diamonds") + pars.add_argument("--dl_spacing", type=float, default=4, help="Spacing of diamonds") + + pars.add_argument("--cl_length", type=float, default=24, help="Length of combs") + pars.add_argument("--cl_spacing", type=float, default=6, help="Spacing of combs") + + pars.add_argument("--wl_length", type=int, default=20, help="Length of links") + pars.add_argument("--wl_interval", type=int, default=30, help="Interval between links") + pars.add_argument("--wl_spacing", type=float, default=0.5, help="Spacing between links") + + def convert(self, value): + return self.svg.unittouu(str(value) + self.options.unit) + + def convertmm(self, value): + return self.svg.unittouu('%fmm' % value) + + def effect(self): + stroke_width = self.svg.unittouu("0.2mm") + self.options.width = self.convert(self.options.width) + self.options.height = self.convert(self.options.height) + + def draw_one(x, y): + if self.options.tab == "straight_lattice": + generator = StraightLatticeGenerator( + x, + y, + self.options.width, + self.options.height, + stroke_width, + self.svg, + self.convertmm(self.options.sl_length), + self.convertmm(self.options.sl_spacing), + link_gap=self.convertmm(self.options.sl_gap), + ) + elif self.options.tab == "diamond_lattice": + generator = DiamondLatticeGenerator( + x, + y, + self.options.width, + self.options.height, + stroke_width, + self.svg, + self.convertmm(self.options.dl_length), + self.convertmm(self.options.dl_spacing), + diamond_curve=self.options.dl_curve, + ) + elif self.options.tab == "cross_lattice": + generator = CrossLatticeGenerator( + x, + y, + self.options.width, + self.options.height, + stroke_width, + self.svg, + self.convertmm(self.options.cl_length), + self.convertmm(self.options.cl_spacing), + ) + elif self.options.tab == "wavy_lattice": + generator = WavyLatticeGenerator( + x, + y, + self.options.width, + self.options.height, + stroke_width, + self.svg, + self.convertmm(self.options.wl_length), + self.convertmm(self.options.wl_spacing), + ) + else: + inkex.errormsg("Select a valid pattern tab before rendering.") + return + generator.generate(self.options.swatch) + + if self.options.swatch or not self.svg.selected: + draw_one(0, 0) + else: + for elem in self.svg.selected.values(): + bbox = elem.bounding_box() + self.options.width = self.svg.unittouu(bbox.width) + self.options.height = self.svg.unittouu(bbox.height) + x = self.svg.unittouu(bbox.x.minimum) + y = self.svg.unittouu(bbox.y.minimum) + draw_one(x, y) + +BuxtronixLivingHinges().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz/buxtronix_living_hinges/images/about.png b/extensions/fablabchemnitz/buxtronix_living_hinges/images/about.png new file mode 100644 index 0000000000000000000000000000000000000000..b4bfd54ab1d279b90b185384dd4bb46eba2c9764 GIT binary patch literal 73693 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\gW|_QriItTq`?eRkHnB{qqmQ1gHzSo~ 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 literal 0 HcmV?d00001 diff --git a/extensions/fablabchemnitz/buxtronix_living_hinges/images/diamond-lattice.png b/extensions/fablabchemnitz/buxtronix_living_hinges/images/diamond-lattice.png new file mode 100644 index 0000000000000000000000000000000000000000..d03cf75b6862c903293de3eb40c7633129dad1b3 GIT binary patch literal 3805 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 + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/extensions/fablabchemnitz/buxtronix_living_hinges/images/straight-lattice.png b/extensions/fablabchemnitz/buxtronix_living_hinges/images/straight-lattice.png new file mode 100644 index 0000000000000000000000000000000000000000..dd911d59a9862b15ab9d74074942da9e010ca19b GIT binary patch literal 852 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 literal 0 HcmV?d00001 diff --git a/extensions/fablabchemnitz/buxtronix_living_hinges/meta.json b/extensions/fablabchemnitz/buxtronix_living_hinges/meta.json new file mode 100644 index 0000000..3cef86b --- /dev/null +++ b/extensions/fablabchemnitz/buxtronix_living_hinges/meta.json @@ -0,0 +1,21 @@ +[ + { + "name": "Buxtronix Living Hinges", + "id": "fablabchemnitz.de.buxtronix_living_hinges", + "path": "buxtronix_living_hinges", + "dependent_extensions": null, + "original_name": "Living Hinges", + "original_id": "net.buxtronix.living_hinge", + "license": "GNU GPL v3", + "license_url": "https://github.com/buxtronix/living-hinge/blob/master/LICENSE", + "comment": "", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/buxtronix_living_hinges", + "fork_url": "https://github.com/buxtronix/living-hinge", + "documentation_url": "https://stadtfabrikanten.org/display/IFM/Buxtronix+Living+Hinges", + "inkscape_gallery_url": null, + "main_authors": [ + "github.com/buxtronix", + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/chip_scratches/chip_scratches.inx b/extensions/fablabchemnitz/chip_scratches/chip_scratches.inx new file mode 100644 index 0000000..566a3de --- /dev/null +++ b/extensions/fablabchemnitz/chip_scratches/chip_scratches.inx @@ -0,0 +1,50 @@ + + + Chip Scratches + fablabchemnitz.de.chip_scratches + + + + true + 1000 + 1000 + 1.0 + 200 + + + true + 2.0 + 0.0 + 0.2 + false + 90. + 0.0 + false + + + true + 1.0 + 0.0 + 1.0 + false + + + true + 1.0 + 0.0 + 10.0 + false + + + + all + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/chip_scratches/chip_scratches.py b/extensions/fablabchemnitz/chip_scratches/chip_scratches.py new file mode 100644 index 0000000..3b3a446 --- /dev/null +++ b/extensions/fablabchemnitz/chip_scratches/chip_scratches.py @@ -0,0 +1,733 @@ +#!/usr/bin/env python3 + +import math +import inkex +import random +from lxml import etree + +""" +This extension creates visual noise of various kinds, using +3 ingredients, scratches, chips, and specks. + +Extensions -> Generate -> Noise -> ChipScratches + +The 3 ingredients go into 3 Inkscape groups. Where they are in +the tree is controlled by the object selected at the time the +extension is called. They become sisters of the selected object, +under the same parent. If there is no selection, they go to +the root level. + +In the text below, each * indicates a settable parameter in +the pop-up box. + +The extension fills a rectangle, which defaults* to the page +size, or is width* by height*. The overall size* and number* +of marks is set. However, for each of the 3, a multiplier +changes the size* and number*. To get the overall value, +just set the multiplier to 1.0 + +Also, each of the 3 may be separately enabled* or disabled. + +For each ingredient, it is possible to set the size to grow* +with y. For this case, it is possible to set the size to +a negative multiplier, so that it, when growing, will pass +through zero somewhere in the middle of the box. + +For scratches, it is possible to change their orientation +from vertical to angular*, radiating from the center of the box. +(If so, growth is measured from the center.) The initial +angle* and the change with distance* are set. + +For chips and specks, there are similar controls, except the +angular ones, which are omitted. + +Last, there is the option to use a density gradient*. In the +simple case, the probability of making a mark is the same +everywhere. With a gradient, it changes from 0 to 1 across +the box from left to right. + +-- + +Some of the features above may be of little use, while some +omitted ones might be important. This is a beta version, so +I await user feedback. + +I notice that the extension might take 5 seconds to run. Is +this important? A bit of clean-up might help this. + +Two features that might slow it down considerably are clusters +and collisions. Collisions, if implemented, would keep any 2 +marks from landing on top of each other. Slow, because each +mark must search all the previous marks. + +Clusters is some method of putting new marks near old ones. +I think this would be especially useful for specks, which +could be clustered around the end of scratches. Right now, +they're uniform, and so fade into the background. + +Again, feedback? + +Technical note: This file may also be used to generate the inx +file. (The bundled inx file was generated this way.) Set the +global /inxGen/ =1 and run the file stand-alone. + +- AK Sept 2018 +""" + +class ChipScratches(inkex.EffectExtension): + """ +Creates visual noise. 3 kinds: Scratches, chips, specks. +50, 100, 100 instances are predefined. These are chosen +randomly and scattered randomly across the page. Controls +for number and size, as well as some specific to each type. + """ + def add_arguments(self, pars): + pars.add_argument("--pgsizep", type=inkex.Boolean, default=True, help="Default rectangle to page size?") + pars.add_argument("--rx", type=int, default=1000, help="Width") + pars.add_argument("--ry", type=int, default=1000, help="Height") + pars.add_argument("--mainSize", type= float, default=1.0, help="Size of objects") + pars.add_argument("--mainNum", type=int, default=200, help="Number of objects") + pars.add_argument("--honp", type=inkex.Boolean, help="Enable scratches") + pars.add_argument("--hsize", type=float, default=2.0, help="Size of scratches") + pars.add_argument("--hgrow", type=float, default=0.0, help="Grow scratches with distance") + pars.add_argument("--hnum", type= float, default=0.2, help="Number of scratches") + pars.add_argument("--hrad", type=inkex.Boolean, default=False, help="Angle scratches toward center") + pars.add_argument("--hang", type= float, default=90.0, help="Angle from radius") + pars.add_argument("--hcurve", type= float, default=0.0, help="Change angle with distance") + pars.add_argument("--hgrad", type=inkex.Boolean, default=False, help="Use density gradient") + pars.add_argument("--conp", type=inkex.Boolean, default=True, help="Enable chips") + pars.add_argument("--csize", type= float, default=1.0, help="Size of chips") + pars.add_argument("--cgrow", type= float, default=0.0, help="Grow chips with distance") + pars.add_argument("--cnum", type= float, default=1.0, help="Number of chips") + pars.add_argument("--cgrad", type=inkex.Boolean, default=False, help="Use density gradient") + pars.add_argument("--sonp", type=inkex.Boolean, default=True, help="Enable specks") + pars.add_argument("--ssize", type= float, default=1.0, help="Size of specks") + pars.add_argument("--sgrow", type= float, default=0.0, help="Grow specks with distance") + pars.add_argument("--snum", type= float, default=10.0, help="Number of specks") + pars.add_argument("--sgrad", type=inkex.Boolean, default=False, help="Use density gradient") + pars.add_argument("--Nmain", "--Overall") + + def effect(self): + # Get access to main SVG document element and get its dimensions. + if self.options.pgsizep: + rx = self.svg.unittouu(self.svg.get('width')) + ry = self.svg.unittouu(self.svg.attrib['height']) + else: + rx = self.options.rx + ry = self.options.ry + parent = self.document.getroot() + +#Create scratches + + pdic = { + 'rx' : rx, + 'ry' : ry, + 'size' : self.options.mainSize * self.options.hsize, + 'enable' : self.options.honp, + 'num' : int( self.options.mainNum * self.options.hnum ), + 'grow' : self.options.hgrow, + 'radial' : self.options.hrad, + 'ang' : self.options.hang, + 'curve' : self.options.hcurve, + 'grad' : self.options.hgrad, + } + draw( scratches, parent, pdic) + +#Create chips + + + pdic = { + 'rx' : rx, + 'ry' : ry, + 'size' : self.options.mainSize * self.options.csize, + 'enable' : self.options.conp, + 'num' : int( self.options.mainNum * self.options.cnum ), + 'grow' : self.options.cgrow, + 'radial' : False, + 'ang' : False, + 'curve' : False, + 'grad' : self.options.cgrad, + } + draw( chips, parent, pdic) + +#Create specks + + + pdic = { + 'rx' : rx, + 'ry' : ry, + 'size' : self.options.mainSize * self.options.ssize, + 'enable' : self.options.sonp, + 'num' : int( self.options.mainNum * self.options.snum ), + 'grow' : self.options.sgrow, + 'radial' : False, + 'ang' : False, + 'curve' : False, + 'grad' : self.options.sgrad, + } + draw( specks, parent, pdic) + +def draw( obj, parent, pdic) : + if not pdic['enable'] : + return + + group = etree.SubElement(parent, 'g') + + if pdic['grad'] : + f = lambda x: math.sqrt(x) + else : + f = lambda x: x + + rx = pdic['rx'] + ry = pdic['ry'] + fmstyle = str(inkex.Style({"fill" : "#000000"})) + mrx = rx // 2 + mry = ry // 2 + mrmax = mrx if mrx > mry else mry + #Curves 90 going from the center to the edge (long dim.) if parm = 1.0 + curve = pdic['curve'] * 0.5 * math.pi / mrmax + + ctrs = [(rx * f(random.random()) , ry * random.random()) + for i in range(pdic['num'])] + zp = 2 + 3 * int(random.random()*len(obj) / 3 ) + for ctr in ctrs : + path = etree.Element(inkex.addNS('path','svg')) + path.set('style', fmstyle) + zp = (zp + 3) % len(obj) + path.set('d', obj[zp]) + trstring = "translate (%g %g)" % ctr + if pdic['radial'] : + ang = math.atan2(ctr[1]-mry , ctr[0]-mrx) + curve * math.sqrt( + (ctr[1]-mry)**2 + (ctr[0]-mrx)**2) + trstring += " rotate (%g)" % (ang * 180 / math.pi + pdic['ang']) + if pdic['size'] != 1.0 or pdic['grow'] != 0.0 : + if pdic['radial'] : + size = math.sqrt((ctr[1]-mry)**2 + (ctr[0]-mrx)**2) * ( + pdic['grow'] / mrmax ) + pdic['size'] + else : + size = ctr[1] * pdic['grow'] / mrmax + pdic['size'] + trstring += " scale (%g)" % size + path.set('transform', trstring) + group.append(path) + + +chips=( +4.17065, 3.83403, +"M -2.98542 -3.8338 c 0.34234,0 0.74533,0.14835 0.89583,0.32966 0.15043,0.18131 0.19014,0.32965 0.088,0.32965 -0.10212,0 0.0341,0.15422 0.30304,0.34254 0.26887,0.18832 0.56984,0.29206 0.66874,0.23093 0.0989,-0.0612 0.44473,-0.1589 0.76833,-0.21763 0.48389,-0.0877 0.6122,-0.0113 0.72327,0.43138 0.0745,0.29608 0.0843,0.73458 0.0215,0.97438 -0.0648,0.24806 -0.005,0.43833 0.13992,0.44082 0.13978,0.003 0.49312,0.18902 0.7855,0.41379 0.40627,0.31226 0.68285,0.3654 1.1727,0.22492 0.66407,-0.19047 1.37707,0.0827 1.57744,0.60479 0.14702,0.38319 -1.10951,0.94947 -2.1067,0.94947 -0.77639,0 -0.84516,0.0496 -0.84516,0.60652 0,0.36844 -0.17253,0.71404 -0.43955,0.88079 -0.24174,0.15096 -0.43953,0.47139 -0.43953,0.71211 0,0.56109 -0.49051,0.55224 -1.73627,-0.0314 -0.53191,-0.24917 -0.87804,-0.51738 -0.7692,-0.59622 0.10884,-0.0788 0.21711,-0.44315 0.24037,-0.80954 0.0361,-0.56828 -0.10116,-0.75694 -0.93402,-1.28385 -0.53699,-0.33972 -0.97558,-0.78166 -0.97308,-0.98208 0.003,-0.31564 0.0318,-0.32027 0.21635,-0.0349 0.14197,0.21974 0.21384,0.23816 0.21631,0.0549 0.003,-0.15109 -0.19671,-0.47488 -0.44125,-0.7194 -0.31961,-0.31961 -0.38937,-0.55126 -0.24852,-0.82414 0.10773,-0.20875 0.26287,-0.75031 0.34467,-1.20358 0.13057,-0.72333 0.22505,-0.82414 0.77135,-0.82414 z", +4.13855, 4.24985, +"M -1.85248 -4.24978 c 0.27589,0.003 0.47037,0.0646 0.48312,0.20271 0.0137,0.1478 0.0399,0.47805 0.0582,0.73402 0.026,0.36225 0.21413,0.47395 0.84811,0.50359 0.44794,0.0209 0.94806,0.0473 1.11126,0.0582 0.16314,0.011 0.39599,0.28179 0.51767,0.601744 0.12163,0.31997 0.37346,0.58176 0.55949,0.58176 0.18595,0 0.48549,0.14734 0.66583,0.3277 0.18035,0.18035 0.57257,0.36361 0.87127,0.40723 0.35897,0.0524 0.62021,0.31158 0.77039,0.76447 0.20387,0.61474 0.15184,0.74842 -0.50541,1.29714 -0.40292,0.33638 -0.73264,0.79074 -0.73264,1.0099 0,0.21915 -0.16606,0.65189 -0.36907,0.96172 -0.20296,0.30985 -0.30165,0.67266 -0.21907,0.80628 0.0894,0.1446 -0.091,0.24316 -0.44539,0.24316 -0.32756,0 -0.5954,-0.0917 -0.5954,-0.20362 0,-0.11191 0.15163,-0.63243 0.33677,-1.15715 0.18525,-0.52472 0.2637,-0.99731 0.17453,-1.04989 -0.0892,-0.0526 -0.63351,-0.17283 -1.20942,-0.26725 -0.57596,-0.0944 -1.10945,-0.26987 -1.18578,-0.38997 -0.0763,-0.12012 -0.53312,-0.25519 -1.01492,-0.29996 -1.10287,-0.10248 -1.29329,-0.29762 -1.33349,-1.3685 -0.0191,-0.50625 -0.13647,-0.82688 -0.28496,-0.77674 -0.76171,0.25701 -1.09657,-1.581564 -0.42769,-2.348844 0.31962,-0.36665 1.3196,-0.64382 1.92663,-0.63767 z", +4.22195, 4.21947, +"M 1.69537 -4.21932 c -0.0345,-8.8e-4 -0.0688,0.002 -0.1027,0.008 -0.18069,0.0328 -0.35094,0.1712 -0.50284,0.46983 -0.0104,1.09687 -0.6782,2.01812 -0.47774,3.15318 0.24531,0.74578 -0.54886,0.45228 -0.99871,0.50283 -1.3297,0.0104 -0.14408,-1.07574 -1.55709,-0.976 -0.42439,-0.67608 -0.98245,-2.34963 -1.81896,-0.91876 -0.17688,0.51739 -0.9194,1.1638 -0.0326,1.53546 0.37737,0.014 0.60982,0.25307 0.77516,0.58044 -0.0269,0.19027 -0.0344,0.50819 -0.0112,0.88577 0.0503,0.81728 -0.0383,1.14531 -0.37549,1.39186 -0.48057,0.35139 -0.36025,0.73074 0.3532,1.11256 0.18114,0.0969 0.28904,0.14046 0.33832,0.12594 0.0493,-0.0146 0.0402,-0.0871 -0.0116,-0.22214 -0.0798,-0.20803 0.0612,-0.40175 0.36204,-0.49725 0.33273,-0.1056 0.47599,-0.33503 0.4903,-0.78121 0.13921,-0.0295 0.30389,-0.11064 0.50376,-0.26119 1.46647,-0.57469 1.19941,1.53559 2.36963,1.92306 0.98055,1.45246 1.30915,-1.39831 1.46716,-2.1424 0.10424,-1.37891 -0.4829,-1.40293 0.43107,-1.92205 0.91202,0.23598 1.36087,-0.55942 1.32261,-1.38814 -0.0299,-0.64451 -0.35397,-1.30896 -0.98476,-1.52384 -0.44029,-0.27942 -1.02203,-1.0427 -1.53965,-1.05586 z", +2.29614, 3.86905, +"M -0.15038 -3.86873 c -0.32838,-0.009 -0.63053,0.17109 -0.7121,0.59531 -0.44133,-0.069 -1.15128,-1.08751 -1.3529,-0.1297 0.0799,0.51796 -0.18084,1.09953 -0.0362,1.560632 0.0859,0.54933 0.0879,1.28864 0.86402,1.13739 0.41931,0.12913 0.19391,1.48787 0.86352,1.32705 -0.27268,0.12418 -0.56414,0.20057 -0.90951,0.15607 -0.33358,0.0733 -0.0995,0.50263 0.10232,0.59686 0.69781,0.49054 1.25008,-1.24221 1.59784,0.0651 -0.10673,0.74125 -1.42009,1.11534 -1.22938,1.91513 0.45471,0.77949 1.52934,0.52133 2.19882,0.20722 0.426,-0.25368 0.96231,-0.36258 0.60153,-1.01906 -0.16613,-0.63544 -0.25215,-1.31953 -0.28578,-1.93476 0.19172,-0.28339 0.73189,-0.81591 0.74414,-1.18391 0.004,-0.12267 -0.0506,-0.22674 -0.19637,-0.29765 -0.12346,0.2062 -0.2481,0.38506 -0.39325,0.52399 -0.0738,-0.30337 -0.26755,-0.59016 -0.57981,-0.70486 -0.97504,-0.90992 0.71916,-1.624862 1.05005,-2.274802 v -5.1e-4 c -0.35914,-0.76136 -1.12554,0.174 -1.4578,-0.003 -0.18611,-0.32959 -0.54083,-0.52743 -0.86918,-0.5364 z", +3.31745, 5.20184, +"M -3.04057 -3.12517 c -0.12013,0.49557 0.22954,0.992902 -0.0125,1.481942 -0.3042,0.4355 -0.16661,0.96485 -0.24617,1.47138 -0.13051,0.54661 0.48075,0.72787 0.5505,1.18424 0.34005,0.28842 -0.34128,0.56491 -0.0684,0.64532 -0.0254,0.006 -0.0507,0.009 -0.076,0.0172 -0.12397,0.005 -0.0329,0.12902 0.0254,0.13283 0.0916,0.0214 0.17487,0.0566 0.25509,0.0975 -0.0618,0.0963 -0.13661,0.20956 -0.0942,0.3182 -0.0579,0.17996 -0.64502,0.46539 -0.41368,0.58716 0.27677,0.0877 0.30423,0.26778 0.27821,0.46656 -0.10304,0.0342 -0.16783,0.13651 -0.0334,0.1966 -0.0441,0.20892 -0.0836,0.41478 0.0836,0.54124 0.26204,0.0239 0.56304,-0.0127 0.85778,-0.0113 0.15595,0.053 0.3112,0.10898 0.45235,0.19132 0.44943,0.28858 0.77251,0.76143 1.30321,0.92948 0.251,0.13085 0.47062,0.0872 0.47613,-0.0674 0.003,-0.0703 -0.0394,-0.1635 -0.14241,-0.2736 -0.32012,-0.35787 -0.80262,-0.50472 -1.20241,-0.70974 0.26829,0.001 0.53112,0.2429 0.72923,-0.0975 -0.0774,-0.49202 -0.79569,-0.59976 -1.12805,-0.94766 -0.38855,-0.23155 -1.03547,-0.33263 -0.82509,-0.89511 0.19784,0.16083 0.38233,0.34262 0.59643,0.46985 0.2225,0.39004 0.96906,0.0149 1.31442,0.31886 0.30953,-0.35321 0.59538,0.79256 0.80227,0.11169 0.0337,-0.0757 0.0554,-0.16401 0.0621,-0.24848 v 0 c 0.0205,-0.25339 -0.0915,-0.47343 -0.40312,-0.22337 -0.19188,0.0244 -0.12003,-0.54699 -0.50655,-0.40708 -0.4008,-0.0492 -0.88145,0.32259 -1.01738,-0.24187 -0.22216,-0.0951 -0.4652,-0.19534 -0.71735,-0.25079 0.0546,-0.37763 0.0308,-0.78884 0.12161,-1.10494 -0.53717,-0.3656 -0.0495,-0.98532 -0.21974,-1.39571 -0.0611,-0.41652 0.91697,0.0243 0.77055,0.42327 0.0859,0.35784 0.84999,1.14566 0.90668,0.36743 0.24362,-0.49009 -0.0688,-1.08376 -0.55477,-1.27742 -0.23421,-0.13565 -0.50438,-0.44811 -0.0324,-0.37734 0.54993,-0.25032 0.8983,0.51127 1.39901,0.21378 0.31014,0.12139 0.34301,0.5908 0.78477,0.50158 0.32429,0.42527 0.37542,0.96608 0.52008,1.43504 -0.0457,0.40839 0.12259,0.77239 0.32746,1.1089 -0.0386,0.0876 -0.0483,0.19899 -0.0139,0.33208 -0.033,0.23478 0.0471,0.26766 0.266,0.26566 0.0265,0.0178 0.0539,0.0311 0.0816,0.0423 0.0757,0.35193 0.0297,0.752 0.33572,0.99755 0.38603,0.3712 0.90219,0.0857 0.7319,-0.43054 -0.0466,-0.30798 -0.29681,-0.49153 -0.49234,-0.70745 0.0877,-0.0846 0.14598,-0.18839 0.14571,-0.28813 0,-0.12995 -0.0965,-0.25111 -0.34364,-0.30729 -0.0113,-0.01 -0.0233,-0.0175 -0.035,-0.0261 0,-0.008 0,-0.0144 0.002,-0.0221 -0.0783,-0.58378 -0.29364,-1.04867 -0.57824,-1.54836 -0.003,-0.54764 -0.26269,-1.00095 -0.42559,-1.5107 -0.16414,-0.40027 -0.18097,-0.931632 -0.68992,-1.070242 -0.35382,-0.0791 -0.24553,0.52958 -0.32482,0.740812 -0.19094,0.0194 -0.35815,-0.327932 -0.61756,-0.303992 -0.0498,-0.45204 -0.10633,-0.96193 -0.59179,-1.08313 -0.21979,-0.35661 -0.7287,-0.40785 -0.73915,-0.88256 -1.36004,-2.36534 -1.95836,0.29957 -1.63423,1.12013 z", +2.98467, 4.66325, +"M 0.614136 -2.29735 c -0.0974,-0.40618 -0.7125,-0.83436 -0.90598,-1.29221 -0.16432,-0.38885 0.094,-0.83201 -0.0209,-0.95324 -0.29875,-0.3152 -0.35677,0.40541 -0.62004,0.28161 -0.5706,-0.2683 -0.96784,-0.4991 -1.56386,-0.36057 -0.0124,0.2114 0.004,0.42436 -0.0171,0.63525 -0.31209,0.73101 0.0309,1.55931 -0.31858,2.0946 0.0848,0.12448 0.14997,0.25099 0.20148,0.37838 0.0156,0.21967 0.0503,0.44298 0.0725,0.67113 0.0238,0.0613 0.0395,0.12615 0.0585,0.18949 0.50136,1.84607 -0.0172,1.42527 -0.43442,1.35738 -0.24015,0.81789 0.45195,1.85386 0.52381,2.81106 0.18281,2.0407 0.89697,0.86601 2.0265,0.22853 10e-4,-0.91029 -0.0244,-0.95992 0.52581,-1.46817 0.74242,-0.0378 1.71531,-0.0436 1.76344,-0.97207 0.0521,-0.0462 0.0914,-0.0908 0.12716,-0.13473 0.0493,0.0552 0.15625,0.0926 0.36013,0.10319 0.40274,0.0431 0.56401,-0.18544 0.58867,-0.47407 0.0542,-0.63499 -0.55312,-1.55926 -0.70765,-0.51248 0.0324,0.14484 -0.0426,0.29511 -0.1234,0.43883 -0.16329,-0.54242 -1.37396,-0.96101 -1.47446,-1.59914 -0.1211,-0.0939 -0.22103,-0.19865 -0.29781,-0.30976 0.11513,-0.10721 0.23173,-0.21303 0.34755,-0.31918 0.004,-0.24309 -0.0645,-0.52303 -0.11148,-0.7939 z", +2.04389, 5.29494, +"M -1.85309 -5.04915 c 0.23783,0.26043 0.21099,0.66518 0.22712,1.04875 -0.4069,0.38004 0.1825,0.8748 0.0781,1.30474 -0.0389,1.015465 -0.55187,0.49378 -0.49101,1.508525 0.13462,0.44679 0.16841,0.72546 0.81526,1.43512 0.29219,0.0781 -0.22258,1.36221 -0.28588,2.05254 -0.0792,0.86353 0.71412,1.04806 0.51067,1.67394 l 1.06331,1.32048 c -0.0314,-0.1812 -0.0448,-0.35515 0.0627,-0.47402 0.28009,0.15408 0.64109,0.57435 0.77582,0.0169 0.14718,-0.48429 0.42232,-0.0327 0.35542,0.2494 0.26229,0.10277 0.4328,-0.33043 0.71684,-0.13395 0.23715,-0.46565 -0.19546,-0.38058 -0.45959,-0.49191 -0.009,-0.3719 0.26324,-0.82167 -0.25285,-0.92357 -0.0662,-0.19471 0.006,-0.46625 -0.0348,-0.68452 -0.17436,-0.24732 -0.63358,-0.4809 -0.23403,-0.8166 0.25025,-0.42226 -0.85867,-0.85207 -0.48249,-1.2856 0.22844,0.18931 0.44217,0.179 0.35732,-0.17819 -0.13207,-0.6247 0.35102,-0.79202 -0.0534,-1.09863 -0.38584,-0.3369 -0.93599,-0.41779 -1.28967,-0.79966 -0.019,-0.23696 -0.17121,-0.4219 -0.2883,-0.61236 0.0439,-0.11202 0.10964,-0.220495 0.20235,-0.323135 0.29428,-0.26016 0.28836,-0.24769 0.10101,-0.59292 0.21808,-0.22172 -0.30092,-0.49114 -0.22305,-0.80405 -0.27966,-0.40328 -0.31858,-0.96801 -0.26602,-1.46128 0.16807,-0.43289 -0.90489,0.07 -0.90489,0.07 z", +5.1605, 3.51819, +"M 0.197111 -3.51809 c -0.25831,-0.008 -0.64247,0.48592 -1.65703,1.8944 -0.30917,0.4292 -1.11412,0.75117 -2.18011,0.87133 -1.27846,0.1441 -1.64072,0.31871 -1.48755,0.71783 0.11143,0.29022 0.20229,0.59651 0.20229,0.68056 0,0.084 0.36946,0.14096 0.82122,0.12688 0.7781,-0.0243 0.78325,-0.0409 0.0914,-0.31499 -0.4578,-0.18138 0.0596,-0.25533 1.38729,-0.19875 1.16464,0.0496 2.21889,0.19137 2.34248,0.31499 0.12366,0.12358 -0.0554,0.22449 -0.39706,0.22449 -0.50809,0 -0.54984,0.1332 -0.23026,0.73025 0.17922,0.33488 0.49805,0.6159 0.76974,0.70096 0.0157,0.0639 0.0352,0.12709 0.063,0.18811 0,0.0641 0.1163,0.0991 0.11048,0.1646 0.28267,0.39771 0.73888,1.40678 1.24267,0.67834 0.003,-0.26195 -0.48278,-1.34025 0.0102,-1.11978 0.13677,0.65215 0.88947,0.55265 1.32385,0.40816 0.52365,0.38992 1.46911,0.38685 1.70496,-0.35447 0.0158,-0.0853 0.0252,-0.17953 0.0359,-0.27196 0.0967,0.31684 0.14402,0.24344 0.17214,-0.30257 0.007,-0.13895 2.7e-4,-0.25575 -0.0191,-0.35714 0.0953,-0.19421 0.25677,-0.34478 0.56255,-0.38997 0.0741,-0.0998 0.10036,-0.18124 0.0932,-0.24534 -0.0312,-0.27771 -0.69621,-0.22987 -0.87843,0.0617 -0.18949,0.0256 -0.34877,-0.047 -0.49421,-0.15972 0.68347,-0.14164 0.77742,-0.40214 0.7724,-2.03813 -0.004,-1.25111 -0.11592,-1.71698 -0.33141,-1.37666 -0.17911,0.28293 -0.24087,0.73482 -0.13754,1.00399 0.10335,0.26916 0.005,0.48979 -0.21607,0.48979 -0.22226,0 -0.41684,-0.20557 -0.43256,-0.45651 -0.023,-0.36431 -0.0665,-0.3644 -0.21338,-4.5e-4 -0.14313,0.35465 -0.34793,0.34082 -0.92502,-0.0634 -0.40789,-0.28557 -0.99692,-0.42235 -1.30788,-0.30302 -0.31722,0.12184 -0.46945,0.062 -0.34693,-0.1362 0.1201,-0.19428 0.0622,-0.59178 -0.12911,-0.88331 -0.11326,-0.17268 -0.20468,-0.27964 -0.3221,-0.28394 z m -0.32296,4.90546 c -0.003,0.0156 -0.004,0.031 -0.007,0.0466 -0.0389,-0.0151 -0.0395,-0.0307 0.007,-0.0466 z", +3.88374, 3.51074, +"M 0.152516 -3.50963 c -0.0671,-0.0035 -0.13954,0.0012 -0.21726,0.01501 0.0239,0.38383 -0.009,0.664347 -0.0834,0.870756 -0.5491,-0.372894 -1.21382,-0.623817 -1.99453,-0.680445 0.004,0.330283 0.0274,0.672343 0.0583,1.019123 -0.60216,-0.112963 -1.22906,-0.191918 -1.71237,0.117895 l -0.087,0.185898 c 1.00994,1.039798 2.17682,1.967379 2.19764,3.587233 0.17881,0.262722 0.36799,0.463849 0.56477,0.61642 0.13818,0.425596 0.28373,0.847187 0.44201,1.256679 1.15883,0.174004 1.9076,-0.383239 2.23915,-1.246964 0.44076,-0.188455 0.8768,-0.414276 1.29111,-0.606262 0.84054,-0.06761 1.08622,-0.328197 1.02353,-0.67868 -0.11969,-0.669085 -1.36303,-1.666368 -1.734,-2.275359 -0.58197,-0.72387 -0.79212,-0.277084 -0.95819,0.185455 -0.11392,-0.207857 -0.24645,-0.407202 -0.39388,-0.596988 0.20718,-0.755268 0.0844,-1.73265 -0.63582,-1.769775 z", +3.17107, 3.48989, +"M -0.695755 -3.48975 c -0.14458,-0.002 -0.31898,0.0184 -0.53872,0.0514 -0.48796,0.0735 -0.9685,0.32099 -1.33449,0.68684 -0.48142,0.48132 -0.57636,0.733 -0.59963,1.58863 -0.0182,0.66578 0.0642,1.0927 0.23826,1.23725 0.14629,0.12144 0.26581,0.37135 0.26581,0.5554 0,0.44729 0.44932,0.79765 0.83375,0.65015 0.1706,-0.0654 0.31045,-0.035 0.31045,0.0672 0,0.10242 0.35026,0.62619 0.77866,1.16423 0.44864,0.56348 0.93335,0.97854 1.14294,0.97854 0.35308,0 1.38754,-1.22023 1.59865,-1.8853 0.056,-0.17641 0.36274,-0.47456 0.68184,-0.66306 0.45927,-0.27126 0.55359,-0.42928 0.45275,-0.75654 -0.23387,-0.759 -0.79899,-1.36205 -1.72673,-1.84317 -0.54539,-0.28283 -1.03708,-0.70924 -1.20888,-1.04864 -0.29712,-0.58699 -0.46072,-0.77923 -0.89466,-0.78284 z", +4.76911, 3.80814, +"M 1.68749 -3.80769 c -0.0899,-0.004 -0.20175,0.019 -0.3478,0.0548 -0.2754,0.068 -0.80502,0.1779 -1.295,0.27337 -0.002,-5.7e-4 -0.003,-0.003 -0.005,-0.004 v 5.1e-4 c -0.0214,-0.004 -0.0479,0.004 -0.0775,0.0196 -0.0805,0.0155 -0.16738,0.0341 -0.24289,0.0481 -0.55451,0.10268 -1.25868,0.42197 -1.56475,0.70952 l -0.55708,0.52297 -0.1452,-0.57826 c -0.22357,-0.89072 -0.83344,-0.9771 -1.61438,-0.22893 -1.22476,1.1734 -0.44024,2.73403 0.96946,1.92856 0.38743,-0.22135 0.94538,-0.33453 1.30844,-0.2651 0.50575,0.0967 0.65979,0.0172 0.7674,-0.39377 0.0749,-0.28637 0.25625,-0.4356 0.4563,-0.46716 0.007,0.37514 0.15968,0.7233 0.44339,0.89866 0.15237,0.0942 0.1253,0.23529 -0.091,0.47439 -0.32686,0.36118 -0.77208,1.06994 -1.10431,1.69498 -0.72099,0.39409 -1.14366,1.04266 -0.95602,1.53169 0.0709,0.18476 0.27588,0.33538 0.45527,0.33538 0.35557,0 1.2275,-0.60376 1.86139,-1.20819 0.12891,0.3163 0.20815,0.7041 0.18085,1.048 -0.0504,0.63594 -0.005,0.73571 0.32609,0.71675 0.21154,-0.012 0.52486,-0.0817 0.69607,-0.15503 0.21968,-0.0938 0.34301,-0.0121 0.4191,0.27905 0.17931,0.68569 0.76809,0.39235 0.94774,-0.47232 0.086,-0.41422 0.22873,-0.84663 0.31782,-0.96067 0.089,-0.11402 0.22021,-0.45146 0.29146,-0.7493 0.0898,-0.37587 0.33261,-0.6263 0.79272,-0.81856 0.42373,-0.17705 0.70601,-0.44922 0.7829,-0.75551 0.19283,-0.76824 -0.0249,-1.0573 -0.79841,-1.0573 -0.39962,0 -0.93906,-0.17198 -1.26298,-0.40256 -0.12655,-0.0901 -0.23128,-0.15678 -0.32761,-0.20515 -0.0225,-0.18343 -0.0534,-0.37777 -0.0956,-0.58808 -0.19008,-0.94639 -0.26088,-1.21336 -0.5307,-1.2268 z", +2.54464, 4.86321, +"M 2.11268 -4.86312 -2.4e-4,3.4e-4 c -0.42259,-0.005 -0.71865,0.16899 -1.01028,0.58895 -0.2341,0.33711 -0.33434,0.40738 -0.61019,0.42851 -0.19518,0.0149 -0.37421,0.089 -0.43826,0.18143 -0.0182,0.0262 -0.0368,0.0486 -0.0555,0.0679 -0.009,-10e-6 -0.0175,-0.002 -0.0259,-6.4e-4 -0.071,0.004 -0.13477,0.0243 -0.18907,0.0571 -0.0242,-0.0244 -0.0391,-0.59467 -0.0391,-0.65359 0,-0.36718 -0.95879,-0.22794 -1.02811,0.14931 -0.0212,0.11589 0.0311,0.75145 0.13054,0.79443 0.23059,0.0996 0.20734,0.48697 -0.037,0.66412 -0.0408,-0.002 -0.0836,-0.005 -0.13238,-0.0129 -0.2574,-0.0398 -0.36727,-0.008 -0.58024,0.1696 -0.28227,0.235 -0.2933,0.288473 -0.26634,1.268603 0.0133,0.48463 0.0593,0.66991 0.18495,0.74461 0.11022,0.0655 0.20912,0.0728 0.28966,0.0212 0.0568,-0.0364 0.11754,-0.12674 0.17124,-0.23402 0.107,0.0658 0.25755,0.11689 0.41792,0.14507 -0.0242,0.0438 -0.0493,0.0775 -0.0743,0.0935 -0.22968,0.14714 -0.18073,0.29031 0.16346,0.47951 0.16459,0.0905 0.24667,0.16091 0.28464,0.26651 -0.22328,0.31999 -0.54905,0.56105 -0.79857,0.56105 -0.26805,0 -0.38363,0.13101 -0.38363,0.43504 0,0.099 -0.14109,0.28428 -0.31344,0.41175 -0.29557,0.21858 -0.40894,0.4781 -0.23503,0.53776 0.0431,0.0148 0.21951,0.23939 0.39186,0.49911 0.29454,0.44378 0.49384,0.61168 1.14242,0.96274 0.2234,0.12093 0.26771,0.2085 0.26771,0.52841 0,0.21082 0.0564,0.42682 0.1253,0.48004 0.17164,0.13252 0.36279,0.12141 0.72039,-0.0417 0.2969,-0.13538 0.35429,-0.23188 0.31892,-0.53634 -0.0158,-0.13554 0.343,-0.51902 0.92317,-0.98692 0.28788,-0.23216 0.26618,-0.30644 -0.12894,-0.44069 -0.37244,-0.12655 -0.37109,-0.11805 -0.22497,-1.22413 0.0601,-0.45428 0.10536,-0.49778 0.48606,-0.46787 0.10405,0.008 0.18291,-0.0399 0.1829,-0.11171 0,-0.16011 -0.092,-0.15842 -0.53246,0.01 -0.43953,0.16783 -0.58282,0.30447 -0.72314,0.68954 -0.0603,0.16556 -0.19888,0.33774 -0.30795,0.3828 -0.10906,0.045 -0.22827,0.15462 -0.26475,0.24337 -0.0547,0.1331 -0.11029,0.17837 -0.15911,0.14437 0.0191,-0.0362 0.0267,-0.0666 0.0146,-0.0817 -0.0268,-0.0333 -0.007,-0.17466 0.0454,-0.31397 0.0701,-0.18872 0.056,-0.28296 -0.0553,-0.36886 -0.17292,-0.13348 -0.20148,-0.65681 -0.04,-0.73384 0.0536,-0.0256 0.0859,-0.25521 0.0912,-0.59759 0.0308,-0.0283 0.0572,-0.054 0.0821,-0.0789 0.15372,-0.0696 0.2735,-0.27581 0.20759,-0.4084 -0.0286,-0.0576 0.009,-0.313 0.0811,-0.59847 0.0866,0.0779 0.22739,0.11682 0.37448,0.10077 0.33605,-0.0365 0.41939,-0.41959 0.11843,-0.54393 -0.1668,-0.0689 -0.21038,-0.19846 -0.25309,-0.75131 -0.0284,-0.367453 -0.0136,-0.746523 0.0327,-0.842563 0.0464,-0.0961 0.0457,-0.2254 0.0137,-0.35209 0.24966,-0.16135 0.77006,-0.17218 0.9474,-0.007 0.3168,0.29467 0.52241,0.0917 0.52241,-0.51569 0,-0.31975 0.0512,-0.41964 0.31732,-0.61647 0.40678,-0.30086 0.38252,-0.55289 -0.0562,-0.58224 -0.0293,-0.002 -0.058,-0.004 -0.0862,-0.004 z", +2.20356, 4.42723, +"M -0.779833 -4.42535 c -0.11252,0.01 -0.20766,0.0645 -0.31936,0.15707 -0.19303,0.1602 -0.30553,0.46533 -0.24987,0.67821 0.0557,0.21288 -0.031,0.75799 -0.19276,1.21128 -0.16176,0.45332 -0.29873,0.73139 -0.30366,0.61778 -0.006,-0.11371 -0.12301,-0.0935 -0.26176,0.0452 -0.19127,0.19127 -0.10817,0.47025 0.34411,1.1537 0.45766,0.69158 0.55864,1.03463 0.43407,1.47638 -0.0892,0.31659 -0.13322,0.67331 -0.0981,0.79292 0.0352,0.11957 0.15515,0.65783 0.267,1.19605 0.11176,0.53827 0.24306,1.10126 0.29128,1.25078 0.1727,0.53503 0.7492,0.25702 1.23653,-0.59635 0.27267,-0.47751 0.6625,-0.86921 0.86619,-0.87004 0.20765,-9.2e-4 0.5269,-0.33172 0.72679,-0.75294 0.29035,-0.6119 0.31116,-0.88889 0.11183,-1.49304 -0.13459,-0.40798 -0.22205,-1.12174 -0.19417,-1.58632 0.11331,-1.88242 -0.006,-2.47587 -0.49595,-2.47587 -0.25281,0 -0.83601,-0.21102 -1.29552,-0.46928 -0.44311,-0.24903 -0.67905,-0.35297 -0.86669,-0.33554 z", +2.98889, 3.67435, +"M 0.0402496 -3.67435 c -0.32831,0 -1.18189,0.92749 -1.79096,1.94648 -0.3584,0.59962 -0.44172,0.96993 -0.33994,1.5125 0.10659,0.56847 0.0207,0.89088 -0.41379,1.54736 -0.30817,0.46568 -0.51868,1.04377 -0.47984,1.31799 0.0652,0.45978 0.15767,0.48811 1.5781,0.48811 0.9272,0 1.60942,0.10087 1.77078,0.26195 0.68945,0.68812 2.06575,-0.0134 2.06575,-1.05284 0,-0.21065 0.15263,-0.67888 0.33994,-1.04091 0.34011,-0.65768 0.33957,-0.65885 -0.40829,-1.25881 -0.58894,-0.47247 -0.77875,-0.80242 -0.89043,-1.54736 -0.14276,-0.95204 -0.94727,-2.17447 -1.43132,-2.17447 z", +3.40151, 5.32865, +"M 2.71045 -5.32831 v 3.7e-4 c -0.67587,-0.012 -1.14971,0.34982 -1.61607,1.21978 -0.37425,0.69821 -0.53418,0.84374 -0.97521,0.8875 -0.312,0.0309 -0.59827,0.1844 -0.70069,0.37577 -0.2226,0.41586 -0.49528,0.41624 -0.49528,7e-4 0,-0.76048 -1.53295,-0.4721 -1.64379,0.30924 -0.0339,0.24004 0.0495,0.46036 0.20873,0.54939 0.37193,0.2081 0.33168,1.02339 -0.0686,1.38571 -0.49393,0.44696 -1.00322,2.96143 -0.75706,3.73717 0.13368,0.42094 0.97103,0.75376 1.58712,0.63054 0.60075,-0.12019 0.73147,0.051 0.50116,0.65685 -0.0961,0.2532 -0.13673,0.56011 -0.0898,0.68207 0.0467,0.12199 0.19735,0.22188 0.33479,0.22188 0.31413,0 0.6262,-0.56153 0.49789,-0.89591 -0.053,-0.13863 0.0311,-0.82668 0.18716,-1.52901 0.31845,-1.4316 0.19566,-1.84197 -0.4343,-1.44858 -0.48884,0.30529 -0.65563,0.11304 -0.66886,-0.77128 -0.007,-0.43091 -0.0729,-0.93369 -0.14734,-1.11741 -0.18115,-0.44714 0.24354,-0.91857 0.82717,-0.91857 0.24714,0 0.58532,-0.15039 0.75154,-0.33411 0.36082,-0.39872 1.28482,-0.44747 1.58678,-0.0837 0.50646,0.6103 0.83488,0.19 0.83488,-1.06807 0,-0.66226 0.0822,-0.86909 0.50773,-1.27679 0.65033,-0.6231 0.61157,-1.14509 -0.09,-1.20588 -0.0467,-0.005 -0.093,-0.008 -0.13814,-0.008 z", +3.13042, 4.93641, +"M 0.240783 -4.93553 c -0.15688,-0.0178 -0.29819,0.23397 -0.49049,0.81373 -0.2825,0.85157 -0.93362,1.59307 -1.39943,1.59307 -0.39149,0 -0.56027,0.24786 -0.56027,0.82307 0,0.18722 -0.20606,0.53783 -0.45779,0.77901 -0.4317,0.41355 -0.59724,0.90453 -0.34324,1.01741 0.0626,0.028 0.32056,0.45291 0.57229,0.94429 0.43015,0.8396 0.72124,1.15726 1.66856,1.82145 0.32624,0.22878 0.39098,0.39448 0.39098,0.99971 0,0.39888 0.0823,0.80753 0.18298,0.90823 0.25071,0.2507 0.52985,0.2297 1.05213,-0.0788 0.43363,-0.25616 0.51743,-0.4387 0.4658,-1.01474 -0.0233,-0.25645 0.50065,-0.98195 1.348,-1.8672 0.42045,-0.43923 0.38879,-0.57978 -0.18835,-0.83377 -0.54393,-0.23942 -0.54167,-0.22334 -0.32824,-2.31596 0.0877,-0.8595 0.15391,-0.94177 0.70992,-0.88519 0.15197,0.0155 0.26679,-0.0756 0.26679,-0.21137 0,-0.30291 -0.13407,-0.30005 -0.77732,0.018 -0.64195,0.31753 -0.85123,0.57637 -1.05619,1.3049 -0.0882,0.31325 -0.29044,0.63899 -0.44972,0.72425 -0.15934,0.0852 -0.33341,0.29254 -0.38672,0.46045 -0.16715,0.5267 -0.33974,0.3349 -0.41637,-0.46279 -0.0465,-0.4866 -0.17065,-0.83911 -0.33826,-0.96165 -0.24082,-0.17607 -0.24289,-0.21137 -0.022,-0.39467 0.14751,-0.1224 0.24275,-0.43967 0.24275,-0.80907 0,-0.42563 0.11425,-0.74365 0.38136,-1.06115 0.43886,-0.52158 0.46645,-0.71391 0.16257,-1.12559 -0.0841,-0.11391 -0.15837,-0.17762 -0.2297,-0.18565 z", +3.36677, 6.16908, +"M 2.46494 -6.16587 c -0.0541,-0.01 -0.12003,0.003 -0.18482,0.0437 -0.14889,0.092 -0.21185,0.45187 -0.17387,0.99402 l 0.0595,0.84965 -0.8909,0.25437 c -0.85575,0.24425 -0.91404,0.30547 -1.49387,1.561 -0.68138,1.47535 -0.8842,1.39519 -0.95601,-0.37731 -0.0677,-1.67347 -0.53514,-1.57118 -0.54675,0.1197 -0.008,1.20372 -0.14815,1.49162 -0.91678,1.88573 -0.33093,0.1697 -0.55445,0.43025 -0.55445,0.64665 0,0.31078 0.1713,0.37963 1.20109,0.48124 0.9293,0.0916 1.27169,0.056 1.51288,-0.15692 0.17144,-0.15173 0.40028,-0.22045 0.50832,-0.15367 0.34578,0.21373 0.21149,0.66082 -0.35303,1.17641 -0.30209,0.2759 -0.64427,0.77409 -0.76029,1.10686 -0.28842,0.82736 -0.63087,0.63547 -0.63087,-0.35346 0,-0.78244 -0.0622,-0.90627 -0.45738,-0.90627 -0.31541,0 -0.7871,0.90286 -1.04012,1.99129 -0.23161,0.9964 -0.22259,1.08589 0.16459,1.6532 0.22515,0.32984 0.51912,0.64232 0.65352,0.69436 0.40194,0.15571 0.95683,-0.25666 0.95683,-0.71094 0,-0.48104 0.73081,-0.96973 1.18811,-0.79425 0.41463,0.1592 0.35885,0.40487 -0.17185,0.7526 -0.495,0.32433 -0.61311,0.99321 -0.24064,1.36566 0.25886,0.25887 0.69051,0.28229 1.0462,0.0571 0.1824,-0.11553 0.21563,-0.36728 0.12213,-0.92083 -0.13213,-0.78273 -0.0775,-0.84677 0.66079,-0.77645 0.16235,0.0149 0.40663,-0.10649 0.54313,-0.27095 0.19821,-0.23888 0.20282,-0.37194 0.0222,-0.6612 -0.12434,-0.19914 -0.17751,-0.44051 -0.11809,-0.53664 0.0594,-0.0961 0.0229,-0.48362 -0.0813,-0.86098 -0.23192,-0.83997 0.12462,-1.35152 0.94265,-1.35152 0.63152,0 0.89091,-0.51453 0.89091,-1.76764 0,-0.91589 -0.27505,-1.06452 -0.83144,-0.4497 -0.45014,0.49738 -0.77029,0.46537 -0.87594,-0.0874 -0.091,-0.47571 0.45137,-1.57555 0.77684,-1.57555 0.18146,0 0.93054,-1.3103 0.93054,-1.62773 0,-0.0901 -0.16195,-0.3501 -0.35992,-0.57829 -0.19792,-0.22822 -0.3899,-0.50528 -0.42664,-0.61551 -0.0186,-0.0556 -0.061,-0.0898 -0.11526,-0.0999 z", +3.36642, 4.71204, +"M 2.14302 -4.71204 c -0.63965,0.002 -0.47682,2.13844 -1.24978,1.55409 -0.92613,-1.50861 -3.40173,-0.29544 -3.14116,1.46395 0.51593,1.36936 -1.77871,0.91049 -0.92686,1.85562 1.40951,0.21819 -0.44125,1.4145 0.82327,1.66419 -0.57592,1.3499 0.6215,1.87772 1.29993,2.57621 l 0.0604,0.24159 c 1.21026,0.51184 1.30627,-1.98878 1.77943,-2.80526 0.61441,-1.01698 0.0716,-4.43446 2.03773,-3.03058 1.29395,-0.57329 -0.14993,-2.07687 -0.0896,-3.11886 -0.25448,-0.28697 -0.44513,-0.40085 -0.59283,-0.40095 z", +2.67932, 7.19187, +"M 1.11365 -7.19037 c -0.3679,0.0246 -0.63802,0.36228 -0.63802,0.85647 0,0.30813 -0.20548,0.69239 -0.54292,1.01568 -0.4374,0.41905 -0.65076,0.49812 -1.10192,0.40788 -0.45379,-0.0908 -0.64747,-0.0176 -1.02293,0.38733 -0.49761,0.53665 -0.51748,0.65878 -0.46996,2.8971 0.0235,1.10675 0.10496,1.52987 0.32646,1.70046 0.19433,0.14956 0.36827,0.16624 0.51027,0.0483 0.29856,-0.24777 0.67015,-1.55748 0.53886,-1.89956 -0.13302,-0.34677 0.56593,-0.78978 0.75734,-0.48002 0.19788,0.32019 -0.0997,2.15035 -0.38855,2.39006 -0.4049,0.33604 -0.31862,0.66299 0.28818,1.09508 0.4482,0.31914 0.55259,0.52604 0.55259,1.09468 0,0.38551 -0.1213,1.04395 -0.26923,1.46305 -0.32207,0.91276 -0.13816,3.08081 0.28414,3.35093 0.18196,0.11631 0.35857,0.0495 0.5824,-0.21965 0.17673,-0.21254 0.28298,-0.44885 0.23579,-0.52518 -0.0472,-0.0763 -0.0118,-0.39886 0.0802,-0.71701 0.12359,-0.43098 0.0987,-0.64618 -0.0975,-0.84237 -0.30484,-0.30484 -0.35517,-1.49996 -0.0705,-1.67587 0.1173,-0.0725 0.18049,-0.84131 0.16121,-1.95881 -0.0334,-1.94431 0.16284,-2.55058 0.62232,-1.92213 0.14856,0.20308 0.41417,0.30595 0.69123,0.26682 0.59243,-0.0836 0.73976,-0.95822 0.20916,-1.24219 -0.29405,-0.15734 -0.37126,-0.4532 -0.44656,-1.71577 -0.05,-0.83913 -0.0241,-1.70487 0.0576,-1.92415 0.21457,-0.57599 -0.13731,-1.67514 -0.5816,-1.81613 -0.0932,-0.0296 -0.18312,-0.0407 -0.26802,-0.0351 z", +3.567, 4.28391, +"M 2.1794 -4.28301 c -0.79452,0.0388 -2.13823,1.33278 -2.9006,1.67225 -1.91886,1.17374 2.21816,1.25105 0.10284,2.06499 -0.58361,-0.83118 -3.01823,-1.30637 -2.94711,0.17002 3.14717,0.20852 0.16743,2.80766 0.98237,4.53047 l 0.2031,0.12919 c 1.35802,-1.01667 2.60945,-2.23253 4.49275,-2.01435 2.35172,-1.19271 1.28122,-3.42569 0.70123,-5.26324 0.0473,-0.98574 -0.21839,-1.30966 -0.63458,-1.28933 z", +2.56174, 3.97214, +"M 1.23387 -3.97214 c -0.18031,0 -0.50408,0.11364 -0.92088,0.35086 -0.75763,0.43141 -0.89736,0.64381 -0.99891,1.519285 -0.10988,0.94689 -0.17227,1.02365 -0.88521,1.09244 -0.89236,0.0859 -1.14888,0.68747 -0.90125,2.11048 0.0846,0.48667 0.1492,1.23005 0.14367,1.65208 -0.008,0.60558 0.0866,0.7674 0.44804,0.7674 0.25202,0 0.52438,0.10634 0.6046,0.23617 0.21463,0.34726 0.57153,0.29583 2.12908,-0.30748 1.35943,-0.52657 1.40925,-0.57732 1.58906,-1.59422 0.28866,-1.63263 0.097,-2.0538 -1.0387,-2.2784 -1.22331,-0.24191 -1.64524,-0.80341 -1.07591,-1.43248 0.2218,-0.24509 0.40307,-0.615415 0.40307,-0.823195 0,-0.20788 0.17214,-0.54991 0.3824,-0.76018 0.3479,-0.34787 0.35277,-0.53337 0.12094,-0.53276 z", +1.40175, 2.35464, +"M 0.715347 1.73249 c 0.5213,-0.7219 1.00154,-1.43136 0.42262,-1.81986 -0.0242,-0.002 -0.0403,-0.0133 -0.0667,-0.0124 -0.2124,-0.35703 -0.18293,-1.55466 -0.66093,-1.50121 -0.38391,0.0613 -0.36171,-0.99746 -1.04282,-0.70124 -0.84233,0.26952 -1.03878,1.15204 -0.35968,1.72237 -0.28818,0.80849 -0.72983,1.85273 -0.017,2.57194 0.11293,0.13641 0.31123,0.26109 0.54043,0.35233 0.20746,0.0826 0.99861,-0.35508 1.18408,-0.61193 z", +3.58152, 4.34829, +"M -2.44195 -4.34714 c -0.75319,0.0362 -0.7762,0.92587 -0.55537,1.58591 -0.55027,0.26441 -0.90264,0.93541 -0.1653,1.39825 0.67743,0.40826 1.43356,1.01809 1.58319,1.83852 0.64834,0.73248 -0.1527,1.61798 -0.33278,2.42552 l 0.54118,0.63011 c 0.0142,-0.52312 0.48191,-0.59895 0.82051,-0.61429 -0.003,0.37955 0.1004,0.74248 0.40424,1.04909 0.11924,0.14402 0.32868,0.2752 0.57065,0.37153 0.21902,0.0872 1.05405,-0.37478 1.24987,-0.64594 0.55034,-0.76211 1.05742,-1.51075 0.44627,-1.92088 -0.0255,-0.002 -0.0426,-0.014 -0.0704,-0.0131 -0.0106,-0.0172 -0.0174,-0.0448 -0.0267,-0.0654 0.21024,-0.3016 0.38758,-0.56962 0.74632,-0.0954 0.65582,0.69676 1.24636,-0.49914 0.37097,-0.65739 -0.4622,0.24406 -0.37168,-0.72499 -0.69993,-0.96236 -0.10039,-0.91415 -0.4508,-1.68175 -0.81563,-2.50845 -0.28239,-0.46623 -0.83252,-1.22127 -1.4135,-1.3415 -0.0742,-0.0449 -0.15322,-0.0625 -0.2357,-0.0556 -0.32052,0.0264 -0.68498,0.39222 -0.99017,0.71794 -0.2134,-0.59389 -0.55451,-1.1417 -1.22475,-1.1271 -0.0728,-0.01 -0.14044,-0.0118 -0.20295,-0.01 z", +3.66123, 3.92165, +"M -2.89919 -0.28264 c 0.5248,0.64771 0.38465,1.62029 -0.46302,1.88928 -0.85786,0.6722 0.38319,1.31277 0.57724,1.97921 0.11171,0.25581 0.51808,0.48818 0.72707,0.20878 0.35103,-0.2002 0.83823,0.2502 1.11623,-0.3514 0.28826,-0.50439 0.39449,-1.18406 1.07021,-1.30949 0.38793,-0.46627 -0.45389,-0.99265 0.11266,-1.47639 0.35536,-0.69249 0.56184,-1.84188 1.34721,-2.07791 0.63362,0.38352 1.48161,0.65582 1.72651,-0.31936 0.39002,-0.4159 0.59822,-1.04678 -0.19431,-1.0914 -0.59473,-0.216 -1.75681,-0.9684 -1.89285,-1.06904 -0.17327,-0.12817 -0.40811,0.35444 -0.60881,0.59258 -0.2757,0.48096 -1.0685,0.56942 -0.82373,1.34875 0.16859,0.56791 -0.21712,0.74465 -0.57515,0.30903 -0.73642,-0.18936 -0.47345,1.25664 -1.18184,0.50643 -0.15757,-0.16278 -0.39659,0.0541 -0.64211,-0.053 -0.23726,-0.1035 0.0848,-0.3456 -0.27012,-0.34843 -0.37484,-0.003 -0.30986,0.87936 -0.0252,1.26233 z", +4.66444, 5.18369, +"M 2.11104 -5.18252 c -0.17844,-0.0365 -0.59098,0.79076 -0.87075,0.86971 -0.28109,-0.28971 -0.64463,-0.14558 -0.67074,0.31678 0.17296,0.35303 -0.32848,0.92855 -0.38034,0.37982 -0.48361,-0.88691 -0.84545,0.5953 -1.32914,0.67386 -0.34102,0.46556 0.0161,0.50242 0.25064,0.78445 -0.56409,0.44035 -0.67167,0.83211 -0.3612,1.14774 -0.006,0.0911 0.005,0.19332 0.0424,0.31316 0.16859,0.56791 -0.21712,0.74465 -0.57516,0.30903 -0.73641,-0.18936 -0.47344,1.25663 -1.18184,0.50642 -0.15758,-0.16277 -0.39629,0.0539 -0.64182,-0.0532 -0.23725,-0.1035 0.0846,-0.34547 -0.27027,-0.3483 -0.37484,-0.003 -0.30999,0.87948 -0.0253,1.26246 0.52481,0.64771 0.38466,1.6203 -0.46302,1.88928 -0.85785,0.6722 0.3837,1.31277 0.57775,1.97921 0.1117,0.25581 0.51758,0.48817 0.72657,0.20878 0.35102,-0.20021 0.83873,0.25019 1.11673,-0.3514 0.28826,-0.5044 0.39399,-1.18405 1.06971,-1.30949 0.38793,-0.46627 -0.4539,-0.99265 0.11266,-1.47639 0.35533,-0.69249 0.56234,-1.84188 1.34771,-2.07791 0.30376,0.18387 0.65616,0.34025 0.96842,0.34778 0.33359,0.3812 0.84312,0.50562 1.2237,-0.11369 -0.30948,-1.21831 1.01658,-2.14727 1.88669,-2.2686 -0.41399,-0.6498 -0.0859,-1.85265 -0.94827,-2.09135 -0.29061,-0.0875 -1.51122,0.0898 -1.51876,-0.51108 0.006,-0.26471 -0.0266,-0.37397 -0.0858,-0.38705 z", +3.05335, 5.71572, +"M 2.29249 -5.71375 c -0.44087,0.0257 -0.84558,0.29637 -0.4935,0.77566 0.043,0.5726 -0.66244,1.13031 -1.01182,1.61954 -0.59536,0.0643 -0.67884,0.58579 -0.62891,1.04283 -0.0328,0.0299 -0.0632,0.056 -0.0997,0.092 -0.45413,0.43121 -0.7044,1.02376 -0.9338,1.62522 -0.0229,-0.0163 -0.0443,-0.0282 -0.0687,-0.0486 -0.64201,-0.37339 -0.381,-1.68417 -1.16064,-1.73633 -0.89157,0.53168 -0.63784,1.71779 -0.94877,2.58124 0.41748,0.0224 0.78081,-0.11303 0.77824,-0.56637 -0.029,-0.81387 0.44852,-0.14497 0.38963,0.22686 0.1398,0.26873 0.29702,0.57106 0.45476,0.83974 -0.22764,0.40185 -0.52107,0.74432 -0.9617,0.95911 -0.36584,-0.3203 -0.60315,0.95868 -0.12867,0.68575 0.24482,-0.0374 0.49482,-0.0125 0.74567,0.0408 -0.13684,0.27374 -0.30318,0.52271 -0.54673,0.70848 -0.72324,1.44096 1.7649,0.37106 0.93432,1.48157 -1.67179,-0.43188 -1.37967,2.24445 0.49197,0.51159 0.93927,-0.75809 1.02925,-2.0752 2.374,-2.39416 0.0427,-0.19658 0.0496,-0.37691 0.0326,-0.54519 0.007,-0.013 0.0142,-0.0244 0.0212,-0.0377 -0.0109,-0.006 -0.0181,-0.0127 -0.0284,-0.0186 -0.0376,-0.26876 -0.14378,-0.50259 -0.29869,-0.70797 0.0675,-0.50253 0.39688,-1.12995 0.27337,-1.65519 0.0776,-0.12843 0.15978,-0.26383 0.2372,-0.3974 0.51546,-0.0608 0.96877,-0.52849 0.25114,-0.86041 -0.99645,-0.23462 -0.10779,-1.19683 -0.005,-1.79162 -0.13147,-0.84084 0.53896,-1.24912 1.0418,-1.73478 0.20727,-0.50166 -0.26911,-0.72137 -0.71004,-0.69608 z", +3.25546, 5.30144, +"M 1.7045 -3.73289 c -0.59536,0.0643 -0.67884,0.58579 -0.62891,1.04283 -0.0328,0.0299 -0.0632,0.056 -0.0997,0.092 -0.11954,0.11351 -0.22424,0.23899 -0.31885,0.37207 -0.16346,-0.31767 -0.41725,-0.59374 -0.693,-0.86196 -0.0135,-0.57623 -0.52533,-0.68908 -0.93429,-0.86196 -0.3143,-0.11364 -0.30232,-0.22096 -0.26924,-0.50178 10e-4,-0.35694 -0.19302,-0.64802 -0.63614,-0.70849 -0.52435,-0.42985 -0.56304,0.22719 -0.74414,0.56328 0.27,0.2644 0.29136,0.75232 -0.0961,1.02939 -0.41132,0.0707 -0.85182,1.03037 -0.23047,1.04387 0.0806,0.4722 0.45971,1.10991 0.004,1.55132 -0.11771,0.33019 0.0386,0.9166 0.39997,1.19631 -0.16174,0.3523 -0.42196,0.8126 -0.35452,1.31207 0.12679,0.12631 0.14632,0.23085 0.13179,0.31729 l 0.17828,0.42323 1.16996,0.47026 c -0.67056,1.39319 1.77057,0.35041 0.9462,1.45262 -1.67179,-0.43188 -1.37969,2.24446 0.49194,0.5116 0.93927,-0.7581 1.02929,-2.0752 2.37403,-2.39417 0.0427,-0.19657 0.0496,-0.37691 0.0325,-0.54519 0.007,-0.013 0.0142,-0.0244 0.0212,-0.0377 -0.0109,-0.006 -0.0181,-0.0127 -0.0284,-0.0186 -0.0375,-0.26875 -0.14377,-0.50258 -0.29869,-0.70796 0.0675,-0.50253 0.39688,-1.12996 0.27337,-1.6552 0.0776,-0.12843 0.15978,-0.26383 0.2372,-0.39739 0.51546,-0.0608 0.96877,-0.52849 0.25114,-0.86041 -0.99645,-0.23463 -0.10795,-1.19683 -0.005,-1.79163 -0.13147,-0.84083 -0.82474,-0.52493 -1.17413,-0.0357 z", +2.78553, 3.0102, +"M 1.13709 -3.01011 c -0.11999,0.003 -0.27165,0.0974 -0.47025,0.32039 0.066,1.27176 -1.98331,0.51776 -2.42723,1.40147 -0.0487,-0.008 -0.0958,-0.0135 -0.13954,-0.0155 v 0 c -0.1647,-0.007 -0.38814,1.2022 -0.42942,1.30522 -0.044,0.10842 -0.0601,0.18666 0.12544,0.44857 -0.29803,0.73252 -0.15986,0.47603 -0.30581,1.26773 -0.70138,0.52342 0.0894,1.15559 0.6594,0.67903 0.0741,-0.0339 0.14901,-0.0598 0.22426,-0.0801 0.006,0.0576 0.0156,0.14035 0.019,0.18707 0.3897,0.22008 0.6114,0.17646 0.72191,-0.0186 l 0.27597,0.52503 c 0.45595,-0.0258 0.61214,-0.2684 0.60356,-0.57309 0.61931,0.11342 1.21306,0.13704 1.71154,-0.50953 1.48952,-0.17693 -0.82934,-2.42653 0.68212,-1.97766 0.62791,0.54053 0.50184,-1.28519 -0.30697,-0.9617 -0.50501,-0.32149 -0.42357,-2.01307 -0.94361,-1.99832 z", +3.40832, 4.84469, +"M 2.62836 -4.84469 c -0.55086,0.67388 -0.63529,1.54387 -0.99475,2.24637 -0.0561,-0.0679 -0.1206,-0.11028 -0.20103,-0.108 h -5.3e-4 c -0.11999,0.003 -2.65788,1.24415 -2.89783,1.72186 -0.0487,-0.009 -0.0958,-0.0135 -0.13954,-0.0155 -0.0819,-0.003 -0.17807,0.29411 -0.2594,0.60668 -0.20463,-0.0148 -0.40645,-0.0353 -0.59997,-0.0636 -0.21733,0.51377 -0.40796,0.43238 -0.59894,0.21445 -0.86921,0.67457 0.0811,1.38892 0.91467,1.8433 -0.0122,0.0981 -0.0303,0.22652 -0.0661,0.42065 -0.70135,0.52342 0.0894,1.15558 0.6594,0.67903 0.0741,-0.0339 0.14904,-0.0598 0.22428,-0.0801 0.006,0.0576 0.0157,0.14035 0.0191,0.18707 0.3897,0.22008 0.61142,0.17645 0.72194,-0.0186 l 0.27593,0.52503 c 0.0851,-0.005 0.15658,-0.0193 0.2217,-0.0382 -0.54399,0.66639 2.71703,2.46603 2.19988,1.0232 -0.0139,-0.61741 -0.002,-1.35716 -0.17984,-1.98593 0.0244,-0.028 0.0494,-0.0506 0.0734,-0.0816 0.0125,-0.001 0.0226,-0.004 0.0346,-0.006 0.0456,0.024 0.0912,0.0457 0.13642,0.0744 0.28681,-0.0617 0.92583,0.13145 0.99012,-0.27905 -0.20907,-0.18446 -0.45444,-0.38854 -0.68937,-0.61029 -8e-5,-9e-5 1.1e-4,-4.4e-4 0,-5.2e-4 -0.18285,-0.66281 -0.73432,-1.43655 0.21035,-1.156 0.62791,0.54053 0.50183,-1.28519 -0.30697,-0.9617 -0.16449,-0.10471 -0.26461,-0.35892 -0.34571,-0.64802 0.40217,-0.89611 1.62198,-1.24553 1.16322,-2.50115 0.10718,-0.40833 0.32133,-0.44801 0.15195,-0.57722 -0.14476,-0.11041 -0.66517,-0.33109 -0.71729,-0.41031 z", +2.91331, 4.2784, +"M 2.48505 -2.50743 -1.1297,-0.69932 c -0.26081,0.34403 -0.73919,0.6277 -1.09585,0.98835 -0.24912,0.29904 -0.87887,0.48065 -0.71385,-0.14805 0.12544,-0.65962 -0.50944,-0.96834 -0.73168,-1.47416 -0.346,0.0114 -0.71232,0.27983 -0.97235,-0.16999 -0.28809,-0.52063 -1.0299,-0.21119 -0.64799,0.32288 0.0949,0.43869 -0.36202,1.16319 0.1949,1.57459 0.20779,0.3961 0.46321,0.88104 0.35823,1.27627 -0.32873,0.54046 0.48828,0.91234 0.59778,1.40794 -0.21794,0.44035 -0.88762,0.52868 -0.68223,1.17211 -0.14326,0.65293 0.62787,0.80659 0.88904,0.25258 0.25359,-0.22465 0.61647,-0.63708 0.95934,-0.57843 0.36095,0.23638 0.80362,0.33863 0.64427,0.90689 -0.14441,0.70198 1.27406,0.83383 0.55797,1.45519 -0.0887,0.73566 0.84516,-0.20652 0.74062,0.41996 0.0243,0.13225 0.1875,0.0766 0.22429,-0.008 0.52299,-0.10663 0.83538,-0.53091 0.87788,-1.00509 -0.28215,-0.43305 -0.9743,-0.71636 -0.8522,-1.3157 0.1777,-0.15854 0.72403,0.14848 0.86856,-0.2217 0.0626,-0.53635 0.50097,-0.95686 0.279,-1.47081 -0.26406,-0.25211 -0.7397,-0.041 -0.99059,-0.11792 -0.1503,-0.59096 0.62362,-0.44277 0.78004,-0.89386 0.23735,-0.31162 -0.0744,-0.59806 -0.34594,-0.66771 0.35082,-0.27779 0.25851,-0.66602 0.19046,-1.00583 z", +3.95524, 4.27828, +"M -1.82143 -4.27815 c -0.25411,0.0105 -0.45471,0.25635 -0.21601,0.59015 0.0949,0.43869 -0.3616,1.16318 0.19532,1.57458 0.2078,0.3961 0.4631,0.88118 0.35814,1.27641 -0.0519,0.0854 -0.0729,0.16631 -0.0749,0.24443 -0.30033,-0.55817 -0.63892,-1.39159 -1.45005,-0.93483 -0.68429,0.018 -1.4623,0.76829 -0.48681,1.12758 0.43926,0.0751 -0.26699,0.60334 0.20516,0.87695 -0.0159,0.0235 -0.0497,0.0421 -0.0672,0.0651 l 1.56943,0.97152 c -0.003,-0.009 0,-0.0182 -0.003,-0.0269 0.0739,-0.017 0.13893,-0.0512 0.20052,-0.0894 -0.0235,0.0959 -0.022,0.20757 0.0222,0.34571 -0.14325,0.65293 0.6282,0.80671 0.88937,0.2527 0.0456,-0.0404 0.0984,-0.0907 0.15036,-0.13952 0.28739,0.18954 0.63963,0.18337 0.97256,-0.0904 0.0949,0.088 0.29792,0.16289 0.50125,0.2434 0.0167,0.087 0.0148,0.18794 -0.0206,0.3147 -0.0412,0.20018 0.049,0.35167 0.17622,0.4837 -0.60791,0.27447 1.22695,0.76516 1.12241,1.39164 0.0243,0.13225 0.18749,0.0763 0.22429,-0.008 0.52297,-0.10663 0.83547,-0.53093 0.87797,-1.00511 -0.18696,-0.28696 -0.5497,-0.50948 -0.74052,-0.80047 0.3039,-0.33202 0.6305,-0.62391 1.08003,-0.69298 0.3443,-0.30868 -0.18545,-0.98462 0.27493,-1.39681 -0.003,-0.027 0.0145,-0.0359 0.0156,-0.0605 v -5.3e-4 c -0.15378,-0.23531 -0.0824,-0.95349 -0.51263,-0.59635 -0.008,0.0349 -0.0352,0.0725 -0.0403,0.10697 -0.23939,0.0364 -0.4218,0.16976 -0.58653,0.33073 -0.0687,0.002 -0.13319,1.9e-4 -0.18605,-0.016 -0.15028,-0.59096 0.62391,-0.44292 0.78031,-0.894 0.23736,-0.31162 -0.0747,-0.59801 -0.34621,-0.66766 0.35081,-0.2778 0.25874,-0.66582 0.19069,-1.00563 v -5.3e-4 l -1.12967,-0.69918 c -0.2608,0.34403 -0.73938,0.62792 -1.09606,0.98857 -0.24911,0.29904 -0.87866,0.48039 -0.71364,-0.14831 0.12544,-0.65962 -0.5095,-0.96851 -0.73173,-1.47433 -0.34602,0.0114 -0.71252,0.2798 -0.97255,-0.17002 -0.10803,-0.19523 -0.27956,-0.27346 -0.43202,-0.26716 z", +4.74428, 5.06938, +"M -3.5022 -4.25506 c 0.0377,1.35963 1.56777,-0.33227 2.03738,0.80243 0.10379,0.0956 0.208,0.18438 0.31094,0.26506 -0.0406,0.39354 -0.0321,0.76444 0.0226,0.99137 -0.0937,0.13068 -0.17696,0.30235 -0.24523,0.49401 l -0.016,0.006 c 0.002,0.008 0.003,0.018 0.005,0.0266 -0.0996,0.28994 -0.16492,0.62239 -0.17565,0.93429 -0.0765,0.0524 -0.1308,0.11334 -0.15194,0.17898 l -7.4e-4,1e-4 c -0.0328,0.10411 0.0199,0.22082 0.19471,0.33612 0.0223,0.0965 0.0512,0.18645 0.0924,0.26307 -0.0649,0.0713 -0.11275,0.14849 -0.14391,0.22932 l -4e-4,-3.2e-4 c -0.0213,0.0536 -0.0342,0.10888 -0.042,0.16478 -0.07,-0.0196 -0.14851,-0.0772 -0.2347,-0.1906 -0.4414,-0.50596 -1.07643,-0.19724 -1.61154,-0.33475 -0.20468,0.2792 -0.21946,0.73356 -0.73384,0.66033 -0.58741,-0.0949 -0.8024,0.67948 -0.14649,0.70885 0.40367,0.19623 0.69169,1.00265 1.35917,0.8186 0.43988,0.0811 0.97908,0.17983 1.22514,0.50646 0.22215,0.59228 1.0194,0.17931 1.47686,0.39919 0.0351,0.0735 0.0519,0.1516 0.0635,0.23048 -0.003,0.23736 -0.0256,0.46963 -0.1023,0.6877 0.73066,0.46689 1.85021,2.14597 1.91273,0.29922 l -0.0399,-0.38017 c 0.17772,-0.45619 0.21761,-0.97787 0.11319,-1.43135 0.18902,-0.0344 0.36991,0.007 0.54937,0.25255 0.46301,0.54704 1.44266,-0.4874 1.48929,0.45953 0.5239,0.52402 0.35947,-0.79213 0.7877,-0.32307 0.11904,0.0625 0.17579,-0.10037 0.1322,-0.18137 0.23905,-0.4772 0.0983,-0.98501 -0.24849,-1.31123 -0.51486,-0.0455 -1.16504,0.32403 -1.56109,-0.14209 -0.015,-0.23767 0.56363,-0.47753 0.36169,-0.8198 -0.38324,-0.38042 -0.44322,-0.98487 -0.98457,-1.1276 -0.36135,0.052 -0.48894,0.55663 -0.70435,0.70647 -0.55766,-0.24666 0.0368,-0.76423 -0.22141,-1.1658 -0.0503,-0.19364 -0.18405,-0.2692 -0.33237,-0.2754 -0.0404,-0.3067 -0.57848,-0.81058 -0.65503,-0.97077 -0.40971,-0.63902 0.92366,-1.3558 0.28285,-1.97222 -0.0522,-0.16312 -0.21544,-0.27501 -0.49717,-0.33243 -0.0587,-0.0278 -0.11515,-0.0458 -0.1692,-0.0573 -0.0289,-0.0113 -0.057,-0.0238 -0.0853,-0.0361 -1.03981,-0.53291 -2.51397,0.22465 -3.31269,0.63055 z", +3.95515, 2.62566, +"M 3.95505 -0.686011 c -0.15408,-0.23494 -0.0822,-0.95418 -0.51263,-0.59686 -0.008,0.0349 -0.0352,0.0725 -0.0403,0.10697 -0.83055,0.12629 -1.00177,1.38378 -1.97093,1.12551 -0.48091,0.005 -0.94795,-0.32656 -1.45987,-0.33538 -0.37338,-0.52472 -0.57999,-1.00169 -0.26509,-1.59473 0.0936,-0.67218 -1.16382,-0.98056 -0.65939,-0.11679 0.26345,0.50822 0.18968,1.40264 -0.508,0.75758 -0.32954,-0.53085 -0.64802,-1.61561 -1.54771,-1.10898 -0.68429,0.018 -1.46227,0.76829 -0.48678,1.12758 0.43926,0.0751 -0.26701,0.60334 0.20516,0.87695 -0.0159,0.0235 -0.0497,0.0426 -0.0672,0.0656 l 1.56941,0.97152 c -0.002,-0.009 -10e-4,-0.0182 -0.003,-0.0269 0.39897,-0.0917 0.59063,-0.63554 0.87437,-0.0842 0.29559,0.58427 0.85214,0.78099 1.36064,0.36277 0.29091,0.26967 1.59176,0.4144 0.83405,0.98495 -0.96634,0.19424 0.0436,1.30965 0.4563,0.51211 0.65617,-0.49446 1.06992,-1.43769 1.93064,-1.56993 0.3443,-0.30868 -0.18545,-0.98462 0.27493,-1.39681 -0.002,-0.0272 0.0148,-0.0361 0.0155,-0.061 z", +3.39269, 3.51493, +"M 0.0750514 -3.51461 c -0.19846,-0.006 -0.39854,0.0731 -0.58965,0.27905 -0.3796,0.57495 -1.2206,0.87046 -1.87431,0.68161 -0.71429,-0.005 -1.49539,0.87511 -0.60666,1.43299 0.6417,0.38671 1.3579,0.96436 1.49963,1.7415 0.61413,0.69383 -0.14464,1.5326 -0.31522,2.29753 l 0.51263,0.59686 c 0.0171,-0.63284 0.7448,-0.57701 1.00822,-0.58962 0.0858,-1.15842 1.23714,0.33687 1.55236,-0.74983 0.69887,0.1792 0.74695,-1.30546 1.36168,-0.49299 0.62122,0.65999 1.1806,-0.4728 0.35139,-0.62271 -0.4378,0.23119 -0.35205,-0.68673 -0.66301,-0.91157 -0.0951,-0.86591 -0.42699,-1.59301 -0.77256,-2.37608 -0.28776,-0.47507 -0.86916,-1.26771 -1.4645,-1.28674 z", +2.56824, 2.063, +"M -1.65563 -2.06134 c -1.25863,0.0605 -1.00656,1.90514 -0.4826,2.70738 1.27622,-0.20063 1.59649,2.35287 2.91245,1.0399 0.34188,-0.16365 0.38346,-0.31718 0.30757,-0.47967 0.0248,-0.0232 0.0505,-0.0458 0.0754,-0.0689 0.78294,-0.61042 2.07913,-1.20867 0.99887,-2.30315 -0.1618,-0.25964 -0.35631,-0.35126 -0.56606,-0.33394 -0.4303,0.0354 -0.91952,0.5265 -1.3292,0.96373 -0.28645,-0.79722 -0.7443,-1.53257 -1.64403,-1.51297 -0.0978,-0.0128 -0.18852,-0.0162 -0.27243,-0.0128 z", +2.69804, 3.17552, +"M -0.907231 -3.17534 c -0.24929,0.007 -0.46483,0.2028 -0.59435,0.71789 -0.1246,0.75535 -1.2685,1.31142 -0.66913,2.14191 -1.32502,1.15191 0.1607,2.97757 1.02977,3.49106 l 0.1303,-0.11175 0.15128,-0.13697 c 0.8895,-0.21167 1.24411,-0.76409 1.26851,-1.69723 0.19571,-0.87034 1.02336,-1.14446 1.34665,-0.12867 0.20799,-0.56415 1.74212,-1.10319 0.39257,-1.55429 -0.99736,-0.1586 -0.23361,-1.73999 -1.4904,-1.42319 -0.30638,-0.417 -1.01682,-1.31425 -1.56523,-1.29875 z", +2.85984, 5.28311, +"M 2.73793 -5.28207 c -0.015,-0.002 -0.0319,-10e-4 -0.0501,0.002 l -0.34004,0.31678 c -0.17511,0.027 -0.38357,0.16702 -0.5669,0.42116 -0.73686,-0.0649 -1.46563,0.13236 -1.66706,0.13746 -0.67315,0.017 -0.52935,1.98311 -0.49609,2.62775 0.0175,0.11077 0.0314,0.16367 0.0424,0.19378 -0.0163,0.0123 -0.0413,0.0577 -0.0791,0.18656 -0.0357,0.12199 -0.10261,0.35732 -0.14883,0.51521 -0.17169,-0.11412 -0.34298,-0.19051 -0.50125,-0.18604 -0.24929,0.007 -0.46477,0.2027 -0.59428,0.71779 -0.12462,0.75535 -1.2686,1.3115 -0.66921,2.14199 -1.32504,1.15191 0.16084,2.97725 1.02989,3.49074 l 0.13022,-0.11162 0.1509,-0.13694 c 0.8895,-0.21167 1.24425,-0.76392 1.26867,-1.69706 0.19572,-0.87034 1.02339,-1.14446 1.34668,-0.12867 0.20799,-0.56415 1.74228,-1.10333 0.39275,-1.55443 -0.98558,-0.15672 -0.25485,-1.69952 -1.45005,-1.4304 0.0337,-0.19455 0.0813,-0.37702 0.15608,-0.53589 0.30318,-0.62037 1.08029,-1.8405 1.08415,-2.40243 0.005,-0.76342 0.83722,-0.66127 0.91932,-1.45315 0.13685,-0.53732 0.26681,-1.08517 0.0419,-1.11414 z", +2.25069, 2.15736, +"M -1.31572 -2.15659 c -0.1647,-0.007 -0.28795,0.0329 -0.32919,0.13591 -0.0487,0.11989 0.0156,0.32374 0.25373,0.63355 -0.18714,0.21042 -0.36899,0.44338 -0.58703,0.64182 -0.85828,0.33362 0.60076,1.16166 0.42995,1.80145 0.20592,0.53574 0.73787,1.3365 1.35496,0.78031 l 0.16846,0.32091 c 0.59552,-0.0337 1.38631,-0.20816 2.03242,-1.02836 l -0.19119,-0.8568 c -0.137,-0.23584 -0.2603,-0.40707 -0.37311,-0.53743 0.37941,-0.26434 1.13768,-0.0887 0.64751,-0.82579 -0.0527,-0.0367 -0.10821,-0.0708 -0.1633,-0.10542 0.49546,-0.53719 -0.1007,-0.64494 -0.7457,-0.38034 -0.43736,-0.17954 -0.90406,-0.30825 -1.35702,-0.38189 -0.0559,-0.008 -0.10962,-0.0114 -0.16124,-0.0119 -0.0978,-10e-4 -0.18828,0.009 -0.27284,0.0295 -0.24662,-0.12465 -0.50609,-0.20615 -0.70591,-0.21549 z", +3.67275, 3.21569, +"M -0.0460498 -3.21533 c -0.11996,0.001 -0.23781,0.009 -0.32142,0.0129 -0.29093,0.0121 -0.53765,0.0695 -0.3235,0.53536 -0.22627,0.0914 -0.90234,0.55329 -1.04024,-0.0388 -0.31879,-0.0384 -0.77856,0.15926 -0.93379,0.43718 -0.43863,-0.21291 -0.84127,0.042 -0.99891,0.44856 -0.043,0.32893 0.0751,0.60333 0.26046,0.84749 -0.009,0.3245 0.1084,0.47004 0.30022,0.49558 l -0.38343,0.45217 c 0.29165,0.62004 0.78181,0.43344 1.16014,0.0506 0.0781,0.0553 0.15775,0.10901 0.23977,0.16071 -0.53198,0.40496 -0.7605,0.97563 0.31369,1.28933 l 0.72294,-0.49765 c 0.0642,-0.0825 0.11237,-0.15383 0.16278,-0.22686 0.0327,0.0105 0.0654,0.0181 0.0982,0.0279 0.16068,0.39255 0.77761,0.90608 0.66302,1.33532 0.20593,0.53574 0.73787,1.3365 1.35496,0.78032 l 0.16846,0.32091 c 0.59552,-0.0337 1.38581,-0.20816 2.03192,-1.02837 l -0.19069,-0.85679 c -0.137,-0.23584 -0.2608,-0.40707 -0.37361,-0.53743 0.37941,-0.26434 1.13818,-0.0887 0.64801,-0.82579 -0.0527,-0.0367 -0.10871,-0.0708 -0.16383,-0.10542 0.49549,-0.5372 -0.10067,-0.64494 -0.74567,-0.38034 -0.43736,-0.17954 -0.90406,-0.30825 -1.35702,-0.38189 -0.0559,-0.008 -0.10962,-0.0114 -0.16124,-0.0119 -0.0978,-0.001 -0.18828,0.009 -0.27284,0.0294 -0.0795,-0.0402 -0.15954,-0.0736 -0.23926,-0.10387 0.11316,-0.10188 0.2712,-0.17912 0.47128,-0.21652 0.0483,-0.28576 0.18888,-1.14252 -0.003,-1.27021 -0.32433,-0.21564 -0.36465,-0.44676 -0.55502,-0.44183 -0.10408,0.003 -0.0796,-0.25731 -0.19894,-0.27234 -0.0916,-0.0237 -0.21338,-0.0292 -0.33332,-0.0279 z", +4.37172, 2.82177, +"M 4.15107 -2.76363 c -0.12588,-0.061 -0.31491,-0.0778 -0.59006,-0.0321 -0.39183,1.50176 -2.22417,-0.002 -2.85969,1.25239 -0.22059,0.57212 0.36731,0.82629 -0.0102,1.2242 -0.47996,0.50597 -1.83247,1.95136 -2.83873,1.05509 -1.37002,-0.71385 -1.45547,1.3313 -2.22411,1.81568 0.29352,0.31468 0.80913,0.29068 1.2014,0.23962 1.08757,-0.8648 2.32743,0.27342 3.58569,-0.0204 0.84516,-0.67246 1.49671,-1.57107 2.62485,-1.94719 0.46688,-0.61992 1.62754,-0.4097 1.06677,-1.52838 -0.0528,-0.66878 0.58863,-1.79182 0.0441,-2.05885 z", +4.37157, 4.1273, +"M 0.620322 -4.12594 c -0.55557,0.0573 -1.03581,1.84758 -1.54823,2.21485 0.3837,0.6876 0.283,1.30919 0.0419,1.9172 -0.42523,0.16787 -0.86971,0.17674 -1.26193,-0.1726 -1.37001,-0.71385 -1.45499,1.33153 -2.22363,1.81591 0.29352,0.31468 0.8087,0.29032 1.20097,0.23926 0.48778,-0.38788 1.00761,-0.36748 1.54461,-0.25941 -0.14566,0.3988 -0.2277,0.81069 -0.15658,1.24953 0.36957,0.23628 0.50355,0.43109 0.52038,0.60462 l 0.91723,0.64388 c 0.68612,-0.27271 2.29931,-0.23369 1.41335,-1.51153 0.38381,-0.70654 1.05535,-1.29742 0.97981,-2.16938 0.29503,-0.21386 0.61597,-0.39961 0.99218,-0.52503 0.46689,-0.61992 1.62738,-0.40991 1.06659,-1.52859 -0.0528,-0.66878 0.58846,-1.79176 0.0439,-2.05879 -0.12586,-0.061 -0.31498,-0.0777 -0.59012,-0.032 -0.31404,1.2036 -1.55213,0.47891 -2.35903,0.78858 -0.16962,-0.30286 -0.26535,-0.61458 -0.18346,-0.94051 -0.13758,-0.21015 -0.26969,-0.28917 -0.39791,-0.27595 z", +2.40615, 2.34567, +"M 1.22057 -2.34541 c -0.11996,0.001 -0.23783,0.009 -0.32144,0.0129 -0.29094,0.0121 -0.53763,0.0695 -0.32348,0.53537 -0.22627,0.0914 -0.90236,0.55323 -1.04026,-0.0388 -0.3188,-0.0384 -0.77856,0.15925 -0.9338,0.43718 -0.43862,-0.21292 -0.84126,0.042 -0.9989,0.44855 -0.043,0.32893 0.0751,0.60334 0.26045,0.8475 -0.009,0.3245 0.10843,0.47003 0.30025,0.49557 l -0.38343,0.45217 c 0.29165,0.62004 0.78179,0.4334 1.16012,0.0506 0.0781,0.0553 0.15777,0.10901 0.23979,0.16071 -0.53197,0.40497 -0.76052,0.97563 0.31366,1.28933 l 0.72295,-0.49764 c 0.0642,-0.0825 0.11239,-0.15383 0.1628,-0.22686 0.21412,0.0689 0.42973,0.123 0.64233,0.15606 l 0.0419,-0.0403 c 0.16619,-0.0829 0.52523,-0.15309 0.76946,-0.27698 0.23728,0.032 0.30295,-0.10345 0.24339,-0.30644 -0.006,-0.0574 -0.03,-0.12095 -0.0847,-0.19327 -2.9e-4,-2.4e-4 -7.2e-4,-2.8e-4 -10e-4,-5.2e-4 -0.0729,-0.13224 -0.17968,-0.27385 -0.3147,-0.40928 -0.1447,-0.38814 0.092,-0.78214 0.63511,-0.88366 0.0483,-0.28576 0.18899,-1.14252 -0.003,-1.27021 -0.32432,-0.21564 -0.36462,-0.44676 -0.55499,-0.44184 -0.10408,0.003 -0.0796,-0.25731 -0.19896,-0.27233 -0.0916,-0.0237 -0.21336,-0.0292 -0.3333,-0.0279 z", +3.50783, 3.58322, +"M 2.96957 -3.58221 c -0.054,-0.004 -0.10962,0.004 -0.16682,0.0204 -0.50287,0.14531 -1.11843,0.96574 -1.59686,0.75172 -0.10443,0.2409 -0.0893,0.42169 -0.004,0.56879 -0.16015,0.0374 -0.31561,0.12717 -0.45888,0.27949 -0.18095,-0.16288 -0.36634,-0.32735 -0.52012,-0.46987 -0.20437,-0.0568 -0.39359,-0.0485 -0.5582,7.6e-4 -0.3902,0.11676 -0.63677,0.46713 -0.60175,0.74583 -0.82773,-0.51376 -1.62373,-1.30541 -2.57037,-1.06536 h -4e-4 c 0.26652,0.79551 1.77909,1.50405 1.31935,2.59942 -0.29573,1.43857 0.96759,1.36306 1.9262,0.86162 -0.19051,0.27421 -0.33048,0.55606 -0.0695,0.87617 0.2907,0.72136 0.51069,1.5495 1.19922,1.99646 0.20081,-0.39583 0.52596,-0.80888 0.35365,-1.27772 -0.24696,-0.37352 -0.82161,-0.82316 -0.85651,-1.19804 0.67455,0.0369 1.28244,0.50499 1.61609,-0.44907 0.0895,-0.17713 0.12714,-0.35251 0.13189,-0.52562 0.5227,-0.002 0.92832,-0.16026 0.80786,-0.83572 -0.02,-0.11225 -0.0568,-0.22688 -0.10279,-0.34112 0.29762,0.56825 0.4526,0.29332 0.43494,-0.27949 0.56932,-0.62085 -0.0145,-1.20088 0.14248,-1.85712 -0.11901,-0.28003 -0.26387,-0.39114 -0.4255,-0.40157 z m -3.15799,2.26732 c -0.008,0.02 -0.0114,0.0391 -0.0165,0.0585 -0.0297,-0.0163 -0.0596,-0.0336 -0.0906,-0.0557 0.0354,-6.9e-4 0.0686,8.4e-4 0.10709,-0.003 z", +3.7615, 3.60448, +"M 2.71615 -3.60346 c -0.054,-0.004 -0.10972,0.004 -0.1669,0.0202 -0.32652,0.0944 -0.70003,0.46997 -1.05317,0.6656 -0.0392,-0.0864 -0.0913,-0.17253 -0.16949,-0.2589 -0.13989,0.11483 -0.28059,0.23472 -0.44546,0.30385 -0.37044,0.0914 -0.55509,0.29917 -0.72657,0.58653 -0.0611,-0.0552 -0.13033,-0.11623 -0.185,-0.16691 -0.20439,-0.0568 -0.39351,-0.0488 -0.55811,5.1e-4 -0.35949,0.10757 -0.59423,0.413107 -0.60203,0.678517 -0.0136,0.0138 -0.0277,0.0274 -0.0398,0.0413 -0.81341,-0.513967 -1.59923,-1.275407 -2.53061,-1.039227 h -5e-4 c 0.26651,0.795517 1.77903,1.503967 1.31929,2.599337 -0.29573,1.43857 0.9679,1.3634 1.92651,0.86196 -0.19053,0.27421 -0.33076,0.5558 -0.0698,0.87592 0.012,0.0298 0.0233,0.0613 0.0351,0.0915 -0.14874,0.19134 -0.58581,0.55204 -0.12969,0.59428 0.55962,-0.15196 0.50268,0.68369 0.64232,1.02681 0.27718,0.29651 0.87279,0.45861 1.25006,0.19069 0.25513,-0.26582 0.48609,-6.5e-4 0.76999,-0.005 0.16695,-0.18991 0.32821,-0.0961 0.49556,-0.0584 0.71837,-0.71386 0.97589,-1.56297 1.28365,-2.4846 -0.70366,-0.43516 -0.773,-0.65102 -0.81441,-1.42007 l -0.0104,-0.33796 c 0.0471,-0.0983 0.0696,-0.27697 0.0625,-0.50798 0.56933,-0.62085 -0.0149,-1.200497 0.14211,-1.856747 -0.11901,-0.28003 -0.26366,-0.39109 -0.42529,-0.40152 z", +2.73778, 2.64431, +"M -1.85179 2.64296 c 0.2123,0.0405 0.70405,-0.84096 1.03766,-0.92501 0.33497,0.30812 0.76833,0.15488 0.79944,-0.33693 -0.20608,-0.37546 0.3914,-0.98771 0.45321,-0.40411 0.57615,0.94326 1.00706,-0.63268 1.58337,-0.71623 0.18095,0.0986 0.3791,0.08 0.57309,0.10232 0.38124,-1.55226 -0.0574,-1.82885 -0.65008,-1.86604 0.0889,-0.23201 0.18206,-0.4544 0.29609,-0.63924 -0.83934,-0.59743 -2.12622,-0.83961 -2.63705,0.29611 -0.0335,0.0842 -0.0746,0.16672 -0.12041,0.24856 -0.21743,0.0386 -0.42992,0.0931 -0.60772,0.19482 -0.90374,-0.25609 -0.4962,0.82188 -0.69969,1.33377 -0.68622,0.72594 -1.23518,1.47159 -0.69607,2.40967 0.21852,-0.0632 0.39881,-0.18586 0.55965,-0.33848 0.002,0.0764 0.006,0.15365 0.006,0.22945 -0.008,0.28213 0.0321,0.39784 0.10282,0.41134 z", +2.73778, 2.64431, +"M -1.85179 2.64296 c 0.2123,0.0405 0.70405,-0.84096 1.03766,-0.92501 0.33497,0.30812 0.76833,0.15488 0.79944,-0.33693 -0.20608,-0.37546 0.3914,-0.98771 0.45321,-0.40411 0.57615,0.94326 1.00706,-0.63268 1.58337,-0.71623 0.18095,0.0986 0.3791,0.08 0.57309,0.10232 0.38124,-1.55226 -0.0574,-1.82885 -0.65008,-1.86604 0.0889,-0.23201 0.18206,-0.4544 0.29609,-0.63924 -0.83934,-0.59743 -2.12622,-0.83961 -2.63705,0.29611 -0.0335,0.0842 -0.0746,0.16672 -0.12041,0.24856 -0.21743,0.0386 -0.42992,0.0931 -0.60772,0.19482 -0.90374,-0.25609 -0.4962,0.82188 -0.69969,1.33377 -0.68622,0.72594 -1.23518,1.47159 -0.69607,2.40967 0.21852,-0.0632 0.39881,-0.18586 0.55965,-0.33848 0.002,0.0764 0.006,0.15365 0.006,0.22945 -0.008,0.28213 0.0321,0.39784 0.10282,0.41134 z", +2.72104, 3.39079, +"M 0.286178 -3.39079 c -0.14007,0.11497 -0.28086,0.23514 -0.44596,0.30437 -0.43748,0.10788 -0.61692,0.37041 -0.8201,0.74518 -0.20775,0.47047 -0.48958,-0.22623 -0.70953,-0.14625 -0.17844,0.25772 -0.66421,0.48419 -0.68522,0.74259 0.48728,-0.0488 0.29403,0.53326 0.005,0.63149 -0.19034,0.18451 -0.59938,0.72542 -0.14417,0.90072 0.44725,-0.12109 0.48747,0.26394 0.52038,0.58136 -0.074,-0.44637 0.62326,-0.57247 0.80926,-0.27647 -0.19566,0.38226 -0.23154,0.87394 -0.36896,1.30586 -0.1065,0.17514 -0.65649,0.59395 -0.16746,0.63924 0.55962,-0.15196 0.50271,0.68369 0.64236,1.02681 0.27718,0.29651 0.87278,0.45861 1.25005,0.19069 0.25514,-0.26582 0.48606,-0.001 0.76996,-0.005 0.16695,-0.18991 0.32824,-0.0961 0.49559,-0.0584 0.71837,-0.71386 0.97589,-1.56297 1.28366,-2.4846 -0.70366,-0.43516 -0.77306,-0.65079 -0.81447,-1.41984 l -0.0209,-0.66544 c -0.14473,-0.20288 -0.29131,-0.40206 -0.49768,-0.48162 -0.51565,0.12706 -0.62662,-0.15055 -0.84926,-0.31646 -0.0172,-0.40469 0.11379,-0.80938 -0.25281,-1.21407 z", +2.54738, 3.09564, +"M -2.54738 -1.21382 c 0.12657,0.31725 -0.0579,0.48889 0.29639,1.02693 0.28022,0.42555 1.10094,1.23068 1.25829,1.46812 0.39733,0.5996 0.15592,0.35314 -0.13001,1.1135 l 0.41975,0.48888 c 0.0197,-0.0589 0.63189,-0.11044 0.65209,-0.17001 0.0222,0.0431 0.0455,0.0859 0.0661,0.12919 0.0877,0.19747 0.15333,0.26483 0.2067,0.25115 0.16015,-0.0429 0.20981,-0.81511 0.41291,-0.98341 0.33369,0.10267 0.58274,-0.14635 0.44182,-0.49713 -0.2667,-0.19187 -0.0552,-0.81306 0.18034,-0.42943 0.71052,0.46274 0.48797,-0.77085 0.8594,-1.01906 0.15785,0.008 0.28929,-0.0697 0.43098,-0.11834 -0.24882,-1.20063 -0.644,-1.24748 -1.06662,-1.07745 -0.0152,-0.19 -0.0245,-0.3749 -0.006,-0.54054 -0.15658,-0.0274 -0.32065,-0.0374 -0.48318,-0.0305 l 0.0367,-0.18293 c -0.41522,-0.73638 -1.14845,-2.2421 -2.38538,-0.50798 -0.386,0.22163 0.0136,0.52023 -0.16174,0.80202 -0.29782,0.28407 -0.20672,-0.38153 -0.40463,-0.14883 -0.23569,0.10251 -0.42783,0.26499 -0.62375,0.42581 z", +4.16689, 3.81427, +"M -1.95926 -3.81051 c -0.29384,0.0315 -0.63098,0.25701 -1.01751,0.79892 -0.386,0.22163 0.0136,0.52023 -0.16173,0.80202 -0.29785,0.28407 -0.20672,-0.38153 -0.40463,-0.14883 -0.23569,0.10251 -0.42783,0.265 -0.62376,0.42582 0.12658,0.31725 -0.0582,0.48929 0.29612,1.02733 0.0583,0.0886 0.14341,0.19507 0.23771,0.30799 -0.0747,9e-4 -0.14412,0.0272 -0.19894,0.0687 h -5.3e-4 c -0.17727,0.13413 -0.20177,0.41817 0.24545,0.45268 -0.39825,0.48749 0.43336,0.66351 0.60359,1.13223 -0.0301,0.59814 0.20492,1.21839 -0.0532,1.81385 -0.21561,0.33237 0.23479,0.51094 0.38809,0.76015 0.0564,0.0501 0.0678,0.1023 0.10335,0.154 h 5.3e-4 c 0.4419,0.12956 0.9933,-0.19327 1.50844,-0.36587 0.76589,-0.53181 1.53929,-1.25257 2.29753,-1.59473 0.2199,0.13691 0.43069,0.36556 0.6263,0.4749 0.45749,0.20053 0.51117,0.84887 1.06042,0.88005 0.3851,0.004 0.70237,-0.18814 0.91467,-0.51573 -0.35343,-0.19801 -0.27543,-0.7836 0.0424,-1.07745 0.47445,-0.42372 0.22762,-1.0411 -0.13642,-1.4304 -0.40209,-0.32194 0.51559,-0.78393 -0.0935,-0.79737 -0.15158,-0.14276 -0.26191,-0.30716 -0.3855,-0.45837 l -0.23204,0.0605 c -0.52811,0.011 -1.14326,-0.0144 -1.2087,0.19172 l -0.31109,0.56431 c -0.38256,0.0826 -0.41923,0.31447 -1.16274,0.24132 -0.0683,0.071 -0.12409,0.1551 -0.17259,0.24754 l -0.003,-0.004 c 0.0758,-0.27877 0.11591,-0.63338 0.29712,-0.75448 0.15785,0.008 0.2893,-0.0697 0.43098,-0.11834 -0.24881,-1.20062 -0.64397,-1.24748 -1.06658,-1.07745 -0.0152,-0.19 -0.0242,-0.37489 -0.006,-0.54053 -0.15658,-0.0274 -0.32065,-0.0374 -0.48319,-0.0305 l 0.0367,-0.18294 c -0.28546,-0.50626 -0.72144,-1.37616 -1.36787,-1.3069 z", +3.3826, 3.20591, +"M 0.917115 -3.20545 c -0.0393,0.67856 -0.8055,0.38483 -1.10476,0.76992 0.21062,0.50964 -0.42472,0.8769 -0.74454,1.18986 -0.0806,-0.39166 -0.0452,-0.8526 -0.44329,-0.91195 -0.65614,0.0726 -0.81839,-0.6789 -1.28317,-0.87078 -0.2656,0.13569 -0.49393,0.3231 -0.72396,0.51189 0.16808,0.42128 -0.0773,0.64903 0.39322,1.36349 0.3721,0.56508 1.46193,1.63419 1.67087,1.94948 0.52763,0.79619 0.20746,0.4691 -0.17223,1.47876 l 0.55718,0.64914 c 0.0262,-0.0782 0.83916,-0.14666 0.86601,-0.22576 0.0295,0.0572 0.0604,0.11406 0.0878,0.17155 0.11646,0.26222 0.20361,0.35166 0.27446,0.33349 0.21267,-0.057 0.27862,-1.08235 0.54829,-1.30583 0.44311,0.13633 0.77382,-0.19433 0.5867,-0.66013 -0.35415,-0.25477 -0.0733,-1.07964 0.23947,-0.57022 0.9435,0.61446 0.64796,-1.0236 1.14116,-1.35319 0.2096,0.0106 0.38415,-0.0925 0.57228,-0.15714 -0.33038,-1.59428 -0.85513,-1.65649 -1.41632,-1.43072 -0.017,-0.21332 -0.024,-0.41843 -0.012,-0.61071 -0.22056,0.0324 -0.42912,0.0689 -0.60935,0.12495 -0.11459,-0.34405 -0.26659,-0.45533 -0.42751,-0.44603 z", +3.6319, 4.78495, +"M 0.896993 -4.78491 c -1.04618,0.86919 1.22964,1.02801 0.62706,2.09804 -0.0111,0.14066 -0.0168,0.27728 -0.0167,0.40806 -0.33465,0.21103 -0.62095,0.44688 -0.76564,0.63005 -0.40971,0.0176 -0.98566,0.24842 -1.41538,0.56247 -0.0885,-0.0278 -0.17012,-0.0331 -0.23481,-0.009 l -4.4e-4,-4.3e-4 c -0.10214,0.0385 -0.1614,0.15187 -0.14414,0.36058 -0.0621,0.0771 -0.11487,0.15557 -0.14971,0.23526 -0.0962,-0.007 -0.18664,0.003 -0.26946,0.0282 v -4.3e-4 c -0.51314,0.15257 -0.75518,0.85767 -0.51544,1.44917 0.0468,0.13673 0.0411,0.38968 0.0235,0.67624 -0.563,0.31662 -0.99981,0.90929 -1.60573,1.11511 0.0839,0.86303 -0.5451,2.78068 0.94615,1.68955 l 0.27419,-0.26605 c 0.59919,-0.18144 1.14669,-0.60514 1.40596,-1.11211 0.70056,-0.69037 0.4631,-1.79139 0.86788,-2.69387 0.38804,-0.19262 0.71359,-0.58299 1.22675,-0.0295 0.503,0.48469 0.58214,-0.85407 0.69164,-1.07533 0.24966,-0.71685 1.63714,-0.11067 1.72634,-0.99534 0.0961,-0.14176 0.083,-0.33963 -0.0458,-0.59669 -0.0144,-0.0633 -0.0351,-0.11846 -0.0594,-0.1681 -0.009,-0.0297 -0.0165,-0.0595 -0.0243,-0.0894 -0.22286,-1.14696 -1.72872,-1.83888 -2.54117,-2.21652 z m -1.97015,4.93649 c 0.004,0.004 0.009,0.008 0.0133,0.0124 -0.0133,0.047 -0.0288,0.0941 -0.044,0.14115 0.009,-0.0514 0.0193,-0.10257 0.0308,-0.15356 z", +2.20024, 4.20283, +"M 0.680372 -4.20263 c -0.17134,-0.003 -0.35314,0.0281 -0.51107,0.0956 h -0.002 c -0.37912,0.16215 -0.6214,0.53304 -0.25527,1.13533 0.0428,0.30239 0.0412,0.55368 -5.3e-4,0.76378 -0.20661,0.20366 -0.36107,0.43947 -0.42891,0.67541 -0.25368,0.17815 -0.60508,0.27842 -1.04386,0.33693 -0.81735,0.77798 1.48963,1.90805 0.56173,2.45463 -0.32718,0.0973 -0.67947,0.11365 -0.9953,0.0207 -0.64842,0.99087 0.36237,2.72148 1.30794,2.69131 l 0.25683,-0.16433 0.13385,-0.19999 c 0.0466,-0.0443 0.0923,-0.0929 0.13795,-0.14159 0.17233,0.17619 0.32211,0.35812 0.41807,0.55397 0.56925,-0.35075 1.47415,0.57288 1.80713,-0.0207 -1.12112,-0.65447 -1.73331,-1.46106 -0.64026,-2.46807 -0.1388,-0.15461 -0.33557,-0.2819 -0.49663,-0.40411 0.0189,-0.22272 0.0125,-0.44358 -0.0258,-0.65784 0.0824,-0.0552 0.18539,-0.11327 0.31935,-0.17622 0.92186,-0.47154 0.76654,-2.17728 0.97665,-2.5032 -0.36297,-0.32872 -0.97897,0.11256 -1.34102,-0.54364 -0.0805,0.02 -0.16004,0.0479 -0.23873,0.0796 0.0343,-0.20274 0.15489,-0.40552 0.40256,-0.60616 0.59182,-0.58976 0.17092,-0.91141 -0.34314,-0.92139 z", +2.88699, 5.39383, +"M 1.3671 -5.39363 c -0.17122,-0.003 -0.3528,0.0282 -0.51057,0.0956 h -0.003 c -0.37912,0.16215 -0.62142,0.53304 -0.25529,1.13533 0.0428,0.30239 0.0412,0.55368 0,0.76378 -0.20662,0.20366 -0.36108,0.43947 -0.42892,0.67541 -0.25368,0.17815 -0.6051,0.27842 -1.04386,0.33693 -0.81735,0.77798 1.4896,1.90805 0.56171,2.45463 -0.32718,0.0973 -0.67945,0.11362 -0.99528,0.0207 -0.14761,0.22555 -0.20556,0.49003 -0.20154,0.76275 -0.051,0.0146 -0.10085,0.0324 -0.14729,0.0579 -0.23484,0.6226 -0.50334,1.23094 -0.7865,1.83296 -0.19645,0.25916 -0.14105,0.63084 -0.33951,0.83613 -0.11512,0.138 -0.11041,0.31176 -0.0977,0.48472 l 1.21801,1.32705 c 0.11266,-0.0498 0.24308,-0.0702 0.37931,-0.0165 0.29117,0.0276 0.68913,0.0748 0.86971,-0.23874 0.30268,-0.33688 0.72999,0.11684 1.03198,-0.17725 0.082,-0.27859 0.31242,-0.40815 0.41085,-0.68988 0.33589,-0.752 0.92244,-0.0445 1.15649,-0.42471 0.35317,-0.13097 0.0367,-1.3743 -0.16174,-1.55863 0.0322,-0.0731 0.0626,-0.14742 0.0972,-0.21911 0.2109,0.004 0.28993,-0.14967 0.11834,-0.38292 -0.0568,-0.22605 0.26795,-0.75271 -0.0594,-0.80564 -0.2096,0.24628 -0.25599,0.65901 -0.5855,0.79892 -0.1397,-0.40155 -0.0145,-0.84498 0.51882,-1.33635 -0.1388,-0.15462 -0.33554,-0.2819 -0.49659,-0.40412 0.0188,-0.22271 0.0124,-0.44358 -0.0259,-0.65784 0.0824,-0.0552 0.18539,-0.11326 0.31938,-0.17621 0.92183,-0.47154 0.76655,-2.17729 0.97668,-2.50321 -0.36298,-0.32872 -0.97896,0.11256 -1.34101,-0.54364 -0.0805,0.02 -0.16005,0.0479 -0.23874,0.0796 0.0343,-0.20274 0.15489,-0.40552 0.40254,-0.60616 0.59163,-0.58956 0.17121,-0.9112 -0.34261,-0.92139 z", +2.2926, 5.13722, +"M 0.802274 -5.13667 c -0.15648,0.008 -0.31396,0.11235 -0.39378,0.36329 0.17158,0.46045 -0.71247,0.26413 -0.98288,0.53433 -0.18795,-0.0953 -0.37721,-0.18365 -0.56276,-0.25735 -0.30393,-0.35352 -0.57627,-0.46456 -0.78031,-0.41599 h -0.001 c -0.34007,0.0809 -0.48919,0.60594 -0.27337,1.19424 1.00303,1.38655 -0.11896,2.78412 0.99219,3.28301 0.18788,-0.0184 0.35102,-0.008 0.49866,0.0202 0.0272,0.0107 0.055,0.0168 0.0842,0.017 1.09791,0.28456 1.07577,1.83267 1.1281,2.82101 1.29392,0.57385 -0.73445,2.82023 1.25884,2.61276 0.17748,0.17897 0.47238,0.11556 0.51522,-0.14728 0.081,-1.48014 -0.80518,-2.85605 -0.76896,-4.31808 0.16182,-0.1731 0.22826,-0.33544 0.2403,-0.49299 0.17579,-0.13499 0.36803,-0.25536 0.53588,-0.29662 -0.45833,-0.34903 -0.47617,-0.81306 -0.45474,-1.07591 -1.13773,-0.23427 0.49343,-1.18353 -0.54364,-1.63607 0.26771,-0.66998 -1.19856,-0.90889 -0.31369,-1.41387 0.50499,-0.3651 0.16598,-0.81 -0.17827,-0.79168 z", +4.57828, 3.5071, +"M 2.91251 -3.50687 c -0.4486,0.0106 0.45675,0.54041 0.18913,0.76585 -0.86641,-0.29492 -1.26553,1.09463 -1.96578,0.93793 -0.86302,0.0543 -1.79475,0.32429 -2.49597,0.83405 -0.39846,-0.0495 -0.7705,-0.009 -1.1157,0.12454 -0.006,0.0507 0.007,0.10957 -0.003,0.15813 0.0966,0.98514 -1.0613,0.70185 -1.47535,0.23151 -0.37552,-0.57285 -1.03049,0.23261 -0.27905,0.28888 -0.31933,0.39262 0.19955,0.57156 0.46199,0.88831 -0.002,0.0106 -0.005,0.0172 -0.006,0.0284 0.0115,0.11487 0.0542,0.20711 0.11732,0.28474 0.007,0.52372 0.17613,1.06164 -0.0476,1.58079 -0.20304,0.31453 0.22357,0.4826 0.36896,0.71778 0.0533,0.0472 0.064,0.0964 0.0977,0.14521 h 5e-4 c 0.41788,0.12151 0.93829,-0.18412 1.42473,-0.3483 0.40148,-0.2801 0.80497,-0.61424 1.20716,-0.9126 0.50226,-0.12855 1.03791,-0.70742 1.45571,-0.97152 -0.39362,-0.88195 1.08802,-0.72117 1.19787,-1.3348 -0.12419,-0.6673 -0.7335,-1.91974 0.42995,-1.96474 0.86471,-0.32419 0.78534,1.59558 1.21698,0.39687 -0.25257,-0.73375 0.38536,-0.64026 0.82942,-0.33848 0.28241,-0.45436 -0.55153,-1.06703 -1.10898,-1.37252 v 5.1e-4 c -0.0792,-0.0443 -0.15266,-0.0811 -0.21706,-0.1111 -0.12671,-0.0221 -0.21858,-0.031 -0.28266,-0.0295 z", +3.74688, 2.41634, +"M 2.72883 -2.41634 -0.35677,0.016 c -0.33291,0.36885 -0.63684,0.43941 -0.88624,0.44063 -0.0292,-0.0173 -0.0593,-0.0354 -0.0868,-0.0506 v 3.3e-4 c -0.051,-0.0285 -0.0983,-0.0522 -0.13977,-0.0716 -0.0816,-0.0142 -0.14078,-0.02 -0.18205,-0.019 -0.10932,0.003 -0.0935,0.0532 -0.0413,0.1228 -0.0466,0.007 -0.0874,0.0211 -0.1198,0.0519 -0.0676,0.10644 -0.089,0.22694 -0.0958,0.35209 -0.32395,0.17106 -0.55217,0.6454 -0.88722,0.57042 -0.5558,0.035 -1.15583,0.20884 -1.6074,0.53712 -0.25661,-0.0319 -0.49621,-0.006 -0.7185,0.0802 -0.004,0.0326 0.005,0.0706 -0.002,0.10184 0.0622,0.63443 -0.68347,0.45199 -0.95012,0.14909 -0.24183,-0.36891 -0.66363,0.14979 -0.17971,0.18604 -0.20564,0.25284 0.12851,0.36808 0.29752,0.57207 -0.001,0.007 -0.003,0.0111 -0.004,0.0183 0.007,0.074 0.0349,0.13337 0.0755,0.18337 0.005,0.33727 0.1135,0.68368 -0.0306,1.01801 -0.13076,0.20256 0.14398,0.3108 0.23761,0.46226 0.0343,0.0304 0.0412,0.0621 0.0629,0.0935 h 3.2e-4 c 0.26912,0.0782 0.60427,-0.11857 0.91752,-0.2243 0.25856,-0.18038 0.5184,-0.39557 0.77741,-0.58771 0.32345,-0.0828 0.66843,-0.45558 0.93749,-0.62566 -0.18482,-0.41411 0.27077,-0.47225 0.55943,-0.62599 0.042,0.26188 -0.16431,0.57971 -0.0466,0.81602 -0.0361,0.3214 0.2697,0.38876 0.29186,0.65727 -0.0155,0.41805 0.31928,0.10309 0.49155,0.006 0.24347,0.16794 0.51027,0.0323 0.71949,-0.1644 0.15749,-0.44026 0.53019,-0.15638 0.81901,-0.0952 0.098,-0.20391 0.35342,-0.32496 0.4526,-0.4992 -0.0531,-0.28513 0.23897,-0.57539 0.41732,-0.72149 v -3.4e-4 c 0.3295,-0.64851 0.11566,-1.00699 -0.21897,-1.51055 l 0.28918,-0.44994 0.22499,-0.29984 c -0.18304,-0.14669 -0.3661,-0.12842 -0.54912,-0.0343 l -0.38038,0.11848 c 0.28124,-0.43579 0.14347,-0.51087 -0.0885,-0.57341 z", +1.5426, 3.75375, +"M -0.18215 -3.74938 c -0.43006,0.0954 -0.0238,1.66304 -0.29143,2.06565 -1.23283,0.67467 0.70648,1.73509 -0.66571,2.29879 -1.27771,1.27642 0.87232,1.5933 1.05811,1.42669 -1.72666,0.27299 0.54523,3.0984 0.51438,0.84809 0.0778,-1.31836 1.51452,-1.87061 0.99737,-3.31344 -0.0269,-1.19813 0.0509,-2.86032 -1.37276,-3.26853 -0.10038,-0.0537 -0.17819,-0.0707 -0.23966,-0.0572 z", +2.6102, 2.40582, +"M -2.60391 1.07532 1.21829,1.32714 c 0.11265,-0.0498 0.24287,-0.0704 0.37911,-0.0167 0.29115,0.0276 0.68939,0.0748 0.86997,-0.23871 0.30266,-0.33688 0.72982,0.11701 1.03183,-0.17708 0.082,-0.27859 0.31221,-0.40824 0.41064,-0.68997 0.0829,-0.35912 0.3014,-0.69002 0.49691,-1.00001 0.25988,-0.36573 0.40154,-0.79981 0.5954,-1.20228 0.21088,0.004 0.29,-0.14987 0.11841,-0.38313 -0.0568,-0.22605 0.26786,-0.75294 -0.0595,-0.80587 -0.21044,0.24728 -0.25622,0.66273 -0.58937,0.80098 -0.0881,0.24739 -0.32811,0.21877 -0.5183,0.099 -0.43381,-0.0984 -0.16894,-0.56282 -0.0503,-0.81595 -0.18037,-0.10226 -0.47473,0.10933 -0.66436,0.16038 0.14099,0.42689 -0.26992,0.60149 -0.59482,0.72943 -0.10138,0.24534 -0.36733,-0.0479 -0.17905,-0.12239 0.19862,-0.22162 0.39983,-0.47805 0.66131,-0.63217 0.23857,-0.24684 -0.1743,-0.27544 -0.34069,-0.2571 -0.28559,0.11508 -0.52696,7.5e-4 -0.74386,-0.19182 -0.1358,-0.11552 -0.22022,-0.0715 -0.27824,0.0899 -0.15588,0.0841 -0.36986,0.0793 -0.5395,0.17231 -0.23485,0.6226 -0.50305,1.23123 -0.78622,1.83325 -0.19645,0.25916 -0.14117,0.63063 -0.33965,0.83592 -0.11511,0.138 -0.11073,0.31194 -0.098,0.4849 z", +3.83978, 2.30066, +"M 1.89988 -2.28596 c -0.46473,-0.0533 -0.93451,0.0301 -1.2983,0.38777 -0.61395,-0.10651 -1.14946,0.60908 -1.8877,0.45323 -0.65836,-0.53157 -1.19607,0.74513 -1.84876,0.2517 -0.22541,0.36322 -0.81294,0.89409 -0.68754,1.46714 0.20541,0.12631 0.2374,0.23071 0.21384,0.31715 l 0.28852,0.42359 5.18412,1.28604 c -0.12156,-0.38789 0.57265,-0.65546 1.06815,-0.66503 0.3002,-0.42158 1.17579,-0.37128 0.82666,-1.04765 -0.64248,0.006 -0.4043,-0.75074 -0.0849,-0.96787 z", +2.48198, 2.67999, +"M -0.947181 2.42314 c 0.18893,-0.12837 0.39015,-0.1443 0.5237,0.25685 0.51028,-0.15853 1.30811,-0.11944 1.84667,-0.42769 1.22161,0.34616 0.47447,-1.31052 0.96133,-1.80427 0.18748,-0.84884 0.0458,-1.7551 0.0512,-2.62474 0.0372,-1.37538 -0.84814,0.48939 -1.39027,0.62596 -0.40821,-0.37552 -0.93592,-0.18917 -0.97385,0.41022 0.25116,0.45758 -0.477,1.20377 -0.55234,0.49252 -0.7022,-1.14958 -1.22788,0.77102 -1.93025,0.87284 -0.42731,0.88954 1.20329,1.9184 1.46381,2.19831 z", +4.26056, 3.08976, +"M -2.80517 -3.08919 c -0.26757,0.53645 -1.24706,-0.0831 -1.33583,0.28009 0.54354,0.28297 0.25361,0.49804 -0.0894,0.49764 -0.15417,0.30689 0.31539,0.50952 0.66921,0.73174 -0.43301,0.39009 -0.69014,0.69733 -0.58912,0.83612 0.13288,0.3976 0.66614,0.90708 0.14624,0.88781 -0.3356,0.1386 0.28826,0.9763 0.62944,1.30069 0.0448,-0.0159 0.0277,0.18537 0.2382,0.28009 0.59182,-0.12048 0.63855,0.74505 1.24386,0.67799 0.29986,0.0447 0.27308,0.39182 0.33383,0.68678 0.2408,-0.23569 0.71932,-0.51227 0.5607,-0.89607 0.24093,-0.31002 0.88424,-0.0359 0.83043,-0.6966 0.27241,-0.35349 0.87897,-0.0301 1.26195,-0.22117 0.25652,0.75949 1.11287,0.11487 0.97616,-0.46044 0.16131,-0.52891 0.74101,-0.64995 0.6723,-0.0481 0.77777,0.57404 1.08543,-0.60114 0.85577,-1.1653 -0.30509,-0.30498 -0.47604,-0.87464 0.16433,-0.83974 0.20368,0.0876 0.36298,0.0215 0.49766,-0.10077 -0.0896,-0.39051 -1.13962,0.24844 -1.35134,-0.41238 -0.39409,-0.50595 -0.71183,-0.003 -0.74157,0.42736 -0.27477,0.54361 -1.36311,1.08291 -1.44074,0.11938 0.49909,-0.34336 0.0274,-0.70102 -0.47749,-0.47543 -0.34422,0.48082 -1.39303,0.25803 -0.98856,-0.43408 -0.39558,-0.16344 -0.54981,-0.83329 -0.99528,-0.80667 -0.46308,0.47435 -0.67871,-0.19078 -1.07075,-0.16898 z", +2.85227, 3.44376, +"M 2.39399 0.825598 c 0.51165,-1.00701 0.17934,-1.56385 -0.34027,-2.34578 l 0.44899,-0.69865 0.34956,-0.46536 c -0.28419,-0.22778 -0.56839,-0.19965 -0.85258,-0.0535 l -0.59069,0.18407 c 0.43669,-0.6767 0.22244,-0.79303 -0.13779,-0.89014 l -0.55392,0.0248 c -1.05242,1.16603 -1.92058,0.41374 -2.26059,0.73685 -0.31726,0.4997 -0.002,1.19184 -0.27419,1.71558 -0.0601,0.59507 -1.33712,0.72874 -0.96788,1.37654 0.68403,0.42661 -0.0301,1.17727 0.22283,1.68512 -0.056,0.49908 0.41904,0.60361 0.45347,1.02055 -0.0241,0.64915 0.49545,0.16052 0.76293,0.009 0.37808,0.26076 0.79269,0.0499 1.11759,-0.25546 0.24455,-0.68364 0.82318,-0.24258 1.27166,-0.14754 0.15219,-0.31662 0.54842,-0.50454 0.70243,-0.77509 -0.0825,-0.44275 0.37149,-0.89378 0.64845,-1.12065 z", +3.408, 3.57197, +"M 2.62753 -3.57195 c -0.64407,0.7879 -0.64716,1.84506 -1.20222,2.58759 -1.34442,-0.27745 -1.52748,0.69891 -1.31733,1.75739 -0.78212,0.16845 -1.74702,0.16312 -2.57312,0.0427 -0.21732,0.51378 -0.40761,0.43217 -0.59858,0.21424 -1.0749,0.8342 0.63602,1.73677 1.46282,2.1222 1.23346,0.6503 2.55782,-0.35092 3.77246,0.4198 0.2868,-0.0617 0.92584,0.13183 0.99013,-0.27867 -0.83826,-0.73953 -2.26236,-1.79647 -1.23986,-3.02911 0.18907,-1.17518 1.78492,-1.4423 1.271,-2.84888 0.10716,-0.40834 0.32162,-0.44801 0.15222,-0.57722 -0.14475,-0.11041 -0.6654,-0.33083 -0.71752,-0.41005 z", +2.16401, 4.29525, +"M 1.65199 -3.9757 c -0.1751,0.027 -0.38331,0.16713 -0.56662,0.42127 -0.73687,-0.0649 -1.46581,0.13196 -1.66725,0.13706 -0.67315,0.017 -0.52923,1.98326 -0.49599,2.6279 0.0831,0.52678 0.10231,-0.0945 -0.0368,0.38051 -0.25456,0.86925 -0.82603,2.79733 -0.99814,3.68266 -0.0219,0.0245 -0.0307,0.0543 -0.0512,0.0793 0.26405,0.40175 0.43883,0.65708 0.62561,0.94225 1.81312,-0.12134 0.99017,-2.46123 1.53551,-3.61943 0.3032,-0.62038 1.0801,-1.84071 1.08397,-2.40264 0.005,-0.76342 0.83708,-0.66154 0.9192,-1.45341 0.14595,-0.57315 0.28406,-1.1579 -0.008,-1.11255 z", +2.42152, 3.19498, +"M 1.79275 3.19496 c 0.0358,-0.35442 0.0143,-0.94751 0.14977,-1.20163 0.29216,-0.54826 0.76509,-0.61761 0.24914,-1.04756 l -0.46191,-0.29639 c -0.0199,-0.009 -0.0339,-0.008 -0.0548,-0.0191 0.008,-0.67733 -0.40627,-1.15393 -0.87696,-1.61178 -0.0135,-0.57623 -0.52506,-0.68936 -0.93404,-0.86224 -0.3143,-0.11364 -0.30235,-0.2211 -0.26928,-0.50192 0.001,-0.35694 -0.19325,-0.6476 -0.63636,-0.70807 -0.52435,-0.42985 -0.56303,0.22718 -0.74414,0.56327 0.27001,0.2644 0.29136,0.75233 -0.0961,1.0294 -0.41132,0.0707 -0.85183,1.03036 -0.23048,1.04386 0.0806,0.4722 0.45958,1.10992 0.004,1.55133 -0.1628,0.45669 0.19683,1.40675 0.90123,1.35186 0.45163,-0.12672 0.99602,0.14704 1.99196,-0.16774 0.14912,0.4712 0.54383,0.84975 1.00786,0.87673 z", +2.60961, 2.6311, +"M 2.50705 -1.19561 -0.25339,-0.1347 c -0.4738,-0.41913 -0.99447,-0.94138 -1.21945,-0.8131 l -0.73175,0.24406 c -0.40381,-0.23794 -0.62439,-0.0636 -1.21942,-0.73175 -0.45864,0.0258 -0.91727,0.38107 -1.37591,0.59171 -0.0117,0.11781 -0.0183,0.23633 -0.0649,0.35298 -0.27654,0.35904 -0.46239,0.91911 0.20227,0.9358 0.65658,0.0504 0.51399,0.93494 0.66863,1.40794 0.23986,0.54801 -0.23986,1.16298 0.21828,1.63643 0.33587,0.31601 0.77101,0.40448 1.22387,0.28852 -0.1503,-0.46126 0.39437,-0.91344 0.91269,-0.91403 0.76165,0.0123 1.04546,-0.73144 1.04116,-1.36969 -0.0925,-0.60988 1.09071,-0.27154 0.56549,-0.77799 -0.0175,-0.24875 0.0184,-0.48273 0.0324,-0.71618 z", +2.91238, 3.10557, +"M -2.9122 1.73814 c 0.28378,0.47289 1.03118,0.63668 1.62475,0.90306 1.10867,0.1542 2.37832,0.14746 3.32429,0.46437 0.29646,-0.1176 0.26342,-0.96007 0.29166,-1.66776 l 0.0964,-0.71277 c 0.0983,-0.21454 0.10887,-0.66087 0.22079,-0.8799 0.101,-0.19778 0.31208,-0.17115 0.25795,-0.31721 -0.37435,-0.55516 -0.83678,-0.93415 -1.38048,-1.15063 -0.0489,0.0422 -0.0876,0.10835 -0.13886,0.14474 -0.75872,0.99895 -1.59127,-0.26181 -1.57102,-1.05567 0.14438,-0.85593 -1.15818,-0.67142 -0.50818,0.0282 -0.74639,0.10568 -0.15692,0.9358 -0.38769,1.48657 -0.51224,0.50199 -0.80922,1.23824 -1.51997,1.55271 -0.45966,0.11748 -0.20829,0.6411 -0.27572,0.98493 0.009,0.0899 -0.0234,0.14503 -0.0341,0.21939 z", +3.04347, 2.84609, +"M 0.490388 -2.84481 c -0.17818,-0.0381 -0.59112,0.79085 -0.87113,0.86987 -0.28109,-0.28971 -0.64432,-0.14548 -0.67045,0.31688 0.17296,0.35303 -0.32861,0.92862 -0.38047,0.37989 -0.4836,-0.88691 -0.84563,0.59496 -1.32932,0.67352 -0.34102,0.46556 0.0163,0.50226 0.25082,0.78429 -0.88963,0.69447 -0.64769,1.26964 0.58717,1.61261 0.64827,-0.33916 1.89403,-1.4075 1.52897,0.052 0.13212,0.76935 0.98486,1.48997 1.55068,0.56922 -0.30948,-1.21831 1.0167,-2.14737 1.88681,-2.26869 -0.414,-0.6498 -0.0862,-1.85279 -0.94851,-2.09149 -0.29062,-0.0875 -1.51076,0.0901 -1.51829,-0.51083 0.006,-0.26528 -0.0269,-0.37452 -0.0863,-0.38722 z", +2.60354, 3.87863, +"M -2.58741 2.42622 5e-5,-5.1e-4 c 0.0545,-0.28255 0.24695,-0.66339 0.55812,-1.04225 0.58545,-0.71275 0.69899,-1.23193 0.40168,-1.83633 -0.12573,-0.25554 -0.10279,-0.32366 0.0655,-0.19436 0.14242,0.10941 0.35573,0.007 0.47396,-0.22648 0.13004,-0.25726 0.0644,-0.53105 -0.16725,-0.69336 -0.61079,-0.42848 -0.34025,-1.8077 0.39236,-1.99985 0.39389,-0.1033 0.67136,-0.0486 0.77194,0.15245 0.10567,0.21111 0.29186,0.16355 0.57011,-0.14555 0.38478,-0.42741 0.42246,-0.42673 0.54193,0.0137 0.0706,0.26033 0.052,0.57305 -0.0418,0.69491 -0.0936,0.12183 0.004,0.1741 0.21775,0.11617 0.29389,-0.0797 0.38668,0.21619 0.38089,1.21691 -0.004,0.7281 0.16873,1.53845 0.38543,1.80433 0.21632,0.26545 0.31499,0.58433 0.21915,0.70905 -0.0958,0.12468 -0.0624,0.2383 0.074,0.2522 0.13645,0.0139 0.2856,0.26879 0.33189,0.56623 0.0463,0.29751 -0.0165,0.46361 -0.13944,0.36914 -0.12297,-0.0945 -0.23633,-0.046 -0.25195,0.10731 -0.0156,0.15332 -0.25555,0.25548 -0.53324,0.22719 -0.90574,-0.0923 -1.36908,0.17162 -1.43488,0.81735 -0.0549,0.53905 -0.17952,0.61343 -0.83029,0.49663 -0.42102,-0.0756 -0.70687,-0.21398 -0.63513,-0.3073 0.15929,-0.20731 -0.61961,-0.67165 -1.08123,-0.6447 -0.24076,0.0141 -0.3242,-0.17035 -0.26966,-0.4529 z", +3.89459, 2.76207, +"M 2.11989 -2.76207 h 1.36873 l -0.35549,1.28958 c -0.29269,1.05994 -0.25675,1.36166 0.20266,1.6976 0.30734,0.22472 0.5588,0.76635 0.5588,1.20359 0,0.73869 -0.10906,0.78002 -1.53862,0.58406 -1.12744,-0.15454 -1.65256,-0.0734 -1.96439,0.30227 -0.42093,0.50722 -1.08901,0.5684 -2.78519,0.25655 -1.43006,-0.26295 -1.74284,-0.69806 -1.33735,-1.86135 0.19689,-0.56461 0.55188,-1.02688 0.78878,-1.02688 0.23697,0 0.64286,-0.3974 0.90268,-0.88292 0.48391,-0.90417 1.76118,-1.45844 2.42085,-1.05075 0.20303,0.12556 0.36914,0.0615 0.36914,-0.14193 0,-0.20347 0.61632,-0.36982 1.3694,-0.36982 z", +2.94033, 4.04841, +"M 0.955924 -4.04819 c 0.27815,0.007 0.71396,0.18533 1.21285,0.53472 0.89248,0.62514 1.02887,1.65306 0.31401,2.36795 -0.76145,0.76144 -1.35601,2.05174 -1.12098,2.432 0.1187,0.19201 0.0454,0.34882 -0.16219,0.34882 -0.20765,0 -0.37588,0.28073 -0.37181,0.62384 0.004,0.53339 0.0558,0.54652 0.35298,0.0891 0.26617,-0.40941 0.32982,-0.30503 0.27295,0.4456 -0.0609,0.80483 -0.24384,0.98032 -1.02141,0.98032 -0.52094,0 -1.4289,0.0959 -2.01772,0.21375 -0.62778,0.12557 -1.17184,0.0511 -1.31523,-0.18103 -0.13461,-0.2177 0.0843,-0.81432 0.48665,-1.32566 0.40219,-0.51129 0.6373,-1.08236 0.52222,-1.26856 -0.11506,-0.18621 0.0922,-0.41733 0.46092,-0.51383 0.46375,-0.12126 0.65661,-0.47079 0.62453,-1.1342 -0.0293,-0.6002 0.27891,-1.26441 0.82367,-1.77476 0.4875,-0.45671 0.78245,-1.04493 0.67046,-1.33678 -0.13082,-0.34108 -0.0108,-0.50804 0.2681,-0.5013 z", +2.50487, 5.03272, +"M -2.16669 -3.17022 1.86046,-0.51083 c 1.02338,-0.28104 1.94395,-0.73695 2.04586,-1.01295 0.10187,-0.27602 0.34634,-0.41088 0.54358,-0.29979 0.19726,0.11107 0.27852,0.40249 0.17931,0.64757 -0.0993,0.24506 -0.39051,1.29581 -0.64811,2.33521 -0.319,1.28729 -0.645,1.9083 -1.02188,1.94754 -0.38441,0.0401 -0.38656,0.0854 -0.007,0.14812 0.29981,0.0496 0.43437,0.35011 0.29918,0.66799 -0.23474,0.55145 -0.25461,0.55221 -0.43484,0.0127 -0.12461,-0.37299 -0.49795,0.24186 -1.09772,1.80788 -0.49978,1.30521 -1.09181,2.41091 -1.31488,2.45715 -0.22322,0.0463 -0.0643,-0.59646 0.35215,-1.4284 0.47376,-0.94633 0.58524,-1.53429 0.29799,-1.5706 -0.9072,-0.11464 -1.60579,-1.99425 -1.33221,-3.5826 z", +4.0742, 4.47677, +"M -1.73269 -4.47592 v 5.3e-4 c -0.11923,-0.0214 -0.34907,0.20596 -0.62117,0.66663 -0.42148,0.71353 -0.27757,1.66663 0.30591,2.02726 0.18712,0.11561 0.15346,0.28882 -0.11213,0.5824 -0.75139,0.83028 -2.02901,3.17126 -1.90582,3.49229 0.21982,0.57286 0.9162,0.20501 1.12292,-0.59273 0.10928,-0.42187 0.30009,-0.76688 0.42323,-0.76688 0.46329,0 0.96755,1.15024 0.89659,2.04432 -0.0619,0.78083 -0.006,0.90333 0.4005,0.88005 0.25974,-0.0148 0.64453,-0.10023 0.85474,-0.19017 0.26972,-0.11518 0.42074,-0.0149 0.51416,0.34262 0.22016,0.8419 0.94316,0.48133 1.16377,-0.58033 0.10563,-0.50859 0.28131,-1.03924 0.39066,-1.17926 0.10925,-0.14 0.27067,-0.55414 0.35812,-0.91984 0.11033,-0.4615 0.40817,-0.76905 0.97308,-1.0051 0.52028,-0.21739 0.86677,-0.55204 0.96118,-0.92811 0.23675,-0.94326 -0.0311,-1.2976 -0.98084,-1.2976 -0.49064,0 -1.15258,-0.21143 -1.55027,-0.49454 -0.69181,-0.49257 -0.89485,-0.48303 -1.68363,0.0796 -0.35702,0.25464 -0.49911,0.1962 -1.0015,-0.41186 -0.38391,-0.46468 -0.54345,-0.8907 -0.46455,-1.2392 0.0738,-0.32572 0.0477,-0.49342 -0.045,-0.51005 z", +4.05861, 3.1259, +"M 1.4673 -3.12553 c 0.2083,-0.0104 0.30102,0.19858 0.4976,0.72986 l 0.28366,0.76589 0.85394,-0.10578 c 0.75247,-0.0929 0.83822,-0.0672 0.72384,0.2093 -0.0771,0.18457 -0.0519,0.26844 0.0579,0.20316 0.12017,-0.07 0.17818,0.0104 0.17417,0.18171 v -7.9e-4 c 0,0.17241 -0.0697,0.43828 -0.19554,0.74443 -0.13945,0.33975 -0.31333,0.45866 -0.61256,0.41861 -0.29078,-0.0393 -0.443,0.0567 -0.49759,0.31661 -0.043,0.20532 -0.16706,0.68434 -0.27521,1.06489 l -0.19702,0.6923 -1.07262,-0.0537 c -1.68416,-0.0835 -2.45547,0.0134 -2.35518,0.29672 0.0623,0.17504 -0.11423,0.24332 -0.61168,0.22847 -0.63289,-0.0166 -0.67621,0.0119 -0.45086,0.30435 0.21928,0.2847 0.20904,0.30719 -0.0905,0.18553 -0.18708,-0.0764 -0.48128,-0.1495 -0.65307,-0.1495 -0.27046,-0.0104 -0.27432,-0.0337 -0.0267,-0.18475 0.25384,-0.15875 0.17922,-0.25993 -0.10237,-0.14406 -0.0593,0.0242 -0.19242,-0.11646 -0.29508,-0.31204 -0.13945,-0.26497 -0.12017,-0.39565 0.0742,-0.51137 0.20429,-0.12255 0.18916,-0.15151 -0.0682,-0.16636 -0.22417,-0.007 -0.32431,-0.16022 -0.31586,-0.48071 0,-0.25783 0.0979,-0.46381 0.20014,-0.46381 0.10385,0.003 0.18975,-0.0786 0.19242,-0.18248 0,-0.10355 -0.13204,-0.19547 -0.29983,-0.19547 -0.24183,-0.006 -0.25607,-0.0623 -0.0757,-0.26911 0.17714,-0.20219 0.17032,-0.29634 -0.0282,-0.42243 -0.48024,-0.30624 -0.47979,-0.7686 0,-1.16533 0.25591,-0.21095 0.46895,-0.51184 0.47296,-0.66929 0,-0.20785 0.12759,-0.25156 0.45234,-0.16253 0.24509,0.0682 0.50427,0.0347 0.57652,-0.0751 0.0727,-0.11053 0.38795,-0.19961 0.70232,-0.18477 0.42357,0.0104 0.54225,0.0849 0.45917,0.2852 -0.0905,0.21809 -0.0208,0.23926 0.36348,0.1043 0.35042,-0.12269 0.43854,-0.10875 0.33425,0.0499 -0.0994,0.15132 -0.0326,0.17466 0.22238,0.0782 0.1994,-0.0751 0.63898,-0.20767 0.97664,-0.2967 0.74565,-0.19402 0.8271,-0.41151 0.10089,-0.2691 l -0.51896,0.10192 0.47608,-0.26372 c 0.25518,-0.1408 0.42148,-0.2323 0.54655,-0.2323 z", +4.06584, 3.46902, +"M 0.0899704 -3.46718 c -0.17768,-0.01 -0.28056,0.0213 -0.24431,0.083 0.0487,0.0831 -0.11034,0.13842 -0.35322,0.13842 -0.4581,-0.0115 -0.94486,0.37267 -0.74196,0.58647 0.0645,0.0674 0.0315,0.11778 -0.0731,0.11778 -0.1046,-0.003 -0.23714,0.15712 -0.29461,0.35544 -0.0745,0.25648 -0.19559,0.32418 -0.41912,0.23103 -0.25478,-0.1056 -0.29634,-0.0555 -0.22139,0.26509 0.0588,0.25046 0.0143,0.3895 -0.1347,0.3895 -0.12466,-0.003 -0.36123,0.13641 -0.52717,0.30953 -0.27842,0.29188 -0.27469,0.33282 0.0487,0.54646 0.19201,0.1271 0.34547,0.35797 0.34132,0.51242 0,0.15476 0.076,0.23203 0.17696,0.17327 0.10175,-0.059 0.18084,0.0149 0.17697,0.16438 0,0.14962 -0.0946,0.32273 -0.19989,0.38431 -0.13183,0.0768 -0.12753,0.19543 0.0143,0.37395 0.32527,0.41241 -0.0745,0.29467 -0.72864,-0.21473 -0.71245,-0.55498 -1.05936,-0.39598 -0.95892,0.43985 0.0416,0.33988 0.12324,0.48366 0.20807,0.35468 0.0888,-0.13655 0.20691,-0.004 0.32584,0.36877 0.10174,0.32039 0.28573,0.55263 0.40724,0.51536 0.34705,-0.10575 0.38459,-0.42635 0.0874,-0.73974 -0.43074,-0.4534 -0.31081,-0.73099 0.15547,-0.35986 0.25348,0.20188 0.38044,0.45716 0.32427,0.65161 -0.0502,0.17568 2.9e-4,0.32435 0.12036,0.32433 0.1175,0.003 0.16537,-0.076 0.10747,-0.17623 -0.0602,-0.1046 0.0143,-0.13327 0.17182,-0.0674 0.15345,0.0636 0.28113,0.0207 0.28428,-0.0956 0,-0.12179 0.0774,-0.1647 0.16508,-0.10732 0.0874,0.058 0.79011,0.13068 1.5603,0.16217 0.87538,0.0363 1.30439,0.11506 1.14548,0.20955 -0.1943,0.1165 -0.16808,0.15227 0.1089,0.1666 0.29763,0.0129 0.31238,0.0459 0.086,0.1792 -0.19932,0.1188 -0.22081,0.21924 -0.0803,0.36729 0.0602,0.0639 0.31711,0.0949 0.49235,0.14587 -0.0258,-0.0297 -0.0559,-0.0606 -0.0545,-0.13326 0,-0.1003 0.0903,-0.17623 0.19631,-0.17623 0.0788,0.003 0.1175,0.0486 0.1046,0.11334 0,0.0217 -0.0143,0.0455 -0.0301,0.0703 -0.0516,0.0791 -0.11177,0.12094 -0.1592,0.14286 0.55597,0.14794 1.3051,0.23898 1.40841,0.0807 0.0602,-0.0917 0.0272,-0.21988 -0.0731,-0.28583 -0.33674,-0.22037 0.1784,-0.8133 0.69525,-0.79898 0.23472,0.006 0.34648,-0.01 0.35695,-0.0652 v 0 c 0,-0.0331 -0.0229,-0.0801 -0.0846,-0.14512 -0.11607,-0.12266 -0.20835,-0.36821 -0.20362,-0.54575 0,-0.19462 -0.17309,-0.37354 -0.4495,-0.45093 -0.25205,-0.0703 -0.41684,-0.16677 -0.36583,-0.21549 0.0516,-0.0483 -0.0229,-0.21043 -0.16507,-0.35988 -0.14186,-0.14945 -0.21293,-0.34046 -0.15848,-0.42356 0.0545,-0.0832 0,-0.21354 -0.11033,-0.28804 -0.14187,-0.0937 -0.16236,-0.0546 -0.0616,0.12222 0.12466,0.22596 0.10173,0.22495 -0.16135,0 -0.24246,-0.20762 -0.25721,-0.29549 -0.0702,-0.40726 0.21766,-0.12996 0.0803,-0.22733 -0.2585,-0.1829 -0.0745,0.01 -0.13327,-0.10374 -0.1304,-0.25324 0,-0.15017 -0.0702,-0.27694 -0.16593,-0.27694 -0.0946,-0.003 -0.37127,-0.21307 -0.61386,-0.46872 -0.2426,-0.2556 -0.39377,-0.46206 -0.33617,-0.46206 0.0573,0.002 0.0143,-0.11506 -0.1003,-0.25843 -0.14042,-0.17871 -0.1443,-0.29802 -0.0143,-0.37395 0.37657,-0.21937 0.1976,-0.59398 -0.32656,-0.68568 -0.0731,-0.01 -0.14043,-0.0222 -0.19918,-0.0236 z", +3.04742, 4.1149, +"M 0.969015 -4.11451 c -0.1123,0.003 -0.4062,0.23381 -0.6532,0.51211 -0.247,0.27833 -0.4917,0.4659 -0.5436,0.41704 -0.052,-0.0489 -0.092,-0.0185 -0.089,0.0677 0,0.0862 -0.1232,0.13629 -0.2795,0.11111 -0.1564,-0.0252 -0.2829,0.0298 -0.2812,0.12247 0,0.10163 -0.054,0.0859 -0.141,-0.0393 -0.1244,-0.18039 -0.1424,-0.17678 -0.1385,0.0248 0,0.12772 -0.089,0.27161 -0.2042,0.31987 -0.1152,0.0483 -0.2111,0.0261 -0.2134,-0.0491 0,-0.0753 -0.1476,-0.13195 -0.3225,-0.12505 -0.2601,0.009 -0.2789,0.0366 -0.1017,0.14882 0.1624,0.10279 0.1233,0.11844 -0.1572,0.0625 -0.3368,-0.0673 -0.3789,-0.0286 -0.4299,0.39739 -0.081,0.67937 0.181,2.0534 0.4382,2.29547 0.2153,0.2027 0.2296,0.52597 0.052,1.16531 -0.07,0.25284 -0.1989,0.3266 -0.6031,0.34623 -0.4968,0.0241 -0.4903,0.0295 0.199,0.1819 1.3697,0.30279 2.4788,0.44216 2.7978,0.35191 0.1769,-0.05 0.674,-0.0115 1.1048,0.0858 l 0.7829,0.17673 -0.011,0.54881 c -0.051,2.51094 0.8952,0.2636 0.8723,-1.92856 h -5e-4 l -0.017,-1.60197 -0.6072,0.0429 c -0.3341,0.0235 -0.6756,0.0384 -0.7586,0.0336 -0.1011,-0.006 -0.1467,-0.54478 -0.138,-1.63452 0.013,-1.66481 -0.091,-2.04807 -0.5566,-2.03399 z", +5.34994, 2.90409, +"M 0.205271 -2.88963 c -0.13829,-0.0359 -0.26164,-0.004 -0.39597,0.0846 -0.4055,0.27123 -0.57988,1.88599 -0.20283,1.87455 0.14783,-0.004 0.19695,0.23609 0.12558,0.61444 -0.22207,1.18362 -0.24909,1.20421 -0.83216,0.65553 -1.004,-0.9451 -2.68326,-0.94665 -3.80823,-0.007 -0.588,0.49193 -0.58959,1.01822 0,1.10322 0.48466,0.0703 2.31733,0.0446 3.47298,-0.0477 1.30444,-0.10428 2.47502,0.0916 2.48901,0.41565 0.0207,0.47846 0.40456,0.83765 0.9455,0.88472 0.2971,0.0257 1.17457,0.10237 1.94935,0.17084 0.97395,0.0862 1.40585,0.0494 1.4014,-0.1208 v -7.4e-4 c 0,-0.13544 -0.24559,-0.23879 -0.53554,-0.23 -0.51615,0.0159 -0.52728,-0.021 -0.47228,-1.65113 l 0.0572,-1.66673 -0.87063,0.0172 c -1.71646,0.0362 -1.88385,-0.0251 -1.9042,-0.69824 -0.0159,-0.34413 -0.10173,-0.62322 -0.20124,-0.6202 -0.10015,0.003 -0.42332,-0.20574 -0.71803,-0.46412 -0.20188,-0.17696 -0.35766,-0.27952 -0.49691,-0.31544 z", +4.12566, 4.16038, +"M -4.12566 1.26026 c 0.3983,1.33704 0.5968,1.95916 0.8005,2.60191 0.1973,-0.15081 0.2728,-0.16272 0.4356,0.0408 0.1118,0.13999 0.2564,0.25733 0.3214,0.25733 0.2494,0.007 0.5568,-0.47474 0.585,-0.91673 0.016,-0.25389 0.1112,-0.52612 0.2113,-0.60513 0.1002,-0.0788 0.3032,-0.36546 0.4507,-0.63717 0.2314,-0.41949 0.2393,-0.48358 0.058,-0.41963 -0.11549,0.041 -0.176,0.0232 -0.1349,-0.0398 0.041,-0.063 0.2731,-0.0781 0.51471,-0.032 0.37159,0.0703 0.50419,0.0242 0.85939,-0.29872 0.2311,-0.2101 0.5599,-0.49394 0.7307,-0.63045 0.1707,-0.13658 0.2623,-0.25061 0.2036,-0.25061 -0.059,-0.002 0.01,-0.0802 0.14211,-0.17517 0.13679,-0.0944 0.2916,-0.14405 0.34419,-0.10907 0.053,0.034 0.2139,0.0285 0.3576,-0.0134 0.211,-0.0609 0.24771,-0.14503 0.1917,-0.43562 -0.059,-0.30721 0.028,-0.46208 0.5891,-1.05009 0.3622,-0.37938 0.6599,-0.741607 0.6615,-0.804607 0,-0.063 0.043,-0.21795 0.092,-0.34417 0.072,-0.18478 0.016,-0.16969 -0.2863,0.077 l -0.3762,0.30645 0.3152,-0.33952 c 0.1734,-0.18614 0.3417,-0.31097 0.3746,-0.27596 0.033,0.035 0.1383,0.002 0.2336,-0.0729 0.2257,-0.1773 0.2371,-0.4254 0.013,-0.28317 -0.092,0.0587 -0.077,0.0236 0.034,-0.078 0.11061,-0.10141 0.2745,-0.33917 0.3649,-0.52813 l 0.16431,-0.34367 -0.6878,-0.0176 c -0.57011,-0.0152 -0.7141,0.0264 -0.8377,0.24342 -0.082,0.14406 -0.1236,0.37092 -0.093,0.50382 0.036,0.15298 -0.01,0.2372 -0.1214,0.2372 -0.2107,-0.006 -0.2346,0.14356 -0.053,0.33435 0.071,0.0753 0.1477,0.31057 0.169,0.52298 0.045,0.453997 -0.308,0.827227 -0.7953,0.840237 -0.1728,0.005 -0.3814,0.0724 -0.4636,0.15039 -0.2358,0.22381 -0.5701,0.15658 -0.8759,-0.17674 -0.2915,-0.31779 -0.8445,-0.54271 -0.8495,-0.3457 0,0.0616 -0.2271,0.21883 -0.5003,0.34932 -0.5806,0.27771 -0.6869,0.47366 -0.6015,1.1152 0.075,0.56536 0.01,0.62764 -1.1157,1.05936 -0.4885,0.18751 -0.9565,0.38981 -1.4252,0.58394 z", +3.86911, 4.42196, +"M -3.86911 -0.871814 1.5374,2.2846 c 0.2008,-0.0776 0.3166,-0.10729 0.602,-0.2408 0.5019,-0.2349 0.9751,-0.3859 1.0516,-0.33592 0.082,0.0531 0.1067,0.2639 0.061,0.50541 -0.056,0.29721 -0.026,0.43696 0.1075,0.49197 0.1027,0.0425 0.1471,0.13787 0.098,0.21188 -0.061,0.093 -0.015,0.0986 0.1499,0.0196 0.3172,-0.15314 1.3733,-0.36761 1.7591,-0.35761 0.1701,0.005 0.4193,0.13343 0.5544,0.28628 0.1977,0.2236 0.2285,0.38401 0.1566,0.82322 -0.071,0.43418 -0.048,0.56343 0.1142,0.63045 0.1121,0.0465 0.1708,0.13486 0.1308,0.19584 -0.04,0.0607 0.016,0.11679 0.124,0.11679 0.1083,0.003 0.1966,0.0477 0.1953,0.0998 0,0.12689 0.7177,0.55224 0.9426,0.56224 0.1639,0.004 0.1918,-0.43416 0.1075,-1.68103 0,-0.057 -0.064,-0.0689 -0.1354,-0.0279 -0.071,0.0416 -0.1333,0.0151 -0.1406,-0.0589 -0.01,-0.0739 -0.025,-0.1915 -0.04,-0.26148 -0.016,-0.07 -0.034,-0.18423 -0.041,-0.25424 -0.01,-0.0699 -0.1177,-0.1328 -0.2459,-0.1328 -0.5387,-0.0141 -0.9,-1.15501 -0.4197,-1.325 0.3033,-0.1074 0.1118,-0.30189 -0.2402,-0.2439 -0.2282,0.0375 -0.3614,-0.0331 -0.5065,-0.26768 -0.2727,-0.44103 -0.3275,-0.86317 -0.1121,-0.8532 0.096,0.002 0.2993,-0.16322 0.4532,-0.36793 0.1542,-0.2046 0.2449,-0.37412 0.2015,-0.37412 -0.044,-0.001 0.084,-0.13883 0.2837,-0.30541 0.069,-0.0573 0.084,-0.0527 0.1308,-0.0884 -0.2037,-0.64275 -0.4022,-1.26486 -0.8005,-2.60191 -0.3301,0.13674 -0.6584,0.26051 -1.0041,0.41082 -0.2463,0.1071 -0.4953,0.2654 -0.5529,0.35139 -0.058,0.0861 -0.1658,0.15298 -0.2403,0.15298 -0.082,-0.002 -0.064,-0.0868 0.043,-0.2124 0.1554,-0.18108 0.1516,-0.19894 -0.029,-0.13693 -0.1142,0.039 -0.26049,0.0158 -0.325,-0.0522 -0.1486,-0.15661 -0.8354,0.43305 -1.0434,0.89556 -0.115,0.25451 -0.1159,0.351 0,0.40101 0.083,0.037 0.048,0.0698 -0.077,0.0698 -0.232,0.004 -0.2745,0.0305 -0.9012,0.55758 -0.19939,0.16759 -0.4385,0.30075 -0.5318,0.30075 -0.093,-0.002 -0.2048,0.0796 -0.24749,0.18293 -0.043,0.10311 -0.20891,0.18034 -0.36951,0.18034 -0.16049,-0.004 -0.3865,0.0966 -0.50179,0.22429 -0.09,0.0994 -0.2028,0.17031 -0.29871,0.22429 z", +5.21206, 3.61562, +"M 5.21167 3.31641 -2.87571,-2.99268 c -0.10415,0.0389 -0.20387,0.0802 -0.36033,0.0775 -0.39269,-0.007 -0.9471,0.19838 -1.34636,0.49674 -0.14729,-0.0882 -0.27752,-0.24828 -0.39406,-0.40426 0.0978,-0.0826 0.13979,-0.19254 0.0398,-0.3869 -0.11869,0.002 -0.19394,-0.0372 -0.23982,-0.0956 0.0252,-0.0258 0.0176,-0.0405 -0.0283,-0.0478 -0.013,-0.0295 -0.0214,-0.0615 -0.0245,-0.096 0.13076,-0.0385 0.17321,-0.0758 0.0928,-0.0834 -0.026,-0.002 -0.0566,-0.0159 -0.0886,-0.0336 0.0543,-0.31133 0.38549,-0.64795 0.53791,-0.19087 0.30229,-0.0939 0.77511,-0.0703 1.09423,-0.25331 0.7238,0.2051 0.28056,-0.77685 0.56901,-1.06934 0.11112,-0.50295 0.0275,-1.03897 0.0306,-1.55424 0.0222,-0.81487 -0.50294,0.28945 -0.82428,0.37028 -0.24188,-0.2226 -0.5545,-0.11178 -0.57697,0.24343 0.14866,0.27116 -0.28257,0.71309 -0.32723,0.29163 -0.41601,-0.68112 -0.72709,0.45649 -1.14325,0.5169 -0.44399,-0.24164 -0.97952,-0.15946 -1.35193,0.20668 -0.44324,-0.0768 -0.82988,0.4394 -1.36296,0.32681 -0.47543,-0.38381 -0.86283,0.53807 -1.33412,0.18179 -0.16273,0.26228 -0.58769,0.64528 -0.49715,1.05906 0.23477,0.14434 0.20747,0.26981 0.0897,0.31932 l 1.3417,2.68325 0.0924,0.16202 c 0.0405,-0.0728 0.12901,-0.19265 0.24502,-0.311 0.1846,-0.18774 0.29739,-0.23065 0.48407,-0.17861 0.13382,0.0374 0.26642,0.10711 0.29441,0.15529 0.088,0.15111 0.30436,0.10201 0.60459,-0.13753 0.15959,-0.12775 0.31636,-0.20397 0.34817,-0.17032 0.0321,0.0336 0.31919,0.0603 0.63861,0.068 0.3195,0.003 0.57545,0.0368 0.56948,0.0735 -0.0321,0.18681 0.0122,0.40741 0.0814,0.40741 0.0428,7.6e-4 0.16479,-0.0719 0.27032,-0.16241 0.17956,-0.15424 0.94963,-0.38544 1.25629,-0.37779 0.0757,0.002 0.16234,0.0919 0.19361,0.19996 0.0314,0.10799 0.0976,0.17291 0.14737,0.14384 0.0497,-0.0285 0.16563,-0.006 0.2577,0.051 0.14438,0.0896 0.13169,0.0996 -0.0917,0.0996 -0.14246,-0.002 -0.32385,0.0583 -0.40307,0.13318 -0.0793,0.0783 -0.1687,0.11036 -0.19921,0.0782 -0.0306,-0.0321 -0.16794,0.011 -0.30543,0.096 -0.13819,0.0859 -0.39911,0.14129 -0.58333,0.12369 -0.34235,-0.032 -0.52482,0.0456 -0.40461,0.1723 0.0375,0.0391 0.10439,0.0155 0.14898,-0.0525 0.0627,-0.0962 0.095,-0.0855 0.14185,0.0466 0.0459,0.13 0.088,0.14508 0.17627,0.0613 0.0635,-0.0608 0.23759,-0.11077 0.38648,-0.10313 0.14882,0.004 0.27185,-0.0325 0.27308,-0.0814 0,-0.0528 0.15555,-0.0724 0.34259,-0.0525 0.18705,0.0199 0.36279,6e-4 0.39085,-0.0423 0.0283,-0.0428 0.11096,-0.0528 0.18415,-0.0229 0.0734,0.0306 0.21779,0.0125 0.32163,-0.0395 0.13466,-0.0674 0.22391,-0.06 0.3114,0.0253 0.096,0.0969 0.10843,0.0961 0.0574,0 -0.0775,-0.14622 0.21305,-0.26384 0.8457,-0.34183 0.36163,-0.0446 0.45791,-0.0239 0.53033,0.1138 0.0688,0.13016 0.18399,0.16163 0.51496,0.13793 0.30955,-0.0222 0.4563,0.0117 0.53698,0.12369 0.092,0.12747 0.14476,0.13361 0.31147,0.0379 0,-0.002 0.008,-7.7e-4 0.01,-0.002 z", +4.53803, 3.30484, +"M 4.22266 2.80997 0.31537,-1.12559 c -0.009,-0.02 -0.007,-0.0204 -0.0166,-0.0433 -0.0891,-0.18672 -0.1596,-0.43114 -0.15657,-0.54337 0.007,-0.26307 -0.3226,-0.50877 -0.59978,-0.44658 -0.15585,0.0349 -0.21211,0.009 -0.20929,-0.0975 0.007,-0.14506 -0.37221,-0.30892 -0.51604,-0.22496 -0.20972,0.12206 -0.56233,-0.52094 -0.54975,-1.00228 0.007,-0.20306 0.69387,-0.85441 0.89802,-0.84718 0.0246,5.8e-4 0.22013,-0.0893 0.33034,-0.13193 l -1.11178,-1.65212 c -0.0195,0.0111 -0.0463,0.0411 -0.0615,0.0459 -0.0992,0.0317 -0.0915,0.0811 0.0376,0.23393 0.25,0.29716 0.14659,0.5097 -0.3124,0.64203 -0.308,0.0886 -0.41177,0.0914 -0.56956,0.006 -0.0485,-0.28545 -0.10942,-0.55919 -0.33331,-0.56055 l -3.8e-4,0.004 c -0.026,-3.8e-4 -0.055,-4e-5 -0.0856,0.0109 -0.0383,0.12372 -0.0535,0.2567 -0.0629,0.39275 -0.44908,-0.0654 -1.05986,-0.0415 -1.14461,0.0878 -0.0434,0.0662 -0.21861,0.14678 -0.38942,0.17789 -0.21261,0.0392 -0.30785,0.10585 -0.30192,0.21152 0,0.0285 -0.007,0.0534 -0.0145,0.0759 -0.0275,0.0216 -0.055,0.0453 -0.0822,0.0702 -0.007,0.001 -0.013,0.005 -0.0195,0.005 -0.0333,-7.2e-4 -0.12923,0.0237 -0.25528,0.0624 -0.08,-0.4784 -0.33186,-1.13708 -0.5564,-0.91446 0,0.16306 -0.0847,0.21734 -0.17609,0.21377 -3.8e-4,-3e-5 0,3.8e-4 0,3.8e-4 0.0499,0.24365 0.10392,0.55738 0.16712,0.8031 -0.14354,0.0227 -0.30849,0.0898 -0.40511,0.14461 -0.33424,0.33619 -0.74507,0.32102 -1.16899,0.1805 -0.26236,-0.0809 -0.35492,0.0333 -0.33894,0.29672 -0.15324,0.19325 -0.41676,0.31324 -0.60167,0.50786 -0.007,-0.0163 -0.013,-0.0322 -0.0181,-0.0486 0,0.0296 -0.007,0.0486 -0.008,0.0785 0.008,-0.01 0.0166,-0.0192 0.0253,-0.0284 0.0398,0.11691 0.0952,0.23149 0.15439,0.34417 -0.11751,0.0925 -0.227,0.23553 -0.25939,0.35127 -0.0586,0.21246 -0.18947,0.31968 -0.36325,0.38455 l 2.71944,2.83005 c 0.10689,-0.0587 0.32051,-0.1065 0.48394,-0.0994 0.16654,0.004 0.35001,-0.037 0.40736,-0.0912 0.0571,-0.0545 0.38558,-0.0909 0.72945,-0.0814 0.45349,0.0129 0.67232,-0.0226 0.79822,-0.12894 0.16481,-0.13918 0.99615,-0.19618 2.20563,-0.15135 0.19706,0.007 0.40331,-0.0138 0.45849,-0.0463 0.17471,-0.10371 0.36931,-0.0972 0.43389,0.0138 0.0217,0.0374 0.19258,0.0665 0.52581,0.0904 z", +1.92692, 5.24979, +"M -1.16568 5.24449 1.57665,-0.6191 c -0.0474,-0.4867 0.0954,-1.5337 0.25114,-1.6836 0.17039,-0.164 0.21291,-0.1563 0.37621,0.073 0.1012,0.1417 0.23035,0.3447 0.28834,0.4506 0.0858,0.1573 0.13611,0.1636 0.2744,0.034 0.16722,-0.1573 0.0631,-0.3063 -0.31419,-0.4501 -0.062,-0.024 0.01,-0.2644 0.15968,-0.5354 0.14994,-0.271 0.33213,-0.7281 0.40412,-1.0154 0.12608,-0.5015 0.1184,-0.5257 -0.1969,-0.5974 -0.23368,-0.053 -0.38971,-0.2226 -0.53949,-0.5876 -0.27201,-0.6626 -0.33335,-2.3657 -0.093,-2.5786 0.1421,-0.1258 0.13903,-0.1774 -0.0181,-0.2987 -0.2079,-0.1604 -0.2341,-1.2411 -0.045,-1.8552 0.10281,-0.3339 0.0903,-0.3456 -0.38601,-0.3581 -0.27072,-0.01 -0.61438,-0.1034 -0.76379,-0.214 -0.23149,-0.1708 -1.32257,-0.6546 -1.34407,0.41 -0.0512,2.5087 -0.0881,2.9436 -0.26511,3.1115 -0.141,0.1334 -0.16333,0.2237 -0.0692,0.2847 0.089,0.058 0.11213,0.5288 0.0651,1.3498 -0.0634,1.1134 -0.0451,1.2803 0.15967,1.4319 0.1278,0.094 0.22429,0.3077 0.22429,0.4734 -0.005,0.1661 0.0515,0.3404 0.12455,0.3886 0.073,0.048 0.0983,0.1683 0.0573,0.2682 -0.042,0.1012 -0.0193,0.1489 0.0517,0.1075 0.22709,-0.1322 0.12486,0.2738 -0.14264,0.5664 -0.28461,0.3116 -0.3362,0.4982 -0.13951,0.5033 0.0694,0 0.12142,0.091 0.12142,0.1964 -0.003,0.1065 0.0736,0.2267 0.17055,0.2666 0.27159,0.1124 0.32136,0.5471 0.078,0.6806 -0.118,0.064 -0.15684,0.1214 -0.0868,0.125 0.01,0 0.0111,0.067 0.0207,0.077 z", +3.13742, 6.38177, +"M 2.09259 -6.37924 c -0.0333,0.0351 -0.0639,0.10651 -0.0665,0.15881 0,0.0523 -0.18168,0.28228 -0.39724,0.51128 -0.21557,0.22899 -0.38735,0.49799 -0.38192,0.5977 0.009,0.0998 -0.12845,0.28291 -0.29726,0.40676 -0.16872,0.12384 -0.25759,0.22444 -0.19726,0.22261 0.0604,-0.002 -0.0906,0.167 -0.33569,0.37418 -0.24507,0.20716 -0.43708,0.42009 -0.42666,0.47372 0.0105,0.0536 -0.0482,0.12244 -0.12993,0.15248 -0.0977,0.0359 -0.11558,-0.005 -0.0508,-0.11945 0.0753,-0.13452 0.0578,-0.14289 -0.077,-0.0371 -0.42105,0.33004 -1.55709,-0.0183 -1.22158,-0.37463 0.0735,-0.078 0.0797,-0.24976 0.0166,-0.41989 -0.0587,-0.15829 -0.0988,-0.34453 -0.0883,-0.41354 0.0105,-0.069 -0.1864,-0.18257 -0.43752,-0.25293 -0.41046,-0.11495 -0.47884,-0.10036 -0.67549,0.14524 -0.16671,0.20808 -0.20217,0.22125 -0.14981,0.0547 0.0473,-0.14918 0.009,-0.21718 -0.13028,-0.2131 -0.15393,0.004 -0.19438,0.1355 -0.18098,0.57824 0.0149,0.48242 0.0447,0.54807 0.19,0.41943 0.13588,-0.11986 0.24384,-0.10913 0.50537,0.0511 0.28184,0.17272 0.32921,0.27874 0.3082,0.69317 l -0.0245,0.48911 0.74029,0.20541 c 0.40731,0.11309 0.788,0.17473 0.84561,0.13664 0.0578,-0.0382 0.1837,-0.008 0.2801,0.0674 0.0963,0.0751 0.31283,0.14691 0.48138,0.15972 0.35154,0.0267 0.74431,0.3456 0.61989,0.50313 -0.0464,0.0583 0.0114,0.0287 0.12757,-0.066 0.19438,-0.1583 0.21329,-0.12545 0.2294,0.40676 0.0131,0.42739 0.0569,0.5552 0.16925,0.4873 0.11986,-0.0727 0.12074,-0.0569 0.009,0.0756 -0.15786,0.18104 -1.51069,0.30581 -1.51577,0.13981 0,-0.14178 -1.40641,-0.0172 -1.51069,0.13438 -0.0517,0.0751 -0.0904,0.0544 -0.0946,-0.0516 -0.009,-0.12779 -0.0569,-0.10875 -0.18194,0.0674 -0.12678,0.17864 -0.17695,0.19682 -0.18369,0.0665 -0.009,-0.13638 -0.0429,-0.14397 -0.14885,-0.0313 -0.0867,0.0919 -0.12888,0.63215 -0.11172,1.42118 0.0149,0.70002 -0.0201,1.3785 -0.0771,1.50759 -0.0948,0.21303 -0.0569,0.22862 0.40722,0.17012 0.28115,-0.0354 0.527,-0.0233 0.54609,0.0267 0.0552,0.14325 2.4345,0.49083 2.60208,0.38007 0.0832,-0.0547 0.19542,-0.0735 0.25067,-0.0416 0.14753,0.0851 0.14473,0.78506 0,0.78953 -0.0709,0.003 -0.0902,0.13157 -0.0429,0.29772 0.0718,0.25436 0.0228,0.31646 -0.36283,0.45699 -0.3814,0.13879 -0.4806,0.13359 -0.68005,-0.0362 -0.12845,-0.10932 -0.43358,-0.20333 -0.67865,-0.20858 -0.24507,-0.005 -0.44758,-0.0599 -0.44977,-0.12127 0,-0.0615 -0.11129,0.02 -0.24253,0.18099 -0.40469,0.49616 -0.24227,0.75036 0.46562,0.72891 0.22712,-0.007 0.30163,0.0579 0.30942,0.26921 0.009,0.22501 0.0315,0.24213 0.12442,0.0891 0.0974,-0.16124 0.1161,-0.15665 0.1231,0.0299 0.009,0.17543 0.0753,0.20061 0.34611,0.12804 0.18571,-0.0497 0.38919,-0.14057 0.45205,-0.20179 0.063,-0.0612 0.2062,-0.11426 0.31801,-0.11764 0.2244,-0.007 0.65264,0.38173 0.61088,0.55426 -0.014,0.0601 0.0201,0.23309 0.0762,0.38459 0.21836,0.58332 0.33254,0.22078 0.29725,-0.94474 -0.0263,-0.87541 0.0123,-1.28197 0.13799,-1.45917 0.0959,-0.1351 0.17196,-0.37168 0.16968,-0.52576 0,-0.15407 0.0552,-0.3837 0.12941,-0.51037 0.16216,-0.27806 0.0175,-1.04903 -0.2434,-1.29449 -0.15253,-0.14353 -0.15612,-0.19583 -0.021,-0.31536 0.0892,-0.0787 0.25321,-0.1112 0.36424,-0.0724 0.2413,0.0843 0.44854,-0.40882 0.41895,-0.99812 -0.0105,-0.21248 0.0245,-0.69433 0.0779,-1.07052 0.0534,-0.37619 0.10261,-1.28473 0.10909,-2.01932 h -0.009 c 0,-0.31321 0,-0.55466 -4.3e-4,-0.7452 -0.0131,-0.57155 -0.0744,-0.68608 -0.28106,-0.91216 -0.24901,-0.27261 -0.30434,-0.29013 -0.36511,-0.11627 -0.0394,0.1127 -0.13728,0.18217 -0.21757,0.15428 -0.0975,-0.0339 -0.14036,-0.32845 -0.12897,-0.88591 0.01,-0.45938 -0.0105,-0.80654 -0.0438,-0.77144 z", +2.66052, 3.77103, +"M -0.39949 -3.77089 c -0.24655,0.002 -0.48424,0.0415 -0.7069,0.14289 -0.091,0 -0.14007,0.16428 -0.23247,0.15604 -0.56186,0.39932 -1.98716,1.04365 -0.95829,1.755351 0.37012,0.004 1.89317,-0.681921 1.58174,0.0144 -0.92118,0.19316 -0.78062,1.25644 -0.57652,1.87004 -0.5507,0.73969 -0.54645,2.07518 0.50073,2.40836 0.72023,0.13329 1.71345,0.023 1.86698,1.06161 0.14079,0.10466 0.256,0.14178 0.34647,0.13161 0.39231,-0.0442 0.32501,-0.98344 -0.0873,-1.24084 -0.12491,-0.92548 1.37777,-1.34914 1.32417,-2.16898 -0.0121,-0.11715 -0.0461,-0.24263 -0.12721,-0.37852 -0.83872,-0.59956 -0.43161,-1.77015 -0.097,-2.539971 0.45562,-0.35901 -0.33799,-0.65515 -0.53141,-0.9275 -0.74291,0.0304 -1.56344,-0.29219 -2.30307,-0.2845 z", +3.00843, 4.63, +"M -3.00308 -3.2356 c 0.0216,0.023 0.10979,0.055 0.26872,0.1013 0.56889,0.1649 0.8117,0.2144 1.07177,0.2196 0.22155,0 0.65876,0.8395 0.44286,0.846 -0.0655,0 -0.0523,0.2079 0.0295,0.4583 0.0816,0.2503 0.16335,0.662 0.1819,0.9142 0.0185,0.2523 0.0943,0.4564 0.16795,0.4542 0.0735,0 0.11453,0.2196 0.091,0.4925 -0.0236,0.273 5.3e-4,0.4946 0.0532,0.493 0.0529,0 0.10741,0.2474 0.12093,0.5529 0.0301,0.6823 0.35271,2.2028 0.57102,2.6913 0.0887,0.1985 0.29547,0.4232 0.4594,0.4992 0.4735,0.2194 0.77786,0.184 0.76378,-0.089 -0.0797,-1.554 0.36543,-3.8118 0.78032,-3.9574 0.13544,-0.047 0.34304,-0.3075 0.46147,-0.5778 0.11837,-0.2703 0.26596,-0.4621 0.32814,-0.4263 0.0622,0.036 0.15067,-0.042 0.19637,-0.1726 0.10948,-0.3133 -0.1781,-0.4655 -0.66611,-0.3525 -0.21603,0.05 -0.39776,0.035 -0.40411,-0.033 -0.0656,-0.6804 -0.18153,-1.2185 -0.31109,-1.4439 -0.19053,-0.3315 0.13535,-0.7608 0.48473,-0.6387 0.17021,0.059 0.20863,0 0.16433,-0.2589 -0.0455,-0.2639 -0.2012,-0.3747 -0.72399,-0.5147 -0.42937,-0.115 -0.69455,-0.2732 -0.74517,-0.4454 -0.0417,-0.1415 -0.0928,-0.2038 -0.2341,-0.2067 h -5.3e-4 c -0.0848,0 -0.20163,0.018 -0.36845,0.054 -0.28858,0.063 -0.6874,0.2067 -0.88573,0.3179 -0.1983,0.1112 -0.45557,0.2061 -0.57206,0.2113 -0.18831,0.01 -0.18809,0.024 0.004,0.1401 0.16267,0.098 0.094,0.1364 -0.27802,0.1524 -0.27189,0.012 -0.61486,0.1186 -0.76223,0.2372 -0.14743,0.1187 -0.39883,0.2252 -0.55862,0.2367 -0.10787,0.01 -0.15286,0.021 -0.13126,0.044 z", +4.45538, 5.00079, +"M 3.67326 3.58666 c 0.27079,-0.66346 0.32332,-0.78121 0.57421,-1.39679 -0.20034,0.0973 -0.44394,0.2056 -0.86662,0.24908 l -1.01753,0.10469 -0.32442,-0.67827 c -0.17835,-0.37327 -0.32777,-0.8685 -0.33148,-1.10044 -0.0123,-0.7472 0.88739,-1.58524 1.72954,-1.61074 0.5103,-0.0154 0.92804,-0.83692 1.00146,-1.96776 0.0482,-0.75168 0.021,-0.81363 -0.45222,-0.97588 -0.57495,-0.19732 -0.73908,-0.88336 -0.22222,-0.92927 0.16771,-0.0148 0.0408,-0.1032 -0.2829,-0.19608 -0.44802,-0.12851 -0.61919,-0.11519 -0.71732,0.0549 -0.0705,0.12285 -0.198,0.23615 -0.2829,0.25164 -0.0853,0.0156 -0.12804,0.13016 -0.0952,0.25547 0.0321,0.12524 -0.17735,0.31878 -0.46742,0.42983 -0.29007,0.11098 -0.52514,0.27295 -0.52254,0.35957 0,0.0866 -0.11865,0.16151 -0.26881,0.16606 -0.19491,0.006 -0.23866,0.10876 -0.1514,0.35702 0.0667,0.19175 0.0408,0.62287 -0.0593,0.95864 -0.17315,0.58372 -0.19898,0.59981 -0.58372,0.36405 -0.22135,-0.13498 -0.45358,-0.19271 -0.51599,-0.12646 -0.0618,0.0664 -0.11741,-0.01 -0.12235,-0.16988 -0.0124,-0.36216 -0.41947,-0.36654 -0.69941,-0.007 -0.16709,0.21426 -0.16598,0.26711 0.0124,0.26185 0.17006,-0.005 0.17254,0.0494 0.0136,0.25292 -0.11123,0.14297 -0.14918,0.41073 -0.0853,0.59461 0.0643,0.1839 0.0297,0.54243 -0.0766,0.79706 -0.208,0.49594 -0.48287,0.62505 -0.49485,0.23248 0,-0.14554 -0.19528,-0.23117 -0.48732,-0.22034 -1.11751,0.0426 -1.1384,0.0298 -1.03656,-0.62143 0.0828,-0.52592 0.0321,-0.64517 -0.37881,-0.8967 -0.45308,-0.27763 -0.48287,-0.27552 -0.70373,0.0466 -0.5061,0.73788 -0.0284,1.65526 0.58113,1.11704 0.16054,-0.14168 0.25509,-0.15557 0.25868,-0.0377 0,0.10208 -0.0692,0.23597 -0.16154,0.29699 -0.10505,0.0697 -0.0853,0.23703 0.0569,0.45089 0.18144,0.27371 0.18045,0.36979 -0.0124,0.49434 -0.28512,0.18973 -0.063,0.9574 0.23248,0.80537 0.11,-0.0566 0.33641,-0.15535 0.50264,-0.21971 0.16636,-0.0644 0.29909,-0.22545 0.29514,-0.35829 -0.0124,-0.28263 0.95709,-0.35933 1.62287,-0.12901 0.43418,0.15018 0.81187,1.06462 0.49239,1.19176 -0.0865,0.0347 -0.15412,0.20558 -0.1488,0.37938 0,0.17383 -0.10011,0.36244 -0.23569,0.41897 -0.55653,0.23312 -0.27128,1.40722 0.48027,1.97542 0.39685,0.30003 0.52477,0.25768 0.6936,-0.23056 0.12915,-0.37324 0.23049,-0.42519 0.68407,-0.34872 0.40588,0.0685 0.53095,0.0271 0.52502,-0.175 -0.0124,-0.32797 0.45877,-0.54947 0.56394,-0.26633 0.0569,0.15333 0.14905,0.14191 0.36015,-0.0434 0.19972,-0.17521 0.52736,-0.21946 1.12468,-0.16094 z", +4.04617, 5.42426, +"M -2.94195 4.57672 5.547,0.84754 c -0.0131,-0.11956 -0.002,-0.25067 -0.022,-0.34369 l -0.11879,-0.55384 0.67428,-0.21593 c 0.37071,-0.11919 0.75479,-0.27013 0.85339,-0.33717 0.28775,-0.19498 -0.63141,-0.34362 -1.29568,-0.20935 -0.56865,0.11499 -1.08906,-0.007 -1.15769,-0.27139 -0.0188,-0.0737 -0.18848,-0.31709 -0.37655,-0.54178 -0.18811,-0.22467 -0.3416,-0.53824 -0.3413,-0.69665 9.2e-4,-0.50293 -0.54357,-1.30997 -1.04569,-1.54977 -0.35267,-0.16848 -0.52754,-0.36992 -0.6645,-0.76621 -0.10221,-0.29559 -0.14563,-0.52528 -0.0964,-0.51011 0.17354,0.0539 -0.66737,-2.76228 -0.96072,-3.21725 -0.16345,-0.25346 -0.27119,-0.54462 -0.23941,-0.64722 0.036,-0.1166 0.008,-0.13435 -0.0749,-0.0476 -0.11577,0.12068 -0.2106,-0.0208 -0.25406,-0.37838 -0.006,-0.0499 -0.10171,-0.11849 -0.21226,-0.15262 -0.027,-0.008 -0.0774,-0.16167 -0.11391,-0.2073 -0.53067,-0.0874 -0.63302,-0.10779 -1.20503,-0.20227 10e-4,0.01 0.003,0.01 0.004,0.0175 0.0527,0.43032 0.14887,0.71581 0.25112,0.74742 0.10484,0.0326 0.0998,0.202 -0.0141,0.46214 -0.1944,0.44418 -0.0765,0.73425 0.34048,0.83519 0.23019,0.0556 0.28611,0.20689 0.44455,1.20419 0.20536,1.29285 0.19184,1.41099 -0.17315,1.50581 -0.32706,0.0846 -0.58936,0.79809 -0.36878,1.00225 0.20564,0.19033 0.36751,0.75346 0.20212,0.70237 -0.20848,-0.0645 -0.0864,0.17277 0.22532,0.43844 0.1607,0.13697 0.2717,0.3158 0.24664,0.39698 -0.0253,0.0806 0.0317,0.17074 0.12496,0.19997 0.11335,0.0347 0.11536,0.1239 0.004,0.26449 -0.11539,0.14655 -0.10247,0.49598 0.0428,1.1318 l 0.21014,0.91939 z", +5.49752, 3.12991, +"M 1.37015 -3.12969 v 0.001 c -0.1107,0 -0.2247,0.002 -0.3421,0.005 -0.273,0.007 -0.4227,0.0758 -0.4227,0.19482 0,0.26786 -0.2484,0.3097 -0.772,0.12971 -0.3784,-0.1301 -0.526,-0.12457 -0.8269,0.031 -0.5169,0.26723 -1.5029,0.35961 -2.096,0.19586 -0.4659,-0.12864 -0.5236,-0.11468 -0.7643,0.1912 -0.2181,0.27728 -0.3304,0.31769 -0.696,0.24908 -0.3971,-0.0745 -0.4341,-0.0551 -0.4114,0.21911 0.014,0.1656 -0.1182,0.49771 -0.2935,0.73742 -0.3107,0.42518 -0.3126,0.43928 -0.066,0.58239 0.1392,0.0807 0.5196,0.38777 0.8454,0.68265 0.3259,0.29485 0.7242,0.57704 0.8852,0.62684 0.1609,0.0498 0.2925,0.14516 0.2925,0.21187 0,0.15407 1.2613,0.16018 1.3565,0.006 0.039,-0.0632 0.3437,-0.24332 0.6769,-0.39997 0.425,-0.19982 0.6332,-0.24126 0.6967,-0.1385 0.05,0.0805 0.1662,0.12856 0.2589,0.10697 0.093,-0.0217 0.2127,0.11828 0.2671,0.31058 0.087,0.30723 0.054,0.36567 -0.2775,0.48111 -0.4545,0.1584 -0.4945,0.26092 -0.07,0.17983 0.1982,-0.0379 0.3343,0.0134 0.3845,0.14418 0.064,0.16602 0,0.18801 -0.3395,0.1235 l -0.4165,-0.0786 0.2599,0.26149 c 0.1431,0.14385 0.3029,0.23712 0.3551,0.20722 0.052,-0.0299 0.2166,0.0106 0.3658,0.0904 0.2162,0.11576 0.2544,0.22258 0.1876,0.52659 l -0.084,0.38085 h 0.8407 c 0.752,0 0.8633,-0.0341 1.0527,-0.32297 0.1164,-0.17773 0.372,-0.36144 0.5679,-0.40825 0.4395,-0.10496 0.7018,-0.3012 0.6072,-0.45424 -0.039,-0.0635 -0.01,-0.11523 0.066,-0.11523 0.076,7e-5 0.1379,0.0441 0.1379,0.0977 0,0.23852 1.0762,0.16168 1.5126,-0.10801 0.2339,-0.14457 0.366,-0.29703 0.386,-0.40307 v 0 c 0.02,-0.10602 -0.072,-0.16583 -0.28679,-0.12403 -0.13541,0.0264 -0.67191,0.0638 -1.19271,0.0827 -0.9133,0.0331 -0.9439,0.0241 -0.8619,-0.24339 0.047,-0.15257 0.1949,-0.38208 0.3292,-0.51006 0.297,-0.28318 0.3099,-0.52576 0.041,-0.74878 -0.462,-0.38339 -0.6379,-1.28709 -0.3137,-1.61127 0.069,-0.0691 0.1261,-0.22671 0.1261,-0.35038 0,-0.12366 0.089,-0.31478 0.1984,-0.42426 0.3806,-0.38055 -0.5051,-0.62598 -2.1652,-0.61598 z", +3.63043, 5.15692, +"M -3.62726 -3.36795 c -0.0468,0.32054 0.43759,0.66685 0.52881,0.98692 0.28647,0.32487 -0.28269,0.47336 -0.316,0.71696 0.10063,0.38021 0.34235,0.83542 0.13607,1.20634 -0.51118,0.31783 0.37465,0.71304 0.29987,1.10283 0.36141,0.35332 -0.44509,0.42029 -0.41731,0.69873 -0.13664,0.46798 -0.26085,0.93998 -0.21981,1.41789 0.0582,0.12446 -0.11212,0.37614 0.0969,0.41685 0.88284,-0.0585 0.30904,0.58298 0.69294,0.85291 -0.34214,0.33774 0.0244,0.78826 0.73335,0.72836 0.43959,0.29919 1.07278,0.24331 1.63813,0.35228 l 0.0736,0.0448 c 0.38778,-0.10404 0.0245,-0.72353 0.20718,-1.01432 0.51323,-0.34366 -0.20283,-0.45485 -0.61814,-0.53103 0.0274,-0.33275 0.26259,-0.74304 0.21784,-1.13747 0.23923,-0.2064 0.75099,-0.0848 1.11881,-0.12006 l -0.0149,0.53094 c 0.18821,0.46487 0.40821,0.92446 0.12828,1.42682 -0.43537,0.34603 -0.20149,0.86785 0.62785,0.73084 0.32264,-0.28321 0.35317,-0.75168 -0.0804,-1.04175 0.56867,-0.53073 1.11997,0.32514 1.3861,0.60116 -0.0255,0.3657 1.32511,0.75896 0.98294,0.21235 -0.28172,-0.41656 -0.56593,-0.8647 -1.16271,-1.16373 0.0169,-0.28998 -0.30591,-0.44892 -0.51256,-0.68143 -0.27438,-0.51775 0.92277,-0.55614 1.32949,-0.29182 0.37686,0.30057 0.6089,-0.11077 0.11594,-0.20101 0.11778,-0.45323 -0.55455,-0.70288 -0.75334,-1.04554 -0.24517,-0.39883 0.35093,-0.72371 0.47053,-1.00707 -0.74221,-0.0978 -0.87992,-0.65893 -1.14431,-1.03193 -0.0424,0.27079 -0.61393,0.63737 -0.40714,0.94708 -0.39146,0.39072 -0.2133,0.90337 -0.19158,1.3428 -0.38873,0.18762 -0.1672,0.38452 -0.0853,0.62107 -0.61435,0.26479 -0.31061,-0.34619 -0.56846,-0.50332 -0.0127,-0.48721 -0.72194,-0.78357 -0.99598,-1.2129 0.12473,-0.33506 -0.33466,-0.51389 -0.36161,-0.82807 0.1997,-0.42706 0.3237,-0.84131 0.26038,-1.28998 0.68927,-0.44553 -0.67313,-0.6391 -0.21405,-1.09468 0.22086,-0.37425 0.42402,-0.90652 -0.18371,-1.18138 -0.43025,-0.35212 -0.0683,-0.76225 -0.19938,-1.15243 -0.35117,-0.0477 -0.85403,-0.20224 -1.27169,-0.19685 -0.25089,0.003 -0.47094,0.0655 -0.60781,0.24375 -0.36841,0.38217 -0.14434,0.8521 -0.46111,1.23525 -0.16785,0.0992 -0.24225,0.20322 -0.2578,0.31006 z", +2.88035, 4.06242, +"M 1.25865 -4.0624 c -0.26985,0.16593 -0.42018,0.52485 -0.45144,0.83652 -0.0532,0.14065 -0.26733,-0.18208 -0.24919,0.11733 -0.28494,0.18546 0.14687,0.48052 0.0223,0.77037 0.036,0.36289 0.3756,0.58792 0.53905,0.88077 -0.13707,-0.006 -0.45978,0.15371 -0.4101,-0.0997 -0.0108,-0.31743 -0.1796,-0.59765 -0.41569,-0.80388 -0.20831,-0.2224 -0.50043,-0.35247 -0.56789,-0.66266 -0.28582,-0.18946 -0.72788,-0.02 -0.85216,-0.40249 -0.34073,-0.28483 -0.60874,0.19553 -0.79607,0.42709 -0.15294,0.28679 -0.28387,0.62305 -0.36898,0.94692 0.0288,0.41155 0.59654,0.31526 0.78223,0.64991 0.21197,0.12691 0.79092,0.32794 0.42931,0.61615 -0.22783,0.17371 -0.51269,0.28054 -0.73081,0.21635 -0.3129,0.0885 -0.69087,0.0242 -0.91787,0.32227 -0.0986,0.0888 -0.18264,0.18327 -0.14058,0.32426 0.0153,0.33863 0,0.68711 0.12159,1.00883 -0.17136,0.30467 0.34515,0.28606 0.24024,0.61504 0.0458,0.34026 0.22841,0.60042 0.53816,0.73395 0.11715,0.34628 0.48027,0.43439 0.68656,0.10861 0.22092,-0.24425 0.13892,-0.64131 0.4966,-0.81417 0.22425,-0.28822 0.71346,-0.14432 0.87741,-0.50084 0.18991,-0.18243 0.5743,-0.40112 0.46598,0.0664 0.0489,0.38641 -0.2614,0.6663 -0.34171,1.01509 0.0213,0.33786 0.19593,0.66602 0.38507,0.93374 0.16136,0.28358 0.42527,0.5179 0.5243,0.8088 0.11306,0.0261 0.24555,0.005 0.31311,-0.099 0.17679,-0.18075 0.42474,-0.24465 0.67359,-0.22126 0.24753,-0.26223 0.54092,-0.49076 0.73684,-0.79584 0.0703,-0.37759 -0.42896,-0.49317 -0.57771,-0.73752 -0.0631,-0.34107 -0.18323,-0.61203 -0.31803,-0.91518 0.0979,-0.36538 -0.30776,-0.49131 -0.24159,-0.85374 -0.0624,-0.37632 -0.49732,-0.49981 -0.55581,-0.87137 -0.0398,-0.29907 -0.0805,-0.80571 0.373,-0.62533 0.25606,0.0228 0.19023,-0.34809 0.48675,-0.27109 0.24961,-0.0512 0.49133,-0.32109 0.67696,-0.0456 0.3421,-0.12553 0.19087,-0.82493 -0.23511,-0.63717 -0.36514,-0.0659 0.34354,-0.40056 0.18392,-0.66355 -0.01,-0.40846 -0.52884,-0.49985 -0.47624,-0.91853 -0.12166,-0.36074 -0.58136,-0.42643 -0.90604,-0.4595 z", +3.57088, 4.77385, +"M -1.37842 -4.77385 c -0.32004,0.38562 -0.90978,0.44109 -1.06475,0.98212 -0.33196,0.58155 -0.34433,1.24636 -0.0431,1.86247 0.63654,0.61117 -0.46462,0.56209 -0.81103,0.5768 -0.71739,0.43468 0.23093,1.04171 -0.0105,1.64117 0.14314,0.6155 0.45858,1.33418 1.13619,1.48914 0.64762,-0.0825 1.4885,0.94379 0.87455,1.42229 -0.20223,0.48484 -0.89031,0.9814 -0.1661,1.42189 0.23434,0.25918 0.59181,0.15737 0.78734,-0.0868 0.49244,-0.4069 1.22385,-0.34712 1.79188,-0.53942 0.40959,-0.0676 0.43978,-0.38024 0.52823,-0.71925 0.4924,0.34324 1.17879,0.64169 1.71133,0.1823 0.40615,-0.60741 0.1742,-1.49048 -0.17359,-2.078 -0.01,-0.55871 -0.45537,-1.1785 -1.0577,-0.79483 -0.47109,0.82821 -1.0013,-0.36652 -0.57886,-0.79192 0.0974,-0.61938 -0.40188,-1.41863 -1.12248,-1.2263 -0.615,0.15415 -0.83256,-0.44564 -0.6852,-0.84049 -0.60947,-0.41783 0.57646,-1.01268 -0.19227,-1.48999 -0.1719,-0.39383 -0.74183,-0.82494 -0.92398,-1.01118 z", +3.57088, 3.49495, +"M -2.51747 -3.49406 c -0.44274,0.0168 -0.80575,0.24519 -0.65317,0.74056 0.77847,0.68723 0.006,1.14574 -0.40024,1.60094 0.45273,0.85169 -0.057,2.25152 1.13658,2.51484 0.58996,0.19997 -0.83942,0.82749 0.19445,1.21761 0,0.4092 0.84626,1.20435 1.14506,0.8068 0.96341,-0.49284 2.10194,-0.48523 3.16453,-0.62008 1.00752,-0.34932 1.59197,-1.40776 1.48958,-2.45213 -0.18766,-1.01556 -0.54571,-2.14247 -1.52062,-2.68748 -0.56572,-0.6585 -2.34805,-1.70658 -2.30696,-0.17264 1.19275,1.31973 -1.71147,1.34573 -1.07034,-0.0774 0.0918,-0.5639 -0.60964,-0.89245 -1.17887,-0.87092 z", +2.19827, 3.72855, +"M 1.79578 -3.16055 c 0.29134,0.9127 -0.8513,1.88012 -1.60506,1.23145 -0.61184,0.26144 -1.4819,1.48613 -0.34626,1.65621 0.20292,0.5854 -0.87432,1.11229 -0.86456,1.82626 -0.34284,0.66001 -1.30935,-0.58756 -1.16324,0.49712 0.015,0.16218 -0.0225,0.37679 0.0868,0.50798 0.35875,0.66438 1.22487,1.01087 1.95492,0.77514 0.59338,-0.43345 1.13653,0.4314 1.81488,0.39374 0.23014,-0.39462 0.28884,-0.97791 0.31677,-1.46193 0.0963,-1.02031 -0.0218,-2.07603 0.20824,-3.07268 -0.0106,-0.662 -0.26526,-1.55587 -0.0532,-2.3394 0.10891,-0.75342 -0.47035,-0.79317 -0.34929,-0.0139 z", +3.57085, 3.77374, +"M -1.00965 -3.77187 c -0.50773,-0.0455 -0.59851,0.75754 -1.18315,0.62357 -0.2759,0.006 -0.43238,-0.20174 -0.54732,-0.35854 -0.42974,-0.101 -0.98298,0.0786 -0.79185,0.62433 0.0918,0.27667 0.63885,0.21922 0.50031,0.65458 -0.008,0.28654 0.415,0.4124 0.12652,0.69333 -0.0968,0.21542 0.3362,0.39395 0.19527,0.57658 -0.37534,0.22876 0.12223,0.32999 0.18878,0.60483 0.26355,0.34866 -0.14544,0.74459 -0.0203,1.14239 0.22773,0.37599 0.42716,0.78503 0.71585,1.1349 0.20089,0.31178 0.59558,0.80482 0.97387,0.45305 0.53952,-0.18877 -0.0114,0.38539 -0.26603,0.32129 -0.005,0.24853 0.24187,0.42998 0.13101,0.70434 0.12782,0.27427 0.66178,0.50327 0.90612,0.28229 -0.19362,-0.28539 -0.38278,-0.53996 -0.23003,-0.90337 0.0118,-0.18256 0.14722,-0.40585 -0.0853,-0.48031 0.11501,-0.13614 0.31125,-0.45293 0.29528,-0.0705 0.13823,0.35583 0.51741,0.5319 0.87087,0.59257 0.22815,-0.32159 0.48104,-0.66059 0.8381,-0.85811 0.36776,-0.32583 0.73175,-0.66601 1.02963,-1.05813 0.31551,-0.18006 0.54504,-0.50482 0.93287,-0.49481 -0.0706,-0.38435 -0.81564,-0.26725 -0.51007,-0.7296 -0.004,-0.20098 0.28139,-0.50601 0.11752,-0.63332 -0.38126,0.008 -0.77281,0.0549 -1.14464,-0.0458 0.22089,-0.13301 0.47335,-0.47944 0.54081,-0.80185 0.14915,-0.29117 0.0598,-0.94753 -0.38205,-0.76085 -0.38265,-0.0285 -0.7182,-0.62895 -1.06013,-0.13102 -0.15706,0.19112 -0.33864,-0.13478 -0.29078,-0.28203 0.22718,-0.13574 0.44603,-0.63936 0.0285,-0.63858 -0.11854,0.35338 -0.58257,0.49089 -0.85134,0.14477 -0.29235,-0.20085 -0.66289,-0.31351 -1.02838,-0.30604 z", +3.57089, 5.62272, +"M -1.42379 -5.622 c -0.43389,0.0339 0.14764,1.23134 -0.27034,1.52136 -0.32134,0.64017 -0.3091,1.54516 -1.19918,1.59638 -0.5274,0.17075 -1.08366,0.90166 -0.25472,1.09547 0.18208,0.59783 0.78062,1.0544 0.80096,1.66886 -0.42354,0.53578 -1.0075,1.1037 -0.51402,1.81991 -0.22824,0.69684 -0.48371,1.55859 -0.0453,2.29815 0.0422,0.68578 0.8206,0.79979 1.16895,1.23743 0.21794,0.0348 0.4294,-0.063 0.61318,-0.16915 0.77997,-0.43845 0.0476,-1.6467 0.62273,-2.13958 0.98799,-0.075 0.80763,-1.11489 1.07434,-1.82644 0.15326,-0.73964 1.0527,-0.44914 1.60996,-0.48531 0.28374,0.01 0.59117,0.0806 0.75616,-0.21396 0.52814,-0.37956 0.96391,-1.07548 0.28243,-1.5707 -0.29818,-0.54672 -1.30735,-0.15148 -0.43951,0.146 0.46422,0.42259 -0.74074,0.6148 -1.00937,0.33025 -0.36553,0.13004 -0.87668,0.44845 -0.74154,-0.26028 0.0857,-0.69248 0.10805,-1.45821 -0.47727,-1.77811 -0.56593,-0.56035 0.55259,-0.94649 0.6444,-1.55057 0.2319,-0.78726 -0.94437,-0.99379 -1.45289,-1.28073 -0.40803,0.36815 -0.78127,0.16543 -0.91525,-0.37606 -0.10931,-0.0486 -0.19174,-0.0678 -0.25373,-0.0629 z", +3.57089, 3.9589, +"M -0.662738 -3.95715 c -0.22732,0.1856 -0.1616,0.62065 -0.53242,0.4242 -0.47422,0.18596 -1.1086,-0.11391 -1.44717,0.37963 -0.0317,0.5894 -0.93935,0.14582 -0.92847,0.72408 0.18671,0.31101 0.54772,0.37476 0.774,0.25063 0.73663,0.38029 -0.26627,0.73927 -0.27541,1.18012 -0.16873,0.24378 -0.22553,0.49255 -0.0791,0.74385 -0.35807,0.49099 0.49544,0.79295 0.89329,0.76898 0.7408,0.0465 -0.0421,0.63402 -0.3488,0.72743 -0.19071,0.30445 -0.16117,0.71804 -0.63596,0.65942 -0.0994,0.45223 -0.3579,0.95834 0.0972,1.33927 0.29409,0.53974 0.96448,0.4094 1.42438,0.6058 0.25557,0.31566 0.59274,-0.11505 0.78137,-0.28179 0.43541,-0.29546 0.89088,-1.01334 1.42439,-0.89697 0.37087,0.20728 0.82182,0.38467 1.17308,0.10018 0.30848,0.23171 0.74947,0.19845 1.07289,0.43056 0.23849,0.006 0.56519,-0.37111 0.53108,-0.64333 0.0427,-0.41341 0.67275,-0.95516 0.002,-1.22669 -0.51332,0.33701 -1.04337,-0.18935 -1.52993,-0.35215 -0.31537,-0.10025 -1.01146,-0.23443 -0.48651,-0.62826 0.0794,-0.34626 0.44388,-0.30417 0.61988,-0.4711 -0.5035,-0.3571 -0.4592,-1.16755 -1.13992,-1.30979 0.084,-0.42636 0.24714,-0.98594 0.42956,-1.45855 -0.12383,-0.36592 -0.23396,-1.20431 -0.77535,-0.74854 -0.42722,0.24522 -0.7282,-0.3551 -1.04407,-0.31698 z", +4.35997, 4.86053, +"M 4.12802 -4.85771 c -0.10456,-0.0226 -0.24399,0.0881 -0.41693,0.42159 -0.2125,0.98079 -0.39661,2.00485 -1.27137,2.64164 -0.55259,0.76964 -0.84457,2.28577 -2.02939,2.16135 -0.53939,-0.50526 -1.4269,0.18538 -2.12311,0.20849 -0.55867,0.36525 -1.1619,-0.53149 -1.67378,0.28501 -0.92928,0.12919 -0.84737,1.30207 -0.21641,1.57615 -0.23706,0.6136 -1.50686,1.78461 -0.11541,1.86052 0.32445,0.23972 0.55181,0.97448 0.94742,0.25664 0.58659,-0.89664 1.44208,-1.65942 1.52995,-2.76437 0.89443,-0.40943 1.08676,1.66279 2.17983,1.45475 1.174,0.49699 -0.92964,1.24862 -0.11145,1.5821 0.52277,-1.10045 2.1059,-0.15978 2.383,-1.305 0.26784,-0.82205 1.53393,-1.83991 0.82737,-2.6377 -0.22347,-0.70652 -1.39017,-0.1269 -1.3248,-0.76992 -0.23832,-0.99719 0.89102,-1.4275 1.08066,-2.29858 -0.19297,-0.68688 0,-1.06432 0.50602,-1.52073 0.12078,-0.40486 0.0586,-1.10219 -0.17153,-1.15194 z", +2.04794, 5.74865, +"M 1.10481 -5.74852 c -0.2228,0.001 -0.42374,0.10801 -0.27902,0.38066 -0.22773,0.32416 -1.04651,0.01 -0.86657,0.6221 0.26376,0.4125 0.0107,0.98862 -0.32022,1.27218 0.2249,0.43579 0.30114,0.9337 0.36381,1.39786 -0.18081,0.1263 -0.35082,0.59103 -0.47477,0.5752 0.13163,-0.4456 -0.6191,-0.80374 -0.54723,-0.18253 0.0335,0.4939 0.30706,0.8021 0.65488,1.16755 0.0573,0.18913 0.50349,0.27841 0.054,0.30188 -0.32151,0.0134 -0.70298,0.15083 -0.96036,0.26819 -0.004,0.5051 -0.55904,0.90049 -0.23512,1.41321 -0.58144,0.13334 -0.38504,0.76784 -0.14975,1.12213 0.1297,0.3844 0.11185,0.7896 -0.32623,0.90896 -0.31629,0.49376 0.60887,-0.10276 0.51957,0.45041 -0.50415,0.22985 -0.21881,0.79349 -0.0156,1.13687 0.0134,0.25246 0.20574,0.68606 0.45883,0.6615 0.0963,-0.10895 0.22038,-0.21662 0.23453,-0.37013 -0.0641,-0.49914 0.3279,-0.12706 0.46184,0.0763 0.39469,0.33331 0.98388,0.17352 1.28451,-0.20657 0.25784,-0.20591 0.90771,-0.24636 0.52498,-0.65428 0.40076,-0.52758 -0.33316,-0.93582 -0.19243,-1.46581 0.0606,-0.56794 -0.0204,-1.15758 0.12958,-1.71117 0.1498,-0.39418 -0.30538,0.12251 -0.36231,-0.28414 -0.0417,-0.31502 0.45507,-0.37624 0.54784,-0.65519 0.36583,-0.13394 0.0559,-0.67183 0.39269,-0.91255 0.2087,-0.31728 -0.37429,-0.20735 -0.2216,-0.60377 -0.11082,-0.46181 -0.47329,-0.89905 -0.93241,-1.04485 -0.14753,0.0856 -0.34858,0.34434 -0.37436,-0.04 0.25058,-0.4456 -0.0889,-0.88442 0.0608,-1.31458 -0.11306,-0.4522 0.68191,0.0944 0.52617,-0.54182 0.2472,-0.31727 0.41213,-0.71248 0.436,-1.11462 -0.0466,-0.2419 0.0663,-0.32026 0.29827,-0.3073 0.43849,-0.20873 -0.33546,-0.1678 -0.47237,-0.3142 -0.0671,-0.0208 -0.14373,-0.032 -0.21799,-0.0316 z", +3.57088, 2.80202, +"M -0.301059 -2.80177 c -0.17254,0.005 -0.33301,0.071 -0.43996,0.26942 0.0409,0.2666 0.3491,0.47076 0.41858,0.69966 -0.36962,0.1128 -0.73032,0.3493 -1.08495,0.0913 -0.38249,0.0613 -0.25611,0.72381 0.036,0.88696 0.2585,0.30716 -0.38849,0.35691 -0.58937,0.39089 -0.44316,0.0903 -0.23306,0.50499 -0.19046,0.77618 -0.15188,0.28342 -0.52426,0.566 -0.8221,0.58572 0.13061,-0.25419 0.13318,-0.51381 -0.18414,-0.64646 -0.2523,-0.20486 -0.5502,0.37635 -0.34497,0.58256 0.0492,0.32508 -0.0329,0.76492 0.43389,0.8515 0.34683,0.12336 0.70559,0.1523 1.03297,0.318 0.37589,0.0865 0.73238,-0.13092 1.03003,-0.32214 0.24664,0.20939 0.57748,0.44613 0.93799,0.5041 0.31649,0.14136 0.22886,-0.80563 0.61876,-0.47421 0.16196,0.33427 0.30384,0.70629 0.62118,0.93166 0.24438,-0.0315 0.44964,0.28662 0.6275,0.0294 0.27443,-0.16145 0.69426,0.0631 1.03638,0.0219 0.26986,0.26652 1.04494,-0.002 0.59931,-0.38117 -0.10676,-0.38309 -0.23137,-0.76018 -0.4295,-1.11046 0.008,-0.29153 -0.0528,-0.52528 -0.27889,-0.7016 0.0236,-0.29755 0.67185,-0.5939 0.17224,-0.85368 -0.25747,-0.317 0.0128,-0.57784 0.20261,-0.8357 -0.15225,-0.23193 -0.67612,-0.3641 -0.45235,-0.74897 0.0316,-0.51263 -0.46331,-0.52312 -0.81311,-0.58111 -0.28658,-0.15328 -0.55917,0.57451 -0.89206,0.23687 -0.31681,-0.0816 -0.31441,-0.59906 -0.73342,-0.41882 -0.15487,-0.0489 -0.33957,-0.10634 -0.51211,-0.1018 z", +3.16396, 6.28632, +"M -0.0681559 -6.28552 c -0.27397,0.0139 -0.48549,0.2094 -0.46561,0.68988 -0.13806,0.64257 -0.98468,1.02766 -0.7705,1.89187 -0.48185,0.70273 0.94628,1.12941 0.80874,1.464 -0.56632,0.088 -1.05088,0.56396 -1.53894,0.75344 0.69345,0.93338 -1.41697,0.2104 -1.09603,1.20509 0.35057,0.59033 0.4561,1.79086 1.47845,1.37459 0.45409,-0.19336 0.97791,0.0161 0.31471,0.32402 -0.53264,0.2974 -0.72491,1.05029 0.10387,0.95704 0.54052,0.2765 1.10715,0.49524 1.67639,0.62219 -0.14509,0.73633 -1.35981,0.56002 -1.27744,1.47226 -0.11997,0.30673 -0.90705,0.8281 -0.69143,0.97203 0.64811,0.19804 1.34276,0.11448 1.99522,0.29869 0.71434,-0.16557 1.26673,0.36676 1.79782,0.54674 -0.065,-0.01 0.33212,-0.10842 0.24134,-0.11937 0.49432,-0.10903 0.93445,-0.26785 0.43665,-0.76378 -0.0961,-0.57586 -0.91548,-1.29645 -0.12038,-1.6831 -0.4048,-0.51862 0.47421,-1.14462 -0.38966,-1.35703 -0.75428,-0.50253 -0.338,-1.22127 0.38603,-1.49396 0.40886,-0.84209 -0.29071,-1.68516 -0.11525,-2.56832 -0.038,-0.76264 0.0716,-1.5506 -0.0966,-2.2965 -0.33673,-0.72185 -1.00957,-1.22882 -1.66863,-1.66295 -0.20068,-0.36268 -0.65647,-0.64475 -1.00871,-0.62683 z", + ) +scratches=( +1.21098, 12.0742, +"M 0.000565603 -12.0742 c -0.13128,0.38351 -0.75628,0.6648 -1.19561,1.82211 -0.1414,0.37239 0.70808,0.91154 0.5936,1.35961 -0.4133,1.61789 0.0395,2.85731 0.44366,3.80288 0.14158,0.26984 -0.43294,2.12241 -0.31668,2.13113 0.97645,1.62823 0.21172,1.22883 0.13349,3.04219 0.57549,2.43115 0.2224,3.6139 0.12544,6.25854 0.33054,2.36608 -0.73036,1.37715 0.43984,5.73195 0.69244,-3.11326 0.13428,-4.81509 0.0535,-6.02599 0.14464,0.36647 0.22405,-0.58222 0.79938,-1.15807 -0.0141,-0.45337 -0.0246,-0.90699 -0.0494,-1.35961 -0.12372,-0.71424 -0.19704,-1.42486 -0.13769,-2.16524 -0.26034,-0.76585 0.18753,-1.53555 -0.15299,-2.29857 -0.018,-0.66796 0.41747,-1.89258 0.47387,-2.52801 -0.26969,-0.62391 -0.19911,-1.3802 -0.23483,-1.23662 -0.16028,-0.23971 -0.65345,-1.05872 -0.69112,-1.99936 0.0472,-0.699 0.26798,-1.33045 0.18587,-2.0593 0.0935,-0.5642 -0.25882,-1.6984 0.35341,-1.78749 0.55821,-0.1124 -6e-5,-0.993 -0.21304,-0.42272 -0.52661,-0.0264 0.002,-0.62728 -0.20154,-0.94723 -0.17458,-0.0432 -0.29981,0.0337 -0.38438,0.17519 -0.007,-0.1122 -0.0131,-0.22491 -0.0249,-0.33538 z m 0.0394,1.76526 c 0.16024,0.34312 0.14013,0.70048 -0.0104,0.99271 0,-0.34768 0.005,-0.67207 0.0104,-0.99271 z", +1.21091, 19.8304, +"M 0.362522 -19.83 c -0.0425,-0.0104 -0.0565,0.20572 -0.0739,0.68316 -0.17118,4.69021 -0.36552,8.35313 -0.44801,8.44393 -0.0551,0.0606 -0.0981,0.35879 -0.0961,0.66198 0.003,0.45283 0.0497,0.48001 0.26043,0.15399 0.14105,-0.2183 0.25847,-0.63823 0.26046,-0.93327 0.002,-0.29501 0.19851,-0.81366 0.43616,-1.1529 0.17211,-0.24575 0.26287,-0.41037 0.27647,-0.53486 0.0136,-0.12454 -0.0499,-0.20942 -0.18603,-0.29352 -0.25998,-0.1606 -0.30745,-0.89742 -0.19897,-3.07991 0.0784,-1.57793 0.0496,-3.16673 -0.0641,-3.53054 -0.0829,-0.26526 -0.1333,-0.40997 -0.1664,-0.41806 z m -0.52554,11.09286 c -0.0402,-0.006 -0.0675,0.0911 -0.0755,0.28371 -0.0115,0.27886 0.0511,0.43465 0.13901,0.34675 0.0438,-0.044 0.0678,-0.12308 0.0718,-0.21498 h 5.3e-4 c 0.004,-0.0919 -0.013,-0.19595 -0.0512,-0.29145 -0.0317,-0.0792 -0.0606,-0.12035 -0.0848,-0.12403 z m 0.13952,1.125 c -0.007,-9.6e-4 -0.0143,0.001 -0.0217,0.006 -0.11779,0.0728 -0.22286,1.22667 -0.23307,2.56419 -0.004,0.48057 -0.0157,0.84616 -0.032,1.15393 -0.11018,0.1207 -0.22863,0.25041 -0.36277,0.42995 -0.0519,-0.0854 -0.0727,-0.0405 -0.0842,0.12247 -0.15026,0.2185 -0.30279,0.48437 -0.4377,0.83975 -0.11105,0.29241 0.38748,0.68769 0.55189,1.06091 -0.003,0.13173 0.002,0.29377 0.006,0.45631 -0.24328,1.08473 -0.099,1.99333 0.14417,2.75642 0.002,0.0868 0.0117,0.25962 0.0109,0.30282 -0.005,0.2518 0.103,0.52662 0.23926,0.61082 0.0341,0.0211 0.067,0.0269 0.0966,0.0191 0.0622,0.28054 -0.21254,1.2988 -0.31004,1.80195 -0.0228,-0.0699 -0.058,-0.1111 -0.1044,-0.1111 -0.12534,0 -0.22789,0.29714 -0.22789,0.66094 0,0.36375 0.0455,0.66198 0.10128,0.66198 0.0558,0 0.1583,-0.29823 0.22789,-0.66198 0.0132,-0.0692 0.0186,-0.13206 0.0238,-0.19482 0.90374,1.53576 0.17148,1.18929 0.0946,2.97243 0.57549,2.43115 0.22254,3.6139 0.12557,6.25853 0.33054,2.36608 -0.73044,1.37714 0.43976,5.73195 0.69244,-3.11326 0.13401,-4.81509 0.0532,-6.02599 0.14464,0.36647 0.2241,-0.58222 0.79943,-1.15807 -0.0141,-0.45337 -0.0243,-0.90698 -0.0491,-1.3596 -0.12372,-0.71424 -0.19733,-1.42486 -0.13798,-2.16525 -0.26033,-0.76585 0.18756,-1.53554 -0.15296,-2.29856 -0.018,-0.66796 0.41749,-1.89257 0.47387,-2.52802 -0.26969,-0.6239 -0.19889,-1.38019 -0.23461,-1.23661 -0.16028,-0.23971 -0.65375,-1.05872 -0.69143,-1.99936 0.0472,-0.699 0.26815,-1.33046 0.18605,-2.05931 0.0935,-0.5642 -0.25876,-1.6984 0.35346,-1.78749 0.55822,-0.1124 8e-5,-0.99299 -0.21291,-0.42271 -0.10411,-0.005 -0.1661,-0.0335 -0.20153,-0.077 10e-4,-0.13439 10e-4,-0.26153 -10e-4,-0.37982 0.0406,-0.17118 0.0872,-0.35502 10e-4,-0.49041 -0.0109,-0.003 -0.0199,-8.1e-4 -0.0305,-0.003 -0.0297,-0.26499 -0.0801,-0.43408 -0.1633,-0.43408 -0.17193,0 -0.23233,-0.58849 -0.16124,-1.572 0.0586,-0.81059 0.0233,-1.43103 -0.0786,-1.44539 z m -0.66869,13.69167 c -0.0402,-0.006 -0.068,0.091 -0.076,0.2837 -0.0115,0.27886 0.0511,0.43465 0.13901,0.34675 0.0439,-0.044 0.0684,-0.12256 0.0723,-0.21446 0.004,-0.0919 -0.013,-0.19647 -0.0512,-0.29197 -0.0317,-0.0792 -0.0601,-0.12034 -0.0842,-0.12402 z m 0,1.05833 c -0.0402,-0.006 -0.068,0.0911 -0.076,0.28371 -0.0115,0.27886 0.0511,0.43465 0.13901,0.34675 0.0439,-0.044 0.0684,-0.12308 0.0723,-0.21498 0.004,-0.0919 -0.013,-0.19595 -0.0512,-0.29145 -0.0317,-0.0792 -0.0601,-0.12035 -0.0842,-0.12403 z", +1.49495, 18.3425, +"M -0.389083 -18.3412 c -0.0137,-0.002 -0.0282,-0.002 -0.0419,0.002 -0.10038,0.0279 -0.19454,0.22976 -0.24185,0.70177 -0.26567,1.67026 -0.34483,3.24287 -0.40257,4.9351 -0.13546,0.59246 -0.11445,1.16489 -0.0517,1.73632 -0.0585,0.4088 -0.0804,0.92918 0.002,1.32964 -0.12052,1.75209 -0.60079,3.29057 -0.2346,5.20847 0.16549,1.86259 -0.34446,4.07682 0.14933,5.25032 0.0936,0.18527 0.19288,-0.31455 0.29921,-0.15916 0.13603,-0.0189 0.22781,-0.1762 0.28991,-0.41806 0.0507,0.92595 0.15436,1.84189 0.32038,2.69544 0.53221,-0.0551 0.41124,0.9134 0.20775,1.79317 0.51184,0.22894 0.34367,2.25374 0.002,2.89388 -0.0368,0.48543 -0.0891,1.00555 -0.13539,1.53634 0.0369,-1.13406 0.0173,-2.27104 -0.57621,-2.24896 -0.21034,3.7268 -0.29522,7.48925 -0.0279,11.21121 0.34301,0.69517 0.62318,-0.48978 0.76737,-0.70229 -0.15983,-1.72878 -0.22984,-3.51098 -0.2041,-5.28185 0.0306,0.26264 0.0729,0.51868 0.13383,0.76275 0.76367,0.6551 0.19733,-2.26198 0.72554,-2.8298 0.19862,-1.54766 0.11464,-3.48741 0.30178,-5.14232 -0.27355,-1.32725 -0.3366,-3.24034 0.42067,-3.55069 0.7031,-1.9288 -0.89779,-1.8191 -0.56743,-3.27577 0.0274,-1.9927 -0.44524,-3.31209 -0.79632,-4.81779 -0.27045,1.00189 -0.45267,2.49784 -0.54364,3.82767 -0.0214,-0.31841 -0.0436,-0.64831 -0.0615,-0.91622 -0.0602,-1.06935 0.3048,-2.00573 0.18499,-3.34967 0.15293,-0.0682 0.31221,-0.28396 0.43977,-0.72089 0.4395,-1.55568 -0.22239,-3.13405 -0.0129,-4.73201 -0.24661,-1.51874 -0.005,-3.03839 -0.11162,-4.46122 0.17729,-0.52717 -0.0266,-1.24147 -0.23461,-1.27745 z m 0.33951,11.62978 c 2.4e-4,-9.5e-4 2.7e-4,-0.002 5.1e-4,-0.003 h -0.002 c 2.4e-4,0.001 7.7e-4,0.002 10e-4,0.003 z", +1.53299, 18.3425, +"M -0.351212 -18.3412 c -0.0137,-0.002 -0.0281,-0.002 -0.0418,0.002 -0.10036,0.0279 -0.19452,0.22975 -0.24183,0.70176 -0.26567,1.67026 -0.34483,3.24287 -0.40256,4.9351 -0.13547,0.59246 -0.11444,1.1649 -0.0517,1.73633 -0.0484,0.33819 -0.0679,0.74913 -0.0279,1.10898 -0.19071,1.02501 -0.32009,2.2804 -0.38034,3.36517 -0.0761,1.42435 -0.0331,2.95284 0.15555,4.37751 -0.0636,1.14999 -0.12615,2.23412 0.16949,2.93677 0.0697,0.13803 0.14251,-0.10384 0.21913,-0.17208 -0.005,0.0233 -0.01,0.047 -0.015,0.0703 0.51186,0.22893 0.34366,2.25375 0.002,2.89388 -0.1252,1.65317 -0.43757,3.69316 -0.0424,5.2772 0.0544,0.0467 0.10184,0.0733 0.14364,0.0858 -0.12761,3.049 -0.14573,6.11235 0.0724,9.1488 0.343,0.69517 0.62267,-0.48977 0.76686,-0.70228 -0.15983,-1.72878 -0.22934,-3.51098 -0.20359,-5.28185 0.0306,0.26264 0.0724,0.51867 0.13332,0.76274 0.76367,0.6551 0.19733,-2.26198 0.72554,-2.8298 0.19862,-1.54766 0.11465,-3.48741 0.30179,-5.14232 -0.27356,-1.32725 -0.3361,-3.24034 0.42116,-3.55069 0.7031,-1.9288 -0.89829,-1.8191 -0.56793,-3.27577 0.0274,-1.9927 -0.44524,-3.31209 -0.79634,-4.81779 -0.0429,0.15891 -0.0825,0.33356 -0.12092,0.5147 -0.005,-0.41675 -0.0275,-0.80863 -0.0698,-1.17513 0.0749,-0.11708 0.14656,-0.28021 0.21035,-0.49867 0.4395,-1.55568 -0.22191,-3.13405 -0.0124,-4.73201 -0.24662,-1.51874 -0.005,-3.0384 -0.11163,-4.46123 0.1773,-0.52717 -0.0266,-1.24146 -0.23461,-1.27744 z m 0.33952,11.62978 c 2.6e-4,-9.5e-4 2.9e-4,-0.002 5.3e-4,-0.003 h -0.002 c 2.4e-4,0.001 8e-4,0.002 10e-4,0.003 z m -0.0956,9.67279 c 0.34693,0.1444 0.2326,0.99256 0.0522,1.77251 0.51183,0.22894 0.34374,2.25373 0.002,2.89388 -0.0368,0.48543 -0.0891,1.00555 -0.13539,1.53634 0.0309,-0.95055 0.0204,-1.90052 -0.33279,-2.17093 0.0287,-0.40839 0.0871,-0.76874 0.23823,-0.93121 0.1206,-0.9398 0.13944,-2.0231 0.17568,-3.10059 z", +1.20633, 23.4716, +"M 1.20633 -23.4715 c -0.5053,0.33607 -0.23791,1.76733 -0.95755,1.18391 l -0.14986,-0.19483 c -0.008,-0.0416 -0.016,-0.007 -0.0238,0.0713 v 5.2e-4 c 0.18164,0.13239 0.32232,0.3276 0.39534,0.62063 0.0427,0.088 0.061,0.19852 0.061,0.32143 -0.002,0.4222 -0.235,0.98918 -0.51157,1.29759 -0.021,1.53032 -0.0353,3.79606 -0.046,6.48384 0.0137,0.012 0.0215,0.0282 0.0155,0.0491 -0.001,0.008 -0.0116,0.0176 -0.0155,0.0264 -0.003,0.66229 -0.002,1.56265 -0.005,2.27222 -0.26217,1.91668 -0.35258,3.7582 -0.4196,5.72264 -0.4378,1.91459 0.36031,3.66604 0.19897,5.64617 -0.22442,0.63928 -0.0753,1.29189 0.201,1.54461 -0.003,11.37386 0.0137,22.45681 -0.006,21.87567 0.14362,-0.69488 -0.32321,-2.78058 0.72811,-2.35232 -0.12814,0.70466 0.19505,1.16669 0.36795,1.67432 -0.0668,-2.83822 -0.14226,-12.31522 -0.15967,-21.95783 0.0124,-0.0381 0.0257,-0.0691 0.0377,-0.11007 0.42336,-1.49849 0.0674,-3.0137 -0.0413,-4.54288 2.1e-4,-0.48242 10e-4,-0.94352 0.002,-1.42058 0.007,-0.0756 0.0123,-0.15121 0.0222,-0.22686 -0.008,-0.051 -0.0143,-0.102 -0.0217,-0.15296 0.008,-5.2851 0.0362,-10.20918 0.10488,-13.52062 -0.0288,0.0211 -0.0623,0.0406 -0.10282,0.0573 -0.22574,-0.68079 -0.0267,-0.7215 0.11576,-0.56947 0.0507,-2.17256 0.11869,-3.59653 0.20978,-3.79925 z m -2.21742,27.16423 c -0.21037,3.7268 -0.29472,7.48924 -0.0274,11.2112 0.343,0.69518 0.62317,-0.48977 0.76737,-0.70228 -0.19468,-2.10548 -0.25887,-4.29063 -0.17518,-6.43733 -0.14325,-1.11457 0.39523,-4.10729 -0.5643,-4.07159 z", +1.19276, 25.078, +"M -0.421376 -3.88054 c -0.27631,0.25272 -0.42545,0.90533 -0.20103,1.54461 0,0.0137 0,0.0271 0.003,0.0408 -0.0445,-0.0116 -0.0846,-0.0199 -0.13695,-0.0377 l -0.11678,-0.0403 0.0201,0.0682 c 0.1305,0.45681 0.22437,0.8044 0.24133,0.92553 0,0.015 0,0.03 -0.003,0.045 -0.003,8e-4 -0.005,0.002 -0.0109,-0.005 0.003,0.20217 -0.0377,0.38449 -0.14211,0.45011 0.0449,0.007 0.0822,0.0209 0.11626,0.0382 -0.0299,0.3032 -0.0693,0.6025 -0.11057,0.90072 -0.0932,0.0649 -0.2028,0.0993 -0.32401,0.078 -0.14565,0.51493 0.25239,1.08423 -0.0393,1.56063 0.0722,0.17488 0.13539,0.34219 0.17312,0.50901 0.003,0.14782 0.0111,0.29635 0.0254,0.44545 -0.0156,0.11938 -0.0498,0.24159 -0.11213,0.36897 0.24339,0.56784 0.14218,1.21602 0.18034,1.82263 0.0321,0.60964 -0.054,1.23666 0.0951,1.83296 0.21513,0.29946 -0.39643,0.31017 -0.11369,0.67955 0.039,0.74934 0.21111,1.48345 0.17364,2.23707 0.0111,0.43606 0.0354,1.12135 -0.22066,1.29191 0.64399,0.51467 -0.31361,0.91939 -0.18965,1.4857 0.0477,0.49885 0.30371,1.02019 0.0961,1.48363 -0.0396,0.59756 -0.0501,1.20341 0.21238,1.7234 0.0946,0.62129 -0.0953,1.21664 -0.0124,1.84589 -0.0453,0.5497 0.3098,1.19228 -0.0542,1.66449 -0.19063,0.44185 0,0.91783 -0.19327,1.33791 -0.0311,0.51712 -0.0706,1.05694 -0.0429,1.57355 -0.0493,0.5227 -0.0711,1.06009 -0.003,1.58078 0.079,0.51085 0.0409,0.93085 -0.0816,1.42058 0.0312,0.0244 0.0439,0.0586 0.0692,0.0863 l 1.44333,-3.35897 c -0.0392,-0.12324 -0.10192,-0.24394 -0.21963,-0.35346 -0.0796,-0.4752 0.0952,-0.97383 0.23461,-1.4056 0.16936,0.27841 0.1652,0.98193 0.50075,1.20509 -0.0911,-0.20272 -0.15912,-1.62669 -0.20982,-3.79925 -0.14245,0.15203 -0.34149,0.11132 -0.11575,-0.56947 0.0405,0.0167 0.074,0.0363 0.10284,0.0574 -0.006,-0.28889 -0.0101,-0.65271 -0.0156,-0.96532 0.0822,-0.14175 0.16769,-0.28152 0.24908,-0.42891 -0.0214,-0.20087 -0.14751,-0.3117 -0.26252,-0.4191 -0.005,-0.33733 -0.0116,-0.6269 -0.0161,-0.98547 0.0805,-0.35753 0.10441,-0.72698 0.19428,-1.08055 0.0366,-0.47155 -0.0944,-0.90339 -0.21703,-1.34462 -0.0209,-2.51731 -0.0327,-5.33076 -0.0372,-8.29665 0.007,-0.051 0.0138,-0.10197 0.0217,-0.15297 -0.01,-0.0757 -0.0153,-0.15126 -0.0222,-0.22685 0,-0.47706 -0.003,-0.93817 -0.003,-1.42059 0.0257,-0.36017 0.0648,-0.71939 0.10441,-1.07797 0.10797,-0.15575 0.16115,-0.31721 0.0486,-0.4532 0.0116,-0.11133 0.0217,-0.22266 0.032,-0.33383 0.56079,-1.63193 0.75962,-1.19491 0.0356,-1.64228 -0.0274,-0.34604 -0.082,-0.69129 -0.1793,-1.0356 -0.0119,-0.041 -0.0254,-0.072 -0.0377,-0.11007 0.0175,-9.64261 0.0929,-19.11961 0.15967,-21.95783 -0.1729,0.50763 -0.49607,0.96966 -0.36793,1.67432 -0.80568,3.15608 0.55147,3.77736 -0.72101,19.52334 z", +0.670938, 8.19849, +"M -0.407338 -8.00763 c -0.0754,0.25511 -0.0986,0.76103 -0.002,1.48952 -0.15641,1.5163 0.005,3.60812 -0.2616,5.1103 0.11078,2.14938 0.16104,4.46253 0.31355,6.6328 0.0244,0.8744 0.0171,4.68192 0.38457,2.0748 0.22082,-1.3347 0.65056,-2.59474 0.58926,-4.39985 0.27685,-1.75982 -0.59717,-2.80885 -0.47885,-4.72632 -0.0715,-1.81309 0.41368,-3.66693 -0.0322,-5.23362 -0.11395,-1.10094 -0.38606,-1.37269 -0.51194,-0.94764 z", +0.670938, 12.9232, +"M -0.407338 -12.6223 c -0.0754,0.40213 -0.0986,1.19961 -0.002,2.34792 -0.15641,2.39013 0.005,5.68743 -0.2616,8.05531 0.11078,3.38804 0.16104,7.03423 0.31355,10.4552 0.0244,1.37832 0.0171,7.38006 0.38457,3.27049 0.22082,-2.10387 0.65056,-4.09006 0.58926,-6.93544 0.27685,-2.77398 -0.59717,-4.42755 -0.47885,-7.45005 -0.0715,-2.85794 0.41368,-5.78013 -0.0322,-8.24969 -0.11395,-1.7354 -0.38606,-2.16376 -0.51194,-1.49375 z", +0.753237, 9.39521, +"M -0.337287 -9.3947 c -0.0586,-0.007 -0.11261,0.0579 -0.15195,0.19068 h -5.1e-4 c -0.0754,0.25511 -0.0987,0.76083 -0.002,1.48932 -0.15642,1.51629 0.005,3.6081 -0.26149,5.11028 0.10925,2.11959 0.16037,4.39716 0.308,6.5412 -0.63693,1.04513 0.47877,2.68047 -0.28112,3.96927 0.31912,0.41893 0.25879,2.08373 1.06919,1.26659 0.80684,-0.22766 0.17536,-1.16368 0.17414,-2.66186 -0.30014,-0.12043 -0.46132,-0.32959 -0.54001,-0.58446 0.22741,-1.27036 0.61566,-2.49792 0.55705,-4.22299 0.27686,-1.75983 -0.59735,-2.80886 -0.47902,-4.72633 -0.0715,-1.81309 0.41383,-3.6671 -0.032,-5.23379 -0.0783,-0.7569 -0.23124,-1.12184 -0.36017,-1.13791 z", +1.73753, 21.1382, +"M 0.27454 -21.1377 c -0.0586,-0.007 -0.11258,0.0573 -0.15192,0.19016 l -5e-4,5.2e-4 c -0.0754,0.25511 -0.0987,0.76083 -0.002,1.48932 -0.15452,1.498 -4.5e-4,3.55549 -0.25371,5.05343 -0.15516,0.069 -0.19791,0.18561 -0.17881,0.37363 0.093,0.91418 -0.0185,1.41725 -0.27855,1.25677 -0.1455,-0.0898 -0.26453,-0.51355 -0.26459,-0.94155 3e-5,-0.49146 -0.137,-0.77825 -0.37155,-0.77825 -0.2589,0 -0.40127,0.42059 -0.47077,1.38907 -0.0191,0.26627 -0.0317,0.52238 -0.0367,0.76739 -0.0365,1.71506 0.26421,2.89312 0.85627,3.30781 0.5721,0.40073 0.5816,0.49454 0.39946,3.88917 -0.10265,1.91329 -0.16684,4.25278 -0.14263,5.19865 0.0283,1.10976 -0.0992,1.98889 -0.35968,2.47788 -0.50411,0.94668 -0.52832,1.39496 -0.0542,1.00149 0.28816,-0.23923 0.33626,1.20389 0.27647,8.26771 -0.0584,6.89886 -0.002,8.65365 0.28887,9.05165 0.33266,0.45496 0.37624,0.41244 0.55449,-0.53795 0.10638,-0.56717 0.0821,-1.77797 -0.0543,-2.6908 -0.13639,-0.91282 -0.17248,-1.61256 -0.0796,-1.55546 0.0928,0.0573 0.18032,-0.51603 0.19431,-1.27434 0.0252,-1.36423 0.11504,-1.96676 0.60204,-4.02456 0.13776,-0.58206 0.29511,-3.3592 0.34933,-6.1712 0.0542,-2.81205 0.20923,-5.22336 0.34467,-5.35884 0.13546,-0.13545 0.26493,-0.75165 0.28734,-1.36943 0.0309,-0.85348 -0.0157,-0.99638 -0.19431,-0.59428 -0.17402,0.392 -0.23993,0.42036 -0.25374,0.11007 -0.0102,-0.23043 0.0657,-0.50284 0.16846,-0.60565 0.1623,-0.16235 0.15642,-3.36764 -0.0145,-8.03723 -0.0279,-0.76399 0.0292,-1.38905 0.12663,-1.38906 0.0973,-1e-5 0.17671,-0.41671 0.17671,-0.92604 0,-0.90243 -0.0261,-0.92604 -1.04799,-0.92605 -0.0114,0 -0.0199,4.9e-4 -0.031,5.2e-4 0.001,-0.0895 0.002,-0.17939 0.008,-0.27285 -0.0715,-1.81309 0.41386,-3.6671 -0.032,-5.23379 -0.0784,-0.7569 -0.23125,-1.12184 -0.36021,-1.13791 z", +0.90975, 7.69929, +"M 0.5118 4.3328 0.0773,-1.89734 c -0.78022,-0.65432 -0.7026,-1.85535 0.0991,-2.36604 l 0.22155,-5.30816 c -0.0671,-0.11321 -0.12273,-0.0764 -0.193,-0.25561 -0.39953,-0.40971 -0.50958,-1.87041 -0.78623,-2.16685 l -0.14591,-0.0381 c -0.0432,0.0195 -0.10273,0.16373 -0.15446,0.23376 l -0.5399,11.53632 c 0.09,-0.0554 0.16763,-0.042 0.26343,-0.13249 0.2235,1.06334 -0.41852,2.98144 0.13712,3.761 1.10534,-0.76211 0.3114,-2.4459 1.02162,-3.36601 z", +0.909985, 21.0802, +"M 0.069295 -21.0802 c -1.60221,0.95118 0.0978,2.94503 -0.79529,4.45968 0.31909,0.41893 0.25829,2.08373 1.06866,1.26659 0.80687,-0.22766 0.17589,-1.16368 0.17467,-2.66185 -1.23089,-0.49394 -0.14943,-2.46581 -0.44751,-3.06442 z m -0.28475,6.45077 c -0.0432,0.0195 -0.10276,0.16407 -0.15449,0.2341 l -0.54004,11.53624 c 0.09,-0.0554 0.16777,-0.0423 0.26355,-0.13281 0.22352,1.06334 -0.41867,2.98145 0.13695,3.76101 0.11266,-0.0777 0.20122,-0.16697 0.27803,-0.262 -0.02,0.26698 -0.062,0.40312 -0.11938,0.34572 -0.0852,-0.0852 -0.1323,0.67721 -0.1323,2.13269 0,0.59617 -0.0104,1.04983 -0.0263,1.41593 -0.043,0.0648 -0.0864,0.12977 -0.12454,0.18552 -0.0367,0.0537 -0.0978,0.0547 -0.11316,0.11265 -0.0217,0.0815 0.0922,0.078 0.0744,0.15503 -0.0144,0.0623 -0.10165,-0.009 -0.1116,0.0537 -0.0128,0.0803 0.18314,0.1196 0.17,0.20206 -0.007,0.0452 -0.0103,0.091 -0.009,0.13746 -9.3e-4,1.7e-4 -0.002,0.003 -0.003,0.003 h -5.1e-4 c -0.0783,0 -0.1189,0.16869 -0.091,0.37517 0.0279,0.20649 0.12144,0.35145 0.20825,0.32194 0.003,-9.4e-4 0.005,0.001 0.008,0.001 0.0106,0.0622 0.0188,0.12677 0.0248,0.19224 10e-4,0.0292 0.002,0.0591 0.004,0.0884 0.002,0.0585 0.005,0.11669 0,0.17931 8.2e-4,0.0518 -0.0608,0.12352 -0.0594,0.17312 0.001,0.0496 0.0533,0.0771 0.0553,0.12454 0.002,0.0475 -0.046,0.11479 -0.0434,0.16019 0.002,0.0335 0.0533,0.17164 0.0863,0.27079 0.0126,0.33511 0.0159,0.66968 -0.007,1.00149 -0.0129,0.0186 -0.027,0.0231 -0.0424,0.008 -0.0679,-0.068 -0.10681,0.27415 -0.11419,0.92501 -0.066,0.23273 -0.1523,0.46252 -0.27183,0.68678 0.1062,0.21699 0.19947,0.37376 0.28527,0.49919 0.009,0.30425 0.0207,0.49363 0.0408,0.46354 -0.008,0.28451 -0.0302,0.75484 -0.0398,1.26349 -0.10361,0.44818 -0.1356,1.31544 -0.0109,1.44022 0.14782,0.14777 0.17589,1.00278 0.0796,2.44481 -0.0191,0.28562 -0.0175,0.6403 -0.003,0.9586 -0.0617,0.0399 -0.12502,0.089 -0.19225,0.1571 0.0518,0.38782 0.074,0.81499 0.0935,1.24953 -0.004,0.003 -0.009,0.003 -0.0124,0.007 -0.0863,0.0863 -0.11387,0.41392 -0.0672,0.79169 0.0438,0.35436 0.0791,0.9009 0.0791,1.21439 0,0.46794 0.0655,0.57783 0.36483,0.61443 0.0158,0.002 0.023,0.001 0.0372,0.003 0.0344,0.0746 0.0714,0.14651 0.11266,0.21445 0.15124,-0.0321 0.23686,-0.14678 0.29507,-0.28525 0.0212,0.0538 0.0649,0.0638 0.11575,0.0129 0.0515,-0.0515 0.0774,-0.33668 0.0873,-0.67231 0.29014,-0.88165 0.123,-3.135 -0.53848,-3.37654 l -5e-4,5.2e-4 c -0.0427,-0.0173 -0.0878,-0.0231 -0.13489,-0.0207 0.002,-0.84663 0.0224,-1.14112 0.0972,-1.12552 0.002,4.9e-4 0.005,0.004 0.008,0.005 0.1579,0.11986 0.38113,0.13515 0.67231,-0.0475 -0.022,-0.60336 -0.25202,-1.93024 -0.50488,-2.00556 -0.0135,-0.004 -0.027,-0.005 -0.0408,-10e-4 0.0589,-0.0887 0.12261,-0.19962 0.19431,-0.34623 -0.0435,-0.19088 -0.0688,-0.3762 -0.0847,-0.56017 0.0114,0.004 0.0236,0.008 0.0362,0.016 0.24339,0.15111 0.38658,-0.25127 0.37258,-1.04593 -0.006,-0.35248 0.0815,-0.86868 0.19431,-1.14722 0.12518,-0.30915 0.16568,-0.65349 0.10388,-0.88367 -0.0556,-0.20738 -0.10724,-0.52146 -0.11422,-0.69814 -0.007,-0.17668 -0.10248,-0.32443 -0.21188,-0.32763 -0.0382,-9.7e-4 -0.0689,-0.0206 -0.0946,-0.0522 0.007,-0.0407 0.0134,-0.0917 0.0212,-0.12815 0.0171,-0.0261 0.0359,-0.0485 0.0511,-0.0729 l 5.3e-4,-0.002 -0.047,-3.21014 c 0.0994,-0.6389 0.22457,-1.57045 0.1824,-1.57045 -0.0641,0 -0.11626,-0.10246 -0.11626,-0.22738 0,-0.12493 0.0594,-0.16741 0.13229,-0.0946 0.0729,0.0729 0.1328,-0.0128 0.1328,-0.18966 0,-0.17699 -0.0574,-0.3783 -0.12711,-0.44803 -0.0698,-0.0697 -0.0933,-0.26863 -0.0522,-0.44184 0.0465,-0.19637 -0.005,-0.3147 -0.13798,-0.3147 -0.11716,0 -0.21341,-0.13706 -0.21341,-0.30438 0,-0.16734 -0.0396,-0.47302 -0.0884,-0.67903 -0.0605,-0.2553 -0.0396,-0.32487 0.0661,-0.21911 0.10713,0.10714 0.15502,-0.0773 0.15502,-0.59582 0,-0.65769 0.18227,-0.88497 0.0692,-0.89452 -0.0382,-0.003 -0.10946,0.0186 -0.23151,0.0563 0.0311,-0.6426 0.004,-1.30921 0.36587,-1.77818 l -5e-4,-5.2e-4 0.077,-1.89756 c -0.78023,-0.65432 -0.70247,-1.85506 0.0992,-2.36574 l 0.22169,-5.30821 c -0.0671,-0.11321 -0.123,-0.0766 -0.19328,-0.2558 -0.39952,-0.40971 -0.50935,-1.87035 -0.78599,-2.16679 z m 0.0336,28.36158 c -0.0146,0.0334 -0.0293,0.0897 -0.0439,0.13384 -0.006,-0.0264 -0.0126,-0.0554 -0.0196,-0.0832 0.0197,-0.011 0.0416,-0.0302 0.0636,-0.0506 z", +0.70928, 12.466, +"M 0.18321 -12.4659 c -0.10784,-0.006 -0.2246,0.65736 -0.33539,2.3642 -0.2559,1.61556 0.0378,4.44866 0.86146,3.05511 -0.022,-1.62742 -0.25194,-5.20773 -0.50488,-5.40898 l -0.002,-0.002 c 4.3e-4,3.1e-4 6.4e-4,0.002 0.001,0.002 -0.007,-0.006 -0.0136,-0.01 -0.0207,-0.0103 z m -0.37155,7.36079 c -0.0907,0.007 -0.12097,0.50508 -0.0698,1.9544 -0.26241,4.289499 0.38667,9.178069 -0.45114,13.416749 1.02915,5.67045 1.03722,-1.11191 1.24077,-3.68918 0.0171,-0.0704 0.0353,-0.13161 0.0506,-0.1974 l 0.001,-0.005 -0.0532,-9.785969 c -0.32449,-0.66216 -0.58576,-1.7036 -0.71829,-1.69395 z", +0.791801, 10.8742, +"M 0.37094 -10.8739 c -0.0383,-0.003 -0.10962,0.0185 -0.23202,0.0563 -0.32348,0.10008 -0.3638,0.20621 -0.3638,0.95808 0,0.50923 -0.053,0.793 -0.13282,0.71313 -0.0852,-0.0852 -0.13229,0.67721 -0.13229,2.13269 0,0.59618 -0.0104,1.04983 -0.0263,1.41593 -0.043,0.0648 -0.0864,0.12977 -0.12454,0.18552 -0.0367,0.0537 -0.0978,0.0547 -0.11316,0.11266 -0.0217,0.0815 0.0922,0.078 0.0744,0.15503 -0.0144,0.0623 -0.10166,-0.009 -0.11161,0.0537 -0.0128,0.0803 0.18315,0.11959 0.17,0.20205 -0.007,0.0452 -0.01,0.091 -0.009,0.13746 -9.3e-4,1.7e-4 -0.002,0.003 -0.003,0.003 h -5.3e-4 c -0.0783,0 -0.11885,0.16869 -0.0909,0.37517 0.0279,0.20648 0.12145,0.35145 0.20826,0.32195 0.003,-9.4e-4 0.005,0.001 0.008,0.001 0.0245,0.14353 0.0418,0.2935 0.0284,0.45992 8e-4,0.0518 -0.0608,0.12351 -0.0594,0.17311 10e-4,0.0496 0.0533,0.0771 0.0553,0.12454 0.002,0.0475 -0.046,0.11479 -0.0434,0.1602 0.003,0.0454 0.11377,0.32348 0.11679,0.3669 0.0104,0.14968 0.0239,0.28357 0.0383,0.40928 -0.0199,0.3693 -0.0606,0.56165 -0.11834,0.50384 -0.0843,-0.0844 -0.12634,0.43821 -0.11526,1.43558 0.009,0.84768 0.0233,1.18693 0.0553,1.13894 -0.008,0.28451 -0.0302,0.75484 -0.0398,1.26349 -0.10361,0.44818 -0.13563,1.31545 -0.0109,1.44023 0.1478,0.14777 0.1759,1.00278 0.0796,2.44481 -0.0316,0.47191 -0.0123,1.14721 0.0434,1.5012 0.0959,0.60757 0.19674,0.59567 0.19274,-0.21446 -0.006,-1.40297 0.0164,-1.64026 0.14005,-1.5167 0.0647,0.0647 0.19682,-0.0363 0.29353,-0.22479 0.14898,-0.29044 0.13581,-0.38968 -0.0848,-0.65061 -0.14306,-0.1693 -0.24148,-0.32752 -0.21857,-0.35192 0.0229,-0.0244 -0.002,-0.23205 -0.0569,-0.46095 -0.0157,-0.0663 -0.0256,-0.11223 -0.0398,-0.16847 0.10073,-0.0561 0.22942,-0.23081 0.39328,-0.56585 -0.0435,-0.19088 -0.0689,-0.37621 -0.0848,-0.56018 0.0114,0.004 0.0236,0.008 0.0362,0.016 0.24339,0.15111 0.38658,-0.25127 0.37259,-1.04593 -0.006,-0.35248 0.0815,-0.86867 0.19428,-1.14721 0.12517,-0.30915 0.16568,-0.65349 0.10387,-0.88367 -0.0556,-0.20738 -0.1072,-0.52147 -0.11419,-0.69815 -0.007,-0.17668 -0.10247,-0.32443 -0.21188,-0.32763 -0.0396,-0.001 -0.0716,-0.0212 -0.0977,-0.0548 -0.006,-0.51267 -0.0453,-1.07976 -0.14057,-1.72237 -0.0104,-0.12615 -0.027,-0.22448 -0.0444,-0.32195 0.004,-0.009 0.006,-0.0184 0.0104,-0.0274 0.0792,-0.15448 0.12295,-0.41373 0.0971,-0.57619 -0.0258,-0.16259 -0.0261,-0.2425 -5.3e-4,-0.17828 0.0256,0.0642 0.35351,-2.15491 0.2894,-2.15491 -0.0641,0 -0.11628,-0.10246 -0.11628,-0.22738 0,-0.12493 0.0594,-0.16745 0.13229,-0.0946 0.0729,0.0729 0.13282,-0.0128 0.13282,-0.18965 0,-0.17699 -0.0574,-0.3783 -0.12713,-0.44803 -0.0698,-0.0697 -0.0933,-0.26863 -0.0522,-0.44184 0.0465,-0.19637 -0.005,-0.31471 -0.13798,-0.31471 -0.11715,0 -0.21344,-0.13705 -0.21344,-0.30437 0,-0.16734 -0.0396,-0.47302 -0.0884,-0.67903 -0.0605,-0.2553 -0.0396,-0.32487 0.0661,-0.21911 0.10713,0.10713 0.15504,-0.0773 0.15504,-0.59583 0,-0.6594 0.18355,-0.88659 0.0687,-0.89503 z m -0.77409,10.7518 c 0.008,0.0177 0.0132,0.12011 0.0176,0.27698 -0.03,0.0588 -0.0609,0.11849 -0.0967,0.18449 0.0414,-0.31691 0.0656,-0.49083 0.0791,-0.46147 z m -0.14833,8.34212 c -0.0352,-0.005 -0.064,0.002 -0.0842,0.0222 -0.0863,0.0863 -0.1139,0.41391 -0.0672,0.79168 0.0438,0.35437 0.079,0.90091 0.079,1.2144 0,0.46794 0.0655,0.57783 0.36484,0.61443 0.27919,0.0342 0.31816,-0.004 0.16586,-0.16433 -0.17018,-0.17883 -0.16531,-0.21039 0.0331,-0.21239 0.12763,-0.002 0.23204,0.0988 0.23204,0.22376 0,0.1249 0.0583,0.16907 0.1297,0.0977 0.14147,-0.14143 0.0967,-2.02722 0.0274,-1.95802 -0.0692,0.0692 -0.28162,-0.0722 -0.47181,-0.31419 -0.14263,-0.18155 -0.30326,-0.30098 -0.40875,-0.31523 z", +1.07687, 9.8574, +"M -0.468434 -9.85737 c 0.35117,1.50705 0.82497,2.82661 0.79752,4.82073 -0.33038,1.45668 1.2704,1.34706 0.56728,3.27586 -0.75726,0.31035 -0.69421,2.22344 -0.42064,3.55069 -0.18715,1.65491 -0.10345,3.59501 -0.30207,5.14267 -0.52822,0.56782 0.0385,3.48463 -0.72515,2.82953 -0.39519,-1.58404 -0.0832,-3.62405 0.042,-5.27722 0.3416,-0.64014 0.50986,-2.66493 -0.002,-2.89386 0.20349,-0.87978 0.32479,-1.84821 -0.20741,-1.79313 -0.33006,-1.69697 -0.41673,-3.64057 -0.32176,-5.41903 0.0788,-1.41878 0.27531,-3.13331 0.5735,-4.23627 z", +2.2155, 17.1585, +"M 0.126795 -17.1552 c -0.0862,0.0295 -0.10147,0.26481 0.15555,0.17053 -0.0201,-0.0566 -0.0417,-0.0964 -0.0625,-0.12402 -0.0181,-0.0239 -0.0356,-0.0379 -0.0522,-0.045 h -5.3e-4 c -0.0144,-0.006 -0.0281,-0.006 -0.0403,-0.002 z m -0.11575,1.07797 c -0.2067,8.5e-4 -0.36484,0.15284 -0.2589,0.56792 -0.78081,0.4633 -0.40071,1.63009 -0.15092,2.37195 -0.26111,0.38499 -0.0968,0.69767 0.0336,0.94413 0.003,0.15192 0.005,0.3124 0.008,0.46612 -0.0424,0.0281 -0.0954,0.0546 -0.17159,0.078 -0.38372,0.36544 -0.96946,0.62763 -0.47024,1.2516 0.61513,-0.37333 -0.39214,1.24462 0.37827,1.11983 0.58034,0.63299 -0.16417,1.58188 -0.29199,0.99788 -0.36309,0.82279 -0.74943,2.75375 0.30697,2.90059 0.65154,0.38277 -1.22994,0.47827 -0.32247,1.03353 0.12882,0.11405 0.2826,0.54247 0.4527,0.34778 0.0882,-0.10334 0.15261,-0.21193 0.20463,-0.32349 0.004,0.47543 0.008,0.94591 0.0124,1.42162 -0.1546,-0.15317 -0.30245,-0.264 -0.41445,-0.27802 -0.19592,-0.0245 -0.2839,0.23429 -0.11266,1.02733 0.39989,1.176989 -1.12924,1.251499 -0.25992,2.377629 0.20293,1.10216 -0.30896,2.46141 -0.11473,3.72122 -0.26596,1.39175 1.38674,0.67395 0.53589,2.24534 -0.60793,1.13701 0.0733,2.34518 0.5674,3.05614 -0.24691,0.6918 -0.4676,-0.15486 -0.46559,-0.52399 -0.52125,-0.0811 -0.56888,0.96424 -0.10543,1.27589 0.44555,0.85109 -0.8023,1.42473 0.10078,2.29133 0.72273,0.54138 -0.004,1.44593 -0.46149,0.78445 -0.46868,0.32104 0.99774,0.86268 0.33591,1.56889 -0.12715,0.56519 0.112,1.93607 0.42477,0.65009 0.31115,-0.77077 0.98546,-1.04884 1.25005,-1.8526 -0.41074,-0.17674 -0.96338,-0.29486 -0.21032,-0.51986 0.87294,-0.30163 0.89675,-2.52384 0.20465,-3.22254 0.0979,-0.4361 -0.17264,-0.70085 -0.44082,-0.96635 0.0414,-0.83119 0.0704,-1.69667 0.11163,-2.32389 0.0512,-0.6609 0.0902,-1.54857 0.11988,-2.55954 0.17206,-0.23191 0.19942,-0.56928 0.0243,-0.8847 0.002,-0.0714 0.002,-0.15084 0.004,-0.22324 0.21306,-0.76122 0.28736,-1.5621 0.0243,-2.17454 0.002,-0.29119 0.003,-0.5884 0.004,-0.88677 0.22603,-0.40201 0.27916,-1.31894 0.0305,-1.5658 -0.008,-0.008 -0.0188,-0.0119 -0.0279,-0.0186 -0.0212,-4.586229 -0.18235,-9.480359 -0.49194,-11.419969 0.21301,-0.40925 0.4383,-0.83985 0.42579,-1.43867 0.27437,-0.6706 -0.68641,-0.14121 -0.21238,-0.89969 -0.0211,-0.10544 -0.0977,-0.20384 -0.19741,-0.27854 l -0.001,-10e-4 c -0.11229,-0.0842 -0.25379,-0.13798 -0.37774,-0.13746 z m -1.07128,3.59616 c -0.046,0.0125 -0.11609,0.15283 -0.19843,0.50126 -0.0447,0.11946 -0.12068,0.55421 0.0775,0.36484 0.19362,-0.34691 0.21455,-0.81723 0.14004,-0.86403 h -5e-4 c -0.006,-0.003 -0.012,-0.004 -0.0186,-0.002 z m -0.6356,1.5627 c -0.079,-0.0128 -0.19479,0.0402 -0.34883,0.19792 -0.19704,0.0386 -0.26882,0.95532 0.0331,0.63458 0.39754,-0.0448 0.5438,-0.64657 0.38243,-0.79943 -0.0183,-0.0177 -0.0403,-0.0276 -0.0667,-0.0326 z m 3.53157,0.28783 c -0.0145,-0.003 -0.0279,-0.003 -0.0398,0.002 -0.0792,0.0285 -0.0914,0.22185 0.078,0.65371 0.0425,0.16251 0.28297,0.43936 0.34157,0.13023 -0.006,-0.29077 -0.11668,-0.53703 -0.22944,-0.67335 h -5.1e-4 c -0.0529,-0.0638 -0.10628,-0.10342 -0.14986,-0.11214 z m -3.06699,0.71417 c -0.11473,0.005 -0.36497,0.34787 -0.21913,0.6656 l 0.11472,-0.12816 c 0.15291,-0.30965 0.17669,-0.46521 0.14161,-0.51832 0,7.2e-4 0.002,-2.3e-4 0.002,5.2e-4 l -0.002,-0.002 v 5.2e-4 c -0.009,-0.012 -0.0222,-0.0194 -0.0372,-0.0186 z m 0.91829,1.10691 c 0,1.7e-4 0,3.5e-4 0,5.2e-4 -5.3e-4,1.2e-4 -0.001,-1.2e-4 -0.002,0 5.5e-4,-1.3e-4 9.8e-4,-3.8e-4 0.002,-5.2e-4 z m 1.47484,23.342759 c -0.0965,-0.0137 -0.20217,0.35222 0.0749,0.14676 -0.0109,-0.0548 -0.0222,-0.0916 -0.0357,-0.11472 -0.0122,-0.0202 -0.0259,-0.03 -0.0393,-0.032 z m -0.98237,0.9338 c -0.14174,0.0139 -0.29345,0.21991 -0.24496,0.71003 -0.0263,0.31998 0.15116,0.22384 0.22998,0.0662 0.29102,-0.34448 0.26099,-0.62222 0.14571,-0.72864 v -5.1e-4 c -0.037,-0.0349 -0.0834,-0.052 -0.13073,-0.047 z m 0.4005,1.03714 c -0.1714,-0.0358 -0.43241,0.24697 -0.11526,0.65423 l 0.1447,-0.10853 c 0.1255,-0.28076 0.10745,-0.44152 0.0388,-0.50952 l -0.002,-0.001 c -0.0189,-0.0187 -0.0416,-0.0301 -0.0661,-0.0351 z", +0.780383, 20.4192, +"M -0.105503 -20.4188 c -0.0405,-0.002 -0.0956,0.004 -0.16536,0.017 -0.29935,0.0549 -0.36433,0.21983 -0.36433,0.92115 0,0.46985 -0.0358,1.28906 -0.0796,1.82015 -0.0467,0.5662 -0.0191,1.05683 0.0672,1.18617 0.081,0.1214 0.30279,-0.076 0.49299,-0.43885 0.19016,-0.36274 0.40254,-0.575 0.47181,-0.47122 0.0693,0.10377 0.11406,-2.72234 -0.0274,-2.93432 -0.0714,-0.10706 -0.1297,-0.0411 -0.1297,0.14614 0,0.18729 -0.1044,0.33898 -0.23201,0.33532 -0.19841,-0.003 -0.20326,-0.0502 -0.0331,-0.31828 0.1142,-0.18005 0.12105,-0.25755 -5.3e-4,-0.2633 z m -0.26458,4.60917 c -0.0347,0.0205 -0.0779,0.24114 -0.11988,0.63953 -0.0557,0.53054 -0.075,1.54319 -0.0434,2.25048 0.0963,2.16125 0.0682,3.44269 -0.0796,3.66416 -0.16271,0.24387 -0.0597,2.39029 0.12248,2.55214 0.0663,0.0589 0.11298,0.78233 0.10335,1.60754 -0.0172,1.47849 -0.0189,1.48377 -0.11523,0.37494 -0.0781,-0.90009 -0.10126,-0.6552 -0.11523,1.22451 -0.0111,1.494811 0.0309,2.278081 0.11523,2.151631 0.0606,-0.0909 0.10337,0.21775 0.12195,0.82742 -0.11997,0.0834 -0.25326,0.46905 -0.39997,1.18617 0.0168,0.60699 0.0279,1.24832 0.0393,1.8896 -0.002,0.0692 -7.2e-4,0.13106 0.004,0.18789 0.10261,6.050652 0.0186,13.334762 0.56481,17.672782 0.34438,-0.35219 0.35478,-2.7314 0.4532,-3.9671 0.15868,-1.69005 0.20889,-5.0472 0.15865,-8.334692 0.08,-0.0549 0.10705,-0.21387 0.0698,-0.4495 -0.0411,-0.25961 -0.0181,-0.55719 0.0517,-0.66168 0.0697,-0.10451 0.12713,-0.40665 0.12713,-0.67191 0,-0.26509 -0.0599,-0.39341 -0.13282,-0.28418 -0.0729,0.10924 -0.13229,0.0454 -0.13229,-0.14188 0,-0.18721 0.0523,-0.34043 0.11629,-0.34043 0.0641,0 -0.26379,-3.32582 -0.28938,-3.22958 -0.0256,0.0962 -0.0253,-0.0239 5e-4,-0.26757 0.0258,-0.24348 -0.0179,-0.63167 -0.0971,-0.8632 -0.10261,-0.30004 -0.10358,-0.60608 -0.002,-1.06389 0.078,-0.35332 0.12729,-0.97353 0.10903,-1.37832 -0.0212,-0.47251 0.0377,-0.73954 0.16537,-0.74562 0.1094,-0.005 0.20484,-0.225601 0.21187,-0.490401 0.007,-0.2648 0.0586,-0.73603 0.1142,-1.04684 0.0618,-0.34499 0.0213,-0.86088 -0.10385,-1.32421 -0.11285,-0.41748 -0.19997,-1.19131 -0.19381,-1.71961 0.014,-1.19099 -0.12967,-1.79354 -0.37309,-1.56707 -0.1185,0.11022 -0.18552,-0.0461 -0.18552,-0.4333 0,-0.33342 -0.0706,-0.66331 -0.15658,-0.73284 -0.0967,-0.0782 -0.0238,-0.365 0.0372,-0.75073 0.0545,-0.34306 0.0797,-0.6532 0.0569,-0.6898 -0.0229,-0.0366 0.0755,-0.27457 0.21859,-0.52832 0.22053,-0.39106 0.23374,-0.53911 0.0847,-0.97441 -0.0967,-0.28243 -0.22886,-0.43441 -0.29353,-0.33744 -0.12361,0.18519 -0.1457,-0.17035 -0.14004,-2.27306 0.002,-0.68298 -0.0283,-0.98758 -0.0729,-0.96121 z", +2.50105, 20.7737, +"M 1.99533 -20.1853 c -0.0375,-0.25789 -0.33261,-0.42551 -0.56905,-0.58839 -0.23996,0.23872 -0.47489,0.49163 -0.6009,0.8121 -0.0812,0.48893 -0.29007,0.81482 -0.38877,1.29015 0.002,0.54267 -0.41169,0.99749 -0.40079,1.54481 -0.29754,0.24097 -0.55536,0.37238 -0.50367,0.84202 0.0614,0.57416 -0.22723,1.12925 -0.28672,1.7031 -0.14255,0.60343 -0.28189,1.20471 -0.38066,1.8095 -0.0293,0.59441 -0.2814,1.18246 -0.12046,1.75323 -0.2131,-0.15862 -0.45105,-0.0488 -0.16056,0.12001 -0.0693,0.38384 -0.39321,0.81136 -0.33681,1.29405 0.0267,0.64265 -0.0113,1.27603 -0.14224,1.89832 -0.003,0.60064 -0.10155,1.21537 -0.24239,1.79332 -0.22967,0.32796 0.15308,0.6786 0.11208,1.04197 0.2095,-0.3435 0.24518,-0.79906 0.5964,-1.0637 0.58133,0.18835 0.24969,0.75808 0.31901,1.19987 -0.26469,0.52559 -0.0489,0.91024 0.47559,1.11661 0.25093,-0.0203 0.43656,0.83787 0.43804,0.4442 -0.0618,-0.51559 0.4207,-0.87267 0.41211,-1.37583 0.013,-0.55963 0.17412,-1.11826 0.20939,-1.67553 -0.40638,-0.35369 -0.56249,-0.94788 -0.16108,-1.40288 -0.26584,-0.54166 0.46688,-1.0424 -0.027,-1.55948 -0.72899,-0.49884 0.91668,-0.76908 0.36771,-1.29742 0.0275,0.33925 -0.48808,0.48735 -0.42907,0.0774 0.21303,-0.33662 0.68355,-1.28644 0.0603,-1.29291 -0.1772,-0.18811 -0.2848,-1.18628 0.34402,-1.22453 0.56288,-0.22657 -0.41458,0.0439 -0.23023,-0.39889 0.21834,-0.27814 0.12847,-0.9857 0.5386,-0.9766 0.24676,0.4666 0.0743,-0.15601 -0.0145,-0.31345 0.32655,-0.0856 0.16625,-0.26335 0.21161,-0.564 -0.17635,-0.4556 0.40637,-0.92508 0.0292,-1.47058 -0.0333,-0.47745 0.11583,-1.16532 0.30655,-1.6979 0.30437,-0.47718 0.2963,-1.07386 0.51455,-1.54766 0.0565,-0.10923 0.0727,-0.20496 0.0598,-0.29086 z m -0.67527,5.18673 c -0.005,-0.0207 -0.0401,-0.0511 -0.1331,-0.0891 -0.12685,0.13115 0.14583,0.15153 0.1331,0.0891 z m -0.51447,2.32592 c -0.01,-0.026 -0.0378,-0.0564 -0.0928,-0.089 -0.1546,0.23186 0.13611,0.20162 0.0928,0.089 z m -0.55676,9.92556 c -0.004,-0.0178 -0.0117,-0.0421 -0.0244,-0.0749 l -3.8e-4,8e-5 c -0.10421,-0.01 0.0523,0.1987 0.0247,0.0748 z m -0.40593,0.62749 c -0.029,-0.13397 -0.065,-0.26569 -0.10661,-0.39404 -0.0954,0.0982 -0.57871,0.21425 -0.47507,0.55849 0.0692,0.55607 -0.16309,0.96182 -0.64341,1.21137 -0.634,0.49658 -0.78164,-0.34647 -0.88631,-0.80154 -0.48235,0.13084 -0.0802,0.8574 0.0167,1.20292 -0.36114,0.39753 0.0177,1.11042 -0.11524,1.68891 -0.23801,0.62967 0.24476,1.16486 0.31513,1.76431 0.0279,0.59829 0.024,1.19727 0.091,1.79736 l 3.7e-4,-8e-5 c -5.9e-4,0.16055 0.01,0.32283 0.0418,0.48106 0.14355,0.59006 0.21051,0.10446 0.26051,-0.22378 -0.0205,-0.63973 -0.27186,-1.28964 0.006,-1.90725 0.12037,-0.14839 0.19349,-0.5856 0.41752,-0.32353 0.46234,0.3705 0.3394,1.09108 0.53985,1.60971 0.27126,0.36763 0.39796,0.77484 0.51709,1.26206 -0.002,-0.30581 -0.0844,-1.00791 0.24199,-1.29206 0.11117,-0.32729 -0.38379,-0.91151 -0.20475,-1.38978 0.34489,-0.30119 -0.033,-0.25259 -0.0944,-0.49538 -0.24459,-0.22385 -0.04,-0.56816 -0.16501,-0.76622 -0.1494,-0.4034 -0.40711,-0.71884 -0.52267,-1.12154 -0.24067,-0.7641 0.5871,-1.03146 0.79857,-1.63 0.0764,-0.40778 0.0532,-0.8291 -0.0337,-1.23099 z m 0.89502,9.36585 c -0.0536,-0.20202 -0.20583,-0.37279 -0.33916,-0.2913 0.0256,0.46608 -0.22812,0.1812 -0.20758,-0.11481 0.50238,-0.20886 -0.136,-0.53619 -0.35884,-0.67825 -0.19176,0.37421 -0.0305,0.92091 -0.0919,1.3655 0.20082,0.60747 -0.0474,1.25588 0.23051,1.83712 0.46931,0.45584 0.1681,1.16914 0.30673,1.73368 -0.0209,1.03972 0.15888,2.08076 0.41848,3.08564 0.2179,0.9083 0.43884,1.83468 0.46756,2.76969 l -3.8e-4,8e-5 c -0.0559,0.1059 -0.0189,0.23303 -0.009,0.34529 -0.0466,0.49251 0.47733,1.10683 0.86726,0.99131 0.0869,-0.81136 -0.1849,-1.61553 -0.23186,-2.42464 -0.0153,-0.79202 -0.18322,-1.5676 -0.33686,-2.34287 -0.2662,-0.49125 0.35995,-0.65771 -0.11227,-1.06692 -0.29724,-0.73686 -0.33568,-1.55313 -0.49201,-2.32897 -0.13547,-0.6156 -0.29699,-1.09551 -0.32023,-1.74958 -0.42463,-0.16399 -0.2469,-0.50188 0.0726,-0.6905 0.13034,-0.0698 0.16881,-0.21103 0.15303,-0.35262 -0.003,-0.0295 -0.009,-0.059 -0.0165,-0.0878 z m -2.57871,-11.32017 c -0.2708,-0.55639 -0.38057,-0.0872 -0.31795,0.29402 l -0.0116,0.0821 c -0.0994,0.78435 0.40245,-0.0619 0.32958,-0.37609 z m 4.33185,23.83573 c -0.0258,-0.0834 -0.10025,-0.11446 -0.21568,0.0379 -0.0385,0.0658 -0.10012,0.12716 -0.0971,0.2101 0.26257,0.17623 0.35541,-0.10828 0.31288,-0.24765 z m -0.18954,-0.48941 c -0.002,-0.0411 -0.0436,-0.0877 -0.15571,-0.12611 -0.17795,0.32518 0.16312,0.24936 0.15571,0.12611 z m -3.39268,-11.78328 c -0.007,-0.0222 -0.015,-0.0442 -0.0268,-0.0646 -0.39951,-0.3938 -0.32809,-1.07152 -0.63904,-1.49675 0.0493,0.59576 0.19414,1.18256 0.32136,1.76612 0.004,0.62023 0.44185,0.12916 0.34453,-0.20475 z m 2.27835,12.58899 c -0.0101,-0.0525 -0.027,-0.0984 -0.0521,-0.13269 -0.007,-0.44623 -0.38635,-0.40063 -0.30696,0.0345 -6.4e-4,0.18442 0.0187,0.36863 0.0509,0.55019 0.11903,0.61469 0.37941,-0.0844 0.30817,-0.45198 z m -3.29846,-15.55671 c -0.007,-0.0317 -0.0473,-0.0578 -0.14608,-0.0599 -0.11114,0.30062 0.16683,0.15497 0.14608,0.0599 z", +1.65654, 15.5833, +"M 1.65648 7.45006 c -0.014,-0.2553 -0.50256,-0.33488 -0.51056,-0.80616 -0.15816,0.27247 -0.44145,0.24588 -0.34003,-0.16846 0.52996,-0.0216 0.43279,-0.95853 0.27957,-1.38131 -0.46566,0.32298 -1.49686,0.71091 -1.96216,0.28887 0.47799,-0.50839 -0.10776,-0.98406 0.0393,-1.53376 0.24102,-1.11239 1.05865,-0.30535 1.5689,0.0594 0.29417,-0.54317 -0.42213,-1.43185 -0.2713,-2.12699 0.053,-0.33438 -0.14256,-0.76674 0.18035,-0.99478 0.74093,-0.4137 0.071,-1.20457 0.48731,-1.77662 0.16189,-0.87009 0.12472,-1.775858 0.0253,-2.653088 -0.37764,-0.45524 0.11408,-0.79274 0.0103,-1.24229 -0.0546,-1.40989 0.11322,-2.83197 0.009,-4.24522 -0.18099,-0.66609 0.36361,-1.5512 -0.2403,-2.13217 -0.76022,-0.19291 -1.74581,-0.46318 -1.47846,-1.48984 0.23135,-0.3261 0.005,-1.03309 -0.27595,-0.47181 -0.1149,1.29353 -0.0485,2.59721 -0.0899,3.89486 0.0166,1.91664 -0.15304,3.83585 -0.0129,5.74952 -0.10524,0.84254 -0.15444,1.608928 -0.11524,2.481498 -0.1778,1.05201 -0.0675,2.11953 -0.11111,3.18223 -0.0119,0.29604 0.0774,0.64029 -0.25631,0.78393 h -5.2e-4 c -0.29571,0.18497 -0.24881,0.55168 -0.24081,0.84905 0.12861,0.90109 0.33978,-0.31956 0.34778,-0.59272 0.25303,0.5402 0.0916,1.52043 0.1478,2.22414 -0.0982,0.37068 0.22385,1.646 -0.31678,1.42214 0.003,0.32776 -0.0945,1.3313 0.0145,1.937875 -0.20501,0.86879 0.24098,1.79626 -0.0889,2.66081 0.58049,0.22895 -0.1934,0.54647 0.0367,1.02682 0.20168,0.73761 0.51285,1.49881 0.25838,2.27219 -0.43599,0.48255 0.11253,1.05024 0.3359,0.29043 0.1027,-1.16376 -0.0313,-2.33825 0.0682,-3.50416 0.18831,-1.09985 0.14716,0.68392 0.80718,0.4754 0.30346,0.13933 1.74688,-0.14938 0.9679,-0.23408 -0.58672,-0.4472 0.61164,-1.04584 0.54674,-1.60403 -0.11252,-0.73311 -0.62171,-1.66272 0,-2.307345 0.13633,-0.14516 0.18483,-0.24977 0.17983,-0.33489 z m -0.94413,-22.308708 c -0.13146,-0.53592 -0.80296,-1.00793 -1.25935,-0.52142 -0.21226,0.79762 0.82396,0.58812 1.25935,0.52142 z m -0.25166,28.192583 c 5.1e-4,-0.0774 -0.0451,-0.16422 -0.17674,-0.2346 -0.24185,0.61669 0.17474,0.46696 0.17674,0.2346 z m -0.27799,2.11821 c 0.006,-0.0684 -0.0265,-0.1592 -0.1323,-0.26303 -0.24658,0.46943 0.11469,0.4681 0.1323,0.26303 z m -1.26453,-22.438413 c -10e-4,-0.053 -0.009,-0.11049 -0.0264,-0.17208 0.003,-0.25223 -0.003,-1.72141 -0.21342,-1.21079 -0.0657,0.43773 -0.0695,0.88514 -0.0537,1.32707 -0.0378,0.55499 0.30152,0.42662 0.29352,0.0558 z m -0.0667,3.28145 c -0.004,-0.0288 -0.0281,-0.0608 -0.0847,-0.092 -0.26244,0.28511 0.10135,0.21687 0.0847,0.092 z m -0.2961,17.933793 c -0.005,-0.0297 -0.0175,-0.0677 -0.0413,-0.11629 -0.28174,0.10517 0.0752,0.32372 0.0413,0.11629 z", +1.55663, 17.8159, +"M 0.508125 -17.8159 c 1.02192,1e-5 1.04851,0.0236 1.04851,0.92603 0,0.50934 -0.0799,0.92605 -0.17722,0.92606 -0.0974,1e-5 -0.15454,0.62507 -0.1266,1.38906 0.17088,4.66959 0.17679,7.8749 0.0145,8.03725 -0.10277,0.10281 -0.17864,0.3752 -0.16849,0.60563 0.0138,0.31029 0.0797,0.28188 0.25371,-0.11012 0.17857,-0.4021 0.22525,-0.2592 0.19434,0.59428 -0.0224,0.61778 -0.15187,1.23396 -0.28734,1.36941 -0.13546,0.13548 -0.29046,2.54681 -0.34467,5.35886 -0.0542,2.812 -0.21156,5.58913 -0.34933,6.17119 -0.48698,2.0578 -0.57684,2.66036 -0.60202,4.02459 -0.014,0.75831 -0.10149,1.33161 -0.19432,1.27433 -0.0929,-0.0571 -0.0568,0.64262 0.0796,1.55544 0.13639,0.91283 0.16059,2.12362 0.0542,2.69079 -0.17825,0.95039 -0.22183,0.99291 -0.55449,0.53795 -0.29134,-0.398 -0.34675,-2.15278 -0.28836,-9.05164 0.0598,-7.06382 0.0117,-8.50695 -0.27647,-8.26772 -0.47407,0.39347 -0.44992,-0.0548 0.0542,-1.00148 0.26051,-0.48899 0.38793,-1.36812 0.35966,-2.47788 -0.0242,-0.94587 0.04,-3.28537 0.14265,-5.19866 0.18216,-3.39463 0.32775,-9.3534 1.16794,-9.35337 z", +1.17205, 11.7473, +"M 1.02268 -10.861 c 0.1091,0.1814 0.17719,0.37632 0.13837,0.50034 -0.0351,0.11193 -0.27619,0.1724 -0.53581,0.13446 -0.37479,-0.0547 -0.43967,0.0318 -0.3153,0.41964 0.0861,0.2686 0.0411,0.54794 -0.0997,0.62149 -0.25308,0.13194 -0.18099,1.81839 0.10401,2.43261 0.0809,0.17447 0.095,0.4829 0.0316,0.68524 -0.0634,0.20236 -0.0497,0.46476 0.0303,0.58334 0.25808,0.3824 -0.27881,17.31188 -0.58526,17.230934 -0.163,-0.04269 -0.48752,-0.232899 -0.72224,-0.421235 -0.33692,-0.271053 -0.32403,-0.457558 0.0633,-0.889384 0.26957,-0.300525 0.40319,-0.70571 0.29707,-0.900197 -0.34087,0.04626 0.15589,-9.963114 -0.40834,-15.903028 0.12837,-0.35962 0.16399,-0.9136 0.0792,-1.23105 -0.0848,-0.31748 -0.12098,-0.89469 -0.0803,-1.28251 0.0407,-0.38778 -0.003,-1.16267 -0.0972,-1.72233 -0.12675,-0.75336 -0.0633,-1.00192 0.24376,-0.95706 0.22809,0.0334 0.44313,-0.031 0.47827,-0.14277 0.0351,-0.11192 0.19636,-0.007 0.35828,0.23297 0.16257,0.24082 0.3604,0.33132 0.44178,0.2019 0.10143,-0.16052 0.39628,0.10439 0.57817,0.40666 z", +1.95058, 13.6269, +"M 0.471013 -13.6265 c -0.0226,0.002 -0.0393,0.019 -0.0481,0.0517 -0.0351,0.13069 -0.24992,0.20591 -0.47799,0.16691 -0.30708,-0.0524 -0.37068,0.23818 -0.24392,1.1188 0.0942,0.65419 0.13785,1.56002 0.0971,2.01331 -0.0407,0.45333 -0.004,1.12802 0.0806,1.49913 0.0848,0.37107 0.0488,1.01882 -0.0796,1.43919 -0.20937,0.68561 -0.0718,1.6412 0.37155,2.62827 -0.11168,0.0113 -0.23463,0.0283 -0.38137,0.0563 -0.6455,0.12341 -0.72607,0.25452 -0.72607,1.18184 -1.6e-4,0.62786 -0.10541,0.97834 -0.26458,0.87954 -0.16997,-0.10511 -0.26459,0.835241 -0.26459,2.630332 0,1.81333 -0.0999,2.79364 -0.28421,2.79363 h -5e-4 c -0.15627,-2e-5 -0.23813,0.20835 -0.18243,0.46302 0.0557,0.25469 0.2427,0.43297 0.416,0.39687 0.21384,-0.0449 0.3152,0.40637 0.31522,1.40457 0,0.91314 -0.10041,1.40916 -0.26458,1.30741 -0.16825,-0.10405 -0.25207,0.54034 -0.22998,1.77042 0.0279,1.54684 0.074,1.74841 0.22998,1.0077 0.19206,-0.91245 0.19513,-0.90816 0.22945,0.3085 0.0192,0.67909 -0.0733,1.27442 -0.20569,1.32292 -0.36356,0.1332 -0.56917,1.89947 -0.24442,2.10013 0.29488,0.18225 0.69575,0.93239 0.58706,0.65009 -0.12179,-0.3174 -0.0778,-0.55313 0.11522,-0.61753 0.17206,-0.0571 0.3121,-0.3287 0.31213,-0.60307 3.4e-4,-0.31822 0.13407,-0.44675 0.37052,-0.35605 0.4857,0.18639 0.77203,-0.30974 0.74414,-1.28984 -0.41298,-4.18519 -0.41174,-10.39178 -0.21031,-12.921172 0.13216,0.0905 0.25572,0.15931 0.33795,0.18449 0.30644,0.0946 0.84307,-3.81941 0.58497,-4.26641 -0.08,-0.13861 -0.0934,-0.44506 -0.0299,-0.68161 0.0634,-0.23652 0.0494,-0.59705 -0.0315,-0.80099 -0.28499,-0.71796 -0.35746,-2.68952 -0.10438,-2.84375 0.14078,-0.086 0.18584,-0.4126 0.0997,-0.72657 -0.12435,-0.45333 -0.0596,-0.55441 0.31522,-0.49041 0.25964,0.0444 0.50081,-0.0263 0.53589,-0.15709 0.0388,-0.14498 -0.0294,-0.37294 -0.13848,-0.58498 -0.1819,-0.35333 -0.4763,-0.66307 -0.57775,-0.47543 -0.0814,0.15128 -0.27926,0.0453 -0.44182,-0.23616 -0.12145,-0.21024 -0.24284,-0.33152 -0.31057,-0.32401 z", +0.746818, 13.5457, +"M 0.651624 -11.1239 c 0.0695,0.49565 0.1129,1.02826 0.0882,1.36713 -0.0224,0.30582 -0.17599,0.47106 -0.34142,0.36739 -0.23882,-0.1496 -0.28016,0.087 -0.20091,1.14663 0.0549,0.73391 0.0262,1.49718 -0.0635,1.69814 -0.16126,0.36052 -0.11532,4.968579 0.0663,6.646849 0.0516,0.47672 0.0605,1.31946 0.0201,1.87234 -0.0404,0.55294 -0.0317,1.2699 0.0193,1.59391 0.16445,1.04487 -0.17766,10.194453 -0.37293,9.973273 -0.10386,-0.11664 -0.31064,-0.63636 -0.46021,-1.15097 -0.21468,-0.74062 -0.20647,-1.25023 0.0403,-2.43014 0.17177,-0.82115 0.25691,-1.928273 0.18929,-2.459683 -0.30256,-2.37873 -0.39749,-4.69547 -0.26019,-6.34493 0.0818,-0.98262 0.10449,-2.49631 0.0505,-3.363699 -0.054,-0.86748 -0.0771,-2.44465 -0.0512,-3.50432 0.0259,-1.05958 -0.002,-3.17689 -0.0619,-4.70608 -0.0808,-2.05847 -0.0403,-2.73764 0.15533,-2.61506 0.14533,0.0912 0.28236,-0.0846 0.30475,-0.39011 0.0224,-0.30582 0.12512,-0.0187 0.22829,0.63658 0.10359,0.65802 0.22965,0.90528 0.2815,0.55166 0.0646,-0.43862 0.25251,0.28522 0.36841,1.11114 z", +1.38957, 16.4755, +"M 0.138886 -16.4755 -1.35549,1.84795 c 0.27683,0.42497 0.50699,1.05938 0.54983,1.48879 0.0601,0.48725 0.0332,0.97552 -0.0119,1.46658 -0.0892,-0.49054 -0.17108,-0.69618 -0.19068,-0.4284 -0.0224,0.30551 -0.15905,0.48136 -0.30438,0.39016 -0.19563,-0.12258 -0.23635,0.55687 -0.15555,2.61535 0.0599,1.52918 0.0879,3.64658 0.062,4.70617 -0.0259,1.05967 -0.003,2.63669 0.0512,3.50417 0.054,0.86739 0.0311,2.381 -0.0506,3.36362 -0.13732,1.64946 -0.0421,3.96611 0.26043,6.34484 0.0676,0.5314 -0.0179,1.63864 -0.18966,2.45979 -0.24675,1.17991 -0.25497,1.68972 -0.0403,2.43035 0.12094,0.41612 0.27699,0.82396 0.38809,1.03094 -0.25501,0.55068 -0.28125,1.13805 -0.22479,1.73064 l 1.4609,-0.003 c 0.0168,-0.42614 0.0252,-0.85476 0.0677,-1.27434 0.25389,-1.34995 0.14287,-2.66726 0.36689,-4.02611 0.031,-1.4516 0.11288,-2.8398 0.19175,-4.25762 0.12581,-1.2814 -0.13108,-2.63661 0.16224,-3.91397 -0.10988,-1.37381 -0.11983,-2.74916 -0.14417,-4.11603 0.0786,-1.41425 -0.2367,-2.81377 -0.12764,-4.19458 -0.0646,-1.50176 -0.23391,-3.00258 -0.21238,-4.4483 0.78798,-0.10067 0.97116,-1.25283 0.22117,-1.50379 0.42751,0.71673 -0.5987,0.75403 -0.39428,0.0444 0.49067,-0.38166 0.47429,-0.58582 0.0196,-0.82733 0.15126,-1.10944 -0.28977,-2.18413 -0.17312,-3.35639 -0.008,-0.38118 -0.13687,-0.71882 -0.22635,-1.07229 z m -0.46355,8.37158 c 0.0189,0.005 0.0414,0.0166 0.0641,0.0295 0.11988,0.62091 -0.0121,1.26337 -0.16021,1.91254 5.9e-4,-0.24158 -0.005,-0.49741 -0.0243,-0.75809 -0.0694,-0.92718 -0.0464,-1.22436 0.12041,-1.18391 z m -0.25374,3.57756 c 0.0898,0.93296 0.42876,1.87606 0.6594,2.79259 0.23042,1.45009 0.26061,2.8781 -0.008,4.3031 -0.24439,1.27673 -0.30588,2.48657 0.0294,3.77031 -0.13909,1.17698 -0.45156,2.32446 -0.53951,3.48144 0.0761,-2.22329 0.11075,-4.44633 0.0346,-4.92993 -0.051,-0.32401 -0.06,-1.04076 -0.0196,-1.5937 0.0404,-0.55288 0.0314,-1.39552 -0.0202,-1.87224 -0.1455,-1.34446 -0.20132,-4.53663 -0.13592,-5.95157 z m 0.0796,15.91375 c 0.14541,0.99939 0.5629,2.03294 -0.10957,2.94194 -0.0303,0.0418 -0.0541,0.0847 -0.0811,0.12713 0.0646,-0.57923 0.13222,-1.74103 0.19069,-3.06907 z", +2.34195, 11.5159, +"M 2.34146 -4.20638 c 0.002,0.0553 -0.002,0.11609 -0.0145,0.17985 -0.0644,0.3366 -0.42979,0.50248 -1.33841,0.60719 -0.68743,0.0792 -1.29195,0.0792 -1.34307,0 -0.0514,-0.079 -0.0507,0.0201 4.4e-4,0.22012 0.0516,0.20034 -0.0357,0.52005 -0.19353,0.71065 -0.20476,0.24688 -0.20659,0.49864 -0.005,0.87541 0.15568,0.29074 0.2535,0.80116 0.21707,1.13429 -0.0424,0.38883 0.0761,0.60836 0.33071,0.6134 0.21831,0.004 0.40817,0.18566 0.42215,0.40362 0.014,0.21788 0.11684,0.60569 0.22773,0.8615 0.12326,0.2839 0.0426,0.70855 -0.20724,1.08985 -0.22511,0.34352 -0.39934,0.98017 -0.38738,1.41481 0.0279,0.9801 -0.25842,1.47623 -0.74413,1.28984 -0.23645,-0.0907 -0.37001,0.038 -0.37035,0.35622 -2e-5,0.27437 -0.14008,0.54597 -0.31215,0.60306 -0.19306,0.0644 -0.23703,0.30013 -0.11526,0.61753 0.10871,0.2823 0.15952,0.5378 0.11365,0.56793 -0.0459,0.0299 0.15058,0.22581 0.4361,0.43468 0.44013,0.32178 0.46571,0.44377 0.1685,0.80197 -0.19293,0.23238 -0.45647,0.35733 -0.58549,0.27753 -0.2465,-0.15271 -0.29031,0.14035 -0.27906,1.87067 0.007,0.99916 -0.004,1.01393 -0.19528,0.26464 -0.11079,-0.43669 -0.15026,-1.27006 -0.0873,-1.8521 0.19222,-1.77852 0.13676,-2.83306 -0.15812,-3.01531 -0.32475,-0.20066 -0.11915,-1.96693 0.24443,-2.10013 0.13238,-0.0485 0.2249,-0.64383 0.20567,-1.32292 -0.0343,-1.21666 -0.0374,-1.22096 -0.22946,-0.30851 -0.15593,0.74072 -0.20203,0.53914 -0.22995,-1.0077 -0.0221,-1.23009 0.0617,-1.87448 0.22995,-1.77043 0.16417,0.10175 0.26459,-0.39427 0.2646,-1.30741 -2e-5,-0.99819 -0.10145,-1.44949 -0.31528,-1.40457 -0.17329,0.0361 -0.36031,-0.1422 -0.41598,-0.39689 -0.0557,-0.25466 0.0262,-0.46301 0.18245,-0.463 h 5.2e-4 c 0.18433,1e-5 0.28421,-0.9803 0.28422,-2.79364 0,-1.79509 0.0946,-2.73543 0.26457,-2.63032 0.15915,0.0988 0.2644,-0.25166 0.26456,-0.87952 -1e-5,-0.92732 0.0806,-1.05844 0.72609,-1.18185 0.97706,-0.18674 1.12602,-0.0503 1.126,1.03409 10e-6,0.63956 -0.0957,0.86695 -0.30949,0.73485 -0.21128,-0.13012 -0.25315,-0.0441 -0.13229,0.27076 0.0974,0.25407 0.17731,0.63077 0.17721,0.83716 -2e-5,0.20637 0.19145,0.37518 0.42527,0.37521 0.26515,2e-5 0.36883,0.14645 0.27599,0.38857 -0.082,0.21364 -0.0353,0.45868 0.10391,0.54466 0.13913,0.086 0.2532,0.33466 0.2532,0.55296 -7e-5,0.21815 -0.11907,0.32343 -0.26457,0.23359 -0.14556,-0.0898 -0.26459,-0.0373 -0.2646,0.11674 -8e-5,0.15409 0.10469,0.28009 0.23249,0.28014 0.12785,-1e-5 0.38035,0.35716 0.56117,0.79376 0.18081,0.4366 0.44232,0.79375 0.58084,0.79377 0.10393,0 0.17072,0.11718 0.1778,0.28317 z", +1.43162, 19.3805, +"M -0.137187 -19.38 c -0.0842,-0.005 -0.19127,0.031 -0.32713,0.0946 -0.35901,0.16796 -0.4036,0.34656 -0.4036,1.60868 -7e-5,0.85455 -0.0588,1.3313 -0.14726,1.19683 -0.0946,-0.14306 -0.14727,1.13695 -0.14727,3.58014 -3e-5,2.46804 -0.0551,3.80237 -0.15761,3.80236 h -5.3e-4 c -0.0869,-10e-6 -0.13229,0.28333 -0.10128,0.62993 0.031,0.34665 0.13459,0.58964 0.23098,0.54054 0.11895,-0.0611 0.17571,0.55293 0.17571,1.91151 0,1.24282 -0.056,1.9177 -0.14727,1.77922 -0.0936,-0.14162 -0.14047,0.73546 -0.12816,2.409662 0.0155,2.10531 0.0415,2.37964 0.12816,1.37149 0.10681,-1.24188 0.10853,-1.23579 0.12764,0.42013 0.0107,0.92427 -0.0411,1.73441 -0.11473,1.80041 -0.20225,0.1813 -0.31652,2.58511 -0.13591,2.85822 0.16401,0.24805 0.19476,1.6835 0.0879,4.104145 -0.035,0.792181 -0.013,1.926426 0.0485,2.520775 0.10663,1.019821 0.11306,0.999718 0.10907,-0.360182 -0.006,-2.355041 0.0179,-2.753938 0.15502,-2.546099 0.0718,0.108619 0.21825,-0.06148 0.32557,-0.377759 0.16531,-0.48752 0.15123,-0.65344 -0.0936,-1.0914 -0.15883,-0.28428 -0.26837,-0.551 -0.24286,-0.5917 0.0255,-0.041 -0.003,-0.38885 -0.063,-0.77308 -0.0677,-0.43199 -0.0433,-0.75256 0.0641,-0.84026 0.0957,-0.0777 0.17362,-0.44719 0.17362,-0.82062 1.8e-4,-0.43313 0.0747,-0.60869 0.20619,-0.48524 0.27014,0.25368 0.42944,-0.42149 0.41394,-1.75545 -0.007,-0.59156 0.0903,-1.45792 0.21548,-1.92546 0.13896,-0.51897 0.18375,-1.09672 0.11525,-1.48312 -0.0617,-0.348152 -0.11914,-0.875982 -0.12713,-1.172522 -0.008,-0.29666 -0.11319,-0.54484 -0.23461,-0.54984 -0.14163,-0.007 -0.20757,-0.30536 -0.18396,-0.83457 0.0203,-0.45341 -0.0338,-1.14839 -0.12042,-1.5441 -0.11189,-0.5128 -0.11128,-0.85512 0.003,-1.19114 0.0877,-0.25941 0.13668,-0.69471 0.108,-0.96738 -0.0285,-0.2722 -0.0291,-0.40724 -5.3e-4,-0.29972 0.025,0.0947 0.29102,0.10153 0.61341,0.03 0.0405,0.52236 0.0906,1.04394 0.0915,1.57561 -0.0608,0.60189 -0.078,1.11737 -0.0465,1.74821 0.0696,0.63278 0.297,1.09496 0.0998,1.78077 -0.058,0.73385 0.0101,1.474622 0.002,2.207102 -0.0197,0.81022 0.0418,1.60891 0.004,2.4262 -0.0875,0.63698 -0.0763,1.43498 -0.22429,1.9482 0.12394,0.22305 0.34293,0.21881 0.24702,0.84078 -0.0607,1.1452 -0.0473,2.30122 -0.0796,3.45147 0.0458,0.825198 -0.0683,1.62066 -0.093,2.435508 0.0204,1.1895 -0.1012,2.349915 -0.17311,3.516066 -0.0662,0.696058 -0.0537,1.411333 -0.0966,2.110981 -0.0148,0.25309 -0.0926,0.598914 0.0625,0.599964 0.29631,0.0457 0.33951,0.87489 0.30128,1.493449 -0.10774,0.477189 0.0255,1.113514 0.0103,1.577165 l 0.14004,-0.146246 c 0.0399,-0.520959 0.0745,-1.044482 0.11576,-1.564762 0.18883,-2.023379 0.28009,-4.091098 0.39534,-6.147427 0.0855,-1.171151 0.0493,-2.370113 0.13795,-3.538798 -0.0101,-0.73951 0.0498,-1.47317 0.032,-2.21279 0.0113,-0.74373 0.0533,-1.47966 0.0351,-2.2226 0.0413,-0.71668 -0.0126,-1.40059 -0.001,-2.13166 0.0365,-0.74313 0.0171,-1.48879 -0.0109,-2.22673 0.07,-0.4474 -0.0966,-1.347812 0.0646,-1.455202 -0.015,0.783202 0.13674,0.20012 0.1297,-0.24288 -0.002,-0.28913 -0.0311,-1.39426 -0.15089,-0.66404 0.14613,0.14266 -0.0403,0.66546 -0.10491,0.6289 0.1066,-0.45472 0.0111,-0.96117 0.0522,-1.43971 0.15606,-0.65158 0.0842,-1.40153 -0.077,-1.97559 -0.0905,-0.69785 -0.11025,-1.42475 -0.13901,-2.14043 -0.009,-0.18957 -0.0222,-0.37781 -0.0341,-0.56689 0.11245,-0.13013 0.17013,-0.29776 0.18757,-0.5209 0.007,-0.0868 0.009,-0.16965 0.008,-0.24495 h -5.3e-4 c -0.004,-0.22592 -0.0414,-0.3855 -0.0992,-0.3855 -0.0459,-2e-5 -0.11597,-0.18397 -0.18653,-0.44959 -10e-4,-0.0362 -0.004,-0.0729 -0.005,-0.10904 0.003,-0.57553 -0.0511,-1.12705 -0.10387,-1.6769 h -0.001 l -0.26149,0.19689 c -0.0296,-0.0724 -0.0569,-0.12196 -0.0775,-0.12196 -0.0711,-7e-5 -0.12922,-0.17164 -0.12916,-0.38137 0,-0.20968 0.0663,-0.28087 0.14726,-0.15864 0.0809,0.12226 0.14724,-0.0209 0.14727,-0.31781 0,-0.29713 -0.0637,-0.63588 -0.14108,-0.75293 -0.0774,-0.11702 -0.10347,-0.45026 -0.0579,-0.74104 0.0516,-0.32953 -0.006,-0.52914 -0.15349,-0.52917 -0.13004,-4e-5 -0.23669,-0.22969 -0.23667,-0.51056 0,-0.28091 -0.044,-0.79366 -0.0982,-1.13947 -0.0672,-0.42852 -0.0441,-0.54555 0.0734,-0.36845 0.11893,0.17979 0.17208,-0.12947 0.17208,-0.99994 3e-5,-1.10695 -0.0466,-1.48805 -0.29919,-1.50223 z", +1.43294, 9.17485, +"M 0.959443 6.24537 c 0.0279,0.9801 -0.25842,1.47623 -0.74413,1.28984 -0.23645,-0.0907 -0.37001,0.038 -0.37035,0.35622 -2e-5,0.27437 -0.14008,0.54597 -0.31215,0.60306 -0.19306,0.0644 -0.23703,0.30013 -0.11526,0.61753 0.10871,0.2823 -0.29212,-0.46774 -0.587,-0.64999 -0.32475,-0.20066 -0.11915,-1.96693 0.24443,-2.10013 0.13238,-0.0485 0.2249,-0.64383 0.20567,-1.32292 -0.0343,-1.21666 -0.0374,-1.22096 -0.22946,-0.30851 -0.15593,0.74072 -0.20203,0.53914 -0.22995,-1.0077 -0.0221,-1.23009 0.0617,-1.87448 0.22995,-1.77043 0.16417,0.10175 0.26459,-0.39427 0.2646,-1.30741 -2e-5,-0.99819 -0.10145,-1.44949 -0.31528,-1.40457 -0.17329,0.0361 -0.36031,-0.1422 -0.41598,-0.39689 -0.0557,-0.25466 0.0262,-0.46301 0.18245,-0.463 h 5.2e-4 c 0.18433,1e-5 0.28421,-0.980298 0.28422,-2.793628 0,-1.79509 0.0946,-2.73543 0.26457,-2.63032 0.15915,0.0988 0.2644,-0.25166 0.26456,-0.87952 -1e-5,-0.92732 0.0806,-1.05844 0.72609,-1.18185 0.97706,-0.18674 1.12602,-0.0503 1.126,1.03409 10e-6,0.63956 -0.0957,0.86695 -0.30949,0.73485 -0.49107,-2.81613 -0.76298,7.511348 -0.16401,13.581278 z", +0.865975, 16.9234, +"M 0.579895 11.5198 c 0.0168,1.80783 -0.15617,2.72296 -0.4497,2.37916 -0.14289,-0.1673 -0.22361,0.0701 -0.22381,0.65706 -10e-6,0.50609 -0.0846,1.00706 -0.18865,1.11237 -0.11667,0.11879 -0.14325,0.5536 -0.0697,1.13906 0.0657,0.52071 -0.17654,-0.86277 -0.35474,-1.19894 -0.19626,-0.37012 -0.072,-3.62807 0.14772,-3.87377 0.08,-0.0895 0.13591,-1.18757 0.12429,-2.44017 -0.0208,-2.24418 -0.0226,-2.25211 -0.13867,-0.56906 -0.0942,1.36629 -0.1221,0.99446 -0.13897,-1.85874 -0.0133,-2.26895 0.0373,-3.45755 0.13897,-3.26563 0.0992,0.18768 0.1599,-0.72725 0.15991,-2.41157 -10e-6,-1.8412 -0.0613,-2.67364 -0.19055,-2.59078 -0.10472,0.0666 -0.21773,-0.26229 -0.25139,-0.73208 -0.0337,-0.46973 0.0158,-0.85404 0.11023,-0.85402 h 3.2e-4 c 0.11135,2e-5 0.17176,-1.8082 0.17176,-5.15295 0,-3.31112 0.0571,-5.04561 0.1599,-4.85173 0.0962,0.18224 0.15978,-0.4642 0.15987,-1.62232 0,-1.71048 0.0487,-1.95233 0.4388,-2.17997 0.59049,-0.34444 0.6805,-0.0928 0.68049,1.90742 10e-6,1.17971 -0.0578,1.59914 -0.18703,1.35547 -0.29677,-5.19447 -0.46111,13.85497 -0.0991,25.05119 z", +0.920438, 15.73, +"M 0.600428 -15.73 -0.20928,0.13642 c 0.0116,0.10797 -0.008,0.20908 -0.10025,0.29611 -0.24135,0.42805 0.0459,1.00331 -0.24961,1.42213 0.2354,0.42752 0.12838,0.94985 0.13438,1.42472 0.10674,0.60433 -0.83865,0.28316 -0.87696,0.59066 0.2572,0.43226 -0.0173,0.8381 -0.0377,1.27641 0.21408,0.45321 -0.16298,0.88129 0.0558,1.32705 -0.23974,0.30068 0.19899,0.60454 -0.0589,0.92553 -0.006,0.92527 -0.0266,1.85081 -0.0517,2.77606 0.0152,0.4801 -0.0752,1.02655 0.1478,1.45779 -0.25858,-0.0769 -0.30935,0.24479 -0.16174,0.47594 -0.075,0.46382 0.1289,0.91188 -0.016,1.36787 -0.0107,1.507429 0.0413,3.015669 0.10387,4.521689 0.1733,0.47524 0.0581,0.99741 0.19534,1.44487 -0.36306,0.3697 -0.20534,0.96671 -0.25064,1.43919 -0.0318,0.49346 0.11663,1.03192 -0.0951,1.49087 0.14563,0.84649 0.0783,1.712415 0.1111,2.567805 -0.0665,0.45222 0.24575,0.922311 -0.0563,1.326021 -0.16113,0.30199 -0.14399,0.87954 0.10178,1.04644 -0.008,0.50476 0.33634,0.95241 0.1287,1.45211 0.19711,0.12306 0.23505,0.16337 0.093,0.39998 -0.25935,0.34252 0.27749,0.87321 -0.10438,1.09347 -0.51512,0.10675 0.14734,0.092 0.17105,0.3359 -0.11327,0.32055 -0.0946,1.20549 0.39066,0.72502 0.77099,0.005 -0.24847,-0.55676 0.12041,-0.89814 0.0876,-0.7571 0.0667,-1.52622 0.0171,-2.28565 -0.17201,-0.6034 -0.11922,-1.24776 -0.0837,-1.86965 0.24858,-0.51407 -0.0498,-1.029341 0.016,-1.553911 -0.006,-0.45575 0.10213,-0.879465 -0.0367,-1.321375 -0.0154,-0.45173 -0.18732,-0.86783 0.13748,-1.26039 0.17298,-0.38763 0.16687,0.10802 0.19378,0.28939 0.13417,0.39563 0.14967,0.90483 0.22738,1.25987 0.1107,-0.96718 0.0622,-1.94664 0.0801,-2.9192 0.0259,-4.03603 -0.0233,-8.072429 0.0181,-12.108299 0.23979,-0.22266 0.005,0.79598 0.22736,0.78083 0.0587,-0.30736 0.032,-0.62753 0.03,-0.93948 0,-0.1962 -0.0468,-0.69798 -0.0713,-0.75137 -0.0348,0.24268 0.0825,0.63699 -0.16899,0.74 -0.058,-0.72244 -0.0291,-1.46041 -0.0476,-2.18901 -0.006,-2.09788 -0.0295,-4.19582 -0.0243,-6.29367 z", +1.1248, 15.7337, +"M 0.154165 -15.7331 c -0.024,0.006 -0.0442,0.058 -0.0594,0.16072 -0.0119,0.0804 -0.0224,0.198 -0.032,0.33693 -0.18859,0.42108 0.0568,0.96324 -0.22582,1.36374 0.2354,0.42752 0.12835,0.94985 0.13436,1.42472 0.10673,0.60433 -0.83863,0.28316 -0.87694,0.59066 0.2572,0.43226 -0.0173,0.8381 -0.0377,1.27641 0.21408,0.45321 -0.16298,0.88129 0.0558,1.32705 -0.23974,0.30068 0.199,0.60453 -0.0589,0.92553 -0.006,0.92527 -0.0266,1.8508 -0.0517,2.77605 0.0152,0.4801 -0.0752,1.02656 0.14777,1.4578 -0.25857,-0.0769 -0.30935,0.24479 -0.16174,0.47594 -0.075,0.46382 0.12888,0.91188 -0.016,1.36787 -0.0107,1.507433 0.0413,3.015673 0.10384,4.521693 0.17331,0.47524 0.0581,0.99741 0.19535,1.44487 -0.36307,0.3697 -0.20532,0.96671 -0.25062,1.43919 -0.0318,0.49346 0.11663,1.03192 -0.0951,1.49086 0.14563,0.84649 0.0783,1.71241 0.1111,2.5678 -0.0665,0.45222 0.24572,0.9223 -0.0563,1.32601 -0.16113,0.30199 -0.14396,0.87955 0.10181,1.04645 -0.008,0.50476 0.33631,0.95241 0.12867,1.45211 0.19711,0.12306 0.23508,0.16336 0.093,0.39998 -0.25935,0.34252 0.27746,0.87321 -0.10441,1.09347 -0.51512,0.10675 0.14735,0.092 0.17105,0.3359 -0.11326,0.32055 -0.0946,1.20548 0.39069,0.72501 0.77099,0.005 -0.24847,-0.55675 0.12041,-0.89813 0.0876,-0.7571 0.0666,-1.52622 0.017,-2.28565 -0.17201,-0.6034 -0.11922,-1.24776 -0.0837,-1.86965 0.24857,-0.51407 -0.0498,-1.02934 0.016,-1.55391 -0.006,-0.45575 0.10213,-0.87945 -0.0367,-1.32136 -0.0154,-0.45173 -0.18735,-0.86783 0.13745,-1.26039 0.17299,-0.38763 0.16688,0.10802 0.19378,0.28939 0.13417,0.39563 0.14968,0.90483 0.22739,1.25987 0.1107,-0.96718 0.0622,-1.94664 0.0801,-2.9192 0.006,-0.9718 0.007,-1.94324 0.007,-2.91507 0.0104,0.0106 0.0205,0.0219 0.0315,0.031 0.27921,0.23143 0.31816,-0.0277 0.16589,-1.11104 -0.17018,-1.20977 -0.16534,-1.42171 0.0331,-1.43661 0.12761,-0.0166 0.23202,0.66842 0.23202,1.51361 0,0.84503 0.0583,1.14304 0.12972,0.65991 0.14145,-0.95658 0.0967,-13.710923 0.0274,-13.242613 -0.0693,0.46832 -0.28163,-0.48851 -0.47181,-2.12545 -0.062,-0.53393 -0.12687,-0.97738 -0.18965,-1.3286 -1.9e-4,-0.26869 -0.003,-0.53746 -0.002,-0.80616 l -0.16123,0.10542 c -0.0298,-0.0783 -0.0571,-0.11812 -0.0806,-0.11213 z", +1.19528, 10.0475, +"M 0.114948 -10.0474 -0.50148,0.14618 c 0.0736,0.18661 0.16739,0.36967 0.261,0.54185 -0.0538,0.4307 0.22483,0.82056 0.0968,1.2648 -0.0525,0.36807 -0.1816,0.11366 -0.21076,-0.0961 -0.007,-0.23246 -0.37153,-0.97536 -0.51525,-0.43993 -0.11169,0.66702 0.20719,1.30602 0.21001,1.96991 -0.10058,0.38477 -0.12871,0.71438 -0.0766,1.11766 0.11511,0.40452 0.49088,0.70014 0.16472,1.13856 -0.0959,0.46912 0.0158,0.94258 0.003,1.41083 -0.0326,0.51795 0.0689,1.02842 0.006,1.55089 -0.14471,0.4072 -0.12605,0.91736 -0.37066,1.24545 0.20492,0.14259 0.56731,0.13997 0.4087,0.53758 -0.10038,0.73209 -0.0783,1.47103 -0.13167,2.20635 0.0757,0.52752 -0.1133,1.03601 -0.15412,1.55692 0.0337,0.76041 -0.16675,1.50234 -0.28566,2.24782 -0.1094,0.44497 -0.0894,0.90202 -0.16034,1.34929 -0.0245,0.16179 -0.1532,0.38291 0.10343,0.38358 0.48997,0.0292 0.56196,0.55944 0.49872,0.95487 -0.17814,0.30505 0.0416,0.71193 0.0159,1.00833 l 0.2316,-0.0937 c 0.066,-0.33303 0.12356,-0.66776 0.19171,-1.00036 0.31225,-1.29348 0.46274,-2.61533 0.65329,-3.92988 0.14143,-0.74868 0.0819,-1.51508 0.22844,-2.26219 -0.0167,-0.47274 0.0824,-0.94169 0.053,-1.41451 0.0186,-0.47544 0.0882,-0.94598 0.058,-1.42092 0.0683,-0.45815 -0.0209,-0.89535 -0.002,-1.36269 0.0604,-0.47506 0.0288,-0.95181 -0.0173,-1.42355 0.1158,-0.28601 -0.15986,-0.86145 0.10674,-0.9301 -0.0248,0.50068 0.22634,0.12776 0.21472,-0.15544 -0.004,-0.18483 -0.0516,-0.89113 -0.24975,-0.42432 0.24166,0.0912 -0.0666,0.42542 -0.17345,0.40205 0.17628,-0.29069 0.0179,-0.61457 0.0859,-0.92048 0.25808,-0.41654 0.13936,-0.89587 -0.12721,-1.26285 -0.14964,-0.44611 -0.18222,-0.91074 -0.22982,-1.36825 -0.0568,-0.4894 -0.17777,-0.9772 -0.21376,-1.45567 0.005,-0.36792 -0.0846,-0.72055 -0.17196,-1.07205 z", +1.30323, 16.4753, +"M 0.0525373 -16.4753 -1.35577,1.84766 c 0.27683,0.42497 0.50698,1.05949 0.54982,1.4889 0.16442,1.33355 -0.31785,2.67593 -0.0632,4.05717 0.89557,1.12078 0.40959,2.34393 0.16413,3.57614 -0.17728,1.24541 0.33502,2.53287 0.6468,3.771819 0.23041,1.45009 0.26088,2.878319 -0.008,4.303319 -0.24439,1.27673 -0.30622,2.48615 0.0291,3.76989 -0.15519,1.31328 -0.52854,2.58989 -0.56215,3.88389 -0.40545,1.32231 0.79113,2.83626 -0.1482,4.10603 -0.48269,0.66505 -0.53542,1.40168 -0.46451,2.14587 l 1.46058,-0.003 c 0.0168,-0.42614 0.0252,-0.85474 0.0677,-1.27432 0.2539,-1.34995 0.14317,-2.66731 0.3672,-4.02616 0.031,-1.4516 0.11297,-2.83964 0.19182,-4.25746 0.12583,-1.2814 -0.13142,-2.63659 0.16191,-3.91395 -0.1099,-1.37381 -0.1194,-2.74933 -0.14373,-4.116199 0.0786,-1.414249 -0.23712,-2.813419 -0.12807,-4.194219 -0.0646,-1.50176 -0.23348,-3.00275 -0.21195,-4.44847 0.788,-0.10067 0.97118,-1.25313 0.22118,-1.50409 0.42751,0.71673 -0.59912,0.75408 -0.39471,0.0445 0.49068,-0.38166 0.47426,-0.5855 0.0196,-0.82701 0.15128,-1.10943 -0.28974,-2.18426 -0.17309,-3.35652 -0.008,-0.38118 -0.13645,-0.71905 -0.22593,-1.07252 z", +3.07777, 16.9417, +"M -0.540315 -15.4793 c -0.24634,0.11349 -1.09658,-1.59624 -1.32736,-1.45407 -0.46023,-0.0191 -0.87738,0.005 -0.4728,0.85065 -0.38438,0.23736 0.33291,1.49353 -0.0462,1.73799 0.11651,0.36917 0.22846,-0.0337 0.42244,7.7e-4 0.15386,0.31092 0.11637,0.69337 0.1657,1.02389 0.34684,0.15366 0.10848,0.64269 0.28358,0.76644 0.41195,-0.0452 0.55085,0.74543 0.0419,0.5194 -0.27864,0.26975 0.19724,0.25988 0.15384,0.53117 0.1548,0.28493 0.18472,-0.0741 0.12234,-0.20191 0.13378,-0.5353 0.43906,0.1542 0.21787,0.35432 -0.44319,-0.0388 -0.0774,0.48499 0.15909,0.23185 0.10925,-0.0917 0.16042,0.22403 0.24283,0.28936 0.16253,0.3502 -0.0983,-0.0308 -0.20977,-0.0917 0.0884,0.0915 -0.32447,0.49774 -0.0756,0.36635 0.504,-0.0226 -0.0992,0.43767 0.20795,0.63982 -0.12496,0.26315 0.26137,0.29982 0.17242,0.57031 0.17152,0.21667 0.0867,0.45418 -0.10428,0.6239 0.17103,0.10816 0.33957,0.15221 0.1982,0.38978 -0.16129,0.25419 0.1763,0.20125 0.0976,0.39005 0.32354,0.0622 -0.0735,0.53313 0.26064,0.44952 0.16282,-0.294 0.37219,0.22828 0.27145,0.4162 -0.47933,0.1604 0.29042,0.60248 -0.0488,0.85553 -0.3968,0.13941 0.16426,0.23706 -0.0494,0.45862 0.28882,0.23742 -0.26764,0.54324 0.13284,0.74483 -0.10693,0.19204 0.083,0.29149 0.17713,0.48105 -0.15407,0.2054 0.003,0.54361 0.2659,0.31837 0.41731,-0.0408 -0.0181,0.41236 -0.166,0.51107 -0.33606,0.19565 -0.0219,0.65064 -0.0739,0.87903 0.16745,0.29274 -0.13216,0.58183 -0.1062,0.84082 0.34137,-0.0301 0.0236,0.11514 0.051,0.28009 0.0409,0.34986 0.13526,0.72795 0.0252,1.04597 0.15197,0.3677 0.14533,0.69256 0.16035,1.08996 -0.036,0.32787 -0.12398,0.67271 -0.0792,1.00699 0.0442,0.35265 -0.0843,0.70567 0.0129,1.05246 -0.16927,0.31514 0.0256,0.61454 -0.0918,0.92499 0.16825,0.22895 -0.33833,0.64208 -0.0292,0.80537 0.15925,-0.0153 0.26898,-0.23555 0.49496,-0.0945 0.26864,0.26814 -0.20509,0.57525 -0.34709,0.79008 -0.22991,0.0506 -0.30996,0.1628 -0.20241,0.38893 -0.17522,0.31665 -0.083,0.71442 -0.19792,1.05749 -0.13603,0.29173 -0.0706,0.64159 -0.18877,0.95263 -0.0571,0.35637 -0.19909,0.70354 -0.20502,1.0641 0.0598,0.35902 -0.37999,0.56428 -0.25411,0.85446 -0.17361,0.0964 -0.0151,0.24287 -0.10293,0.35328 -0.12389,0.31997 -0.23871,0.64343 -0.31422,0.9698 0.37628,0.16039 -0.17227,0.39286 -0.16858,0.63597 0.30078,0.23058 -0.13834,0.45129 -0.031,0.70849 -0.25057,0.0583 -0.25681,0.38137 -0.29542,0.62486 -0.16162,0.27054 -0.36499,0.58731 -0.41785,0.94511 -0.20866,0.32369 -0.2598,0.71855 -0.47571,1.0374 -0.0588,0.22792 -0.45417,0.58871 -0.21593,0.77317 0.17559,0.16477 -0.45739,0.3482 -0.45852,0.6172 -0.19443,0.35075 0.20244,0.16374 0.23716,-0.0487 0.19866,0.0213 -0.14873,0.46087 -0.16338,0.61248 0.061,0.23503 -0.25086,0.084 -0.18389,0.22621 0.0489,0.15635 0.11616,0.29085 0.27212,0.14598 0.22858,-0.16237 0.2946,-0.0576 0.29863,0.10731 l 0.58122,-0.23538 c 0.0821,-0.26109 0.13335,-0.52666 0.32626,-0.73129 0.29731,-0.21914 0.4927,-0.5536 0.42053,-0.90933 0.28474,-0.14849 -0.14372,-0.26041 0.14824,-0.39219 0.0582,-0.25514 0.25636,-0.49292 0.21565,-0.73236 0.20454,-0.25284 0.2954,-0.60737 0.43347,-0.91621 0.15348,-0.36215 0.22129,-0.75885 0.40247,-1.10584 -0.28553,-0.13508 0.0396,-0.0926 0.0685,-0.27653 0.002,-0.34291 0.29517,-0.66136 0.262,-0.97518 -0.081,-0.33699 0.1328,-0.65558 0.15942,-0.96449 0.0684,-0.31442 0.27457,-0.63665 0.23586,-0.96492 0.0625,-0.50054 0.23178,-0.97825 0.42326,-1.44136 0.18554,-0.19438 0.0484,-0.42979 0.14205,-0.62178 0.0484,-0.35206 0.10613,-0.7143 0.13996,-1.07237 -0.0486,-0.32538 0.0402,-0.66028 0.0568,-0.98284 -0.1766,-0.19954 0.22096,-0.45145 -0.005,-0.58272 0.24328,-0.0558 0.0135,-0.13491 -0.0604,-0.28181 0.19276,-0.31297 0.27144,-0.70626 0.22753,-1.05971 -0.0252,-0.37093 0.27933,-0.65074 0.23872,-1.02209 0.13549,-0.19061 0.0276,-0.13206 -0.15026,-0.14387 0.20177,-0.27604 0.0426,-0.68124 0.0698,-1.00127 -0.25174,-0.36563 0.5493,-0.54553 0.3428,-0.81705 -0.25356,-0.23622 0.32006,-0.0315 0.44898,-0.15681 0.26237,0.0525 0.16508,-0.0532 0.004,-0.17008 -0.44135,-0.0992 -0.0848,-0.46999 0.19506,-0.38124 0.28648,0.19195 0.22981,-0.48563 0.0384,-0.17107 0.12844,-0.16201 -0.19188,-0.2907 -0.11936,-0.0706 -0.26147,0.0464 0.31544,-0.3974 0.12276,-0.52606 -0.5222,-0.16455 0.47293,-0.4875 0.0622,-0.80128 -0.15487,-0.35815 -0.30698,0.0345 -0.12834,0.21111 0.11054,0.25141 -0.0432,0.17819 -0.13073,0.002 -0.25855,-0.2018 0.0244,-0.36195 -0.0498,-0.57233 -0.0965,-0.35513 0.12392,-0.0329 0.17524,0.11028 0.25543,0.19264 0.35139,-0.0251 0.16432,-0.22037 -0.004,-0.33007 -0.26981,-0.63496 -0.12873,-0.93904 -0.26093,-0.11267 -0.0552,-0.27303 0.0915,-0.39209 -0.21433,-0.10496 0.0965,-0.35929 -0.11769,-0.54934 -0.25618,-0.32729 0.28716,-0.15825 0.25115,-0.39389 0.11279,-0.26574 -0.36057,-0.39294 -0.28675,-0.7419 0.005,-0.33252 -0.16188,-0.73649 0.0676,-0.99258 -0.30161,0.0812 -0.28705,-0.41089 -0.53868,-0.52123 -0.15675,0.11505 -0.4179,0.16922 -0.34564,-0.13387 0.14195,-0.3866 0.5009,0.36188 0.45085,-0.0604 0.23245,-0.0749 0.17085,-0.38571 -0.1051,-0.20675 -0.4024,0.21999 -0.32985,-0.45314 -0.03,-0.54873 0.23973,-0.30604 -0.0514,-0.68237 0.0219,-1.00559 -0.25351,0.14792 -0.18752,-0.10625 -0.0293,-0.19294 -0.17696,-0.18581 0.13556,-0.36147 -0.0298,-0.49713 0.0619,-0.35137 -0.28931,-0.20494 -0.41784,0.002 -0.25619,0.36645 -0.46783,-0.021 -0.55009,-0.28332 -0.23712,-0.21349 0.077,-0.44237 -0.0703,-0.63757 -0.0231,-0.364 -0.38759,-0.5027 -0.41947,-0.85291 -0.40308,-0.16283 -0.33097,-0.5917 -0.39057,-0.93046 0.066,-0.25081 0.0521,-0.49286 -0.16035,-0.69864 -0.0175,-0.32952 -0.20434,-0.65743 -0.31229,-0.96069 -0.27709,-0.23307 -0.26297,-0.67784 -0.45519,-0.90665 z", +1.20026, 9.02829, +"M -0.647852 8.69897 c 0.27123,0.89699 0.28293,-0.25188 1.17294,-0.91121 -0.019,-0.45337 -0.0333,-0.90699 -0.0667,-1.35961 -0.16717,-0.71424 -0.26623,-1.42486 -0.18603,-2.16524 -0.35177,-0.76585 0.25336,-1.53555 -0.20672,-2.29857 -0.0243,-0.66796 0.56421,-1.8924 0.64041,-2.52784 -0.36439,-0.62391 0.76929,-1.52704 0.43002,-2.6141 -0.11243,0.31694 -0.2569,0.21823 -0.27552,0.42189 -0.0451,0.49293 -0.42354,0.81201 -0.47179,0.95559 -0.21656,-0.23971 -0.88287,-1.05873 -0.93376,-1.99936 0.0638,-0.699 0.36156,-1.33045 0.25064,-2.05931 0.12634,-0.5642 -0.3497,-1.6984 0.4775,-1.78749 0.75422,-0.1124 -8e-5,-0.99299 -0.28784,-0.42271 -0.71152,-0.0264 0.003,-0.62728 -0.27184,-0.94723 -0.76967,-0.14096 -0.83801,0.98907 -0.55758,1.51309 0.38695,0.50259 0.21479,1.05455 -0.26614,1.39216 0.0501,0.97361 0.11051,1.94686 0.15451,2.92075 0.0822,1.46354 0,2.94343 0.2372,4.39147 0.007,0.81629 0.20886,1.59379 0.30335,2.39622 0.37107,0.77953 -0.48689,1.40959 -0.29922,2.23398 0.25837,0.71917 0.26924,1.49082 0.23463,2.2629 0.0409,0.22802 -0.003,0.42297 -0.078,0.60462 z", +1.28909, 16.4888, +"M -0.601805 -16.4887 c -0.64066,0.01 -0.68406,1.0337 -0.42117,1.52497 0.38696,0.50259 0.21482,1.05455 -0.26611,1.39216 0.0501,0.97361 0.11051,1.94686 0.15451,2.92075 0.0822,1.46354 -2e-5,2.94343 0.23718,4.39147 0.007,0.81629 0.20886,1.5938 0.30334,2.39623 0.37108,0.77953 -0.48686,1.40959 -0.29919,2.23397 0.25837,0.71917 0.26921,1.49084 0.23461,2.26291 0.0409,0.22802 -0.003,0.42297 -0.078,0.60462 0.2036,0.67334 0.26077,0.19399 0.65318,-0.36587 0.0969,0.52347 -0.0537,1.09567 -0.19016,1.50792 0.0168,0.88995 0.65551,0.74475 0.31729,1.64124 -0.0177,0.60701 -0.0656,1.18107 -0.18346,1.53996 0.25987,0.69342 -0.0198,1.56597 -0.17106,2.204 0.0508,0.45325 0.55251,1.01924 0.18243,1.5999 -0.21179,0.38644 0.0962,0.7179 0.22789,0.6749 0.10991,0.92985 -0.3225,-0.36708 -0.2527,0.61391 0.31975,-0.39811 0.20545,1.13303 0.061,1.51257 -0.1973,0.59553 0.0532,1.92311 -0.32557,1.88361 -0.17997,0.49675 0.006,0.49018 0.12301,0.36483 0.33612,0.4428 0.44119,1.18723 0.49659,2.04277 0.35883,0.26987 0.25639,-1.31676 0.30748,-1.8836 0.23582,-0.55477 -0.0262,-1.73369 0.22997,-2.05673 0.17235,-0.37447 0.2776,-0.92052 0.4041,-1.32911 0.0863,-0.79196 -0.53517,-1.19078 -0.13745,-1.73065 0.23614,0.1059 0.15208,-0.41602 0.14108,-0.81338 -0.096,-0.43366 0.0207,-0.65455 0.1421,-0.69195 l -0.0377,-1.03611 c -0.11308,0.12238 -0.18047,0.14259 -0.0718,-0.41652 0.0189,-0.52013 -0.27541,-0.60437 -0.0723,-1.15703 -0.14343,-0.6791 -0.24172,-1.29806 -0.2718,-2.10478 -0.0691,-0.7367 -0.28104,-1.22923 -0.22945,-1.98438 -0.19344,-0.65924 0.37674,-0.26839 0.13023,-1.00149 -0.20709,-0.36744 0.15814,-0.68667 -0.0765,-0.90382 0.23915,-0.85322 -0.17302,-1.75788 0.092,-2.56418 h 5e-4 c 0.18233,-0.97684 -0.41499,-1.56326 -0.47749,-2.1239 -0.0678,0.0482 -0.15229,0.007 -0.23513,-0.0357 -0.0187,-0.0404 -0.0387,-0.0806 -0.063,-0.12092 -0.0243,-0.66796 0.56457,-1.89257 0.64077,-2.52801 -0.36438,-0.62391 0.76922,-1.52674 0.42995,-2.6138 -0.11242,0.31694 -0.25681,0.21802 -0.27543,0.42168 -0.0451,0.49293 -0.42355,0.81192 -0.47181,0.9555 -0.21656,-0.23971 -0.88289,-1.05873 -0.93379,-1.99936 0.0638,-0.699 0.36155,-1.33045 0.25064,-2.05931 0.12634,-0.5642 -0.3497,-1.6984 0.47749,-1.78748 0.75422,-0.1124 -8e-5,-0.993 -0.28784,-0.42272 -0.71152,-0.0264 0.003,-0.62728 -0.27183,-0.94723 -0.0481,-0.009 -0.0937,-0.0125 -0.13642,-0.0119 z", +0.891012, 10.9638, +"M 0.353692 -8.74076 c -0.26499,0.8063 0.14695,1.71094 -0.0922,2.56416 0.23462,0.21715 -0.13037,0.53651 0.0767,0.90395 0.24652,0.7331 -0.32371,0.3421 -0.13029,1.00134 -0.0516,0.75515 0.16007,1.24804 0.22912,1.98474 0.0301,0.80672 0.12886,1.42571 0.27229,2.10481 -0.20308,0.55266 0.0911,0.63666 0.0722,1.1568 -0.10866,0.55911 -0.0412,0.53899 0.0719,0.4166 l 0.0376,1.03625 c -0.12144,0.0374 -0.23824,0.25801 -0.14224,0.69167 0.011,0.39736 0.0951,0.91925 -0.14103,0.81335 -0.39773,0.53987 0.224,0.93857 0.13772,1.73053 -0.12651,0.40859 -0.23189,0.95495 -0.40425,1.32942 -0.25615,0.32304 0.006,1.5018 -0.22982,2.05657 -0.0511,0.56684 0.0512,2.15362 -0.30762,1.88375 -0.0554,-0.85554 -0.16078,-1.60008 -0.49692,-2.04288 -0.11732,0.12535 -0.30284,0.13188 -0.12285,-0.36487 0.37871,0.0395 0.12845,-1.28817 0.32574,-1.8837 0.14445,-0.37954 0.25865,-1.91074 -0.0611,-1.51263 -0.0698,-0.98099 0.36247,0.31593 0.25256,-0.61392 -0.13168,0.043 -0.43956,-0.28828 -0.22776,-0.67472 0.37007,-0.58066 -0.13156,-1.14676 -0.18233,-1.60001 0.15123,-0.63803 0.43113,-1.51051 0.17126,-2.20393 0.11781,-0.35889 0.16536,-0.93265 0.18299,-1.53966 0.33822,-0.89649 -0.30017,-0.75144 -0.31703,-1.64139 0.16345,-0.49382 0.35255,-1.21826 0.1047,-1.81199 -0.36685,-0.1049 0.17326,-0.62553 0.0859,-1.18473 0.11267,-0.55844 0.1666,-0.62712 -0.10721,-0.68 0.21516,-0.68305 -0.17153,-1.14907 -0.0833,-1.906 0.13977,-0.58259 0.0436,-0.99951 -0.009,-1.65408 -0.0315,-1.04621 0.34527,-0.33266 0.55695,-0.48326 0.0625,0.56064 0.66002,1.14699 0.47769,2.12383 z", +1.40858, 15.4784, +"M -0.215316 -14.2449 c -0.0573,-0.39663 -0.09,-0.9845 -0.25167,-1.23351 l -0.008,0.0889 c -0.008,0.51419 -0.0135,1.82829 -0.0164,3.62614 -0.16272,-0.0566 -0.15885,-0.0396 -0.42542,-0.0862 0.12658,0.42973 0.13679,0.99178 0.0761,0.91046 0.003,0.20217 -0.0381,0.38449 -0.14261,0.45011 0.57288,0.0852 0.23548,1.11425 -0.31834,1.01699 -0.14563,0.51493 0.25241,1.08423 -0.0393,1.56063 0.18624,0.45092 0.31719,0.8511 0.0863,1.32291 0.24339,0.56784 0.14216,1.21654 0.18034,1.82315 0.0321,0.60964 -0.054,1.23667 0.0951,1.83296 0.21513,0.29947 -0.39592,0.30966 -0.11316,0.67903 0.039,0.74934 0.21058,1.48397 0.17309,2.23759 0.0111,0.43606 0.0354,1.12083 -0.22064,1.29139 0.64397,0.51467 -0.3131,0.91939 -0.18915,1.4857 0.0477,0.49886 0.30321,1.02072 0.0956,1.48415 -0.0396,0.59756 -0.0501,1.20341 0.21238,1.72341 0.0946,0.62128 -0.0948,1.21611 -0.0119,1.84536 -0.0453,0.5497 0.30977,1.1923 -0.0543,1.66451 -0.19063,0.44184 -8e-5,0.91834 -0.19378,1.33842 -0.0311,0.51712 -0.0706,1.05695 -0.0429,1.57355 -0.0493,0.5227 -0.0706,1.05957 -0.003,1.58026 0.079,0.51085 0.0409,0.93086 -0.0816,1.42059 0.0312,0.0244 0.0439,0.0591 0.0692,0.0868 l 1.44333,-3.35947 c -0.0392,-0.12325 -0.10192,-0.24343 -0.21964,-0.35295 -0.0919,-0.54896 0.15828,-1.13571 0.29766,-1.60611 -0.0725,-0.11045 -0.11144,-0.22339 -0.13435,-0.33744 l 1.00769,-1.16841 c -2.7e-4,-0.0874 0.0233,-0.25803 -0.051,-0.4113 -0.0574,-0.11829 -0.21368,-0.21272 -0.23231,-0.33456 -0.0501,-0.32747 0.096,-0.64257 0.0949,-1.07853 0,-0.22596 -0.12986,-0.49448 -0.12229,-0.73317 0.0391,-1.23285 0.2989,-2.52798 0.29792,-3.1837 0.0119,-0.61935 -0.007,-12.50878 -0.007,-13.10462 0.0514,-0.4966 -0.0418,0.0395 0.1633,-0.14005 0.0463,0.3542 0.0498,-0.47899 0.0491,-0.11317 0.0143,-1.07594 -0.0857,-2.58572 -0.28713,-2.87271 -0.1198,-0.17068 -0.28631,0.41503 -0.45638,0.89253 -0.0151,-0.0313 -0.61574,-1.82898 -0.72041,-1.81959 z m 0.94094,4.32328 c -0.007,2.38506 -0.13253,2.52318 -0.13645,1.38389 -0.004,-0.49656 -0.0196,-0.97179 0.13645,-1.38389 z m -0.7084,1.35338 c 0,7e-5 0,-9e-5 0.003,0 0.0662,0.009 0.17023,0.0887 0.1819,0.15865 0.008,0.0466 -0.0254,0.0889 -0.13798,0.10335 -0.0214,-0.0326 -0.0326,-0.0554 -0.0465,-0.0811 2.1e-4,-0.0603 0,-0.12059 0,-0.18087 z m 0.48411,-0.0599 c 0.0272,0.008 0.063,0.0884 0.0682,0.18345 0.003,0.0634 -0.007,0.13334 -0.0419,0.19224 -0.0347,-0.0107 -0.0299,-0.0884 -0.0419,-0.12299 -0.0298,-0.19578 -0.0116,-0.2606 0.0156,-0.2527 z m -0.55491,2.5006 c 0.0892,0.006 0.19317,0.0297 0.24858,0.0346 0.11311,-0.0172 0.16436,0.0169 0.17415,0.0708 0.003,0.0101 0.003,0.0207 0,0.032 -0.0114,0.14338 -0.23088,0.36319 -0.37465,0.25063 -0.0662,-0.13041 -0.10052,-0.25938 -0.1106,-0.38706 0.0193,-0.001 0.0391,-0.002 0.0615,-0.001 z m 0.13229,1.002 c 0.0214,-0.01 0.0347,0.0183 0.0383,0.0615 0.007,0.0865 -0.0249,0.23269 -0.11009,0.25321 -0.0212,-0.0395 -0.0345,-0.10075 -0.014,-0.14831 0.0356,-0.10904 0.0645,-0.15666 0.0858,-0.1664 z m 0,0.52504 c 0.006,-0.002 0.0143,2.2e-4 0.0233,0.005 0.036,0.0197 0.0874,0.0851 0.0889,0.12505 0,0.0264 -0.0206,0.0421 -0.0842,0.0248 -0.0461,-0.10744 -0.046,-0.14933 -0.0279,-0.15502 z m 0.0201,4.1553 v 0 c 0.0656,-0.0183 0.009,0.15149 0.0156,0.29559 0.0532,0.0409 0.0778,0.0874 0.0837,0.13229 0.003,0.0122 0.003,0.0243 0,0.0362 -0.0151,0.17868 -0.30001,0.30917 -0.21085,-0.0398 -0.005,-0.11149 -0.0596,-0.23076 -0.003,-0.33538 0.056,-0.0558 0.0913,-0.0828 0.11319,-0.0889 z m 1.20973,2.00814 c -0.003,-2.6e-4 -0.005,0.004 -0.007,0.0114 v 0 c -0.008,0.0314 -0.0132,0.12504 0,0.25528 l 0.005,0.0145 0.006,-0.03 c 0.003,-0.0485 0.005,-0.0893 0.005,-0.12299 0.003,-0.0882 -0.003,-0.12732 -0.01,-0.12815 z m -0.0517,0.48576 c -0.007,-0.004 -0.0151,-0.003 -0.0228,0.005 -0.0201,0.0212 -0.0409,0.0895 -0.0594,0.22738 -0.11983,0.55066 -0.2176,3.41162 0.003,3.71346 0.36878,-0.48993 0.18709,-2.28477 0.17984,-2.57762 -0.007,-0.29285 -0.0406,-0.59455 -0.0305,-0.87643 0.0206,-0.16536 -0.0193,-0.46288 -0.0703,-0.49196 z", +1.40858, 15.4784, +"M -0.215316 -14.2449 c -0.0573,-0.39663 -0.09,-0.9845 -0.25167,-1.23351 l -0.008,0.0889 c -0.008,0.51419 -0.0135,1.82828 -0.0164,3.62614 -0.16272,-0.0566 -0.15885,-0.0396 -0.42542,-0.0862 0.12658,0.42973 0.13679,0.99178 0.0761,0.91046 0.003,0.20216 -0.0381,0.38449 -0.14261,0.4501 0.57288,0.0852 0.23548,1.11425 -0.31834,1.017 -0.14563,0.51492 0.25241,1.08422 -0.0393,1.56063 0.18624,0.45092 0.31719,0.8511 0.0863,1.32291 0.24339,0.56784 0.14216,1.21653 0.18034,1.82315 0.0321,0.60964 -0.054,1.23666 0.0951,1.83296 0.21513,0.29947 -0.39592,0.30966 -0.11316,0.67902 0.039,0.74935 0.21058,1.48397 0.17309,2.23759 0.0111,0.43606 0.0354,1.12083 -0.22064,1.2914 0.64397,0.51466 -0.3131,0.91938 -0.18915,1.48569 0.0477,0.49885 0.30321,1.02071 0.0956,1.48415 -0.0396,0.59756 -0.0501,1.20342 0.21238,1.72341 0.0946,0.62127 -0.0948,1.21611 -0.0119,1.84536 -0.0453,0.5497 0.30977,1.19229 -0.0543,1.6645 -0.19063,0.44184 -8e-5,0.91834 -0.19378,1.33842 -0.0311,0.51712 -0.0706,1.05695 -0.0429,1.57355 -0.0493,0.5227 -0.0706,1.05957 -0.003,1.58026 0.079,0.51085 0.0409,0.93086 -0.0816,1.42059 0.0312,0.0244 0.0439,0.0591 0.0692,0.0868 l 1.44333,-3.35948 c -0.0392,-0.12324 -0.10192,-0.24343 -0.21964,-0.35295 -0.0919,-0.54896 0.15828,-1.13571 0.29766,-1.60611 -0.0725,-0.11045 -0.11144,-0.22339 -0.13435,-0.33744 l 1.00769,-1.16841 c -2.7e-4,-0.0874 0.0233,-0.25803 -0.051,-0.4113 -0.0574,-0.11829 -0.21368,-0.21272 -0.23231,-0.33456 -0.0501,-0.32747 0.096,-0.64257 0.0949,-1.07853 0,-0.22595 -0.12986,-0.49447 -0.12229,-0.73317 0.0391,-1.23284 0.2989,-2.52797 0.29792,-3.18369 0.0119,-0.61935 -0.007,-12.50878 -0.007,-13.10462 0.0514,-0.4966 -0.0418,0.0395 0.1633,-0.14005 0.0463,0.3542 0.0498,-0.47899 0.0491,-0.11317 0.0143,-1.07594 -0.0857,-2.58572 -0.28713,-2.87271 -0.1198,-0.17068 -0.28631,0.41503 -0.45638,0.89253 -0.0151,-0.0313 -0.61574,-1.82898 -0.72041,-1.81959 z m 0.94094,4.32327 c -0.007,2.38507 -0.13253,2.52318 -0.13645,1.3839 -0.004,-0.49657 -0.0196,-0.97179 0.13645,-1.3839 z m -0.7084,1.35339 c 0,7e-5 0,-9e-5 0.003,0 0.0662,0.009 0.17023,0.0887 0.1819,0.15865 0.008,0.0466 -0.0254,0.0889 -0.13798,0.10335 -0.0214,-0.0326 -0.0326,-0.0554 -0.0465,-0.0811 2.1e-4,-0.0603 0,-0.12058 0,-0.18087 z m 0.48411,-0.0599 c 0.0272,0.008 0.063,0.0884 0.0682,0.18345 0.003,0.0634 -0.007,0.13333 -0.0419,0.19224 -0.0347,-0.0107 -0.0299,-0.0884 -0.0419,-0.123 -0.0298,-0.19577 -0.0116,-0.26059 0.0156,-0.25269 z m -0.55491,2.5006 c 0.0892,0.006 0.19317,0.0297 0.24858,0.0346 0.11311,-0.0172 0.16436,0.0169 0.17415,0.0708 0.003,0.0101 0.003,0.0207 0,0.032 -0.0114,0.14339 -0.23088,0.36319 -0.37465,0.25063 -0.0662,-0.13041 -0.10052,-0.25937 -0.1106,-0.38705 0.0193,-0.001 0.0391,-0.002 0.0615,-0.001 z m 0.13229,1.002 c 0.0214,-0.01 0.0347,0.0183 0.0383,0.0615 0.007,0.0865 -0.0249,0.23269 -0.11009,0.25321 -0.0212,-0.0395 -0.0345,-0.10075 -0.014,-0.14832 0.0356,-0.10903 0.0645,-0.15665 0.0858,-0.16639 z m 0,0.52504 c 0.006,-0.002 0.0143,2.1e-4 0.0233,0.005 0.036,0.0197 0.0874,0.0851 0.0889,0.12505 0,0.0264 -0.0206,0.0421 -0.0842,0.0248 -0.0461,-0.10744 -0.046,-0.14934 -0.0279,-0.15502 z m 0.0201,4.1553 v 0 c 0.0656,-0.0183 0.009,0.15149 0.0156,0.29558 0.0532,0.0409 0.0778,0.0874 0.0837,0.1323 0.003,0.0122 0.003,0.0243 0,0.0362 -0.0151,0.17868 -0.30001,0.30918 -0.21085,-0.0398 -0.005,-0.1115 -0.0596,-0.23077 -0.003,-0.33539 0.056,-0.0558 0.0913,-0.0828 0.11319,-0.0889 z m 1.20973,2.00814 c -0.003,-2.6e-4 -0.005,0.004 -0.007,0.0114 v 0 c -0.008,0.0314 -0.0132,0.12505 0,0.25528 l 0.005,0.0145 0.006,-0.03 c 0.003,-0.0485 0.005,-0.0893 0.005,-0.12298 0.003,-0.0882 -0.003,-0.12732 -0.01,-0.12816 z m -0.0517,0.48576 c -0.007,-0.004 -0.0151,-0.003 -0.0228,0.005 -0.0201,0.0212 -0.0409,0.0895 -0.0594,0.22737 -0.11983,0.55067 -0.2176,3.41162 0.003,3.71346 0.36878,-0.48992 0.18709,-2.28477 0.17984,-2.57762 -0.007,-0.29285 -0.0406,-0.59455 -0.0305,-0.87643 0.0206,-0.16535 -0.0193,-0.46288 -0.0703,-0.49196 z", +1.19541, 13.7255, +"M -0.876944 -13.7255 0.0201,0.0681 c 0.1772,0.62029 0.2896,1.04659 0.2289,0.96528 0.002,0.20217 -0.038,0.38439 -0.14247,0.45001 0.57288,0.0852 0.23535,1.11439 -0.31847,1.01713 -0.14564,0.51493 0.25248,1.08419 -0.0392,1.56059 0.18623,0.45093 0.31728,0.85144 0.0864,1.32325 0.24339,0.56784 0.14204,1.21638 0.18021,1.82299 0.0321,0.60964 -0.0539,1.23657 0.0952,1.83287 0.21514,0.29946 -0.3963,0.30988 -0.11356,0.67925 0.039,0.74934 0.21098,1.48377 0.17351,2.23739 0.0112,0.43606 0.0353,1.12094 -0.22077,1.2915 0.64399,0.51467 -0.31336,0.91952 -0.1894,1.48583 0.0477,0.49885 0.3035,1.02028 0.0959,1.48372 -0.0396,0.59756 -0.0502,1.20353 0.21231,1.72353 0.0946,0.62128 -0.0949,1.21631 -0.012,1.84556 -0.0453,0.5497 0.30974,1.19243 -0.0543,1.66464 -0.19062,0.44184 9e-5,0.91798 -0.19363,1.33806 -0.0311,0.51712 -0.0704,1.05705 -0.0427,1.57365 -0.0493,0.5227 -0.071,1.05966 -0.003,1.58035 0.079,0.51085 0.041,0.93086 -0.0815,1.42059 0.0312,0.0244 0.0438,0.059 0.0691,0.0867 l 1.4435,-3.35926 c -0.0392,-0.12324 -0.102,-0.24386 -0.21971,-0.35338 -0.0919,-0.54896 0.15862,-1.13534 0.29801,-1.60574 -0.33671,-0.51282 -0.0478,-1.07406 0.0233,-1.5934 0.1794,-0.51138 -0.42493,-0.9927 -0.1319,-1.57117 0.10052,-0.42731 0.34806,-0.7585 0.55653,-1.13598 -0.0485,-0.45487 -0.63618,-0.4481 -0.40805,-0.98503 0.20565,-0.4798 0.19847,-1.00573 0.32411,-1.49994 0.0473,-0.60976 -0.18707,-1.15221 -0.31882,-1.73588 -0.20363,-0.49064 -0.48402,-0.98562 -0.62777,-1.483 -0.0236,-0.51779 0.25969,-0.98172 0.1594,-1.47137 0.1783,-0.63379 0.0603,-1.30668 0.0592,-1.95596 -0.13465,-0.3989 -0.16238,-0.76032 0.0586,-1.11763 -0.46748,-0.37921 0.27905,-0.83492 0.14106,-1.29856 -0.31768,-0.55003 0.008,-1.06122 -0.008,-1.63184 0.006,-0.47253 0.005,-0.94519 0.008,-1.41776 0.24498,-0.23512 0.71548,-0.65116 0.36114,-0.92225 0.73256,-2.2984 0.9711,-1.21193 -0.28683,-2.21043 -0.41602,-0.19937 -0.35419,0.1806 -1.06564,-0.0622 l -0.11675,-0.0402 z", +0.884301, 13.8117, +"M -0.123121 -2.30275 c -0.004,0.0919 -0.0285,0.17097 -0.0723,0.21497 -0.0879,0.0879 -0.15049,-0.0684 -0.13901,-0.34726 0.0127,-0.30824 0.0757,-0.37079 0.1602,-0.15968 0.0382,0.0955 0.0552,0.20005 0.0512,0.29197 z m 1.00562,-4.18682 c -0.0136,0.12449 -0.10434,0.28911 -0.27647,0.53486 -0.23763,0.33924 -0.43417,0.85838 -0.43615,1.15339 -0.002,0.29504 -0.1194,0.71499 -0.26045,0.93329 -0.21074,0.32602 -0.25744,0.29832 -0.26045,-0.15451 -0.002,-0.30319 0.041,-0.60087 0.0961,-0.66146 0.0825,-0.0908 0.27686,-3.75423 0.44804,-8.44444 0.031,-0.84879 0.0508,-0.8709 0.24029,-0.26459 0.11369,0.36381 0.14246,1.9526 0.0641,3.53053 -0.10848,2.18249 -0.061,2.9193 0.19896,3.0799 0.13612,0.0841 0.19963,0.16849 0.18603,0.29303 z m -0.97307,14.8394 c 0,0.28238 -0.11129,0.44439 -0.24753,0.36017 -0.13626,-0.0842 -0.24426,-0.35901 -0.23926,-0.61081 0.005,-0.25181 -0.0503,-1.31485 -0.12247,-2.36263 -0.0894,-1.29767 -0.0341,-1.94495 0.17311,-2.02985 0.21135,-0.0867 0.20302,-0.13124 -0.0269,-0.14574 -0.1819,-0.0114 -0.32231,-0.28855 -0.31212,-0.61597 0.0178,-0.56801 0.029,-0.57121 0.24598,-0.0661 0.15007,0.34917 0.23368,-0.29792 0.24597,-1.90273 0.0102,-1.33752 0.11528,-2.49142 0.23307,-2.56418 0.11788,-0.0728 0.16275,0.57507 0.10025,1.4397 -0.0711,0.98351 -0.0107,1.572 0.16123,1.572 0.54297,0 -0.21133,6.64377 -0.21133,6.92614 z m -0.43305,2.47427 c -0.003,0.0791 -0.0141,0.16582 -0.0315,0.25683 -0.0696,0.36375 -0.17208,0.66146 -0.22789,0.66146 -0.0558,0 -0.10129,-0.29771 -0.10129,-0.66146 0,-0.3638 0.10256,-0.66145 0.2279,-0.66145 0.094,0 0.14338,0.16742 0.1328,0.40462 z m -0.12867,1.68982 c -0.004,0.0919 -0.0285,0.17097 -0.0724,0.21497 -0.0879,0.0879 -0.1505,-0.0684 -0.13901,-0.34726 0.0127,-0.30824 0.0757,-0.37077 0.1602,-0.15968 0.0382,0.0955 0.0552,0.20005 0.0512,0.29197 z m 0,1.05833 c -0.004,0.0919 -0.0285,0.17097 -0.0724,0.21497 -0.0879,0.0879 -0.1505,-0.0684 -0.13901,-0.34726 0.0127,-0.30824 0.0757,-0.37079 0.1602,-0.15968 0.0382,0.0955 0.0552,0.20005 0.0512,0.29197 z", +0.762531, 16.9731, +"M 0.232564 -5.04002 c -0.0256,-0.11674 -0.0255,0.0289 2.6e-4,0.32444 0.0258,0.29532 -0.0179,0.76648 -0.0971,1.0473 -0.1026,0.36391 -0.10352,0.73496 -0.002,1.29023 0.078,0.42853 0.12701,1.18085 0.10877,1.67181 -0.0212,0.57309 0.0381,0.8967 0.16574,0.90407 0.1094,0.006 0.20455,0.27367 0.21158,0.59484 0.007,0.32117 0.0586,0.89271 0.11421,1.26969 0.0618,0.41843 0.0213,1.04432 -0.10385,1.60629 -0.11282,0.50634 -0.20014,1.44467 -0.19397,2.08543 0.014,1.44453 -0.12951,2.17576 -0.37292,1.90107 -0.1185,-0.13368 -0.18543,0.0559 -0.18543,0.52551 0,0.40439 -0.0704,0.80453 -0.15642,0.88886 -0.0967,0.0949 -0.0239,0.44232 0.0371,0.91016 0.0545,0.41609 0.0799,0.79268 0.057,0.83706 -0.0229,0.0444 0.0755,0.33281 0.21858,0.64057 0.22056,0.47431 0.2334,0.65408 0.0844,1.18204 -0.0967,0.34255 -0.22876,0.52665 -0.29342,0.40904 -0.12361,-0.22462 -0.1455,0.20684 -0.13985,2.75717 0.004,1.47266 -0.0968,1.49441 -0.19275,0.38996 -0.0557,-0.64348 -0.0753,-1.8719 -0.0437,-2.72975 0.0963,-2.62133 0.0685,-4.17561 -0.0793,-4.44423 -0.16273,-0.29578 -0.0597,-2.89904 0.12249,-3.09534 0.0663,-0.0715 0.1127,-0.94893 0.10307,-1.94981 -0.0172,-1.79322 -0.0187,-1.79958 -0.11498,-0.45471 -0.0781,1.0917 -0.10126,0.79463 -0.11525,-1.48522 -0.0111,-1.81302 0.0309,-2.76277 0.11525,-2.6094 0.0823,0.14963 0.1326,-0.58109 0.1326,-1.92698 0,-1.47122 -0.0508,-2.13633 -0.15798,-2.07016 -0.0868,0.0537 -0.18056,-0.20961 -0.20847,-0.58495 -0.0279,-0.37534 0.0131,-0.68244 0.0914,-0.68244 h 2.6e-4 c 0.0924,0 0.14244,-1.44486 0.14244,-4.11748 0,-2.64579 0.0474,-4.03168 0.13259,-3.87679 0.0798,0.14518 0.13259,-0.37062 0.13259,-1.29631 0,-1.36676 0.0404,-1.55998 0.36387,-1.7419 0.48964,-0.27527 0.1634,-0.0741 0.1634,1.52406 0,0.94267 -0.048,1.2778 -0.15513,1.08305 -0.10578,-0.19225 -0.12686,-0.065 -0.0663,0.39909 0.0488,0.37448 0.0888,0.92971 0.0888,1.23389 0,0.30416 0.096,0.55297 0.21314,0.55297 0.13289,0 0.18485,0.21576 0.13829,0.57273 -0.0411,0.31487 -0.0177,0.67604 0.0521,0.80278 0.0697,0.12676 0.1269,0.49327 0.1269,0.815 0,0.32153 -0.0597,0.47673 -0.1326,0.34425 -0.0729,-0.1325 -0.1326,-0.055 -0.1326,0.17214 0,0.22706 0.0525,0.41282 0.11654,0.41282 0.0641,0 -0.26373,4.03388 -0.28935,3.91715 z", +0.560077, 8.98122, +"M 0.467182 8.52902 c -0.0714,0.48313 -0.12974,0.18491 -0.12974,-0.66012 0,-0.84519 -0.10442,-1.5299 -0.23204,-1.51334 -0.1984,0.0149 -0.20328,0.22696 -0.0331,1.43673 0.15228,1.08338 0.11346,1.34238 -0.16574,1.11095 -0.29936,-0.24779 -0.36464,-0.99245 -0.36464,-4.15731 0,-2.12029 -0.0357,-5.81576 -0.0795,-8.212422 -0.0467,-2.55505 -0.019,-4.76947 0.0673,-5.35317 0.081,-0.54783 0.30289,0.34342 0.49308,1.9808 0.19018,1.63694 0.4026,2.59378 0.47186,2.12546 0.0693,-0.46831 0.11396,12.285842 -0.0275,13.242422 z", +0.762531, 19.7675, +"M 0.232564 -7.83435 c -0.0256,-0.11674 -0.0255,0.0289 2.6e-4,0.32444 0.0258,0.29532 -0.0179,0.76648 -0.0971,1.0473 -0.1026,0.36391 -0.10352,0.73496 -0.002,1.29023 0.078,0.42853 0.12701,1.18085 0.10877,1.67181 -0.0212,0.57309 0.0381,0.8967 0.16574,0.90407 0.1094,0.006 0.20455,0.27367 0.21158,0.59484 0.007,0.32117 0.0586,0.89271 0.11421,1.26969 0.0618,0.41843 0.0213,1.04432 -0.10385,1.60629 -0.11282,0.50634 -0.20014,1.44467 -0.19397,2.08543 0.014,1.44453 -0.12951,2.17576 -0.37292,1.90107 -0.1185,-0.13368 -0.18543,0.0559 -0.18543,0.52551 0,0.40439 -0.0704,0.80453 -0.15642,0.88886 -0.0967,0.0949 -0.0239,0.44232 0.0371,0.91016 0.0545,0.41609 0.0799,0.79268 0.057,0.83706 -0.0229,0.0444 0.0755,0.33281 0.21858,0.64057 0.22056,0.47431 0.2334,0.65408 0.0844,1.18204 -0.0967,0.34255 -0.22876,0.52665 -0.29342,0.40904 -0.12361,-0.22462 -0.1455,0.20684 -0.13985,2.75717 0.004,1.47266 -0.0968,1.49441 -0.19275,0.38996 -0.0557,-0.64348 -0.0753,-1.8719 -0.0437,-2.72975 0.0963,-2.62133 0.0685,-4.17561 -0.0793,-4.44423 -0.16273,-0.29578 -0.0597,-2.89904 0.12249,-3.09534 0.0663,-0.0715 0.1127,-0.94893 0.10307,-1.94981 -0.0172,-1.79322 -0.0187,-1.79958 -0.11498,-0.45471 -0.0781,1.0917 -0.10126,0.79463 -0.11525,-1.48522 -0.0111,-1.81302 0.0309,-2.76277 0.11525,-2.6094 0.0823,0.14963 0.1326,-0.58109 0.1326,-1.92698 0,-1.47122 -0.0508,-2.13633 -0.15798,-2.07016 -0.0868,0.0537 -0.18056,-0.20961 -0.20847,-0.58495 -0.0279,-0.37534 0.0131,-0.68244 0.0914,-0.68244 h 2.6e-4 c 0.0924,0 0.14244,-1.44486 0.14244,-4.11748 0,-2.64579 0.0474,-4.03168 0.13259,-3.87679 0.0798,0.14518 0.13259,-0.37062 0.13259,-1.29631 0,-1.36676 0.0404,-1.55998 0.36387,-1.7419 0.48964,-0.27527 0.1634,-0.0741 0.1634,1.52406 0,0.94267 -0.048,1.2778 -0.15513,1.08305 -0.10578,-0.19225 -0.12686,-0.065 -0.0663,0.39909 0.0488,0.37448 0.0888,0.92971 0.0888,1.23389 0,0.30416 0.096,0.55297 0.21314,0.55297 0.13289,0 0.18485,0.21576 0.13829,0.57273 -0.0411,0.31487 -0.0177,0.67604 0.0521,0.80278 0.0697,0.12676 0.1269,0.49327 0.1269,0.815 0,0.32153 -0.0597,0.47673 -0.1326,0.34425 -0.0729,-0.1325 -0.1326,-0.055 -0.1326,0.17214 0,0.22706 0.0525,0.41282 0.11654,0.41282 0.0641,0 -0.26373,4.03388 -0.28935,3.91715 z m 0.0396,27.48027 c -0.0714,0.12985 -0.12974,0.0497 -0.12974,-0.17742 0,-0.22716 -0.10442,-0.41119 -0.23204,-0.40674 -0.1984,0.004 -0.20328,0.061 -0.0331,0.38615 0.15228,0.29118 0.11346,0.36079 -0.16574,0.29859 -0.29936,-0.0666 -0.36464,-0.26674 -0.36464,-1.11736 0,-0.56987 -0.0357,-1.5631 -0.0795,-2.20725 -0.0467,-0.68672 -0.019,-1.28189 0.0673,-1.43877 0.081,-0.14724 0.30289,0.0923 0.49308,0.53238 0.19018,0.43996 0.4026,0.69713 0.47186,0.57126 0.0693,-0.12587 0.11396,3.30206 -0.0275,3.55916 z", +1.269, 19.5416, +"M 0.14825 -19.5416 c -0.32661,0.39468 -0.3994,1.66107 -0.7598,2.04169 -0.41626,0.2009 -0.37637,1.71843 -0.58357,2.35306 0.0458,1.94112 -0.13983,3.86046 -0.048,5.80025 0.0294,1.34326 0.10658,2.68769 0.0855,4.03529 -0.0762,1.10649 0.0737,2.4593 -0.0252,3.70953 -0.0204,0.90305 0.056,1.55369 -0.0307,2.40511 0.0317,2.24936 0.21841,4.51036 0.0946,6.75626 -0.0753,1.08892 0.0479,1.9506 0.41334,1.69121 0.43294,0.76903 0.0677,2.22794 -0.0667,3.18578 -0.19001,0.81644 0.11544,1.40278 0.30591,1.39693 -0.0451,-0.42285 -0.28028,-2.17954 0.0281,-1.08788 0.33743,0.48853 -0.12596,2.7085 -0.38629,1.41622 -0.28035,0.0578 0.0439,1.62405 -0.26723,2.03911 -0.13348,0.55093 0.1996,1.81699 0.24795,0.69045 -0.11076,1.53067 0.61772,1.10071 0.51013,2.65016 0.0573,-0.0207 0.22667,-1.00323 0.23225,-1.34788 0.08,-0.9498 0.53243,-2.15075 0.25784,-3.07732 -0.30065,-0.79082 0.41871,-1.52126 0.11979,-2.62364 -0.0371,-0.56266 -0.17904,-1.49854 -0.12697,-0.30689 0.003,0.94503 -0.34219,0.63414 -0.29234,1.70477 -0.30776,-0.58284 0.30053,-2.415 -0.32326,-2.26952 0.11911,-0.39881 0.21227,-1.78449 0.37582,-0.58638 0.38472,0.39819 0.28972,-1.2848 0.30849,-2.1732 0.01,-1.30431 0.11678,-2.2807 -0.0501,-3.51089 -0.22551,-0.80379 0.19385,-2.07867 -0.24626,-2.47433 -0.35322,-0.76698 0.20938,-2.5558 0.24625,-0.9447 0.20473,1.61631 0.33115,-1.44215 -0.0187,-1.00535 -0.20738,-0.73783 0.50146,-0.8757 0.0966,-1.34105 -0.23718,0.80488 -0.81457,0.0175 -0.51184,-1.058 0.23378,-0.45163 0.79437,0.53657 0.57233,-1.14201 -0.13148,-0.58581 -0.34247,-1.16952 -0.45141,-1.63641 0.0722,-0.37607 0.21467,-1.5057 0.37321,-0.66014 0.20019,0.95972 0.14835,-1.38787 0.16689,-1.8434 -0.0266,-0.64918 0.1111,-1.97392 -0.17902,-1.90736 -0.13214,-0.95422 0.003,-2.15651 0.24077,-2.14256 -0.0855,-1.27561 0.30739,-2.14491 0.59873,-1.54848 0.46782,-0.57364 0.0341,-2.11974 -0.0515,-3.1238 -0.0488,-1.29164 -0.35659,-0.91037 -0.47231,-0.43792 -0.20293,-0.6018 -0.22527,-1.26026 -0.1283,-2.00164 -0.13967,-0.42976 -0.33758,0.56271 -0.34577,-0.61191 0.10408,-0.26168 0.33651,-0.79224 0.0907,-1.01316 z", +2.21549, 17.1584, +"M -0.167255 -17.1539 c -0.0167,0.007 -0.0346,0.0209 -0.0528,0.0449 -0.0209,0.0276 -0.0424,0.0677 -0.0625,0.1243 0.29371,0.10775 0.23216,-0.21534 0.1151,-0.1692 z m 0.15604,1.07656 c -0.12396,-5.2e-4 -0.2654,0.0531 -0.37769,0.13732 l -0.001,8.7e-4 c -0.0997,0.0747 -0.17632,0.1734 -0.19745,0.27884 0.47404,0.75848 -0.48688,0.22899 -0.21252,0.89958 -0.0284,1.36166 1.17753,1.85975 0.65585,3.19253 1.11667,0.51287 -0.4379,2.54995 0.4584,2.75912 -0.46709,-0.10692 -0.70481,0.87074 -0.3325,1.21901 0.65675,1.18822 -0.35631,2.59721 0.49336,3.59223 0.1701,0.19469 0.32366,-0.23386 0.45247,-0.34791 0.90751,-0.55526 -0.97382,-0.65062 -0.32228,-1.03339 1.05641,-0.14684 0.66978,-2.07793 0.30667,-2.90072 -0.1278,0.58401 -0.87195,-0.365 -0.2916,-0.99799 0.7704,0.12479 -0.23691,-1.49304 0.37823,-1.11971 0.49922,-0.62397 -0.0865,-0.88636 -0.47023,-1.2518 -0.78012,-0.24 0.39106,-0.72068 -0.12964,-1.48835 0.24984,-0.74186 0.6296,-1.90821 -0.15119,-2.37151 0.10592,-0.41508 -0.0521,-0.5672 -0.25878,-0.56805 z m 1.05236,3.59827 c -0.0745,0.0468 -0.0538,0.51726 0.13983,0.86417 0.1982,0.18937 0.12229,-0.24571 0.0775,-0.36517 -0.0941,-0.39821 -0.17239,-0.52458 -0.21681,-0.499 z m 0.65476,1.56087 c -0.0264,0.005 -0.0484,0.015 -0.0667,0.0327 -0.16138,0.15286 -0.015,0.75465 0.38253,0.79942 0.3019,0.32074 0.22976,-0.59592 0.0327,-0.63453 -0.15403,-0.15771 -0.26966,-0.21053 -0.34864,-0.1977 z m -3.49173,0.28921 c -0.0476,-0.0172 -0.11945,0.0254 -0.18993,0.11043 h -5.4e-4 c -0.11277,0.13632 -0.22294,0.3826 -0.22919,0.67337 0.0586,0.30913 0.29916,0.0322 0.34164,-0.13031 0.16947,-0.43186 0.1572,-0.62497 0.078,-0.65352 z m 3.02689,0.71223 c -0.015,-7.5e-4 -0.0279,0.007 -0.0371,0.019 -0.0354,0.0528 -0.0117,0.20856 0.1415,0.51884 l 0.1146,0.1278 c 0.14585,-0.31772 -0.10424,-0.66014 -0.21896,-0.6656 z m -0.0371,0.019 c 0,0 0,-8.9e-4 0,-8.9e-4 l -0.002,0.002 c 5e-4,-7.5e-4 0.002,-1.6e-4 0.002,-8.8e-4 z m -0.52135,6.72 c -0.3266,0.0409 -0.95395,0.87087 -1.18526,1.33727 -0.16786,-0.13281 -0.29294,-0.12997 -0.38091,-0.0431 -0.26269,0.26077 -0.19142,1.27654 0.0678,1.63511 0.24643,-0.25664 0.56346,-0.67538 0.39223,0.23741 -0.75859,0.63588 -0.69093,1.82753 -0.36102,2.9059 -0.34879,0.52437 -0.0947,1.14594 0.44171,1.23281 0.99104,0.75169 0.10007,2.18367 0.0608,3.29439 0.68087,1.18413 -0.94373,1.30332 -0.72471,2.27914 -0.69212,0.6987 -0.66851,2.92111 0.20443,3.22274 0.75306,0.225 0.20039,0.34297 -0.21036,0.51971 0.26459,0.80376 0.93921,1.0819 1.25036,1.85267 0.31277,1.28598 0.55164,-0.0849 0.42449,-0.65009 -0.66183,-0.70621 0.80496,-1.24759 0.33626,-1.56863 -0.45715,0.66148 -1.18436,-0.24337 -0.46161,-0.78475 0.90308,-0.8666 -0.34499,-1.44013 0.10057,-2.29122 0.46346,-0.31165 0.41583,-1.35705 -0.10541,-1.27598 0.002,0.36914 -0.21848,1.21584 -0.4654,0.52404 0.49413,-0.71096 1.17556,-1.9191 0.56762,-3.05611 -0.85085,-1.57139 0.80183,-0.85373 0.53587,-2.24548 0.19424,-1.25981 -0.31804,-2.6187 -0.11511,-3.72086 0.8693,-1.12613 -0.65975,-1.20057 -0.25986,-2.37756 0.17124,-0.79304 0.0835,-1.05187 -0.11243,-1.02734 z m -1.83464,17.71081 c -0.0134,0.002 -0.0271,0.0117 -0.0393,0.0319 -0.0134,0.0231 -0.0247,0.06 -0.0356,0.11477 0.2771,0.20545 0.1713,-0.16054 0.0748,-0.14684 z m 0.98242,0.93411 c -0.0473,-0.005 -0.0936,0.0117 -0.13065,0.0466 v 8.8e-4 c -0.11527,0.10642 -0.14517,0.38416 0.14585,0.72864 0.0788,0.1577 0.25607,0.25348 0.22974,-0.0665 0.0485,-0.49012 -0.10308,-0.69576 -0.24481,-0.70964 z m -0.40028,1.03683 c -0.0246,0.005 -0.0473,0.0167 -0.0662,0.0354 l -0.002,8.9e-4 c -0.0687,0.068 -0.0867,0.22859 0.0388,0.50935 l 0.14467,0.10876 c 0.31715,-0.40726 0.0558,-0.69018 -0.1156,-0.65438 z", +1.67889, 12.4576, +"M 0.170368 -12.417 c -0.11243,0.0479 -0.25614,0.13683 -0.43964,0.27748 -1.27389,0.78909 -1.21189,2.51347 -0.18945,3.31231 -0.13431,0.55548 -0.36031,1.04129 -0.87302,1.22619 0.20361,1.23934 0.72541,2.15584 0.32094,3.54244 0.008,0.02 0.015,0.0396 0.024,0.0595 -0.27904,1.22039 -1.13252,2.77766 -0.40612,3.53991 0.14735,-0.35853 0.2824,-0.44551 0.41469,-0.40806 -0.0972,0.57648 -0.15854,1.15046 -0.0182,1.72729 -0.06,2.38124 0.71903,4.78601 0.0209,7.13418 0.14601,1.27941 0.088,2.90648 1.11768,4.46334 0.20931,-0.32402 -0.26141,-4.04795 -0.1288,-4.40228 -0.87044,-5.44038 0.51261,-4.61027 0.27264,-7.20329 -0.0762,-1.65323 0.16439,0.11009 -0.0256,-1.53491 0.0358,-0.0631 0.0717,-0.12629 0.10943,-0.208 0.33307,-0.84154 1.06509,-1.4845 1.30907,-2.19339 -0.67902,-0.22846 -0.0546,-1.46994 -1.00086,-1.45768 -0.0423,-0.98007 1.23341,-1.30442 0.84312,-2.52886 -0.10207,-0.60431 -0.005,-1.4265 -0.08,-2.10218 -0.0192,-0.64914 -0.14685,-1.29953 -0.44026,-1.94485 -0.24035,-0.076 -0.43253,-0.0872 -0.58683,-0.0473 -0.003,7.9e-4 -0.007,0.003 -0.01,0.005 0.1136,-0.70342 0.31863,-1.48809 -0.23437,-1.25593 z", +0.606945, 19.5532, +"M 0.535288 -19.101 c -0.12312,-0.64981 -0.32031,-0.73191 -0.52216,0.6492 0.13498,2.03239 -0.19035,3.48484 -0.30626,5.15433 -0.22468,2.50128 -0.19194,5.27546 -0.28382,8.06552 0.14367,2.92828 -0.0892,5.74081 -0.015,8.6394 0.14902,2.95697 -0.015,5.88803 0.0117,8.84688 -0.15971,3.34873 0.87967,3.73489 0.85929,7.01865 -0.015,-0.18654 0.22435,0.61848 0.19054,0.10792 0.3206,-2.15319 -0.0271,-5.6381 0.0215,-8.31354 -0.0332,-2.93964 0.13264,-5.81334 0.0481,-8.77509 0.005,-0.0175 0.005,0.002 0.01,-0.0134 l -10e-4,-1.53853 c -0.0167,-0.17135 -0.0117,-0.39165 -4.9e-4,-0.67826 l -0.007,-8.52476 c -0.0251,-0.17877 -0.0216,-0.38728 -0.0573,-0.55526 -0.008,-0.46963 0.0383,-0.97844 0.056,-1.46172 z", +2.75846, 24.0847, +"M -0.53697 -24.0496 c -0.0684,0.29866 -0.0297,0.66596 0.13574,0.88282 0.0473,-0.31373 0.004,-0.65245 -0.12095,-0.91797 z m 0.36555,2.05274 c -0.1428,0.26785 -0.15703,0.69044 0.006,0.94726 -0.0394,0.35884 -0.44025,0.2613 -0.4462,0.64649 -0.13341,0.55376 -0.0618,1.26397 0.2782,1.6289 0.38647,-0.11637 0.44767,-0.80593 0.38665,-1.27862 -0.042,-0.65364 -0.0767,-1.31482 -0.20924,-1.94599 z m -0.0685,3.66015 c 0.0544,0.007 0.0464,-0.065 0,0 z m 0.13171,0.71485 c 0.0476,-0.0128 0.0369,-0.0718 0,0 z m 0.22847,2.58984 c -0.2894,0.77897 -0.28573,1.72489 -0.63166,2.4668 -0.47716,0.40261 -0.61905,1.44325 -0.27551,2.07422 0.26278,1.07486 -0.0427,2.34757 -0.66794,3.01562 -0.17172,0.2786 -0.0476,0.77973 0.20981,0.82791 0.38219,0.22562 0.82919,-0.30745 0.78616,-0.89087 0.15146,-1.09007 0.68275,-2.05871 0.59978,-3.21392 -0.003,-1.4276 0.18264,-2.88329 -0.0126,-4.29148 z m -0.97436,8.98632 c -0.0867,0.087 0.0488,0.007 0,0 z m -0.15187,0.90625 c -0.52835,0.40878 -0.4693,1.70374 0.0726,2.04297 0.51682,0.6066 0.26815,1.98415 -0.36821,2.19969 -0.32196,0.17741 -0.71983,0.44113 -0.75527,1.00981 -0.0704,0.4972 0.0592,1.03177 0.30905,1.38034 0.22493,0.75424 -0.1245,1.49918 -0.25804,2.21485 -0.161,0.74022 -0.28768,1.49458 -0.42066,2.24609 -0.42887,0.46517 -0.40727,1.40504 -0.13373,2.00508 0.29613,1.28961 0.23854,2.67245 0.42671,3.99298 0.18501,0.44913 0.6129,0.71487 0.60881,1.30273 -0.0974,1.02173 -0.7334,1.84226 -0.61687,2.92188 0.12358,1.36478 0.23492,2.73359 0.422,4.08398 -0.24493,1.20409 -0.0575,2.46873 0.1344,3.6582 0.13244,0.3425 0.51859,0.10392 0.49139,-0.2639 0.55319,-3.33295 0.74881,-6.77676 0.71199,-10.19928 -0.0341,-0.83387 -0.0795,-1.67038 -0.0382,-2.50557 0.0769,-0.26194 0.38773,-0.21698 0.42872,0.0606 0.15576,0.33179 0.55489,0.0325 0.49055,-0.3418 0.06,-0.507 0.13468,-1.1082 0.46904,-1.38867 0.49047,-0.0745 0.76751,0.85571 1.26869,0.67578 0.19449,-0.0457 0.51816,-0.0809 0.52146,-0.46093 -0.0813,-0.81436 -0.69657,-1.24081 -1.21561,-1.19272 -0.33451,-7.4e-4 -0.67174,-0.17488 -0.89675,-0.54267 -0.25083,-0.25457 -0.59572,0.13269 -0.82418,-0.2197 -0.16795,-0.3508 -0.22547,-0.80084 -0.2634,-1.22044 -0.006,-0.32789 -0.0804,-0.74575 0.14222,-0.96155 0.15244,-0.17908 0.31154,-0.47312 0.18536,-0.76146 -0.21856,-0.80287 -0.55515,-1.67299 -0.34299,-2.55633 0.20639,-1.08152 0.37362,-2.21388 0.29836,-3.33932 -0.28596,-1.22431 -0.25129,-2.59774 -0.71303,-3.73317 -0.026,-0.0821 -0.07,-0.13612 -0.1344,-0.10742 z m -0.89104,25.33205 c 0.0499,0.0937 0.0486,9.1e-4 0,0 z", +1.8822, 22.4677, +"M 1.25124 -21.5684 c -0.28418,-2.48971 -0.62962,0.79472 -0.69653,2.55163 -0.0134,0.33593 -0.0346,0.5327 -0.047,0.43714 -0.02,-0.15681 -0.0495,-0.15546 -0.3007,0.0153 -0.15327,0.10424 0.0424,3.35182 -0.0498,3.34843 -0.21601,-0.007 -0.41768,0.37741 -0.36668,0.70163 0.0286,0.18236 0.006,0.24818 -0.0802,0.2448 -0.11908,-0.004 -0.25364,0.43529 -0.18471,0.6037 0.71933,5.30949 -0.84428,1.36714 -0.18964,5.27515 l -0.17336,0.21594 c 0.0917,0.13776 0.14905,0.31886 0.14544,0.60895 -0.002,0.12917 0.013,0.27497 0.0381,0.42665 l -0.0218,0.006 c 0.0168,0.0338 0.0268,0.0634 0.039,0.094 0.0143,0.0729 0.0307,0.14633 0.05,0.22032 0.005,0.11878 -0.013,0.27501 -0.054,0.53201 -0.0541,0.33939 -0.13657,0.63375 -0.18319,0.65397 -0.11671,0.0506 -0.47174,-0.31269 -0.41853,-0.4284 0.0236,-0.0514 -0.008,-0.20294 -0.0696,-0.33617 -0.10666,-0.22943 -0.11316,-0.23096 -0.12398,-0.0315 -0.009,0.17127 -0.0213,0.16013 -0.0663,-0.059 -0.0305,-0.14804 -0.06,-0.19604 -0.0661,-0.10622 -0.005,0.0898 -0.0795,0.23039 -0.16355,0.31212 -0.18138,0.17617 -0.20093,0.37374 -0.046,0.46512 0.061,0.0363 0.11066,0.11279 0.10955,0.17048 -8.5e-4,0.0577 0.0954,0.32276 0.21449,0.58884 0.119,0.26609 0.21567,0.53536 0.21448,0.59889 -8.5e-4,0.0635 0.0919,0.18952 0.20682,0.27978 0.33391,0.262 0.4046,0.46417 0.37893,1.08499 -0.0255,0.61623 0.034,0.7011 0.50815,0.72217 0.35806,0.0162 0.65582,0.76507 0.53973,1.35777 l -0.0519,0.2636 -0.14759,-0.22163 c -0.0812,-0.122 -0.18117,-0.19419 -0.22184,-0.16043 -0.0407,0.034 -0.0928,-0.0143 -0.11598,-0.10711 -0.0668,-0.26845 -0.30372,-0.21195 -0.36208,0.0865 -0.0286,0.14608 -0.10177,0.26395 -0.16293,0.26142 -0.0612,-0.002 -0.11204,0.0439 -0.11323,0.10273 -8.4e-4,0.0588 -0.0557,0.10482 -0.1212,0.10228 -0.0995,-0.003 -0.11067,0.0715 -0.0685,0.45245 0.0278,0.2512 0.0474,0.70532 0.0445,1.00937 -0.005,0.46262 0.0255,0.59462 0.19024,0.8096 0.10822,0.14128 0.21652,0.38557 0.24057,0.54249 0.0239,0.15696 0.10666,0.38658 0.18349,0.51059 0.0826,0.13306 0.13642,0.3788 0.13286,0.59976 -0.005,0.29947 -0.0602,0.43199 -0.27492,0.66315 -0.29456,0.31713 -0.32923,0.45939 -0.16264,0.66709 0.0663,0.0827 0.10722,0.31839 0.10188,0.59277 -0.006,0.36907 0.035,0.51904 0.22,0.79079 0.17112,0.25109 0.20751,0.35709 0.18442,0.59584 l -0.67781,0.21289 c 0.0524,0.58516 -0.0123,0.94307 -0.20099,0.93593 -0.1353,-0.005 -0.20989,0.31179 -0.2378,1.00981 -0.0241,0.60164 -0.11859,0.82734 -0.43141,1.02948 -0.21966,0.14195 -0.22403,0.19455 -0.112,1.34903 0.0368,0.38004 0.68935,2.90966 0.7272,2.97271 0.0949,0.15747 0.0814,0.40225 -0.0366,0.66257 -0.11787,0.2598 -0.13449,0.64857 -0.0423,0.98759 0.0667,0.24519 0.0456,0.44952 -0.0548,0.532 -0.0228,0.0188 -0.0711,0.63594 0.0835,1.35624 0.0409,0.19057 0.50838,1.19206 0.55879,1.39985 0.35151,1.44898 0.46272,2.37383 0.46272,2.37383 0.79566,1.73874 0.72766,1.04386 0.63346,0.41525 2.3e-4,-0.0113 0.27534,-0.54652 0.19995,-0.70081 -0.15301,-0.31339 -0.17759,-0.66368 -0.083,-1.18261 0.0379,-0.20818 0.0431,-0.45443 0.016,-0.78147 -0.0498,-0.60249 -0.0427,-0.9744 0.0205,-1.07732 0.0273,-0.0442 0.0455,-0.20317 0.0407,-0.35337 -0.005,-0.15019 0.008,-0.40879 0.0283,-0.57478 0.0361,-0.29302 -0.0429,-0.6788 -0.13963,-0.68256 -0.0551,-0.002 -0.036,-0.53013 0.0208,-0.57728 0.0735,-0.061 0.0636,-0.34385 -0.0156,-0.44254 -0.0385,-0.048 -0.0692,-0.13755 -0.0682,-0.19891 8.5e-4,-0.0614 -0.0387,-0.22756 -0.0887,-0.36892 -0.0547,-0.15488 -0.0881,-0.38704 -0.0846,-0.58367 0.004,-0.17953 0.25499,-2.55145 0.21196,-2.61624 -0.10744,-0.16134 -0.0424,-0.84634 0.0767,-0.80785 0.0511,0.0165 0.0952,-0.062 0.097,-0.17486 0.005,-0.31876 -0.0724,-0.5529 -0.16081,-0.47955 -0.0451,0.0375 -0.0572,0.0165 -0.0276,-0.0476 0.006,-0.0155 0.0119,-0.0321 0.0145,-0.049 l 0.1838,-0.0577 c -0.0115,-0.0716 -0.0185,-0.14175 -0.0282,-0.21332 0.20698,0.0786 0.41395,-0.23158 0.42283,-0.71561 0.005,-0.26614 0.0327,-0.33495 0.1166,-0.28546 0.12218,0.0721 0.27032,-0.32611 0.27768,-0.7484 0.002,-0.0908 -0.0206,-0.17365 -0.0559,-0.23737 5.9e-4,-0.0146 0.002,-0.0265 0.004,-0.0424 0.005,-0.34543 -0.25055,-1.04474 -0.35226,-0.9604 -0.11645,0.0967 -0.30456,-0.0735 -0.301,-0.2719 0.002,-0.10386 -0.0615,-0.41419 -0.14115,-0.68982 -0.11849,-0.41032 -0.13308,-0.61892 -0.0811,-1.1497 0.0697,-0.71055 0.11872,-0.77415 0.58883,-0.76544 0.238,0.004 0.28272,-0.0309 0.28627,-0.22645 0.002,-0.12743 0.0471,-0.25037 0.0991,-0.27321 0.0739,-0.0324 0.0727,-0.0806 -0.005,-0.2212 -0.0565,-0.10309 -0.0965,-0.4463 -0.0923,-0.80434 0.005,-0.50518 0.0383,-0.66811 0.17397,-0.85156 0.2095,-0.28327 0.22253,-0.69385 0.0313,-0.98096 -0.13165,-0.19763 -0.12715,-0.26243 0.016,-0.22994 0.027,0.006 0.0267,-0.12053 -3e-4,-0.28152 -0.0271,-0.16095 -0.0753,-0.26956 -0.10744,-0.24131 -0.0321,0.0282 -0.10477,-0.11781 -0.16139,-0.32479 -0.08,-0.29191 -0.11861,-0.34197 -0.17307,-0.22339 -0.11294,0.2457 -0.17081,-0.12246 -0.0727,-0.46293 0.0682,-0.23598 0.0579,-0.30034 -0.0653,-0.39999 -0.10565,-0.0857 -0.14006,-0.21238 -0.12273,-0.45333 0.0132,-0.18386 -0.0139,-0.35393 -0.0604,-0.37813 -0.0466,-0.0241 -0.17138,-0.16327 -0.27646,-0.30993 -0.14602,-0.2042 -0.17876,-0.32905 -0.13838,-0.53551 0.0291,-0.14806 0.0832,-0.29471 0.12058,-0.32567 0.11733,-0.0974 0.0792,-0.33666 -0.10677,-0.66884 -0.0991,-0.17651 -0.15862,-0.34993 -0.13256,-0.38512 0.0261,-0.0352 0.0492,-0.35308 0.0528,-0.70643 0.004,-0.35346 0.0287,-0.6367 0.0573,-0.62993 0.14508,0.0352 0.31458,-0.0129 0.31636,-0.0896 4.8e-4,-0.0395 -0.042,-0.13954 -0.0951,-0.23868 l 0.11112,-0.0301 c -0.0111,-0.0958 -0.0399,-0.22407 -0.0386,-0.28983 0.002,-0.0834 0.0713,-0.1796 0.15527,-0.2142 0.0838,-0.0346 0.13399,-0.10798 0.11167,-0.16306 -0.0224,-0.055 -0.005,-0.18319 0.0394,-0.28502 0.0692,-0.15973 0.0802,-0.14567 0.0772,0.10142 -0.002,0.15765 0.0451,0.35827 0.10343,0.44589 0.0579,0.0877 0.0857,0.18709 0.0608,0.22076 -0.004,0.004 0.0112,0.0354 0.01,0.0433 l 0.1746,-0.0472 c -0.008,-0.0688 -0.0286,-0.0867 -0.0208,-0.19104 0.0154,-0.20696 6e-4,-0.4013 -0.0325,-0.43233 -0.0332,-0.0311 -0.041,-0.12276 -0.0174,-0.20371 0.0236,-0.0809 0.009,-0.24097 -0.031,-0.35584 -0.0524,-0.14895 -0.0466,-0.24767 0.0196,-0.34447 0.0735,-0.10616 0.0727,-0.11992 -0.002,-0.0634 -0.11355,0.0858 -0.20488,-0.23611 -0.26541,-0.93593 -0.0346,-0.40002 -0.0183,-0.50647 0.0887,-0.58665 0.10165,-0.076 0.1255,-0.20309 0.1071,-0.56917 -0.0173,-0.34244 0.009,-0.5044 0.0958,-0.59364 0.0992,-0.10173 0.1041,-0.161 0.0298,-0.34535 -0.0495,-0.12234 -0.0867,-0.38173 -0.0832,-0.57659 0.004,-0.19488 -0.0302,-0.40942 -0.0748,-0.47649 -0.0448,-0.0671 -0.0747,-0.45108 -0.0669,-0.85331 0.0111,-0.53051 -0.0185,-0.78692 -0.10588,-0.93418 -0.11429,-0.19274 -0.16109,-1.16523 -0.12426,-2.58004 0.005,-0.23051 -0.0111,-0.47175 -0.0377,-0.53638 -0.085,-0.20429 -0.0795,-0.43155 0.0115,-0.50709 0.0628,-0.0521 0.0982,-0.7782 0.12335,-2.54026 0.0111,-0.7367 0.0229,-1.05157 0.0353,-1.42947 z", +2.42744, 13.3932, +"M -1.21246 -13.3117 c -0.52065,0.12572 -0.51196,0.12241 -1.03612,0.24908 -0.001,0.0734 0.0127,0.13564 0.008,0.20774 l -0.0413,0.60203 0.49247,-0.0656 c 0.3575,-0.0477 0.5449,-0.0103 0.68368,0.13592 0.10525,0.11049 0.21523,0.17879 0.24443,0.15089 0.0553,-0.0525 0.18585,0.42322 0.50591,1.84847 0.40153,1.78589 0.46949,2.16266 0.39429,2.16266 -0.043,2.5e-4 0.005,0.0582 0.10801,0.12919 0.16623,0.1151 0.1658,0.14317 -0.006,0.25114 -0.1387,0.0873 -0.15256,0.14904 -0.0501,0.22015 0.21167,0.14601 0.22839,0.42645 0.0548,0.91828 -0.0852,0.24126 -0.19974,0.751 -0.25424,1.13224 -0.0545,0.38124 -0.13282,0.79864 -0.17312,0.9281 -0.0476,0.15154 -0.0232,0.20647 0.0687,0.15297 0.0797,-0.0464 0.13994,5.4e-4 0.13694,0.10697 -0.003,0.10433 -0.0625,0.22286 -0.13332,0.26406 -0.0707,0.0411 -0.13559,0.30272 -0.1416,0.58085 -0.009,0.34992 0.0322,0.47879 0.13488,0.41909 0.0929,-0.0543 0.11283,-0.0321 0.0532,0.0589 -0.22213,0.33938 -0.21073,0.73976 0.0279,0.96739 0.27232,0.25969 0.31048,0.5796 0.0935,0.78548 -0.1029,0.0973 -0.10442,0.20891 -0.007,0.40359 0.0743,0.14815 0.11655,0.465619 0.094,0.705379 -0.0314,0.33474 0.0303,0.49527 0.26613,0.69092 0.39591,0.32862 0.4506,0.97704 0.0971,1.15445 -0.19818,0.0995 -0.25884,0.08 -0.30024,-0.0971 -0.0413,-0.17754 -0.0559,-0.18235 -0.0718,-0.0238 -0.0147,0.14713 -0.11818,0.18202 -0.39791,0.13332 -0.33766,-0.0586 -0.37754,-0.0306 -0.38654,0.26458 -0.005,0.1817 -0.0655,0.33614 -0.1354,0.34314 -0.0697,0.007 -0.18114,0.0178 -0.24804,0.0248 -0.0668,0.007 -0.20301,0.11829 -0.30231,0.24701 -0.0994,0.12871 -0.25695,0.2064 -0.34985,0.1726 -0.19915,-0.0722 -0.63789,0.30833 -0.64389,0.55914 -0.008,0.28898 0.32739,0.49631 0.64751,0.40101 0.16115,-0.0479 0.37848,-0.0986 0.48317,-0.11265 0.6821,-0.0915 0.75775,-0.16898 0.69815,-0.71314 -0.0515,-0.47073 -0.0192,-0.55211 0.31006,-0.78135 0.25416,-0.17695 0.44432,-0.22349 0.61702,-0.15089 0.24881,0.10484 0.24866,0.10527 -0.004,0.12247 -0.1394,0.009 -0.29578,0.009 -0.34778,0 -0.0519,-0.01 -0.0957,0.043 -0.0977,0.11731 -0.002,0.0774 0.10491,0.10318 0.25115,0.061 0.26076,-0.0754 0.35205,0.12076 0.11937,0.25631 -0.071,0.0413 -0.0973,0.21478 -0.0594,0.38551 0.0649,0.2906 -0.0353,0.37589 -0.36948,0.31419 -0.0517,-0.01 -0.0962,0.0455 -0.0982,0.12247 -0.002,0.0766 0.0821,0.10935 0.18655,0.0724 0.10479,-0.0372 0.18115,-0.0268 0.17415,0.0227 -0.009,0.0495 -0.004,0.14704 0.0109,0.21704 0.0872,0.41425 -0.088,1.66625 -0.25579,1.82779 -0.17035,0.164 -0.21288,0.15606 -0.37621,-0.0729 -0.1012,-0.14177 -0.23055,-0.34474 -0.28835,-0.45062 -0.0858,-0.15729 -0.1361,-0.16357 -0.2744,-0.0336 -0.16719,0.15723 -0.063,0.30632 0.31419,0.4501 0.062,0.0236 -0.01,0.26437 -0.15968,0.53537 -0.14984,0.27102 -0.33181,0.72807 -0.40411,1.01544 -0.12606,0.50143 -0.11796,0.52568 0.1974,0.59738 0.23372,0.0532 0.38925,0.22256 0.53899,0.58757 0.27181,0.66258 0.33329,2.3657 0.093,2.57865 -0.14193,0.12572 -0.13896,0.17735 0.0181,0.29869 0.20771,0.16041 0.23365,1.24108 0.0444,1.85518 -0.10282,0.33391 -0.0903,0.34552 0.38603,0.35812 0.0498,0.001 0.0875,0.0324 0.14056,0.0393 l 2.02778,-1.91874 c 0.0391,-0.84014 0.0901,-1.31251 0.20567,-1.42214 0.1408,-0.13348 0.16273,-0.22373 0.0687,-0.28474 -0.0888,-0.0584 -0.11201,-0.52874 -0.0651,-1.34978 0.0634,-1.11341 0.0451,-1.28034 -0.15968,-1.43196 -0.12777,-0.0943 -0.22728,-0.30706 -0.22428,-0.47284 0.005,-0.16601 -0.0515,-0.3404 -0.12454,-0.3886 -0.0731,-0.048 -0.0993,-0.16882 -0.0579,-0.26872 0.0422,-0.10162 0.0192,-0.14879 -0.0517,-0.10749 -0.22711,0.13224 -0.12436,-0.27378 0.14314,-0.56637 0.2846,-0.31158 0.33629,-0.4973 0.13953,-0.50229 -0.0693,-0.002 -0.12444,-0.0905 -0.12144,-0.19689 0.003,-0.10651 -0.074,-0.22624 -0.17053,-0.26614 -0.27152,-0.11237 -0.32136,-0.54803 -0.078,-0.68161 0.1171,-0.0642 0.15641,-0.12105 0.0868,-0.12506 -0.0694,-0.004 -0.13414,-0.24406 -0.14314,-0.5333 -0.009,-0.28926 -0.11377,-0.63887 -0.23255,-0.77721 -0.18088,-0.21019 -0.21428,-0.54858 -0.20928,-2.06292 0.006,-1.693699 0.0211,-1.808719 0.23564,-1.769919 0.21803,0.0394 0.41737,-0.1166 0.42736,-0.33435 0.002,-0.055 -0.0668,-0.0927 -0.15399,-0.0837 -0.56087,0.0579 -0.60799,-0.005 -0.56689,-0.7519 0.0221,-0.39949 -0.0155,-0.87281 -0.0832,-1.05213 -0.14126,-0.3744 0.0208,-0.75214 0.31936,-0.74414 0.10486,0.003 0.15977,-0.048 0.12247,-0.11265 -0.0376,-0.0646 0.004,-0.13992 0.092,-0.16692 0.12652,-0.039 0.12829,-0.0886 0.008,-0.24236 -0.0831,-0.10642 -0.15413,-0.46452 -0.15813,-0.79582 -0.004,-0.33891 -0.0742,-0.62959 -0.1602,-0.66559 -0.0981,-0.0407 -0.14427,-0.3485 -0.13177,-0.85886 0.0114,-0.43746 -0.0148,-0.97902 -0.0579,-1.20355 -0.0579,-0.30105 -0.0202,-0.47 0.14418,-0.64233 0.17836,-0.18698 0.20786,-0.35499 0.14676,-0.8413 -0.0419,-0.33433 -0.0924,-0.83108 -0.11214,-1.10381 -0.0199,-0.27268 -0.0595,-0.52067 -0.0879,-0.55087 -0.0287,-0.0302 0.0105,-0.22077 0.0873,-0.42374 0.17376,-0.45944 -0.0535,-1.17751 -0.34055,-1.07591 -0.10107,0.0357 -0.20737,0.0633 -0.23667,0.0631 -0.0292,-7.8e-4 -0.0549,0.0807 -0.0579,0.18087 -0.003,0.10015 -0.0715,0.22122 -0.15296,0.26871 -0.0924,0.0533 -0.11257,0.0315 -0.0543,-0.0574 0.052,-0.0791 0.0375,-0.14476 -0.032,-0.14676 -0.0696,-0.002 -0.16379,0.0535 -0.20929,0.12299 -0.0455,0.0695 -0.14895,0.0835 -0.22945,0.0305 -0.0807,-0.0528 -0.34584,-0.10465 -0.58911,-0.11265 -0.2954,-0.011 -0.39714,-0.0935 -0.48317,-0.27751 z", + ) +specks=( +0.19582, 0.378634, +"M -0.161959 -0.371071 c -0.1979,0.116362 0.54642,1.511327 0.31137,0.17337 -0.16941,-0.158525 -0.26567,-0.200234 -0.31137,-0.17337 z", +0.0857523, 0.142767, +"M -0.0570877 -0.130051 c -0.079,0.08213 0.0173,0.518112 0.14284,0.08157 -0.0697,-0.09649 -0.11628,-0.108996 -0.14284,-0.08157 z", +0.25372, 0.210386, +"M 0.0480998 -0.205499 c -0.42327,0.07051 -0.4419,0.885499 0.20562,0.02193 -0.0763,-0.02736 -0.14491,-0.032 -0.20562,-0.02193 z", +0.140526, 0.148695, +"M -0.13122 -0.139672 c -0.0745,0.07221 0.32456,0.53906 0.26582,0.107512 -0.16476,-0.111376 -0.2411,-0.131561 -0.26582,-0.107512 z", +0.249924, 0.342306, +"M -0.114966 -0.341551 c -0.34386,0.03623 0.04,1.35907 0.36489,0.226387 -0.16717,-0.174662 -0.28557,-0.234744 -0.36489,-0.226387 z", +0.825503, 0.732431, +"M -0.326263 0.732431 c 0.0466,-0.194767 0.0978,-0.389834 0.33522,-0.575911 0.67157,-0.184934 1.35761,-1.225527 0.16941,-0.77828 -0.39118,0.182831 -0.72402,0.18703 -1.00387,0.107874 z", +0.16647, 0.33039, +"M -0.07457 -0.329965 c -0.15388,0.01622 -0.13629,0.783005 0.22124,0.643371 l 0.0198,-0.08888 -0.0371,-0.25956 c -0.0823,-0.222794 -0.15267,-0.300475 -0.20355,-0.295097 z", +0.262126, 0.290338, +"M -0.233294 -0.271662 c -0.17079,0.144103 0.47197,1.053092 0.49542,0.204111 -0.29067,-0.215468 -0.43843,-0.252153 -0.49542,-0.204111 z", +0.240004, 0.127086, +"M -0.124553 -0.0975163 c -0.46137,0.111203 0.63127,0.460222 0.30142,-0.02957 -0.13801,0.0028 -0.23555,0.01328 -0.30142,0.02957 z", +0.221255, 0.286652, +"M -0.173286 -0.268838 c -0.24785,0.147346 0.55483,1.130889 0.36527,0.06706 -0.19413,-0.09043 -0.30799,-0.101042 -0.36527,-0.06706 z", +0.187681, 0.221884, +"M -0.00844687 -0.221884 c -0.63303,0.150003 0.66682,0.918773 0,0 z", +0.186594, 0.274126, +"M -0.108183 -0.271572 c -0.33666,0.06033 0.53913,1.16614 0.22586,0.04727 -0.10437,-0.04356 -0.17776,-0.05583 -0.22586,-0.04727 z", +0.143206, 0.14809, +"M -0.134411 -0.138893 c -0.0733,0.07232 0.33765,0.536966 0.27008,0.106063 -0.16769,-0.110755 -0.24568,-0.130215 -0.27008,-0.106063 z", +0.205727, 0.193789, +"M -0.128883 -0.184279 c -0.27335,0.08926 0.26505,0.768387 0.33461,0.05638 -0.16492,-0.06656 -0.27156,-0.07703 -0.33461,-0.05638 z", +0.305162, 0.456411, +"M 0.128243 -0.44135 c -0.29988,0.132509 -0.79724,1.080982 -0.0121,0.866257 l 0.0851,-0.147363 0.073,-0.208094 c 0.0833,-0.462398 -0.0138,-0.57096 -0.1475,-0.510616 z", +0.218898, 0.391658, +"M -0.131822 -0.379923 c -0.19943,0.127506 -0.0454,1.240958 0.35072,0.543718 l -0.0293,-0.2389 c -0.14923,-0.280285 -0.25533,-0.347357 -0.32181,-0.304858 z", +0.314969, 0.187616, +"M -0.110991 -0.158343 c -0.32093,0.126299 -0.30492,0.600436 0.35146,0.16703 l 0.0607,-0.06813 0.0138,-0.06262 c -0.17113,-0.08176 -0.31579,-0.07863 -0.42277,-0.03643 z", +0.144384, 0.265972, +"M -0.0991 -0.265684 c -0.18575,-0.02027 0.26116,1.038075 0.24294,0.222501 -0.1237,-0.15592 -0.19996,-0.217867 -0.24294,-0.222501 z", +0.249929, 0.219643, +"M -0.0945313 -0.210573 c -0.25801,0.08907 -0.22795,0.792505 0.34446,0.186141 -0.1406,-0.177396 -0.25858,-0.215823 -0.34446,-0.186141 z", +0.311515, 0.537401, +"M -0.140345 -0.534025 c -0.2896,0.082 -0.25686,1.549308 0.45186,0.911044 l -0.009,-0.160716 -0.0654,-0.241334 c -0.1551,-0.409456 -0.28705,-0.536186 -0.38358,-0.508808 z", +0.177607, 0.337109, +"M -0.0901732 -0.335988 c -0.24366,0.04365 0.0797,1.339997 0.26778,0.215464 -0.12508,-0.168462 -0.21151,-0.225565 -0.26778,-0.215464 z", +0.174549, 0.307061, +"M -0.0785809 -0.300444 c -0.14612,0.07522 -0.16717,0.806477 0.23933,0.555164 l 0.0138,-0.09759 v 0 c -0.0894,-0.391069 -0.18135,-0.492186 -0.24739,-0.457993 z", +0.103904, 0.181685, +"M -0.0611958 -0.180411 c -0.10023,0.0313 -0.0155,0.631126 0.1651,0.216629 -0.0781,-0.174417 -0.13129,-0.227114 -0.1651,-0.216629 z", +0.300084, 0.415141, +"M -0.145146 -0.407237 c -0.287,0.106735 -0.19552,1.250324 0.44523,0.648168 l -0.0387,-0.306045 c -0.17379,-0.297695 -0.31118,-0.377743 -0.40684,-0.342148 z", +0.871496, 0.707663, +"M 0.738024 -0.703243 c 0.1632,-0.03202 0.20538,0.105011 -0.038,0.573046 -0.007,0.328165 0.23952,1.188452 -0.39899,0.681635 -0.51284,-0.241795 -1.94836,0.149951 -0.63082,-0.4331 0.18654,-0.245067 0.7955,-0.768223 1.06753,-0.82157 z", +0.197296, 0.279834, +"M -0.119824 -0.279832 c -0.264,-0.0013 0.22383,1.101454 0.31712,0.214591 -0.15509,-0.155747 -0.25613,-0.214387 -0.31712,-0.214591 z", +0.362209, 0.376951, +"M -0.0190514 -0.364089 c 0.31129,-0.08445 0.64101,0.259813 0.068,0.656187 -0.0781,-0.02833 -0.31369,0.170722 -0.40954,0.03985 -0.0204,-0.440504 0.15544,-0.645356 0.34191,-0.696058 z", +0.322117, 0.43818, +"M 0.123244 -0.437076 c 0.21552,-0.01825 0.34427,0.190347 -0.0901,0.577559 0.0262,0.147674 -0.23676,0.452306 -0.33939,0.202753 -0.0887,-0.518231 0.21366,-0.762308 0.42909,-0.780276 z", +0.245771, 0.389516, +"M -0.127069 -0.385828 c -0.24435,0.07803 -0.10731,1.36138 0.37284,0.449505 -0.16786,-0.367879 -0.29138,-0.475521 -0.37284,-0.449505 z", +0.230177, 0.205962, +"M 0.0753834 -0.190211 c 0.31684,-0.138599 0.11369,0.694489 -0.30556,0.278851 0.13249,-0.162699 0.23246,-0.246844 0.30556,-0.278851 z", +0.195686, 0.378332, +"M -0.161823 -0.370693 c -0.19787,0.116276 0.54614,1.510428 0.31108,0.172533 -0.16941,-0.158542 -0.26538,-0.199394 -0.31108,-0.172533 z", +0.156073, 0.178711, +"M -0.123092 -0.173272 c 0.12455,-0.06557 0.54867,0.486539 0.0207,0.320803 -0.073,-0.208356 -0.063,-0.298951 -0.0207,-0.320803 z", +0.292868, 0.408748, +"M -0.0994831 -0.377205 c 0.2675,-0.127455 0.66049,0.135735 0.12818,0.70988 -0.0423,0.149106 -0.21965,0.04812 -0.24627,-0.04082 -0.15751,-0.374986 -0.0435,-0.592568 0.11835,-0.669165 z", +0.23406, 0.207114, +"M 0.15688 -0.205786 c 0.21509,-0.03505 -0.053,0.63824 -0.39094,0.33352 0.19441,-0.231554 0.31926,-0.321849 0.39094,-0.33352 z", +0.201117, 0.166598, +"M -0.0170272 -0.150178 c 0.25106,-0.12761 0.39144,0.539989 -0.18409,0.23713 0.0628,-0.135856 0.1261,-0.207647 0.18409,-0.23713 z", +0.114132, 0.18984, +"M -0.0125222 -0.189323 c 0.12162,-0.02091 0.24963,0.600837 -0.10161,0.293838 0.0204,-0.208237 0.0609,-0.286747 0.10161,-0.293838 z", +0.0915151, 0.173045, +"M -0.00111513 -0.171143 c 0.1168,-0.04285 0.15872,0.6575 -0.0904,0.172206 0.0312,-0.113136 0.0631,-0.162096 0.0904,-0.172206 z", +0.197077, 0.0630351, +"M -0.0264672 -0.0279184 c 0.34231,-0.128835 0.29613,0.142843 -0.17061,0.08191 0.0647,-0.03707 0.12128,-0.06352 0.17061,-0.08191 z", +0.32193, 0.326561, +"M -0.0297401 -0.311587 c 0.33824,-0.13351 0.67663,0.670587 -0.23729,0.637132 l -0.0549,-0.125695 c 0.0671,-0.318517 0.17898,-0.466864 0.29172,-0.511371 z", +0.15739, 0.161874, +"M -0.112614 -0.152979 c 0.14163,-0.07868 0.53585,0.392922 -0.0121,0.303528 -0.0537,-0.189612 -0.0352,-0.27729 0.0121,-0.303528 z", +0.492892, 0.413638, +"M -0.474932 -0.402985 c 0.083,-0.07235 0.43945,0.238304 0.76375,0.494301 0.64017,0.214078 -0.41841,0.52196 -0.55019,0.144016 -0.21378,-0.413279 -0.26311,-0.594893 -0.21413,-0.638157 z", +0.280378, 0.178761, +"M -0.23433 -0.147759 c 0.20564,-0.136598 1.00237,0.215878 0.0761,0.32652 -0.14871,-0.18142 -0.14543,-0.28092 -0.0761,-0.32652 z", +0.162268, 0.210341, +"M -0.102042 -0.210249 c -0.15268,-0.0093 0.003,0.684278 0.26431,0.309297 -0.12766,-0.225447 -0.21324,-0.306126 -0.26431,-0.309297 z", +0.173218, 0.312533, +"M 0.0960123 -0.312183 c 0.1701,0.02182 0.0498,1.05689 -0.26923,0.415217 0.12369,-0.317554 0.21268,-0.422492 0.26923,-0.415217 z", +0.225385, 0.163164, +"M -0.170322 -0.147418 c 0.19286,-0.101284 0.78196,0.319518 0.005,0.310437 -0.0894,-0.185115 -0.0687,-0.276769 -0.005,-0.310437 z", +0.256583, 0.29513, +"M 0.153207 -0.27621 c -0.24739,0.13332 -0.78467,0.91045 0.003,0.399077 0.15923,-0.386903 0.10662,-0.459705 -0.003,-0.399077 z", +0.142144, 0.160053, +"M -0.0769161 -0.159666 c -0.19378,0.01932 0.0939,0.633237 0.21906,0.107305 -0.10454,-0.08281 -0.17446,-0.111446 -0.21906,-0.107305 z", +0.257763, 0.339205, +"M -0.152337 -0.339123 c -0.34676,0.01225 0.26021,1.339727 0.4101,0.24746 -0.19896,-0.18325 -0.33009,-0.250231 -0.4101,-0.24746 z", +0.358938, 0.665171, +"M -0.0631218 -0.64564 c 0.1073,-0.03088 0.24635,-0.02708 0.42206,0.02536 -0.16562,0.294692 0.0819,1.345849 -0.37241,1.282725 -0.38085,-0.375619 -0.51502,-1.172797 -0.0474,-1.308222 z", +0.514964, 0.316052, +"M 0.0658635 -0.289668 c -0.47326,0.143016 -1.01805,0.807806 -0.02,0.544771 0.16837,-0.03778 0.41057,-0.08108 0.4691,-0.279942 -0.034,-0.28679 -0.23428,-0.329746 -0.44939,-0.264863 z", +0.28151, 0.425671, +"M -0.238974 -0.406955 c 0.18858,-0.163182 0.91161,0.793301 0.2413,0.832626 l -0.18057,-0.220986 c -0.12698,-0.378745 -0.12387,-0.557216 -0.0604,-0.611607 z", +0.146439, 0.286498, +"M -0.0593209 -0.282103 c -0.20198,0.07761 -0.019,1.143862 0.20576,0.141757 -0.0918,-0.124884 -0.15889,-0.159664 -0.20576,-0.141757 z", +0.224774, 0.345217, +"M -0.143886 -0.34214 c -0.21102,0.06745 0.0186,1.204903 0.36866,0.40122 -0.1801,-0.327159 -0.29833,-0.423613 -0.36866,-0.40122 z", +0.364393, 0.448279, +"M 0.118202 -0.416096 c -0.35164,0.168272 -0.86793,0.937323 -0.0295,0.85876 l 0.1563,-0.199134 c 0.2359,-0.645352 0.0842,-0.760655 -0.1268,-0.659676 z", +0.178445, 0.406469, +"M 0.0463255 -0.4059 c 0.18761,0.03174 0.22558,1.377763 -0.22477,0.5358 0.0833,-0.411175 0.16234,-0.546375 0.22477,-0.5358 z", +0.304022, 0.447803, +"M -0.00200764 -0.442434 c -0.3188,0.09523 -0.5662,1.415475 0.23893,0.655491 l 0.0671,-0.219199 c -0.0863,-0.363197 -0.19964,-0.467949 -0.30603,-0.436344 z", +0.738368, 0.337605, +"M -0.320121 -0.185236 c 0.66788,-0.249967 1.7692,-0.202284 0.41521,0.216789 -0.27722,0.04994 -0.4964,0.346511 -0.78619,0.3014 -0.14647,-0.229779 0.0671,-0.404455 0.37101,-0.518134 z", +0.375081, 0.882719, +"M -0.0815792 -0.881282 c -0.0944,0.0069 -0.19344,0.08954 -0.2912,0.259464 0.43267,0.359195 -0.52183,2.120841 0.4626,1.279309 0.52762,-0.392181 0.23605,-1.588716 -0.17148,-1.538687 z", +0.352805, 1.09079, +"M -0.163519 -1.08216 c 0.0236,-0.0085 0.05,-0.01121 0.0787,-0.0059 0.20435,0.405278 0.95305,2.696139 -0.15267,2.071683 -0.0376,-0.500541 -0.27879,-1.943774 0.0742,-2.06522 z", +0.41009, 1.14354, +"M 0.143813 -1.1422 c 0.118,-0.0138 0.21959,0.07711 0.26221,0.355831 0.0248,0.57158 -0.0509,3.125281 -0.59151,1.256692 -0.51863,-0.436258 -0.024,-1.551867 0.32926,-1.612506 z", +0.140552, 0.154723, +"M 0.0177994 -0.154723 c -0.5212,0.106098 0.44996,0.639827 0,0 z", +0.533274, 0.437204, +"M -0.502236 -0.433749 c -0.0649,0.02284 -0.0361,0.171895 0.16389,0.539065 0.1023,0.205429 0.86901,0.563972 0.87162,0.118795 -0.2874,-0.156058 -0.89227,-0.709351 -1.03553,-0.657957 z", +0.200361, 0.314278, +"M -0.124469 -0.30535 c -0.17097,0.09682 -0.049,0.951731 0.32483,0.477136 l -0.0547,-0.244774 c -0.12404,-0.21357 -0.21339,-0.264707 -0.27044,-0.232426 z", +0.274543, 0.539917, +"M -0.0453373 -0.535301 c -0.54472,0.105752 0.0193,1.964059 0.27489,0.540906 0.031,-0.148363 0.0654,-0.312167 0.03,-0.464016 -0.12663,-0.07108 -0.22779,-0.09212 -0.30563,-0.07677 z", +0.171092, 0.292515, +"M -0.137189 -0.285982 c 0.12732,-0.0772 0.5456,0.554711 0.12559,0.578497 l -0.11369,-0.216331 c -0.0635,-0.232403 -0.0552,-0.336408 -0.0103,-0.362199 z", +0.270716, 0.41871, +"M -0.224043 -0.39102 c -0.27325,0.221011 0.75659,1.649373 0.43008,0.09126 -0.23446,-0.129041 -0.36699,-0.142153 -0.43008,-0.09126 z", +0.173802, 0.188374, +"M 0.0173279 -0.186489 c 0.18489,-0.03985 0.2935,0.568112 -0.19113,0.311443 0.0597,-0.212936 0.13008,-0.298228 0.19113,-0.311443 z", +0.23479, 0.730233, +"M -0.0770773 -0.699585 c -0.11437,0.07401 -0.20017,0.281408 -0.13542,0.641983 0.0405,0.983203 0.0543,1.109157 0.35222,0.01811 0.23794,-0.534592 -0.0224,-0.783153 -0.21742,-0.659545 z", +0.439088, 0.707771, +"M 0.246767 -0.701228 c -0.10299,0.02191 -0.25293,0.102474 -0.45902,0.264588 -0.16872,0.17726 -0.43644,1.694364 0.0511,0.931154 0.43805,-0.288567 0.85607,-1.292506 0.40786,-1.195742 z", +0.139899, 0.344117, +"M -0.0663814 -0.336297 c -0.14129,0.105407 -0.0823,1.226019 0.20628,0.344756 -0.0904,-0.302541 -0.15923,-0.379811 -0.20628,-0.344756 z", +0.102613, 0.185851, +"M 0.0541974 -0.185523 c 0.10196,0.01725 0.0397,0.631684 -0.15681,0.242402 0.0711,-0.187404 0.12283,-0.247802 0.15681,-0.242402 z", +0.302008, 0.560567, +"M -0.0270707 -0.55462 c -0.18178,0.03761 -0.35011,0.264001 -0.23973,0.713802 0.0228,0.671208 0.15302,0.377879 0.44061,0.0069 0.28805,-0.504213 0.0331,-0.769335 -0.20105,-0.721031 z", +0.085711, 0.142485, +"M -0.056959 -0.129834 c -0.0792,0.08246 0.0173,0.517289 0.14267,0.08091 -0.0697,-0.09661 -0.11541,-0.107822 -0.14267,-0.08091 z", +0.180055, 0.427331, +"M -0.0363549 -0.425781 c 0.19187,0.05348 0.43026,1.467351 -0.1437,0.536886 0.0224,-0.422025 0.08,-0.554673 0.1437,-0.536886 z", +0.253994, 0.158651, +"M -0.157396 -0.151199 c -0.33829,0.07177 0.31285,0.629548 0.41139,0.04756 -0.20239,-0.05529 -0.33338,-0.06404 -0.41139,-0.04756 z", +0.142239, 0.160356, +"M -0.077041 -0.160032 c -0.19381,0.01932 0.0942,0.634082 0.21928,0.108167 -0.10472,-0.08281 -0.17481,-0.111962 -0.21928,-0.108167 z", +0.204532, 0.23177, +"M -0.125112 -0.231668 c 0.18825,-0.0086 0.62843,0.52902 0.0155,0.456753 -0.14112,-0.336734 -0.10644,-0.453147 -0.0155,-0.456753 z", +0.302086, 0.355289, +"M -0.150514 -0.321921 c -0.41485,0.206156 0.12059,1.269337 0.4281,0.224788 l 0.0245,-0.194374 c -0.21141,-0.07953 -0.35705,-0.07849 -0.45276,-0.03088 z", +0.319431, 0.249425, +"M -0.132339 -0.243618 c -0.4405,0.08143 -0.0266,0.995486 0.45177,0.108513 -0.20224,-0.10282 -0.34995,-0.127317 -0.45177,-0.108513 z", +0.318818, 0.231988, +"M 0.0318226 -0.193927 c -0.30533,0.13422 -0.649,0.55842 0.0989,0.38482 l 0.16407,-0.11973 c 0.0881,-0.31984 -0.0811,-0.34462 -0.26387,-0.2645 z", +0.196202, 0.386572, +"M -0.0913577 -0.381538 c -0.40284,0.05141 0.50388,1.52278 0.23778,0.253201 l -0.14026,-0.243385 c -0.0383,-0.01208 -0.0716,-0.01725 -0.0973,-0.0138 z", +0.252923, 0.25611, +"M -0.0991266 -0.255205 c -0.34893,0.0343 -0.0492,1.01793 0.35205,0.16303 -0.15613,-0.12749 -0.27152,-0.17097 -0.35205,-0.16303 z", +0.227743, 0.364507, +"M -0.129097 -0.362268 c -0.18019,0.05106 -0.14232,0.970885 0.35684,0.664393 -0.14854,-0.531815 -0.27503,-0.687804 -0.35684,-0.664393 z", +0.164352, 0.175428, +"M -0.045238 -0.173643 c -0.22431,0.03864 -0.11921,0.700104 0.20959,0.09557 -0.0887,-0.08074 -0.15768,-0.104545 -0.20959,-0.09557 z", +0.39131, 0.330262, +"M -0.0448403 -0.29959 c -0.36646,0.172171 -0.65831,0.979631 0.30262,0.455235 l 0.13353,-0.110583 c -0.087,-0.369322 -0.26893,-0.422388 -0.43553,-0.344152 z", +0.08851, 0.144333, +"M -0.06158 -0.131595 c -0.0797,0.0825 0.0316,0.52359 0.15009,0.0835 -0.0751,-0.0988 -0.12318,-0.11093 -0.15009,-0.0835 z", +0.142269, 0.160385, +"M -0.0770807 -0.160034 c -0.19379,0.01932 0.0942,0.634151 0.21935,0.108167 -0.10471,-0.08281 -0.17483,-0.112135 -0.21935,-0.108167 z", +0.141781, 0.160158, +"M -0.076419 -0.159773 c -0.19379,0.01932 0.093,0.633582 0.2182,0.107477 -0.10472,-0.08281 -0.17386,-0.111617 -0.2182,-0.107477 z", +0.209206, 0.30405, +"M -0.116284 -0.296837 c -0.20484,0.0951 -0.0599,1.08425 0.32549,0.30178 -0.15043,-0.26622 -0.25717,-0.33337 -0.32549,-0.30178 z", +0.201742, 0.3747, +"M -0.146133 -0.374084 c -0.24908,0.0343 0.42422,1.48646 0.34064,0.25287 -0.17607,-0.19356 -0.28321,-0.26077 -0.34064,-0.25287 z", +0.322667, 0.259474, +"M -0.114613 -0.226479 c -0.33039,0.161993 -0.30744,0.843431 0.36278,0.242972 l 0.0745,-0.165098 c -0.17776,-0.127834 -0.3269,-0.132147 -0.4369,-0.07815 z", +0.182682, 0.131912, +"M -0.0706049 -0.115145 c -0.38616,0.0825 0.35908,0.51914 0.2403,-0.0121 -0.10644,-0.0121 -0.18509,0.002 -0.2403,0.0121 z", +0.226747, 0.401068, +"M -0.210404 -0.386184 c -0.12456,0.15492 0.50616,1.44357 0.43089,0.3531 -0.26357,-0.33026 -0.38924,-0.40472 -0.43089,-0.3531 z", +0.231976, 0.335615, +"M -0.105621 -0.325515 c 0.23153,-0.10299 0.64145,0.61459 -0.029,0.66113 l -0.0958,-0.22943 c -0.0121,-0.27202 0.048,-0.39727 0.1249,-0.4317 z", +0.335965, 0.335139, +"M -0.0942353 -0.30707 c -0.34582,0.173534 -0.39751,1.086591 0.3636,0.373859 l 0.0511,-0.10489 0.0155,-0.10903 c -0.16113,-0.19389 -0.30903,-0.218301 -0.42429,-0.160612 z", +0.0697059, 0.240406, +"M -0.0569386 -0.237373 c 0.0566,0.055 0.24727,0.84545 0.0121,0.26736 -0.0321,-0.22226 -0.0297,-0.28589 -0.0121,-0.26736 z", +0.242776, 0.518825, +"M -0.137028 -0.512424 c -0.43441,0.07384 0.62996,1.783124 0.32347,0.636705 -0.0242,-0.208434 -0.0183,-0.497208 -0.21632,-0.628062 -0.0433,-0.0138 -0.0788,-0.01725 -0.10696,-0.0138 z", +0.0911062, 0.261377, +"M -0.00830619 -0.25616 c 0.11369,-0.08798 0.1788,0.975612 -0.0828,0.280459 0.0274,-0.178605 0.0571,-0.260274 0.0828,-0.280459 z", +0.175081, 0.18501, +"M -0.0388005 -0.179991 c 0.20821,-0.07297 0.40631,0.681507 -0.13628,0.207658 0.0405,-0.129905 0.0885,-0.190855 0.13628,-0.207658 z", +0.118897, 0.176509, +"M -0.0742332 -0.173289 c -0.15768,0.0526 0.1494,0.70495 0.19313,0.0823 -0.0947,-0.0745 -0.15647,-0.0942 -0.19313,-0.0823 z", + ) + +def mt( s ) : + return s.isspace() or len(s) == 0 + +def addparms( p ) : + s = '' + for parm in p.split(',') : + if mt(parm) : + continue + s += parm + ' ' + return s + +if __name__ == '__main__': + ChipScratches().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz/chip_scratches/meta.json b/extensions/fablabchemnitz/chip_scratches/meta.json new file mode 100644 index 0000000..bf322c5 --- /dev/null +++ b/extensions/fablabchemnitz/chip_scratches/meta.json @@ -0,0 +1,21 @@ +[ + { + "name": "Chip Scratches", + "id": "fablabchemnitz.de.chip_scratches", + "path": "chip_scratches", + "dependent_extensions": null, + "original_name": "ChipScratches", + "original_id": "ca.sfu.AT.kurn.ChipScratches", + "license": "GNU GPL v2", + "license_url": "https://inkscape.org/~kurn/%E2%98%85chipscratches", + "comment": "ported to Inkscape v1 by Mario Voigt", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/chip_scratches", + "fork_url": "https://inkscape.org/~kurn/%E2%98%85chipscratches", + "documentation_url": "https://stadtfabrikanten.org/display/IFM/Chip+Scratches", + "inkscape_gallery_url": null, + "main_authors": [ + "inkscape.org/kurn", + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/ellipse_by_five_points/ellipse_by_five_points.inx b/extensions/fablabchemnitz/ellipse_by_five_points/ellipse_by_five_points.inx new file mode 100644 index 0000000..4fce39a --- /dev/null +++ b/extensions/fablabchemnitz/ellipse_by_five_points/ellipse_by_five_points.inx @@ -0,0 +1,16 @@ + + + Ellipse By Five Points (Replaced by LPE) + fablabchemnitz.de.ellipse_by_five_points + + path + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/ellipse_by_five_points/ellipse_by_five_points.py b/extensions/fablabchemnitz/ellipse_by_five_points/ellipse_by_five_points.py new file mode 100644 index 0000000..a7dfe77 --- /dev/null +++ b/extensions/fablabchemnitz/ellipse_by_five_points/ellipse_by_five_points.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python3 +# Copyright (c) 2012 Stuart Pernsteiner +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import sys +import inkex +from inkex.paths import Path +import gettext +_ = gettext.gettext +from copy import deepcopy +import math +from math import sqrt + +class EllipseByFivePoints(inkex.EffectExtension): + + def effect(self): + if len(self.svg.selected) == 0: + sys.exit(_("Error: You must select at least one path")) + + for pathId in self.svg.selected: + path = self.svg.selected[pathId] + pathdata = Path(path.get('d')).to_arrays() + if len(pathdata) < 5: + sys.exit(_("Error: The selected path has %d points, " + + "but 5 are needed.") % len(pathdata)) + + points = [] + for i in range(5): + # pathdata[i] is the i'th segment of the path + # pathdata[i][1] is the list of coordinates for the segment + # pathdata[i][1][-2] is the x-coordinate of the last x,y pair + # in the segment definition + segpoints = pathdata[i][1] + x = segpoints[-2] + y = segpoints[-1] + points.append((x,y)) + + conic = solve_conic(points) + [a,b,c,d,e,f] = conic + + if bareiss_determinant([[a,b/2,d/2],[b/2,c,e/2],[d/2,e/2,f]]) == 0 or a*c - b*b/4 <= 0: + sys.exit(_("Error: Could not find an ellipse that passes " + + "through the provided points")) + + center = ellipse_center(conic) + [ad1, ad2] = ellipse_axes(conic) + al1 = ellipse_axislen(conic, center, ad1) + al2 = ellipse_axislen(conic, center, ad2) + + # Create an object with the appropriate cx,cy and + # with the major axis in the x direction. Then add a transform to + # rotate it to the correct angle. + + if al1 > al2: + major_dir = ad1 + major_len = al1 + minor_len = al2 + else: + major_dir = ad2 + major_len = al2 + minor_len = al1 + + # add sodipodi magic to turn the path into an ellipse + def sodi(x): + return inkex.addNS(x, 'sodipodi') + path.set(sodi('cx'), str(center[0])) + path.set(sodi('cy'), str(center[1])) + path.set(sodi('rx'), str(major_len)) + path.set(sodi('ry'), str(minor_len)) + path.set(sodi('type'), 'arc') + + #inkex.utils.debug(str(center[0])) + #inkex.utils.debug(str(center[1])) + + angle = math.atan2(major_dir[1], major_dir[0]) + if angle > math.pi / 2: + angle -= math.pi + if angle < -math.pi / 2: + angle += math.pi + path.apply_transform() + path.set('transform', 'rotate(%f %f %f)' % (angle * 180 / math.pi, center[0], center[1])) + # NASTY BUGFIX: We do apply_transform and path.set twice because otherwise the ellipse will not be rendered correctly. Reason unknown! + path.apply_transform() + path.set('transform', 'rotate(%f %f %f)' % (angle * 180 / math.pi, center[0], center[1])) + +def solve_conic(pts): + # Find the equation of the conic section passing through the five given + # points. + # + # This technique is from + # http://math.fullerton.edu/mathews/n2003/conicfit/ConicFitMod/Links/ConicFitMod_lnk_9.html + # (retrieved 31 Jan 2012) + rowmajor_matrix = [] + for i in range(5): + (x,y) = pts[i] + row = [x*x, x*y, y*y, x, y, 1] + rowmajor_matrix.append(row) + + full_matrix = [] + for i in range(6): + col = [] + for j in range(5): + col.append(rowmajor_matrix[j][i]) + full_matrix.append(col); + + coeffs = [] + sign = 1 + for i in range(6): + mat = [] + for j in range(6): + if j == i: + continue + mat.append(full_matrix[j]) + coeffs.append(bareiss_determinant(mat) * sign) + sign = -sign + return coeffs + +def bareiss_determinant(mat_orig): + # Compute the determinant of the matrix using Bareiss's algorithm. It + # doesn't matter whether 'mat' is in row-major or column-major layout, + # because det(A) = det(A^T) + + # Algorithm from: + # Yap, Chee, "Linear Systems", Fundamental Problems of Algorithmic Algebra + # Lecture X, Section 2 + # http://cs.nyu.edu/~yap/book/alge/ftpSite/l10.ps.gz + + mat = deepcopy(mat_orig); + + size = len(mat) + last_akk = 1 + for k in range(size-1): + if last_akk == 0: + return 0 + for i in range(k+1, size): + for j in range(k+1, size): + mat[i][j] = (mat[i][j] * mat[k][k] - mat[i][k] * mat[k][j]) / last_akk + last_akk = mat[k][k] + return mat[size-1][size-1] + +def ellipse_center(conic): + # From + # http://en.wikipedia.org/wiki/Matrix_representation_of_conic_sections#Center + [a,b,c,d,e,f] = conic + x = (b*e - 2*c*d) / (4*a*c - b*b); + y = (d*b - 2*a*e) / (4*a*c - b*b); + return (x,y) + +def ellipse_axes(conic): + # Compute the axis directions of the ellipse. + # This technique is from + # http://en.wikipedia.org/wiki/Matrix_representation_of_conic_sections#Axes + [a,b,c,d,e,f] = conic + + # Compute the eigenvalues of + # / a b/2 \ + # \ b/2 c / + # This algorithm is from + # http://www.math.harvard.edu/archive/21b_fall_04/exhibits/2dmatrices/index.html + # (retrieved 31 Jan 2012) + ma = a + mb = b/2 + mc = b/2 + md = c + mdet = ma*md - mb*mc + mtrace = ma + md + + (l1,l2) = solve_quadratic(1, -mtrace, mdet); + + # Eigenvalues (\lambda_1, \lambda_2) + #l1 = mtrace / 2 + sqrt(mtrace*mtrace/4 - mdet) + #l2 = mtrace / 2 - sqrt(mtrace*mtrace/4 - mdet) + + if mb == 0: + return [(0,1), (1,0)] + else: + return [(mb, l1-ma), (mb, l2-ma)] + +def ellipse_axislen(conic, center, direction): + # Compute the axis length as a multiple of the magnitude of 'direction' + [a,b,c,d,e,f] = conic + (cx,cy) = center + (dx,dy) = direction + + dlen = sqrt(dx*dx + dy*dy) + dx /= dlen + dy /= dlen + + # Solve for t: + # a*x^2 + b*x*y + c*y^2 + d*x + e*y + f = 0 + # x = cx + t * dx + # y = cy + t * dy + # by substituting, we get qa*t^2 + qb*t + qc = 0, where: + qa = a*dx*dx + b*dx*dy + c*dy*dy + qb = a*2*cx*dx + b*(cx*dy + cy*dx) + c*2*cy*dy + d*dx + e*dy + qc = a*cx*cx + b*cx*cy + c*cy*cy + d*cx + e*cy + f + + (t1,t2) = solve_quadratic(qa,qb,qc) + + return max(t1,t2) + +def solve_quadratic(a,b,c): + disc = b*b - 4*a*c + disc_root = sqrt(b*b - 4*a*c) + x1 = (-b + disc_root) / (2*a) + x2 = (-b - disc_root) / (2*a) + return (x1,x2) + +if __name__ == '__main__': + EllipseByFivePoints().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz/ellipse_by_five_points/meta.json b/extensions/fablabchemnitz/ellipse_by_five_points/meta.json new file mode 100644 index 0000000..fdfe0ba --- /dev/null +++ b/extensions/fablabchemnitz/ellipse_by_five_points/meta.json @@ -0,0 +1,21 @@ +[ + { + "name": "Ellipse By Five Points (Replaced by LPE)", + "id": "fablabchemnitz.de.ellipse_by_five_points", + "path": "ellipse_by_five_points", + "dependent_extensions": null, + "original_name": "Ellipse by 5 Points", + "original_id": "org.pernsteiner.inkscape.ellipse_5pts", + "license": "BSD-2-Clause License", + "license_url": "http://www.pernsteiner.org/inkscape/ellipse_5pts/inkscape-ellipse_5pts-0.1.1.zip", + "comment": "bugfixed and ported to Inkscape v1 manually by Mario Voigt", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/ellipse_by_five_points", + "fork_url": "http://www.pernsteiner.org/inkscape/ellipse_5pts/", + "documentation_url": "https://stadtfabrikanten.org/pages/viewpage.action?pageId=55019659", + "inkscape_gallery_url": null, + "main_authors": [ + "pernsteiner.org/Stuart Pernsteiner", + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/fun_shapes/fun_shapes.inx b/extensions/fablabchemnitz/fun_shapes/fun_shapes.inx new file mode 100755 index 0000000..01b3464 --- /dev/null +++ b/extensions/fablabchemnitz/fun_shapes/fun_shapes.inx @@ -0,0 +1,16 @@ + + + Fun Shapes + fablabchemnitz.de.fun_shapes + + path + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/fun_shapes/fun_shapes.py b/extensions/fablabchemnitz/fun_shapes/fun_shapes.py new file mode 100644 index 0000000..5e1a9f6 --- /dev/null +++ b/extensions/fablabchemnitz/fun_shapes/fun_shapes.py @@ -0,0 +1,199 @@ +#!/usr/bin/env python3 +# coding=utf-8 +# +# Copyright (C) [2021] [Matt Cottam], [mpcottam@raincloud.co.uk] +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +""" +A simple Extension to test if a Gtk3 Gui will work on most Inkscape 1.1+ Systems. +Inkscape 1.1 is the minimum verion. +Draws a simple set of randomly coloured circles and outputs them to the canvas. +""" + +import inkex +from inkex.elements import Group, PathElement +from inkex import transforms, styles + +import random +import gi + +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk, GdkPixbuf, Gdk +from lxml import etree + +# Could not find simplestyle, found this instead in extensions repo +def formatStyle(a): + """Format an inline style attribute from a dictionary""" + return ";".join([att + ":" + str(val) for att, val in a.items()]) + + +def random_rgb(self): + random_red = random.randrange(0, 255) + random_green = random.randrange(0, 255) + random_blue = random.randrange(0, 255) + + return f'rgb({random_red}, {random_green}, {random_blue})' + + +# Generate a circle or circle path +def draw_svg_circle(self, r, cx, cy, parent, is_path): + style = {'stroke': 'black', + # 'stroke-opacity': (r/200), + 'stroke-width': '0.1', + # 'fill': 'none' + 'fill': random_rgb(self) + } + + attribs = { + 'style': formatStyle(style), + 'r': str(r), + 'cx': str(cx), + 'cy': str(cy) + } + + my_circle = etree.SubElement(Funshapes.output_group, inkex.addNS('circle', 'svg'), attribs) + + +def draw_svg_circle_series(self, r, cx, cy, parent, is_path): + + my_list = range(1, 100) + for item in reversed(my_list): + draw_svg_circle(self, item, cx, cy, parent, is_path) + + gtk3_add_svg_image(self, Funshapes.output_group) + + +def draw_svg_circle_series_scale(self, r, cx, cy, parent, is_path): + Funshapes.output_group.clear() + + upper_range = int(Funshapes.main_window.h_scale.get_value()) + + my_list = range(1, upper_range) + for item in reversed(my_list): + draw_svg_circle(self, item, cx, cy, parent, is_path) + + gtk3_add_svg_image(self, Funshapes.output_group) + + + +def group_wrapper(self, my_objects, to_layer): + group_id = 'g' + str(random.randrange(100000, 1000000)) + + new_group = self.svg.add(Group.new('#' + group_id)) + # inkex set, takes account of NS attribs etc + new_group.set('inkscape:groupmode', 'layer') + new_group.set('inkscape:label', 'My_Layer_' + group_id) + + # When plucking an object from an svg, will only have its own transforms + # Composed transforms must be applied instead. + + for my_object in my_objects: + my_object_transforms = my_object.composed_transform() + my_object.attrib['transform'] = '' + my_object.transform.add_matrix(my_object_transforms) + new_group.append(my_object) + + new_group.attrib['id'] = group_id + return new_group + + +def object_to_xml_tag(self): + my_tag = str(self.tostring().decode("utf-8")) + return my_tag + +########################## +# GTK3 GUI SECTION BELOW +########################## + + +def gtk3_gui(self): + + Funshapes.main_window = Gtk.Window() + Funshapes.main_window.root_grid = Gtk.Grid() + Funshapes.main_window.add(Funshapes.main_window.root_grid) + + root_grid = Funshapes.main_window.root_grid + main_window = Funshapes.main_window + + gtk3_scales(root_grid, Funshapes.main_window) + + main_window.connect("destroy", Gtk.main_quit) + main_window.show_all() + + draw_svg_circle_series(self, 200, 100, 100, Funshapes.self.svg, 'yes') + + Gtk.main() + + return main_window + + +def gtk3_scales(grid, inkex_self): + ad1 = Gtk.Adjustment(value=20, lower=0, upper=100, step_increment=5, page_increment=10, page_size=0) + + inkex_self.h_scale = Gtk.Scale( + orientation=Gtk.Orientation.HORIZONTAL, adjustment=ad1) + + inkex_self.h_scale.set_digits(0) + inkex_self.h_scale.set_valign(Gtk.Align.START) + + inkex_self.h_scale.connect("value-changed", draw_svg_circle_series_scale, 50, 100, 100, None, None) + + grid.attach(inkex_self.h_scale, 1, 0, 1, 1) + + +def gtk3_add_svg_image(self, svg_object): + + Funshapes.base_image = Gtk.Image() + Funshapes.base_image.set_from_file('white.png') + + random_number = random.randrange(10000, 1000000, 1) + + # convert svg object to svg xml + svg = object_to_xml_tag(svg_object) + + svg = f'{svg} ' + + loader = GdkPixbuf.PixbufLoader() + loader.write(svg.encode()) + loader.close() + pixbuf = loader.get_pixbuf() + + Funshapes.preview_image = Gtk.Image.new_from_pixbuf(pixbuf) + Funshapes.preview_image.show_all() + + if Funshapes.main_window.root_grid.get_child_at(1, 1) is None: + Funshapes.main_window.root_grid.attach(Funshapes.preview_image, 1, 1, 1, 1) + else: + Funshapes.main_window.root_grid.get_child_at(1, 1).destroy() + Funshapes.main_window.root_grid.attach(Funshapes.preview_image, 1, 1, 1, 1) + + +class Funshapes(inkex.EffectExtension): + + def effect(self): + Funshapes.self = self + output_group_id = f'Funshapes_{random.randrange(10000, 1000000, 1)}' + Funshapes.output_group = Group.new('#' + output_group_id) + # create new gtk3 window and attach to effect self + self.win = gtk3_gui(self) + + # When GTK is exited + Funshapes.self.svg.append(Funshapes.output_group) + + +if __name__ == '__main__': + Funshapes().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz/fun_shapes/meta.json b/extensions/fablabchemnitz/fun_shapes/meta.json new file mode 100644 index 0000000..4c89904 --- /dev/null +++ b/extensions/fablabchemnitz/fun_shapes/meta.json @@ -0,0 +1,21 @@ +[ + { + "name": "Fun Shapes", + "id": "fablabchemnitz.de.fun_shapes", + "path": "fun_shapes", + "dependent_extensions": null, + "original_name": "Fun Shapes", + "original_id": "org.inkscape.funshapes", + "license": "GNU GPL v3", + "license_url": "https://inkscape.org/~inklinea/%E2%98%85funshapes", + "comment": "", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/fun_shapes", + "fork_url": "https://inkscape.org/~inklinea/%E2%98%85funshapes", + "documentation_url": "https://stadtfabrikanten.org/display/IFM/Fun+Shapes", + "inkscape_gallery_url": null, + "main_authors": [ + "inkscape.org/inklinea", + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/hatches_and_grains/hatches_and_grains.inx b/extensions/fablabchemnitz/hatches_and_grains/hatches_and_grains.inx new file mode 100644 index 0000000..a3dc6af --- /dev/null +++ b/extensions/fablabchemnitz/hatches_and_grains/hatches_and_grains.inx @@ -0,0 +1,81 @@ + + + Hatches And Grains + fablabchemnitz.de.hatches_and_grains + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/hatches_and_grains/hatches_and_grains.py b/extensions/fablabchemnitz/hatches_and_grains/hatches_and_grains.py new file mode 100644 index 0000000..b4bad26 --- /dev/null +++ b/extensions/fablabchemnitz/hatches_and_grains/hatches_and_grains.py @@ -0,0 +1,144 @@ +#!/bin/env python3 +# +# Copyright (C) 2020 Marc Jeanmougin, Laurent Porcheret +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +# +# Thanks to Bénédicte Cuperly for reminding me to do this and for her feedback + + +""" Geography patterns """ + +import math +import inkex +from inkex import Pattern, PathElement, Circle, Rectangle, AbortExtension + +GRAIN_V="m 0 0 10 20 10 -20" +GRAIN_VI="m 0 20 10 -20 10 20" +GRAIN_PLUS="M 10 0 10 20 M 0 10 20 10" +GRAIN_X="M 0 0 20 20 M 0 20 20 0" + + +class Geography(inkex.EffectExtension): + + def add_arguments(self, pars): + pars.add_argument('--tab', default='grains_page', help='grains_page or hatches_page') + pars.add_argument('--type', default='h', help='h|d') + pars.add_argument('--angle', default='0', help='angle') + pars.add_argument('--thickness', default='1', help='width') + pars.add_argument('--spacing', default='8', help='spacing between hatches') + pars.add_argument('--type_grain', default='grain_v', help='Shape of patterns (v^+xoO)') + pars.add_argument('--size', default='1', help='size of grain') + pars.add_argument('--hcolor', default=inkex.Color(255), type=inkex.Color, help='color of hatches') + pars.add_argument('--gcolor', default=inkex.Color(255), type=inkex.Color, help='color of grains') + + def effect(self): + #step 0: find desired id + i=self.get_id() + #step 1: add stuff in defs if not present + if self.svg.getElementById(i) is None: + #construct it + newNode = self.svg.defs.add(Pattern()) + self.construct(newNode) + + #step 2: assign + for node in self.svg.selection.values(): + node.style['fill'] = "url(#"+i+")" + node.set('fill', "url(#"+i+")") + + def construct(self, node): + if(self.options.tab == "grains_page"): + self.construct_grain(node) + else: + self.construct_hatch(node) + node.set('patternUnits', "userSpaceOnUse") + node.set('id', self.get_id()) + + def get_id(self): + if(self.options.tab=="grains_page"): + return "inkgeo_"+self.options.type_grain+"_"+self.options.size+"_"+str(int(self.options.gcolor)) + else: + return "inkgeo_"+self.options.type+"_"+self.options.angle+"_"+self.options.thickness+"_"+self.options.spacing+"_"+str(int(self.options.hcolor)) + + + def construct_grain(self, node): + size=str(math.sqrt(float(self.options.size))) + node.set('width', "100") + node.set('height', "100") + n1=0 + n2=0 + node.style="stroke-width:4;" + if self.options.type_grain == "grain_c" or self.options.type_grain == "grain_r": + n1 = node.add(Circle()) + n2 = node.add(Circle()) + n1.set('cx',10) + n1.set('cy',10) + n1.set('r',10) + n2.set('cx',10) + n2.set('cy',10) + n2.set('r',10) + if self.options.type_grain == "grain_c": + node.style.set_color(self.options.gcolor, 'stroke') + node.set('fill', "none") + else: + node.style.set_color(self.options.gcolor, 'stroke') + node.style.set_color(self.options.gcolor, 'fill') + else: + node.style.set_color(self.options.gcolor, 'stroke') + node.set('fill', "none") + #paths + n1 = node.add(PathElement()) + n2 = node.add(PathElement()) + if self.options.type_grain == "grain_v": + n1.set('d', GRAIN_V) + n2.set('d', GRAIN_V) + elif self.options.type_grain == "grain_m": + n1.set('d', GRAIN_VI) + n2.set('d', GRAIN_VI) + elif self.options.type_grain == "grain_p": + n1.set('d', GRAIN_PLUS) + n2.set('d', GRAIN_PLUS) + elif self.options.type_grain == "grain_x": + n1.set('d', GRAIN_X) + n2.set('d', GRAIN_X) + n1.set('transform', "translate(5,5)scale("+size+")") + n2.set('transform', "translate(55,55)scale("+size+")") + node.set('patternTransform', "scale(0.1)") + + def construct_hatch(self,node): + h = int(self.options.spacing)+int(self.options.thickness) + node.set('width', str(h)) + node.set('patternTransform', "rotate("+self.options.angle+")") + r = node.add(Rectangle()) + r.set('x', "0") + r.set('y', "0") + r.set('height', self.options.thickness) + r.style.set_color(self.options.hcolor, 'fill') + if self.options.type=="h": + node.set('height',str(h)) + r.set('width', str(h)) + else: + node.set('height',str(2*h)) + r.set('width', str(h/2)) + r2 = node.add(Rectangle()) + r2.set('x', str(h/2)) + r2.set('y', str(h)) + r2.set('width', str(h/2)) + r2.set('height', self.options.thickness) + r2.style.set_color(self.options.hcolor, 'fill') + + +if __name__ == '__main__': + Geography().run() diff --git a/extensions/fablabchemnitz/hatches_and_grains/locale/fr/LC_MESSAGES/hatches_grains.mo b/extensions/fablabchemnitz/hatches_and_grains/locale/fr/LC_MESSAGES/hatches_grains.mo new file mode 100644 index 0000000000000000000000000000000000000000..46d34d30da6deca35fce0c4fef29613a9a294ffe GIT binary patch literal 2279 zcmcgsJ&zkj7+xR*SO_0MQ5qt>Ithu0tYbSuI`(u3aoio2ayct!PN_)dcE|SM-I--( z_H;)9qNG9;2uh?hT!}>&+iw{eHEa+ zjQ$Gx59n9WZ$5@Uw4ZnDANT?0zvA#cU>D9$ zu>K{G?S%N~CE#Ts$8{BWiO&J?3w9dZ2Xb6@fXu-Rcp3O9kmLFq$no9>;un06KR*8> zkp2A9;BP>z}O{`GbkvEj8@mN}^z2Za0Qel;`%HtR%!g_@ni=Qv_!6ywu8{k{Q!P)-g)! z2q~^ajg?Lq4m?cG5Sa2*80XXxtRnNI=H*zqQe<>2tP$5cai>sTQ)o}_Q+^02~-_}3+3l$I5W6)Fx;k8(hw=T@UYW+qtoqm`rUpv z*jhw&8tih7fa=WHdh8k?C%wlFwevW5ufF;gt81uBY_U|^X$~$e43?P(`&J?CiiJ2h zKmp?4SkHId)D{*Bk-&8vpj48Xmd?e&&>AkyXplySoTkxn`@!8hitx59U@6*j6O~5q zloJ%}+vuVdcDjp#`!CfFa_aBr};y>!&; zbi*yf1?r>GX@MhNp7`r13#B(GnFH1-DZD->fz>Vn%<(`)eQvX;Ev5?!W)ZJ+7P3W6glR1qFt$_t#^k;rl|gY z=SIkHcYY>u|E^Vmg)%s7IJ}Y4Rfs`;r% zrl@4Ml%D^`fo!EgI?vId7E##qZz&UvGKi8(y-IQMa2(+w@zPS&IO0J@g|vCK2T1?} zb%sklV1bYsD}%2AsaA#-`GKCwS1qa#iE7%21<0zm3!@VcOYYi3D4r@XF7W16OY@2@ ztj67t{b+?^MH`e1whXknO0=n>Rw5uOBA2f3VzZ?- r_?x-K`a^UB9!5gpvUq^k$RV`fU}@VyK4i|~8VB>w3!$9jEaKoV?d7eH literal 0 HcmV?d00001 diff --git a/extensions/fablabchemnitz/hatches_and_grains/locale/fr/hatches_grains.po b/extensions/fablabchemnitz/hatches_and_grains/locale/fr/hatches_grains.po new file mode 100644 index 0000000..62ff9b4 --- /dev/null +++ b/extensions/fablabchemnitz/hatches_and_grains/locale/fr/hatches_grains.po @@ -0,0 +1,128 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: hatches_grains\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-09-28 11:27+0200\n" +"PO-Revision-Date: 2020-09-28 11:32+0200\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"Last-Translator: \n" +"Language-Team: \n" +"X-Generator: Poedit 2.3\n" + +#: hatches_grains.inx:3 +msgid "Hatches and grains" +msgstr "Hachures et grains" + +#: hatches_grains.inx:11 +msgid "Hatches" +msgstr "Hachures" + +#: hatches_grains.inx:12 +msgid "" +"\n" +"Create standardized hatches to differentiate or prioritize cartographic " +"objects. \n" +" " +msgstr "" +"\n" +"Crée des hachures standardisées pour différencier ou prioriser des objets " +"cartographiques.\n" +" " + +#: hatches_grains.inx:16 +msgid "Hatches settings" +msgstr "Paramètres de hachures" + +#: hatches_grains.inx:18 +msgid "Sort of hatches:" +msgstr "Type de hachures :" + +#: hatches_grains.inx:23 +msgid "Orientation:" +msgstr "Orientation :" + +#: hatches_grains.inx:30 +msgid "Thickness:" +msgstr "Épaisseur :" + +#: hatches_grains.inx:37 +msgid "Spacing:" +msgstr "Espacement :" + +#: hatches_grains.inx:49 hatches_grains.inx:50 +msgid "Hatches color" +msgstr "Couleur de hachures" + +#: hatches_grains.inx:55 +msgid "Grains" +msgstr "Grains" + +#: hatches_grains.inx:57 +msgid "" +"\n" +"Create standardized grains to differentiate or prioritize cartographic " +"objects.\n" +" " +msgstr "" +"\n" +"Crée des grains standardisées pour différencier ou prioriser des objets " +"cartographiques.\n" +" " + +#: hatches_grains.inx:61 +msgid "Grains settings" +msgstr "Paramètres de grains" + +#: hatches_grains.inx:63 +msgid "Grains:" +msgstr "Grains :" + +#: hatches_grains.inx:72 +msgid "Size:" +msgstr "Taille :" + +#: hatches_grains.inx:79 hatches_grains.inx:80 +msgid "Grain color" +msgstr "Couleur de grains" + +#: hatches_grains.inx:86 +msgid "Information" +msgstr "Information" + +#: hatches_grains.inx:87 +msgid "" +"\n" +"This mapping module is intended for the community of geographers and " +"cartographers.\n" +"\n" +"It makes it possible to create visual variables like \"hatch\" or \"grain\" " +"on surface or point implantation, in order to differentiate or prioritize " +"the cartographic information.\n" +"\n" +"Laurent Porcheret \n" +"Géographe - cartographe / Geographer - cartographer\n" +"Sorbonne université - INSPE de Paris\n" +"V.15.01.2020" +msgstr "" +"\n" +"Ce module est destiné à la communauté des géographes et des cartographes.\n" +"Il permet de créer des variables visuelles telles que des hachures ou des " +"grains sur des surfaces ou des ponctuels, pour différencier ou hiérarchiser " +"des informations cartographiques.\n" +"\n" +"Laurent Porcheret \n" +"Géographe - cartographe / Geographer - cartographer\n" +"Sorbonne université - INSPE de Paris" + +#: hatches_grains.inx:102 +msgid "Cartography" +msgstr "Cartographie" diff --git a/extensions/fablabchemnitz/hatches_and_grains/locale/hatches_grains.pot b/extensions/fablabchemnitz/hatches_and_grains/locale/hatches_grains.pot new file mode 100644 index 0000000..59fabdc --- /dev/null +++ b/extensions/fablabchemnitz/hatches_and_grains/locale/hatches_grains.pot @@ -0,0 +1,110 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-09-28 11:33+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: hatches_grains.inx:3 +msgid "Hatches and grains" +msgstr "" + +#: hatches_grains.inx:11 +msgid "Hatches" +msgstr "" + +#: hatches_grains.inx:12 +msgid "" +"\n" +"Create standardized hatches to differentiate or prioritize cartographic " +"objects. \n" +" " +msgstr "" + +#: hatches_grains.inx:16 +msgid "Hatches settings" +msgstr "" + +#: hatches_grains.inx:18 +msgid "Sort of hatches:" +msgstr "" + +#: hatches_grains.inx:23 +msgid "Orientation:" +msgstr "" + +#: hatches_grains.inx:30 +msgid "Thickness:" +msgstr "" + +#: hatches_grains.inx:37 +msgid "Spacing:" +msgstr "" + +#: hatches_grains.inx:49 hatches_grains.inx:50 +msgid "Hatches color" +msgstr "" + +#: hatches_grains.inx:55 +msgid "Grains" +msgstr "" + +#: hatches_grains.inx:57 +msgid "" +"\n" +"Create standardized grains to differentiate or prioritize cartographic " +"objects.\n" +" " +msgstr "" + +#: hatches_grains.inx:61 +msgid "Grains settings" +msgstr "" + +#: hatches_grains.inx:63 +msgid "Grains:" +msgstr "" + +#: hatches_grains.inx:72 +msgid "Size:" +msgstr "" + +#: hatches_grains.inx:79 hatches_grains.inx:80 +msgid "Grain color" +msgstr "" + +#: hatches_grains.inx:86 +msgid "Information" +msgstr "" + +#: hatches_grains.inx:87 +msgid "" +"\n" +"This mapping module is intended for the community of geographers and " +"cartographers.\n" +"\n" +"It makes it possible to create visual variables like \"hatch\" or \"grain\" " +"on surface or point implantation, in order to differentiate or prioritize " +"the cartographic information.\n" +"\n" +"Laurent Porcheret \n" +"Géographe - cartographe / Geographer - cartographer\n" +"Sorbonne université - INSPE de Paris\n" +"V.15.01.2020" +msgstr "" + +#: hatches_grains.inx:102 +msgid "Cartography" +msgstr "" diff --git a/extensions/fablabchemnitz/hatches_and_grains/meta.json b/extensions/fablabchemnitz/hatches_and_grains/meta.json new file mode 100644 index 0000000..6e8fc75 --- /dev/null +++ b/extensions/fablabchemnitz/hatches_and_grains/meta.json @@ -0,0 +1,21 @@ +[ + { + "name": "Hatches And Grains", + "id": "fablabchemnitz.de.hatches_and_grains", + "path": "hatches_and_grains", + "dependent_extensions": null, + "original_name": "Hatches and grains", + "original_id": "carto", + "license": "GNU GPL v3", + "license_url": "https://gitlab.com/marcjeanmougin/inkscape-carto-ext/-/blob/master/LICENSE", + "comment": "", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/hatches_and_grains", + "fork_url": "https://gitlab.com/marcjeanmougin/inkscape-carto-ext", + "documentation_url": "https://stadtfabrikanten.org/display/IFM/Hatches+And+Grains", + "inkscape_gallery_url": null, + "main_authors": [ + "gitlab.com/marcjeanmougin", + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/ids_to_text/ids_to_text.inx b/extensions/fablabchemnitz/ids_to_text/ids_to_text.inx new file mode 100644 index 0000000..c4df6be --- /dev/null +++ b/extensions/fablabchemnitz/ids_to_text/ids_to_text.inx @@ -0,0 +1,50 @@ + + + Ids To Text + fablabchemnitz.de.ids_to_text + + + + + + + + + 10 + 255 + Roboto + + + + + + + + + + + + + + + + + 0 + false + false + + + + + all + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/ids_to_text/ids_to_text.py b/extensions/fablabchemnitz/ids_to_text/ids_to_text.py new file mode 100644 index 0000000..2069727 --- /dev/null +++ b/extensions/fablabchemnitz/ids_to_text/ids_to_text.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 + +import re +import inkex +from inkex import TextElement, TextPath, Tspan +from inkex.bezier import csparea, cspcofm, csplength +from inkex.colors import Color + +class IdsToText(inkex.EffectExtension): + + def add_arguments(self, pars): + pars.add_argument('--fontsize', type = int, default = '10', help = 'Font Size') + pars.add_argument('--color', type=Color, default = 255, help = 'Color') + pars.add_argument('--font', default = 'Roboto', help = 'Font Family') + pars.add_argument('--fontweight', default = 'bold', help = 'Font Weight') + pars.add_argument('--replaced', default = '', help = 'Text to replace') + pars.add_argument('--replacewith', default = '', help = 'Replace with this text') + pars.add_argument('--angle', type = float, dest = 'angle', default = 0, help = 'Rotation angle') + pars.add_argument('--capitals', type = inkex.Boolean, default = False, help = 'Capitalize') + pars.add_argument('--path_attribute', default='id', help='Path attribute to show') + pars.add_argument('--matchre', default='', help='Match regular expression') + pars.add_argument('--group', type=inkex.Boolean, default=False, help='Group paths with generated text elements') + + def extract_path_attribute(self, attr, node): + ret = '' + if attr == 'id': + ret = node.get(attr) + elif attr == 'label': + value = node.get(attr) + ret = str(value) if value else (node.get("inkscape:label") or "") + elif attr == 'width': + ret = format(node.bounding_box().width, '.2f') + elif attr == 'height': + ret = format(node.bounding_box().height, '.2f') + elif attr == 'fill' or attr == 'stroke': + if 'style' in node.attrib: + style = node.attrib.get('style') + style = dict(inkex.styles.Style.parse_str(style)) + if attr in style: + ret = style.get(attr) + elif attr in node.attrib: + ret = node.attrib.get(attr) + return ret + + def effect(self): + if len(self.svg.selection.filter(inkex.PathElement)) == 0: + inkex.errormsg("Please select some paths first.") + exit() + + path_attribute = self.options.path_attribute + is_text_attribute = path_attribute in ['id', 'label'] + for id, node in self.svg.selection.filter(inkex.PathElement).items(): + to_show = self.extract_path_attribute(path_attribute, node) + + node.path.transform(node.composed_transform()).to_superpath() + bbox = node.bounding_box() + tx, ty = bbox.center + + if self.options.group: + group_element = node.getparent().add(inkex.Group()) + group_element.add(node) + group_element.set('id', node.get('id') + "_group") + text_element = group_element.add(inkex.TextElement()) + else: + text_element = node.getparent().add(inkex.TextElement()) + + tspan_element = text_element.add(inkex.Tspan()) + tspan_element.set('sodipodi:role', 'line') + styles = {'text-align': 'center', + 'vertical-align': 'bottom', + 'text-anchor': 'middle', + 'font-size': str(self.options.fontsize) + 'px', + 'font-weight': self.options.fontweight, + 'font-style': 'normal', + 'font-family': self.options.font, + 'fill': str(self.options.color) + } + tspan_element.set('style', str(inkex.Style(styles))) + tspan_element.set('dy', '0') + + if is_text_attribute: + if self.options.capitals: + to_show = to_show.upper() + + if self.options.matchre != '': + matches = re.findall(self.options.matchre, to_show) + if len(matches) > 0: + to_show = matches[0] + + if self.options.replaced != '': + to_show = to_show.replace( + self.options.replaced, self.options.replacewith) + + tspan_element.text = to_show + tspan_element.set('id', node.get('id') + "_tspan") + text_element.set('id', node.get('id') + "_text") + text_element.set('x', str(tx)) + text_element.set('y', str(ty)) + text_element.set('transform', 'rotate(%s, %s, %s)' % + (-int(self.options.angle), tx, ty)) + +if __name__ == '__main__': + IdsToText().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz/ids_to_text/meta.json b/extensions/fablabchemnitz/ids_to_text/meta.json new file mode 100644 index 0000000..e1a202e --- /dev/null +++ b/extensions/fablabchemnitz/ids_to_text/meta.json @@ -0,0 +1,21 @@ +[ + { + "name": "Ids To Text", + "id": "fablabchemnitz.de.ids_to_text", + "path": "ids_to_text", + "dependent_extensions": null, + "original_name": "Ids To Text", + "original_id": "org.inkscape.render.ids_to_text", + "license": "GNU GPL v3", + "license_url": "https://github.com/whiplashoo/ids_to_text_inkscape/blob/master/LICENSE", + "comment": "", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/ids_to_text", + "fork_url": "https://github.com/whiplashoo/ids_to_text_inkscape", + "documentation_url": "https://stadtfabrikanten.org/display/IFM/Ids+To+Text", + "inkscape_gallery_url": null, + "main_authors": [ + "github.com/whiplashoo", + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/ifs_fractals/ifs_fractals.inx b/extensions/fablabchemnitz/ifs_fractals/ifs_fractals.inx new file mode 100644 index 0000000..8623eb1 --- /dev/null +++ b/extensions/fablabchemnitz/ifs_fractals/ifs_fractals.inx @@ -0,0 +1,80 @@ + + + IFS Fractals + fablabchemnitz.de.ifs_fractals + + + 3 + + + + true + 0.5 + 0 + 0 + 0.5 + 0 + 0 + + + false + 0.5 + 0 + 0 + 0.5 + 1 + 0 + + + false + 0.5 + 0 + 0 + 0.5 + 0.5 + 1 + + + false + 0.5 + 0 + 0 + 0.5 + 0 + 0 + + + false + 0.5 + 0 + 0 + 0.5 + 0 + 0 + + + + + + + + + + + all + + + + + + + + diff --git a/extensions/fablabchemnitz/ifs_fractals/ifs_fractals.py b/extensions/fablabchemnitz/ifs_fractals/ifs_fractals.py new file mode 100644 index 0000000..b9c08ff --- /dev/null +++ b/extensions/fablabchemnitz/ifs_fractals/ifs_fractals.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +# coding=utf-8 +# +# Copyright (C) 2020 Dylan Simon, dylan@dylex.net +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +""" +Perform fixed-depth IFS repeated duplicate-and-transform. +""" + +import inkex + +class IFSFractals(inkex.EffectExtension): + NXFORM = 5 + XFORM_PARAMS = list("ABCDEF") + + def add_arguments(self, pars): + pars.add_argument("--tab") + pars.add_argument("--iter", type=int, default=3, help="number of iterations") + for i in range(self.NXFORM): + pars.add_argument("--xform%d"%i, type=inkex.Boolean, default=False, help="enable transformation %d"%i) + for p in self.XFORM_PARAMS: + pars.add_argument("--%s%d"%(p,i), type=float, help="transformation matrix %d %s"%(i,p)) + + def effect(self): + xforms = [] + for i in range(self.NXFORM): + if getattr(self.options,'xform%d'%i): + t = [getattr(self.options,"%s%d"%(p,i)) for p in self.XFORM_PARAMS] + xforms.append(inkex.Transform(t)) + + if not xforms: + inkex.errormsg(_('There are no transforms to apply')) + return False + + if not self.svg.selected: + inkex.errormsg(_('There is no selection to duplicate')) + return False + + nodes = self.svg.selected.values() + grp = inkex.Group('IFS') + layer = self.svg.get_current_layer().add(grp) + + for i in range(self.options.iter): + n = [] + for node in nodes: + for x in xforms: + d = node.copy() + d.transform = x @ d.transform + n.append(d) + g = inkex.Group('IFS iter %d'%i) + g.add(*n) + grp.add(g) + nodes = n + + return True + +if __name__ == '__main__': + IFSFractals().run() diff --git a/extensions/fablabchemnitz/ifs_fractals/meta.json b/extensions/fablabchemnitz/ifs_fractals/meta.json new file mode 100644 index 0000000..500cfeb --- /dev/null +++ b/extensions/fablabchemnitz/ifs_fractals/meta.json @@ -0,0 +1,21 @@ +[ + { + "name": "IFS Fractals", + "id": "fablabchemnitz.de.ifs_fractals", + "path": "ifs_fractals", + "dependent_extensions": null, + "original_name": "IFS", + "original_id": "org.inkscape.filter.ifs", + "license": "GNU GPL v2", + "license_url": "https://github.com/dylex/inkscape-ifs/blob/master/ifs.py", + "comment": "", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/ifs_fractals", + "fork_url": "https://github.com/dylex/inkscape-ifs", + "documentation_url": "https://stadtfabrikanten.org/display/IFM/IFS+Fractals", + "inkscape_gallery_url": null, + "main_authors": [ + "github.com/dylex", + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/insert_paper_template/insert_paper_template.inx b/extensions/fablabchemnitz/insert_paper_template/insert_paper_template.inx new file mode 100644 index 0000000..70d3788 --- /dev/null +++ b/extensions/fablabchemnitz/insert_paper_template/insert_paper_template.inx @@ -0,0 +1,30 @@ + + + Insert Paper Template + fablabchemnitz.de.insert_paper_template + + + + + + + + + + + + + + true + + all + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/insert_paper_template/insert_paper_template.py b/extensions/fablabchemnitz/insert_paper_template/insert_paper_template.py new file mode 100644 index 0000000..b348145 --- /dev/null +++ b/extensions/fablabchemnitz/insert_paper_template/insert_paper_template.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 + + +# Copyright 2016 Luke Phillips (lukerazor@hotmail.com) +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +# Extension dirs +# linux:~/.config/inkscape/extensions +# windows: D:\Program Files\Inkscape\share\extensions +from lxml import etree +import inkex + +inkex.NSS[u'cs'] = u'http://www.razorfoss.org/tuckboxextension/' + +class InsertPaperTemplate(inkex.EffectExtension): + + def add_arguments(self, pars): + pars.add_argument('-p', '--papertype') + pars.add_argument('-s', '--show_type') + + ### colour ### + self.StrokeWidthMM = 0.25 + self.FontSize = "11px" + + def effect(self): + self.Group = etree.SubElement(self.svg.get_current_layer(), inkex.addNS('g','svg'), {} ) + + papertypes = {} + papertypes["A5"] = (148, 210, "#ffeeaa") # yellow + papertypes["A4"] = (210, 297, "#ffccaa") # orange + papertypes["A3"] = (297, 420, "#afdde9") # blue + papertypes["A2"] = (420, 594, "#ccaaff") # purple + papertypes["A1"] = (594, 841, "#afe9c6") # green + papertypes["A0"] = (841, 1189, "#ffd5d5") # red + papertypes["POKER"] = (63.5, 88, "#ffffff") # white + papertypes["BRIDGE"] = (56, 88, "#ffffff") # white + papertypes["MINI_US"] = (41, 63, "#ffffff") # white + papertypes["MINI_EU"] = (44, 68, "#ffffff") # white + papertypes["TAROT"] = (70, 120, "#ffffff") # white + + + if self.options.papertype in papertypes: + self.CreateTemplate(self.options.papertype, *(papertypes[self.options.papertype])) + else: + raise Exception("Paper type '{0}' is undefined".format(self.options.papertype)) + + def CreateTemplate(self, label, width, height, colour): + x = 0 + y = 0 + self._CreateRectangleInMillimetres(width-self.StrokeWidthMM, height-self.StrokeWidthMM, x, y, colour) + if self.options.show_type == "true": + self._CreateText(label, x + width/2 , y + height/2) + + def _CreateText(self, labelText, x, y): + style = {'stroke': '#000000', + 'stroke-width': self.MMtoUU(self.StrokeWidthMM), + 'fill' : '#000000', + 'font-size' : self.FontSize, + 'text-align' : 'center', + 'text-anchor' : 'middle' + } + + attribs = {'style': str(inkex.Style(style)), 'x': self.MMtoUU(x), 'y': self.MMtoUU(y)} + + text = etree.Element(inkex.addNS('text','svg'), attribs) + text.text = labelText + + self.Group.append(text) + + def _CreateRectangleInMillimetres(self, width, height, x, y, color): + style = {'stroke': '#000000', 'stroke-width': self.MMtoUU(self.StrokeWidthMM), 'fill' : color} + attribs = {'style': str(inkex.Style(style)), 'height': self.MMtoUU(height), 'width': self.MMtoUU(width), 'x': self.MMtoUU(x), 'y': self.MMtoUU(y)} + etree.SubElement(self.Group, inkex.addNS('rect','svg'), attribs ) + + def MMtoUU(self, mmval): + if hasattr(self.svg, "unittouu"): + return str(self.svg.unittouu("{0}mm".format(mmval))) + else: + MM_TO_PIXELS = 1 + + return str(MM_TO_PIXELS * mmval) + +if __name__ == '__main__': + InsertPaperTemplate().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz/insert_paper_template/meta.json b/extensions/fablabchemnitz/insert_paper_template/meta.json new file mode 100644 index 0000000..1bdf04c --- /dev/null +++ b/extensions/fablabchemnitz/insert_paper_template/meta.json @@ -0,0 +1,21 @@ +[ + { + "name": "Insert Paper Template", + "id": "fablabchemnitz.de.insert_paper_template", + "path": "insert_paper_template", + "dependent_extensions": null, + "original_name": "Insert Paper Template", + "original_id": "phillips.effect.papertemplate", + "license": "GNU GPL v2", + "license_url": "https://sourceforge.net/p/razorfoss/svn/HEAD/tree/trunk/Inkscape/InsertPaperTemplate/InsertPaperTemplate.py", + "comment": "", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/insert_paper_template", + "fork_url": "https://sourceforge.net/p/razorfoss/svn/HEAD/tree/trunk/Inkscape/InsertPaperTemplate/", + "documentation_url": "https://stadtfabrikanten.org/display/IFM/Insert+Paper+Template", + "inkscape_gallery_url": null, + "main_authors": [ + "Luke Phillips:lukerazor@hotmail.com", + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/join_paths/join_paths.inx b/extensions/fablabchemnitz/join_paths/join_paths.inx new file mode 100644 index 0000000..5fd7189 --- /dev/null +++ b/extensions/fablabchemnitz/join_paths/join_paths.inx @@ -0,0 +1,109 @@ + + + Join Paths / Create Tabs And Dimples + fablabchemnitz.de.join_paths + + + + + + true + true + 0.0100 + + + + false + false + + + + + + + + false + false + false + true + + + + + + + + + 45.000 + 4.000 + 45.000 + 4.000 + + + + + + + + + + false + 1 + 40 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ../000_about_fablabchemnitz.svg + + + + path + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/join_paths/join_paths.py b/extensions/fablabchemnitz/join_paths/join_paths.py new file mode 100644 index 0000000..4d009dd --- /dev/null +++ b/extensions/fablabchemnitz/join_paths/join_paths.py @@ -0,0 +1,429 @@ +#!/usr/bin/env python3 + +''' +Inkscape extension to join the selected paths. With the optimized option selected, +the next path to be joined is the one, which has one of its end nodes closest to the ending +node of the earlier path. + +Copyright (C) 2019 Shrinivas Kulkarni + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +''' + +import inkex +from inkex.paths import CubicSuperPath +import sys +import copy +import math + +def floatCmpWithMargin(float1, float2, margin): + return abs(float1 - float2) < margin + +def vectCmpWithMargin(vect1, vect2, margin): + return all(floatCmpWithMargin(vect2[i], vect1[i], margin) for i in range(0, len(vect1))) + +def getPartsFromCubicSuper(cspath): + parts = [] + for subpath in cspath: + part = [] + prevBezPt = None + for i, bezierPt in enumerate(subpath): + if(prevBezPt != None): + seg = [prevBezPt[1], prevBezPt[2], bezierPt[0], bezierPt[1]] + part.append(seg) + prevBezPt = bezierPt + parts.append(part) + return parts + +def getCubicSuperFromParts(parts): + cbsuper = [] + for part in parts: + subpath = [] + lastPt = None + pt = None + for seg in part: + if(pt == None): + ptLeft = seg[0] + pt = seg[0] + ptRight = seg[1] + subpath.append([ptLeft, pt, ptRight]) + ptLeft = seg[2] + pt = seg[3] + subpath.append([ptLeft, pt, pt]) + cbsuper.append(subpath) + return cbsuper + +def getArrangedIds(pathMap, startPathId): + nextPathId = startPathId + orderPathIds = [nextPathId] + + #Arrange in order + while(len(orderPathIds) < len(pathMap)): + minDist = 9e+100 #A large float + closestId = None + np = pathMap[nextPathId] + if np[-1] == []: + inkex.utils.debug("Warning. Selection seems to contain invalid paths, e.g. pointy paths like M 54,54 Z. Please check and try again!") + exit(1) + npPts = [np[-1][-1][-1]] + if(len(orderPathIds) == 1):#compare both the ends for the first path + npPts.append(np[0][0][0]) + + for key in pathMap: + if(key in orderPathIds): + continue + parts = pathMap[key] + start = parts[0][0][0] + end = parts[-1][-1][-1] + + for i, npPt in enumerate(npPts): + dist = abs(start[0] - npPt[0]) + abs(start[1] - npPt[1]) + if(dist < minDist): + minDist = dist + closestId = key + dist = abs(end[0] - npPt[0]) + abs(end[1] - npPt[1]) + if(dist < minDist): + minDist = dist + pathMap[key] = [[[pts for pts in reversed(seg)] for seg in \ + reversed(part)] for part in reversed(parts)] + closestId = key + + #If start point of the first path is closer reverse its direction + if(i > 0 and closestId == key): + pathMap[nextPathId] = [[[pts for pts in reversed(seg)] for seg in \ + reversed(part)] for part in reversed(np)] + + orderPathIds.append(closestId) + nextPathId = closestId + return orderPathIds + +def rotate(origin, point, angle): + """ + Rotate a point counterclockwise by a given angle around a given origin. + + The angle should be given in radians. + """ + ox, oy = origin + px, py = point + + qx = ox + math.cos(angle) * (px - ox) - math.sin(angle) * (py - oy) + qy = oy + math.sin(angle) * (px - ox) + math.cos(angle) * (py - oy) + return qx, qy + +class JoinPaths(inkex.EffectExtension): + + def add_arguments(self, pars): + pars.add_argument("--optimized", type=inkex.Boolean, default=True) + pars.add_argument("--reverse", type=inkex.Boolean, default=False) + pars.add_argument("--margin", type=float, default=0.0100) + pars.add_argument("--add_dimples", type=inkex.Boolean, default=False) + pars.add_argument("--draw_dimple_centers", type=inkex.Boolean, default=False) + pars.add_argument("--draw_arcs_as_paths", type=inkex.Boolean, default=False) + pars.add_argument("--dimple_invert", type=inkex.Boolean, default=False) + pars.add_argument("--dimple_type", default="lines") + pars.add_argument("--dimples_to_group", type=inkex.Boolean, default=False) + pars.add_argument("--draw_both_sides", type=inkex.Boolean, default=False) + pars.add_argument("--dimple_height_mode", default="by_height") + pars.add_argument("--dimple_height", type=float, default=4) + pars.add_argument("--dimple_angle", type=float, default=45) + pars.add_argument("--dimple_tab_angle", type=float, default=45) + pars.add_argument("--dimple_sheetmetal_depth", type=float, default=4) + pars.add_argument("--dimple_gap_filter", type=inkex.Boolean, default=False) + pars.add_argument("--dimple_min_gap", type=float, default=1) + pars.add_argument("--dimple_max_gap", type=float, default=40) + pars.add_argument("--dimple_gap_filter_units", default="mm") + pars.add_argument("--dimple_height_units", default="mm") + pars.add_argument("--tab", default="sampling", help="Tab") + + def effect(self): + + pathNodes = self.document.xpath('//svg:path',namespaces=inkex.NSS) + if self.options.reverse is True: #helps debugging some strange Z orders (try out) + pathNodes = pathNodes[::-1] + #pathNodes[0].path = pathNodes[0].path.reverse() + #pathNodes[0].path = pathNodes[-1].path.reverse() + + paths = {p.get('id'): getPartsFromCubicSuper(CubicSuperPath(p.get('d'))) for p in pathNodes } + #paths.keys() Order disturbed + pathIds = [p.get('id') for p in pathNodes] + + if self.options.dimples_to_group is True: + dimpleUnifyGroup = self.svg.get_current_layer().add(inkex.Group(id=self.svg.get_unique_id("dimplesCollection"))) + + if(len(paths) > 1): + if(self.options.optimized): + startPathId = pathIds[0] + pathIds = getArrangedIds(paths, startPathId) + newParts = [] + firstElem = None + for key in pathIds: + parts = paths[key] + # ~ parts = getPartsFromCubicSuper(cspath) + start = parts[0][0][0] + try: + elem = self.svg.selected[key] + + if(len(newParts) == 0): + newParts += parts[:] + firstElem = elem + else: + if(vectCmpWithMargin(start, newParts[-1][-1][-1], margin = self.options.margin)) and self.options.add_dimples is False: + newParts[-1] += parts[0] + else: + if self.options.add_dimples is True: + if self.options.dimples_to_group is True: + dimpleGroup = dimpleUnifyGroup.add(inkex.Group(id="dimpleGroup-{}".format(elem.attrib["id"]))) + else: + dimpleGroup = elem.getparent().add(inkex.Group(id="dimpleGroup-{}".format(elem.attrib["id"]))) + + p1 = newParts[-1][-1][-1] + p2 = start + midPoint = [(p1[0] + p2[0])/2, (p1[1] + p2[1])/2] + newParts[-1].append([newParts[-1][-1][-1], newParts[-1][-1][-1], midPoint, midPoint]) + newParts[-1].append([newParts[-1][-1][-1], newParts[-1][-1][-1], p2, p2]) + newParts[-1] += parts[0] + + #get slope, distance and norm slope + dx = midPoint[0]-p1[0] + dy = midPoint[1]-p1[1] + dist = math.sqrt(dx*dx + dy*dy) + dx /= dist + dy /= dist + + dx2 = p2[0]-p1[0] + dy2 = p2[1]-p1[1] + dist2 = math.sqrt(dx2*dx2 + dy2*dy2) + if dx2 == 0: + slope=sys.float_info.max #vertical + else: + slope=(p2[1] - p1[1]) / dx2 + slope_angle = 90 + math.degrees(math.atan(slope)) + if (self.options.dimple_gap_filter is True \ + and dist2 >= self.svg.unittouu(str(self.options.dimple_min_gap) + self.options.dimple_gap_filter_units) \ + and dist2 < self.svg.unittouu(str(self.options.dimple_max_gap) + self.options.dimple_gap_filter_units) + ) \ + or self.options.dimple_gap_filter is False: + if self.options.dimple_height_mode == "by_height": + dimple_height = self.svg.unittouu(str(self.options.dimple_height) + self.options.dimple_height_units) + else: + dimple_height = dist * math.sin(math.radians(self.options.dimple_angle)) + + x3 = midPoint[0] + (dimple_height)*dy + y3 = midPoint[1] - (dimple_height)*dx + x4 = midPoint[0] - (dimple_height)*dy + y4 = midPoint[1] + (dimple_height)*dx + + dimple_center_style = {'stroke': '#00FFFF', 'fill': 'none', 'stroke-width': str(self.svg.unittouu('1px'))} + dimple_style = {'stroke': '#0000FF', 'fill': 'none', 'stroke-width': str(self.svg.unittouu('1px'))} + + if self.options.draw_dimple_centers is True: + #add a new dimple center cross (4 segments) + line = dimpleGroup.add(inkex.PathElement(id=self.svg.get_unique_id('dimple_center_perp1'))) + line.set('d', "M{:0.6f},{:0.6f} L{:0.6f},{:0.6f}".format(midPoint[0], midPoint[1], x3, y3)) + line.style = dimple_center_style + line = dimpleGroup.add(inkex.PathElement(id=self.svg.get_unique_id('dimple_center_perp2'))) + line.set('d', "M{:0.6f},{:0.6f} L{:0.6f},{:0.6f}".format(midPoint[0], midPoint[1], x4, y4)) + line.style = dimple_center_style + line = dimpleGroup.add(inkex.PathElement(id=self.svg.get_unique_id('dimple_center_join1'))) + line.set('d', "M{:0.6f},{:0.6f} L{:0.6f},{:0.6f}".format(p1[0], p1[1], midPoint[0], midPoint[1])) + line.style = dimple_center_style + line = dimpleGroup.add(inkex.PathElement(id=self.svg.get_unique_id('dimple_center_join1'))) + line.set('d', "M{:0.6f},{:0.6f} L{:0.6f},{:0.6f}".format(midPoint[0], midPoint[1], p2[0], p2[1])) + line.style = dimple_center_style + + ########## + ### LINES + ########## + if self.options.dimple_type == "lines": + line = dimpleGroup.add(inkex.PathElement(id=self.svg.get_unique_id('dimple_line'))) + line.set('d', "M{:0.6f},{:0.6f} L{:0.6f},{:0.6f}".format(p1[0], p1[1], p2[0], p2[1])) + line.style = dimple_style + + ########## + ### PEAKS + ########## + elif self.options.dimple_type == "peaks": + if self.options.dimple_invert is True: + x5 = x3 + y5 = y3 + x3 = x4 + y3 = y4 + x4 = x5 + y4 = y5 + #add a new dimple center + line = dimpleGroup.add(inkex.PathElement(id=self.svg.get_unique_id('dimple_peak'))) + line.set('d', "M{:0.6f},{:0.6f} L{:0.6f},{:0.6f} L{:0.6f},{:0.6f}".format(p1[0], p1[1], x3, y3, p2[0], p2[1])) + line.style = dimple_style + + if self.options.draw_both_sides is True: + #add a new opposite dimple center + line = dimpleGroup.add(inkex.PathElement(id=self.svg.get_unique_id('dimple_peak'))) + line.set('d', "M{:0.6f},{:0.6f} L{:0.6f},{:0.6f} L{:0.6f},{:0.6f}".format(p1[0], p1[1], x4, y4, p2[0], p2[1])) + line.style = dimple_style + ########## + ### ARCS + ########## + elif self.options.dimple_type == "arcs": + if self.options.draw_arcs_as_paths is False: + ellipse = dimpleGroup.add(inkex.Ellipse(id=self.svg.get_unique_id('dimple_arc'))) + ellipse.set('transform', "rotate({:0.6f} {:0.6f} {:0.6f})".format(slope_angle, midPoint[0], midPoint[1])) + ellipse.set('sodipodi:arc-type', "arc") + ellipse.set('sodipodi:type', "arc") + ellipse.set('sodipodi:cx', "{:0.6f}".format(midPoint[0])) + ellipse.set('sodipodi:cy', "{:0.6f}".format(midPoint[1])) + ellipse.set('sodipodi:rx', "{:0.6f}".format(dimple_height)) + ellipse.set('sodipodi:ry', "{:0.6f}".format(dist2 / 2)) + if self.options.dimple_invert is True: + ellipse.set('sodipodi:start', "{:0.6f}".format(math.radians(90.0))) + ellipse.set('sodipodi:end', "{:0.6f}".format(math.radians(270.0))) + else: + ellipse.set('sodipodi:start', "{:0.6f}".format(math.radians(270.0))) + ellipse.set('sodipodi:end', "{:0.6f}".format(math.radians(90.0))) + ellipse.style = dimple_style + + if self.options.draw_both_sides is True: + ellipse = dimpleGroup.add(inkex.Ellipse(id=self.svg.get_unique_id('dimple_arc'))) + ellipse.set('transform', "rotate({:0.6f} {:0.6f} {:0.6f})".format(slope_angle, midPoint[0], midPoint[1])) + ellipse.set('sodipodi:arc-type', "arc") + ellipse.set('sodipodi:type', "arc") + ellipse.set('sodipodi:cx', "{:0.6f}".format(midPoint[0])) + ellipse.set('sodipodi:cy', "{:0.6f}".format(midPoint[1])) + ellipse.set('sodipodi:rx', "{:0.6f}".format(dimple_height)) + ellipse.set('sodipodi:ry', "{:0.6f}".format(dist2 / 2)) + if self.options.dimple_invert is True: + ellipse.set('sodipodi:start', "{:0.6f}".format(math.radians(270.0))) + ellipse.set('sodipodi:end', "{:0.6f}".format(math.radians(90.0))) + else: + ellipse.set('sodipodi:start', "{:0.6f}".format(math.radians(90.0))) + ellipse.set('sodipodi:end', "{:0.6f}".format(math.radians(270.0))) + ellipse.style = dimple_style + else: #if draw_arcs_as_paths is True + # +--- x-end point + # | + # counterclockwise ---+ | +--- y-end point + # | | | + # + # | | | | + # 1 Radius x-Axis ---+ | | +--- 4 short / long way + # | | + # 2 Radius y-Axis ---+ +--- 3 Rotation x + if self.options.dimple_invert is True: + b1 = 1 + b2 = 0 + else: + b1 = 0 + b2 = 1 + ellipse = dimpleGroup.add(inkex.PathElement(id=self.svg.get_unique_id('dimple_arc'))) + ellipse.set('d', "M {:0.6f} {:0.6f} A {:0.6f} {:0.6f} {:0.6f} 0 {} {:0.6f} {:0.6f}".format(p1[0], p1[1], dimple_height, dist2 / 2, slope_angle, b1, p2[0], p2[1])) + ellipse.style = dimple_style + if self.options.draw_both_sides is True: + ellipse = dimpleGroup.add(inkex.PathElement(id=self.svg.get_unique_id('dimple_arc'))) + ellipse.set('d', "M {:0.6f} {:0.6f} A {:0.6f} {:0.6f} {:0.6f} 0 {} {:0.6f} {:0.6f}".format(p1[0], p1[1], dimple_height, dist2 / 2, slope_angle, b2, p2[0], p2[1])) + ellipse.style = dimple_style + + ########## + ### TABS + ########## + elif self.options.dimple_type == "tabs": + l_hypo = dimple_height / (math.cos(math.radians(90.0 - self.options.dimple_tab_angle))) + pbottom1 = rotate(p1, [p1[0] + l_hypo * dx, p1[1] + l_hypo * dy], math.radians(-self.options.dimple_tab_angle)) + pbottom2 = rotate(p2, [p2[0] - l_hypo * dx, p2[1] - l_hypo * dy], math.radians(-360.0 + self.options.dimple_tab_angle)) + ptop1 = rotate(p1, [p1[0] + l_hypo * dx, p1[1] + l_hypo * dy], math.radians(self.options.dimple_tab_angle)) + ptop2 = rotate(p2, [p2[0] - l_hypo * dx, p2[1] - l_hypo * dy], math.radians(360.0 - self.options.dimple_tab_angle)) + + + if self.options.dimple_invert is True: + ptemp1 = pbottom1 + ptemp2 = pbottom2 + pbottom1 = ptop1 + pbottom2 = ptop2 + ptop1 = ptemp1 + ptop2 = ptemp2 + + #add a new tab + line = dimpleGroup.add(inkex.PathElement(id=self.svg.get_unique_id('dimple_tab'))) + line.set('d', "M{:0.6f},{:0.6f} L{:0.6f},{:0.6f} L{:0.6f},{:0.6f} L{:0.6f},{:0.6f}".format( + p1[0], p1[1], pbottom1[0], pbottom1[1], pbottom2[0], pbottom2[1], p2[0], p2[1])) + line.style = dimple_style + if self.options.draw_both_sides is True: + line = dimpleGroup.add(inkex.PathElement(id=self.svg.get_unique_id('dimple_tab'))) + line.set('d', "M{:0.6f},{:0.6f} L{:0.6f},{:0.6f} L{:0.6f},{:0.6f} L{:0.6f},{:0.6f}".format( + p1[0], p1[1], ptop1[0], ptop1[1], ptop2[0], ptop2[1], p2[0], p2[1])) + line.style = dimple_style + + ########## + ### sHEETMETAL + ########## + elif self.options.dimple_type == "sheetmetal": + + if self.options.dimple_invert is True: + self.options.dimple_tab_angle = 360.0 - self.options.dimple_tab_angle + + pbottom1 = rotate(p1, [p1[0] + dimple_height * dx, p1[1] + dimple_height * dy], math.radians(-self.options.dimple_tab_angle)) + pbottom2 = rotate(p2, [p2[0] - dimple_height * dx, p2[1] - dimple_height * dy], math.radians(-360.0 + self.options.dimple_tab_angle)) + + depth = self.svg.unittouu(str(self.options.dimple_sheetmetal_depth) + self.options.dimple_height_units) + poff1 = [p1[0] + (depth)*dx, p1[1] + (depth)*dy] + poff2 = [p2[0] - (depth)*dx, p2[1] - (depth)*dy] + poff1_start = rotate(poff1, [poff1[0] + dimple_height * dx, poff1[1] + dimple_height * dy], math.radians(180.0 - self.options.dimple_tab_angle)) + poff2_end = rotate(poff2, [poff2[0] + dimple_height * dx, poff2[1] + dimple_height * dy], math.radians(self.options.dimple_tab_angle)) + + line = dimpleGroup.add(inkex.PathElement(id=self.svg.get_unique_id('dimple_sheetmetal_start'))) + line.set('d', "M{:0.6f},{:0.6f} L{:0.6f},{:0.6f}".format( + p1[0], p1[1], pbottom1[0], pbottom1[1])) + line.style = dimple_style + + line = dimpleGroup.add(inkex.PathElement(id=self.svg.get_unique_id('dimple_sheetmetal_middle'))) + line.set('d', "M{:0.6f},{:0.6f} L{:0.6f},{:0.6f} L{:0.6f},{:0.6f} L{:0.6f},{:0.6f}".format( + poff1_start[0], poff1_start[1], poff1[0], poff1[1], poff2[0], poff2[1], poff2_end[0], poff2_end[1])) + line.style = dimple_style + + line = dimpleGroup.add(inkex.PathElement(id=self.svg.get_unique_id('dimple_sheetmetal_end'))) + line.set('d', "M{:0.6f},{:0.6f} L{:0.6f},{:0.6f}".format( + p2[0], p2[1], pbottom2[0], pbottom2[1])) + line.style = dimple_style + + #cleanup groups + if len(dimpleGroup) == 1: ##move up child if group has only one child + for child in dimpleGroup: + dimpleGroup.getparent().insert(elem.getparent().index(elem), child) + dimpleGroup.delete() #delete the empty group now + + else: + newParts[-1].append([newParts[-1][-1][-1], newParts[-1][-1][-1], start, start]) + newParts[-1] += parts[0] + + if(len(parts) > 1): + newParts += parts[1:] + + parent = elem.getparent() + idx = parent.index(elem) + if self.options.add_dimples is False: + parent.remove(elem) + except: + pass #elem might come from group item - in this case we need to ignore it + + if firstElem is None: + self.msg('Please select some paths first. Check if you selected a group or an object instead.') + exit() + newElem = copy.copy(firstElem) + oldId = firstElem.get('id') + newElem.set('d', CubicSuperPath(getCubicSuperFromParts(newParts))) + newElem.set('id', oldId + '_joined') + if self.options.add_dimples is False: + parent.insert(idx, newElem) + +if __name__ == '__main__': + JoinPaths().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz/join_paths/meta.json b/extensions/fablabchemnitz/join_paths/meta.json new file mode 100644 index 0000000..fbd5498 --- /dev/null +++ b/extensions/fablabchemnitz/join_paths/meta.json @@ -0,0 +1,21 @@ +[ + { + "name": "Join Paths / Create Tabs And Dimples", + "id": "fablabchemnitz.de.join_paths", + "path": "join_paths", + "dependent_extensions": null, + "original_name": "Join Paths Optimized", + "original_id": "khema.optim.join.paths", + "license": "GNU GPL v2", + "license_url": "https://github.com/Shriinivas/inkscapejoinpaths/blob/master/LICENSE", + "comment": "ported to Inkscape v1 by Mario Voigt", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/join_paths", + "fork_url": "https://github.com/Shriinivas/inkscapejoinpaths", + "documentation_url": "https://stadtfabrikanten.org/pages/viewpage.action?pageId=55019193", + "inkscape_gallery_url": null, + "main_authors": [ + "github.com/Shriinivas", + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/living_hinge/living_hinge.inx b/extensions/fablabchemnitz/living_hinge/living_hinge.inx new file mode 100644 index 0000000..f32cfa5 --- /dev/null +++ b/extensions/fablabchemnitz/living_hinge/living_hinge.inx @@ -0,0 +1,37 @@ + + + Living Hinge (Fit To Rectangle) + fablabchemnitz.de.living_hinge + + + + + + + + + + + 19.0 + 3.0 + 1.5 + + + all + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/living_hinge/living_hinge.py b/extensions/fablabchemnitz/living_hinge/living_hinge.py new file mode 100644 index 0000000..d03f5e8 --- /dev/null +++ b/extensions/fablabchemnitz/living_hinge/living_hinge.py @@ -0,0 +1,264 @@ +#!/usr/bin/env python3 +""" +hinge_cuts.py +A module for creating lines to laser cut living hinges + +Copyright (C) 2013 Mark Endicott; drphonon@gmail.com + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +For a copy of the GNU General Public License +write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +""" + +""" +Change in version 0.2. +Changed self.unittouu to self.svg.unittouu +and self.uutounit to self.uutounit +to make it work with Inkscape 0.91 +Thanks to Pete Prodoehl for pointing this out. +""" + +""" +Change in version 0.3 +Add a direction option so the cuts can be done in the X or Y direction. +Modification by Sylvain GARNAVAULT; garnav@wanadoo.fr +""" + +""" +Change in version 0.4. +Python3 / inkscape 1.0 migration +""" +__version__ = "0.4" + +import inkex +import gettext +_ = gettext.gettext + +from lxml import etree + +class LivingHinge(inkex.EffectExtension): + + def add_arguments(self, pars): + pars.add_argument('--direction',default='y',help='cuts direction') + pars.add_argument('--unit',default='mm',help='units of measurement') + pars.add_argument('--cut_length',type=float, default=0,help='length of the cuts for the hinge.') + pars.add_argument('--gap_length',type=float, default=0,help='separation distance between successive hinge cuts.') + pars.add_argument('--sep_distance',type=float, default=0,help='distance between successive lines of hinge cuts.') + + def effect(self): + + unit=self.options.unit + # which direction are we cutting + dir = self.options.direction + # starting cut length. Will be adjusted for get an integer number of cuts in the y-direction. + l = self.svg.unittouu(str(self.options.cut_length) + unit) + # cut separation in the y-direction + d = self.svg.unittouu(str(self.options.gap_length) + unit) + # starting separation between lines of cuts in the x-direction. Will be adjusted to get an integer + # number of cut lines in the x-direction. + dd = self.svg.unittouu(str(self.options.sep_distance) + unit) + + # get selected nodes + if self.svg.selected: + # put lines on the current layer + parent = self.svg.get_current_layer() + for id, node in self.svg.selected.items(): + # inkex.utils.debug("id:" + id) + # for key in node.attrib.keys(): + # inkex.utils.debug(key + ": " + node.get(key)) + bbox = node.bounding_box() + + # calculate the cut lines for the hinge + if (dir=="y"): + lines, l_actual, d_actual, dd_actual = self.calcYCutLines(bbox.left, bbox.top, bbox.width, bbox.height, l, d, dd) + else: + lines, l_actual, d_actual, dd_actual = self.calcXCutLines(bbox.left, bbox.top, bbox.width, bbox.height, l, d, dd) + + s = '' + for line in lines: + s = s + "M %s, %s L %s, %s " % (line['x1'], line['y1'], line['x2'], line['y2']) + style = { 'stroke': '#000000', 'fill': 'none', 'stroke-width': self.svg.unittouu("0.1 mm")} + drw = {'style':str(inkex.Style(style)), 'd': s} + hinge = etree.SubElement(parent, inkex.addNS('path', 'svg'), drw) + desc = etree.SubElement(hinge, inkex.addNS('desc', 'svg')) + desc.text = "Hinge cut parameters: actual(requested)\n" \ + "cut length: %.2f %s (%.2f %s)\n" \ + "gap length: %.2f %s (%.2f %s)\n" \ + "separation distance: %.2f %s (%.2f %s)" % (self.svg.uutounit(l_actual, unit), unit, self.svg.uutounit(l, unit), unit, + self.svg.uutounit(d_actual, unit), unit, self.svg.uutounit(d, unit), unit, + self.svg.uutounit(dd_actual, unit), unit, self.svg.uutounit(dd, unit), unit) + else: + inkex.utils.debug("No rectangle(s) have been selected.") + + def calcYCutLines(self, x, y, dx, dy, l, d, dd): + """ + Return a list of cut lines as dicts. Each dict contains the end points for one cut line. + [{x1, y1, x2, y2}, ... ] + + Parameters + x, y: the coordinates of the lower left corner of the bounding rect + dx, dy: width and height of the bounding rect + l: the nominal length of a cut line + d: the separation between cut lines in the y-direction + dd: the nominal separation between cut lines in the x-direction + + l will be adjusted so that there is an integral number of cuts in the y-direction. + dd will be adjusted so that there is an integral number of cuts in the x-direction. + """ + ret = [] + + # use l as a starting guess. Adjust it so that we get an integer number of cuts in the y-direction + # First compute the number of cuts in the y-direction using l. This will not in general be an integer. + p = (dy-d)/(d+l) + #round p to the nearest integer + p = round(p) + #compute the new l that will result in p cuts in the y-direction. + if p == 0: + p = 1 #avoid divison by zero + l = (dy-d)/p - d + + # use dd as a starting guess. Adjust it so that we get an even integer number of cut lines in the x-direction. + p = dx/dd + p = round(p) + if p % 2 == 1: + p = p + 1 + dd = dx/p + + # + # Column A cuts + # + currx = 0 + donex = False + while not donex: + doney = False + starty = 0 + endy = (l + d)/2.0 + while not doney: + if endy >= dy: + endy = dy + # Add the end points of the line + ret.append({'x1' : x + currx, 'y1' : y + starty, 'x2': x + currx, 'y2': y + endy}) + starty = endy + d + endy = starty + l + if starty >= dy: + doney = True + currx = currx + dd * 2.0 + if currx - dx > dd: + donex = True +# inkex.utils.debug("lastx: " + str(lastx) + "; currx: " + str(currx)) + # + #Column B cuts + # + currx = dd + donex = False + while not donex: + doney = False + starty = d + endy = starty + l + while not doney: + if endy >= dy: + endy = dy + # create a line + ret.append({'x1' : x + currx, 'y1' : y + starty, 'x2': x + currx, 'y2': y + endy}) + starty = endy + d + endy = starty + l + if starty >= dy: + doney = True + currx = currx + dd*2.0 + if currx > dx: + donex = True + + return (ret, l, d, dd) + + + def calcXCutLines(self, x, y, dx, dy, l, d, dd): + """ + Return a list of cut lines as dicts. Each dict contains the end points for one cut line. + [{x1, y1, x2, y2}, ... ] + + Parameters + x, y: the coordinates of the lower left corner of the bounding rect + dx, dy: width and height of the bounding rect + l: the nominal length of a cut line + d: the separation between cut lines in the x-direction + dd: the nominal separation between cut lines in the y-direction + + l will be adjusted so that there is an integral number of cuts in the x-direction. + dd will be adjusted so that there is an integral number of cuts in the y-direction. + """ + ret = [] + + + # use l as a starting guess. Adjust it so that we get an integer number of cuts in the y-direction + # First compute the number of cuts in the x-direction using l. This will not in general be an integer. + p = (dx-d)/(d+l) + #round p to the nearest integer + p = round(p) + #compute the new l that will result in p cuts in the x-direction. + l = (dx-d)/p - d + + # use dd as a starting guess. Adjust it so that we get an even integer number of cut lines in the y-direction. + p = dy/dd + p = round(p) + if p % 2 == 1: + p = p + 1 + dd = dy/p + + # + # Rows A cuts + # + curry = 0 + doney = False + while not doney: + donex = False + startx = 0 + endx = (l + d)/2.0 + while not donex: + if endx >= dx: + endx = dx + # Add the end points of the line + ret.append({'x1' : x + startx, 'y1' : y + curry, 'x2': x + endx, 'y2': y + curry}) + startx = endx + d + endx = startx + l + if startx >= dx: + donex = True + curry = curry + dd * 2.0 + if curry - dy > dd: + doney = True + + # + # Rows B cuts + # + curry = dd + doney = False + while not doney: + donex = False + startx = d + endx = startx + l + while not donex: + if endx >= dx: + endx = dx + # create a line + ret.append({'x1' : x + startx, 'y1' : y + curry, 'x2': x + endx, 'y2': y + curry}) + startx = endx + d + endx = startx + l + if startx >= dx: + donex = True + curry = curry + dd*2.0 + if curry > dy: + doney = True + + return (ret, l, d, dd) + +if __name__ == '__main__': + LivingHinge().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz/living_hinge/meta.json b/extensions/fablabchemnitz/living_hinge/meta.json new file mode 100644 index 0000000..553016e --- /dev/null +++ b/extensions/fablabchemnitz/living_hinge/meta.json @@ -0,0 +1,22 @@ +[ + { + "name": "Living Hinge (Fit To Rectangle)", + "id": "fablabchemnitz.de.living_hinge", + "path": "living_hinge", + "dependent_extensions": null, + "original_name": "Living Hinge", + "original_id": "org.lvl1.living_hinge", + "license": "GNU GPL v3", + "license_url": "https://github.com/siteswapjuggler/Inkscape_LivingHinge/blob/master/LICENSE.md", + "comment": "", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/living_hinge", + "fork_url": "https://github.com/siteswapjuggler/Inkscape_LivingHinge", + "documentation_url": "https://stadtfabrikanten.org/pages/viewpage.action?pageId=55018530", + "inkscape_gallery_url": null, + "main_authors": [ + "github.com/drphonon", + "github.com/siteswapjuggler", + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/move_path_node/move_path_node.inx b/extensions/fablabchemnitz/move_path_node/move_path_node.inx index bb27882..85811d8 100644 --- a/extensions/fablabchemnitz/move_path_node/move_path_node.inx +++ b/extensions/fablabchemnitz/move_path_node/move_path_node.inx @@ -17,7 +17,7 @@ - + diff --git a/extensions/fablabchemnitz/normalize_drawing_scale/meta.json b/extensions/fablabchemnitz/normalize_drawing_scale/meta.json new file mode 100644 index 0000000..402ac9a --- /dev/null +++ b/extensions/fablabchemnitz/normalize_drawing_scale/meta.json @@ -0,0 +1,20 @@ +[ + { + "name": "Normalize Drawing Scale", + "id": "fablabchemnitz.de.normalize_drawing_scale", + "path": "laser_check", + "dependent_extensions": null, + "original_name": "Normalize Drawing Scale", + "original_id": "fablabchemnitz.de.normalize_drawing_scale", + "license": "GNU GPL v3", + "license_url": "", + "comment": "", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/normalize_drawing_scale", + "fork_url": null, + "documentation_url": "https://stadtfabrikanten.org/display/IFM/Normale+Drawing+Scale", + "inkscape_gallery_url": null, + "main_authors": [ + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/normalize_drawing_scale/normalize_drawing_scale.inx b/extensions/fablabchemnitz/normalize_drawing_scale/normalize_drawing_scale.inx new file mode 100644 index 0000000..f3a0e9b --- /dev/null +++ b/extensions/fablabchemnitz/normalize_drawing_scale/normalize_drawing_scale.inx @@ -0,0 +1,18 @@ + + + Normalize Drawing Scale + fablabchemnitz.de.normalize_drawing_scale + false + 100.0 + + all + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/normalize_drawing_scale/normalize_drawing_scale.py b/extensions/fablabchemnitz/normalize_drawing_scale/normalize_drawing_scale.py new file mode 100644 index 0000000..32e62c8 --- /dev/null +++ b/extensions/fablabchemnitz/normalize_drawing_scale/normalize_drawing_scale.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 + +import inkex +from inkex import Transform +from lxml import etree + +class NormalizeDrawingScale(inkex.EffectExtension): + + def add_arguments(self, pars): + pars.add_argument('--remove_viewbox', type=inkex.Boolean, default=True) + pars.add_argument('--target_scale', type=float, default=100.0) + + def effect(self): + format_units = inkex.units.parse_unit(self.svg.get('width'))[1] #get the "Format:" unit at "Display tab" + namedView = self.document.getroot().find(inkex.addNS('namedview', 'sodipodi')) + display_units = namedView.get(inkex.addNS('document-units', 'inkscape')) #means the "Display units:" at "Display tab" + docScale = self.svg.scale + inkscapeScale = self.svg.inkscape_scale #this is the "Scale:" value at "Display tab" + + docWidth = self.svg.get('width') + docHeight = self.svg.get('height') + + docWidth_fin = inkex.units.parse_unit(docWidth)[0] + docHeight_fin = inkex.units.parse_unit(docHeight)[0] + + vxMin, vyMin, vxMax, vyMax = self.svg.get_viewbox() + vxTotal = vxMax - vxMin + targetScale = self.options.target_scale / 100 + visualScaleX = self.svg.unittouu(str(vxTotal / self.svg.viewport_width) + display_units) + formatScaleX = self.svg.unittouu(str(vxTotal / self.svg.viewport_width) + format_units) + + docWidth_new = docWidth_fin * visualScaleX * inkscapeScale + docHeight_new = docHeight_fin * visualScaleX * inkscapeScale + + docWidth_new = docWidth_fin * targetScale / inkscapeScale + docHeight_new = docHeight_fin * targetScale / inkscapeScale + + #inkex.errormsg("format_units: " + str(format_units)) + #inkex.errormsg("display_units: " + str(display_units)) + #inkex.errormsg("docScale: {:0.6f}".format(docScale)) + #inkex.errormsg("inkscapeScale: {:0.6f}".format(inkscapeScale)) + #inkex.errormsg("docWidth_fin: {:0.3f}{}".format(docWidth_fin, format_units)) + #inkex.errormsg("docHeight_fin: {:0.3f}{}".format(docHeight_fin, format_units)) + #inkex.errormsg("vxTotal: " + str(vxTotal)) + #inkex.errormsg("docWidth_new: {:0.3f}{} ({:0.3f}px)".format(docWidth_new, format_units, self.svg.unittouu(str(docWidth_new) + format_units))) + #inkex.errormsg("docHeight_new: {:0.3f}{} ({:0.3f}px)".format(docHeight_new, format_units, self.svg.unittouu(str(docHeight_new) + format_units))) + #inkex.errormsg("targetScale: {:0.6f}".format(targetScale)) + #inkex.errormsg("visualScaleX: {:0.6f}".format(visualScaleX)) + #inkex.errormsg("formatScaleX: {:0.6f}".format(formatScaleX)) + + if inkscapeScale == targetScale: #strange rule. might break sth. + inkex.utils.debug("Nothing to do. Scale is already 100%") + return + + if visualScaleX == 0.0: #seems there is no viewBox attribute, then ... + #inkex.errormsg("viewBox attribute is missing in svg:svg. Applying new one ...") + visualScaleX = 1.0 #this is the case we deal with px as display unit and we removed the viewBox + self.svg.set('viewBox', '0 0 {} {}'.format(targetScale * docWidth_fin, targetScale * docHeight_fin)) + if round(visualScaleX, 5) != targetScale or self.options.remove_viewbox is True: + #set scale to 100% (we adjust viewBox) + sc = (1 / (targetScale / inkscapeScale)) + if self.options.remove_viewbox is False: + viewBoxNew = '0 0 {} {}'.format(docWidth_fin / targetScale, docHeight_fin / targetScale) + #inkex.errormsg("viewBox modifying to: {}".format(viewBoxNew)) + #inkex.errormsg("width modifying to: {}{}".format(docWidth_fin, format_units)) + #inkex.errormsg("height modifying to: {}{}".format(docHeight_fin, format_units)) + self.svg.set('viewBox', viewBoxNew) + self.svg.set('width', "{}{}".format(docWidth_fin, format_units)) + self.svg.set('height', "{}{}".format(docHeight_fin, format_units)) + else: + #inkex.errormsg("viewBox popping; setting back to px ...") + self.svg.pop('viewBox') + self.document.getroot().set('inkscape:document-units', 'px') + self.svg.set('width', docWidth_fin) + self.svg.set('height', docHeight_fin) + namedView.attrib[inkex.addNS('document-units', 'inkscape')] = 'px' + + translation_matrix = [[sc, 0.0, 0.0], [0.0, sc, 0.0]] + #select each top layer and apply the transformation to scale + processed = [] + for element in self.document.getroot().iter(tag=etree.Element): + if element != self.document.getroot(): + if element.tag == inkex.addNS('g','svg'): + parent = element.getparent() + if parent.get('inkscape:groupmode') != 'layer' and element.get('inkscape:groupmode') == 'layer': + element.transform = Transform(translation_matrix) @ element.composed_transform() + processed.append(element) + + #do the same for all elements which lay on first level and which are not a layer + for element in self.document.getroot().getchildren(): + if isinstance(element, inkex.ShapeElement) and element not in processed: + element.transform = Transform(translation_matrix) @ element.composed_transform() + + else: + inkex.utils.debug("Nothing to do. Scale is already 100%") + return + + +if __name__ == '__main__': + NormalizeDrawingScale().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz/ocr/.gitignore b/extensions/fablabchemnitz/ocr/.gitignore new file mode 100644 index 0000000..b6e4761 --- /dev/null +++ b/extensions/fablabchemnitz/ocr/.gitignore @@ -0,0 +1,129 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ diff --git a/extensions/fablabchemnitz/ocr/meta.json b/extensions/fablabchemnitz/ocr/meta.json new file mode 100644 index 0000000..d78dbf6 --- /dev/null +++ b/extensions/fablabchemnitz/ocr/meta.json @@ -0,0 +1,20 @@ +[ + { + "name": "OCR (Image To Text)", + "id": "fablabchemnitz.de.ocr", + "path": "ocr", + "dependent_extensions": null, + "original_name": "Image To Text", + "original_id": "org.inkscape.ocr", + "license": "Apache-2.0 License", + "license_url": "https://github.com/amal-san/inkscape-ocr/blob/main/LICENSE", + "comment": "", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/ocr", + "fork_url": "https://github.com/amal-san/inkscape-ocr", + "documentation_url": "https://stadtfabrikanten.org/pages/viewpage.action?pageId=114524275", + "inkscape_gallery_url": null, + "main_authors": [ + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/ocr/ocr.inx b/extensions/fablabchemnitz/ocr/ocr.inx new file mode 100644 index 0000000..7ab7b59 --- /dev/null +++ b/extensions/fablabchemnitz/ocr/ocr.inx @@ -0,0 +1,145 @@ + + + OCR (Image To Text) + fablabchemnitz.de.ocr + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + path + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/ocr/ocr.py b/extensions/fablabchemnitz/ocr/ocr.py new file mode 100755 index 0000000..94014a3 --- /dev/null +++ b/extensions/fablabchemnitz/ocr/ocr.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2021 Amal Santhosh , amalsanp@gmail.com + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +import inkex +import pytesseract +from PIL import Image +import cairosvg +import os + +class OcrOutputExtension(inkex.OutputExtension): + + def add_arguments(self, pars): + pars.add_argument('--lang',default='eng',help='Language') + + def effect(self): + try: + img = 'read.png' + cairosvg.svg2png(url = self.file_io.name, write_to = img) + text = pytesseract.image_to_string(Image.open(img), lang = self.options.lang) + self.msg(text.rstrip()) + os.remove('read.png') + except Exception as e: + self.msg(e) + self.msg("Image reading failed!") + return + + def save(self, stream): + pass + +if __name__ == '__main__': + OcrOutputExtension().run() diff --git a/extensions/fablabchemnitz/ocr/read.png b/extensions/fablabchemnitz/ocr/read.png new file mode 100644 index 0000000000000000000000000000000000000000..5588ed83701226e1d104aee1d265780cc782014c GIT binary patch literal 40578 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 literal 0 HcmV?d00001 diff --git a/extensions/fablabchemnitz/offset_paths/meta.json b/extensions/fablabchemnitz/offset_paths/meta.json new file mode 100644 index 0000000..5277267 --- /dev/null +++ b/extensions/fablabchemnitz/offset_paths/meta.json @@ -0,0 +1,20 @@ +[ + { + "name": "Offset Paths", + "id": "fablabchemnitz.de.offset_paths", + "path": "offset_paths", + "dependent_extensions": null, + "original_name": "Offset Paths", + "original_id": "fablabchemnitz.de.offset_paths", + "license": "GNU GPL v3", + "license_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/LICENSE", + "comment": "based on https://github.com/TimeTravel-0/ofsplot", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/offset_paths", + "fork_url": null, + "documentation_url": "https://stadtfabrikanten.org/display/IFM/Offset+Paths", + "inkscape_gallery_url": "https://inkscape.org/de/~MarioVoigt/%E2%98%85offset-paths", + "main_authors": [ + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/offset_paths/offset_paths.inx b/extensions/fablabchemnitz/offset_paths/offset_paths.inx new file mode 100644 index 0000000..3f330d2 --- /dev/null +++ b/extensions/fablabchemnitz/offset_paths/offset_paths.inx @@ -0,0 +1,80 @@ + + + Offset Paths + fablabchemnitz.de.offset_paths + + + + + + + + + + + 1 + 1.0000 + 1.0000 + 0.0000 + 3.0 + 1024 + + + + + + + + + + + + + false + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ../000_about_fablabchemnitz.svg + + + + all + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/offset_paths/offset_paths.py b/extensions/fablabchemnitz/offset_paths/offset_paths.py new file mode 100644 index 0000000..1357a32 --- /dev/null +++ b/extensions/fablabchemnitz/offset_paths/offset_paths.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 + +""" +Based on +- https://github.com/TimeTravel-0/ofsplot + +ToDo's +- break apart combined paths +- option to handle groups + +Author: Mario Voigt / FabLab Chemnitz +Mail: mario.voigt@stadtfabrikanten.org +Last Patch: 10.06.2021 +License: GNU GPL v3 + +""" + +import inkex +import math +from inkex.paths import CubicSuperPath +import re +import copy +import pyclipper + +class OffsetPaths(inkex.EffectExtension): + + def add_arguments(self, pars): + pars.add_argument('--tab') + pars.add_argument('--unit') + pars.add_argument("--offset_count", type=int, default=1, help="Number of offset paths") + pars.add_argument("--offset", type=float, default=1.000, help="Offset amount") + pars.add_argument("--init_offset", type=float, default=0.000, help="Initial Offset Amount") + pars.add_argument("--offset_increase", type=float, default=0.000, help="Offset increase between iterations") + pars.add_argument("--jointype", default="2", help="Join type") + pars.add_argument("--endtype", default="3", help="End type") + pars.add_argument("--miterlimit", type=float, default=3.0, help="Miter limit") + pars.add_argument("--clipperscale", type=int, default=1024, help="Scaling factor. Should be a multiplicator of 2, like 2^4=16 or 2^10=1024. The higher the scale factor the higher the quality.") + pars.add_argument("--copy_org", type=inkex.Boolean, default=True, help="copy original path") + pars.add_argument("--individual", type=inkex.Boolean, default=True, help="Separate into individual paths") + pars.add_argument("--group", type=inkex.Boolean, default=True, help="Put all offset paths into group") + pars.add_argument("--path_types", default="both", help="Process open, closed or all paths!") + + + def effect(self): + unit_factor = 1.0 / self.svg.uutounit(1.0, self.options.unit) + pathElements = self.svg.selection.filter(inkex.PathElement).values() + count = sum(1 for pathElement in pathElements) + pathElements = self.svg.selection.filter(inkex.PathElement).values() #we need to call this twice because the sum function consumes the generator + if count == 0: + inkex.errormsg("No paths selected.") + exit() + for pathElement in pathElements: + csp = CubicSuperPath(pathElement.get('d')) + + ''' + check for closed or open paths + ''' + isClosed = False + raw = pathElement.path.to_arrays() + if raw[-1][0] == 'Z' or \ + (raw[-1][0] == 'L' and raw[0][1] == raw[-1][1]) or \ + (raw[-1][0] == 'C' and raw[0][1] == [raw[-1][1][-2], raw[-1][1][-1]]) \ + : #if first is last point the path is also closed. The "Z" command is not required + isClosed = True + if self.options.path_types == "open_paths" and isClosed is True: + continue #skip this loop iteration + elif self.options.path_types == "closed_paths" and isClosed is False: + continue #skip this loop iteration + + scale_factor = self.options.clipperscale # 2 ** 32 = 1024 - see also https://github.com/fonttools/pyclipper/wiki/Deprecating-SCALING_FACTOR + pco = pyclipper.PyclipperOffset(self.options.miterlimit) + + JT = None #join types + if self.options.jointype == "0": + JT = pyclipper.JT_SQUARE + elif self.options.jointype == "1": + JT = pyclipper.JT_ROUND + elif self.options.jointype == "2": + JT = pyclipper.JT_MITER + + ET = None #end types + if self.options.endtype == "0": + ET = pyclipper.ET_CLOSEDPOLYGON + elif self.options.endtype == "1": + ET = pyclipper.ET_CLOSEDLINE + elif self.options.endtype == "2": + ET = pyclipper.ET_OPENBUTT + elif self.options.endtype == "3": + ET = pyclipper.ET_OPENSQUARE + elif self.options.endtype == "4": + ET = pyclipper.ET_OPENROUND + + newPaths = [] + + # load in initial paths + for subPath in csp: + sub_simple = [] + for item in subPath: + itemx = [float(z) * scale_factor for z in item[1]] + sub_simple.append(itemx) + pco.AddPath(sub_simple, JT, ET) + + # calculate offset paths for different offset amounts + offset_list = [] + offset_list.append(self.options.init_offset * unit_factor) + for i in range(0, self.options.offset_count): + ofs_increase = +math.pow(float(i) * self.options.offset_increase * unit_factor, 2) + if self.options.offset_increase < 0: + ofs_increase = -ofs_increase + offset_list.append(offset_list[0] + float(i) * self.options.offset * unit_factor + ofs_increase * unit_factor) + + solutions = [] + for offset in offset_list: + solution = pco.Execute(offset * scale_factor) + solutions.append(solution) + if len(solution) <= 0: + continue # no more loops to go, will provide no results. + + # re-arrange solutions to fit expected format & add to array + for solution in solutions: + for sol in solution: + solx = [[float(s[0]) / scale_factor, float(s[1]) / scale_factor] for s in sol] + sol_p = [[a, a, a] for a in solx] + sol_p.append(sol_p[0][:]) + if sol_p not in newPaths: + newPaths.append(sol_p) + + if self.options.individual is True: + parent = pathElement.getparent() + if self.options.group is True: parentGroup = parent.add(inkex.Group(id="g-offset-{}".format(pathElement.attrib["id"]))) + idx = parent.index(pathElement) + 1 + idSuffix = 0 + for newPath in newPaths: + copyElement = copy.copy(pathElement) + elementId = copyElement.get('id') + copyElement.path = CubicSuperPath(newPath) + copyElement.set('id', elementId + str(idSuffix)) + if self.options.group is True: + parentGroup.append(copyElement) + else: + parent.append(copyElement) + idSuffix += 1 + if self.options.group is True: parent.insert(idx, parentGroup) + if self.options.copy_org is False: + pathElement.delete() + else: + if self.options.copy_org is True: + for subPath in csp: + newPaths.append(subPath) + pathElement.set('d', CubicSuperPath(newPaths)) + +if __name__ == '__main__': + OffsetPaths().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz/open_dir/meta.json b/extensions/fablabchemnitz/open_dir/meta.json new file mode 100644 index 0000000..89ba163 --- /dev/null +++ b/extensions/fablabchemnitz/open_dir/meta.json @@ -0,0 +1,20 @@ +[ + { + "name": "Open Extension Directory", + "id": "fablabchemnitz.de.open_dir", + "path": "open_dir", + "dependent_extensions": null, + "original_name": "Open Extension Directory", + "original_id": "fablabchemnitz.de.open_dir", + "license": "GNU GPL v3", + "license_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/LICENSE", + "comment": "Written by Mario Voigt", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/open_dir", + "fork_url": null, + "documentation_url": "https://stadtfabrikanten.org/display/IFM/Open+Extension+Directory", + "inkscape_gallery_url": null, + "main_authors": [ + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/open_dir/open_dir.inx b/extensions/fablabchemnitz/open_dir/open_dir.inx new file mode 100644 index 0000000..f596de7 --- /dev/null +++ b/extensions/fablabchemnitz/open_dir/open_dir.inx @@ -0,0 +1,14 @@ + + + Open Extension Directory + fablabchemnitz.de.open_dir + + all + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/open_dir/open_dir.py b/extensions/fablabchemnitz/open_dir/open_dir.py new file mode 100644 index 0000000..3037596 --- /dev/null +++ b/extensions/fablabchemnitz/open_dir/open_dir.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 + +import subprocess +import os +import sys +import warnings +import inkex + +DETACHED_PROCESS = 0x00000008 + +class OpenExtensionDirectory(inkex.EffectExtension): + + def spawnIndependentProcess(self, args): + warnings.simplefilter('ignore', ResourceWarning) #suppress "enable tracemalloc to get the object allocation traceback" + if os.name == 'nt': + subprocess.Popen(args, close_fds=True, creationflags=DETACHED_PROCESS) + else: + subprocess.Popen(args, start_new_session=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + warnings.simplefilter("default", ResourceWarning) + + def effect(self): + extension_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..', '..') + + if os.name == 'nt': + explorer = "explorer" + else: + explorer = "xdg-open" + args = [explorer, extension_dir] + try: + self.spawnIndependentProcess(args) + except FileNotFoundError as e: + inkex.utils.debug(e) + exit(1) + +if __name__ == '__main__': + OpenExtensionDirectory().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz/paths_to_lowlevel_strokes/meta.json b/extensions/fablabchemnitz/paths_to_lowlevel_strokes/meta.json new file mode 100644 index 0000000..7270e9c --- /dev/null +++ b/extensions/fablabchemnitz/paths_to_lowlevel_strokes/meta.json @@ -0,0 +1,20 @@ +[ + { + "name": "Paths To Lowlevel Strokes", + "id": "fablabchemnitz.de.paths_to_lowlevel_strokes", + "path": "paths_to_lowlevel_strokes", + "dependent_extensions": null, + "original_name": "Paths To Lowlevel Strokes", + "original_id": "fablabchemnitz.de.paths_to_lowlevel_strokes", + "license": "GNU GPL v3", + "license_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/LICENSE", + "comment": "Created by Mario Voigt", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/paths_to_strokes", + "fork_url": null, + "documentation_url": "https://stadtfabrikanten.org/display/IFM/Paths+To+Lowlevel+Strokes", + "inkscape_gallery_url": null, + "main_authors": [ + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/paths_to_lowlevel_strokes/paths_to_lowlevel_strokes.inx b/extensions/fablabchemnitz/paths_to_lowlevel_strokes/paths_to_lowlevel_strokes.inx new file mode 100644 index 0000000..1b7ce68 --- /dev/null +++ b/extensions/fablabchemnitz/paths_to_lowlevel_strokes/paths_to_lowlevel_strokes.inx @@ -0,0 +1,20 @@ + + + Paths To Lowlevel Strokes + fablabchemnitz.de.paths_to_lowlevel_strokes + true + 0.100 + 3 + true + + path + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/paths_to_lowlevel_strokes/paths_to_lowlevel_strokes.py b/extensions/fablabchemnitz/paths_to_lowlevel_strokes/paths_to_lowlevel_strokes.py new file mode 100644 index 0000000..9d9489e --- /dev/null +++ b/extensions/fablabchemnitz/paths_to_lowlevel_strokes/paths_to_lowlevel_strokes.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 + + +from lxml import etree +import inkex +from inkex import bezier, PathElement +from inkex.paths import CubicSuperPath, Path +import copy + +class PathsToStrokes(inkex.EffectExtension): + + def add_arguments(self, pars): + pars.add_argument("--flattenbezier", type=inkex.Boolean, default=False, help="Flatten bezier curves to polylines") + pars.add_argument("--flatness", type=float, default=0.1, help="Minimum flatness = 0.1. The smaller the value the more fine segments you will get (quantization).") + pars.add_argument("--decimals", type=int, default=3) + pars.add_argument("--keep_style", type=inkex.Boolean, default=False) + + def effect(self): + + def flatten(node): + path = node.path.transform(node.composed_transform()).to_superpath() + bezier.cspsubdiv(path, self.options.flatness) + newpath = [] + for subpath in path: + first = True + for csp in subpath: + cmd = 'L' + if first: + cmd = 'M' + first = False + newpath.append([cmd, [csp[1][0], csp[1][1]]]) + node.path = newpath + + def break_contours(element, breakelements = None): + if breakelements == None: + breakelements = [] + if element.tag == inkex.addNS('path','svg'): + if self.options.flattenbezier is True: + flatten(element) + parent = element.getparent() + idx = parent.index(element) + idSuffix = 0 + raw = element.path.to_arrays() + subPaths = [] + prev = 0 + for i in range(len(raw)): # Breaks compound paths into simple paths + if raw[i][0] == 'M' and i != 0: + subPath = raw[prev:i] + subPaths.append(Path(subPath)) + prev = i + subPaths.append(Path(raw[prev:])) #finally add the last path + for subPath in subPaths: + replacedelement = copy.copy(element) + oldId = replacedelement.get('id') + csp = CubicSuperPath(subPath) + if len(subPath) > 1 and csp[0][0] != csp[0][1]: #avoids pointy paths like M "31.4794 57.6024 Z" + replacedelement.path = subPath + if len(subPaths) == 1: + replacedelement.set('id', oldId) + else: + replacedelement.set('id', oldId + str(idSuffix)) + idSuffix += 1 + parent.insert(idx, replacedelement) + breakelements.append(replacedelement) + element.delete() + for child in element.getchildren(): + break_contours(child, breakelements) + return breakelements + + if len(self.svg.selected) == 0: + elementsToWork = break_contours(self.document.getroot()) + else: + elementsToWork = None + for element in self.svg.selected.values(): + elementsToWork = break_contours(element, elementsToWork) + + for element in elementsToWork: + oldId = element.get('id') + oldStyle = element.style + path = element.path.to_absolute().to_arrays() #to_arrays() is deprecated. How to make more modern? + pathIsClosed = False + if path[-1][0] == 'Z' or \ + (path[-1][0] == 'L' and path[0][1] == path[-1][1]) or \ + (path[-1][0] == 'C' and path[0][1] == [path[-1][1][-2], path[-1][1][-1]]) \ + : #if first is last point the path is also closed. The "Z" command is not required + pathIsClosed = True + parent = element.getparent() + idx = parent.index(element) + element.delete() + + if len(path) == 2 and pathIsClosed is False: + ll = inkex.Line(id=oldId) + ll.set('x1', '{:0.{dec}f}'.format(path[0][1][0], dec=self.options.decimals)) + ll.set('y1', '{:0.{dec}f}'.format(path[0][1][1], dec=self.options.decimals)) + ll.set('x2', '{:0.{dec}f}'.format(path[1][1][0], dec=self.options.decimals)) + ll.set('y2', '{:0.{dec}f}'.format(path[1][1][1], dec=self.options.decimals)) + + if len(path) > 2 and pathIsClosed is False: + ll = inkex.Polyline(id=oldId) + points = "" + for i in range(0, len(path)): + points += '{:0.{dec}f},{:0.{dec}f} '.format(path[i][1][0], path[i][1][1], dec=self.options.decimals) + ll.set('points', points) + + if len(path) > 2 and pathIsClosed is True: + ll = inkex.Polygon(id=oldId) + points = "" + for i in range(0, len(path) - 1): + points += '{:0.{dec}f},{:0.{dec}f} '.format(path[i][1][0], path[i][1][1], dec=self.options.decimals) + ll.set('points', points) + if self.options.keep_style is True: + ll.style = oldStyle + else: + ll.style = "fill:none;stroke:#0000FF;stroke-width:" + str(self.svg.unittouu("1px")) + parent.insert(idx, ll) + +if __name__ == '__main__': + PathsToStrokes().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz/polygon_side/meta.json b/extensions/fablabchemnitz/polygon_side/meta.json new file mode 100644 index 0000000..91123e2 --- /dev/null +++ b/extensions/fablabchemnitz/polygon_side/meta.json @@ -0,0 +1,21 @@ +[ + { + "name": "Polygon Side", + "id": "fablabchemnitz.de.polygon_side", + "path": "polygon_side", + "dependent_extensions": null, + "original_name": "Polygon Side", + "original_id": "org.inkscape.polygon_side", + "license": "GNU GPL v3", + "license_url": "https://inkscape.org/de/~inklinea/%E2%98%85polygon-side", + "comment": "", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/polygon_side", + "fork_url": "https://inkscape.org/de/~inklinea/%E2%98%85polygon-side", + "documentation_url": "https://stadtfabrikanten.org/display/IFM/Polygon+Side", + "inkscape_gallery_url": null, + "main_authors": [ + "inkscape.org/inklinea", + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/polygon_side/polygon_side.inx b/extensions/fablabchemnitz/polygon_side/polygon_side.inx new file mode 100755 index 0000000..52df43c --- /dev/null +++ b/extensions/fablabchemnitz/polygon_side/polygon_side.inx @@ -0,0 +1,22 @@ + + + Polygon Side + fablabchemnitz.de.polygon_side + 3 + 25 + + + + + + path + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/polygon_side/polygon_side.py b/extensions/fablabchemnitz/polygon_side/polygon_side.py new file mode 100644 index 0000000..95209aa --- /dev/null +++ b/extensions/fablabchemnitz/polygon_side/polygon_side.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +# +# Copyright (C) [2021] [Matt Cottam], [mpcottam@raincloud.co.uk] +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# +# Create a Polygon given a number of sides and side length. +# + +import math +import inkex +from inkex import PathElement +from inkex import units +import re + +# Formula to find the circumradius ( centre to apex ) required to create +# for a given number of sectors to return desired side length + +def radius_from_side_and_sectors(side_length, sectors, found_units, unit_choice): + conversions = { + 'in': 96.0, + 'pt': 1.3333333333333333, + 'px': 1.0, + 'mm': 3.779527559055118, + 'cm': 37.79527559055118, + 'm': 3779.527559055118, + 'km': 3779527.559055118, + 'Q': 0.94488188976378, + 'pc': 16.0, + 'yd': 3456.0, + 'ft': 1152.0, + '': 1.0, # Default px + } + + # Try to convert from detected units into pixels + + if unit_choice == 2: + try: + pixel_conversion_factor = conversions[found_units] + except: + pixel_conversion_factor = 1 + + else: + pixel_conversion_factor = 1 + + radius = (side_length / (2 * (math.sin(math.pi / sectors)))) / pixel_conversion_factor + + path = svg_poly(0, 0, radius, sectors) + + return path + + +# All points of a regular polygon lie on a circle +# Calculate points on circle for given number of sides + +def svg_poly(cx, cy, radius, sectors): + x_start = cx + y_start = cy - radius + + angle = 0 + + y_start = cy / 2 + (radius * (math.sin(angle))) + x_start = cx / 2 + (radius * (math.cos(angle))) + + path = f'M {x_start} {y_start}' + + for sector in range(1, sectors + 1): + angle = (sector * math.pi) / (sectors / 2) + + y = cy / 2 + (radius * (math.sin(angle))) + x = cx / 2 + (radius * (math.cos(angle))) + + path = path + f' L {x} {y} ' + + x_start = x + y_start = y + + return path + ' z' + + +class makepoly(inkex.GenerateExtension): + + def add_arguments(self, pars): + pars.add_argument("--number_of_sides", type=int, dest="sectors", default=6) + pars.add_argument("--length_of_sides", type=float, dest="side_length", default=25) + pars.add_argument("--unit_choice", type=int, dest="unit_choice", default=25) + + container_label = 'Side Poly' + + def generate(self): + found_units = self.svg.unit + + path = radius_from_side_and_sectors(self.options.side_length, self.options.sectors, found_units, + self.options.unit_choice) + + style = {'stroke': '#000000', 'fill': 'none', 'stroke-width': str(self.svg.unittouu('1px'))} + poly_path = PathElement() + poly_path.style = style + poly_path.path = path + + yield poly_path + + +if __name__ == '__main__': + makepoly().run() diff --git a/extensions/fablabchemnitz/sine_and_lace/meta.json b/extensions/fablabchemnitz/sine_and_lace/meta.json new file mode 100644 index 0000000..28028d1 --- /dev/null +++ b/extensions/fablabchemnitz/sine_and_lace/meta.json @@ -0,0 +1,21 @@ +[ + { + "name": "Slic3r STL Input", + "id": "fablabchemnitz.de.slic3r_stl_input", + "path": "slic3r_stl_input", + "dependent_extensions": null, + "original_name": "STL Input", + "original_id": "com.github.jnweiger.inkscape.input.stl", + "license": "GNU GPL v2", + "license_url": "https://github.com/jnweiger/inkscape-input-stl/blob/master/LICENSE", + "comment": "", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/slic3r_stl_input", + "fork_url": "https://github.com/jnweiger/inkscape-input-stl", + "documentation_url": "https://stadtfabrikanten.org/display/IFM/Slic3r+STL+Input", + "inkscape_gallery_url": null, + "main_authors": [ + "github.com/jnweiger", + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/sine_and_lace/sine_and_lace.inx b/extensions/fablabchemnitz/sine_and_lace/sine_and_lace.inx new file mode 100644 index 0000000..a80f7a3 --- /dev/null +++ b/extensions/fablabchemnitz/sine_and_lace/sine_and_lace.inx @@ -0,0 +1,47 @@ + + + Sine And Lace + fablabchemnitz.de.sine_and_lace + + + 3200 + 100 + 10 + 0 + 0 + 2 + 1000 + 0 + 500 + true + false + + + + + + + path + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/sine_and_lace/sine_and_lace.py b/extensions/fablabchemnitz/sine_and_lace/sine_and_lace.py new file mode 100644 index 0000000..85d0b72 --- /dev/null +++ b/extensions/fablabchemnitz/sine_and_lace/sine_and_lace.py @@ -0,0 +1,332 @@ +#!/usr/bin/env python3 + +# eggbot_sineandlace.py +# +# Generate sinusoidal and "lace" curves. The curves are described in SVG +# along with the data necessary to regenerate them. The same data can be +# used to generate new curves which are bounded by a pair of previously +# generated curves. + +# Written by Daniel C. Newman for the Eggbot Project +# dan newman @ mtbaldy us +# Last updated 28 November 2010 +# 15 October 2010 + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from math import pi, cos, sin + +from lxml import etree +import inkex +from inkex.paths import Path + +VERSION = 1 + + +def parseDesc(str): + """ + Create a dictionary from string description + """ + + if str is None: + return {} + else: + return dict([tok.split(':') for tok in str.split(';') if len(tok)]) + + +def formatDesc(d): + """ + Format an inline name1:value1;name2:value2;... style attribute value + from a dictionary + """ + + return ';'.join([atr + ':' + str(val) for atr, val in d.iteritems()]) + + +def drawSine(cycles=8, rn=0, rm=0, nPoints=50, offset=None, + height=200, width=3200, rescale=0.98, bound1='', bound2='', fun='sine', spline=True): + """ + cycles + Number of periods to plot within the rectangle of width 'width' + + rn, rm + Start the function (on the left edge) at the value x = 2 * pi * rn / rm. + When rm = 0, function is started at x = 0. + + nPoints + The number of points to sample the function at. Since the function is + approximated using Bezier cubic splines, this isn't the number of points + to plot. + + offset + (x, y) coordinate of the lower left corner of the bounding rectangle + in which to plot the function. + + height, width + The height and width of the rectangle in which to plot the function. + Ignored when bounding functions, bound1 and bound2, are supplied. + + rescale + Multiplicative Y-scaling factor by which to rescale the plotted function + so that it does not fully reach the vertical limits of its bounds. This + aids in Eggbot plots by preventing lines from touching and overlapping. + + bound1, bound2 + Descriptions of upper and lower bounding functions by which to limit the + vertical range of the function to be plotted. + + fun + May be either 'sine' or 'lace'. + """ + + """ + A complicated way of plotting y = sin(x) + + Complicated because we wish to generate the sine wave using a + parametric representation. For plotting a single sine wave in + Cartesian coordinates, this is overkill. However, it's useful + for when we want to compress and expand the amplitude of the + sine wave in accord with upper and lower boundaries which themselves + are functions. By parameterizing everything in sight with the + same parameter s and restricting s to the range [0, 1], our life + is made much easier. + """ + if offset is None: + offset = [0, 0] + + bounded = False + + if bound1 and bound2: + + func = parseDesc(bound1) + if len(func) == 0: + return None, None + m1 = int(func['rm']) + if m1 == 0: + x_min1 = 0.0 + else: + x_min1 = 2 * pi * float(func['rn']) / float(m1) + x_max1 = x_min1 + 2 * pi * float(func['cycles']) + y_min1 = -1.0 + y_max1 = 1.0 + y_scale1 = float(func['height']) / (y_max1 - y_min1) + y_offset1 = float(func['y']) + Y1s = lambda s: y_offset1 - y_scale1 * sin(x_min1 + (x_max1 - x_min1) * s) + + func = parseDesc(bound2) + if len(func) == 0: + return None, None + m2 = int(func['rm']) + if m2 == 0: + x_min2 = 0.0 + else: + x_min2 = 2 * pi * float(func['rn']) / float(m2) + x_max2 = x_min2 + 2 * pi * float(func['cycles']) + y_min2 = -1.0 + y_max2 = 1.0 + y_scale2 = float(func['height']) / (y_max2 - y_min2) + y_offset2 = float(func['y']) + Y2s = lambda s: y_offset2 - y_scale2 * sin(x_min2 + (x_max2 - x_min2) * s) + + bounded = True + + rescale = float(rescale) + x_offset = float(offset[0]) + y_offset = float(offset[1]) + + # Each cycle is 2pi + r = 2 * pi * float(cycles) + if (int(rm) == 0) or (int(rn) == 0): + x_min = 0.0 + else: + x_min = 2 * pi * float(rn) / float(rm) + x_max = x_min + r + x_scale = float(width) / r # width / ( x_max - x_min ) + + y_min = -1.0 + y_max = 1.0 + y_scale = float(height) / (y_max - y_min) + + # Our parametric equations which map the results to our drawing window + # Note the "-y_scale" that's because in SVG, the y-axis runs "backwards" + if not fun: + fun = 'sine' + fun = fun.lower() + if fun == 'sine': + Xs = lambda s: x_offset + x_scale * (x_max - x_min) * s + Ys = lambda s: y_offset - y_scale * sin(x_min + (x_max - x_min) * s) + dYdXs = lambda s: -y_scale * cos(x_min + (x_max - x_min) * s) / x_scale + elif fun == 'lace': + Xs = lambda s: x_offset + x_scale * ((x_max - x_min) * s + 2 * sin(2 * s * (x_max - x_min) + pi)) + dXs = lambda s: x_scale * (x_max - x_min) * (1.0 + 4.0 * cos(2 * s * (x_max - x_min) + pi)) + Ys = lambda s: y_offset - y_scale * sin(x_min + (x_max - x_min) * s) + dYs = lambda s: -y_scale * cos(x_min + (x_max - x_min) * s) * (x_max - x_min) + dYdXs = lambda s: dYs(s) / dXs(s) + else: + inkex.errormsg('Unknown function {0} specified'.format(fun)) + return + + # Derivatives: remember the chain rule.... + # dXs = lambda s: x_scale * ( x_max - x_min ) + # dYs = lambda s: -y_scale * cos( x_min + ( x_max - x_min ) * s ) * ( x_max - x_min ) + + # x_third is 1/3 the step size + nPoints = int(nPoints) + + # x_third is 1/3 the step size; note that Xs(1) - Xs(0) = x_scale * ( x_max - x_min ) + x_third = (Xs(1.0) - Xs(0.0)) / float(3 * (nPoints - 1)) + + if bounded: + y_upper = Y2s(0.0) + y_lower = Y1s(0.0) + y_offset = 0.5 * (y_upper + y_lower) + y_upper = y_offset + rescale * (y_upper - y_offset) + y_lower = y_offset + rescale * (y_lower - y_offset) + y_scale = (y_upper - y_lower) / (y_max - y_min) + + x1 = Xs(0.0) + y1 = Ys(0.0) + dx1 = 1.0 + dy1 = dYdXs(0.0) + + # Starting point in the path is ( x, sin(x) ) + path_data = [] + path_data.append(['M', [x1, y1]]) + + for i in range(1, nPoints): + + s = float(i) / float(nPoints - 1) + if bounded: + y_upper = Y2s(s) + y_lower = Y1s(s) + y_offset = 0.5 * (y_upper + y_lower) + y_upper = y_offset + rescale * (y_upper - y_offset) + y_lower = y_offset + rescale * (y_lower - y_offset) + y_scale = (y_upper - y_lower) / (y_max - y_min) + + x2 = Xs(s) + y2 = Ys(s) + dx2 = 1.0 + dy2 = dYdXs(s) + if dy2 > 10.0: + dy2 = 10.0 + elif dy2 < -10.0: + dy2 = -10.0 + + # Add another segment to the plot + if spline: + path_data.append(['C', + [x1 + (dx1 * x_third), + y1 + (dy1 * x_third), + x2 - (dx2 * x_third), + y2 - (dy2 * x_third), + x2, y2]]) + else: + path_data.append(['L', [x1, y1]]) + path_data.append(['L', [x2, y2]]) + x1 = x2 + y1 = y2 + dx1 = dx2 + dy1 = dy2 + + path_desc = \ + 'version:{0:d};style:linear;function:sin(x);'.format(VERSION) + \ + 'cycles:{0:f};rn:{1:d};rm:{2:d};points:{3:d};'.format(cycles, rn, rm, nPoints) + \ + 'width:{0:d};height:{1:d};x:{2:d};y:{3:d}'.format(width, height, offset[0], offset[1]) + + return path_data, path_desc + + +class SineAndLace(inkex.EffectExtension): + nsURI = 'http://sample.com/ns' + nsPrefix = 'doof' + + def add_arguments(self, pars): + pars.add_argument("--tab", help="The active tab when Apply was pressed") + pars.add_argument('--fCycles', type=float, default=10.0, help='Number of cycles (periods)') + pars.add_argument('--nrN', type=int, default=0, help='Start x at 2 * pi * n / m') + pars.add_argument('--nrM', type=int, default=0, help='Start x at 2 * pi * n / m') + pars.add_argument('--fRecess', type=float, default=2.0, help='Recede from envelope by factor') + pars.add_argument("--nSamples", type=int, default=50.0, help="Number of points to sample") + pars.add_argument("--nWidth", type=int, default=3200, help="Width in pixels") + pars.add_argument("--nHeight", type=int, default=100, help="Height in pixels") + pars.add_argument("--nOffsetX", type=int, default=0, help="Starting x coordinate (pixels)") + pars.add_argument("--nOffsetY", type=int, default=400, help="Starting y coordinate (pixels)") + pars.add_argument('--bLace', type=inkex.Boolean, default=False, help='Lace') + pars.add_argument('--bSpline', type=inkex.Boolean, default=True, help='Spline') + + self.recess = 0.95 + + def effect(self): + + inkex.NSS[self.nsPrefix] = self.nsURI + + if self.options.bLace: + func = 'lace' + else: + func = 'sine' + + f_recess = 1.0 + if self.options.fRecess > 0.0: + f_recess = 1.0 - self.options.fRecess / 100.0 + if f_recess <= 0.0: + f_recess = 0.0 + + if self.options.ids: + if len(self.options.ids) == 2: + desc1 = self.selected[self.options.ids[0]].get(inkex.addNS('desc', self.nsPrefix)) + desc2 = self.selected[self.options.ids[1]].get(inkex.addNS('desc', self.nsPrefix)) + if (not desc1) or (not desc2): + inkex.errormsg('Selected objects do not smell right') + return + path_data, path_desc = drawSine(self.options.fCycles, + self.options.nrN, + self.options.nrM, + self.options.nSamples, + [self.options.nOffsetX, self.options.nOffsetY], + self.options.nHeight, + self.options.nWidth, + f_recess, + desc1, desc2, func, self.options.bSpline) + else: + inkex.errormsg('Exactly two objects must be selected') + return + else: + self.document.getroot().set(inkex.addNS(self.nsPrefix, 'xmlns'), self.nsURI) + + path_data, path_desc = drawSine(self.options.fCycles, + self.options.nrN, + self.options.nrM, + self.options.nSamples, + [self.options.nOffsetX, self.options.nOffsetY], + self.options.nHeight, + self.options.nWidth, + f_recess, + '', + '', + func, + self.options.bSpline) + + style = {'stroke': 'black', 'stroke-width': '1', 'fill': 'none'} + path_attrs = { + 'style': str(inkex.Style(style)), + 'd': str(Path(path_data)), + inkex.addNS('desc', self.nsPrefix): path_desc} + newpath = etree.SubElement(self.document.getroot(), + inkex.addNS('path', 'svg'), path_attrs, nsmap=inkex.NSS) + + +if __name__ == '__main__': + SineAndLace().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz/spirograph/inkscapeMadeEasy/inkscapeMadeEasy_Base.py b/extensions/fablabchemnitz/spirograph/inkscapeMadeEasy/inkscapeMadeEasy_Base.py new file mode 100644 index 0000000..efeeb98 --- /dev/null +++ b/extensions/fablabchemnitz/spirograph/inkscapeMadeEasy/inkscapeMadeEasy_Base.py @@ -0,0 +1,1307 @@ +#!/usr/bin/python + +# ----------------------------------------------------------------------------- +# +# inkscapeMadeEasy: - Helper module that extends Aaron Spike's inkex.py module, +# focusing productivity in inkscape extension development +# +# Copyright (C) 2016 by Fernando Moura +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# ----------------------------------------------------------------------------- + +import math +import os +import re +import sys +from copy import deepcopy + +import numpy as np +from lxml import etree + +import inkex + + +class inkscapeMadeEasy(inkex.Effect): + + def __init__(self): + inkex.Effect.__init__(self) + self.inkscapeResolution_dpi = 96.0 # number of pixels per inch + + resolution_in = self.inkscapeResolution_dpi + resolution_mm = self.inkscapeResolution_dpi / 25.4 + + self.unitsDict = {'mm': resolution_mm, # 25.4mm per inch + 'cm': resolution_mm * 10.0, # 1cm = 10mm + 'm': resolution_mm * 1.0e3, # 1m = 1000mm + 'km': resolution_mm * 1.0e6, # 1km = 1e6mm + 'in': resolution_in, # 1in = 96px + 'ft': resolution_in * 12.0, # foot = 12*in + 'yd': resolution_in * 12.0 * 3.0, # yard = 3*ft + 'pt': resolution_in / 72.0, # point 1pt = 1/72th of an inch + 'px': 1.0, 'pc': resolution_in / 6.0} # picas 1pc = 1/6th of and inch + + self.blankSVG = """ + + + + + + + image/svg+xml + + + + + + + + """ + # --------------------------------------------- + def bool(self,valueStr): + """ + ArgParser function to turn a boolean string into a python boolean + + :param valueStr: string representing a boolean. Valid values: 'true','false' with any letter capitalization + :type valueStr: string + + :returns: boolean value + :rtype: bool + + .. note:: This function was copied from inkex.utils.py to avoid having to import inkex.py in your project just to use inkex.Boolean in ``arg_parser.add_argument``. You can pass this function in ``arg_parser.add_argument`` method when dealing with boolean values. See :ref:`minimalExample` section for a good example. + + **Example** + + In your ``__init__`` function, ``arg_parser.add_argument`` requires a callable to convert string to bool when dealing with bool variables. See :ref:`minimalExample` section for a good example. + + >>> self.arg_parser.add_argument("--boolVariable", type=self.bool, dest="boolVariable", default=False) + + """ + if valueStr.upper() == 'TRUE': + return True + elif valueStr.upper() == 'FALSE': + return False + return None + + # --------------------------------------------- + def displayMsg(self, msg): + """Display a message to the user. + + :param msg: message + :type msg: string + + :returns: nothing + :rtype: - + + """ + sys.stderr.write(msg + '\n') + + # --------------------------------------------- + def getBasicLatexPackagesFile(self): + """Return the full path of the ``basicLatexPackages.tex`` file with commonly used Latex packages + + The default contents of the ``basicLatexPackages.tex`` is:: + + \\usepackage{amsmath,amsthm,amsbsy,amsfonts,amssymb} + \\usepackage[per=slash]{siunitx} + \\usepackage{steinmetz} + + :returns: Full path of the file with commonly used Latex packages + :rtype: string + + .. note:: You can add other packages to the file ``basicLatexPackages.tex``. + + """ + directory = os.getcwd() + return os.path.abspath(directory + '/../inkscapeMadeEasy/basicLatexPackages.tex') + + # --------------------------------------------- + def Dump(self, obj, file='./dump_file.txt', mode='w'): + """Function to easily output the result of ``str(obj)`` to a file + + :param obj: python object to sent to a file. Any object can be used, as long as ``str(obj)`` is implemented (see ``__str__()`` metaclass definition of your object) + :param file: file path. Default: ``./dump_file.txt`` + :param mode: writing mode of the file Default: ``w`` (write) + :type obj: any + :type file: string + :type mode: string + :returns: nothing + :rtype: - + + .. note:: This function was created to help debugging the code while it is running under inkscape. Since inkscape does not possess a terminal as today (2016), this function overcomes partially the issue of sending things to stdout by dumping result of the function ``str(obj)`` in a text file. + + **Example** + + >>> vector1=[1,2,3,4,5,6] + >>> self.Dump(vector1,file='~/temporary.txt',mode='w') # writes the list to a file + >>> vector2=[7,8,9,10] + >>> self.Dump(vector2,file='~/temporary.txt',mode='a') # append the list to a file + """ + with open(file, mode) as file: + file.write(str(obj) + '\n') + + # --------------------------------------------- + def removeElement(self, element): + """Remove one element (can be a gropu) of the document. + + If the parent of the removed element is a group and has no other children, then the parent group is also removed. + + :param element: inkscape element object to be removed. If the element is a group, then all its chidren are also removed. + :type element: inkscape element object + :returns: nothing + :rtype: - + + **Example** + + >>> rootLayer = self.document.getroot() # retrieves the root layer of the file + >>> groupA = self.createGroup(rootLayer,label='temp') # creates a group inside rootLayer + >>> line1 = inkDraw.line.relCoords(groupA, [[5,0]],[0,0]) # creates a line in groupA + >>> line2 = inkDraw.line.relCoords(rootLayer, [[5,0]],[0,0]) # creates a line in rootLayer + >>> line3 = inkDraw.line.relCoords(groupA, [[15,0]],[10,0]) # creates a line in groupA + >>> self.removeElement(line1) # removes line 1 + >>> self.removeElement(line2) # removes line 2 + >>> self.removeElement(line3) # removes line 3. Also removes groupA since this group has no other children + >>> groupB = self.createGroup(rootLayer,label='temp1') # creates a group inside rootLayer + >>> line4 = inkDraw.line.relCoords(groupB, [[5,0]],[0,0]) # creates a line in groupB + >>> self.removeElement(groupB) # removes group B and all its children + """ + + parent = element.getparent() + + parent.remove(element) + + if parent.tag == 'g' and len(parent.getchildren()) == 0: # if object's parent is a group and has no other children, remove parent too + temp = parent.getparent() + if temp is not None: + temp.remove(parent) + + # --------------------------------------------- + def importSVG(self, parent, fileIn, createGroup=True): + """ Import SVG file into the current document + + This function will all unify the defs node via :meth:`unifyDefs` + + :param parent: parent element where all contents will be placed + :param fileIn: SVG file path + :param createGroup: create a group containing all imported elements. (Default: True) + :type parent: inkscape element object + :type fileIn: string + :type createGroup: bool + :returns: imported element objects. If createGroup==True, returns the group. Otherwise returns a list with all imported elements + :rtype: inkscape element object or list of objects + + **Example** + + >>> rootLayer = self.document.getroot() # retrieves the root layer of the file + >>> imported1 = self.importSVG(rootLayer,'/path/to/file1.svg',True) # import contents of the file and group them. imported1 is the group element + >>> imported2 = self.importSVG(rootLayer,'/path/to/file2.svg',False) # import contents of the file. imported2 is a list of the imported elements + + """ + documentIn = etree.parse(fileIn, parser=etree.XMLParser(huge_tree=True)).getroot() + + if createGroup: + group = self.createGroup(parent, label='importedSVG') + for elem in documentIn: + if elem.tag != inkex.addNS('namedview', 'sodipodi') and elem.tag != inkex.addNS('metadata', 'svg'): + group.append(elem) + self.unifyDefs() + return group + else: + listElements=[] + for elem in documentIn: + if elem.tag != inkex.addNS('namedview', 'sodipodi') and elem.tag != inkex.addNS('metadata', 'svg'): + parent.append(elem) + if elem.tag != inkex.addNS('defs', 'svg'): + listElements.append(elem) + self.unifyDefs() + return listElements + + # --------------------------------------------- + def exportSVG(self, element, fileOut): + """ Export the element (or list of elements) in a new svgfile. + + This function will export the element (or list of elements) to a new SVG file. If a list of elements is passed as argument, all elements in the list will be exported to the same file. + + :param element: element or list of elements to be exported + :param fileOut: file path, including the extension. + :type element: inkscape element object or list of inkscape element objects + :type file: string + :returns: nothing + :rtype: - + + .. note:: Currently (2020), all the defs of the original file will be copied to the new file. Therefore you might want to run the vacuum tool to cleanup the new SVG file ``File > Clean um document`` + + **Example** + + >>> rootLayer = self.document.getroot() # retrieves the root layer of the file + >>> groupA = self.createGroup(rootLayer,label='temp') # creates a group inside rootLayer + >>> groupB = self.createGroup(rootLayer,label='child') # creates a group inside groupA + >>> line1 = inkDraw.line.relCoords(groupA, [[10,0]],[0,0]) # creates a line in groupA + >>> line2 = inkDraw.line.relCoords(groupB, [[20,0]],[0,0]) # creates a line in groupB + >>> self.exportSVG(line1,'path/to/file1.svg') # exports only line1 + >>> self.exportSVG(groupA,'path/to/file2.svg') # exports groupA (and all elements it contais) + >>> self.exportSVG([groupA,groupB],'path/to/file3.svg') # exports groupA and groupB (and all elements they contain) to the same file + + """ + document = etree.fromstring(self.blankSVG.encode('ascii')) + + elem_tmp = deepcopy(element) + # add definitions + defs_tmp = deepcopy(self.getDefinitions()) + document.append(defs_tmp) + + # add elements + if isinstance(elem_tmp, list): + for e in elem_tmp: + document.append(e) + else: + document.append(elem_tmp) + + et = etree.ElementTree(document) + et.write(fileOut, pretty_print=True) + + # --------------------------------------------- + def uniqueIdNumber(self, prefix_id): + """ Generate an unique element ID number with a given prefix ID by adding a numeric suffix + + This function is used to generate a valid unique ID by concatenating a given prefix with a numeric suffix. The overall format is ``prefix-%05d``. + + This function makes sure the ID is unique by checking in ``doc_ids`` member. This function is specially useful for creating an unique ID for markers and other elements in defs. + + :param prefix_id: prefix of the ID + :type prefix_id: string + :returns: the unique ID + :rtype: string + + .. note:: This function has been adapted from inkex.py. However it uses an incremental number method + + **Example** + + >>> a=self.uniqueIdNumber('myName') # a=myName-00001 + >>> b=self.uniqueIdNumber('myName') # b=myName-00002, because myName-00001 is already in use + >>> c=self.uniqueIdNumber('myName') # c=myName-00003, because myName-00001 and myName-00002 are already in use + >>> d=self.uniqueIdNumber('myNameX') # d=myNameX-00001 + + + """ + numberID = 1 + new_id = prefix_id + '-%05d' % numberID + while new_id in self.get_ids(): + numberID += 1 + new_id = prefix_id + '-%05d' % numberID + self.svg.get_ids().add(new_id) + + return new_id + + # --------------------------------------------- + def getDefinitions(self): + """ Return the element of the svg file. + + This function returns the principal element of the current svg file. + + if no can be found, a new empty is created + + :returns: the defs element + :rtype: inkscape element object + + """ + defs = self.getElemFromXpath('/svg:svg//svg:defs') + if defs is None: + defs = etree.SubElement(self.document.getroot(), inkex.addNS('defs', 'svg')) + + return defs + + # --------------------------------------------- + def unifyDefs(self): + """Unify all nodes in a single node. + + :returns: None + :rtype: - + + .. warning:: This function does not check whether the ids are unique! + """ + root = self.getElemFromXpath('/svg:svg') + mainDef = self.getDefinitions() + + for d in root.findall('.//svg:defs', namespaces=inkex.NSS): + if d != mainDef: + for child in d: + mainDef.append(child) + if child.tag == inkex.addNS('g', 'svg') or child.tag == 'g': + self.ungroup(child) + d.getparent().remove(d) + + # --------------------------------------------- + def getDefsByTag(self, tag='marker'): + """ Return a list of elements in of a given a tag. + + :param tag: tag of the element + :type tag: string + + :returns: a list with the def elements + :rtype: list of inkscape elements + + """ + + return self.getDefinitions().findall('.//svg:%s' % tag, namespaces=inkex.NSS) + + # --------------------------------------------- + def getDefsById(self,id): + """ Return a list of elements in of a given (part of) the id + + :param id: (part of the id of the element) + :type tag: string + + :returns: a list with the def elements + :rtype: list of inkscape elements + + """ + + return self.getDefinitions().xpath('./*[contains(@id,"%s")]' % id) + + # --------------------------------------------- + def getElemFromXpath(self, xpath): + """ Return the element from the xml, given its xpath + + :param xpath: xpath of the element to be searched + :type xpath: string + :returns: inkscape element object + :rtype: inkscape element object + + **Example** + + >>> name = self.getElemFromXpath('/svg:svg//svg:defs') # returns the list of definitions of the document + + """ + return self.svg.getElement(xpath) + + # --------------------------------------------- + def getElemAttrib(self, elem, attribName): + """ Return the atribute of one element, given the atribute name + + :param elem: element under consideration + :param attribName: attribute to be searched. Format: namespace:attrName + :type elem: inkscape element object + :type attribName: string + :returns: attribute + :rtype: string + + **Example** + + >>> elem= self.getElemFromXpath('/svg:svg') # first get the element. In this example, the entire document + >>> docNAme = self.getElemAttrib(elem,'sodipodi:docname') # now get the name of the document, an attribute of svg:svg + """ + # splits namespace and attrib name + atribList = attribName.split(':') + + if len(atribList) == 1: # if has no namespace + attrib = attribName + else: # if has namespace + namespace = inkex.NSS[atribList[0]] + attrib = '{%s}' % namespace + atribList[1] + + return elem.attrib[attrib] + + # --------------------------------------------- + def getDocumentScaleFactor(self): + """Return the scale factor of the document. + + The scale factor is defined as + + .. math:: S=\\frac{\\text{document width}}{\\text{viewbox width}} + + **Example** + + >>> scale = self.getDocumentScaleFactor() + """ + + try: + elem = self.getElemFromXpath('/svg:svg') + width = float(self.getElemAttrib(elem, 'width').replace(self.documentUnit, '')) + + viewBox = self.getElemFromXpath('/svg:svg') + viewBox_width = float(self.getElemAttrib(viewBox, 'viewBox').split(' ')[2]) + + doc_scale = viewBox_width / width + except: + doc_scale = 1.0 + + return doc_scale + + # --------------------------------------------- + def getDocumentName(self): + """Return the name of the document + + :returns: fileName + :rtype: string + + **Example** + + >>> name = self.getDocumentName() + + """ + elem = self.getElemFromXpath('/svg:svg') + try: + fileName = self.getElemAttrib(elem, 'sodipodi:docname') + except: + fileName = None + return fileName + + # --------------------------------------------- + def getDocumentUnit(self): + """Return the unit of the document + + :returns: unit string code. See table below + :rtype: string + + **Units** + + The list of available units are: + + ================== ============ ============= + Name string code relation + ================== ============ ============= + millimetre mm 1in = 25.4mm + centimetre cm 1cm = 10mm + metre m 1m = 100cm + kilometre km 1km = 1000m + inch in 1in = 96px + foot ft 1ft = 12in + yard yd 1yd = 3ft + point pt 1in = 72pt + pixel px + pica pc 1in = 6pc + ================== ============ ============= + + **Example** + + >>> docunit = self.getDocumentUnit() #returns 'cm', 'mm', etc. + """ + elem = self.getElemFromXpath('/svg:svg/sodipodi:namedview') + try: + unit = self.getElemAttrib(elem, 'inkscape:document-units') + except: + unit = 'px' + return unit + + # --------------------------------------------- + def getcurrentLayer(self): + """Return the current layer of the document + + :returns: Name of the current layer + :rtype: string + + **Example** + + >>> name = self.getcurrentLayer() + """ + return self.svg.get_current_layer() + + # --------------------------------------------- + def abs2relPath(self, element): + abspath = self.getElemAttrib(element, 'sodipodi:absref') + fileName = os.path.basename(abspath) + + # removes sodipodi:absref attribute + namespace = inkex.NSS['sodipodi'] + attrib = '{%s}' % namespace + 'absref' + + element.attrib.pop(attrib, None) + + # adds sodipodi:relref + attrib = '{%s}' % namespace + 'relref' + element.set(attrib, fileName) + + # --------------------------------------------- + def unit2userUnit(self, value, unit_in): + """Convert a value from given unit to inkscape's default unit (px) + + :param value: value to be converted + :param unit_in: input unit string code. See table below + :type value: float + :type unit_in: string + :returns: converted value + :rtype: float + + **Units** + + The list of available units are: + + ================== ============ ============= + Name string code relation + ================== ============ ============= + millimetre mm 1in = 25.4mm + centimetre cm 1cm = 10mm + metre m 1m = 100cm + kilometre km 1km = 1000m + inch in 1in = 96px + foot ft 1ft = 12in + yard yd 1yd = 3ft + point pt 1in = 72pt + pixel px + pica pc 1in = 6pc + ================== ============ ============= + + **Example** + + >>> x_cm = 5.0 + >>> x_px = self.unit2userUnit(x_cm,'cm') # converts 5.0cm -> 188.97px + """ + + return value * self.unitsDict[unit_in.lower()] + + # --------------------------------------------- + def userUnit2unit(self, value, unit_out): + """Convert a value from inkscape's default unit (px) to specified unit + + :param value: value to be converted + :param unit_out: output unit string code. See table below + :type value: float + :type unit_out: string + :returns: converted value + :rtype: float + + **Units** + + The list of available units are: + + ================== ============ ============= + Name string code relation + ================== ============ ============= + millimetre mm 1in = 25.4mm + centimetre cm 1cm = 10mm + metre m 1m = 100cm + kilometre km 1km = 1000m + inch in 1in = 96px + foot ft 1ft = 12in + yard yd 1yd = 3ft + point pt 1in = 72pt + pixel px + pica pc 1in = 6pc + ================== ============ ============= + + **Example** + + >>> x_px = 5.0 + >>> x_cm = self.userUnit2unit(x_px,'cm') # converts 5.0px -> 0.1322cm + """ + return value / float(self.unitsDict[unit_out.lower()]) + + # --------------------------------------------- + def unit2unit(self, value, unit_in, unit_out): + """Convert a value from one unit to another unit + + :param value: value to be converted + :param unit_in: input unit string code. See table below + :param unit_out: output unit string code. See table below + :type value: float + :type unit_in: string + :type unit_out: string + :returns: converted value + :rtype: float + + **Units** + + The list of available units are: + + ================== ============ ============= + Name string code relation + ================== ============ ============= + millimetre mm 1in = 25.4mm + centimetre cm 1cm = 10mm + metre m 1m = 100cm + kilometre km 1km = 1000m + inch in 1in = 96px + foot ft 1ft = 12in + yard yd 1yd = 3ft + point pt 1in = 72pt + pixel px + pica pc 1in = 6pc + ================== ============ ============= + + **Example** + + >>> x_in = 5.0 + >>> x_cm = self.unit2unit(x_in,'in','cm') # converts 5.0in -> 12.7cm + """ + return value * self.unitsDict[unit_in.lower()] / float(self.unitsDict[unit_out.lower()]) + + # --------------------------------------------- + def createGroup(self, parent, label=None): + """Create a new empty group of elements. + + This function creates a new empty group of elements. To create new elements inside this groups you must create them informing the group as the parent element. + + :param parent: parent object of the group. It can be another group or the root element + :param label: label of the group. Default: ``None``. + The label does not have to be unique + :type parent: inkscape element object + :type label: string + :returns: the group object + :rtype: group element + + **Example** + + >>> rootLayer = self.document.getroot() # retrieves the root layer of the file + >>> groupA = self.createGroup(rootLayer,label='temp') # creates a group inside rootLayer + >>> groupB = self.createGroup(groupA,label='child') # creates a group inside groupA + >>> line1 = inkDraw.line.relCoords(groupA, [[10,0]],[0,0]) # creates a line in groupA + >>> line2 = inkDraw.line.relCoords(groupB, [[20,0]],[0,0]) # creates a line in groupB + + """ + if label is not None: + g_attribs = {inkex.addNS('label', 'inkscape'): label} + group = etree.SubElement(parent, 'g', g_attribs) + else: + group = etree.SubElement(parent, 'g') + + return group + + # --------------------------------------------- + def ungroup(self, group): + """Ungroup elements + + The new parent element of the ungrouped elements will be the parent of the removed group. See example below + + :param group: group to be removed + :type group: group element + :returns: list of the elements previously contained in the group + :rtype: list of inkscape object elements + + **Example** + + + >>> rootLayer = self.document.getroot() # retrieves the root layer of the file + >>> groupA = self.createGroup(rootLayer,label='temp') # creates a group inside rootLayer + >>> groupB = self.createGroup(groupA,label='temp') # creates a group inside groupA + >>> line1 = inkDraw.line.relCoords(groupA, [[10,0]],[0,0]) # creates a line in groupA + >>> line2 = inkDraw.line.relCoords(groupB, [[20,0]],[0,0]) # creates a line in groupB + >>> line3 = inkDraw.line.relCoords(groupB, [[30,0]],[0,0]) # creates a line in groupB + >>> # at this point, the file struct is: rootLayer[groupA[ line1, groupB[ line2, line3 ] ]] + >>> elemList = self.ungroup(groupB) # ungroup line2 and line3. elemList is a list containing line2 and line3 elements. + >>> # now the file struct is: rootLayer[groupA[ line1, line2, line3 ]] + """ + + if group.tag == 'g' or group.tag == inkex.addNS('g', 'svg'): # if object is a group + parent = group.getparent() + + listElem=[] + if parent is not None: + for child in group: + parent.append(child) + listElem.append(child) + + self.removeElement(group) + + return listElem + + # --------------------------------------------- + def getTransformMatrix(self, element): + """Return the transformation attribute of the given element and the resulting 3x3 transformation matrix (numpy Array) + + This function is used to extract the transformation operator of a given element. + + :param element: element object with the transformation matrix + :type element: inkscape element object + :returns: list [transfAttrib, transfMatrix] + + - transfAttrib: string containing all transformations as it is in the file + - transfMatrix: numpy array with the resulting 3x3 transformation matrix + :rtype: tuple + + .. note :: If the element does not have any transformation attribute, this function returns: + - transfAttrib='' (empty string) + - transfMatrix= 3x3 identity matrix + """ + + transfAttrib = '' + transfMatrix = np.eye(3) + + if 'transform' in element.attrib: + transfAttrib = element.attrib['transform'] + + if not transfAttrib: + return transfAttrib, transfMatrix + + # split operation into several strings + listOperations = [e + ')' for e in transfAttrib.replace(',', ' ').split(')') if e != ""] + + for operation in listOperations: + if 'translate' in operation: + data = re.compile(r"translate\((.*?\S)\)").match(operation.lstrip()).group(1).split() # retrieves x and y values + x = float(data[0]) + y = float(data[1]) + mat = np.array([[1, 0, x], [0, 1, y], [0, 0, 1]]) + transfMatrix = np.dot(transfMatrix, mat) + + if 'scale' in operation: + data = re.compile(r"scale\((.*?\S)\)").match(operation.lstrip()).group(1).split() # retrieves x and y values + scalex = float(data[0]) + if len(data) == 2: + scaley = float(data[1]) + else: + scaley = scalex + mat = np.diag([scalex, scaley, 1]) + transfMatrix = np.dot(transfMatrix, mat) + + if 'rotate' in operation: + data = re.compile(r"rotate\((.*?\S)\)").match(operation.lstrip()).group(1).split() # retrieves x and y values + angleRad = -float(data[0]) * np.pi / 180.0 # negative angle because inkscape is upside down =( + matRot = np.array([[np.cos(angleRad), np.sin(angleRad), 0], [-np.sin(angleRad), np.cos(angleRad), 0], [0, 0, 1]]) + if len(data) == 3: # must translate before and after rotation + x = float(data[1]) + y = float(data[2]) + matBefore = np.array([[1, 0, x], [0, 1, y], [0, 0, 1]]) # translation before rotation + matAfter = np.array([[1, 0, -x], [0, 1, -y], [0, 0, 1]]) # translation after rotation + matRot = np.dot(matBefore, matRot) + matRot = np.dot(matRot, matAfter) + + transfMatrix = np.dot(transfMatrix, matRot) + + if 'skewX' in operation: + data = re.compile(r"skewX\((.*?\S)\)").match(operation.lstrip()).group(1).split() # retrieves x and y values + angleRad = float(data[0]) * np.pi / 180.0 + mat = np.array([[1, np.tan(angleRad), 0], [0, 1, 0], [0, 0, 1]]) + transfMatrix = np.dot(transfMatrix, mat) + + if 'skewY' in operation: + data = re.compile(r"skewY\((.*?\S)\)").match(operation.lstrip()).group(1).split() # retrieves x and y values + angleRad = float(data[0]) * np.pi / 180.0 + mat = np.array([[1, 0, 0], [np.tan(angleRad), 1, 0], [0, 0, 1]]) + transfMatrix = np.dot(transfMatrix, mat) + + if 'matrix' in operation: + data = re.compile(r"matrix\((.*?\S)\)").match(operation.lstrip()).group(1).split() # retrieves x and y values + a = float(data[0]) + b = float(data[1]) + c = float(data[2]) + d = float(data[3]) + e = float(data[4]) + f = float(data[5]) + mat = np.array([[a, c, e], [b, d, f], [0, 0, 1]]) + transfMatrix = np.dot(transfMatrix, mat) + + return transfAttrib, transfMatrix + + # --------------------------------------------- + def rotateElement(self, element, center, angleDeg): + """apply a rotation to the element using the transformation matrix attribute. + + It is possible to rotate isolated elements or groups. + + :param element: element object to be rotated + :param center: center point of rotation + :param angleDeg: angle of rotation in degrees, counter-clockwise direction + :type element: inkscape element object + :type center: list + :type angleDeg: float + :returns: nothing + :rtype: - + + **Example** + + >>> rootLayer = self.document.getroot() # retrieves the root layer of the file + >>> groupA = self.createGroup(rootLayer,label='temp') # creates a group inside rootLayer + >>> line1 = inkDraw.line.relCoords(groupA, [[5,0]],[0,0]) # creates a line in groupA + >>> line2 = inkDraw.line.relCoords(rootLayer, [[5,0]],[0,0]) # creates a line in rootLayer + >>> self.rotateElement(line2,[0,0],120) # rotates line2 120 degrees around center x=0,y=0 + >>> self.rotateElement(groupA,[1,1],-90) # rotates groupA -90 degrees around center x=1,y=1 + """ + transfString = '' + + if angleDeg == 0: + return + + if 'transform' in element.attrib: + transfString = element.attrib['transform'] + + # if transform attribute is present, we must add the new rotation + if transfString: + newTransform = 'rotate(%f %f %f) %s' % (-angleDeg, center[0], center[1], transfString) # negative angle bc inkscape is upside down + else: # if no transform attribute was found + newTransform = 'rotate(%f %f %f)' % (-angleDeg, center[0], center[1]) # negative angle bc inkscape is upside down + + element.attrib['transform'] = newTransform + + def copyElement(self, element, newParent, distance=None, angleDeg=None): + """Copy one element to the same parent or other parent group. + + It is possible to copy elements isolated or entire groups. + + :param element: element object to be copied + :param newParent: New parent object. Can be another group or the same group + :param distance: moving distance of the new copy. The coordinates are relative to the original position. If ``None``, then the copy is placed at the same position + :param angleDeg: angle of rotation in degrees, counter-clockwise direction + :type element: inkscape element object + :type newParent: inkscape element object + :type distance: list + :type angleDeg: float + :returns: new element + :rtype: inkscape element object + + **Example** + + >>> rootLayer = self.document.getroot() # retrieves the root layer of the file + >>> groupA = self.createGroup(rootLayer,label='temp') # creates a group inside rootLayer + >>> line1 = inkDraw.line.relCoords(groupA, [[5,0]],[0,0]) # creates a line in groupA + >>> line2 = inkDraw.line.relCoords(rootLayer, [[5,0]],[0,0]) # creates a line in rootLayer + >>> self.copyElement(line2,groupA) # create a copy of line2 in groupA + >>> self.moveElement(groupA,[10,-10]) # moves line2 DeltaX=10, DdeltaY=-10 + """ + newElem = deepcopy(element) + newParent.append(newElem) + + if distance is not None: + self.moveElement(newElem, distance) + + if angleDeg is not None: + self.rotateElement(newElem, self.getCenter(newElem), angleDeg) + + return newElem + + # --------------------------------------------- + def moveElement(self, element, distance): + """Move the element using the transformation attribute. + + It is possible to move elements isolated or entire groups. + + :param element: element object to be moved + :param distance: moving distance. The coordinates are relative to the original position. + :type element: inkscape element object + :type distance: tuple + :returns: nothing + :rtype: - + + **Example** + + >>> rootLayer = self.document.getroot() # retrieves the root layer of the file + >>> groupA = self.createGroup(rootLayer,label='temp') # creates a group inside rootLayer + >>> line1 = inkDraw.line.relCoords(groupA, [[5,0]],[0,0]) # creates a line in groupA + >>> line2 = inkDraw.line.relCoords(rootLayer, [[5,0]],[0,0]) # creates a line in rootLayer + >>> self.moveElement(line2,[10,10]) # moves line2 DeltaX=10, DdeltaY=10 + >>> self.moveElement(groupA,[10,-10]) # moves line2 DeltaX=10, DdeltaY=-10 + """ + + if distance[0] == 0 and distance[1] == 0: + return + + transfString = '' + + if 'transform' in element.attrib: + transfString = element.attrib['transform'] + + # if transform attribute is present, we must add the new translation + if transfString: + newTransform = 'translate(%f %f) %s ' % (distance[0], distance[1], transfString) + else: # if no transform attribute was found + newTransform = 'translate(%f %f)' % (distance[0], distance[1]) + + element.attrib['transform'] = newTransform + + # --------------------------------------------- + def scaleElement(self, element, scaleX=1.0, scaleY=None, center=None): + """Scale the element using the transformation attribute. + + It is possible to scale elements isolated or entire groups. + + :param element: element object to be scaled + :param scaleX: scaling factor in X direction. Default=1.0 + :param scaleY: scaling factor in Y direction. Default=``None``. If scaleY=``None``, then scaleY=scaleX is assumed (default behavior) + :param center: center point considered as the origin for the scaling. Default=``None``. If ``None``, the origin is adopted + :type element: inkscape element object + :type scaleX: float + :type scaleX: float + :type center: list + :returns: nothing + :rtype: - + + **Example** + + >>> rootLayer = self.document.getroot() # retrieves the root layer of the file + >>> groupA = self.createGroup(rootLayer,label='temp') # creates a group inside rootLayer + >>> circ1 = centerRadius(groupA,centerPoint=[0,0],radius=1.0) # creates a line in groupA + >>> circ2 = centerRadius(rootLayer,centerPoint=[0,0],radius=1.0) # creates a line in rootLayer + >>> self.scaleElement(circ1,2.0) # scales x2 in both X and Y directions + >>> self.scaleElement(circ1,2.0,3.0) # scales x2 in X and x3 in Y + >>> self.scaleElement(groupA,0.5) # scales x0.5 the group in both X and Y directions + """ + if center is not None: + self.moveElement(element, [-center[0], -center[1]]) + + transfString = '' + + if 'transform' in element.attrib: + transfString = element.attrib['transform'] + + # if transform attribute is present, we must add the new translation + if transfString: + if scaleY is not None: + newTransform = 'scale(%f %f) %s ' % (scaleX, scaleY, transfString) + else: + newTransform = 'scale(%f) %s' % (scaleX, transfString) + else: # if no transform attribute was found + if scaleY is not None: + newTransform = 'scale(%f %f)' % (scaleX, scaleY) + else: + newTransform = 'scale(%f)' % scaleX + + element.attrib['transform'] = newTransform + + if center is not None: + self.moveElement(element, [center[0], center[1]]) + + # --------------------------------------------- + def findMarker(self, markerName): + """Search for markerName definition in the document. + + :param markerName: name of the marker + :type markerName: string + :returns: True if markerName is in the document. False otherwise + :rtype: bool + """ + list = self.getDefsByTag(tag='marker') + for m in list: + if m.get('id') == markerName: + return True + + return False + + # --------------------------------------------- + def getPoints(self, element): + """Returns a list of points of the element. + + This function works on paths, texts or groups. In the case of a group, the function will include recursively all its components. + + :param element: element object + :type element: inkscape element object + :returns: array of points + :rtype: numpy array + + .. note:: This function will apply any transformation stored in transform attribute, + that is, it will compute the resulting coordinates of each object + + **Example** + + >>> rootLayer = self.document.getroot() # retrieves the root layer of the file + >>> line1 = inkDraw.line.relCoords(rootLayer, [[5,0],[0,6]],[0,0]) # creates a line in groupA, using relative coordinates + >>> list = self.getPoints(line1) # list = [[0.0, 0.0], [5.0, 0.0], [5.0, 6.0]] + + """ + + # stores the list of coordinates + listCoords = [] + + # check if element is valid. 'path', 'text' and 'g' are valid + accepted_strings = set([inkex.addNS('path', 'svg'), inkex.addNS('text', 'svg'), 'g', inkex.addNS('g', 'svg'), 'path', 'use', inkex.addNS('use', 'svg')]) + if element.tag not in accepted_strings: + return listCoords + + if element.tag in [inkex.addNS('path', 'svg'), 'path']: # if object is path + + # adds special character between letters and splits. the first regular expression excludes e and E bc they are used to represent scientific notation =S + dString = re.sub('([a-df-zA-DF-Z])+?', r'#\1#', element.attrib['d']).replace('z', '').replace('Z', '').replace(',', ' ').split('#') + + dString = [i.lstrip() for i in dString] # removes leading spaces from strings + dString = list(filter(None, dString)) # removes empty elements + Xcurrent = 0 + Ycurrent = 0 + + while len(dString) > 0: + commandType = dString[0] + argument = [float(x) for x in dString[1].split()] # extracts arguments from M command and converts to float + del dString[0] + del dString[0] + + if commandType in 'mMlLtT': # extracts points from command 'move to' M/m or 'line to' l/L or 'smooth quadratic Bezier curveto't/T + X = argument[0::2] # 2 parameters per segment, x is 1st + Y = argument[1::2] # 2 parameters per segment, y is 2nd + + if commandType in 'hH': # extracts points from command 'horizontal line' h/H + X = argument + Y = [Ycurrent] * len(X) + + if commandType in 'vV': # extracts points from command 'vertical line' v/V + Y = argument + X = [Xcurrent] * len(Y) + + if commandType in 'cC': # extracts points from command 'Bezier Curve' c/C + X = argument[4::6] # 6 parameters per segment, x is 5th + Y = argument[5::6] # 6 parameters per segment, y is 6th + + if commandType in 'sSqQ': # extracts points from command 'quadratic Bezier Curve' q/Q or 'smooth curveto' s/S + X = argument[2::4] # 4 parameters per segment, x is 3rd + Y = argument[3::4] # 4 parameters per segment, y is 4th + + if commandType in 'aA': # extracts points from command 'arc' a/A + X = argument[5::7] # 7 parameters per segment, x is 6th + Y = argument[6::7] # 7 parameters per segment, y is 7th + + if commandType in 'h': # if h + for i in range(0, len(X)): # convert to abs coordinates + if i == 0: + X[i] = X[i] + Xcurrent + else: + X[i] = X[i] + X[i - 1] + + if commandType in 'v': # if v + for i in range(0, len(Y)): # convert to abs coordinates + if i == 0: + Y[i] = Y[i] + Ycurrent + else: + Y[i] = Y[i] + Y[i - 1] + + if commandType in 'mltcsqa': # if m or l + for i in range(0, len(X)): # convert to abs coordinates + if i == 0: + X[i] = X[i] + Xcurrent + Y[i] = Y[i] + Ycurrent + else: + X[i] = X[i] + X[i - 1] + Y[i] = Y[i] + Y[i - 1] + + coords = zip(X, Y) + listCoords.extend(coords) + Xcurrent = X[-1] + Ycurrent = Y[-1] + + if element.tag in ['text', inkex.addNS('text', 'svg')]: # if object is a text + x = float(element.attrib['x']) + y = float(element.attrib['y']) + coords = [[x, y]] + listCoords.extend(coords) + + if element.tag in ['g', inkex.addNS('g', 'svg')]: # if object is a group + for obj in element.iterchildren("*"): + if obj != element and obj.tag not in [ 'defs', inkex.addNS('defs', 'svg')]: + listPoints = self.getPoints(obj) + listCoords.extend(listPoints) + + if element.tag in ['use', inkex.addNS('use', 'svg')]: # if object is a use + listCoordsTemp = [] + x = float(element.attrib['x']) + y = float(element.attrib['y']) + link = self.getElemAttrib(element, 'xlink:href').replace('#','') + elemLink = self.getElementById(link) + for obj in elemLink.iter(): + if obj != elemLink: + listPoints = self.getPoints(obj) + listCoordsTemp.extend(listPoints) + + #apply translation + listCoords=[[coord[0]+x,coord[1]+y] for coord in listCoordsTemp] + + + # apply transformation + if len(listCoords)>0: + + # creates numpy array with the points to be transformed + transfMat = self.getTransformMatrix(element)[1] + + coordsNP = np.hstack((np.array(listCoords), np.ones([len(listCoords), 1]))).transpose() + + coordsTransformed = np.dot(transfMat, coordsNP) + coordsTransformed = np.delete(coordsTransformed, 2, 0).transpose() # remove last line, transposes and converts to list of lists + + else: + coordsTransformed = np.array([]) + + return coordsTransformed + + # --------------------------------------------- + def getBoundingBox(self, element): + """Return the bounding Box of the element. + + This function works on paths, texts or groups. In the case of a group, the function will consider recursively all its components + + :param element: element object + :type element: inkscape element object + :returns: two lists: [xMin,yMin] and [xMax,yMax] + :rtype: list + + .. note:: This function will appply any transformation stored in transform attribute, + that is, it will compute the resulting coordinates of each object + + **Example** + + >>> rootLayer = self.document.getroot() # retrieves the root layer of the file + >>> line1 = inkDraw.line.relCoords(rootLayer, [[5,0],[0,6]],[0,0]) # creates a line in groupA + >>> BboxMin,BboxMax = self.getBoundingBox(line1) # gets BboxMin = [0.0, 0.0] and BboxMax = [5.0, 6.0] + + """ + coords = self.getPoints(element) + coordsNP = np.array(coords) + + bboxMax = np.max(coordsNP, 0) + bboxMin = np.min(coordsNP, 0) + return bboxMin.tolist(), bboxMax.tolist() + + # --------------------------------------------- + def getCenter(self, element): + """Return the center coordinates of the bounding Box of the element. + + This function works on paths, texts or groups. In the case of a group, the function will consider recursively all its components + + :param element: element object + :type element: inkscape element object + :returns: list: [xCenter, yCenter] + :rtype: list + + .. note:: This function will apply any transformation stored in transform attribute, + that is, it will compute the resulting coordinates of each object + + **Example** + + >>> rootLayer = self.document.getroot() # retrieves the root layer of the file + >>> line1 = inkDraw.line.relCoords(rootLayer, [[5,0],[0,6]],[0,0]) # creates a line in groupA + >>> Center = self.getCenter(line1) # gets Center = [2.5, 3.0] + + """ + + bboxMin, bboxMax = self.getBoundingBox(element) + + bboxCenter = np.array([(bboxMax[0] + bboxMin[0]) / 2, (bboxMax[1] + bboxMin[1]) / 2]) + + return bboxCenter + + def getSegmentFromPoints(self, pointList, normalDirection='R'): + """Given two points of a straight line segment, returns the parameters of that segment: + + length, angle (in radians), tangent unitary vector and normal unitary vector + + :param pointList: start and end coordinates [ Pstart, Pend ] + :param normalDirection: + + - 'R': normal vector points to the right of the tangent vector (Default) + - 'L': normal vector points to the left of the tangent vector + + :type pointList: list of points + :type normalDirection: string + + :returns: list: [length, theta, t_versor,n_versor] + :rtype: list + + **Example** + + >>> segmentParam = getSegmentFromPoints([[1,1],[2,2]],'R') # returns [1.4142, 0.78540, [0.7071,0.7071], [0.7071,-0.7071] ] + >>> segmentParam = getSegmentFromPoints([[1,1],[2,2]],'L') # returns [1.4142, 0.78540, [0.7071,0.7071], [-0.7071,0.7071] ] + """ + + # tangent versor (pointing P2) + P1 = np.array(pointList[0]) + P2 = np.array(pointList[1]) + + t_vector = P2 - P1 + length = np.linalg.norm(t_vector) + t_versor = t_vector / length + + # normal vector: counter-clockwise with respect to tangent vector + if normalDirection in 'rR': + n_versor = np.array([t_versor[1], -t_versor[0]]) + if normalDirection in 'lL': + n_versor = np.array([-t_versor[1], t_versor[0]]) + + # angle + theta = math.atan2(t_versor[1], t_versor[0]) + + return [length, theta, t_versor, n_versor] + + def getSegmentParameters(self, element, normalDirection='R'): + """Given a path segment composed by only two points, returns the parameters of that segment: + + length, angle (in radians), start point, end point, tangent unitary vector and normal unitary vector + + This function works with paths only. + + - If the element is not a path, the function returns an empty list + - If the path element has more than two points, the function returns an empty list + + :param element: path element object + :param normalDirection: + + - 'R': normal vector points to the right of the tangent vector (Default) + - 'L': normal vector points to the left of the tangent vector + + :type element: inkscape element object + :type normalDirection: string + + :returns: list: [Pstart,Pend,length, theta, t_versor,n_versor] + :rtype: list + + .. note:: This function will apply any transformation stored in transform attribute, + that is, it will compute the resulting coordinates of each object + + **Example** + + >>> rootLayer = self.document.getroot() # retrieves the root layer of the file + >>> line1 = inkDraw.line.absCoords(rootLayer, [[1,1],[2,2]]) # creates a line in groupA + >>> segementList = getSegmentParameters(line1,'R') # returns [[1,1], [2,2],1.4142, 0.78540, [0.7071,0.7071], [0.7071,-0.7071] ] + + """ + + # check if element is valid. 'path' + accepted_strings = set([inkex.addNS('path', 'svg'), 'path']) + if element.tag not in accepted_strings: + return [] + + listPoints = self.getPoints(element) + if len(listPoints) > 2: # if the path has more than two points + return [] + + data = self.getSegmentFromPoints(listPoints, normalDirection) + + return listPoints + data + + + diff --git a/extensions/fablabchemnitz/spirograph/inkscapeMadeEasy/inkscapeMadeEasy_Draw.py b/extensions/fablabchemnitz/spirograph/inkscapeMadeEasy/inkscapeMadeEasy_Draw.py new file mode 100644 index 0000000..664b632 --- /dev/null +++ b/extensions/fablabchemnitz/spirograph/inkscapeMadeEasy/inkscapeMadeEasy_Draw.py @@ -0,0 +1,2231 @@ +#!/usr/bin/python + +# -------------------------------------------------------------------------------------- +# +# inkscapeMadeEasy: - Helper module that extends Aaron Spike's inkex.py module, +# focusing productivity in inkscape extension development +# +# Copyright (C) 2016 by Fernando Moura +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# -------------------------------------------------------------------------------------- + +# Please uncomment (remove the # character) in the following line to disable LaTeX support via textext extension. +useLatex=False + + +import os +import sys + +try: + useLatex +except NameError: + useLatex = True +else: + useLatex = False + +import math + +import numpy as np + +import inkex +from lxml import etree +import re + +if useLatex: + sys.path.append('../textext') + import textext.base as textext + +import tempfile +import copy + +def displayMsg(msg): + """Display a message to the user. + + :param msg: message + :type msg: string + + :returns: nothing + :rtype: - + + .. note:: Identical function has been also defined inside :meth:`inkscapeMadeEasy_Base.inkscapeMadeEasy` class + + """ + sys.stderr.write(msg + '\n') + + +def Dump(obj, file='./dump_file.txt', mode='w'): + """Function to easily output the result of ``str(obj)`` to a file + + :param obj: python object to sent to a file. Any object can be used, as long as ``str(obj)`` is implemented (see ``__str__()`` metaclass definition of your object) + :param file: file path. Default: ``./dump_file.txt`` + :param mode: writing mode of the file Default: ``w`` (write) + :type obj: any + :type file: string + :type mode: string + :returns: nothing + :rtype: - + + .. note:: Identical function has been also defined inside :meth:`inkscapeMadeEasy_Base.inkscapeMadeEasy` class + + This function was created to help debugging the code while it is running under inkscape. Since inkscape does not possess a terminal as today (2016), + this function overcomes partially the issue of sending things to stdout by dumping result of the function ``str()`` in a text file. + + **Example** + + >>> vector1=[1,2,3,4,5,6] + >>> inkDraw.Dump(vector1,file='~/temporary.txt',mode='w') # writes the list to a file + >>> vector2=[7,8,9,10] + >>> inkDraw.Dump(vector2,file='~/temporary.txt',mode='a') # append the list to a file + """ + + with open(file, mode) as file: + file.write(str(obj) + '\n') + + +def circle3Points(P1, P2, P3): + """Find the center and radius of a circle based on 3 points on the circle. + + Returns [None,None] either if the points are aligned and no (finite radius) circle can be defined or if two of the points are coincident. + + :param P1,P2,P3: points [x,y] + + .. warning:: Keep in mind that Inkscape's y axis is upside down! + :type P1,P2,P3: list + + :returns: [center, radius] + :rtype: [numpy array, float] + + """ + # check if points are aligned + v1 = np.array(P1) - np.array(P2) + v2 = np.array(P1) - np.array(P3) + + if np.sqrt((v1[0] ** 2 + v1[1] ** 2))==0 or np.sqrt((v2[0] ** 2 + v2[1] ** 2))==0: + displayMsg('Error: Two of the points are coincident. Aborting it...') + return [None, None] + + v1 = v1 / np.sqrt((v1[0] ** 2 + v1[1] ** 2)) + v2 = v2 / np.sqrt((v2[0] ** 2 + v2[1] ** 2)) + cosTheta = v1.dot(v2) + + if abs(cosTheta) > 0.99999: + displayMsg('Error: The 3 points are collinear (or very close). Aborting it...') + return [None, None] + + # find the center + A = np.array([[-2 * P1[0], -2 * P1[1], 1], [-2 * P2[0], -2 * P2[1], 1], [-2 * P3[0], - 2 * P3[1], 1]]) + b = np.array([-P1[0] ** 2 - P1[1] ** 2, -P2[0] ** 2 - P2[1] ** 2, -P3[0] ** 2 - P3[1] ** 2]) + x = np.linalg.solve(A, b) + center = np.array([x[0], x[1]]) + radius = np.sqrt(x[0] ** 2 + x[1] ** 2 - x[2]) + return [center, radius] + +class color(): + """ + This class manipulates color information, generating a string in inkscape's expected format ``#RRGGBB`` + + .. note:: This class contains only static methods so that your plugin class don't have to inherit it. + + .. warning:: alpha channel is not implemented yet. Assume alpha=1.0 + + """ + + @staticmethod + def defined(colorName): + """ Return the color string representing a predefined color name + + :param colorName: prededined color name. See figure below + :type colorName: string + :returns: string representing the color in inkscape's expected format ``#RRGGBB`` + :rtype: string + + **Available pre defined colors** + + .. image:: ../imagesDocs/Default_colors.png + :width: 400px + + **Example** + + >>> colorString = inkDraw.color.defined('red') # returns #ff0000 representing red color + + """ + if colorName not in ['Dred', 'red', 'Lred', 'Dblue', 'blue', 'Lblue', 'Dgreen', 'green', 'Lgreen', 'Dyellow', 'yellow', 'Lyellow', 'Dmagen', + 'magen', 'Lmagen', 'black', 'white']: + sys.exit("InkscapeDraw.color.defined() : Error. color -->" + colorName + "<-- not defined") + + if colorName == 'Dred': + return '#800000' + if colorName == 'red': + return '#FF0000' + if colorName == 'Lred': + return '#FF8181' + + if colorName == 'Dblue': + return '#000080' + if colorName == 'blue': + return '#0000FF' + if colorName == 'Lblue': + return '#8181FF' + + if colorName == 'Dgreen': + return '#008000' + if colorName == 'green': + return '#00FF00' + if colorName == 'Lgreen': + return '#81FF81' + + if colorName == 'black': + return '#000000' + if colorName == 'white': + return '#FFFFFF' + + if colorName == 'Dyellow': + return '#808000' + if colorName == 'yellow': + return '#FFFF00' + if colorName == 'Lyellow': + return '#FFFF81' + + if colorName == 'Dmagen': + return '#800080' + if colorName == 'magen': + return '#FF00FF' + if colorName == 'Lmagen': + return '#FF81FF' + + @staticmethod + def RGB(RGBlist): + """ return a string representing a color specified by RGB level in the range 0-255 + + :param RGBlist: list containing RGB levels in the range 0-225 each + :type RGBlist: list of ints + :returns: string representing the color in inkscape's expected format ``#RRGGBB`` + :rtype: string + + **Example** + + >>> colorString = inkDraw.color.RGB([120,80,0]) # returns a string representing the color R=120, G=80, B=0 + + """ + RGBhex = [''] * 3 + for i in range(3): + if RGBlist[i] > 255: + RGBlist[i] = 255 + + if RGBlist[i] < 0: + RGBlist[i] = 0 + + if RGBlist[i] < 16: + RGBhex[i] = '0' + hex(int(RGBlist[i]))[2:].upper() + + else: + RGBhex[i] = hex(int(RGBlist[i]))[2:].upper() + + return '#' + '%s%s%s' % (RGBhex[0], RGBhex[1], RGBhex[2]) + + @staticmethod + def rgb(RGBlist): + """ Return a string representing a color specified by RGB level in the range 0.0-1.0 + + :param RGBlist: list containing RGB levels in the range 0.0-1.0 each + :type RGBlist: list of floats + :returns: string representing the color in inkscape's expected format ``#RRGGBB`` + :rtype: string + + **Example** + + >>> colorString = color.rgb([0.5,0.8,0.0]) # returns a string representing the color R=127, G=204, B=0 + + """ + RGBhex = [''] * 3 + for i in range(3): + if RGBlist[i] >= 1.0: + RGBlist[i] = 1.0 + + if RGBlist[i] <= 0.0: + RGBlist[i] = 0 + + if RGBlist[i]*255 < 16: + RGBhex[i] = '0' + hex(int(RGBlist[i]*255))[2:].upper() + + else: + RGBhex[i] = hex(int(RGBlist[i]*255))[2:].upper() + + return '#' + '%s%s%s' % (RGBhex[0], RGBhex[1], RGBhex[2]) + + # --------------------------------------------- + @staticmethod + def gray(percentage): + """ Return a string representing a gray color based on white percentage between 0.0 (black) and 1.0 (white) + + - if percentage is higher than 1.0, percentage is truncated to 1.0 (white) + - if percentage is lower than 0.0, percentage is truncated to 0.0 (black) + + :param percentage: value between 0.0 (black) and 1.0 (white) + :type percentage: float + :returns: string representing the color in inkscape's expected format ``#RRGGBB`` + :rtype: string + + **Example** + + >>> colorString = color.gray(0.6) # returns a string representing the gray level with 60% of white + + """ + RGBLevel = 255 * percentage + + if RGBLevel > 255: + RGBLevel = 255 + if RGBLevel < 0.0: + RGBLevel = 0 + + return color.RGB([RGBLevel] * 3) + + # --------------------------------------------- + @staticmethod + def colorPickerToRGBalpha(colorPickerString): + """ Function that converts the string returned by the widget 'color' in the .inx file into 2 strings, + one representing the color in format ``#RRGGBB`` and the other representing the alpha channel ``AA`` + + .. hint:: you probably don't need to use this function. Consider using the method :meth:`color.parseColorPicker` + + :param colorPickerString: string returned by 'color' widget + :type colorPickerString: string + :returns: a list of strings: [color,alpha] + - color: string in ``#RRGGBB`` format + - alpha: string in ``AA`` format + :rtype: list + + + .. note:: For more information on this widget, see `this `_. + + **Usage** + + 1- You must have one parameter of the type 'color' in your inx file:: + + + + 2- Parse it as a string in your .py file:: + + self.OptionParser.add_argument("--myColorPicker", type=str, dest="myColorPickerVar", default='#000000') + + 3- call this function to convert self.options.myColorPickerVar into two strings + - #RRGGBB with RGB values in hex + - AA with alpha value in hex + + **Example** + + Let your .inx file contain a widget of type 'color' with the name myColorPicker:: + + + + Then in the .py file + + >>> import inkscapeMadeEasy.inkscapeMadeEasy_Base as inkBase + >>> import inkscapeMadeEasy.inkscapeMadeEasy_Draw as inkDraw + >>> import inkscapeMadeEasy.inkscapeMadeEasy_Plot as inkPlot + >>> + >>> class myExtension(inkBase.inkscapeMadeEasy): + >>> def __init__(self): + >>> inkBase.inkscapeMadeEasy.__init__(self) + >>> self.OptionParser.add_argument("--myColorPicker", type=str, dest="myColorPickerVar", default='#000000') # parses the input parameter + >>> + >>> def effect(self): + >>> color,alpha = inkDraw.color.colorPickerToRGBalpha(self.options.myColorPickerVar) # returns the string representing the selected color and alpha channel + + """ + # [2:] removes the 0x , zfill adds the leading zeros, upper: uppercase + colorHex = hex(int(colorPickerString) & 0xffffffff)[2:].zfill(8).upper() + RGB = '#' + colorHex[0:6] + alpha = colorHex[6:] + return [RGB, alpha] + + # --------------------------------------------- + @staticmethod + def parseColorPicker(stringColorOption, stringColorPicker): + """ Function that converts the string returned by the widgets 'color' and 'optiongroup' in the .inx file into 2 strings, + one representing the color in format ``#RRGGBB`` and the other representing the alpha channel ``AA`` + + You must have in your .inx both 'optiongroup' and 'color' widgets as defined below. You don't have to have all the color options presented in the example. + That is the most complete example, considering the default colors in color.defined method. + + + :param stringColorOption: string returned by 'optiongroup' widget + :type stringColorOption: string + :param stringColorPicker: string returned by 'color' widget + :type stringColorPicker: string + :returns: a list of strings: [color,alpha] + - color: string in ``#RRGGBB`` format + - alpha: string in ``AA`` format + :rtype: list + + .. note:: For more information on this widget, see `this link `_ + + **Example** + + It works in the following manner: The user select in the optiongroup list the desired color. All pre defined colors in inkscapeMadeEasy are listed there. + There is also a 'my default color' option where you can set your preferred default color and an 'use color picker' option to activate the color picker widget. + Keep in mind that the selected color in the color picker widget will be considered **ONLY** if 'use color picker' option is selected. + + a) Example with full form of ``color`` widget. In this example a ``use color picker`` is selected from the optiongroup widget. Therefore the color picker widget will have effect + + .. image:: ../imagesDocs/colorPicker02.png + :width: 400px + + b) Example with compact form of ``color`` widget. In this example a color is selected from the optiongroup widget. Therefore the color picker widget will have no effect + + .. image:: ../imagesDocs/colorPicker01.png + :width: 400px + + Bellow is the template 'color' widget with name 'myColorPicker' and an 'optiongroup' with the name 'myColorOption' for the .inx file:: + + + <_option value="#FF0022">my default color <--you can set your pre define color in the form #RRGGBB + <_option value="none">none <-- no color + <_option value="black">black + <_option value="red">red + <_option value="blue">blue + <_option value="yellow">yellow + <_option value="green">green <-- these are all standardized colors in inkscapeMadeEasy_Draw.color class! + <_option value="magen">magenta + <_option value="white">white + <_option value="Lred">Lred + <_option value="Lblue">Lblue + <_option value="Lyellow">Lyellow + <_option value="Lgreen">Lgreen + <_option value="Lmagen">Lmagenta + <_option value="Dred">Dred + <_option value="Dblue">Dblue + <_option value="Dyellow">Dyellow + <_option value="Dgreen">Dgreen + <_option value="Dmagen">Dmagenta + <_option value="picker">use color picker <-- indicate that the color must be taken from the colorPicker attribute + + + + Then in the .py file + + >>> import inkscapeMadeEasy.inkscapeMadeEasy_Base as inkBase + >>> import inkscapeMadeEasy.inkscapeMadeEasy_Draw as inkDraw + >>> import inkscapeMadeEasy.inkscapeMadeEasy_Plot as inkPlot + >>> + >>> class myExtension(inkBase.inkscapeMadeEasy): + >>> def __init__(self): + >>> inkBase.inkscapeMadeEasy.__init__(self) + >>> self.OptionParser.add_argument("--myColorPicker", type=str, dest="myColorPickerVar", default='0') # parses the input parameters + >>> self.OptionParser.add_argument("--myColorOption", type=str, dest="myColorOptionVar", default='black') # parses the input parameter + >>> + >>> def effect(self): + >>> so = self.options + >>> [RGBstring,alpha] = inkDraw.color.parseColorPicker(so.myColorOptionVar,so.myColorPickerVar) + + """ + alphaString = 'FF' + if stringColorOption.startswith("#"): + return [stringColorOption, alphaString] + else: + if stringColorOption == 'none': + colorString = 'none' + else: + if stringColorOption == 'picker': + [colorString, alphaString] = color.colorPickerToRGBalpha(stringColorPicker) + else: + colorString = color.defined(stringColorOption) + return [colorString, alphaString] + + +class marker(): + """ + Class to manipulate markers. + + This class is used to create new custom markers. Markers can be used with the :meth:`inkscapeMadeEasy_Draw.lineStyle` class to define line types that include start, mid and end markers + + The base method of this class is :meth:`marker.createMarker` that can create custom markers. There are also other methods that simplify the creation of commonly used markers. The implemented predefined markers are presented in the figure below. + + .. image:: ../imagesDocs/marker_predefined.png + :width: 400px + + .. note:: This class contains only static methods so that your plugin class don't have to inherit it. + + """ + + # --------------------------------------------- + @staticmethod + def createMarker(ExtensionBaseObj, nameID, markerPath, RenameMode=0, strokeColor=color.defined('black'), fillColor=color.defined('black'), + lineWidth=1.0, markerTransform=None): + """Create a custom line marker + + :param ExtensionBaseObj: Most of the times you have to pass 'self' when calling from inside your plugin class. See example below + :param nameID: nameID of the marker + :param markerPath: Path definition. Must follow 'd' attribute format. See `this link `_ for further information + :param RenameMode: Renaming behavior mode + + - 0: (default) do not rename the marker. If nameID is already taken, the marker will not be modified. + - 1: overwrite marker definition if nameID is already taken + + .. Warning:: when a marker is created using RenameMode=1, any marker with the same name will disapear from inkscape's canvas. This is an inkscape issue. Save the document and reload it, everything should be fine. + - 2: Create a new unique nameID, adding a suffix number (Please refer to :meth:`inkscapeMadeEasy_Base.inkscapeMadeEasy.uniqueIdNumber()` + :param strokeColor: Stroke color in the format ``#RRGGBB`` (hexadecimal), or ``None`` for no color. Default: color.defined('black'). See :meth:`inkscapeMadeEasy_Draw.color` for functions to create color strings + :param fillColor: Filling color in the format ``#RRGGBB`` (hexadecimal), or ``None`` for no color. Default: color.defined('black'). See :meth:`inkscapeMadeEasy_Draw.color` for functions to create color strings + :param lineWidth: Line width of the marker. Default: 1.0 + :param markerTransform: custom transform applied to marker's path. Default: ``None`` + + .. note:: The transform must follow 'transform' attribute format. See `this link `_ for further information + + :type ExtensionBaseObj: inkscapeMadeEasy object + :type nameID: string + :type markerPath: string + :type RenameMode: int + :type strokeColor: string + :type fillColor: string + :type lineWidth: float + :type markerTransform: string + + :returns: NameID of the new marker + :rtype: string + + **System of coordinates** + + The system of coordinates of the marker depends on the point under consideration. The following figure presents the coordinate system for all cases + + .. image:: ../imagesDocs/marker_Orientation.png + :width: 600px + + **Example** + + >>> nameID='myMarker' + >>> markerPath='M 3,0 L 0,1 L 0,-1 z' # defines a path forming an triangle with vertices (3,0) (0,1) (0,-1) + >>> strokeColor=inkDraw.color.defined('red') + >>> fillColor=None + >>> RenameMode=1 + >>> width=1 + >>> markerTransform=None + >>> markerID=inkDraw.marker.createMarker(self,nameID,markerPath,RenameMode,strokeColor,fillColor,width,markerTransform) + >>> myLineStyle = inkDraw.lineStyle.set(1.0, markerEnd=markerID,lineColor=inkDraw.color.defined('black')) # see lineStyle class for further information on this function + >>> + >>> #tries to make another marker with the same nameID, changing RenameMode + >>> strokeColor=inkDraw.color.defined('blue') + >>> RenameMode=0 + >>> markerID=inkDraw.marker.createMarker(self,nameID,RenameMode,scale,strokeColor,fillColor) # this will not modify the marker + >>> RenameMode=1 + >>> markerID=inkDraw.marker.createMarker(self,nameID,RenameMode,scale,strokeColor,fillColor) # modifies the marker 'myMarker' + >>> RenameMode=2 + >>> markerID=inkDraw.marker.createMarker(self,nameID,RenameMode,scale,strokeColor,fillColor) # creates a new marker with nameID='myMarker-0001' + + .. note:: In the future, path definition and transformation will be modified to make it easier to design custom markers. =) + """ + + if RenameMode == 0 and ExtensionBaseObj.findMarker(nameID): + return nameID + + if RenameMode == 2: + numberID = 1 + new_id = nameID + '_n%05d' % numberID + while new_id in ExtensionBaseObj.svg.get_ids(): + numberID += 1 + new_id = nameID + '_n%05d' % numberID + ExtensionBaseObj.svg.get_ids().add(nameID) + nameID = new_id + + if RenameMode == 1 and ExtensionBaseObj.findMarker(nameID): + defs = ExtensionBaseObj.getDefinitions() + for obj in defs.iter(): + if obj.get('id') == nameID: + defs.remove(obj) + + # creates a new marker + marker_attribs = {inkex.addNS('stockid', 'inkscape'): nameID, 'orient': 'auto', 'refY': '0.0', 'refX': '0.0', 'id': nameID, + 'style': 'overflow:visible'} + + newMarker = etree.SubElement(ExtensionBaseObj.getDefinitions(), 'marker', marker_attribs) + + if fillColor is None: + fillColor = 'none' + if strokeColor is None: + strokeColor = 'none' + + marker_style = {'fill-rule': 'evenodd', 'fill': fillColor, 'stroke': strokeColor, 'stroke-width': str(lineWidth)} + + marker_lineline_attribs = {'d': markerPath, 'style': str(inkex.Style(marker_style))} + + if markerTransform: + marker_lineline_attribs['transform'] = markerTransform + + etree.SubElement(newMarker, 'path', marker_lineline_attribs) + + ExtensionBaseObj.svg.get_ids().add(nameID) + + return nameID + + # --------------------------------------------- + @staticmethod + def createDotMarker(ExtensionBaseObj, nameID, RenameMode=0, scale=0.4, strokeColor=color.defined('black'), fillColor=color.defined('black')): + """Create circular dot markers, exactly like inkscape default dotS dotM or dotL markers. + + .. image:: ../imagesDocs/marker_predefined_dot.png + :width: 300px + :align: center + + :param ExtensionBaseObj: Most of the times you have to pass 'self' when calling from inside your plugin class. See example below + :param nameID: nameID of the marker + :param RenameMode: Renaming behavior mode + + - 0: (default) do not rename the marker. If nameID is already taken, the marker will not be modified. + - 1: overwrite marker definition if nameID is already taken + + .. Warning:: when a marker is created using RenameMode=1, any marker with the same name will disapear from inkscape's canvas. This is an inkscape issue. Save the document and reload it, everything should be fine. + - 2: Create a new unique nameID, adding a suffix number (Please refer to :meth:`inkscapeMadeEasy_Base.inkscapeMadeEasy.uniqueIdNumber()` + :param scale: Scale factor of the marker. To exactly copy inkscape sizes dotS/M/L, use 0.2, 0.4 and 0.8 respectively. Default: 0.4 + :param strokeColor: Stroke color in the format ``#RRGGBB`` (hexadecimal), or ``None`` for no color. Default: color.defined('black'). See :meth:`inkscapeMadeEasy_Draw.color` for functions to create color strings + :param fillColor: Filling color in the format ``#RRGGBB`` (hexadecimal), or ``None`` for no color. Default: color.defined('black'). See :meth:`inkscapeMadeEasy_Draw.color` for functions to create color strings + :type ExtensionBaseObj: inkscapeMadeEasy object + :type nameID: string + :type RenameMode: int + :type scale: float + :type strokeColor: string + :type fillColor: string + + :returns: NameID of the new marker + :rtype: string + + **Example** + + >>> myMarker=inkDraw.marker.createDotMarker(self,nameID='myDotMarkerA',RenameMode=1,scale=0.5,strokeColor=inkDraw.color.defined('red'),fillColor=None) + >>> myLineStyle = inkDraw.lineStyle.set(1.0, markerEnd=myMarker,lineColor=inkDraw.color.defined('black')) # see lineStyle class for further information on this function + """ + + markerPath = 'M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z ' + width = 1.0 + markerTransform = 'scale(' + str(scale) + ') translate(7.4, 1)' + return marker.createMarker(ExtensionBaseObj, nameID, markerPath, RenameMode, strokeColor, fillColor, width, markerTransform) + + # --------------------------------------------- + @staticmethod + def createCrossMarker(ExtensionBaseObj, nameID, RenameMode=0, scale=0.4, strokeColor=color.defined('black')): + """Create a cross marker + + .. image:: ../imagesDocs/marker_predefined_cross.png + :width: 300px + :align: center + + :param ExtensionBaseObj: Most of the times you have to pass 'self' when calling from inside your plugin class. See example below + :param nameID: nameID of the marker + :param RenameMode: Renaming behavior mode + + - 0: (default) do not rename the marker. If nameID is already taken, the marker will not be modified. + - 1: overwrite marker definition if nameID is already taken + + .. Warning:: when a marker is created using RenameMode=1, any marker with the same name will disapear from inkscape's canvas. This is an inkscape issue. Save the document and reload it, everything should be fine. + - 2: Create a new unique nameID, adding a suffix number (Please refer to :meth:`inkscapeMadeEasy_Base.inkscapeMadeEasy.uniqueIdNumber()` + :param scale: Scale of the marker. Default: 0.4 + :param strokeColor: Stroke color in the format ``#RRGGBB`` (hexadecimal), or ``None`` for no color. Default: color.defined('black'). See :meth:`inkscapeMadeEasy_Draw.color` for functions to create color strings + :type ExtensionBaseObj: inkscapeMadeEasy object + :type nameID: string + :type RenameMode: int + :type scale: float + :type strokeColor: string + + :returns: NameID of the new marker + :rtype: string + + **Example** + + >>> myMarker=inkDraw.marker.createCrossMarker(self,nameID='myDotMarkerA',RenameMode=1,scale=0.5,strokeColor=inkDraw.color.defined('red')) + >>> myLineStyle = inkDraw.lineStyle.set(1.0, markerEnd=myMarker,lineColor=inkDraw.color.defined('black')) # see lineStyle class for further information on this function + """ + + markerPath = 'M -4,4 L 4,-4 M 4,4 L -4,-4' + markerTransform = 'scale(' + str(scale) + ')' + width = 1.0 + return marker.createMarker(ExtensionBaseObj, nameID, markerPath, RenameMode, strokeColor, None, width, markerTransform) + + # --------------------------------------------- + @staticmethod + def createArrow1Marker(ExtensionBaseObj, nameID, RenameMode=0, scale=0.4, strokeColor=color.defined('black'), fillColor=color.defined('black')): + """Create arrow markers (both start and end markers) + + .. image:: ../imagesDocs/marker_predefined_arrow.png + :width: 300px + :align: center + + :param ExtensionBaseObj: Most of the times you have to pass 'self' when calling from inside your plugin class. See example below + :param nameID: nameID of the marker. + + .. note:: Start and End markers will have 'Start' and 'End' suffixes respectively + + :param RenameMode: Renaming behavior mode + + - 0: (default) do not rename the marker. If nameID is already taken, the marker will not be modified. + - 1: overwrite marker definition if nameID is already taken + + .. Warning:: when a marker is created using RenameMode=1, any marker with the same name will disapear from inkscape's canvas. This is an inkscape issue. Save the document and reload it, everything should be fine. + - 2: Create a new unique nameID, adding a suffix number (Please refer to :meth:`inkscapeMadeEasy_Base.inkscapeMadeEasy.uniqueIdNumber()` + + :param scale: scale of the marker. Default: 0.4 + :param strokeColor: Stroke color in the format ``#RRGGBB`` (hexadecimal), or ``None`` for no color. Default: color.defined('black'). See :meth:`inkscapeMadeEasy_Draw.color` for functions to create color strings + :param fillColor: Filling color in the format ``#RRGGBB`` (hexadecimal), or ``None`` for no color. Default: color.defined('black'). See :meth:`inkscapeMadeEasy_Draw.color` for functions to create color strings + :type ExtensionBaseObj: inkscapeMadeEasy object + :type nameID: string + :type RenameMode: int + :type scale: float + :type strokeColor: string + :type fillColor: string + + :returns: a list of strings: [startArrowMarker,endArrowMarker] + - startArrowMarker: nameID of start marker + - endArrowMarker: nameID of end marker + :rtype: list + + **Example** + + >>> StartArrowMarker,EndArrowMarker=inkDraw.marker.createArrow1Marker(self,nameID='myArrow',RenameMode=1,scale=0.5,strokeColor=inkDraw.color.defined('red'),fillColor=None) + >>> myLineStyle = inkDraw.lineStyle.set(1.0, markerStart=StartArrowMarker,markerEnd=EndArrowMarker,lineColor='#000000') # see lineStyle class for further information on this function + """ + + # transform="scale(0.8) rotate(180) translate(12.5,0)" /> + # transform="scale(0.4) rotate(180) translate(10,0)" /> + # transform="scale(0.2) rotate(180) translate(6,0)" /> + # translation=12.5-17.5/(scale*10) + # linear regression from data of small medium and large + translation = 10.17 * scale + 4.75 + width = 1.0 + + markerPath = 'M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z ' + markerTransform = 'scale(' + str(scale) + ') rotate(0) translate(' + str(translation) + ',0)' + nameStart = marker.createMarker(ExtensionBaseObj, nameID + 'Start', markerPath, RenameMode, strokeColor, fillColor, width, markerTransform) + markerTransform = 'scale(' + str(scale) + ') rotate(180) translate(' + str(translation) + ',0)' + nameEnd = marker.createMarker(ExtensionBaseObj, nameID + 'End', markerPath, RenameMode, strokeColor, fillColor, width, markerTransform) + + return [nameStart, nameEnd] + + # --------------------------------------------- + @staticmethod + def createElipsisMarker(ExtensionBaseObj, nameID, RenameMode=0, scale=1.0, fillColor=color.defined('black')): + """Create ellipsis markers, both start and end markers. + + .. image:: ../imagesDocs/marker_predefined_elipsis.png + :width: 300px + :align: center + + .. note:: These markers differ from inkscape's default ellipsis since these markers are made such that the diameter of the dots are equal to the line width. + + :param ExtensionBaseObj: Most of the times you have to pass 'self' when calling from inside your plugin class. See example below + :param nameID: nameID of the marker. Start and End markers will have 'Start' and 'End' suffix respectively + :param RenameMode: Renaming behavior mode + + - 0: (default) do not rename the marker. If nameID is already taken, the marker will not be modified. + - 1: overwrite marker definition if nameID is already taken + + .. Warning:: when a marker is created using RenameMode=1, any marker with the same name will disapear from inkscape's canvas. This is an inkscape issue. Save the document and reload it, everything should be fine. + - 2: Create a new unique nameID, adding a suffix number (Please refer to :meth:`inkscapeMadeEasy_Base.inkscapeMadeEasy.uniqueIdNumber()` + :param scale: Scale of the marker. Default 1.0 + :param fillColor: Filling color in the format ``#RRGGBB`` (hexadecimal), or ``None`` for no color. Default: color.defined('black'). See :meth:`inkscapeMadeEasy_Draw.color` for functions to create color strings + :type ExtensionBaseObj: inkscapeMadeEasy object + :type nameID: string + :type RenameMode: int + :type scale: float + :type fillColor: string + + :returns: a list of strings: [startInfMarker,endInfMarker] + - startInfMarker: nameID of start marker + - endInfMarker: nameID of end marker + :rtype: list + + **Example** + + >>> startInfMarker,endInfMarker=inkDraw.marker.createElipsisMarker(self,nameID='myInfMarker',RenameMode=1,scale=1.0,fillColor='#00FF00') + >>> myLineStyle = inkDraw.lineStyle.set(1.0, markerStart=startInfMarker,markerEnd=endInfMarker,lineColor='#000000') # see lineStyle class for further information on this function + """ + + # build path for 3 circles + markerPath = '' + radius = scale / 2.0 + + for i in range(3): + + prefix = 'M %f %f ' % (i * 2 + radius, 0) + arcStringA = 'a %f %f 0 1 1 %f %f ' % (radius, radius, -2 * radius, 0) + arcStringB = 'a %f %f 0 1 1 %f %f ' % (radius, radius, 2 * radius, 0) + + markerPath = markerPath + prefix + arcStringA + arcStringB + 'z ' + + if scale != 1.0: + markerTransform = 'translate(' + str(-6.0 * scale) + ', 0) scale(' + str(scale) + ')' + else: + markerTransform = 'translate(' + str(-6.0 * scale) + ', 0)' + + width = 1.0 + # add small line segment + + nameStart = marker.createMarker(ExtensionBaseObj, nameID + 'Start', markerPath, RenameMode, None, fillColor, width, markerTransform) + + if scale != 1.0: + markerTransform = 'translate(' + str(2.0 * scale) + ', 0) scale(' + str(scale) + ')' + else: + markerTransform = 'translate(' + str(2.0 * scale) + ', 0)' + + nameEnd = marker.createMarker(ExtensionBaseObj, nameID + 'End', markerPath, RenameMode, None, fillColor, width, markerTransform) + + return [nameStart, nameEnd] + + +class lineStyle(): + """ + Class to manipulate line styles. + + This class is used to define line styles. It is capable of setting stroke and filling colors, line width, linejoin and linecap, markers (start, mid, and end) and stroke dash array + + The base method of this class is :meth:`lineStyle.set` that can create custom line types. + + .. note:: This class contains only static methods so that your plugin class don't have to inherit it. + + """ + + # --------------------------------------------- + @staticmethod + def set(lineWidth=1.0, lineColor=color.defined('black'), fillColor=None, lineJoin='round', lineCap='round', markerStart=None, markerMid=None, + markerEnd=None, strokeDashArray=None): + """ Create a new line style + + :param lineWidth: Line width. Default: 1.0 + :param lineColor: Color in the format ``#RRGGBB`` (hexadecimal), or ``None`` for no color. Default: color.defined('black') + :param fillColor: Color in the format ``#RRGGBB`` (hexadecimal), or ``None`` for no color. Default: ``None`` + :param lineJoin: Shape of the lines at the joints. Valid values 'miter', 'round', 'bevel'. See image below. Default: round. + :param lineCap: Shape of the lines at the ends. Valid values 'butt', 'square', 'round'. See image below. Default: round + :param markerStart: Marker at the start node. Default: ``None`` + :param markerMid: Marker at the mid nodes. Default: ``None`` + :param markerEnd: Marker at the end node. Default: ``None`` + :param strokeDashArray: Dashed line pattern definition. Default: ``None``. See `this link `_ for further information + + :type lineWidth: float + :type lineColor: string + :type fillColor: string + :type lineJoin: string + :type lineCap: string + :type markerStart: string + :type markerMid: string + :type markerEnd: string + :type strokeDashArray: string + + :returns: line definition following the provided specifications + :rtype: string + + **Line node types** + + .. image:: ../imagesDocs/line_nodes.png + :width: 600px + + **Example** + + >>> # creates a line style using a dot marker at its end node + >>> myMarker=inkDraw.marker.createDotMarker(self,nameID='myMarker',RenameMode=1,scale=0.5,strokeColor=color.defined('red'),fillColor=None) # see marker class for further information on this function + >>> myLineStyle = inkDraw.lineStyle.set(lineWidth=1.0, markerEnd=myMarker,lineColor=inkDraw.color.defined('black'),fillColor=inkDraw.color('red')) + >>> + >>> # creates a line style with dashed line (5 units dash , 10 units space + >>> myDashedStyle = inkDraw.lineStyle.set(lineWidth=1.0,lineColor=inkDraw.color.defined('black'),fillColor=inkDraw.color,strokeDashArray='5,10') + >>> # creates a line style with a more complex pattern (5 units dash , 10 units space, 2 units dash, 3 units space + >>> myDashedStyle = inkDraw.lineStyle.set(lineWidth=1.0,lineColor=inkDraw.color.defined('black'),fillColor=inkDraw.color,strokeDashArray='5,10,2,3') + """ + + if not fillColor: + fillColor = 'none' + if not lineColor: + lineColor = 'none' + if not strokeDashArray: + strokeDashArray = 'none' + + # dictionary with the styles + lineStyle = {'stroke': lineColor, 'stroke-width': str(lineWidth), 'stroke-dasharray': strokeDashArray, 'fill': fillColor} + + # Endpoint and junctions + lineStyle['stroke-linecap'] = lineCap + lineStyle['stroke-linejoin'] = lineJoin + + # add markers if needed + if markerStart: + lineStyle['marker-start'] = 'url(#' + markerStart + ')' + + if markerMid: + lineStyle['marker-mid'] = 'url(#' + markerMid + ')' + + if markerEnd: + lineStyle['marker-end'] = 'url(#' + markerEnd + ')' + + return lineStyle + + # --------------------------------------------- + @staticmethod + def setSimpleBlack(lineWidth=1.0): + """Define a standard black line style. + + The only adjustable parameter is its width. The fixed parameters are: lineColor=black, fillColor=None, lineJoin='round', lineCap='round', no markers, no dash pattern + + :param lineWidth: line width. Default: 1.0 + :type lineWidth: float + + :returns: line definition following the provided specifications + :rtype: string + + **Example** + + >>> mySimpleStyle = inkDraw.lineStyle.setSimpleBlack(lineWidth=2.0) + + """ + return lineStyle.set(lineWidth) + + +class textStyle(): + """ + Class to create text styles. + + This class is used to define text styles. It is capable of setting font size, justification, text color, font family, font style, font weight, line spacing, letter spacing and word spacing + + .. note:: This class contains only static methods so that your plugin class don't have to inherit it. + + """ + + # --------------------------------------------- + @staticmethod + def set(fontSize=10, justification='left', textColor=color.defined('black'), fontFamily='Sans', fontStyle='normal', fontWeight='normal', + lineSpacing='100%', letterSpacing='0px', wordSpacing='0px'): + """Define a new text style + + :param fontSize: Size of the font in px. Default: 10 + :param justification: Text justification. ``left``, ``right``, ``center``. Default: ``left`` + :param textColor: Color in the format ``#RRGGBB`` (hexadecimal), or ``None`` for no color. Default: color.defined('black') + :param fontFamily: Font family name. Default ``Sans`` + + .. warning:: This method does NOT verify whether the font family is installed in your machine or not. + + :param fontStyle: ``normal`` or ``italic``. Default: ``normal`` + :param fontWeight: ``normal`` or ``bold``. Default: ``normal`` + :param lineSpacing: Spacing between lines in percentage. Default: ``100%`` + :param letterSpacing: Extra space between letters. Format: ``_px``. Default: ``0px`` + :param wordSpacing: Extra space between words. Format: ``_px``. Default: ``0px`` + + :type fontSize: float + :type justification: string + :type textColor: string + :type fontFamily: string + :type fontStyle: string + :type fontWeight: string + :type lineSpacing: string + :type letterSpacing: string + :type wordSpacing: string + + :returns: text style definition following the provided specifications + :rtype: string + + **Example** + + >>> myTextStyle=inkDraw.textStyle.set(fontSize=10, justification='left', textColor=color.defined('black'), fontFamily='Sans', + >>> fontStyle='normal', fontWeight='normal', lineSpacing='100%', letterSpacing='0px', wordSpacing='0px') + """ + + if not textColor: + textColor = 'none' + + if justification == 'left': + justification = 'start' + anchor = 'start' + if justification == 'right': + justification = 'end' + anchor = 'end' + if justification == 'center': + anchor = 'middle' + + textStyle = {'font-size': str(fontSize) + 'px', 'font-style': fontStyle, 'font-weight': fontWeight, 'text-align': justification, + # start, center, end + 'line-height': lineSpacing, 'letter-spacing': letterSpacing, 'word-spacing': wordSpacing, 'text-anchor': anchor, + # start, middle, end + 'fill': textColor, 'fill-opacity': '1', 'stroke': 'none', 'font-family': fontFamily} + + return textStyle + + # --------------------------------------------- + @staticmethod + def setSimpleBlack(fontSize=10, justification='left'): + """Define a standard black text style + + The only adjustable parameter are font size and justification. The fixed parameters are: textColor=color.defined('black'), fontFamily='Sans', + fontStyle='normal', fontWeight='normal', lineSpacing='100%', letterSpacing='0px', wordSpacing='0px. + + :param fontSize: Size of the font in px. Default: 10 + :param justification: Text justification. ``left``, ``right``, ``center``. Default: ``left`` + + :type fontSize: float + :type justification: string + + :returns: text style definition following the provided specifications + :rtype: string + + **Example** + + >>> mySimpleStyle = inkDraw.textStyle.setSimpleBlack(fontSize=20,justification='center') + + """ + return textStyle.set(fontSize, justification) + + # --------------------------------------------- + @staticmethod + def setSimpleColor(fontSize=10, justification='left', textColor=color.defined('black')): + """Define a standard colored text style + + The only adjustable parameter are font size, justification and textColor. The fixed parameters are: fontFamily='Sans', fontStyle='normal', + fontWeight='normal', lineSpacing='100%', letterSpacing='0px', wordSpacing='0px. + + :param fontSize: Size of the font in px. Default: 10 + :param justification: Text justification. ``left``, ``right``, ``center``. Default: ``left`` + :param textColor: Color in the format ``#RRGGBB`` (hexadecimal), or ``None`` for no color. Default: color.defined('black') + + :type fontSize: float + :type justification: string + :type textColor: string + + :returns: text style definition following the provided specifications + :rtype: string + + **Example** + + >>> mySimpleStyle = inkDraw.textStyle.setSimpleColor(fontSize=20,justification='center',textColor=inkDraw.color.gray(0.5)) + """ + return textStyle.set(fontSize, justification, textColor) + + +class text(): + """ Class for writing texts. + + This class allows the cration of regular inkscape's text elements or LaTeX text. For the later, TexText is incorporated here. + + .. note:: This class contains only static methods so that your plugin class don't have to inherit it. + + .. warning:: LaTeX support is an optional feature, **enabled by default**. Please refer to :ref:`disableLatexSupport` on how to disable it. + + """ + + @staticmethod + def write(ExtensionBaseObj, text, coords, parent, textStyle=textStyle.setSimpleBlack(fontSize=10, justification='left'), fontSize=None, + justification=None, angleDeg=0.0): + """Add a text line to the document + + :param ExtensionBaseObj: Most of the times you have to pass 'self' when calling from inside your plugin class. See example below + :param text: Text contents. Use \\\\n in the string to start a new line + :param coords: Position [x,y] + :param parent: Parent object + :param textStyle: Text style to be used. See class ``textStyle``. Default: textStyle.setSimpleBlack(fontSize=10,justification='left') + :param fontSize: Size of the font in px. + - ``None``: Uses fontSize of textStyle argument (Default) + - number: takes precedence over the size on textStyle + :param justification: Text justification. ``left``, ``right``, ``center`` + - ``None``: Uses justification of textStyle argument (Default) + - ``left``, ``right``, ``center``: takes precedence over the justification set on textStyle + :param angleDeg: Angle of the text, counterclockwise, in degrees. Default: 0 + + :type ExtensionBaseObj: inkscapeMadeEasy object + :type text: string + :type coords: list + :type parent: inkscape element object + :type textStyle: textStyle object + :type fontSize: float + :type justification: string + :type angleDeg: float + + :returns: the new text object + :rtype: text Object + + **Example** + + >>> root_layer = self.document.getroot() # retrieves the root layer of the document + >>> mySimpleStyle = inkDraw.textStyle.setSimpleBlack(fontSize=20,justification='center') # creates a simple text style. + >>> + >>> #adds a two-line text, at the point x=5.0,y=6.0 + >>> # L1: 'foo bar who-hoo!' + >>> # L2: 'second line!' + >>> myText='foo bar who-hoo!\\nsecond line!' + >>> inkDraw.text.write(self, text=myText, coords=[5.0,6.0], parent=root_layer, textStyle=mySimpleStyle, fontSize=None, justification=None, angleDeg=0.0) + >>> + >>> # creates a group in root-layer and add text to it + >>> myGroup = self.createGroup(root_layer,'textGroup') + >>> #adds a text 'foo bar', rotated 45 degrees, at the point x=0,y=0, overriding justification of mySimpleStyle + >>> inkDraw.text.write(self, text='foo bar', coords=[0.0,0.0], parent=myGroup, textStyle=mySimpleStyle, fontSize=None, justification='left', angleDeg=45.0) + + """ + + if justification == 'left': + textStyle['text-align'] = 'start' + textStyle['text-anchor'] = 'start' + if justification == 'right': + textStyle['text-align'] = 'end' + textStyle['text-anchor'] = 'end' + if justification == 'center': + textStyle['text-align'] = 'center' + textStyle['text-anchor'] = 'middle' + + if fontSize: + textStyle['font-size'] = str(fontSize) + 'px' + + AttribsText = {inkex.addNS('space', 'xml'): "preserve", 'style': str(inkex.Style(textStyle)), 'x': str(coords[0]), 'y': str(coords[1]), + inkex.addNS('linespacing', 'sodipodi'): textStyle['line-height']} + + # textObj = etree.SubElement(parent, inkex.addNS('text','svg'), AttribsText ) + + textObj = etree.Element(inkex.addNS('text', 'svg'), AttribsText) + parent.append(textObj) + + AttribsLineText = {inkex.addNS('role', 'sodipodi'): "line", 'x': str(coords[0]), 'y': str(coords[1])} + + textLines = text.split('\\n') + + for n in range(len(textLines)): + myTspan = etree.SubElement(textObj, inkex.addNS('tspan', 'svg'), AttribsLineText) + myTspan.text = textLines[n] + + if angleDeg != 0: + ExtensionBaseObj.rotateElement(textObj, center=coords, angleDeg=angleDeg) # negative angle bc inkscape is upside down + + return textObj + + # --------------------------------------------- + @staticmethod + def latex(ExtensionBaseObj, parent, LaTeXtext, position, fontSize=10, refPoint='cc', textColor=color.defined('black'), LatexCommands=' ', + angleDeg=0, preambleFile=None): + """Creates text element using LaTeX. You can use any LaTeX contents here. + + .. note:: LaTeX support is an optional feature that requires a few extra packages to be installed outside inkscape. **It is enabled by default**. + Please refer to :ref:`disableLatexSupport` on how to disable it. If disabled, this function will still work, internally calling the :meth:`text.write`. + + :param ExtensionBaseObj: Most of the times you have to pass 'self' when calling from inside your plugin class. See example below + :param parent: parent object + :param LaTeXtext: Contents of the text. Can contain any latex command + :param position: Position of the reference point [x,y] + :param fontSize: Size of the font. Assume any capitql letter of ``\\normalsize`` will have this size. Default: 10 + :param refPoint: Text reference Point. See figure below for options. Default: ``cc`` + :param textColor: Color in the format ``#RRGGBB`` (hexadecimal), or ``None`` for no color. Default: color.defined('black') + :param LatexCommands: Commands to be included before LaTeXtext (default: ' '). If LaTeX support is disabled, this parameter has no effect. + :param angleDeg: Angle of the text, counterclockwise, in degrees. Default: 0 + :param preambleFile: Optional preamble file to be included. Default: None. If LaTeX support is disabled, this parameter has no effect. + + :type ExtensionBaseObj: inkscapeMadeEasy object + :type parent: inkscape element object + :type LaTeXtext: string + :type position: list + :type fontSize: float + :type refPoint: string + :type textColor: string + :type LatexCommands: string + :type angleDeg: float + :type preambleFile: string + + :returns: the new text object + :rtype: text Object + + .. note:: This function does not use ``textStyle`` class elements. + + **Reference point options** + + .. image:: ../imagesDocs/LaTeX_reference_Point.png + :width: 300px + + **Standard Preamble file** + + When a preamble file is not provided, inkscapeMadeEasy assumes a standard preamble file located at ``./textextLib/basicLatexPackages.tex``. By default, its contents is:: + + \\usepackage{amsmath,amsthm,amsbsy,amsfonts,amssymb} + \\usepackage[per=slash]{siunitx} + \\usepackage{steinmetz} + \\usepackage[utf8]{inputenc} + + You will need these packages installed. This file can be modified to include extra default packages and/or commands. + + **LaTeX .tex document structure** + + LaTeX .tex document have the following structure. Note that LatexCommands lies within document environment:: + + \\documentclass[landscape,a0]{article} + + [contents of Preamble file] + + \\pagestyle{empty} + + \\begin{document} + \\noindent + + [contents of LatexCommands] + + [contens of LaTeXtext] + + \\end{document} + + + **Example** + + >>> root_layer = self.document.getroot() # retrieves the root layer of the document + >>> customCommand = r'\\newcommand{\\fooBar}{\\textbf{Foo Bar Function! WhooHoo!}}' # do not forget the r to avoid backslash escape. + >>> inkDraw.text.latex(self, root_layer,r'This is one equation \\begin{align} x=y^2\\end{align} And this is my \\fooBar{}', + >>> position=[0.0,0.0], fontSize=10, refPoint='cc', textColor=inkDraw.color.defined('black'), LatexCommands=customCommand, angleDeg=0, preambleFile=None) + """ + newTmp = True + + # write an empty svg file. + + if not LaTeXtext: # check whether text is empty + return 0 + + if useLatex: # set useLatex=False to replace latex by an standard text (much faster for debugging =) ) + + if newTmp: + tmpf = tempfile.NamedTemporaryFile(mode='w', prefix='temp_svg_inkscapeMadeEasy_Draw_', suffix='.svg', delete=False) + tempFilePath = tmpf.name + tmpf.write(ExtensionBaseObj.blankSVG) + tmpf.close() + else: + tempDir = tempfile.gettempdir() + tempFilePath = tempDir + '/temp_svg_inkscapeMadeEasy_Draw.txt' + Dump(ExtensionBaseObj.blankSVG, tempFilePath, 'w') + + # return + # temp instance for determining font height. Draws a F letter just to find the height of the font + if False: # turning off this part of the code. + texTemp = textext.TexText() # start textText (awesome extension! =] ) + texTemp.run([r'--text=' + 'F', '--scale-factor=1', tempFilePath], output=os.devnull) + + for child in texTemp.document.getroot(): + if child.typename == 'TexTextElement': + groupLatex = child + + BboxMin, BboxMax = ExtensionBaseObj.getBoundingBox(groupLatex) + Height0 = BboxMax[1] - BboxMin[1] + + scale = ExtensionBaseObj.getDocumentScaleFactor() + ExtensionBaseObj.displayMsg('H0=%f\nscaleFactor=%f' % (Height0,scale )) + + else: + # running the code above, we get a 'F' with height of 6.76, with scale 1.0 from textext. This will be used to scale the text accordingly to fit user specification 'fontSize' + # Height0 = 6.76 + Height0 = 9.041644 + + scale = fontSize / Height0 + + tex = textext.TexText() # start textText (awesome extension! =] ) + + if preambleFile: + tex.run([r'--text=' + LatexCommands + LaTeXtext, '--scale-factor=1', '--preamble-file=' + preambleFile, tempFilePath], + output=os.devnull) # in case we want to save the svg file with the text element, uncomment the fllowing line. # tex.document.write(tempFilePath) + else: + tex.run( + [r'--text=' + LatexCommands + LaTeXtext, '--scale-factor=1', '--preamble-file=' + ExtensionBaseObj.getBasicLatexPackagesFile(), + tempFilePath], output=os.devnull) + + if newTmp: + os.unlink(tmpf.name) + + for child in tex.document.getroot(): + if child.typename == 'TexTextElement': + groupLatex = child + + # change color + for obj in groupLatex.iter(): + oldStyle = obj.get('style') + if oldStyle is not None: + newStyle = re.sub('fill:#[0-9a-fA-F]+', 'fill:' + textColor, oldStyle) + newStyle = re.sub('stroke:#[0-9a-fA-F]+', 'stroke:' + textColor, newStyle) + + obj.set('style', newStyle) + + ExtensionBaseObj.scaleElement(groupLatex, scaleX=scale, scaleY=scale) # scale to fit font size + else: + if refPoint[1] == 'l': + justification = 'left' + + if refPoint[1] == 'c': + justification = 'center' + + if refPoint[1] == 'r': + justification = 'right' + + mytextStyle = textStyle.setSimpleColor(fontSize=fontSize / 0.76, justification='left', textColor=textColor) + groupLatex = text.write(ExtensionBaseObj, LaTeXtext, [0, 0], parent, textStyle=mytextStyle, fontSize=fontSize / 0.76, + justification=justification, angleDeg=0.0) # attention! keep angleDeg=0.0 here bc it will be rotated below + + parent.append(groupLatex) + + BboxMin, BboxMax = ExtensionBaseObj.getBoundingBox(groupLatex) + + if useLatex: # set useLatex=False to replace latex by an standard text (much faster for debugging =) ) + if refPoint[0] == 't': + refPointY = BboxMin[1] # BboxMin bc inkscape is upside down + + if refPoint[0] == 'c': + refPointY = (BboxMax[1] + BboxMin[1]) / 2.0 + + if refPoint[0] == 'b': + refPointY = BboxMax[1] # BboxMax bc inkscape is upside down + + if refPoint[1] == 'l': + refPointX = BboxMin[0] + + if refPoint[1] == 'c': + refPointX = (BboxMax[0] + BboxMin[0]) / 2.0 + + if refPoint[1] == 'r': + refPointX = BboxMax[0] + else: + refPointX = BboxMin[0] + if refPoint[0] == 't': + refPointY = BboxMin[1] - fontSize # BboxMin bc inkscape is upside down + + if refPoint[0] == 'c': + refPointY = BboxMin[1] - fontSize / 2.0 # BboxMin bc inkscape is upside down + + if refPoint[0] == 'b': + refPointY = BboxMax[1] # BboxMax bc inkscape is upside down + + ExtensionBaseObj.moveElement(groupLatex, [-refPointX, -refPointY]) # move to origin + ExtensionBaseObj.moveElement(groupLatex, [position[0], position[1]]) + if angleDeg != 0: + ExtensionBaseObj.rotateElement(groupLatex, center=[position[0], position[1]], angleDeg=angleDeg) + + return groupLatex + + +class cubicBezier(): + """ This is a class with different methods for drawing cubic bezier lines. + + .. note:: This class contains only static methods so that your plugin class don't have to inherit it. + """ + + @staticmethod + def addNode(NodeList, coord=[0, 0], cPbefore=[-1, 0], cPafter=[1, 0], typeNode='corner', flagAbsCoords=True): + """Add a new node to the list of nodes of the cubic bezier line. + + .. important:: This function does not draw the curve. To draw the curve see :meth:`cubicBezier.draw` method. + + :param NodeList: Lst of nodes that will receive (append) the new node. + :param coord: List with the coordinates of the node + :param cPbefore: List with the coordinates of the control point before the node. + :param cPafter: List with the coordinates of the control point after the node. Used only if 'typeNode' is 'smooth' or 'corner' + :param typeNode: type of node to be added. See image below + + - ``corner``: Node without smoothness constraint. The bezier curve can have a sharp edge at this node + + - ``smooth``: Node with smoothness constraint. The bezier curve will be smooth at this node. If the control points do not form a straight line, then they are modified to form a straight line. See image below + + - ``symmetric``: same as ``smooth``, but the control points are forced to be symmetric with respect to the node. + + :param flagAbsCoords: Indicate absolute or relative coordinates. See section below on how reference system works. + .. warning:: All nodes in a given list must be defined in the same reference system (absolute or relative). + + :type NodeList: list + :type coord: list [x,y] + :type cPbefore: list [x,y] + :type cPafter: list [x,y] + :type typeNode: string + :type flagAbsCoords: bool + + :returns: None + :rtype: - + + **Node Types** + + The image below presents the types of nodes + + .. image:: ../imagesDocs/bezier_nodeTypes.png + :width: 500px + + **Smoothing control nodes** + + Image below present the process of smoothing control nodes not completely aligned when ``smooth`` is selected. + + .. image:: ../imagesDocs/bezier_smoothProcess.png + :width: 500px + + **Absolute and relative coordinate systems** + + Cubic bezier curves are composed by segments which are defined by 4 coordinates, two node coordinates and two control points. + + .. image:: ../imagesDocs/bezier_definitions.png + :width: 500px + + In absolute coordinate system, all node and control point locations are specified using the origin as reference. + In relative coordinate system, control point localizations are specified using its node as reference, and each node + use the previous node as reference (the first node use the origin as reference). See image below. + + .. warning:: Keep in mind that Inkscape's y axis is upside down! + + .. image:: ../imagesDocs/bezier_references.png + :width: 700px + + **Example** + + .. note:: In the following example, the control point before the first node and after the last node are important when the bezier curve must be closed. See method ``draw`` + + .. image:: ../imagesDocs/bezier_example.png + :width: 400px + + >>> # create a list of nodes using absolute coordinate system + >>> nodeListABS=[] + >>> inkDraw.cubicBezier.addNode(nodeListABS, coord=[4,4], cPbefore=[6,6], cPafter=[2,6], typeNode='corner', flagAbsCoords=True) + >>> inkDraw.cubicBezier.addNode(nodeListABS, coord=[8,12], cPbefore=[4,12], cPafter=[10,12], typeNode='smooth', flagAbsCoords=True) + >>> inkDraw.cubicBezier.addNode(nodeListABS, coord=[12,8], cPbefore=[8,8], cPafter=[12,10], typeNode='corner', flagAbsCoords=True) + >>> inkDraw.cubicBezier.addNode(nodeListABS, coord=[16,8], cPbefore=[14,10], cPafter=None, typeNode='symmetric', flagAbsCoords=True) + >>> inkDraw.cubicBezier.addNode(nodeListABS, coord=[12,4], cPbefore=[16,4], cPafter=[10,6], typeNode='corner', flagAbsCoords=True) + + >>> # create a list of nodes using relative coordinate system + >>> nodeListREL=[] + >>> inkDraw.cubicBezier.addNode(nodeListREL, coord=[4, 4], cPbefore=[2,2], cPafter=[-2,2], typeNode='corner', flagAbsCoords=False) + >>> inkDraw.cubicBezier.addNode(nodeListREL, coord=[4, 8], cPbefore=[-4,0], cPafter=[2,0], typeNode='smooth', flagAbsCoords=False) + >>> inkDraw.cubicBezier.addNode(nodeListREL, coord=[4, -4], cPbefore=[-4,0], cPafter=[0,2], typeNode='corner', flagAbsCoords=False) + >>> inkDraw.cubicBezier.addNode(nodeListREL, coord=[4, 0], cPbefore=[-2,2], cPafter=None, typeNode='symmetric', flagAbsCoords=False) + >>> inkDraw.cubicBezier.addNode(nodeListREL, coord=[-4,-4], cPbefore=[4,0], cPafter=[-2,2], typeNode='corner', flagAbsCoords=False) + + """ + + if typeNode.lower() == 'symmetric': + typeNodeSodipodi = 'z' + + if typeNode.lower() == 'smooth': + typeNodeSodipodi = 's' + + if typeNode.lower() == 'corner': + typeNodeSodipodi = 'c' + + if typeNodeSodipodi.lower() == 'c': # corner + NodeList.append({'node': coord, 'cPoint_before': cPbefore, 'cPoint_after': cPafter, 'type': typeNodeSodipodi, 'absCoords': flagAbsCoords}) + + if typeNodeSodipodi.lower() == 'z': # symmetric + if flagAbsCoords: + deltaX = coord[0] - cPbefore[0] + deltaY = coord[1] - cPbefore[1] + NodeList.append( + {'node': coord, 'cPoint_before': cPbefore, 'cPoint_after': [coord[0] + deltaX, coord[1] + deltaY], 'type': typeNodeSodipodi, + 'absCoords': flagAbsCoords}) + else: + NodeList.append({'node': coord, 'cPoint_before': cPbefore, 'cPoint_after': [-cPbefore[0], -cPbefore[1]], 'type': typeNodeSodipodi, + 'absCoords': flagAbsCoords}) + + if typeNodeSodipodi.lower() == 's': # smooth + + # projects the directions of the control points to a commom direction, perpendicular to both + delta1 = np.array(cPbefore) + delta2 = np.array(cPafter) + + if abs(delta1.dot(delta2)) < 1.0: + + if flagAbsCoords: + delta1 -= np.array(coord) + delta2 -= np.array(coord) + + # https://math.stackexchange.com/questions/2285965/how-to-find-the-vector-formula-for-the-bisector-of-given-two-vectors + bisectorVector = np.linalg.norm(delta2) * delta1 + np.linalg.norm(delta1) * delta2 + tangentVersor = np.array([-bisectorVector[1], bisectorVector[0]]) + tangentVersor /= np.linalg.norm(tangentVersor) + + cPbeforeNew = np.linalg.norm(delta1) * tangentVersor + cPafterNew = np.linalg.norm(delta2) * tangentVersor + + if flagAbsCoords: + cPbeforeNew += np.array(coord) + cPafterNew += np.array(coord) + + NodeList.append({'node': coord, 'cPoint_before': cPbeforeNew.tolist(), 'cPoint_after': cPafterNew.tolist(), 'type': typeNodeSodipodi, + 'absCoords': flagAbsCoords}) + else: + NodeList.append( + {'node': coord, 'cPoint_before': cPbefore, 'cPoint_after': cPafter, 'type': typeNodeSodipodi, 'absCoords': flagAbsCoords}) + + @staticmethod + def draw(parent, NodeList, offset=np.array([0, 0]), label='none', lineStyle=lineStyle.setSimpleBlack(), closePath=False): + """draws the bezier line, given a list of nodes, built using :meth:`cubicBezier.addNode` method + + + :param parent: parent object + :param NodeList: list of nodes. See :`cubicBezier.addNode` method + :param offset: offset coords. Default [0,0] + :param label: label of the line. Default 'none' + :param lineStyle: line style to be used. See :class:`lineStyle` class. Default: lineStyle=lineStyle.setSimpleBlack() + :param closePath: Connects the first point to the last. Default: False + + :type parent: inkscape element object + :type NodeList: list of nodes + :type offset: list + :type label: string + :type lineStyle: lineStyle object + :type closePath: bool + + :returns: the new line object + :rtype: line Object + + **Example** + + .. note:: In the following example, the control point before the first node and after the last node are important + when the bezier curve must be closed. + + .. image:: ../imagesDocs/bezier_example.png + :width: 400px + + >>> root_layer = self.document.getroot() # retrieves the root layer of the document + >>> myLineStyle = set(lineWidth=1.0, lineColor=color.defined('red')) + + >>> # create a list of nodes using absolute coordinate system + >>> nodeListABS=[] + >>> inkDraw.cubicBezier.addNode(nodeListABS, coord=[4,4], cPbefore=[6,6], cPafter=[2,6], typeNode='corner', flagAbsCoords=True) + >>> inkDraw.cubicBezier.addNode(nodeListABS, coord=[8,12], cPbefore=[4,12], cPafter=[10,12], typeNode='smooth', flagAbsCoords=True) + >>> inkDraw.cubicBezier.addNode(nodeListABS, coord=[12,8], cPbefore=[8,8], cPafter=[12,10], typeNode='corner', flagAbsCoords=True) + >>> inkDraw.cubicBezier.addNode(nodeListABS, coord=[16,8], cPbefore=[14,10], cPafter=None, typeNode='symmetric', flagAbsCoords=True) + >>> inkDraw.cubicBezier.addNode(nodeListABS, coord=[12,4], cPbefore=[16,4], cPafter=[10,6], typeNode='corner', flagAbsCoords=True) + + >>> # create a list of nodes using relative coordinate system + >>> nodeListREL=[] + >>> inkDraw.cubicBezier.addNode(nodeListREL, coord=[4, 4], cPbefore=[2,2], cPafter=[-2,2], typeNode='corner', flagAbsCoords=False) + >>> inkDraw.cubicBezier.addNode(nodeListREL, coord=[4, 8], cPbefore=[-4,0], cPafter=[2,0], typeNode='smooth', flagAbsCoords=False) + >>> inkDraw.cubicBezier.addNode(nodeListREL, coord=[4, -4], cPbefore=[-4,0], cPafter=[0,2], typeNode='corner', flagAbsCoords=False) + >>> inkDraw.cubicBezier.addNode(nodeListREL, coord=[4, 0], cPbefore=[-2,2], cPafter=None, typeNode='symmetric', flagAbsCoords=False) + >>> inkDraw.cubicBezier.addNode(nodeListREL, coord=[-4,-4], cPbefore=[4,0], cPafter=[-2,2], typeNode='corner', flagAbsCoords=False) + + >>> C1 = inkDraw.cubicBezier.draw(root_layer,nodeListABS, offset=[0, 0],closePath=False) + >>> C2 = inkDraw.cubicBezier.draw(root_layer,nodeListABS, offset=[0, 0],closePath=True) + >>> C3 = inkDraw.cubicBezier.draw(root_layer,nodeListREL, offset=[0, 0],closePath=False) + >>> C4 = inkDraw.cubicBezier.draw(root_layer,nodeListREL, offset=[0, 0],closePath=True) + + Result of the example + + .. image:: ../imagesDocs/bezier_example_draw.png + :width: 800px + + """ + + # first node + if NodeList[0]['absCoords']: + string_coords = 'M %f,%f ' % (NodeList[0]['node'][0] + offset[0], NodeList[0]['node'][0] + offset[1]) + else: + string_coords = 'M %f,%f ' % (NodeList[0]['node'][0] + offset[0], NodeList[0]['node'][0] + offset[1]) + + string_nodeTypes = '' + Ptotal = np.zeros(2) + for i in range(len(NodeList) - 1): + currNode = NodeList[i] + nextNode = NodeList[i + 1] + + if currNode['absCoords']: + bezier = 'C %f,%f ' % (currNode['cPoint_after'][0] + offset[0], currNode['cPoint_after'][1] + offset[1]) # first control point + bezier += '%f,%f ' % (nextNode['cPoint_before'][0] + offset[0], nextNode['cPoint_before'][1] + offset[1]) # second control point + bezier += '%f,%f ' % (nextNode['node'][0] + offset[0], nextNode['node'][1] + offset[1]) # second node + else: + bezier = 'c %f,%f ' % (currNode['cPoint_after'][0], currNode['cPoint_after'][1]) # first control point + bezier += '%f,%f ' % ( + nextNode['cPoint_before'][0] + nextNode['node'][0], nextNode['cPoint_before'][1] + nextNode['node'][1]) # second control point + bezier += '%f,%f ' % (nextNode['node'][0], nextNode['node'][1]) # second node + Ptotal += np.array(currNode['node']) + + string_nodeTypes += currNode['type'] + string_coords = string_coords + bezier + + if closePath: + currNode = NodeList[-1] + nextNode = copy.deepcopy(NodeList[0]) + + if currNode['absCoords']: + bezier = 'C %f,%f ' % (currNode['cPoint_after'][0] + offset[0], currNode['cPoint_after'][1] + offset[1]) # first control point + bezier += '%f,%f ' % (nextNode['cPoint_before'][0] + offset[0], nextNode['cPoint_before'][1] + offset[1]) # second control point + bezier += '%f,%f ' % (nextNode['node'][0] + offset[0], nextNode['node'][1] + offset[1]) # second node + else: + # writes the coordinates of the first node, relative to the last node. + Ptotal += np.array(currNode['node']) + nextNode['node'][0] = NodeList[0]['node'][0] - Ptotal[0] + nextNode['node'][1] = NodeList[0]['node'][1] - Ptotal[1] + + bezier = 'c %f,%f ' % (currNode['cPoint_after'][0], currNode['cPoint_after'][1]) # first control point + bezier += '%f,%f ' % ( + nextNode['cPoint_before'][0] + nextNode['node'][0], nextNode['cPoint_before'][1] + nextNode['node'][1]) # second control point + bezier += '%f,%f ' % (nextNode['node'][0], nextNode['node'][1]) # second node + + string_nodeTypes += currNode['type'] + nextNode['type'] + string_coords = string_coords + bezier + ' Z' + else: + string_nodeTypes += currNode['type'] + + # M = move, L = line, H = horizontal line, V = vertical line, C = curve, S = smooth curve, + # Q = quadratic Bezier curve, T = smooth quadratic Bezier curve, A = elliptical Arc,Z = closepath + Attribs = {inkex.addNS('label', 'inkscape'): label, 'style': str(inkex.Style(lineStyle)), 'd': string_coords, + inkex.addNS('nodetypes', 'sodipodi'): string_nodeTypes} + + return etree.SubElement(parent, inkex.addNS('path', 'svg'), Attribs) + + +class line(): + """ class with methods for drawing lines (paths). + + .. note:: This class contains only static methods so that your plugin class don't have to inherit it. + """ + + @staticmethod + def absCoords(parent, coordsList, offset=[0, 0], label='none', lineStyle=lineStyle.setSimpleBlack(), closePath=False): + """Draw a (poly)line based on a list of absolute coordinates + + + :param parent: Parent object + :param coordsList: List with coords x and y. ex: [[x1,y1], ..., [xN,yN]] + + .. warning:: Keep in mind that Inkscape's y axis is upside down! + + :param offset: Offset coords. Default [0,0] + :param label: Label of the line. Default 'none' + :param lineStyle: Line style to be used. See :class:`lineStyle` class. Default: lineStyle=lineStyle.setSimpleBlack() + :param closePath: Connects the first point to the last. Default: False + + :type parent: inkscape element object + :type coordsList: list of list + :type offset: list + :type label: string + :type lineStyle: lineStyle object + :type closePath: bool + + :returns: the new line object + :rtype: line Object + + **Example** + + .. image:: ../imagesDocs/lineExample.png + :width: 250px + + >>> root_layer = self.document.getroot() # retrieves the root layer of the document + >>> myLineStyle = inkDraw.lineStyle.set(lineWidth=1.0, lineColor=color.defined('red')) + >>> + >>> # creates a polyline passing through points (0,0) (0,1) (1,1) (1,2) (2,2), and using absolute coordinates + >>> coords=[ [0,0], [0,1], [1,1], [1,2], [2,2] ] + >>> inkDraw.line.absCoords(root_layer, coordsList=coords, offset=[0, 0], label='fooBarLine', lineStyle=myLineStyle) + >>> + >>> # creates the same polyline translated to point (5,6). Note we just have to change the offset + >>> inkDraw.line.absCoords(root_layer, coordsList=coords, offset=[5, 6], label='fooBarLine', lineStyle=myLineStyle) + """ + + # string with coordinates + string_coords = '' + + for point in coordsList: + string_coords = string_coords + ' ' + str(point[0] + offset[0]) + ',' + str(point[1] + offset[1]) + + if closePath: + string_coords += ' Z' + + # M = move, L = line, H = horizontal line, V = vertical line, C = curve, S = smooth curve, + # Q = quadratic Bezier curve, T = smooth quadratic Bezier curve, A = elliptical Arc,Z = closepath + Attribs = {inkex.addNS('label', 'inkscape'): label, 'style': str(inkex.Style(lineStyle)), 'd': 'M ' + string_coords} + + return etree.SubElement(parent, inkex.addNS('path', 'svg'), Attribs) + + # --------------------------------------------- + @staticmethod + def relCoords(parent, coordsList, offset=[0, 0], label='none', lineStyle=lineStyle.setSimpleBlack(), closePath=False): + """Draw a (poly)line based on a list of relative coordinates + + :param parent: Parent object + :param coordsList: List with distances dx and dy for all points. ex [[dx1,dy1], ..., [dxN,dyN]] + + .. warning:: Keep in mind that Inkscape's y axis is upside down! + + :param offset: Offset coords. Default [0,0] + :param label: Label of the line. Default 'none' + :param lineStyle: Line style to be used. See :class:`lineStyle` class. Default: lineStyle=lineStyle.setSimpleBlack() + :param closePath: Connects the first point to the last. Default: False + + :type parent: inkscape element object + :type coordsList: list of list + :type offset: list + :type label: string + :type lineStyle: lineStyle object + :type closePath: bool + + :returns: the new line object + :rtype: line Object + + **Example** + + .. image:: ../imagesDocs/lineExample.png + :width: 250px + + >>> root_layer = self.document.getroot() # retrieves the root layer of the document + >>> myLineStyle = inkDraw.lineStyle.setSimpleBlack(lineWidth=1.0) + >>> + >>> # creates a polyline passing through points (0,0) (0,1) (1,1) (1,2) (2,2) using relative coordinates + >>> coords=[ [0,1], [1,0], [0,1], [1,0] ] + >>> inkDraw.line.relCoords(root_layer, coordsList=coords, offset=[0, 0], label='fooBarLine', lineStyle=myLineStyle) + >>> + >>> # creates the same polyline translated to point (5,6) + >>> inkDraw.line.relCoords(root_layer, coordsList=coords, offset=[5, 6], label='fooBarLine', lineStyle=myLineStyle) + """ + + # string with coordinates + string_coords = '' + for dist in coordsList: + string_coords = string_coords + ' ' + str(dist[0]) + ',' + str(dist[1]) + + if closePath: + string_coords += ' Z' + + # M = move, L = line, H = horizontal line, V = vertical line, C = curve, S = smooth curve, + # Q = quadratic Bezier curve, T = smooth quadratic Bezier curve, A = elliptical Arc,Z = closepath + Attribs = {inkex.addNS('label', 'inkscape'): label, 'style': str(inkex.Style(lineStyle)), + 'd': 'm ' + str(offset[0]) + ' ' + str(offset[1]) + string_coords} + + return etree.SubElement(parent, inkex.addNS('path', 'svg'), Attribs) + + +class arc(): + """ Class with methods for drawing arcs. + + .. note:: This class contains only static methods so that your plugin class don't have to inherit it. + """ + + @staticmethod + def startEndRadius(parent, Pstart, Pend, radius, offset=[0, 0], label='arc', lineStyle=lineStyle.setSimpleBlack(), flagRightOf=True, + arcType='open', largeArc=False): + """Draw a circle arc from ``Pstart`` to ``Pend`` with a given radius + + .. image:: ../imagesDocs/arc_startEndRadius.png + :width: 80px + + :param parent: Parent object + :param Pstart: Start coordinate [x,y] + + .. warning:: Keep in mind that Inkscape's y axis is upside down! + + :param Pend: End coordinate [x,y] + :param radius: Arc radius + :param offset: Extra offset coords [x,y]. Default [0,0] + :param label: Label of the line. Default 'arc' + :param lineStyle: Line style to be used. See :class:`lineStyle` class. Default: lineStyle=lineStyle.setSimpleBlack() + :param flagRightOf: Sets the side of the vector Pend-Pstart which the arc must be drawn. See image below + + - True: Draws the arc to the right (Default) + - False: Draws the arc to the left + + :param arcType: type of arc. Valid values: 'open', 'slice', 'chord'. See image below. Default: 'open' + + :param largeArc: Sets the largest arc to be drawn. See image below + + - True: Draws the largest arc + - False: Draws the smallest arc (Default) + + :type parent: inkscape element object + :type Pstart: list + :type Pend: list + :type radius: float + :type offset: list + :type label: string + :type lineStyle: lineStyle object + :type flagRightOf: bool + :type arcType: string + :type largeArc: bool + + :returns: the new arc object + :rtype: line Object + + **Arc options** + + .. image:: ../imagesDocs/arc_startEndRadius_flags.png + :width: 800px + + **Example** + + >>> root_layer = self.document.getroot() # retrieves the root layer of the document + >>> + >>> P1=[10.0,0.0] + >>> P2=[20.0,10.0] + >>> R=15.0 + >>> myLineStyle=inkDraw.lineStyle.setSimpleBlack() + >>> + >>> #draws an open arc + >>> inkDraw.arc.startEndRadius(parent=root_layer, Pstart=P1, Pend=P2, radius=R, offset=[25,0], label='arc1', lineStyle=myLineStyle, arcType='open') + >>> + >>> #draws a closed (slice) arc + >>> inkDraw.arc.startEndRadius(parent=root_layer, Pstart=P1, Pend=P2, radius=R, offset=[25,20], label='arc2', lineStyle=myLineStyle, arcType='slice') + >>> + >>> #draws an open arc to the right + >>> inkDraw.arc.startEndRadius(parent=root_layer, Pstart=P1, Pend=P2, radius=R, offset=[0,0], label='arc', lineStyle=myLineStyle, flagRightOf=True, largeArc=True) + """ + + # finds the center point using some linear algebra + StartVector = np.array(Pstart) + EndVector = np.array(Pend) + + DistVector = EndVector - StartVector + Dist = np.linalg.norm(DistVector) # distance between start and end + if Dist > 2.0 * radius: + return None + + if (flagRightOf and largeArc) or (not flagRightOf and not largeArc): + RadiusDirection = np.array([-DistVector[1], DistVector[0]]) # perpendicular to DistVector + else: + RadiusDirection = np.array([DistVector[1], -DistVector[0]]) # perpendicular to DistVector + + RadiusDirection = RadiusDirection / np.linalg.norm(RadiusDirection) # normalize RadiusDirection + CenterPoint = StartVector + DistVector / 2.0 + RadiusDirection * math.sqrt(radius ** 2.0 - (Dist / 2.0) ** 2.0) + + # computes the starting angle and ending angle + temp = StartVector - CenterPoint + AngStart = math.atan2(temp[1], temp[0]) + temp = EndVector - CenterPoint + AngEnd = math.atan2(temp[1], temp[0]) + + if flagRightOf: # inkscape does not follow svg path format to create arcs. It uses sodipodi which is weird =S + sodipodiAngleStart = str(AngEnd) + sodipodiAngleEnd = str(AngStart) + else: + sodipodiAngleStart = str(AngStart) + sodipodiAngleEnd = str(AngEnd) + + # arc instructions + if largeArc: + largeArcFlag = 1 + else: + largeArcFlag = 0 + if flagRightOf: + sweepFlag = 0 + else: + sweepFlag = 1 + arcString = ' a %f,%f 0 %d %d %f,%f' % (radius, radius, largeArcFlag, sweepFlag, EndVector[0] - StartVector[0], EndVector[1] - StartVector[1]) + if arcType.lower() == 'slice': + arcString = arcString + ' L ' + str(CenterPoint[0] + offset[0]) + ' ' + str(CenterPoint[1] + offset[1]) + ' z' + if arcType.lower() == 'chord': + arcString = arcString + ' z' + + # M = moveto,L = lineto,H = horizontal lineto,V = vertical lineto,C = curveto,S = smooth curveto,Q = quadratic Bezier curve,T = smooth quadratic Bezier curveto,A = elliptical Arc,Z = closepath + Attribs = {inkex.addNS('label', 'inkscape'): label, 'style': str(inkex.Style(lineStyle)), inkex.addNS('type', 'sodipodi'): 'arc', + inkex.addNS('rx', 'sodipodi'): str(radius), inkex.addNS('ry', 'sodipodi'): str(radius), + inkex.addNS('cx', 'sodipodi'): str(CenterPoint[0] + offset[0]), inkex.addNS('cy', 'sodipodi'): str(CenterPoint[1] + offset[1]), + inkex.addNS('start', 'sodipodi'): sodipodiAngleStart, inkex.addNS('end', 'sodipodi'): sodipodiAngleEnd, + 'd': 'M ' + str(offset[0] + StartVector[0]) + ' ' + str(offset[1] + StartVector[1]) + arcString} + if arcType.lower() == 'open': + Attribs[inkex.addNS('arc-type', 'sodipodi')] = 'arc' + else: + Attribs[inkex.addNS('arc-type', 'sodipodi')] = arcType.lower() + + return etree.SubElement(parent, inkex.addNS('path', 'svg'), Attribs) + + # --------------------------------------------- + @staticmethod + def centerAngStartAngEnd(parent, centerPoint, radius, angStart, angEnd, offset=[0, 0], label='arc', lineStyle=lineStyle.setSimpleBlack(), + arcType='open', largeArc=False): + """Draw a circle arc given its center and start and end angles + + .. image:: ../imagesDocs/arc_centerAngStartAngEnd.png + :width: 200px + + + :param parent: parent object + :param centerPoint: center coordinate [x,y] + + .. warning:: Keep in mind that Inkscape's y axis is upside down! + + :param radius: Arc radius + :param angStart: Start angle in degrees + :param angEnd: End angle in degrees + :param offset: Extra offset coords [x,y] + :param label: Label of the line. Default 'arc' + :param lineStyle: Line style to be used. See :class:`lineStyle` class. Default: lineStyle=lineStyle.setSimpleBlack() + :param arcType: Type of arc. Valid values: 'open', 'slice', 'chord'. See image below. Default: 'open' + :param largeArc: Sets the largest arc to be drawn. See image below + + - True: Draws the largest arc + - False: Draws the smallest arc (Default) + + :type parent: inkscape element object + :type centerPoint: list + :type radius: float + :type angStart: float + :type angEnd: float + :type offset: list + :type label: string + :type lineStyle: lineStyle object + :type arcType: string + :type largeArc: bool + + :returns: the new arc object + :rtype: line Object + + **Arc options** + + .. image:: ../imagesDocs/arc_centerAngStartAngEnd_flags.png + :width: 700px + + **Example** + + >>> root_layer = self.document.getroot() # retrieves the root layer of the document + >>> myLineStyle = inkDraw.lineStyle.setSimpleBlack() + >>> + >>> #draws the shortest arc + >>> inkDraw.arc.centerAngStartAngEnd(parent=root_layer, centerPoint=[0,0], radius=15.0, angStart=-10, angEnd=90, + >>> offset=[0,0], label='arc1', lineStyle=myLineStyle, arcType='open',largeArc=False) + >>> #draws the longest arc + >>> inkDraw.arc.centerAngStartAngEnd(parent=root_layer, centerPoint=[0,0], radius=15.0, angStart=-10, angEnd=90, + >>> offset=[30,0], label='arc1', lineStyle=myLineStyle, arcType='open',largeArc=True) + """ + + Pstart = [radius * math.cos(math.radians(angStart)), radius * math.sin(math.radians(angStart))] + Pend = [radius * math.cos(math.radians(angEnd)), radius * math.sin(math.radians(angEnd))] + + pos = [centerPoint[0] + offset[0], centerPoint[1] + offset[1]] + + if abs(angEnd - angStart) <= 180: + flagRight = largeArc + else: + flagRight = not largeArc + + return arc.startEndRadius(parent, Pstart, Pend, radius, pos, label, lineStyle, flagRight, arcType, largeArc) + + # --------------------------------------------- + @staticmethod + def threePoints(parent, Pstart, Pmid, Pend, offset=[0, 0], label='arc', lineStyle=lineStyle.setSimpleBlack(), arcType='open'): + """Draw a circle arc given 3 points + + .. image:: ../imagesDocs/arc_3points.png + :width: 120px + + + :param parent: parent object + :param Pstart: Start coordinate [x,y] + + .. warning:: Keep in mind that Inkscape's y axis is upside down! + + :param Pmid: Mid coordinate [x,y] + :param Pend: End coordinate [x,y] + :param offset: Extra offset coords [x,y] + :param label: Label of the line. Default 'arc' + :param lineStyle: Line style to be used. See :class:`lineStyle` class. Default: lineStyle=lineStyle.setSimpleBlack() + :param arcType: Type of arc. Valid values: 'open', 'slice', 'chord'. See image below. Default: 'open' + + :type parent: inkscape element object + :type Pstart: list + :type Pmid: list + :type Pend: list + :type offset: list + :type label: string + :type lineStyle: lineStyle object + :type arcType: string + + :returns: the new arc object + :rtype: line Object + + **Arc options** + + .. image:: ../imagesDocs/arc_type_flags.png + :width: 400px + + **Example** + + >>> root_layer = self.document.getroot() # retrieves the root layer of the document + >>> myLineStyle = inkDraw.lineStyle.setSimpleBlack() + >>> + >>> P1=[10.0,0.0] + >>> P2=[20.0,10.0] + >>> P3=[50.0,30.0] + >>> + >>> #draws an open arc + >>> inkDraw.arc.threePoints(parent=root_layer, Pstart=P1, Pmid=P3, Pend=P3, offset=[25,0], label='arc1', lineStyle=myLineStyle, arcType='open') + """ + + [center,radius] = circle3Points(Pstart, Pmid, Pend) + + if center is None: + return + vStart=np.array(Pstart) + vEnd=np.array(Pend) + vMid=np.array(Pmid) + + # find side + DistVector = vEnd-vStart + NormalLeftVector = np.array([DistVector[1],-DistVector[0]]) + MidVector = vMid - vStart + CenterVector = center - vStart + + # check if MidVector and CenterVector are pointing to the same side of DistVector + if np.dot(CenterVector,NormalLeftVector)*np.dot(MidVector,NormalLeftVector)>0: + largeArc = True + else: + largeArc = False + + angStart = math.atan2(Pstart[1]-center[1], Pstart[0]-center[0]) + angEnd = math.atan2(Pend[1]-center[1], Pend[0]-center[0]) + + angles = np.unwrap([angStart, angEnd])*180/np.pi + angStart=angles[0] + angEnd=angles[1] + + if angEnd - angStart>0: + return arc.centerAngStartAngEnd(parent, center, radius, angStart, angEnd, offset, label,lineStyle,arcType,largeArc) + else: + return arc.centerAngStartAngEnd(parent, center, radius, angEnd, angStart, offset, label,lineStyle,arcType,largeArc) + + +class circle(): + """ Class with methods for drawing circles. + + .. note:: This class contains only static methods so that your plugin class don't have to inherit it. + """ + + @staticmethod + def centerRadius(parent, centerPoint, radius, offset=[0, 0], label='circle', lineStyle=lineStyle.setSimpleBlack()): + """Draw a circle given its center point and radius + + :param parent: Parent object + :param centerPoint: Center coordinate [x,y] + + .. warning:: Keep in mind that Inkscape's y axis is upside down! + + :param radius: Circle's radius + :param offset: Extra offset coords [x,y] + :param label: Label of the line. Default 'circle' + :param lineStyle: Line style to be used. See :class:`lineStyle` class. Default: lineStyle=lineStyle.setSimpleBlack() + + :type parent: inkscape element object + :type centerPoint: list + :type radius: float + :type offset: list + :type label: string + :type lineStyle: lineStyle object + + :returns: the new circle object + :rtype: line Object + + **Example** + + >>> root_layer = self.document.getroot() # retrieves the root layer of the document + >>> myLineStyle = inkDraw.lineStyle.setSimpleBlack() + >>> + >>> inkDraw.circle.centerRadius(parent=root_layer, centerPoint=[0,0], radius=15.0, offset=[5,1], label='circle1', lineStyle=myLineStyle) + """ + + # arc instructions + arcStringA = ' a %f,%f 0 1 1 %f,%f' % (radius, radius, -2 * radius, 0) + arcStringB = ' a %f,%f 0 1 1 %f,%f' % (radius, radius, 2 * radius, 0) + + # M = moveto,L = lineto,H = horizontal lineto,V = vertical lineto,C = curveto,S = smooth curveto,Q = quadratic Bezier curve,T = smooth quadratic Bezier curveto,A = elliptical Arc,Z = closepath + Attribs = {inkex.addNS('label', 'inkscape'): label, 'style': str(inkex.Style(lineStyle)), inkex.addNS('type', 'sodipodi'): 'arc', + inkex.addNS('rx', 'sodipodi'): str(radius), inkex.addNS('ry', 'sodipodi'): str(radius), + inkex.addNS('cx', 'sodipodi'): str(centerPoint[0] + offset[0]), inkex.addNS('cy', 'sodipodi'): str(centerPoint[1] + offset[1]), + inkex.addNS('start', 'sodipodi'): '0', inkex.addNS('end', 'sodipodi'): str(2 * math.pi), + 'd': 'M ' + str(centerPoint[0] + offset[0] + radius) + ' ' + str( + centerPoint[1] + offset[1]) + arcStringA + ' ' + arcStringB + ' z'} + + return etree.SubElement(parent, inkex.addNS('path', 'svg'), Attribs) + + # --------------------------------------------- + @staticmethod + def threePoints(parent, P1, P2, P3, offset=[0, 0], label='circle', lineStyle=lineStyle.setSimpleBlack()): + """Draw a circle given 3 poins on the circle. + + The function checks if the 3 points are aligned. In this case, no circle is drawn. + + :param parent: parent object + :param P1: point coordinates [x,y] + :param P2: point coordinates [x,y] + :param P3: point coordinates [x,y] + + .. warning:: Keep in mind that Inkscape's y axis is upside down! + + :param offset: Extra offset coords [x,y] + :param label: Label of the line. Default 'arc' + :param lineStyle: Line style to be used. See :class:`lineStyle` class. Default: lineStyle=lineStyle.setSimpleBlack() + + :type parent: inkscape element object + :type P1: list + :type P2: list + :type P3: list + :type offset: list + :type label: string + :type lineStyle: lineStyle object + + :returns: the new circle object + :rtype: line Object + + **Example** + + >>> root_layer = self.document.getroot() # retrieves the root layer of the document + >>> myLineStyle = inkDraw.lineStyle.setSimpleBlack() + >>> + >>> inkDraw.circle.threePoints(parent=root_layer, P1=[0,0], P2=[30,40], P3=[-20,20], offset=[0,0], label='circle1', lineStyle=myLineStyle) + + .. image:: ../imagesDocs/circle_3P.png + :width: 200px + + """ + + [center,radius] = circle3Points(P1, P2, P3) + + return circle.centerRadius(parent, center, radius, offset, label, lineStyle) + +class rectangle(): + """ Class with methods for drawing rectangles. + + .. note:: This class contains only static methods so that your plugin class don't have to inherit it. + """ + + @staticmethod + def widthHeightCenter(parent, centerPoint, width, height, radiusX=None, radiusY=None, offset=[0, 0], label='rectangle', + lineStyle=lineStyle.setSimpleBlack()): + """Draw a rectangle given its center point and dimensions + + :param parent: Parent object + :param centerPoint: Center coordinate [x,y] + + .. warning:: Keep in mind that Inkscape's y axis is upside down! + + :param width: Dimension in X direction + :param height: Dimension in Y direction + :param radiusX: Rounding radius in X direction. If this value is ``None``, the rectangle will have sharp corners. Default: None + :param radiusY: Rounding radius in Y direction. + - If ``None``, then radiusX will also be used in Y direction. + - If ``None`` and radiusX is also ``None``, then the rectangle will have sharp corners. Default: None + :param offset: Extra offset coords [x,y] + :param label: Label of the line. Default 'circle' + :param lineStyle: Line style to be used. See :class:`lineStyle` class. Default: lineStyle=lineStyle.setSimpleBlack() + + :type parent: inkscape element object + :type centerPoint: list + :type width: float + :type height: float + :type radiusX: float + :type radiusY: float + :type offset: list + :type label: string + :type lineStyle: lineStyle object + + :returns: the new rectangle object + :rtype: rectangle Object + + **Example** + + >>> root_layer = self.document.getroot() # retrieves the root layer of the document + >>> myLineStyle=inkDraw.lineStyle.setSimpleBlack() + >>> + >>> #draws a 50x60 rectangle with radiusX=2.0 and radiusY=3.0 + >>> inkDraw.rectangle.widthHeightCenter(parent=root_layer, centerPoint=[0,0], width=50, height=60, radiusX=2.0,radiusY=3.0, offset=[0,0], label='rect1', lineStyle=myLineStyle) + """ + x = centerPoint[0] - width / 2.0 + offset[0] + y = centerPoint[1] - height / 2.0 + offset[1] + + Attribs = {inkex.addNS('label', 'inkscape'): label, 'style': str(inkex.Style(lineStyle)), 'width': str(width), 'height': str(height), + 'x': str(x), 'y': str(y), 'rx': str(radiusX), 'ry': str(radiusY)} + + if radiusX and radiusX > 0.0: + Attribs['rx'] = str(radiusX) + if radiusY is None: + Attribs['ry'] = str(radiusX) + else: + if radiusY > 0.0: + Attribs['ry'] = str(radiusY) + + return etree.SubElement(parent, inkex.addNS('rect', 'svg'), Attribs) + + @staticmethod + def corners(parent, corner1, corner2, radiusX=None, radiusY=None, offset=[0, 0], label='rectangle', lineStyle=lineStyle.setSimpleBlack()): + """Draw a rectangle given the coordinates of two oposite corners + + :param parent: Parent object + :param corner1: Coordinates of corner 1 [x,y] + + .. warning:: Keep in mind that Inkscape's y axis is upside down! + + :param corner2: Coordinates of corner 2 [x,y] + :param radiusX: Rounding radius in X direction. If this value is ``None``, the rectangle will have sharp corners. Default: None + :param radiusY: Rounding radius in Y direction. If this value is ``None``, then radiusX will also be used in Y direction. If radiusX is also ``None``, then the rectangle will have sharp corners. Default: None + :param offset: Extra offset coords [x,y] + :param label: Label of the line. Default 'circle' + :param lineStyle: Line style to be used. See :class:`lineStyle` class. Default: lineStyle=lineStyle.setSimpleBlack() + + :type parent: inkscape element object + :type corner1: list + :type corner2: list + :type radiusX: float + :type radiusY: float + :type offset: list + :type label: string + :type lineStyle: lineStyle object + + :returns: the new rectangle object + :rtype: rectangle Object + + **Example** + + >>> root_layer = self.document.getroot() # retrieves the root layer of the document + >>> myLineStyle=inkDraw.lineStyle.setSimpleBlack() + >>> + >>> #draws a rectangle with corners C1=[1,5] and C2=[6,10], with radiusX=2.0 and radiusY=3.0 + >>> inkDraw.rectangle.corners(parent=root_layer, corner1=[1,5], corner2=[6,10], radiusX=2.0,radiusY=3.0, offset=[0,0], label='rect1', lineStyle=myLineStyle) + """ + x = (corner1[0] + corner2[0]) / 2.0 + y = (corner1[1] + corner2[1]) / 2.0 + + width = abs(corner1[0] - corner2[0]) + height = abs(corner1[1] - corner2[1]) + + return rectangle.widthHeightCenter(parent, [x, y], width, height, radiusX, radiusY, offset, label, lineStyle) + + +class ellipse(): + """ Class with methods for drawing ellipses. + + .. note:: This class contains only static methods so that your plugin class don't have to inherit it. + """ + + @staticmethod + def centerRadius(parent, centerPoint, radiusX, radiusY, offset=[0, 0], label='circle', lineStyle=lineStyle.setSimpleBlack()): + """Draw an ellipse given its center point and radii + + :param parent: Parent object + :param centerPoint: Center coordinate [x,y] + + .. warning:: Keep in mind that Inkscape's y axis is upside down! + + :param radiusX: Ellipse's radius in x direction + :param radiusY: Ellipse's radius in y direction + :param offset: Extra offset coords [x,y] + :param label: Label of the line. Default 'circle' + :param lineStyle: Line style to be used. See :class:`lineStyle` class. Default: lineStyle=lineStyle.setSimpleBlack() + + :type parent: inkscape element object + :type centerPoint: list + :type radiusX: float + :type radiusY: float + :type offset: list + :type label: string + :type lineStyle: lineStyle object + + :returns: the new ellipse object + :rtype: line Object + + **Example** + + >>> root_layer = self.document.getroot() # retrieves the root layer of the document + >>> myLineStyle=inkDraw.lineStyle.setSimpleBlack() + >>> + >>> #draws the shortest arc + >>> inkDraw.ellipse.centerRadius(parent=root_layer, centerPoint=[0,0], radiusX=15.0, radiusY=25.0, offset=[5,1], label='circle1', lineStyle=myLineStyle) + """ + + # arc instructions + arcStringA = ' a %f,%f 0 1 1 %f,%f' % (radiusX, radiusY, -2 * radiusX, 0) + arcStringB = ' a %f,%f 0 1 1 %f,%f' % (radiusX, radiusY, 2 * radiusX, 0) + + # M = moveto,L = lineto,H = horizontal lineto,V = vertical lineto,C = curveto,S = smooth curveto,Q = quadratic Bezier curve,T = smooth quadratic Bezier curveto,A = elliptical Arc,Z = closepath + Attribs = {inkex.addNS('label', 'inkscape'): label, 'style': str(inkex.Style(lineStyle)), inkex.addNS('type', 'sodipodi'): 'arc', + inkex.addNS('rx', 'sodipodi'): str(radiusX), inkex.addNS('ry', 'sodipodi'): str(radiusY), + inkex.addNS('cx', 'sodipodi'): str(centerPoint[0] + offset[0]), inkex.addNS('cy', 'sodipodi'): str(centerPoint[1] + offset[1]), + inkex.addNS('start', 'sodipodi'): '0', inkex.addNS('end', 'sodipodi'): str(2 * math.pi), + 'd': 'M ' + str(centerPoint[0] + offset[0] + radiusX) + ' ' + str( + centerPoint[1] + offset[1]) + arcStringA + ' ' + arcStringB + ' z'} + + return etree.SubElement(parent, inkex.addNS('path', 'svg'), Attribs) diff --git a/extensions/fablabchemnitz/spirograph/inkscapeMadeEasy/inkscapeMadeEasy_Plot.py b/extensions/fablabchemnitz/spirograph/inkscapeMadeEasy/inkscapeMadeEasy_Plot.py new file mode 100644 index 0000000..5818dad --- /dev/null +++ b/extensions/fablabchemnitz/spirograph/inkscapeMadeEasy/inkscapeMadeEasy_Plot.py @@ -0,0 +1,1632 @@ +#!/usr/bin/python + +# -------------------------------------------------------------------------------------- +# +# inkscapeMadeEasy: - Helper module that extends Aaron Spike's inkex.py module, +# focusing productivity in inkscape extension development +# +# Copyright (C) 2016 by Fernando Moura +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# -------------------------------------------------------------------------------------- + +import math +import sys + +import inkscapeMadeEasy.inkscapeMadeEasy_Draw as inkDraw + + +def displayMsg(msg): + """Display a message to the user. + + :param msg: message + :type msg: string + + :returns: nothing + :rtype: - + + .. note:: Identical function has been also defined inside :meth:`inkscapeMadeEasy_Base.inkscapeMadeEasy` class + + """ + sys.stderr.write(msg + '\n') + + +def Dump(obj, file='./dump_file.txt', mode='w'): + """Function to easily output the result of ``str(obj)`` to a file + + :param obj: python object to sent to a file. Any object can be used, as long as ``str(obj)`` is implemented (see ``__str__()`` metaclass definition of your object) + :param file: file path. Default: ``./dump_file.txt`` + :param mode: writing mode of the file Default: ``w`` (write) + :type obj: any + :type file: string + :type mode: string + :returns: nothing + :rtype: - + + .. note:: Identical function has been also defined inside :meth:`inkscapeMadeEasy_Base.inkscapeMadeEasy` class + + This function was created to help debugging the code while it is running under inkscape. Since inkscape does not possess a terminal as today (2016), + this function overcomes partially the issue of sending things to stdout by dumping result of the function ``str()`` in a text file. + + **Example** + + >>> vector1=[1,2,3,4,5,6] + >>> inkPlot.Dump(vector1,file='~/temporary.txt',mode='w') # writes the list to a file + >>> vector2=[7,8,9,10] + >>> inkPlot.Dump(vector2,file='~/temporary.txt',mode='a') # append the list to a file + """ + + with open(file, mode) as file: + file.write(str(obj) + '\n') + + +def generateListOfTicksLinear(axisLimits, axisOrigin, tickStep): + """Defines list of ticks in a linear plot + + .. note:: Internal function. + """ + + # make the list of ticks, symmetrically to the origin + listTicksPositive = [axisOrigin] + while listTicksPositive[-1] < axisLimits[1]: + listTicksPositive.append(listTicksPositive[-1] + tickStep) + + listTicksNegative = [axisOrigin] + + while listTicksNegative[-1] > axisLimits[0]: + listTicksNegative.append(listTicksNegative[-1] - tickStep) + + listTicks = listTicksPositive + listTicksNegative[1:] + return listTicks + + +def generateListOfTicksLog10(axisLimits): + """Defines list of ticks in a log10 plot + + .. note:: Internal function. + """ + + # make the list of ticks, symmetrically to the origin + listTicks = [axisLimits[0]] + while listTicks[-1] < axisLimits[1]: + listTicks.append(listTicks[-1] * 10) + return listTicks + + +def findOrigin(axisLimits, flagLog10, scale): + """ retrieves the position of the origin. In case of logarithmic scale, it will be axisLimits[0] + + .. note:: Internal function. + """ + if flagLog10: + axisOrigin = math.log10(axisLimits[0]) * scale + else: + if axisLimits[0] <= 0.0 and axisLimits[1] >= 0.0: + axisOrigin = 0.0 + else: + if axisLimits[1] < 0: + axisOrigin = axisLimits[1] * scale + else: + axisOrigin = axisLimits[0] * scale + + return axisOrigin + + +def getPositionAndText(value, scale, flagLog10, axisUnitFactor): + """given a value, its scale, and some flags, finds it position in the diagram and the text to be shown + + .. note:: Internal function.""" + if flagLog10: + pos = math.log10(value) * scale + else: + pos = value * scale + # try to simplify number + if int(value) - value == 0: + valStr = str(int(round(value, 3))) + else: + valStr = str(round(value, 3)) + + # option to add extra factor to the axis ticks + if flagLog10: + exponent = str(int(math.log10(value))) + if axisUnitFactor: + if inkDraw.useLatex: + Text = '10^{' + exponent + '}' + axisUnitFactor + '' + else: + Text = '10^' + exponent + '' + axisUnitFactor + '' + else: + if inkDraw.useLatex: + Text = '10^{' + exponent + '}' + else: + Text = '10^' + exponent + '' + else: + if axisUnitFactor: + if value == 0: + Text = '0' + if value == 1: + Text = axisUnitFactor + if value == -1: + Text = '-' + axisUnitFactor + if value != 0 and value != 1 and value != -1: + Text = valStr + axisUnitFactor + else: + Text = valStr + + if inkDraw.useLatex: + Text = '$' + Text + '$' + + return [pos, Text] + + +class axis(): + """ This class has member functions to create customizable plot axes. + + .. note:: This class contains only static methods so that your plugin class don't have to inherit it. + + .. note:: This class can use LaTeX to render text if LaTeX support is enabled. LaTeX support is an optional feature that requires a few extra packages to be installed outside inkscape. **It is enabled by default**. + Please refer to :ref:`disableLatexSupport` on how to disable it. If disabled, this function will still work, internally calling the :meth:`inkscapeMadeEasy_Draw.text.write` to generate text. + """ + + @staticmethod + def cartesian(ExtensionBaseObj, parent, xLim, yLim, position=[0, 0], xLabel='', yLabel='', xlog10scale=False, ylog10scale=False, xTicks=True, + yTicks=True, xTickStep=1.0, yTickStep=1.0, xScale=20, yScale=20, xAxisUnitFactor='', yAxisUnitFactor='', xGrid=False, yGrid=False, + forceTextSize=0, forceLineWidth=0, drawAxis=True, ExtraLengthAxisX=0.0, ExtraLengthAxisY=0.0): + """Creates the axes of a cartesian plot + + .. note:: This method uses LaTeX in labels and tick marks if LaTeX support is enabled. This is an optional feature, **enabled by default**. Please refer to :ref:`disableLatexSupport` on how to disable it. + + :param ExtensionBaseObj: Most of the times you have to pass 'self' when calling from inside your plugin class. See example below + :param parent: Parent object + :param xLim: Limits of the X axis [x_min,x_max]. If the axis is in log10 scale, then the limits will be rounded to complete one decade. + :param yLim: Limits of the Y axis [y_min,y_max]. If the axis is in log10 scale, then the limits will be rounded to complete one decade. + :param position: Position of the plot. It is defined at the point where x and y axis cross [x0,y0]. The point where the axis cross depend on the limits. + + - If xLimits comprises the origin x=0, then the Y axis crosses the X axis at x=0. + - If xLimits contains only negative numbers, then the Y axis crosses the X axis at x_max. + - If xLimits contains only positive numbers, then the Y axis crosses the X axis at x_min. + + - The same rule applies to y direction. + :param xLabel: Label of the X axis. Default: '' + + The text can contain any LaTeX command. If you want to write mathematical text, you can enclose it between dollar signs $...$. If LaTeX support is disabled, do not use $. + + :param yLabel: Label of the Y axis. Default: '' + + The text can contain any LaTeX command. If you want to write mathematical text, you can enclose it between dollar signs $...$. If LaTeX support is disabled, do not use $. + + :param xlog10scale: Sets X axis to log10 scale if True. Default: False + :param ylog10scale: Sets Y axis to log10 scale if True. Default: False + :param xTicks: Adds axis ticks to the X axis if True. Default: True + :param yTicks: Adds axis ticks to the Y axis if True. Default: True + :param xTickStep: Value interval between two consecutive ticks on X axis. (Not used if X axis is in log10 scale). Default:1.0 + :param yTickStep: Value interval between two consecutive ticks on Y axis. (Not used if Y axis is in log10 scale). Default:1.0 + :param xScale: Distance between each xTickStep in svg units. Default: 20 + + - If axis is linear, then xScale is the size in svg units of each tick + - If axis is log10, the xScale is the size in svg units of one decade + + :param yScale: Distance between each yTickStep in svg units. Default: 20 + + - If axis is linear, then yScale is the size in svg units of each tick + - If axis is log10, the yScale is the size in svg units of one decade + + :param xAxisUnitFactor: Extra text to be added to the ticks in X axis. Default: '' + + This is useful when we want to represent interval with different units. example pi, 2pi 3pi, etc. + The text can be any LaTeX text. Keep in mind that this text will be inserted within a mathematical environment $...$, therefore no $ is needed here. + :param yAxisUnitFactor: Extra text to be added to the ticks in Y axis. Default: '' + + This is useful when we want to represent interval with different units. example pi, 2pi 3pi, etc. + The text can be any LaTeX text. Keep in mind that this text will be inserted within a mathematical environment $...$, therefore no $ is needed here. + + :param xGrid: Adds grid lines to X axis if True. Default: False + :param yGrid: Adds grid lines to Y axis if True. Default: False + :param forceTextSize: Size of the text. If this parameter is 0.0 then the method will compute an appropriate size. Default: 0.0 + :param forceLineWidth: Width of the lines. If this parameter is 0.0 then the method will compute an appropriate size. Default: 0.0 + + :param drawAxis: Control flag of the axis method + + - True: draws axis normally + - False: returns the limits and origin position without drawing the axis itself + + :param ExtraLengthAxisX: Extra length near the arrow pointer of X axis. Default 0.0 + :param ExtraLengthAxisY: Extra length near the arrow pointer of Y axis. Default 0.0 + + :type ExtensionBaseObj: inkscapeMadeEasy object + :type parent: inkscape element object + :type xLim: list + :type yLim: list + :type position: list + :type xLabel: string + :type yLabel: string + :type xlog10scale: bool + :type ylog10scale: bool + :type xTicks: bool + :type yTicks: bool + :type xTickStep: float + :type yTickStep: float + :type xScale: float + :type yScale: float + :type xAxisUnitFactor: string + :type yAxisUnitFactor: string + :type xGrid: bool + :type yGrid: bool + :type forceTextSize: float + :type forceLineWidth: float + :type drawAxis: bool + :type ExtraLengthAxisX: float + :type ExtraLengthAxisY: float + + :returns: [GroupPlot, outputLimits, axisOrigin] + + - GroupPlot: the axis area object (if drawAxis=False, this output is ``None``) + - outputLimits: a list with tuples:[(x_min,xPos_min),(x_max,xPos_max),(y_min,yPos_min),(y_max,yPos_max)] + + - x_min, x_max, y_min, y_max: The limits of the axis object + - xPos_min, xPos_max, yPos_min, yPos_max: The positions of the limits of the axis object, considering the scaling and units + - axisOrigin [X0,Y0]: A list with the coordinates of the point where the axes cross. + :rtype: list + + **Examples** + + >>> root_layer = self.document.getroot() # retrieves the root layer of the document + >>> + >>> inkPlot.axis.cartesian(ExtensionBaseObj, parent=root_layer, xLim=[0,3], yLim=[0,2], position=[0, 0], + >>> xLabel='my label $x$', yLabel='my label $y$', xlog10scale=False, ylog10scale=False, + >>> xTicks=True, yTicks=True, xTickStep=0.5, yTickStep=1.0, xScale=50, yScale=60, + >>> xAxisUnitFactor='', yAxisUnitFactor='', xGrid=True, yGrid=True, forceTextSize=0, forceLineWidth=0, + >>> drawAxis=True, ExtraLengthAxisX=20.0, ExtraLengthAxisY=10.0) + + The images below show the cartesian plane of the example above, together with other variations. + + .. image:: ../imagesDocs/plot_axisCartesianParameters_01.png + :width: 800px + + """ + if drawAxis: + GroupPlot = ExtensionBaseObj.createGroup(parent, 'Plot') + + # sets the scale scaleX and scaleY stores the size of one unit in both axis (linear axis) or the size of a decade in log plots + if xlog10scale: + scaleX = xScale + else: + scaleX = xScale / float(xTickStep) + + if ylog10scale: + scaleY = -yScale + else: + scaleY = -yScale / float(yTickStep) # negative bc inkscape is upside down + + # font size and other text parameters + if forceTextSize == 0: + textSize = 0.25 * min(xScale, yScale) + else: + textSize = forceTextSize + + textSizeSmall = 0.8 * textSize # font size for axis ticks + + text_offset = textSize # base space for text positioning + ExtraSpaceArrowX = (2.0 + ExtraLengthAxisX) * text_offset # extra space for drawing arrow on axis + ExtraSpaceArrowY = (3.0 + ExtraLengthAxisY) * text_offset # extra space for drawing arrow on axis + lenghtTicks = textSize / 2.0 # length of the ticks + + # create styles + if forceLineWidth == 0: + lineWidth = min(xScale, yScale) / 35.0 + else: + lineWidth = forceLineWidth + + lineWidthGrid = 0.7 * lineWidth + lineWidthGridFine = lineWidthGrid / 2.0 + + nameMarkerArrowAxis = inkDraw.marker.createArrow1Marker(ExtensionBaseObj, 'ArrowAxis', RenameMode=1, scale=0.4) + lineStyleAxis = inkDraw.lineStyle.set(lineWidth, lineColor=inkDraw.color.gray(0.3), markerEnd=nameMarkerArrowAxis[1]) + lineStyleTicks = inkDraw.lineStyle.set(lineWidth, lineColor=inkDraw.color.gray(0.3)) + lineStyleGrid = inkDraw.lineStyle.set(lineWidthGrid, lineColor=inkDraw.color.gray(0.7)) + lineStyleGridFine = inkDraw.lineStyle.set(lineWidthGridFine, lineColor=inkDraw.color.gray(0.7)) + + textStyleLarge = inkDraw.textStyle.setSimpleBlack(textSize) + textStyleSmall = inkDraw.textStyle.setSimpleBlack(textSizeSmall, 'center') + + # check if limits are valid + if xLim[0] >= xLim[1]: + sys.stderr.write('Error: xLim is invalid.') + return 0 + if yLim[0] >= yLim[1]: + sys.stderr.write('Error: yLim is invalid.') + return 0 + # check if the limits are valid for logarithmic scales. + if xlog10scale: + if xLim[0] <= 0 or xLim[1] <= 0: + sys.stderr.write('Error: xLim is invalid in logarithmic scale') + return 0 + else: + xmin = pow(10, math.floor(math.log10(xLim[0]))) + xmax = pow(10, math.ceil(math.log10(xLim[1]))) + xLimits = [xmin, xmax] + else: + xLimits = xLim + + if ylog10scale: + if yLim[0] <= 0 or yLim[1] <= 0: + sys.stderr.write('Error: yLim is invalid in logarithmic scale') + return 0 + else: + ymin = pow(10, math.floor(math.log10(yLim[0]))) + ymax = pow(10, math.ceil(math.log10(yLim[1]))) + yLimits = [ymin, ymax] + else: + yLimits = yLim + + # finds the position of the Origin of axis + axisOrigin = [0.0, 0.0] + + axisOrigin[0] = findOrigin(xLimits, xlog10scale, scaleX) + axisOrigin[1] = findOrigin(yLimits, ylog10scale, scaleY) + + # computes the positions of the limits on svg, considering the scale + + if xlog10scale: # convert limits to position in diagram, including scaling factor + xLimitsPos = [math.log10(x) * scaleX for x in xLimits] + else: + xLimitsPos = [x * scaleX for x in xLimits] + + if ylog10scale: # convert limits to position in diagram, including scaling factor + yLimitsPos = [math.log10(y) * scaleY for y in yLimits] + else: + yLimitsPos = [y * scaleY for y in yLimits] + + # build the list of tuples with the limits of the plotting area + outputLimits = list(zip([xLimits[0], xLimits[1], yLimits[0], yLimits[1]], + [xLimitsPos[0] - axisOrigin[0] + position[0], xLimitsPos[1] - axisOrigin[0] + position[0], + yLimitsPos[0] - axisOrigin[1] + position[1], yLimitsPos[1] - axisOrigin[1] + position[1]])) + if not drawAxis: + return [None, outputLimits, axisOrigin] + + # axis ticks + groupTicks = ExtensionBaseObj.createGroup(GroupPlot, 'Ticks') + + if xTicks or xGrid: + + if xlog10scale: + listTicks = generateListOfTicksLog10(xLimits) + else: + listTicks = generateListOfTicksLinear(xLimits, axisOrigin[0] / scaleX, xTickStep) + for x in listTicks: + + if x <= xLimits[1] and x >= xLimits[0]: + + # get position, considering the scale and its text + [posX, xText] = getPositionAndText(x, scaleX, xlog10scale, xAxisUnitFactor) + + if xGrid and posX != axisOrigin[0]: # grid lines. Do not draw if grid line is over the axis + inkDraw.line.absCoords(groupTicks, [[posX, yLimitsPos[0]], [posX, yLimitsPos[1]]], [0, 0], lineStyle=lineStyleGrid) + + # intermediate grid lines in case of logarithmic scale + if xGrid and xlog10scale and x < xLimits[1]: + for i in range(2, 10): + aditionalStep = math.log10(i) * scaleX + inkDraw.line.absCoords(groupTicks, [[posX + aditionalStep, yLimitsPos[0]], [posX + aditionalStep, yLimitsPos[1]]], [0, 0], + lineStyle=lineStyleGridFine) + + # tick + if xTicks: + if posX != axisOrigin[0]: # don't draw if in the origin + inkDraw.line.relCoords(groupTicks, [[0, lenghtTicks]], [posX, axisOrigin[1] - lenghtTicks / 2.0], + lineStyle=lineStyleTicks) + + # sets justification + # inkDraw.text.write(ExtensionBaseObj,'orig='+str(axisOrigin),[axisOrigin[0]+10,axisOrigin[1]-30],groupTicks,fontSize=7) + # inkDraw.text.write(ExtensionBaseObj,'xlim='+str(xLimitsPos),[axisOrigin[0]+10,axisOrigin[1]-20],groupTicks,fontSize=7) + # inkDraw.text.write(ExtensionBaseObj,'ylim='+str(yLimitsPos),[axisOrigin[0]+10,axisOrigin[1]-10],groupTicks,fontSize=7) + + if axisOrigin[1] == yLimitsPos[0]: + justif = 'tc' + offsetX = 0 + offsetY = text_offset / 2.0 # inkDraw.circle.centerRadius(groupTicks, axisOrigin, 10, [0,0]) + + if axisOrigin[1] != yLimitsPos[0] and axisOrigin[1] != yLimitsPos[1]: + justif = 'tr' + offsetX = -text_offset / 4.0 + offsetY = text_offset / 2.0 + # inkDraw.circle.centerRadius(groupTicks, axisOrigin, 10, [0,0]) + # inkDraw.text.write(ExtensionBaseObj,str(axisOrigin[1]),[axisOrigin[0]+10,axisOrigin[1]+10],groupTicks,fontSize=7) + # inkDraw.text.write(ExtensionBaseObj,str(yLimitsPos[0]),[axisOrigin[0]+10,axisOrigin[1]+20],groupTicks,fontSize=7) + if posX == axisOrigin[0]: + if posX == xLimitsPos[1]: + justif = 'tr' + offsetX = -text_offset / 4.0 + else: + justif = 'tl' + offsetX = +text_offset / 4.0 + + if axisOrigin[1] == yLimitsPos[1]: + justif = 'bc' + offsetX = 0 + offsetY = -text_offset / 2.0 + # inkDraw.circle.centerRadius(groupTicks,axisOrigin, 10, [0,0]) + if posX == axisOrigin[0]: + if posX == xLimitsPos[1]: + justif = 'br' + offsetX = -text_offset / 4.0 + else: + justif = 'bl' + offsetX = +text_offset / 4.0 + + # value + if xTicks: + inkDraw.text.latex(ExtensionBaseObj, groupTicks, xText, [posX + offsetX, axisOrigin[1] + offsetY], textSizeSmall, + refPoint=justif) + + if yTicks or yGrid: + # approximate limits to multiples of 10 + if ylog10scale: + listTicks = generateListOfTicksLog10(yLimits) + else: + listTicks = generateListOfTicksLinear(yLimits, axisOrigin[1] / scaleY, yTickStep) + + for y in listTicks: + if y <= yLimits[1] and y >= yLimits[0]: + + # get position, considering the scale and its text + [posY, yText] = getPositionAndText(y, abs(scaleY), ylog10scale, yAxisUnitFactor) + posY = -posY + + if yGrid and posY != axisOrigin[1]: # grid lines. Do not draw if grid line is over the axis + inkDraw.line.absCoords(groupTicks, [[xLimitsPos[0], posY], [xLimitsPos[1], posY]], [0, 0], lineStyle=lineStyleGrid) + + # intermediate grid lines in case of logarithmic scale + if yGrid and ylog10scale and y < yLimits[1]: + for i in range(2, 10): + aditionalStep = math.log10(i) * scaleY + inkDraw.line.absCoords(groupTicks, [[xLimitsPos[0], posY + aditionalStep], [xLimitsPos[1], posY + aditionalStep]], [0, 0], + lineStyle=lineStyleGridFine) + + # tick + if yTicks: + if posY != axisOrigin[1]: # don't draw if in the origin + inkDraw.line.relCoords(groupTicks, [[lenghtTicks, 0]], [axisOrigin[0] - lenghtTicks / 2.0, posY], + lineStyle=lineStyleTicks) + + # sets justification + # inkDraw.text.write(ExtensionBaseObj,'orig='+str(axisOrigin),[axisOrigin[0]+10,axisOrigin[1]-30],groupTicks,fontSize=7) + # inkDraw.text.write(ExtensionBaseObj,'xlim='+str(xLimitsPos),[axisOrigin[0]+10,axisOrigin[1]-20],groupTicks,fontSize=7) + # inkDraw.text.write(ExtensionBaseObj,'ylim='+str(yLimitsPos),[axisOrigin[0]+10,axisOrigin[1]-10],groupTicks,fontSize=7) + + if axisOrigin[0] == xLimitsPos[0]: + justif = 'cr' + offsetX = -text_offset / 2.0 + offsetY = 0 # inkDraw.circle.centerRadius(groupTicks,axisOrigin, 10, [0,0],'trash') + + if axisOrigin[0] != xLimitsPos[0] and axisOrigin[0] != xLimitsPos[1]: + justif = 'tr' + offsetX = -text_offset / 2.0 + offsetY = text_offset / 4.0 + # inkDraw.circle.centerRadius(groupTicks,axisOrigin, 10, [0,0]) + # inkDraw.text.write(ExtensionBaseObj,str(axisOrigin[0]),[axisOrigin[0]+10,axisOrigin[1]+10],groupTicks,fontSize=7) + # inkDraw.text.write(ExtensionBaseObj,str(yLimitsPos[0]*scaleX),[axisOrigin[0]+10,axisOrigin[1]+20],groupTicks,fontSize=7) + if posY == axisOrigin[1]: + if posY == yLimitsPos[1]: + justif = 'tr' + offsetY = text_offset / 4.0 + else: + justif = 'br' + offsetY = -text_offset / 4.0 + + if axisOrigin[0] == xLimitsPos[1]: + justif = 'cl' + offsetX = text_offset / 2.0 + offsetY = 0 + # inkDraw.circle.centerRadius(groupTicks,axisOrigin, 10, [0,0]) + if posY == axisOrigin[1]: + if posY == yLimitsPos[1]: + justif = 'tl' + offsetY = text_offset / 4.0 + else: + justif = 'bl' + offsetY = -text_offset / 4.0 + + # value + if yTicks: + inkDraw.text.latex(ExtensionBaseObj, groupTicks, yText, [axisOrigin[0] + offsetX, (posY + offsetY)], textSizeSmall, + refPoint=justif) + + ExtensionBaseObj.moveElement(GroupPlot, [position[0] - axisOrigin[0], position[1] - axisOrigin[1]]) + + # draw axis in the end so it stays on top of other objects + GroupAxis = ExtensionBaseObj.createGroup(GroupPlot, 'Axis') + + inkDraw.line.absCoords(GroupAxis, [[xLimitsPos[0], 0], [xLimitsPos[1] + ExtraSpaceArrowX, 0]], [0, axisOrigin[1]], 'Xaxis', + lineStyle=lineStyleAxis) + if xLabel: # axis labels + inkDraw.text.latex(ExtensionBaseObj, GroupAxis, xLabel, + [xLimitsPos[1] + ExtraSpaceArrowX - text_offset / 3, axisOrigin[1] + text_offset / 2.0], textSize, refPoint='tl') + + inkDraw.line.absCoords(GroupAxis, [[0, yLimitsPos[0]], [0, yLimitsPos[1] - ExtraSpaceArrowY]], [axisOrigin[0], 0], 'Yaxis', + lineStyle=lineStyleAxis) + if yLabel: # axis labels + inkDraw.text.latex(ExtensionBaseObj, GroupAxis, yLabel, [axisOrigin[0] + text_offset / 2.0, (yLimitsPos[1] - ExtraSpaceArrowY)], textSize, + refPoint='tl') + + return [GroupPlot, outputLimits, axisOrigin] + + @staticmethod + def polar(ExtensionBaseObj, parent, rLim, tLim=[0.0, 360.0], position=[0.0, 0.0], rLabel='', rlog10scale=False, rTicks=True, tTicks=True, + rTickStep=1.0, tTickStep=45.0, rScale=20, rAxisUnitFactor='', rGrid=False, tGrid=False, forceTextSize=0, forceLineWidth=0, + drawAxis=True, ExtraLengthAxisR=0.0): + """Creates the axes of a polar plot + + .. note:: This method uses LaTeX in labels and tick marks if LaTeX support is enabled. This is an optional feature, **enabled by default**. + Please refer to :ref:`disableLatexSupport` on how to disable it. + + :param ExtensionBaseObj: Most of the times you have to pass 'self' when calling from inside your plugin class. See example below + :param parent: Parent object + :param rLim: Limits of the R axis [r_min,r_max]. If the axis is in log10 scale, then the limits will be rounded to complete one decade. + :param tLim: Limits of the theta axis [t_min,t_max]. Values in degrees. Default: [0,360] + :param position: Position of the center [x0,y0]. + + :param rLabel: Label of the R axis. Default: '' + + The text can contain any LaTeX command. If you want to write mathematical text, you can enclose it between dollar signs $...$. If LaTeX support is disabled, do not use $. + + :param rlog10scale: Sets R axis to log10 scale if True. Default: False + + - If rlog10scale=True, then the lower limit of rLim must be >=1 + + :param rTicks: Adds axis ticks to the R axis if True. Default: True + :param tTicks: Adds axis ticks to the theta axis if True. Default: True + :param rTickStep: Value interval between two consecutive ticks on R axis. (Not used if R axis is in log10 scale). Default:1.0 + :param tTickStep: Value interval between two consecutive ticks on theta axis. Default:45.0 + :param rScale: Distance between each rTickStep in svg units. Default: 20 + + - If axis is linear, then rScale is the size in svg units of each tick + - If axis is log10, the rScale is the size in svg units of one decade + + :param rAxisUnitFactor: Extra text to be added to the ticks in R axis. Default: '' + + This is useful when we want to represent interval with different units. example pi, 2pi 3pi, etc. + The text can be any LaTeX text. Keep in mind that this text will be inserted within a mathematical environment $...$, therefore no $ is needed here. + + :param rGrid: Adds grid lines to R axis if true. Default: False + :param tGrid: Adds grid lines to theta axis if true. Default: False + :param forceTextSize: Size of the text. If this parameter is 0.0 then the method will compute an appropriate size. Default: 0.0 + :param forceLineWidth: Width of the lines. If this parameter is 0.0 then the method will compute an appropriate size. Default: 0.0 + + :param drawAxis: Control flag of the axis method + + - True: draws axis normally + - False: returns the limits and origin position without drawing the axis itself + + :param ExtraLengthAxisR: Extra length between the R axis and its label. Default 0.0 + + :type ExtensionBaseObj: inkscapeMadeEasy object + :type parent: inkscape element object + :type rLim: list + :type tLim: list + :type position: list + :type rLabel: string + :type rlog10scale: bool + :type rTicks: bool + :type tTicks: bool + :type rTickStep: float + :type tTickStep: float + :type rScale: float + :type rAxisUnitFactor: string + :type rGrid: bool + :type tGrid: bool + :type forceTextSize: float + :type forceLineWidth: float + :type drawAxis: bool + :type ExtraLengthAxisR: float + + :returns: [GroupPlot, outputRLimits, axisOrigin] + + - GroupPlot: the axis area object (if drawAxis=False, this output is ``None``) + - outputRLimits: a list with tuples:[(r_min,rPos_min),(r_max,rPos_max)] + + - r_min, r_max : The limits of the axis object + - rPos_min, rPos_max : The positions of the limits of the axis object, considering the scaling and units + - axisOrigin [X0,Y0] : A list with the coordinates of the point where the axes cross. + :rtype: list + + **Examples** + + >>> root_layer = self.document.getroot() # retrieves the root layer of the document + >>> + >>> inkPlot.axis.cartesian(self, parent=root_layer, rLim=[0, 3], tLim=[0, 150], position=[0.0, 0.0], rLabel='my radius', + >>> rlog10scale=False, rTicks=True, tTicks=True, rTickStep=1.0, tTickStep=30.0, rScale=50, + >>> rAxisUnitFactor='', rGrid=True, tGrid=True, forceTextSize=0, forceLineWidth=0, + >>> drawAxis=True, ExtraLengthAxisR=10.0) + + The images below show the cartesian plane of the example above, together with other variations. + + .. image:: ../imagesDocs/plot_axisPolarParameters_01.png + :width: 800px + """ + + if drawAxis: + GroupPlot = ExtensionBaseObj.createGroup(parent, 'Plot') + + # sets the scale scaleX and scaleY stores the size of one unit in both axis (linear axis) or the size of a decade in log plots + if rlog10scale: + scaleR = rScale + else: + scaleR = rScale / float(rTickStep) + + # font size and other text parameters + if forceTextSize == 0: + textSize = 0.2 * rScale + else: + textSize = forceTextSize + + textSizeSmall = 0.8 * textSize # font size for axis ticks + + text_offset = textSize # base space for text positioning + ExtraSpaceArrowR = (2.0 + ExtraLengthAxisR) * text_offset # extra space for drawing arrow on axis + lenghtTicks = textSize / 2.0 # length of the ticks + + # create styles + if forceLineWidth == 0: + lineWidth = rScale / 30.0 + else: + lineWidth = forceLineWidth + + lineWidthGrid = 0.7 * lineWidth + lineWidthGridFine = lineWidthGrid / 2.0 + + # nameTickerArrowAxis = inkDraw.marker.createArrow1Marker(ExtensionBaseObj, 'ArrowAxis', RenameMode=1, scale=0.4) + lineStyleAxis = inkDraw.lineStyle.set(lineWidth, lineColor=inkDraw.color.gray(0.3)) + lineStyleTicks = inkDraw.lineStyle.set(lineWidth, lineColor=inkDraw.color.gray(0.3)) + lineStyleGrid = inkDraw.lineStyle.set(lineWidthGrid, lineColor=inkDraw.color.gray(0.7)) + lineStyleGridFine = inkDraw.lineStyle.set(lineWidthGridFine, lineColor=inkDraw.color.gray(0.7)) + + textStyleLarge = inkDraw.textStyle.setSimpleBlack(textSize) + textStyleSmall = inkDraw.textStyle.setSimpleBlack(textSizeSmall, 'center') + + # check if limits are valid + if rLim[0] < 0.0 or rLim[0] >= rLim[1]: + sys.stderr.write('Error: rLim is invalid') + return 0 + if tLim[0] >= tLim[1]: + sys.stderr.write('Error: tLim is invalid') + return 0 + # check if the limits are valid for logarithmic scales. + if rlog10scale: + if rLim[0] < 1 or rLim[1] < 1: + sys.stderr.write('Error: rLim is invalid in logarithmic scale') + return 0 + else: + rmin = pow(10, math.floor(math.log10(rLim[0]))) + rmax = pow(10, math.ceil(math.log10(rLim[1]))) + rLimits = [rmin, rmax] + else: + rLimits = rLim + + tLimits = tLim + + if abs(tLimits[1] - tLimits[0]) > 360: + tLimits = [0, 360] + + if abs(tLimits[1] - tLimits[0]) > 180: + largeArc = True + else: + largeArc = False + + # finds the position of the Origin of axis + axisOrigin = [0.0, 0.0] + axisOrigin[0] = findOrigin(rLimits, rlog10scale, scaleR) + axisOrigin[1] = findOrigin(tLimits, False, 1.0) + + # computes the positions of the limits on svg, considering the scale + + if rlog10scale: # convert limits to position in diagram, including scaling factor + rLimitsPos = [math.log10(x) * scaleR for x in rLimits] + else: + rLimitsPos = [x * scaleR for x in rLimits] + + # build the list of tuples with the limits of the plotting area + outputLimits = list(zip([rLimits[0], rLimits[1]], [rLimitsPos[0] - axisOrigin[0] + position[0], rLimitsPos[1] - axisOrigin[0] + position[0]])) + + if not drawAxis: + return [None, outputLimits, [0, 0]] + + # axis ticks + groupTicks = ExtensionBaseObj.createGroup(GroupPlot, 'Ticks') + + if rTicks or rGrid: + + if rlog10scale: + listTicks = generateListOfTicksLog10(rLimits) + else: + listTicks = generateListOfTicksLinear(rLimits, axisOrigin[0] / scaleR, rTickStep) + for r in listTicks: + + if r <= rLimits[1] and r >= rLimits[0]: + + # get position, considering the scale and its text + [posR, rText] = getPositionAndText(r, scaleR, rlog10scale, rAxisUnitFactor) + + if rGrid and posR > 0.0 and r > rLimits[0] and r < rLimits[1]: # grid lines. + if tLimits[1] - tLimits[0] < 360: + inkDraw.arc.centerAngStartAngEnd(groupTicks, [0, 0], posR, -tLimits[1], -tLimits[0], [0, 0], lineStyle=lineStyleGrid, + largeArc=largeArc) # negative angles bc inkscape is upside down + else: + inkDraw.circle.centerRadius(groupTicks, [0, 0], posR, offset=[0, 0], lineStyle=lineStyleGrid) + + # intermediate grid lines in case of logarithmic scale + if rGrid and rlog10scale and r < rLimits[1]: + for i in range(2, 10): + aditionalStep = math.log10(i) * scaleR + if tLimits[1] - tLimits[0] < 360: + inkDraw.arc.centerAngStartAngEnd(groupTicks, [0, 0], posR + aditionalStep, -tLimits[1], -tLimits[0], [0, 0], + lineStyle=lineStyleGridFine, + largeArc=largeArc) # negative angles bc inkscape is upside down + else: + inkDraw.circle.centerRadius(groupTicks, [0, 0], posR + aditionalStep, offset=[0, 0], lineStyle=lineStyleGridFine) + + # tick + if rTicks and posR > 0.0: + inkDraw.arc.centerAngStartAngEnd(groupTicks, [0, 0], posR, -tLimits[0] - math.degrees(lenghtTicks / float(posR * 2)), + -tLimits[0] + math.degrees(lenghtTicks / float(posR * 2)), [0, 0], lineStyle=lineStyleTicks, + largeArc=False) + if rTicks and posR == 0.0: + inkDraw.line.relCoords(groupTicks, [[0, lenghtTicks]], [0, - lenghtTicks / 2.0], lineStyle=lineStyleTicks) + + # sets justification + # inkDraw.text.write(ExtensionBaseObj,'orig='+str(axisOrigin),[axisOrigin[0]+10,axisOrigin[1]-30],groupTicks,fontSize=7) + # inkDraw.text.write(ExtensionBaseObj,'xlim='+str(xLimitsPos),[axisOrigin[0]+10,axisOrigin[1]-20],groupTicks,fontSize=7) + # inkDraw.text.write(ExtensionBaseObj,'ylim='+str(yLimitsPos),[axisOrigin[0]+10,axisOrigin[1]-10],groupTicks,fontSize=7) + + if posR == 0: + justif = 'cc' + offsetX = 0 + offsetY = text_offset * 1.2 + posX = posR * math.cos(math.radians(-tLimits[0])) + offsetX + posY = posR * math.sin(math.radians(-tLimits[0])) + offsetY + else: + offsetT = text_offset * 1.2 + if tLimits[1] - tLimits[0] > 340: + offsetR = text_offset / 2.0 + else: + offsetR = 0 + justif = 'cc' + posX = (posR + offsetR) * math.cos(math.radians(-tLimits[0])) + offsetT * math.sin(math.radians(tLimits[0])) + posY = (posR + offsetR) * math.sin(math.radians(-tLimits[0])) + offsetT * math.cos(math.radians(-tLimits[0])) + # value + # inkDraw.circle.centerRadius(groupTicks,[posX,posY], 1) + if rTicks: + inkDraw.text.latex(ExtensionBaseObj, groupTicks, rText, [posX, posY], textSizeSmall, refPoint=justif) + + if tTicks or tGrid: + + listTicks = generateListOfTicksLinear(tLimits, axisOrigin[1], tTickStep) + for t in listTicks: + if t <= tLimits[1] and t >= tLimits[0]: + c = math.cos(math.radians(-t)) # negative angles bc inkscape is upside down + s = math.sin(math.radians(-t)) # negative angles bc inkscape is upside down + # get position, considering the scale and its text + if inkDraw.useLatex: + tText = '$' + str(t) + '$' + else: + tText = str(t) + + if (tGrid and t > tLimits[0] and t < tLimits[1]) or (tGrid and t == tLimits[0] and tLimits[1] - tLimits[0] >= 360): + if rLimitsPos[0] == 0: # if rmin is zero, then make the lines to reach the center + if not rlog10scale: + P1 = [(rLimitsPos[0] + scaleR * rTickStep / 2) * c, (rLimitsPos[0] + scaleR * rTickStep / 2) * s] + else: + P1 = [(rLimitsPos[0] + 0.3 * scaleR) * c, (rLimitsPos[0] + 0.3 * scaleR) * s] + else: + P1 = [rLimitsPos[0] * c, rLimitsPos[0] * s] + P2 = [rLimitsPos[1] * c, rLimitsPos[1] * s] + inkDraw.line.absCoords(groupTicks, [P1, P2], [0, 0], lineStyle=lineStyleGrid) + + # tick + if (tTicks and t != tLimits[1]) or (tTicks and t == tLimits[1] and tLimits[1] - tLimits[0] < 360): + P1 = [(rLimitsPos[1] - lenghtTicks / 2.0) * c, (rLimitsPos[1] - lenghtTicks / 2.0) * s] + inkDraw.line.relCoords(groupTicks, [[lenghtTicks * c, lenghtTicks * s]], P1, lineStyle=lineStyleTicks) + + if c > 1.0e-4: + justif = 'cl' + else: + if c < -1.0e-4: + justif = 'cr' + else: + justif = 'cc' + + offsetR = text_offset + posX = (rLimitsPos[1] + offsetR) * c + posY = (rLimitsPos[1] + offsetR) * s + # value + if (tTicks and t != tLimits[1]) or (tTicks and t == tLimits[1] and tLimits[1] - tLimits[0] < 360): + inkDraw.text.latex(ExtensionBaseObj, groupTicks, tText, [posX, posY], textSizeSmall, refPoint=justif) + + ExtensionBaseObj.moveElement(GroupPlot, position) + + # draw axis in the end so it stays on top of other objects + GroupAxis = ExtensionBaseObj.createGroup(GroupPlot, 'Axis') + + c0 = math.cos(math.radians(-tLimits[0])) # negative angles bc inkscape is upside down + s0 = math.sin(math.radians(-tLimits[0])) # negative angles bc inkscape is upside down + c1 = math.cos(math.radians(-tLimits[1])) # negative angles bc inkscape is upside down + s1 = math.sin(math.radians(-tLimits[1])) # negative angles bc inkscape is upside down + P1 = [rLimitsPos[0] * c0, rLimitsPos[0] * s0] + P2 = [rLimitsPos[1] * c0, rLimitsPos[1] * s0] + P3 = [rLimitsPos[1] * c1, rLimitsPos[1] * s1] + P4 = [rLimitsPos[0] * c1, rLimitsPos[0] * s1] + if tLimits[1] - tLimits[0] < 360: + inkDraw.line.absCoords(GroupAxis, [P1, P2], [0, 0], lineStyle=lineStyleAxis) + inkDraw.line.absCoords(GroupAxis, [P3, P4], [0, 0], lineStyle=lineStyleAxis) + else: + if rTicks: + inkDraw.line.absCoords(GroupAxis, [P1, P2], [0, 0], lineStyle=lineStyleAxis) + + if tLimits[1] - tLimits[0] < 360: + if rLimitsPos[0] > 0: + inkDraw.arc.startEndRadius(GroupAxis, P1, P4, rLimitsPos[0], offset=[0, 0], lineStyle=lineStyleAxis, flagRightOf=True, arcType='open', + largeArc=largeArc) + inkDraw.arc.startEndRadius(GroupAxis, P2, P3, rLimitsPos[1], offset=[0, 0], lineStyle=lineStyleAxis, flagRightOf=True, arcType='open', + largeArc=largeArc) + else: + if rLimitsPos[0] > 0: + inkDraw.circle.centerRadius(GroupAxis, [0, 0], rLimitsPos[0], offset=[0, 0], lineStyle=lineStyleAxis) + inkDraw.circle.centerRadius(GroupAxis, [0, 0], rLimitsPos[1], offset=[0, 0], lineStyle=lineStyleAxis) + + if rLabel: # axis labels + c0 = math.cos(math.radians(-tLimits[0]) + text_offset / rLimitsPos[1]) # negative angles bc inkscape is upside down + s0 = math.sin(math.radians(-tLimits[0]) + text_offset / rLimitsPos[1]) # negative angles bc inkscape is upside down + posText = [(rLimitsPos[1] + ExtraSpaceArrowR) * c0, (rLimitsPos[1] + ExtraSpaceArrowR) * s0] + inkDraw.text.latex(ExtensionBaseObj, GroupAxis, rLabel, posText, textSize, refPoint='cl') + + return [GroupPlot, outputLimits, [0, 0]] + + +class plot(): + """ This class has member functions to create plots. + + .. note:: This class contains only static methods so that your plugin class don't have to inherit it. + + .. note:: This class uses LaTeX in labels and tick marks if LaTeX support is enabled. This is an optional feature, **enabled by default**. + Please refer to :ref:`disableLatexSupport` on how to disable it. If disabled, this function will still work, internally calling the :meth:`inkscapeMadeEasy_Draw.text.write` to generate text. + """ + + @staticmethod + def cartesian(ExtensionBaseObj, parent, xData, yData, position=[0, 0], xLabel='', yLabel='', xlog10scale=False, ylog10scale=False, xTicks=True, + yTicks=True, xTickStep=1.0, yTickStep=1.0, xScale=20, yScale=20, xExtraText='', yExtraText='', xGrid=False, yGrid=False, + generalAspectFactorAxis=1.0, lineStylePlot=inkDraw.lineStyle.setSimpleBlack(), forceXlim=None, forceYlim=None, drawAxis=True, + ExtraLengthAxisX=0.0, ExtraLengthAxisY=0.0): + """Create a cartesian Plot + + .. note:: This method uses LaTeX in labels and tick marks if LaTeX support is enabled. This is an optional feature, **enabled by default**. Please refer to :ref:`disableLatexSupport` on how to disable it. + + :param ExtensionBaseObj: Most of the times you have to pass 'self' when calling from inside your plugin class. See example below + :param parent: Parent object + :param xData: List of x data + :param yData: List of y data + :param position: Position of the plot. It is defined at the point where x and y axis cross [x0,y0]. The point where the axis cross depend on the limits. + + - If xLimits comprises the origin x=0, then the Y axis crosses the X axis at x=0. + - If xLimits contains only negative numbers, then the Y axis crosses the X axis at x_max. + - If xLimits contains only positive numbers, then the Y axis crosses the X axis at x_min. + + - The same rule applies to y direction. + :param xLabel: Label of the X axis. Default: '' + + The text can contain any LaTeX command. If you want to write mathematical text, you can enclose it between dollar signs $...$. If LaTeX support is disabled, do not use $. + + :param yLabel: Label of the Y axis. Default: '' + + The text can contain any LaTeX command. If you want to write mathematical text, you can enclose it between dollar signs $...$. If LaTeX support is disabled, do not use $. + + :param xlog10scale: Sets X axis to log10 scale if True. Default: False + :param ylog10scale: Sets Y axis to log10 scale if True. Default: False + :param xTicks: Adds axis ticks to the X axis if True. Default: True + :param yTicks: Adds axis ticks to the Y axis if True. Default: True + :param xTickStep: Value interval between two consecutive ticks on X axis. (Not used if X axis is in log10 scale). Default:1.0 + :param yTickStep: Value interval between two consecutive ticks on Y axis. (Not used if Y axis is in log10 scale). Default:1.0 + :param xScale: Distance between each xTickStep in svg units. Default: 20 + + - If axis is linear, then xScale is the size in svg units of each tick + - If axis is log10, the xScale is the size in svg units of one decade + + :param yScale: Distance between each yTickStep in svg units. Default: 20 + + - If axis is linear, then yScale is the size in svg units of each tick + - If axis is log10, the yScale is the size in svg units of one decade + + :param xExtraText: Extra text to be added to the ticks in X axis. Default: '' + + This is useful when we want to represent interval with different units. example pi, 2pi 3pi, etc. + The text can be any LaTeX text. Keep in mind that this text will be inserted within a mathematical environment $...$, therefore no $ is needed here. + :param yExtraText: Extra text to be added to the ticks in Y axis. Default: '' + + This is useful when we want to represent interval with different units. example pi, 2pi 3pi, etc. + The text can be any LaTeX text. Keep in mind that this text will be inserted within a mathematical environment $...$, therefore no $ is needed here. + + :param xGrid: Adds grid lines to X axis if True. Default: False + :param yGrid: Adds grid lines to Y axis if True. Default: False + :param generalAspectFactorAxis: Regulates the general aspect ratio between grid lines, text and Ticks separations. Default: 1.0 + + :param lineStylePlot: Line style to be used to plot the data. See class ``inkscapeMadeEasy_Draw.lineStyle``. Default: lineStylePlot=inkDraw.lineStyle.setSimpleBlack() + :param forceXlim: Forces limits of X axis to these limits. These limits affect the axis only, that is, all xData is plotted despite of these limits. + + - if forceXlim=None Limits will be defined by the limits of xData (Default) + - if forceXlim=[xMin,xMax] then these limits will be used. + + .. note:: for logarithmic scale, the limits are always adjusted to complete the decade. Usually you don't need this for logarithmic scale + + :param forceYlim: Forces limits of Y axis to these limits. These limits affect the axis only, that is, all yData is plotted despite of these limits. + + - if forceYlim=None Limits will be defined by the limits of yData (Default) + - if forceYlim=[yMin,yMax] then these limits will be used. + + .. note:: for logarithmic scale, the limits are always adjusted to complete the decade. Usually you don't need this for logarithmic scale + + :param drawAxis: Control flag of the axis method + + - True: draws axis normally + - False: returns the limits and origin position without drawing the axis itself + + :param ExtraLengthAxisX: Extra length near the arrow pointer of X axis. Default 0.0 + :param ExtraLengthAxisY: Extra length near the arrow pointer of Y axis. Default 0.0 + + :type ExtensionBaseObj: inkscapeMadeEasy object + :type parent: inkscape element object + :type xData: list + :type yData: list + :type position: list + :type xLabel: string + :type yLabel: string + :type xlog10scale: bool + :type ylog10scale: bool + :type xTicks: bool + :type yTicks: bool + :type xTickStep: float + :type yTickStep: float + :type xScale: float + :type yScale: float + :type xExtraText: string + :type yExtraText: string + :type xGrid: bool + :type yGrid: bool + :type generalAspectFactorAxis: float + :type lineStylePlot: lineStyle object + :type forceXlim: list + :type forceYlim: list + :type drawAxis: bool + :type ExtraLengthAxisX: float + :type ExtraLengthAxisY: float + + :returns: [GroupPlot, outputLimits, axisOrigin] + + - GroupPlot: the plot object + - outputLimits: a list with tuples:[(x_min,xPos_min),(x_max,xPos_max),(y_min,yPos_min),(y_max,yPos_max)] + + - x_min, x_max, y_min, y_max: The limits of the axis object + - xPos_min, xPos_max, yPos_min, yPos_max: The positions of the limits of the axis object, considering the scaling and units + - axisOrigin [X0,Y0]: A list with the coordinates of the point where the axes cross. + :rtype: list + + .. important:: If any of the axis are log10, then the method ignores any pairs of (x,y) data with invalid coordinates, that is, if xData and/or yData is less than or equal to 0.0 (they would result in complex log10... =P ). The method will create a text object alongside your plot warning this. + + .. note:: If any of the axis are linear, the method will ignore any value greater than 10.000 (in absolute value). This avoids plotting very large numbers. The method will create a text object alongside your plot warning this. + + **Example** + + >>> root_layer = self.document.getroot() # retrieves the root layer of the document + >>> xData=[-1,-0.5,0,0.5,1.0,1.5,2] + >>> yData=[x*x for x in xData] # computes y=x*x + >>> #create a lineStyle for the plot + >>> myMarkerDot=inkDraw.marker.createDotMarker(self,'DotM',RenameMode=2,scale=0.3, + >>> strokeColor=inkDraw.color.defined('black'),fillColor=inkDraw.color.defined('black')) + >>> lineStyleDiscrete = inkDraw.lineStyle.set(lineWidth=1.0, markerStart=myMarkerDot,markerMid=myMarkerDot,markerEnd=myMarkerDot) + >>> + >>> inkPlot.plot.cartesian(self,root_layer,xData,yData,position=[0,0], + >>> xLabel='my $x$ data',yLabel='$y(x)$',xlog10scale=False,ylog10scale=False, + >>> xTicks=True,yTicks=True,xTickStep=0.5,yTickStep=2.0, + >>> xScale=20,yScale=10,xExtraText='a',yExtraText='', + >>> xGrid=True,yGrid=True,generalAspectFactorAxis=1.0,lineStylePlot=lineStyleDiscrete, + >>> forceXlim=None,forceYlim=None,drawAxis=True) + + The image below present the plot above with a few argument variations. + + .. image:: ../imagesDocs/plot_plotCartesianParameters_01.png + :width: 800px + + """ + + textSize = generalAspectFactorAxis * 0.25 * min(xScale, yScale) + lineWidthAxis = generalAspectFactorAxis * min(xScale, yScale) / 35.0 + + yDataTemp = [] + xDataTemp = [] + flagShowedError = False + if xlog10scale: # remove invalid pairs of coordinates for log plot (less than or equal to 0.0) + for i in range(len(xData)): + if xData[i] > 0.0: + yDataTemp.append(yData[i]) + xDataTemp.append(xData[i]) + else: + if not flagShowedError: + inkDraw.text.write(ExtensionBaseObj, + 'Error: The point (%f,%f)\n is invalid in logarithmic scale. Ignoring it...' % (xData[i], yData[i]), + [position[0], position[1] + 2 * textSize], parent, fontSize=textSize / 2.0) + inkDraw.text.write(ExtensionBaseObj, ' Please check your graph', [position[0], position[1] + 2.5 * textSize], parent, + fontSize=textSize / 2.0) + flagShowedError = True + else: # remove invalid pairs of coordinates for linear plot (larger than +-10k ) + for i in range(len(xData)): + if abs(xData[i]) <= 1.0e4: + yDataTemp.append(yData[i]) + xDataTemp.append(xData[i]) + else: + if not flagShowedError: + inkDraw.text.write(ExtensionBaseObj, 'Error: The point (%f,%f)\n is too large. Ignoring it...' % (xData[i], yData[i]), + [position[0], position[1] + 2 * textSize], parent, fontSize=textSize / 2.0) + inkDraw.text.write(ExtensionBaseObj, ' Please check your graph', [position[0], position[1] + 2.5 * textSize], parent, + fontSize=textSize / 2.0) + flagShowedError = True + + yData = yDataTemp + xData = xDataTemp + + yDataTemp = [] + xDataTemp = [] + flagShowedError = False + if ylog10scale: # remove invalid pairs of coordinates for log plot (less than or equal to 0.0) + for i in range(len(yData)): + if yData[i] > 0.0: + yDataTemp.append(yData[i]) + xDataTemp.append(xData[i]) + else: + if not flagShowedError: + inkDraw.text.write(ExtensionBaseObj, + 'Error: The point (%f,%f)\n is invalid in logarithmic scale. Ignoring it...' % (xData[i], yData[i]), + [position[0], position[1] + 2 * textSize], parent, fontSize=textSize / 2.0) + inkDraw.text.write(ExtensionBaseObj, ' Please check your graph', [position[0], position[1] + 2.5 * textSize], parent, + fontSize=textSize / 2.0) + flagShowedError = True + else: # remove invalid pairs of coordinates for linear plot (larger than +-10k ) + for i in range(len(yData)): + if abs(yData[i]) <= 1.0e4: + yDataTemp.append(yData[i]) + xDataTemp.append(xData[i]) + else: + if not flagShowedError: + inkDraw.text.write(ExtensionBaseObj, 'Error: The point (%f,%f)\n is too large. Ignoring it...' % (xData[i], yData[i]), + [position[0], position[1] + 2 * textSize], parent, fontSize=textSize / 2.0) + inkDraw.text.write(ExtensionBaseObj, ' Please check your graph', [position[0], position[1] + 2.5 * textSize], parent, + fontSize=textSize / 2.0) + flagShowedError = True + + yData = yDataTemp + xData = xDataTemp + + if forceXlim is not None: + Xlimits = forceXlim + else: + Xlimits = [min(xData), max(xData)] + if forceYlim is not None: + Ylimits = forceYlim + else: + Ylimits = [min(yData), max(yData)] # min<->max inverted bc inkscape is upside down + + if Ylimits[0] == Ylimits[1]: + if Ylimits[0] > 0: + Ylimits[0] = 0 + if Ylimits[0] == 0: + Ylimits[1] = 1 + if Ylimits[0] < 0: + Ylimits[1] = 0 + + if Xlimits[0] == Xlimits[1]: + if Xlimits[0] > 0: + Xlimits[0] = 0 + if Xlimits[0] == 0: + Xlimits[1] = 1 + if Xlimits[0] < 0: + Xlimits[1] = 0 + + # draw axis + axisGroup = ExtensionBaseObj.createGroup(parent, 'PlotData') + + [axisObj, limits, origin] = axis.cartesian(ExtensionBaseObj, axisGroup, Xlimits, Ylimits, position, xLabel=xLabel, yLabel=yLabel, + xlog10scale=xlog10scale, ylog10scale=ylog10scale, xTicks=xTicks, yTicks=yTicks, + xTickStep=xTickStep, yTickStep=yTickStep, xScale=xScale, yScale=yScale, xAxisUnitFactor=xExtraText, + yAxisUnitFactor=yExtraText, xGrid=xGrid, yGrid=yGrid, forceTextSize=textSize, + forceLineWidth=lineWidthAxis, drawAxis=drawAxis, ExtraLengthAxisX=ExtraLengthAxisX, + ExtraLengthAxisY=ExtraLengthAxisY) + + # scales data and convert to logarithmic scale if needed. Also subtracts the origin point of the axis to move the plot to the correct position + if xlog10scale: + xData = [math.log10(x) * xScale - origin[0] for x in xData] + else: + xData = [x * (xScale / xTickStep) - origin[0] for x in xData] + + if ylog10scale: + yData = [-math.log10(y) * yScale - origin[1] for y in yData] + else: + yData = [-y * (yScale / yTickStep) - origin[1] for y in yData] # negative bc inkscape is upside down + + coords = zip(xData, yData) + + inkDraw.line.absCoords(axisGroup, coords, position, lineStyle=lineStylePlot) + + return [axisGroup, limits, origin] + + @staticmethod + def polar(ExtensionBaseObj, parent, rData, tData, position=[0, 0], rLabel='', rlog10scale=False, rTicks=True, tTicks=True, rTickStep=1.0, + tTickStep=45.0, rScale=20, rExtraText='', rGrid=False, tGrid=False, generalAspectFactorAxis=1.0, + lineStylePlot=inkDraw.lineStyle.setSimpleBlack(), forceRlim=None, forceTlim=None, drawAxis=True, ExtraLengthAxisR=0.0): + """Create a polar Plot + + .. note:: This method uses LaTeX in labels and tick marks if LaTeX support is enabled. This is an optional feature, **enabled by default**. Please refer to :ref:`disableLatexSupport` on how to disable it. + + :param ExtensionBaseObj: Most of the times you have to pass 'self' when calling from inside your plugin class. See example below + :param parent: Parent object + :param rData: List of R data + :param tData: List of Theta data + :param position: Position of the plot [x0,y0]. It is defined at the center point + + :param rLabel: Label of the R axis. Default: '' + + The text can contain any LaTeX command. If you want to write mathematical text, you can enclose it between dollar signs $...$. If LaTeX support is disabled, do not use $. + + :param rlog10scale: Sets R axis to log10 scale if True. Default: False + :param rTicks: Adds axis ticks to the R axis if True. Default: True + :param tTicks: Adds axis ticks to the Theta axis if True. Default: True + :param rTickStep: Value interval between two consecutive ticks on R axis. (Not used if R axis is in log10 scale). Default:1.0 + :param tTickStep: Value interval between two consecutive ticks on Theta axis. + :param rScale: Distance between each rTickStep in svg units. Default: 20 + + - If axis is linear, then rScale is the size in svg units of each tick + - If axis is log10, the rScale is the size in svg units of one decade + + :param rExtraText: Extra text to be added to the ticks in R axis. Default: '' + + This is useful when we want to represent interval with different units. example pi, 2pi 3pi, etc. + The text can be any LaTeX text. Keep in mind that this text will be inserted within a mathematical environment $...$, therefore no $ is needed here. + + :param rGrid: Adds grid lines to R axis if True. Default: False + :param tGrid: Adds grid lines to Theta axis if True. Default: False + :param generalAspectFactorAxis: Regulates the general aspect ratio between grid lines, text and Ticks separations. Default: 1.0 + + :param lineStylePlot: Line style to be used to plot the data. See class ``inkscapeMadeEasy_Draw.lineStyle``. Default: lineStylePlot=inkDraw.lineStyle.setSimpleBlack() + :param forceRlim: Forces limits of R axis to these limits. These limits affect the axis only, that is, all rData is plotted despite of these limits. + + - if forceRlim=None Limits will be defined by the limits of rData (Default) + - if forceRlim=[rMin,rMax] then these limits will be used. + + .. note:: for logarithmic scale, the limits are always adjusted to complete the decade. Usually you don't need this for logarithmic scale + + :param forceTlim: Forces limits of Theta axis to these limits. These limits affect the axis only, that is, all tData is plotted despite of these limits. + + - if forceTlim=None Limits will be defined by min and max of tData (Default) + - if forceTlim=[tMin,tMax] then these limits will be used. + + :param drawAxis: Control flag of the axis method + + - True: draws axis normally + - False: returns the limits and origin position without drawing the axis itself + + :param ExtraLengthAxisR: Extra length near the arrow pointer of R axis. Default 0.0 + + :type ExtensionBaseObj: inkscapeMadeEasy object + :type parent: inkscape element object + :type rData: list + :type tData: list + :type position: list + :type rLabel: string + :type rlog10scale: bool + :type rTicks: bool + :type tTicks: bool + :type rTickStep: float + :type tTickStep: float + :type rScale: float + :type rExtraText: string + :type rGrid: bool + :type tGrid: bool + :type generalAspectFactorAxis: float + :type lineStylePlot: lineStyle object + :type forceRlim: list + :type forceTlim: list + :type drawAxis: bool + :type ExtraLengthAxisR: float + + :returns: [GroupPlot, outputLimits, axisOrigin] + + - GroupPlot: the plot object + - outputLimits: a list with tuples:[(x_min,xPos_min),(x_max,xPos_max),(y_min,yPos_min),(y_max,yPos_max)] + + - x_min, x_max, y_min, y_max: The limits of the axis object + - xPos_min, xPos_max, yPos_min, yPos_max: The positions of the limits of the axis object, considering the scaling and units + - axisOrigin [X0,Y0]: A list with the coordinates of the point where the axes cross. + :rtype: list + + .. important:: If any of the axis are log10, then the method ignores any pairs of (x,y) data with invalid coordinates, that is, if rData and/or tData is less than or equal to 0.0 (they would result in complex log10... =P ). The method will create a text object alongside your plot warning this. + + .. note:: If any of the axis are linear, the method will ignore any value greater than 10.000 (in absolute value). This avoids plotting very large numbers. The method will create a text object alongside your plot warning this. + + **Example** + + >>> root_layer = self.document.getroot() # retrieves the root layer of the document + >>> rData=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12] + >>> tData=[30*x for x in range(12)] + >>> + >>> myMarkerDot=inkDraw.marker.createDotMarker(self,'DotM',RenameMode=2,scale=0.3, + >>> strokeColor=inkDraw.color.defined('black'),fillColor=inkDraw.color.defined('black')) + >>> lineStyleDiscrete = inkDraw.lineStyle.set(lineWidth=1.0,linecolor=inkDraw.color.defined('red'), + >>> markerStart=myMarkerDot,markerMid=myMarkerDot,markerEnd=myMarkerDot) + >>> + >>> inkPlot.plot.polar(self,root_layer,rData,tData,position=[0,0], + >>> rLabel='my $R$ data',rlog10scale=False, + >>> rTicks=True,tTicks=True,rTickStep=2,tTickStep=30, + >>> rScale=20,rExtraText='a', + >>> rGrid=True,tGrid=True,generalAspectFactorAxis=1.0,lineStylePlot=lineStyleDiscrete, + >>> forceRlim=None,forceTlim=None,drawAxis=True) + >>> + >>> # another spiral, comprising two turns + >>> tData=[2*x for x in range(360)] + >>> rData=[x/180.0 for x in tData] + >>> + >>> inkPlot.plot.polar(self,root_layer,rData,tData,position=[0,0], + >>> rLabel='my $R$ data',rlog10scale=False, + >>> rTicks=True,tTicks=True,rTickStep=2,tTickStep=30, + >>> rScale=20,rExtraText='', + >>> rGrid=True,tGrid=True,generalAspectFactorAxis=1.0, + >>> forceRlim=None,forceTlim=None,drawAxis=True) + + The image below present the plot above with a few argument variations. + + .. image:: ../imagesDocs/plot_plotPolarParameters_01.png + :width: 900px + + """ + + textSize = generalAspectFactorAxis * 0.25 * rScale + lineWidthAxis = generalAspectFactorAxis * rScale / 35.0 + + tDataTemp = [] + rDataTemp = [] + flagShowedError = False + if rlog10scale: # remove invalid pairs of coordinates for log plot (less than or equal to 0.0) + for i in range(len(rData)): + if rData[i] >= 1.0: + tDataTemp.append(tData[i]) + rDataTemp.append(rData[i]) + else: + if not flagShowedError: + inkDraw.text.write(ExtensionBaseObj, + 'Error: The point (%f,%f)\n is invalid in logarithmic scale. Ignoring it...' % (rData[i], tData[i]), + [position[0], position[1] + 2 * textSize], parent, fontSize=textSize / 2.0) + inkDraw.text.write(ExtensionBaseObj, ' Please check your graph', [position[0], position[1] + 2.5 * textSize], parent, + fontSize=textSize / 2.0) + flagShowedError = True + else: # remove invalid pairs of coordinates for linear plot (larger than +-10k ) + for i in range(len(rData)): + if abs(rData[i]) <= 1.0e4: + tDataTemp.append(tData[i]) + rDataTemp.append(rData[i]) + else: + if not flagShowedError: + inkDraw.text.write(ExtensionBaseObj, 'Error: The point (%f,%f)\n is too large. Ignoring it...' % (rData[i], tData[i]), + [position[0], position[1] + 2 * textSize], parent, fontSize=textSize / 2.0) + inkDraw.text.write(ExtensionBaseObj, ' Please check your graph', [position[0], position[1] + 2.5 * textSize], parent, + fontSize=textSize / 2.0) + flagShowedError = True + + tData = tDataTemp + rData = rDataTemp + + if forceRlim is not None: + Rlimits = forceRlim + else: + Rlimits = [min(rData), max(rData)] + if forceTlim is not None: + Tlimits = forceTlim + else: + Tlimits = [min(tData), max(tData)] # min<->max inverted bc inkscape is upside down + + if Tlimits[0] == Tlimits[1]: + if Tlimits[0] > 0: + Tlimits[0] = 0 + if Tlimits[0] == 0: + Tlimits[1] = 360 + if Tlimits[0] < 0: + Tlimits[1] = 0 + + if Rlimits[0] == Rlimits[1]: + if Rlimits[0] > 0: + Rlimits[0] = 0 + if Rlimits[0] == 0: + Rlimits[1] = 1 + if Rlimits[0] < 0: + Rlimits[1] = 0 + + # draw axis + axisGroup = ExtensionBaseObj.createGroup(parent, 'PlotData') + + [axisObj, limits, origin] = axis.polar(ExtensionBaseObj, axisGroup, Rlimits, Tlimits, position, rLabel=rLabel, rlog10scale=rlog10scale, + rTicks=rTicks, tTicks=tTicks, rTickStep=rTickStep, tTickStep=tTickStep, rScale=rScale, + rAxisUnitFactor=rExtraText, rGrid=rGrid, tGrid=tGrid, forceTextSize=textSize, + forceLineWidth=lineWidthAxis, drawAxis=drawAxis, ExtraLengthAxisR=ExtraLengthAxisR) + + # scales data and convert to logarithmic scale if needed. Also subtracts the origin point of the axis to move the plot to the correct position + nPoints = min(len(rData), len(tData)) + xData = [] + yData = [] + if rlog10scale: + for i in range(nPoints): + xData.append(math.log10(rData[i]) * math.cos(math.radians(-tData[i])) * rScale) # negative theta bc inkscape is upside down + yData.append(math.log10(rData[i]) * math.sin(math.radians(-tData[i])) * rScale) # negative theta bc inkscape is upside down + else: + for i in range(nPoints): + xData.append(rData[i] * math.cos(math.radians(-tData[i])) * (rScale / rTickStep)) # negative theta bc inkscape is upside down + yData.append(rData[i] * math.sin(math.radians(-tData[i])) * (rScale / rTickStep)) # negative theta bc inkscape is upside down + + coords = zip(xData, yData) + + inkDraw.line.absCoords(axisGroup, coords, position, lineStyle=lineStylePlot) + + return [axisGroup, limits, origin] + + @staticmethod + def stem(ExtensionBaseObj, parent, xData, yData, position=[0, 0], xLabel='', yLabel='', ylog10scale=False, xTicks=True, yTicks=True, + xTickStep=1.0, yTickStep=1.0, xScale=20, yScale=20, xExtraText='', yExtraText='', xGrid=False, yGrid=False, generalAspectFactorAxis=1.0, + lineStylePlot=inkDraw.lineStyle.setSimpleBlack(), forceXlim=None, forceYlim=None, drawAxis=True, ExtraLengthAxisX=0.0, + ExtraLengthAxisY=0.0): + """Create a cartesian stem plot + + .. note:: This method uses LaTeX in labels and tick marks if LaTeX support is enabled. This is an optional feature, **enabled by default**. Please refer to :ref:`disableLatexSupport` on how to disable it. + + :param ExtensionBaseObj: Most of the times you have to pass 'self' when calling from inside your plugin class. See example below + :param parent: Parent object + :param xData: List of x data + :param yData: List of y data + :param position: Position of the plot. It is defined at the point where x and y axis cross [x0,y0]. The point where the axis cross depend on the limits. + + - If xLimits comprises the origin x=0, then the Y axis crosses the X axis at x=0. + - If xLimits contains only negative numbers, then the Y axis crosses the X axis at x_max. + - If xLimits contains only positive numbers, then the Y axis crosses the X axis at x_min. + + - The same rule applies to y direction. + :param xLabel: Label of the X axis. Default: '' + + The text can contain any LaTeX command. If you want to write mathematical text, you can enclose it between dollar signs $...$. If LaTeX support is disabled, do not use $. + + :param yLabel: Label of the Y axis. Default: '' + + The text can contain any LaTeX command. If you want to write mathematical text, you can enclose it between dollar signs $...$. If LaTeX support is disabled, do not use $. + + :param ylog10scale: Sets Y axis to log10 scale if True. Default: False + :param xTicks: Adds axis ticks to the X axis if True. Default: True + :param yTicks: Adds axis ticks to the Y axis if True. Default: True + :param xTickStep: Value interval between two consecutive ticks on X axis. (Not used if X axis is in log10 scale). Default:1.0 + :param yTickStep: Value interval between two consecutive ticks on Y axis. (Not used if Y axis is in log10 scale). Default:1.0 + :param xScale: Distance between each xTickStep in svg units. Default: 20 + + - If axis is linear, then xScale is the size in svg units of each tick + - If axis is log10, the xScale is the size in svg units of one decade + + :param yScale: Distance between each yTickStep in svg units. Default: 20 + + - If axis is linear, then yScale is the size in svg units of each tick + - If axis is log10, the yScale is the size in svg units of one decade + + :param xExtraText: Extra text to be added to the ticks in X axis. Default: '' + + This is useful when we want to represent interval with different units. example pi, 2pi 3pi, etc. + The text can be any LaTeX text. Keep in mind that this text will be inserted within a mathematical environment $...$, therefore no $ is needed here. + :param yExtraText: Extra text to be added to the ticks in Y axis. Default: '' + + This is useful when we want to represent interval with different units. example pi, 2pi 3pi, etc. + The text can be any LaTeX text. Keep in mind that this text will be inserted within a mathematical environment $...$, therefore no $ is needed here. + + :param xGrid: Adds grid lines to X axis if True. Default: False + :param yGrid: Adds grid lines to Y axis if True. Default: False + :param generalAspectFactorAxis: Regulates the general aspect ratio between grid lines, text and Ticks separations. Default: 1.0 + + :param lineStylePlot: Line style to be used to plot the data. See class ``inkscapeMadeEasy_Draw.lineStyle``. Default: lineStylePlot=inkDraw.lineStyle.setSimpleBlack() + :param forceXlim: Forces limits of X axis to these limits. These limits affect the axis only, that is, all xData is plotted despite of these limits. + + - if forceXlim=None Limits will be defined by the limits of xData (Default) + - if forceXlim=[xMin,xMax] then these limits will be used. + + .. note:: for logarithmic scale, the limits are always adjusted to complete the decade. Usually you don't need this for logarithmic scale + + :param forceYlim: Forces limits of Y axis to these limits. These limits affect the axis only, that is, all yData is plotted despite of these limits. + + - if forceYlim=None Limits will be defined by the limits of yData (Default) + - if forceYlim=[yMin,yMax] then these limits will be used. + + .. note:: for logarithmic scale, the limits are always adjusted to complete the decade. Usually you don't need this for logarithmic scale + + :param drawAxis: Control flag of the axis method + + - True: draws axis normally + - False: returns the limits and origin position without drawing the axis itself + + :param ExtraLengthAxisX: Extra length near the arrow pointer of X axis. Default 0.0 + :param ExtraLengthAxisY: Extra length near the arrow pointer of Y axis. Default 0.0 + + :type ExtensionBaseObj: inkscapeMadeEasy object + :type parent: inkscape element object + :type xData: list + :type yData: list + :type position: list + :type xLabel: string + :type yLabel: string + :type ylog10scale: bool + :type xTicks: bool + :type yTicks: bool + :type xTickStep: float + :type yTickStep: float + :type xScale: float + :type yScale: float + :type xExtraText: string + :type yExtraText: string + :type xGrid: bool + :type yGrid: bool + :type generalAspectFactorAxis: float + :type lineStylePlot: lineStyle object + :type forceXlim: list + :type forceYlim: list + :type drawAxis: bool + :type ExtraLengthAxisX: float + :type ExtraLengthAxisY: float + + :returns: [GroupPlot, outputLimits, axisOrigin] + + - GroupPlot: the plot object + - outputLimits: a list with tuples:[(x_min,xPos_min),(x_max,xPos_max),(y_min,yPos_min),(y_max,yPos_max)] + + - x_min, x_max, y_min, y_max: The limits of the axis object + - xPos_min, xPos_max, yPos_min, yPos_max: The positions of the limits of the axis object, considering the scaling and units + - axisOrigin [X0,Y0]: A list with the coordinates of the point where the axes cross. + :rtype: list + + .. important:: If any of the axis are log10, then the method ignores any pairs of (x,y) data with invalid coordinates, that is, if xData and/or yData is less than or equal to 0.0 (they would result in complex log10... =P ). The method will create a text object alongside your plot warning this. + + .. note:: If any of the axis are linear, the method will ignore any value greater than 10.000 (in absolute value). This avoids plotting very large numbers. The method will create a text object alongside your plot warning this. + + **Example** + + >>> oot_layer = self.document.getroot() # retrieves the root layer of the document + >>> xData=[-1,-0.5,0,0.5,1.0,1.5,2] + >>> yData=[x*x for x in xData] # computes y=x*x + >>> + >>> # creates a line style with a dot marker for the stem plot + >>> myMarkerDot=inkDraw.marker.createDotMarker(self,'DotMDiscreteTime',RenameMode=2,scale=0.3, + >>> strokeColor=inkDraw.color.defined('black'),fillColor=inkDraw.color.defined('red')) + >>> lineStyleDiscrete = inkDraw.lineStyle.set(lineWidth=1.0, markerEnd=myMarkerDot) + >>> + >>> inkPlot.plot.stem(self,root_layer,xData,yData,position=[0,0], + >>> xLabel='my $x$ data',yLabel='$y(x)$',ylog10scale=False, + >>> xTicks=True,yTicks=True,xTickStep=0.5,yTickStep=2.0, + >>> xScale=20,yScale=20,xExtraText='a',yExtraText='', + >>> xGrid=True,yGrid=True,generalAspectFactorAxis=1.0,lineStylePlot=lineStyleDiscrete, + >>> forceXlim=None,forceYlim=None,drawAxis=True) + + The image below present the plot above. + + .. image:: ../imagesDocs/plot_plotStemParameters_01.png + :width: 400px + + """ + + textSize = generalAspectFactorAxis * 0.25 * min(xScale, yScale) + lineWidthAxis = generalAspectFactorAxis * min(xScale, yScale) / 35.0 + + yDataTemp = [] + xDataTemp = [] + flagShowedError = False + + # remove invalid pairs of coordinates for linear plot (larger than +-10k ) + for i in range(len(xData)): + if abs(xData[i]) <= 1.0e4: + yDataTemp.append(yData[i]) + xDataTemp.append(xData[i]) + else: + if not flagShowedError: + inkDraw.text.write(ExtensionBaseObj, 'Error: The point (%f,%f)\n is too large. Ignoring it...' % (xData[i], yData[i]), + [position[0], position[1] + 2 * textSize], parent, fontSize=textSize / 2.0) + inkDraw.text.write(ExtensionBaseObj, ' Please check your graph', [position[0], position[1] + 2.5 * textSize], parent, + fontSize=textSize / 2.0) + flagShowedError = True + + yData = yDataTemp + xData = xDataTemp + + yDataTemp = [] + xDataTemp = [] + flagShowedError = False + if ylog10scale: # remove invalid pairs of coordinates for log plot (less than or equal to 0.0) + for i in range(len(yData)): + if yData[i] > 0.0: + yDataTemp.append(yData[i]) + xDataTemp.append(xData[i]) + else: + if not flagShowedError: + inkDraw.text.write(ExtensionBaseObj, + 'Error: The point (%f,%f)\n is invalid in logarithmic scale. Ignoring it...' % (xData[i], yData[i]), + [position[0], position[1] + 2 * textSize], parent, fontSize=textSize / 2.0) + inkDraw.text.write(ExtensionBaseObj, ' Please check your graph', [position[0], position[1] + 2.5 * textSize], parent, + fontSize=textSize / 2.0) + flagShowedError = True + else: # remove invalid pairs of coordinates for linear plot (larger than +-10k ) + for i in range(len(yData)): + if abs(yData[i]) <= 1.0e4: + yDataTemp.append(yData[i]) + xDataTemp.append(xData[i]) + else: + if not flagShowedError: + inkDraw.text.write(ExtensionBaseObj, 'Error: The point (%f,%f)\n is too large. Ignoring it...' % (xData[i], yData[i]), + [position[0], position[1] + 2 * textSize], parent, fontSize=textSize / 2.0) + inkDraw.text.write(ExtensionBaseObj, ' Please check your graph', [position[0], position[1] + 2.5 * textSize], parent, + fontSize=textSize / 2.0) + flagShowedError = True + + yData = yDataTemp + xData = xDataTemp + + if forceXlim: + Xlimits = forceXlim + else: + Xlimits = [min(xData), max(xData)] + if forceYlim: + Ylimits = forceYlim + else: + Ylimits = [min(yData), max(yData)] # min<->max inverted bc inkscape is upside down + + if Ylimits[0] == Ylimits[1]: + if Ylimits[0] > 0: + Ylimits[0] = 0 + if Ylimits[0] == 0: + Ylimits[1] = 1 + if Ylimits[0] < 0: + Ylimits[1] = 0 + + if Xlimits[0] == Xlimits[1]: + if Xlimits[0] > 0: + Xlimits[0] = 0 + if Xlimits[0] == 0: + Xlimits[1] = 1 + if Xlimits[0] < 0: + Xlimits[1] = 0 + + # draw axis + axisGroup = ExtensionBaseObj.createGroup(parent, 'PlotData') + + [axisObj, limits, origin] = axis.cartesian(ExtensionBaseObj, axisGroup, Xlimits, Ylimits, position, xLabel=xLabel, yLabel=yLabel, + xlog10scale=False, ylog10scale=ylog10scale, xTicks=xTicks, yTicks=yTicks, xTickStep=xTickStep, + yTickStep=yTickStep, xScale=xScale, yScale=yScale, xAxisUnitFactor=xExtraText, + yAxisUnitFactor=yExtraText, xGrid=xGrid, yGrid=yGrid, forceTextSize=textSize, + forceLineWidth=lineWidthAxis, drawAxis=drawAxis, ExtraLengthAxisX=ExtraLengthAxisX, + ExtraLengthAxisY=ExtraLengthAxisY) + + # scales data and convert to logarithmic scale if needed. Also subtracts the origin point of the axis to move the plot to the correct position + xData = [x * (xScale / xTickStep) - origin[0] for x in xData] + + if ylog10scale: + yData = [-math.log10(y) * yScale - origin[1] for y in yData] + else: + yData = [-y * (yScale / yTickStep) - origin[1] for y in yData] # negative bc inkscape is upside down + + stemGroup = ExtensionBaseObj.createGroup(axisGroup, 'StemGroup') + + for i in range(len(xData)): + inkDraw.line.relCoords(stemGroup, [[0, yData[i]]], [xData[i] + position[0], 0 + position[1]], lineStyle=lineStylePlot) + + return [axisGroup, limits, origin] diff --git a/extensions/fablabchemnitz/spirograph/meta.json b/extensions/fablabchemnitz/spirograph/meta.json new file mode 100644 index 0000000..2f78262 --- /dev/null +++ b/extensions/fablabchemnitz/spirograph/meta.json @@ -0,0 +1,21 @@ +[ + { + "name": "SpiroGraph", + "id": "fablabchemnitz.de.spirograph", + "path": "spirograph", + "dependent_extensions": null, + "original_name": "SpiroGraph", + "original_id": "fsmMLK.spiroGraph", + "license": "GNU GPL v3", + "license_url": "https://github.com/fsmMLK/inkscapeSpirograph/blob/main/LICENSE", + "comment": "", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/spirograph", + "fork_url": "https://github.com/fsmMLK/inkscapeSpirograph", + "documentation_url": "https://stadtfabrikanten.org/display/IFM/SpiroGraph", + "inkscape_gallery_url": null, + "main_authors": [ + "github.com/fsmMLK", + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/spirograph/spirograph.inx b/extensions/fablabchemnitz/spirograph/spirograph.inx new file mode 100644 index 0000000..abcc413 --- /dev/null +++ b/extensions/fablabchemnitz/spirograph/spirograph.inx @@ -0,0 +1,30 @@ + + + SpiroGraph + fablabchemnitz.de.spirograph + + + + + + 10 + 5 + 2 + + + 1 + false + false + + + all + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/spirograph/spirograph.py b/extensions/fablabchemnitz/spirograph/spirograph.py new file mode 100644 index 0000000..4b1b6c7 --- /dev/null +++ b/extensions/fablabchemnitz/spirograph/spirograph.py @@ -0,0 +1,248 @@ +#!/usr/bin/python + +import math +import os +import numpy as np +import scipy.signal as scipySignal + +import inkscapeMadeEasy.inkscapeMadeEasy_Base as inkBase +import inkscapeMadeEasy.inkscapeMadeEasy_Draw as inkDraw +import inkscapeMadeEasy.inkscapeMadeEasy_Plot as inkPlot + + +# least common multiplier +def myLcm(x, y): + return x * y / math.gcd(int(x), int(y)) + + +# --------------------------------------------- +# noinspection PyAttributeOutsideInit +class Spirograph(inkBase.inkscapeMadeEasy): + def __init__(self): + inkBase.inkscapeMadeEasy.__init__(self) + + self.arg_parser.add_argument("--curveType", type=str, dest="curveType", default='resistor') + self.arg_parser.add_argument("--radius_R", type=float, dest="radius_R", default=10.0) + self.arg_parser.add_argument("--radius_r", type=float, dest="radius_r", default=5.0) + self.arg_parser.add_argument("--detailLevel", type=float, dest="detailLevel", default=1.0) + self.arg_parser.add_argument("--adaptiveTheta", type=self.bool, dest="adaptiveTheta", default=False) + self.arg_parser.add_argument("--pencil_distance", type=float, dest="pencil_distance", default=1.0) + self.arg_parser.add_argument("--drawBaseCircles", type=self.bool, dest="drawBaseCircles", default=False) + self.arg_parser.add_argument("--animate", type=self.bool, dest="animate", default=False) + self.arg_parser.add_argument("--directory", type=str, dest="directory", default='./') + + def effect(self): + so = self.options + + # sets the position to the viewport center, round to next 10. + position = [self.svg.namedview.center[0], self.svg.namedview.center[1]] + position[0] = int(math.ceil(position[0] / 10.0)) * 10 + position[1] = int(math.ceil(position[1] / 10.0)) * 10 + + root_layer = self.document.getroot() + group = self.createGroup(root_layer, 'Spiro') + + # curve parameters + R = so.radius_R + r = so.radius_r + d = so.pencil_distance + finalTheta = 2 * np.pi * myLcm(abs(r), R) / R + + if 'hypo' in so.curveType.lower(): + typeCurve = 'hypo' + if 'epi' in so.curveType.lower(): + typeCurve = 'epi' + + # markers and linestyles + Lgray = inkDraw.color.gray(0.8) + Dgray = inkDraw.color.gray(0.3) + # wheel + markerCenterDisk = inkDraw.marker.createDotMarker(self, nameID='diskCenter', scale=0.3, RenameMode=1, strokeColor=Dgray, + fillColor=inkDraw.color.defined('white')) + markerPen = inkDraw.marker.createDotMarker(self, nameID='diskPen', scale=0.3, RenameMode=1, strokeColor=Dgray, + fillColor=inkDraw.color.defined('white')) + [startArrowMarker, endArrowMarker] = inkDraw.marker.createArrow1Marker(self, nameID='arrowRot', RenameMode=1, scale=0.3, strokeColor=Dgray, + fillColor=Dgray) + + if typeCurve == 'hypo': + self.lineStyleArrow = inkDraw.lineStyle.set(lineWidth=r / 40, lineColor=Dgray, markerStart=startArrowMarker, markerEnd=None) + else: + self.lineStyleArrow = inkDraw.lineStyle.set(lineWidth=r / 40, lineColor=Dgray, markerStart=None, markerEnd=endArrowMarker) + + self.lineStyleARM = inkDraw.lineStyle.set(lineWidth=r / 40, lineColor=Dgray, markerStart=markerCenterDisk, markerEnd=markerPen) + self.lineStyleDisk = inkDraw.lineStyle.set(lineWidth=r / 40, lineColor=None, fillColor=Lgray) + + # curve + self.lineStyleCurve = inkDraw.lineStyle.set(lineWidth=0.8, lineColor=inkDraw.color.defined('red'), markerStart=None, markerEnd=None, + markerMid=None) + self.lineStyleCurve2 = inkDraw.lineStyle.set(lineWidth=0.8, lineColor=inkDraw.color.defined('Dgreen'), markerStart=None, markerEnd=None, + markerMid=None) + self.lineStyleCurve3 = inkDraw.lineStyle.set(lineWidth=0.8, lineColor=inkDraw.color.defined('blue'), markerStart=None, markerEnd=None, + markerMid=None) + + self.lineStylePre = inkDraw.lineStyle.set(lineWidth=1, lineColor=inkDraw.color.defined('red')) + self.constructionLine = inkDraw.lineStyle.set(lineWidth=0.5, lineColor=Dgray) + + # draft Points + if so.adaptiveTheta: + nPrePoints = 10 * so.detailLevel # number of pre points per turn + thetasDraft = np.linspace(0, finalTheta, int(nPrePoints * finalTheta / (2 * np.pi))) + + [pointsDraft, _, curvatureDraft] = self.calcCurve__trochoid(typeCurve, R, r, d, thetasDraft) + + # find sampling points based on local curvature + nSamples = np.ones(curvatureDraft.shape)*min(2,so.detailLevel) + detailFactor=5 + # treshold normalized curvatures + nSamples[curvatureDraft>0.8] *=detailFactor + detailFactor = 2.5 + # check if vector changed direction abuptly + for i,p in enumerate(pointsDraft): + if i==0: + v1=pointsDraft[i+1]-pointsDraft[i] + v2=pointsDraft[i]-pointsDraft[-1] + elif i < len(pointsDraft)-1: + v1=pointsDraft[i+1]-pointsDraft[i] + v2=pointsDraft[i]-pointsDraft[i-1] + else: + v1=pointsDraft[0]-pointsDraft[i] + v2=pointsDraft[i]-pointsDraft[i-1] + + v1=v1/np.linalg.norm(v1) + v2=v2/np.linalg.norm(v2) + if np.dot(v1,v2)<0.5: + nSamples[i] *=detailFactor + + thetasFinal = np.array([]) + for i in range(len(nSamples) - 1): + thetasFinal = np.append(thetasFinal, np.linspace(thetasDraft[i], thetasDraft[i + 1], int(nSamples[i]), endpoint=False)) + + thetasFinal = np.append(thetasFinal, finalTheta) + # filter the sampled angles to have a smooth transition. + Ntaps = 5 + gaussWindow = scipySignal.gaussian(Ntaps, std=5) + gaussWindow = gaussWindow / np.sum(gaussWindow) + + # inkPlot.plot.cartesian(self, root_layer, np.arange(thetasFinal.shape[0]), thetasFinal * 180 / np.pi, position, xTicks=False, yTicks=True, xTickStep=thetasFinal.shape[0]/10, yTickStep=120.0, xScale=10, yScale=10,xGrid=True, yGrid=True, forceXlim=None, forceYlim=None) + thetasFinal = scipySignal.filtfilt(gaussWindow, np.array([1]), thetasFinal) + + # inkPlot.plot.cartesian(self, root_layer, np.arange(thetasFinal.shape[0]), thetasFinal * 180 / np.pi, position, xTicks=False, yTicks=True,xTickStep=thetasFinal.shape[0]/10, yTickStep=120.0, xScale=10, yScale=10, xGrid=True, yGrid=True, forceXlim=None, forceYlim=None,drawAxis=False) + else: + nPrePoints = 20 * so.detailLevel # number of pre points per turn + thetasFinal = np.linspace(0, finalTheta, int(nPrePoints * finalTheta / (2 * np.pi))) + + # final shape + [PointsFinal, CentersFinal, curvatureFinal] = self.calcCurve__trochoid(typeCurve, R, r, d, thetasFinal) + [PointsFinal2, CentersFinal2, curvatureFinal2] = self.calcCurve__trochoid(typeCurve, R, r, -d, thetasFinal) + [PointsFinal3, CentersFinal3, curvatureFinal3] = self.calcCurve__trochoid(typeCurve, R, r, r, thetasFinal) + + if so.animate: + animGroup = self.createGroup(group, 'Anim') + + circle_R = inkDraw.circle.centerRadius(parent=animGroup, centerPoint=[0, 0], radius=R, offset=position, lineStyle=self.constructionLine) + + # draw planetary wheel + wheelGroup = self.createGroup(animGroup, 'Anim') + circle_r = inkDraw.circle.centerRadius(wheelGroup, centerPoint=CentersFinal[0], radius=r, offset=position, lineStyle=self.lineStyleDisk) + arms1 = inkDraw.line.absCoords(wheelGroup, coordsList=[CentersFinal[0], PointsFinal[0]], offset=position, lineStyle=self.lineStyleARM) + arms2 = inkDraw.line.absCoords(wheelGroup, coordsList=[CentersFinal2[0], PointsFinal2[0]], offset=position, lineStyle=self.lineStyleARM) + arms3 = inkDraw.line.absCoords(wheelGroup, coordsList=[CentersFinal3[0], PointsFinal3[0]], offset=position, lineStyle=self.lineStyleARM) + + arc1 = inkDraw.arc.centerAngStartAngEnd(wheelGroup, centerPoint=CentersFinal[0], radius=r * 0.6, angStart=40, angEnd=80, offset=position, + lineStyle=self.lineStyleArrow) + arc2 = inkDraw.arc.centerAngStartAngEnd(wheelGroup, centerPoint=CentersFinal[0], radius=r * 0.6, angStart=160, angEnd=200, + offset=position, lineStyle=self.lineStyleArrow) + arc3 = inkDraw.arc.centerAngStartAngEnd(wheelGroup, centerPoint=CentersFinal[0], radius=r * 0.6, angStart=280, angEnd=320, + offset=position, lineStyle=self.lineStyleArrow) + + self.exportSVG(animGroup, os.path.join(so.directory,'outSVG_%1.5d.svg' % 0)) + + for i in range(1, len(thetasFinal)): + + self.moveElement(wheelGroup, [CentersFinal[i][0] - CentersFinal[i - 1][0], CentersFinal[i][1] - CentersFinal[i - 1][1]]) + if typeCurve == 'hypo': + self.rotateElement(wheelGroup, [position[0] + CentersFinal[i][0], position[1] + CentersFinal[i][1]], + (thetasFinal[i] - thetasFinal[i - 1]) * (R - r) / r * 180 / np.pi) + else: + self.rotateElement(wheelGroup, [position[0] + CentersFinal[i][0], position[1] + CentersFinal[i][1]], + - (thetasFinal[i] - thetasFinal[i - 1]) * (R + r) / r * 180 / np.pi) + + curve1 = inkDraw.line.absCoords(parent=animGroup, coordsList=PointsFinal[:i + 1], offset=position, lineStyle=self.lineStyleCurve, + closePath=False) + curve2 = inkDraw.line.absCoords(parent=animGroup, coordsList=PointsFinal2[:i + 1], offset=position, lineStyle=self.lineStyleCurve2, + closePath=False) + curve3 = inkDraw.line.absCoords(parent=animGroup, coordsList=PointsFinal3[:i + 1], offset=position, lineStyle=self.lineStyleCurve3, + closePath=False) + + self.exportSVG(animGroup, os.path.join(so.directory , 'outSVG_%1.5d.svg' % i)) + + self.removeElement(curve1) + self.removeElement(curve2) + self.removeElement(curve3) + self.removeElement(animGroup) + else: + if so.drawBaseCircles: + inkDraw.circle.centerRadius(parent=group, centerPoint=position, radius=R, offset=[0, 0], lineStyle=self.constructionLine) + + if typeCurve == 'hypo': + inkDraw.circle.centerRadius(parent=group, centerPoint=position, radius=r, offset=[R - r, 0], lineStyle=self.constructionLine) + if typeCurve == 'epi': + inkDraw.circle.centerRadius(parent=group, centerPoint=position, radius=r, offset=[R + r, 0], lineStyle=self.constructionLine) + + inkDraw.line.absCoords(group, PointsFinal, position, 'spiro', self.lineStyleCurve, closePath=True) + + # plot curvatures + if False: + inkPlot.plot.polar(self, group, curvatureFinal, thetasFinal * 180 / np.pi, [position[0] + 3 * R, position[1]], rTicks=False, + tTicks=False, rTickStep=0.2, tTickStep=45.0, rScale=20, rGrid=True, tGrid=True, lineStylePlot=self.lineStyleCurve, + forceRlim=[0.0, 1.0]) + + return + + # typeCurve: 'hypo', 'epi' + def calcCurve__trochoid(self, typeCurve, R, r, d, thetas): + j = complex(0, 1) + if typeCurve.lower() == 'hypo': + # https://www.mathcurve.com/courbes2d.gb/hypotrochoid/hypotrochoid.shtml + P_complex = (R - r) * np.exp(j * thetas) + d * np.exp(-j * thetas * (R - r) / r) + dP_complex = (R - r) * j * np.exp(j * thetas) + d * (-j) * (R - r) / r * np.exp(-j * thetas * (R - r) / r) + ddP_complex = (R - r) * (-1) * np.exp(j * thetas) + d * (-1) * ((R - r) / r) ** 2 * np.exp(-j * thetas * (R - r) / r) + centerGear = (R - r) * np.exp(j * thetas) + if typeCurve.lower() == 'epi': + # https://www.mathcurve.com/courbes2d.gb/epitrochoid/epitrochoid.shtml + P_complex = (R + r) * np.exp(j * thetas) - d * np.exp(j * thetas * (R + r) / r) + dP_complex = (R + r) * j * np.exp(j * thetas) - d * j * (R + r) / r * np.exp(j * thetas * (R + r) / r) + ddP_complex = (R + r) * (-1) * np.exp(j * thetas) - d * (-1) * ((R + r) / r) ** 2 * np.exp(j * thetas * (R + r) / r) + centerGear = (R + r) * np.exp(j * thetas) + + with np.errstate(divide='ignore', invalid='ignore'): + curvature = np.divide(abs(dP_complex.real * ddP_complex.imag - dP_complex.imag * ddP_complex.real), + (dP_complex.real ** 2 + dP_complex.imag ** 2) ** (2 / 3)) + + # remove Nan=0/0 + np.nan_to_num(curvature, copy=False) + + # remove values too large + curvature[curvature > 10 * np.mean(curvature)] = 0.0 + + # self.Dump(curvature, '/home/fernando/lixo.txt', 'w') + # normalize curvature + curvature = self._normalizeCurvatures(curvature, 0.0, 1.0) + + Points = np.column_stack((P_complex.real, P_complex.imag)) + Centers = np.column_stack((centerGear.real, centerGear.imag)) + + return [Points, Centers, curvature] + + def _normalizeCurvatures(self, curvatures, normMin=0.0, normMax=1.0): + y1 = normMin + y2 = normMax + x1 = np.min(curvatures) + x2 = np.max(curvatures) + alpha = (y2 - y1) / (x2 - x1) + return alpha * (curvatures - x1) + y1 + + +if __name__ == '__main__': + sp = Spirograph() + sp.run() diff --git a/extensions/fablabchemnitz/unwind_paths/meta.json b/extensions/fablabchemnitz/unwind_paths/meta.json new file mode 100644 index 0000000..33b09fa --- /dev/null +++ b/extensions/fablabchemnitz/unwind_paths/meta.json @@ -0,0 +1,20 @@ +[ + { + "name": "Unwind Paths", + "id": "fablabchemnitz.de.unwind_paths", + "path": "unwind_paths", + "dependent_extensions": null, + "original_name": "Unwind Paths", + "original_id": "fablabchemnitz.de.unwind_paths", + "license": "GNU GPL v3", + "license_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/LICENSE", + "comment": "Created by Mario Voigt", + "source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/unwind_paths", + "fork_url": null, + "documentation_url": "https://stadtfabrikanten.org/display/IFM/Unwind+Paths", + "inkscape_gallery_url": "https://inkscape.org/de/~MarioVoigt/%E2%98%85unwind-paths", + "main_authors": [ + "github.com/eridur-de" + ] + } +] \ No newline at end of file diff --git a/extensions/fablabchemnitz/unwind_paths/unwind_paths.inx b/extensions/fablabchemnitz/unwind_paths/unwind_paths.inx new file mode 100644 index 0000000..d5cde54 --- /dev/null +++ b/extensions/fablabchemnitz/unwind_paths/unwind_paths.inx @@ -0,0 +1,68 @@ + + + Unwind Paths + fablabchemnitz.de.unwind_paths + + + + false + false + false + + false + 10000 + false + false + + + + + + + + + 0.000 + false + 10.000 + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + ../000_about_fablabchemnitz.svg + + + + all + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/unwind_paths/unwind_paths.py b/extensions/fablabchemnitz/unwind_paths/unwind_paths.py new file mode 100644 index 0000000..833205b --- /dev/null +++ b/extensions/fablabchemnitz/unwind_paths/unwind_paths.py @@ -0,0 +1,272 @@ +#!/usr/bin/env python3 + +""" +Extension for InkScape 1.0+ + +Paperfold is another flattener for triangle mesh files, heavily based on paperfoldmodels by Felix Scholz aka felixfeliz. + +Author: Mario Voigt / FabLab Chemnitz +Mail: mario.voigt@stadtfabrikanten.org +Date: 17.05.2021 +Last patch: 18.05.2021 +License: GNU GPL v3 + +For each selected path element, this extension creates an additional path element +consisting of horizontal line segments which are the same size as the original +path segments. Has options to extrude as a band (adds height; adds vertical lines and another horizontal path as bottom enclosure) + +ToDos: +- option to render separate rectangle shapes +- option to duplicate vertical lines and then to group each 4 lines into one rect-shape like group +- option to colorize vertical line start + end +- option to add glue tabs/flaps +- option to add length text to each segment +- option to add segment/surface numbers +""" +import copy +import inkex +from inkex import Color, bezier, Path, CubicSuperPath, TextElement, Tspan +from inkex.bezier import csplength +from lxml import etree +import math +import random + +class UnwindPaths(inkex.EffectExtension): + + #draw an SVG line segment between the given (raw) points + def drawline(self, pathData, name, parent, line_style): + line_attribs = {'style' : str(inkex.Style(line_style)), inkex.addNS('label','inkscape') : name, 'd' : pathData} + line = etree.SubElement(parent, inkex.addNS('path','svg'), line_attribs ) + + def add_arguments(self, pars): + pars.add_argument('--tab') + pars.add_argument('--keep_original', type=inkex.Boolean, default=False, help="If not selected, the original paths get deleted") + pars.add_argument('--break_apart', type=inkex.Boolean, default=False, help="Split each path into single curve segments") + pars.add_argument('--break_only', type=inkex.Boolean, default=False, help="Only splits root paths into segments (no unwinding)") + pars.add_argument('--colorize', type=inkex.Boolean, default=False, help="Colorize original paths and glue pairs") + pars.add_argument('--color_increment', type=int, default=10000, help="For each segment we count up n colors. Does not apply if 'Randomize colors' is enabled.") + pars.add_argument('--randomize_colors', type=inkex.Boolean, default=False, help="Randomize colors") + pars.add_argument('--number', type=inkex.Boolean, default=False, help="Number segments") + pars.add_argument('--unit', default="mm") + pars.add_argument('--thickness_offset', type=float, default=0.000, help="Allows to add/subtract extra offset length for each curve segment.") + pars.add_argument('--extrude', type=inkex.Boolean, default=False) + pars.add_argument('--extrude_height', type=float, default=10.000) + pars.add_argument('--render_vertical_dividers', type=inkex.Boolean, default=False) + pars.add_argument('--render_with_dashes', type=inkex.Boolean, default=False) + + #if multiple curves are inside the path we split (break apart) + def breakContours(self, element, breakelements = None): #this does the same as "CTRL + SHIFT + K" + if breakelements == None: + breakelements = [] + if element.tag == inkex.addNS('path','svg'): + parent = element.getparent() + idx = parent.index(element) + idSuffix = 0 + raw = element.path.to_arrays() + subPaths, prev = [], 0 + for i in range(len(raw)): # Breaks compound paths into simple paths + if raw[i][0] == 'M' and i != 0: + subPaths.append(raw[prev:i]) + prev = i + subPaths.append(raw[prev:]) + if len(subPaths) > 1: + for subpath in subPaths: + replacedelement = copy.copy(element) + oldId = replacedelement.get('id') + csp = CubicSuperPath(subpath) + if len(subpath) > 1 and csp[0][0] != csp[0][1]: #avoids pointy paths like M "31.4794 57.6024 Z" + replacedelement.set('d', csp) + if len(subPaths) == 1: + replacedelement.set('id', oldId) + else: + replacedelement.set('id', oldId + str(idSuffix)) + idSuffix += 1 + parent.insert(idx, replacedelement) + breakelements.append(replacedelement) + parent.remove(element) + else: + breakelements.append(element) + for child in element.getchildren(): + self.breakContours(child, breakelements) + return breakelements + + def rgb(self, minimum, maximum, value): + minimum, maximum = float(minimum), float(maximum) + ratio = 2 * (value-minimum) / (maximum - minimum) + b = int(max(0, 255 * (1 - ratio))) + r = int(max(0, 255 * (ratio - 1))) + g = 255 - b - r + return r, g, b + + def effect(self): + shifting = self.svg.unittouu(str(self.options.extrude_height) + self.options.unit) + to = self.svg.unittouu(str(self.options.thickness_offset) + self.options.unit) + + #some mode handling + if self.options.colorize is True or self.options.number: + self.options.break_apart = True #required to make it work + + if len(self.svg.selected) > 0: + #we break apart combined paths to get distinct contours + breakApartPaths = [] + for element in self.svg.selection.filter(inkex.PathElement).values(): + breakApartPaths.append(self.breakContours(element)) + + for breakApartPath in breakApartPaths: + for element in breakApartPath: + elemGroup = self.svg.get_current_layer().add(inkex.Group(id="unwinding-" + element.get('id'))) + + #beginning point of the unwind band: + bbox = element.bounding_box() #shift the element to the bottom of the element + xmin = bbox.left + ymax = bbox.bottom + bbox.height * 0.1 #10% additional spacing + + csp = element.path.to_superpath() + subCount = len(element.path) + + #generate random colors; used to identify glue tab pairs + if self.options.colorize is True: + colorSet = [] + if self.options.randomize_colors is True: + while len(colorSet) < subCount - 1: + r = lambda: random.randint(0,255) + newColor = '#%02X%02X%02X' % (r(),r(),r()) + if newColor not in colorSet: + colorSet.append(newColor) + else: + for i in range(subCount): + colorSet.append(Color(self.rgb(0, i+self.options.color_increment, 1*i))) + + slengths, stotal = csplength(csp) #get segment lengths and total length of path in document's internal unit + #self.msg(stotal) #total length of the path + + for sub in csp: + #generate new horizontal line data by measuring each segment + new = [] + new.append([sub[0]]) + i = 1 + topPathData = "m {:0.6f},{:0.6f} ".format(xmin, ymax) + bottomPathData = "m {:0.6f},{:0.6f} ".format(xmin, ymax + shifting) + lengths = [] + + if self.options.break_apart is True: + topLineGroup = self.svg.get_current_layer().add(inkex.Group(id="hline-top-" + element.get('id'))) + bottomLineGroup = self.svg.get_current_layer().add(inkex.Group(id="hline-bottom-" + element.get('id'))) + elemGroup.append(topLineGroup) + elemGroup.append(bottomLineGroup) + + newOriginalPathGroup = self.svg.get_current_layer().add(inkex.Group(id="new-original-" + element.get('id'))) + self.svg.get_current_layer().append(newOriginalPathGroup) #we want this to be one level above unwound stuff + + if self.options.extrude is True: + vlinesGroup = self.svg.get_current_layer().add(inkex.Group(id="vlines-" + element.get('id'))) + elemGroup.append(vlinesGroup) + + if self.options.break_only is False: + while i <= len(sub) - 1: + stroke_color = '#000000' + if self.options.colorize is True and self.options.break_apart is True: + stroke_color =colorSet[i-1] + + horizontal_line_style = {'stroke':stroke_color,'stroke-width':self.svg.unittouu('1px'),'fill':'none'} + + length = bezier.cspseglength(new[-1][-1], sub[i]) + to #sub path length + #if length <= 0: + # inkex.utils.debug("Warning: path id={}, segment={} might overlap with previous and/or next segment. Maybe check for negative thickness offset.".format(element.get('id'), i)) + segment = "h {:0.6f} ".format(length) + topPathData += segment + bottomPathData += segment + new[-1].append(sub[i]) #important line! + + mid_coord_x = xmin + sum([length for length in lengths]) + length/2 + font_size = 5 + font_y_offset = font_size + 1 + + if self.options.number is True: + text = topLineGroup.add(TextElement(id=element.get('id') + "_TextNr{}".format(i))) + text.set("x", "{:0.6f}".format(mid_coord_x)) + text.set("y", "{:0.6f}".format(ymax - font_y_offset)) + text.set("font-size", "{:0.6f}".format(font_size)) + text.set("style", "text-anchor:middle;text-align:center;fill:{}".format(stroke_color)) + + tspan = text.add(Tspan(id=element.get('id') + "_TSpanNr{}".format(i))) + tspan.set("x", "{:0.6f}".format(mid_coord_x)) + if length <= 0: + tspan.set("y", "{:0.6f}".format(ymax - font_y_offset - i)) + else: + tspan.set("y", "{:0.6f}".format(ymax - font_y_offset)) + tspan.text = str(i) + + if self.options.break_apart is True: + self.drawline("m {:0.6f},{:0.6f} ".format(xmin + sum([length for length in lengths]), ymax) + segment, + "segmented-top-{}-{}".format(element.get('id'), i), topLineGroup, horizontal_line_style) + if length <= 0: + self.drawline("m {:0.6f},{:0.6f} ".format(mid_coord_x, ymax) + "v {} ".format(-5-i), + "segmented-top-overlap-{}-{}".format(element.get('id'), i), topLineGroup, horizontal_line_style) + if self.options.extrude is True: + self.drawline("m {:0.6f},{:0.6f} ".format(xmin + sum([length for length in lengths]), ymax + shifting) + segment, + "segmented-bottom-{}-{}".format(element.get('id'), i), bottomLineGroup, horizontal_line_style) + lengths.append(length) + i += 1 + + if self.options.break_apart is False: + self.drawline(topPathData, "combined-top-{0}".format(element.get('id')), elemGroup, horizontal_line_style) + if self.options.extrude is True: + self.drawline(bottomPathData, "combined-bottom-{0}".format(element.get('id')), elemGroup, horizontal_line_style) + + #draw as much vertical lines as segments in bezier + start + end vertical line + vertical_end_lines_style = {'stroke':'#000000','stroke-width':self.svg.unittouu('1px'),'fill':'none'} + if self.options.extrude is True: + #render start line + self.drawline("m {:0.6f},{:0.6f} v {:0.6f}".format(xmin, ymax, shifting),"vline-{}-start".format(element.get('id')), vlinesGroup, vertical_end_lines_style) + #render divider lines + if self.options.render_vertical_dividers is True: + vertical_mid_lines_style = {'stroke':'#000000','stroke-width':self.svg.unittouu('1px'),'fill':'none'} + if self.options.render_with_dashes is True: + vertical_mid_lines_style = {'stroke':'#000000','stroke-width':self.svg.unittouu('1px'),"stroke-dasharray":"2 2", 'fill':'none'} + x = 0 + for n in range(0, i-2): + x += lengths[n] + self.drawline("m {:0.6f},{:0.6f} v {:0.6f}".format(xmin + x, ymax, shifting),"vline-{}-{}".format(element.get('id'), n + 1), vlinesGroup, vertical_mid_lines_style) + #render end line + self.drawline("m {:0.6f},{:0.6f} v {:0.6f}".format(xmin + sum([length for length in lengths]), ymax, shifting),"vline-{}-end".format(element.get('id')), vlinesGroup, vertical_end_lines_style) + + if self.options.break_apart is True: + # Split (already broken apart) paths into detached segments + raw = Path(element.get("d")).to_arrays() #returns Uppercase Command Letters; does not include H, V + for i in range(len(raw)): + if i > 0: + + if raw[i-1][0] in ("M", "L"): + startPoint = "M {},{}".format(raw[i-1][1][0], raw[i-1][1][1]) + elif raw[i-1][0] == 'C': + startPoint = "M {},{}".format(raw[i-1][1][-2], raw[i-1][1][-1]) + else: + inkex.utils.debug("Start point error. Unknown command!") + + if raw[i][0] in ("M", "L"): + segment = " {},{}".format(raw[i][1][0], raw[i][1][1]) + elif raw[i][0] == 'C': + segment = "{} {}".format(raw[i][0], ''.join(str(raw[i][1]))[1:-1]) + elif raw[i][0] == 'Z': + segment = "{},{}".format(raw[0][1][0], raw[0][1][1]) + else: + inkex.utils.debug("Segment error. Unknown command!") + + d = str(Path("{} {}".format(startPoint, segment))) + + stroke_color = '#000000' + if self.options.colorize is True: + stroke_color =colorSet[i-1] + new_original_line_style = {'stroke':stroke_color,'stroke-width':self.svg.unittouu('1px'),'fill':'none'} + self.drawline(d, "segmented-" + element.get('id'), newOriginalPathGroup, new_original_line_style) + + if self.options.keep_original is False: + element.delete() + + else: + self.msg('Please select some paths first.') + return + +if __name__ == '__main__': + UnwindPaths().run() diff --git a/extensions/fablabchemnitz/vektorkollektor/vektorkollektor.inx b/extensions/fablabchemnitz/vektorkollektor/vektorkollektor.inx index 731fbb8..5b262ef 100644 --- a/extensions/fablabchemnitz/vektorkollektor/vektorkollektor.inx +++ b/extensions/fablabchemnitz/vektorkollektor/vektorkollektor.inx @@ -26,7 +26,7 @@ - +