22"""
33SVGPATH2MPL
44~~~~~~~~~~~
5- Parse SVG path data strings into matplotlib ` Path` objects.
5+ Parse SVG path definition strings into matplotlib Path objects.
66A path in SVG is defined by a 'path' element which contains a
77``d="(path data)"`` attribute that contains moveto, line, curve (both
88cubic and quadratic Béziers), arc and closepath instructions. See the SVG
1111:copyright: (c) 2016, Nezar Abdennur.
1212:license: BSD.
1313
14- Notes
15- ~~~~~
16- 2018-10: Parser re-write based largely on svg.path
17- (https://github.com/regebro/svg.path/blob/master/src/svg/path/parser.py)
18- 2D coordinates are now encoded as complex numbers.
19-
2014"""
2115from __future__ import division , print_function
2216from math import sin , cos , sqrt , degrees , radians , acos
@@ -161,7 +155,7 @@ def endpoint_to_center(start, radius, rotation, large, sweep, end):
161155 if uy < 0 :
162156 theta = - theta
163157
164- # the angle between two vectors ((x1'-cx')/rx, (y1'-c1y/ry)) and
158+ # the angle between two vectors ((x1'-cx')/rx, (y1'-c1y/ry)) and
165159 # ((-x1'-cx')/rx, (-y1'-c1y/ry))
166160 p = ux * vx + uy * vy
167161 n = sqrt ((ux * ux + uy * uy ) * (vx * vx + vy * vy ))
@@ -190,7 +184,7 @@ def _tokenize_path(pathdef):
190184 for token in FLOAT_RE .findall (x ):
191185 yield token
192186
193-
187+
194188def _next_pos (elements ):
195189 return float (elements .pop ()) + float (elements .pop ()) * 1j
196190
@@ -244,7 +238,7 @@ def _parse_path(pathdef, current_pos):
244238 start_pos = current_pos
245239
246240 yield COMMAND_CODES ['M' ], [(current_pos .real , current_pos .imag )]
247-
241+
248242 # Implicit moveto commands are treated as lineto commands.
249243 # So we set command to lineto here, in case there are
250244 # further implicit commands after this moveto.
@@ -264,7 +258,7 @@ def _parse_path(pathdef, current_pos):
264258 current_pos = start_pos
265259 start_pos = None
266260 command = None # You can't have implicit commands after closing.
267-
261+
268262 # LINETO
269263 elif command == 'L' :
270264 pos = _next_pos (elements )
@@ -389,20 +383,20 @@ def _parse_path(pathdef, current_pos):
389383 end += current_pos
390384
391385 center , theta1 , theta2 = endpoint_to_center (
392- current_pos ,
393- radius ,
394- rotation ,
395- large ,
396- sweep ,
386+ current_pos ,
387+ radius ,
388+ rotation ,
389+ large ,
390+ sweep ,
397391 end
398392 )
399-
393+
400394 # Create an arc on the unit circle
401395 if theta2 > theta1 :
402396 arc = Path .arc (theta1 = theta1 , theta2 = theta2 )
403397 else :
404398 arc = Path .arc (theta1 = theta2 , theta2 = theta1 )
405-
399+
406400 # Transform it into an elliptical arc:
407401 # * scale the minor and major axes
408402 # * translate it to the center
@@ -417,7 +411,7 @@ def _parse_path(pathdef, current_pos):
417411 arc = trans .transform_path (arc )
418412
419413 verts = np .array (arc .vertices )
420- codes = np .array (arc .codes )
414+ codes = np .array (arc .codes )
421415 if sweep :
422416 # mysterious hack needed to render properly when sweeping the
423417 # arc angle in the "positive" angular direction
@@ -427,8 +421,32 @@ def _parse_path(pathdef, current_pos):
427421
428422 current_pos = end
429423
430-
424+
431425def parse_path (pathdef , current_pos = 0 + 0j ):
426+ """
427+ Parse an SVG path definition string into a matplotlib Path object.
428+
429+ Parameters
430+ ----------
431+ pathdef : str
432+ SVG path 'd' attribute, e.g. 'M 100 100 L 300 100 L 200 300 z'.
433+ current_pos : complex, optional
434+ Coordinates of the starting position of the path, given as a complex
435+ number. When provided, an initial moveto operation will be intepreted
436+ as relative to this position even if given as M.
437+
438+ Returns
439+ -------
440+ :class:`matplotlib.path.Path` instance
441+
442+ See also
443+ --------
444+ matplotlib.path.Path
445+ matplotlib.patches.PathPatch
446+ matplotlib.collections.PathCollection
447+ matplotlib.transforms
448+
449+ """
432450 codes = []
433451 verts = []
434452 for c , v in _parse_path (pathdef , current_pos ):
0 commit comments