7
7
8
8
from .wrappers import ProxyWrapper , _stale_wrapper
9
9
10
- from .containers import DataContainer
11
-
12
10
from .artist import Artist , _renderer_group
13
- from .description import Desc
14
- from .conversion_edge import Graph , CoordinateEdge , DefaultEdge
11
+ from .description import Desc , desc_like
12
+ from .containers import DataContainer
13
+ from .conversion_edge import Graph , CoordinateEdge , DefaultEdge , TransformEdge
15
14
16
15
17
16
class Patch (Artist ):
18
17
def __init__ (self , container , edges = None , ** kwargs ):
19
18
super ().__init__ (container , edges , ** kwargs )
20
19
21
20
scalar = Desc ((), "display" ) # ... this needs thinking...
22
- edges = [
21
+ def_edges = [
23
22
CoordinateEdge .from_coords ("xycoords" , {"x" : "auto" , "y" : "auto" }, "data" ),
24
23
CoordinateEdge .from_coords ("codes" , {"codes" : "auto" }, "display" ),
25
- CoordinateEdge .from_coords ("facecolor" , {"color" : Desc (())}, "display" ),
26
- CoordinateEdge .from_coords ("edgecolor" , {"color" : Desc (())}, "display" ),
24
+ CoordinateEdge .from_coords ("facecolor" , {"facecolor" : Desc (())}, "display" ),
25
+ CoordinateEdge .from_coords ("edgecolor" , {"edgecolor" : Desc (())}, "display" ),
26
+ CoordinateEdge .from_coords (
27
+ "facecolor_rgba" , {"facecolor" : Desc (("M" ,))}, "display"
28
+ ),
29
+ CoordinateEdge .from_coords (
30
+ "edgecolor_rgba" , {"edgecolor" : Desc (("M" ,))}, "display"
31
+ ),
27
32
CoordinateEdge .from_coords ("linewidth" , {"linewidth" : Desc (())}, "display" ),
28
33
CoordinateEdge .from_coords ("hatch" , {"hatch" : Desc (())}, "display" ),
29
34
CoordinateEdge .from_coords ("alpha" , {"alpha" : Desc (())}, "display" ),
@@ -34,39 +39,34 @@ def __init__(self, container, edges=None, **kwargs):
34
39
DefaultEdge .from_default_value ("alpha_def" , "alpha" , scalar , 1 ),
35
40
DefaultEdge .from_default_value ("hatch_def" , "hatch" , scalar , None ),
36
41
]
37
- self ._graph = self ._graph + Graph (edges )
42
+ self ._graph = self ._graph + Graph (def_edges )
38
43
39
44
def draw (self , renderer , graph : Graph ) -> None :
40
45
if not self .get_visible ():
41
46
return
42
- g = graph + self ._graph
43
47
desc = Desc (("N" ,), "display" )
44
48
scalar = Desc ((), "display" ) # ... this needs thinking...
45
49
46
50
require = {
47
51
"x" : desc ,
48
52
"y" : desc ,
49
53
"codes" : desc ,
50
- "facecolor" : scalar ,
51
- "edgecolor" : scalar ,
54
+ "facecolor" : Desc ((), "display" ) ,
55
+ "edgecolor" : Desc (( "M" ,), "display" ) ,
52
56
"linewidth" : scalar ,
53
57
"linestyle" : scalar ,
54
58
"hatch" : scalar ,
55
59
"alpha" : scalar ,
56
60
}
57
61
58
- # copy from line
59
- conv = g .evaluator (self ._container .describe (), require )
60
- query , _ = self ._container .query (g )
61
- evald = conv .evaluate (query )
62
-
63
- clip_conv = g .evaluator (
64
- self ._clip_box .describe (),
65
- {"x" : Desc (("N" ,), "display" ), "y" : Desc (("N" ,), "display" )},
62
+ evald = self ._query_and_eval (
63
+ self ._container , require , graph , cacheset = "default"
66
64
)
67
- clip_query , _ = self ._clip_box .query (g )
68
- clipx , clipy = clip_conv .evaluate (clip_query ).values ()
69
- # copy from line
65
+
66
+ clip_req = {"x" : Desc (("N" ,), "display" ), "y" : Desc (("N" ,), "display" )}
67
+ clipx , clipy = self ._query_and_eval (
68
+ self ._clip_box , clip_req , graph , cacheset = "clip"
69
+ ).values ()
70
70
71
71
path = mpath .Path ._fast_from_codes_and_verts (
72
72
verts = np .vstack ([evald ["x" ], evald ["y" ]]).T , codes = evald ["codes" ]
@@ -75,7 +75,7 @@ def draw(self, renderer, graph: Graph) -> None:
75
75
with _renderer_group (renderer , "patch" , None ):
76
76
gc = renderer .new_gc ()
77
77
78
- gc .set_foreground (evald ["facecolor " ], isRGBA = False )
78
+ gc .set_foreground (evald ["edgecolor " ], isRGBA = False )
79
79
gc .set_clip_rectangle (
80
80
mtransforms .Bbox .from_extents (clipx [0 ], clipy [0 ], clipx [1 ], clipy [1 ])
81
81
)
@@ -111,6 +111,190 @@ def draw(self, renderer, graph: Graph) -> None:
111
111
gc .restore ()
112
112
113
113
114
+ class RectangleContainer (DataContainer ): ...
115
+
116
+
117
+ class Rectangle (Patch ):
118
+ def __init__ (self , container , edges = None , ** kwargs ):
119
+ super ().__init__ (container , edges , ** kwargs )
120
+
121
+ rect = mpath .Path .unit_rectangle ()
122
+
123
+ desc = Desc ((4 ,), "abstract_path" )
124
+ scalar = Desc ((), "data" )
125
+ scalar_auto = Desc (())
126
+ def_edges = [
127
+ CoordinateEdge .from_coords (
128
+ "llxycoords" ,
129
+ {"lower_left_x" : scalar_auto , "lower_left_y" : scalar_auto },
130
+ "data" ,
131
+ ),
132
+ CoordinateEdge .from_coords (
133
+ "urxycoords" ,
134
+ {"upper_right_x" : scalar_auto , "upper_right_y" : scalar_auto },
135
+ "data" ,
136
+ ),
137
+ CoordinateEdge .from_coords (
138
+ "rpxycoords" ,
139
+ {"rotation_point_x" : scalar_auto , "rotation_point_y" : scalar_auto },
140
+ "data" ,
141
+ ),
142
+ CoordinateEdge .from_coords ("anglecoords" , {"angle" : scalar_auto }, "data" ),
143
+ DefaultEdge .from_default_value (
144
+ "x_def" , "x" , desc , rect .vertices .T [0 ], weight = 0.1
145
+ ),
146
+ DefaultEdge .from_default_value (
147
+ "y_def" , "y" , desc , rect .vertices .T [1 ], weight = 0.1
148
+ ),
149
+ DefaultEdge .from_default_value (
150
+ "codes_def" ,
151
+ "codes" ,
152
+ desc_like (desc , coordinates = "display" ),
153
+ rect .codes ,
154
+ weight = 0.1 ,
155
+ ),
156
+ DefaultEdge .from_default_value ("angle_def" , "angle" , scalar , 0 ),
157
+ DefaultEdge .from_default_value (
158
+ "rotation_point_x_def" , "rotation_point_x" , scalar , 0
159
+ ),
160
+ DefaultEdge .from_default_value (
161
+ "rotation_point_y_def" , "rotation_point_y" , scalar , 0
162
+ ),
163
+ ]
164
+
165
+ self ._graph = self ._graph + Graph (def_edges )
166
+
167
+ def _get_dynamic_graph (self , query , description , graph , cacheset ):
168
+ if cacheset == "clip" :
169
+ return Graph ([])
170
+
171
+ desc = Desc ((), "data" )
172
+
173
+ requires = {
174
+ "upper_right_x" : desc ,
175
+ "upper_right_y" : desc ,
176
+ "lower_left_x" : desc ,
177
+ "lower_left_y" : desc ,
178
+ "angle" : desc ,
179
+ "rotation_point_x" : desc ,
180
+ "rotation_point_y" : desc ,
181
+ }
182
+
183
+ g = graph + self ._graph
184
+
185
+ conv = g .evaluator (description , requires )
186
+ evald = conv .evaluate (query )
187
+
188
+ bbox = mtransforms .Bbox .from_extents (
189
+ evald ["lower_left_x" ],
190
+ evald ["lower_left_y" ],
191
+ evald ["upper_right_x" ],
192
+ evald ["upper_right_y" ],
193
+ )
194
+ rotation_point = (evald ["rotation_point_x" ], evald ["rotation_point_y" ])
195
+
196
+ scale = mtransforms .BboxTransformTo (bbox )
197
+ rotate = (
198
+ mtransforms .Affine2D ()
199
+ .translate (- rotation_point [0 ], - rotation_point [1 ])
200
+ .rotate_deg (evald ["angle" ])
201
+ .translate (* rotation_point )
202
+ )
203
+
204
+ descn : Desc = Desc (("N" ,), coordinates = "data" )
205
+ xy : dict [str , Desc ] = {"x" : descn , "y" : descn }
206
+ edges = [
207
+ TransformEdge (
208
+ "scale_and_rotate" ,
209
+ desc_like (xy , coordinates = "abstract_path" ),
210
+ xy ,
211
+ transform = scale + rotate ,
212
+ )
213
+ ]
214
+
215
+ return Graph (edges )
216
+
217
+
218
+ class RegularPolygon (Patch ):
219
+ def __init__ (self , container , edges = None , ** kwargs ):
220
+ super ().__init__ (container , edges , ** kwargs )
221
+
222
+ scalar = Desc ((), "data" )
223
+ scalar_auto = Desc (())
224
+ def_edges = [
225
+ CoordinateEdge .from_coords (
226
+ "centercoords" ,
227
+ {"center_x" : scalar_auto , "center_y" : scalar_auto },
228
+ "data" ,
229
+ ),
230
+ CoordinateEdge .from_coords (
231
+ "orientationcoords" , {"orientation" : scalar_auto }, "data"
232
+ ),
233
+ CoordinateEdge .from_coords ("radiuscoords" , {"radius" : scalar_auto }, "data" ),
234
+ CoordinateEdge .from_coords (
235
+ "num_vertices_coords" , {"num_vertices" : scalar_auto }, "data"
236
+ ),
237
+ DefaultEdge .from_default_value ("orientation_def" , "orientation" , scalar , 0 ),
238
+ DefaultEdge .from_default_value ("radius_def" , "radius" , scalar , 5 ),
239
+ ]
240
+
241
+ self ._graph = self ._graph + Graph (def_edges )
242
+
243
+ def _get_dynamic_graph (self , query , description , graph , cacheset ):
244
+ if cacheset == "clip" :
245
+ return Graph ([])
246
+
247
+ desc = Desc ((), "data" )
248
+ desc_abs = Desc (("N" ,), "abstract_path" )
249
+
250
+ requires = {
251
+ "center_x" : desc ,
252
+ "center_y" : desc ,
253
+ "radius" : desc ,
254
+ "orientation" : desc ,
255
+ "num_vertices" : desc ,
256
+ }
257
+
258
+ g = graph + self ._graph
259
+
260
+ conv = g .evaluator (description , requires )
261
+ evald = conv .evaluate (query )
262
+
263
+ circ = mpath .Path .unit_regular_polygon (evald ["num_vertices" ])
264
+
265
+ scale = mtransforms .Affine2D ().scale (evald ["radius" ])
266
+ rotate = mtransforms .Affine2D ().rotate (evald ["orientation" ])
267
+ translate = mtransforms .Affine2D ().translate (
268
+ evald ["center_x" ], evald ["center_y" ]
269
+ )
270
+
271
+ descn : Desc = Desc (("N" ,), coordinates = "data" )
272
+ xy : dict [str , Desc ] = {"x" : descn , "y" : descn }
273
+ edges = [
274
+ TransformEdge (
275
+ "scale_and_rotate" ,
276
+ desc_like (xy , coordinates = "abstract_path" ),
277
+ xy ,
278
+ transform = scale + rotate + translate ,
279
+ ),
280
+ DefaultEdge .from_default_value (
281
+ "x_def" , "x" , desc_abs , circ .vertices .T [0 ], weight = 0.1
282
+ ),
283
+ DefaultEdge .from_default_value (
284
+ "y_def" , "y" , desc_abs , circ .vertices .T [1 ], weight = 0.1
285
+ ),
286
+ DefaultEdge .from_default_value (
287
+ "codes_def" ,
288
+ "codes" ,
289
+ desc_like (desc_abs , coordinates = "display" ),
290
+ circ .codes ,
291
+ weight = 0.1 ,
292
+ ),
293
+ ]
294
+
295
+ return Graph (edges )
296
+
297
+
114
298
class PatchWrapper (ProxyWrapper ):
115
299
_wrapped_class = _Patch
116
300
_privtized_methods = (
0 commit comments