FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
matplotlib/src/_path_wrapper.cpp at main · matplotlib/matplotlib · GitHub
Uh oh!
There was an error while loading.
Please reload this page
.
matplotlib
/
matplotlib
Public
Uh oh!
There was an error while loading.
Please reload this page
.
Notifications
You must be signed in to change notification settings
Fork
8.5k
Star
23.1k
Code
Issues
1.1k
Pull requests
415
Actions
Projects
Wiki
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
matplotlib
/
src
/
_path_wrapper.cpp
Copy path
More file actions
More file actions
Latest commit
History
History
History
352 lines (290 loc) · 11.6 KB
Breadcrumbs
matplotlib
/
src
/
_path_wrapper.cpp
Copy path
File metadata and controls
352 lines (290 loc) · 11.6 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
#
include
<
pybind11/pybind11.h
>
#
include
<
pybind11/stl.h
>
#
ifdef
PYBIND11_HAS_SUBINTERPRETER_SUPPORT
#
include
<
pybind11/subinterpreter.h
>
#
endif
#
include
<
array
>
#
include
<
limits
>
#
include
<
optional
>
#
include
<
string
>
#
include
<
vector
>
#
include
"
_path.h
"
#
include
"
_backend_agg_basic_types.h
"
#
include
"
py_adaptors.h
"
#
include
"
py_converters.h
"
namespace
py
=
pybind11;
using
namespace
pybind11
::literals
;
py::list
convert_polygon_vector
(std::vector<Polygon> &polygons)
{
auto
result =
py::list
(polygons.
size
());
for
(
size_t
i =
0
; i < polygons.
size
(); ++i) {
const
auto
& poly = polygons[i];
py::
ssize_t
dims[] = {
static_cast
<py::
ssize_t
>(poly.
size
()),
2
};
result[i] =
py::array
(dims,
reinterpret_cast
<
const
double
*>(poly.
data
()));
}
return
result;
}
static
bool
Py_point_in_path
(
double
x,
double
y,
double
r, mpl::PathIterator path,
agg::trans_affine trans)
{
return
point_in_path
(x, y, r, path, trans);
}
static
py::
array_t
<
double
>
Py_points_in_path
(py::
array_t
<
double
> points_obj,
double
r, mpl::PathIterator path,
agg::trans_affine trans)
{
auto
points =
convert_points
(points_obj);
py::
ssize_t
dims[] = { points.
shape
(
0
) };
py::
array_t
<
uint8_t
>
results
(dims);
auto
results_mutable = results.
mutable_unchecked
<
1
>();
points_in_path
(points, r, path, trans, results_mutable);
return
results;
}
static
py::tuple
Py_get_path_collection_extents
(agg::trans_affine master_transform,
mpl::PathGenerator paths,
py::
array_t
<
double
> transforms_obj,
py::
array_t
<
double
> offsets_obj,
agg::trans_affine offset_trans)
{
auto
transforms =
convert_transforms
(transforms_obj);
auto
offsets =
convert_points
(offsets_obj);
extent_limits e;
get_path_collection_extents
(
master_transform, paths, transforms, offsets, offset_trans, e);
py::
ssize_t
dims[] = {
2
,
2
};
py::
array_t
<
double
>
extents
(dims);
*extents.
mutable_data
(
0
,
0
) = e.
start
.
x
;
*extents.
mutable_data
(
0
,
1
) = e.
start
.
y
;
*extents.
mutable_data
(
1
,
0
) = e.
end
.
x
;
*extents.
mutable_data
(
1
,
1
) = e.
end
.
y
;
py::
ssize_t
minposdims[] = {
2
};
py::
array_t
<
double
>
minpos
(minposdims);
*minpos.
mutable_data
(
0
) = e.
minpos
.
x
;
*minpos.
mutable_data
(
1
) = e.
minpos
.
y
;
return
py::make_tuple
(extents, minpos);
}
static
py::object
Py_point_in_path_collection
(
double
x,
double
y,
double
radius,
agg::trans_affine master_transform, mpl::PathGenerator paths,
py::
array_t
<
double
> transforms_obj,
py::
array_t
<
double
> offsets_obj,
agg::trans_affine offset_trans,
bool
filled)
{
auto
transforms =
convert_transforms
(transforms_obj);
auto
offsets =
convert_points
(offsets_obj);
std::vector<
int
> result;
point_in_path_collection
(x, y, radius, master_transform, paths, transforms, offsets,
offset_trans, filled, result);
py::
ssize_t
dims[] = {
static_cast
<py::
ssize_t
>(result.
size
()) };
return
py::array
(dims, result.
data
());
}
static
bool
Py_path_in_path
(mpl::PathIterator a, agg::trans_affine atrans,
mpl::PathIterator b, agg::trans_affine btrans)
{
return
path_in_path
(a, atrans, b, btrans);
}
static
py::list
Py_clip_path_to_rect
(mpl::PathIterator path, agg::rect_d rect,
bool
inside)
{
auto
result =
clip_path_to_rect
(path, rect, inside);
return
convert_polygon_vector
(result);
}
static
py::object
Py_affine_transform
(py::
array_t
<
double
, py::array::c_style | py::array::forcecast> vertices_arr,
agg::trans_affine trans)
{
if
(vertices_arr.
ndim
() ==
2
) {
auto
vertices = vertices_arr.
unchecked
<
2
>();
check_trailing_shape
(vertices,
"
vertices
"
,
2
);
py::
ssize_t
dims[] = { vertices.
shape
(
0
),
2
};
py::
array_t
<
double
>
result
(dims);
auto
result_mutable = result.
mutable_unchecked
<
2
>();
affine_transform_2d
(vertices, trans, result_mutable);
return
result;
}
else
if
(vertices_arr.
ndim
() ==
1
) {
auto
vertices = vertices_arr.
unchecked
<
1
>();
py::
ssize_t
dims[] = { vertices.
shape
(
0
) };
py::
array_t
<
double
>
result
(dims);
auto
result_mutable = result.
mutable_unchecked
<
1
>();
affine_transform_1d
(vertices, trans, result_mutable);
return
result;
}
else
{
throw
py::value_error
(
"
vertices must be 1D or 2D, not
"
+
std::to_string
(vertices_arr.
ndim
()) +
"
D
"
);
}
}
static
int
Py_count_bboxes_overlapping_bbox
(agg::rect_d bbox, py::
array_t
<
double
> bboxes_obj)
{
auto
bboxes =
convert_bboxes
(bboxes_obj);
return
count_bboxes_overlapping_bbox
(bbox, bboxes);
}
static
bool
Py_path_intersects_path
(mpl::PathIterator p1, mpl::PathIterator p2,
bool
filled)
{
agg::trans_affine t1;
agg::trans_affine t2;
bool
result;
result =
path_intersects_path
(p1, p2);
if
(filled) {
if
(!result) {
result =
path_in_path
(p1, t1, p2, t2);
}
if
(!result) {
result =
path_in_path
(p2, t1, p1, t2);
}
}
return
result;
}
static
bool
Py_path_intersects_rectangle
(mpl::PathIterator path,
double
rect_x1,
double
rect_y1,
double
rect_x2,
double
rect_y2,
bool
filled)
{
return
path_intersects_rectangle
(path, rect_x1, rect_y1, rect_x2, rect_y2, filled);
}
static
py::list
Py_convert_path_to_polygons
(mpl::PathIterator path, agg::trans_affine trans,
double
width,
double
height,
bool
closed_only)
{
std::vector<Polygon> result;
convert_path_to_polygons
(path, trans, width, height, closed_only, result);
return
convert_polygon_vector
(result);
}
static
py::tuple
Py_cleanup_path
(mpl::PathIterator path, agg::trans_affine trans,
bool
remove_nans,
agg::rect_d clip_rect, e_snap_mode snap_mode,
double
stroke_width,
std::optional<
bool
> simplify,
bool
return_curves, SketchParams sketch)
{
if
(!simplify.
has_value
()) {
simplify = path.
should_simplify
();
}
bool
do_clip = (clip_rect.
x1
< clip_rect.
x2
&& clip_rect.
y1
< clip_rect.
y2
);
std::vector<
double
> vertices;
std::vector<
uint8_t
> codes;
cleanup_path
(path, trans, remove_nans, do_clip, clip_rect, snap_mode, stroke_width,
*simplify, return_curves, sketch, vertices, codes);
auto
length =
static_cast
<py::
ssize_t
>(codes.
size
());
py::
ssize_t
vertices_dims[] = { length,
2
};
py::array
pyvertices
(vertices_dims, vertices.
data
());
py::
ssize_t
codes_dims[] = { length };
py::array
pycodes
(codes_dims, codes.
data
());
return
py::make_tuple
(pyvertices, pycodes);
}
const
char
*Py_convert_to_string__doc__ =
R"""(
--
Convert *path* to a bytestring.
The first five parameters (up to *sketch*) are interpreted as in `.cleanup_path`. The
following ones are detailed below.
Parameters
----------
path : Path
trans : Transform or None
clip_rect : sequence of 4 floats, or None
simplify : bool
sketch : tuple of 3 floats, or None
precision : int
The precision used to "%.*f"-format the values. Trailing zeros and decimal points
are always removed. (precision=-1 is a special case used to implement
ttconv-back-compatible conversion.)
codes : sequence of 5 bytestrings
The bytes representation of each opcode (MOVETO, LINETO, CURVE3, CURVE4, CLOSEPOLY),
in that order. If the bytes for CURVE3 is empty, quad segments are automatically
converted to cubic ones (this is used by backends such as pdf and ps, which do not
support quads).
postfix : bool
Whether the opcode comes after the values (True) or before (False).
)"""
;
static
py::object
Py_convert_to_string
(mpl::PathIterator path, agg::trans_affine trans,
agg::rect_d cliprect, std::optional<
bool
> simplify,
SketchParams sketch,
int
precision,
const
std::array<std::string,
5
> &codes,
bool
postfix)
{
std::string buffer;
bool
status;
if
(!simplify.
has_value
()) {
simplify = path.
should_simplify
();
}
status =
convert_to_string
(path, trans, cliprect, *simplify, sketch, precision,
codes, postfix, buffer);
if
(!status) {
throw
py::value_error
(
"
Malformed path codes
"
);
}
return
py::bytes
(buffer);
}
const
char
*Py_is_sorted_and_has_non_nan__doc__ =
R"""(
--
Return whether the 1D *array* is monotonically increasing, ignoring NaNs, and has at
least one non-nan value.
)"""
;
static
bool
Py_is_sorted_and_has_non_nan
(py::object obj)
{
bool
result;
py::array array =
py::array::ensure
(obj);
if
(array.
ndim
() !=
1
) {
throw
std::invalid_argument
(
"
array must be 1D
"
);
}
auto
dtype = array.
dtype
();
/*
Handle just the most common types here, otherwise coerce to double
*/
if
(dtype.
equal
(py::dtype::of<std::
int32_t
>())) {
result = is_sorted_and_has_non_nan<
int32_t
>(array);
}
else
if
(dtype.
equal
(py::dtype::of<std::
int64_t
>())) {
result = is_sorted_and_has_non_nan<
int64_t
>(array);
}
else
if
(dtype.
equal
(py::dtype::of<
float
>())) {
result = is_sorted_and_has_non_nan<
float
>(array);
}
else
if
(dtype.
equal
(py::dtype::of<
double
>())) {
result = is_sorted_and_has_non_nan<
double
>(array);
}
else
{
array = py::
array_t
<
double
>::
ensure
(obj);
result = is_sorted_and_has_non_nan<
double
>(array);
}
return
result;
}
#
ifdef
PYBIND11_HAS_SUBINTERPRETER_SUPPORT
PYBIND11_MODULE
(_path, m,
py::mod_gil_not_used
(), py::multiple_interpreters::per_interpreter_gil())
#
else
PYBIND11_MODULE
(_path, m, py::mod_gil_not_used())
#
endif
{
m.
def
(
"
point_in_path
"
, &Py_point_in_path,
"
x
"
_a,
"
y
"
_a,
"
radius
"
_a,
"
path
"
_a,
"
trans
"
_a);
m.
def
(
"
points_in_path
"
, &Py_points_in_path,
"
points
"
_a,
"
radius
"
_a,
"
path
"
_a,
"
trans
"
_a);
m.
def
(
"
get_path_collection_extents
"
, &Py_get_path_collection_extents,
"
master_transform
"
_a,
"
paths
"
_a,
"
transforms
"
_a,
"
offsets
"
_a,
"
offset_transform
"
_a);
m.
def
(
"
point_in_path_collection
"
, &Py_point_in_path_collection,
"
x
"
_a,
"
y
"
_a,
"
radius
"
_a,
"
master_transform
"
_a,
"
paths
"
_a,
"
transforms
"
_a,
"
offsets
"
_a,
"
offset_trans
"
_a,
"
filled
"
_a);
m.
def
(
"
path_in_path
"
, &Py_path_in_path,
"
path_a
"
_a,
"
trans_a
"
_a,
"
path_b
"
_a,
"
trans_b
"
_a);
m.
def
(
"
clip_path_to_rect
"
, &Py_clip_path_to_rect,
"
path
"
_a,
"
rect
"
_a,
"
inside
"
_a);
m.
def
(
"
affine_transform
"
, &Py_affine_transform,
"
points
"
_a,
"
trans
"
_a);
m.
def
(
"
count_bboxes_overlapping_bbox
"
, &Py_count_bboxes_overlapping_bbox,
"
bbox
"
_a,
"
bboxes
"
_a);
m.
def
(
"
path_intersects_path
"
, &Py_path_intersects_path,
"
path1
"
_a,
"
path2
"
_a,
"
filled
"
_a =
false
);
m.
def
(
"
path_intersects_rectangle
"
, &Py_path_intersects_rectangle,
"
path
"
_a,
"
rect_x1
"
_a,
"
rect_y1
"
_a,
"
rect_x2
"
_a,
"
rect_y2
"
_a,
"
filled
"
_a =
false
);
m.
def
(
"
convert_path_to_polygons
"
, &Py_convert_path_to_polygons,
"
path
"
_a,
"
trans
"
_a,
"
width
"
_a =
0.0
,
"
height
"
_a =
0.0
,
"
closed_only
"
_a =
false
);
m.
def
(
"
cleanup_path
"
, &Py_cleanup_path,
"
path
"
_a,
"
trans
"
_a,
"
remove_nans
"
_a,
"
clip_rect
"
_a,
"
snap_mode
"
_a,
"
stroke_width
"
_a,
"
simplify
"
_a,
"
return_curves
"
_a,
"
sketch
"
_a);
m.
def
(
"
convert_to_string
"
, &Py_convert_to_string,
"
path
"
_a,
"
trans
"
_a,
"
clip_rect
"
_a,
"
simplify
"
_a,
"
sketch
"
_a,
"
precision
"
_a,
"
codes
"
_a,
"
postfix
"
_a,
Py_convert_to_string__doc__);
m.
def
(
"
is_sorted_and_has_non_nan
"
, &Py_is_sorted_and_has_non_nan,
"
array
"
_a,
Py_is_sorted_and_has_non_nan__doc__);
}
Back
|
FazBrowse Home
|
New Git URL