Skip to content

Commit ce39f3f

Browse files
committed
Add a pybind11 type caster for mpl::PathIterator
1 parent 5b3ab87 commit ce39f3f

File tree

2 files changed

+41
-72
lines changed

2 files changed

+41
-72
lines changed

src/_path_wrapper.cpp

Lines changed: 15 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111

1212
#include "_path.h"
1313

14+
#include "py_adaptors.h"
1415
#include "py_converters.h"
1516
#include "py_converters_11.h"
16-
#include "py_adaptors.h"
1717

1818
namespace py = pybind11;
1919
using namespace pybind11::literals;
@@ -37,31 +37,21 @@ convert_polygon_vector(std::vector<Polygon> &polygons)
3737
}
3838

3939
static bool
40-
Py_point_in_path(double x, double y, double r, py::object path_obj,
40+
Py_point_in_path(double x, double y, double r, mpl::PathIterator path,
4141
agg::trans_affine trans)
4242
{
43-
mpl::PathIterator path;
44-
45-
if (!convert_path(path_obj.ptr(), &path)) {
46-
throw py::error_already_set();
47-
}
48-
4943
return point_in_path(x, y, r, path, trans);
5044
}
5145

5246
static py::array_t<double>
53-
Py_points_in_path(py::array_t<double> points_obj, double r, py::object path_obj,
47+
Py_points_in_path(py::array_t<double> points_obj, double r, mpl::PathIterator path,
5448
agg::trans_affine trans)
5549
{
5650
numpy::array_view<double, 2> points;
57-
mpl::PathIterator path;
5851

5952
if (!convert_points(points_obj.ptr(), &points)) {
6053
throw py::error_already_set();
6154
}
62-
if (!convert_path(path_obj.ptr(), &path)) {
63-
throw py::error_already_set();
64-
}
6555

6656
if (!check_trailing_shape(points, "points", 2)) {
6757
throw py::error_already_set();
@@ -77,16 +67,11 @@ Py_points_in_path(py::array_t<double> points_obj, double r, py::object path_obj,
7767
}
7868

7969
static py::tuple
80-
Py_update_path_extents(py::object path_obj, agg::trans_affine trans, agg::rect_d rect,
81-
py::array_t<double> minpos, bool ignore)
70+
Py_update_path_extents(mpl::PathIterator path, agg::trans_affine trans,
71+
agg::rect_d rect, py::array_t<double> minpos, bool ignore)
8272
{
83-
mpl::PathIterator path;
8473
bool changed;
8574

86-
if (!convert_path(path_obj.ptr(), &path)) {
87-
throw py::error_already_set();
88-
}
89-
9075
if (minpos.ndim() != 1) {
9176
throw py::value_error(
9277
"minpos must be 1D, got " + std::to_string(minpos.ndim()));
@@ -210,32 +195,17 @@ Py_point_in_path_collection(double x, double y, double radius,
210195
}
211196

212197
static bool
213-
Py_path_in_path(py::object a_obj, agg::trans_affine atrans,
214-
py::object b_obj, agg::trans_affine btrans)
198+
Py_path_in_path(mpl::PathIterator a, agg::trans_affine atrans,
199+
mpl::PathIterator b, agg::trans_affine btrans)
215200
{
216-
mpl::PathIterator a;
217-
mpl::PathIterator b;
218-
219-
if (!convert_path(a_obj.ptr(), &a)) {
220-
throw py::error_already_set();
221-
}
222-
if (!convert_path(b_obj.ptr(), &b)) {
223-
throw py::error_already_set();
224-
}
225-
226201
return path_in_path(a, atrans, b, btrans);
227202
}
228203

229204
static py::list
230-
Py_clip_path_to_rect(py::object path_obj, agg::rect_d rect, bool inside)
205+
Py_clip_path_to_rect(mpl::PathIterator path, agg::rect_d rect, bool inside)
231206
{
232-
mpl::PathIterator path;
233207
std::vector<Polygon> result;
234208

235-
if (!convert_path(path_obj.ptr(), &path)) {
236-
throw py::error_already_set();
237-
}
238-
239209
clip_path_to_rect(path, rect, inside, result);
240210

241211
return convert_polygon_vector(result);
@@ -286,21 +256,12 @@ Py_count_bboxes_overlapping_bbox(agg::rect_d bbox, py::object bboxes_obj)
286256
}
287257

288258
static bool
289-
Py_path_intersects_path(py::object p1_obj, py::object p2_obj, bool filled)
259+
Py_path_intersects_path(mpl::PathIterator p1, mpl::PathIterator p2, bool filled)
290260
{
291-
mpl::PathIterator p1;
292-
mpl::PathIterator p2;
293261
agg::trans_affine t1;
294262
agg::trans_affine t2;
295263
bool result;
296264

297-
if (!convert_path(p1_obj.ptr(), &p1)) {
298-
throw py::error_already_set();
299-
}
300-
if (!convert_path(p2_obj.ptr(), &p2)) {
301-
throw py::error_already_set();
302-
}
303-
304265
result = path_intersects_path(p1, p2);
305266
if (filled) {
306267
if (!result) {
@@ -315,46 +276,31 @@ Py_path_intersects_path(py::object p1_obj, py::object p2_obj, bool filled)
315276
}
316277

317278
static bool
318-
Py_path_intersects_rectangle(py::object path_obj, double rect_x1, double rect_y1,
279+
Py_path_intersects_rectangle(mpl::PathIterator path, double rect_x1, double rect_y1,
319280
double rect_x2, double rect_y2, bool filled)
320281
{
321-
mpl::PathIterator path;
322-
323-
if (!convert_path(path_obj.ptr(), &path)) {
324-
throw py::error_already_set();
325-
}
326-
327282
return path_intersects_rectangle(path, rect_x1, rect_y1, rect_x2, rect_y2, filled);
328283
}
329284

330285
static py::list
331-
Py_convert_path_to_polygons(py::object path_obj, agg::trans_affine trans,
286+
Py_convert_path_to_polygons(mpl::PathIterator path, agg::trans_affine trans,
332287
double width, double height, bool closed_only)
333288
{
334-
mpl::PathIterator path;
335289
std::vector<Polygon> result;
336290

337-
if (!convert_path(path_obj.ptr(), &path)) {
338-
throw py::error_already_set();
339-
}
340-
341291
convert_path_to_polygons(path, trans, width, height, closed_only, result);
342292

343293
return convert_polygon_vector(result);
344294
}
345295

346296
static py::tuple
347-
Py_cleanup_path(py::object path_obj, agg::trans_affine trans, bool remove_nans,
297+
Py_cleanup_path(mpl::PathIterator path, agg::trans_affine trans, bool remove_nans,
348298
agg::rect_d clip_rect, py::object snap_mode_obj, double stroke_width,
349299
std::optional<bool> simplify, bool return_curves, py::object sketch_obj)
350300
{
351-
mpl::PathIterator path;
352301
e_snap_mode snap_mode;
353302
SketchParams sketch;
354303

355-
if (!convert_path(path_obj.ptr(), &path)) {
356-
throw py::error_already_set();
357-
}
358304
if (!convert_snap(snap_mode_obj.ptr(), &snap_mode)) {
359305
throw py::error_already_set();
360306
}
@@ -417,19 +363,16 @@ postfix : bool
417363
)""";
418364

419365
static py::object
420-
Py_convert_to_string(py::object path_obj, agg::trans_affine trans, agg::rect_d cliprect,
421-
std::optional<bool> simplify, py::object sketch_obj, int precision,
366+
Py_convert_to_string(mpl::PathIterator path, agg::trans_affine trans,
367+
agg::rect_d cliprect, std::optional<bool> simplify,
368+
py::object sketch_obj, int precision,
422369
std::array<std::string, 5> codes_obj, bool postfix)
423370
{
424-
mpl::PathIterator path;
425371
SketchParams sketch;
426372
char *codes[5];
427373
std::string buffer;
428374
bool status;
429375

430-
if (!convert_path(path_obj.ptr(), &path)) {
431-
throw py::error_already_set();
432-
}
433376
if (!convert_sketch_params(sketch_obj.ptr(), &sketch)) {
434377
throw py::error_already_set();
435378
}

src/py_converters_11.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,32 @@ namespace PYBIND11_NAMESPACE { namespace detail {
8484
return true;
8585
}
8686
};
87+
88+
/* Remove all this macro magic after dropping NumPy usage and just include `py_adaptors.h`. */
89+
#ifdef MPL_PY_ADAPTORS_H
90+
template <> struct type_caster<mpl::PathIterator> {
91+
public:
92+
PYBIND11_TYPE_CASTER(mpl::PathIterator, const_name("PathIterator"));
93+
94+
bool load(handle src, bool) {
95+
if (src.is_none()) {
96+
return true;
97+
}
98+
99+
auto vertices = src.attr("vertices");
100+
auto codes = src.attr("codes");
101+
auto should_simplify = src.attr("should_simplify").cast<bool>();
102+
auto simplify_threshold = src.attr("simplify_threshold").cast<double>();
103+
104+
if (!value.set(vertices.ptr(), codes.ptr(),
105+
should_simplify, simplify_threshold)) {
106+
return false;
107+
}
108+
109+
return true;
110+
}
111+
};
112+
#endif
87113
}} // namespace PYBIND11_NAMESPACE::detail
88114

89115
#endif /* MPL_PY_CONVERTERS_11_H */

0 commit comments

Comments
 (0)