8
8
from .wrappers import ProxyWrapper , _stale_wrapper
9
9
10
10
from .artist import Artist , _renderer_group
11
- from .description import Desc
11
+ from .description import Desc , desc_like
12
12
from .containers import DataContainer
13
- from .conversion_edge import Graph , CoordinateEdge , DefaultEdge
13
+ from .conversion_edge import Graph , CoordinateEdge , DefaultEdge , TransformEdge
14
14
15
15
16
16
class Patch (Artist ):
@@ -21,8 +21,14 @@ def __init__(self, container, edges=None, **kwargs):
21
21
def_edges = [
22
22
CoordinateEdge .from_coords ("xycoords" , {"x" : "auto" , "y" : "auto" }, "data" ),
23
23
CoordinateEdge .from_coords ("codes" , {"codes" : "auto" }, "display" ),
24
- CoordinateEdge .from_coords ("facecolor" , {"color" : Desc (())}, "display" ),
25
- 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
+ ),
26
32
CoordinateEdge .from_coords ("linewidth" , {"linewidth" : Desc (())}, "display" ),
27
33
CoordinateEdge .from_coords ("hatch" , {"hatch" : Desc (())}, "display" ),
28
34
CoordinateEdge .from_coords ("alpha" , {"alpha" : Desc (())}, "display" ),
@@ -45,8 +51,8 @@ def draw(self, renderer, graph: Graph) -> None:
45
51
"x" : desc ,
46
52
"y" : desc ,
47
53
"codes" : desc ,
48
- "facecolor" : scalar ,
49
- "edgecolor" : scalar ,
54
+ "facecolor" : Desc ((), "display" ) ,
55
+ "edgecolor" : Desc (( "M" ,), "display" ) ,
50
56
"linewidth" : scalar ,
51
57
"linestyle" : scalar ,
52
58
"hatch" : scalar ,
@@ -69,7 +75,7 @@ def draw(self, renderer, graph: Graph) -> None:
69
75
with _renderer_group (renderer , "patch" , None ):
70
76
gc = renderer .new_gc ()
71
77
72
- gc .set_foreground (evald ["facecolor " ], isRGBA = False )
78
+ gc .set_foreground (evald ["edgecolor " ], isRGBA = False )
73
79
gc .set_clip_rectangle (
74
80
mtransforms .Bbox .from_extents (clipx [0 ], clipy [0 ], clipx [1 ], clipy [1 ])
75
81
)
@@ -112,6 +118,182 @@ class Rectangle(Patch):
112
118
def __init__ (self , container , edges = None , ** kwargs ):
113
119
super ().__init__ (container , edges , ** kwargs )
114
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
+
115
297
116
298
class PatchWrapper (ProxyWrapper ):
117
299
_wrapped_class = _Patch
0 commit comments