@@ -72,6 +72,117 @@ def segment_hits(cx, cy, x, y, radius):
7272 #print points,lines
7373 return np .concatenate ((points , lines ))
7474
75+ def _mark_every_path (markevery , tpath , affine , ax_transform ):
76+ """
77+ Helper function that sorts out how to deal the input
78+ `markevery` and returns the points where markers should be drawn.
79+
80+ Takes in the `markevery` value and the line path and returns the
81+ sub-sampled path.
82+ """
83+ # pull out the two bits of data we want from the path
84+ codes , verts = tpath .codes , tpath .vertices
85+
86+ def _slice_or_none (in_v , slc ):
87+ '''
88+ Helper function to cope with `codes` being an
89+ ndarray or `None`
90+ '''
91+ if in_v is None :
92+ return None
93+ return in_v [slc ]
94+
95+ # if just a float, assume starting at 0.0 and make a tuple
96+ if isinstance (markevery , float ):
97+ markevery = (0.0 , markevery )
98+ # if just an int, assume starting at 0 and make a tuple
99+ elif isinstance (markevery , int ):
100+ markevery = (0 , markevery )
101+
102+ if isinstance (markevery , tuple ):
103+ if len (markevery ) != 2 :
104+ raise ValueError ('`markevery` is a tuple but its '
105+ 'len is not 2; '
106+ 'markevery=%s' % (markevery ,))
107+ start , step = markevery
108+ # if step is an int, old behavior
109+ if isinstance (step , int ):
110+ #tuple of 2 int is for backwards compatibility,
111+ if not (isinstance (start , int )):
112+ raise ValueError ('`markevery` is a tuple with '
113+ 'len 2 and second element is an int, but '
114+ 'the first element is not an int; '
115+ 'markevery=%s' % (markevery ,))
116+ # just return, we are done here
117+
118+ return Path (verts [slice (start , None , step )],
119+ _slice_or_none (codes , slice (start , None , step )))
120+
121+ elif isinstance (step , float ):
122+ if not (isinstance (start , int ) or
123+ isinstance (start , float )):
124+ raise ValueError ('`markevery` is a tuple with '
125+ 'len 2 and second element is a float, but '
126+ 'the first element is not a float or an '
127+ 'int; '
128+ 'markevery=%s' % (markevery ,))
129+ #calc cumulative distance along path (in display
130+ # coords):
131+ disp_coords = affine .transform (tpath .vertices )
132+ delta = np .empty ((len (disp_coords ), 2 ),
133+ dtype = float )
134+ delta [0 , :] = 0.0
135+ delta [1 :, :] = (disp_coords [1 :, :] -
136+ disp_coords [:- 1 , :])
137+ delta = np .sum (delta ** 2 , axis = 1 )
138+ delta = np .sqrt (delta )
139+ delta = np .cumsum (delta )
140+ #calc distance between markers along path based on
141+ # the axes bounding box diagonal being a distance
142+ # of unity:
143+ scale = ax_transform .transform (
144+ np .array ([[0 , 0 ], [1 , 1 ]]))
145+ scale = np .diff (scale , axis = 0 )
146+ scale = np .sum (scale ** 2 )
147+ scale = np .sqrt (scale )
148+ marker_delta = np .arange (start * scale ,
149+ delta [- 1 ],
150+ step * scale )
151+ #find closest actual data point that is closest to
152+ # the theoretical distance along the path:
153+ inds = np .abs (delta [np .newaxis , :] -
154+ marker_delta [:, np .newaxis ])
155+ inds = inds .argmin (axis = 1 )
156+ inds = np .unique (inds )
157+ # return, we are done here
158+ return Path (verts [inds ],
159+ _slice_or_none (codes , inds ))
160+ else :
161+ raise ValueError ('`markevery` is a tuple with '
162+ 'len 2, but its second element is not an int '
163+ 'or a float; '
164+ 'markevery=%s' % (markevery ,))
165+
166+ elif isinstance (markevery , slice ):
167+ # mazol tov, it's already a slice, just return
168+ return Path (verts [markevery ],
169+ _slice_or_none (codes , markevery ))
170+
171+ elif iterable (markevery ):
172+ #fancy indexing
173+ try :
174+ return Path (verts [markevery ],
175+ _slice_or_none (codes , markevery ))
176+
177+ except (ValueError , IndexError ):
178+ raise ValueError ('`markevery` is iterable but '
179+ 'not a valid form of numpy fancy indexing; '
180+ 'markevery=%s' % (markevery ,))
181+ else :
182+ raise ValueError ('Value of `markevery` is not '
183+ 'recognized; '
184+ 'markevery=%s' % (markevery ,))
185+
75186
76187class Line2D (Artist ):
77188 """
@@ -612,87 +723,8 @@ def draw(self, renderer):
612723 # subsample the markers if markevery is not None
613724 markevery = self .get_markevery ()
614725 if markevery is not None :
615- if isinstance (markevery , float ):
616- markevery = (0.0 , markevery )
617- if isinstance (markevery , tuple ):
618- if len (markevery ) != 2 :
619- raise ValueError ('`markevery` is a tuple but its '
620- 'len is not 2; '
621- 'markevery=%s' % (markevery ,))
622- start , step = markevery
623- if isinstance (step , int ):
624- #tuple of 2 int is for backwards compatibility,
625- if not (isinstance (start , int )):
626- raise ValueError ('`markevery` is a tuple with '
627- 'len 2 and second element is an int, but '
628- 'the first element is not an int; '
629- 'markevery=%s' % (markevery ,))
630- inds = slice (start , None , step )
631- elif isinstance (step , float ):
632- if not (isinstance (start , int ) or
633- isinstance (start , float )):
634- raise ValueError ('`markevery` is a tuple with '
635- 'len 2 and second element is a float, but '
636- 'the first element is not a float or an '
637- 'int; '
638- 'markevery=%s' % (markevery ,))
639- #calc cumulative distance along path (in display
640- # coords):
641- disp_coords = affine .transform (tpath .vertices )
642- delta = np .empty ((len (disp_coords ), 2 ),
643- dtype = float )
644- delta [0 , :] = 0.0
645- delta [1 :, :] = (disp_coords [1 :, :] -
646- disp_coords [:- 1 , :])
647- delta = np .sum (delta ** 2 , axis = 1 )
648- delta = np .sqrt (delta )
649- delta = np .cumsum (delta )
650- #calc distance between markers along path based on
651- # the axes bounding box diagonal being a distance
652- # of unity:
653- scale = self .axes .transAxes .transform (
654- np .array ([[0 , 0 ], [1 , 1 ]]))
655- scale = np .diff (scale , axis = 0 )
656- scale = np .sum (scale ** 2 )
657- scale = np .sqrt (scale )
658- marker_delta = np .arange (start * scale ,
659- delta [- 1 ],
660- step * scale )
661- #find closest actual data point that is closest to
662- # the theoretical distance along the path:
663- inds = np .abs (delta [np .newaxis , :] -
664- marker_delta [:, np .newaxis ])
665- inds = inds .argmin (axis = 1 )
666- inds = np .unique (inds )
667- else :
668- raise ValueError ('`markevery` is a tuple with '
669- 'len 2, but its second element is not an int '
670- 'or a float; '
671- 'markevery=%s' % (markevery ,))
672- elif isinstance (markevery , int ):
673- start , step = 0 , markevery
674- inds = slice (start , None , step )
675- elif isinstance (markevery , slice ):
676- inds = markevery
677- elif iterable (markevery ):
678- #fancy indexing
679- inds = markevery
680- try :
681- tpath .vertices [inds ]
682- except (ValueError , IndexError ):
683- raise ValueError ('`markevery` is iterable but '
684- 'not a valid form of numpy fancy indexing; '
685- 'markevery=%s' % (markevery ,))
686- else :
687- raise ValueError ('Value of `markevery` is not '
688- 'recognized; '
689- 'markevery=%s' % (markevery ,))
690- if tpath .codes is not None :
691- codes = tpath .codes [inds ]
692- else :
693- codes = None
694- vertices = tpath .vertices [inds ]
695- subsampled = Path (vertices , codes )
726+ subsampled = _mark_every_path (markevery , tpath ,
727+ affine , self .axes .transAxes )
696728 else :
697729 subsampled = tpath
698730
0 commit comments