Skip to content

Commit 4a56e52

Browse files
committed
Add a pybind11 type caster for agg::trans_affine
1 parent 25fbbd3 commit 4a56e52

File tree

2 files changed

+42
-42
lines changed

2 files changed

+42
-42
lines changed

src/_path_wrapper.cpp

Lines changed: 14 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -34,34 +34,30 @@ convert_polygon_vector(std::vector<Polygon> &polygons)
3434

3535
static bool
3636
Py_point_in_path(double x, double y, double r, py::object path_obj,
37-
py::object trans_obj)
37+
agg::trans_affine trans)
3838
{
3939
mpl::PathIterator path;
40-
agg::trans_affine trans;
4140

4241
if (!convert_path(path_obj.ptr(), &path)) {
4342
throw py::error_already_set();
4443
}
45-
convert_trans_affine(trans_obj, trans);
4644

4745
return point_in_path(x, y, r, path, trans);
4846
}
4947

5048
static py::array_t<double>
5149
Py_points_in_path(py::array_t<double> points_obj, double r, py::object path_obj,
52-
py::object trans_obj)
50+
agg::trans_affine trans)
5351
{
5452
numpy::array_view<double, 2> points;
5553
mpl::PathIterator path;
56-
agg::trans_affine trans;
5754

5855
if (!convert_points(points_obj.ptr(), &points)) {
5956
throw py::error_already_set();
6057
}
6158
if (!convert_path(path_obj.ptr(), &path)) {
6259
throw py::error_already_set();
6360
}
64-
convert_trans_affine(trans_obj, trans);
6561

6662
if (!check_trailing_shape(points, "points", 2)) {
6763
throw py::error_already_set();
@@ -77,17 +73,15 @@ Py_points_in_path(py::array_t<double> points_obj, double r, py::object path_obj,
7773
}
7874

7975
static py::tuple
80-
Py_update_path_extents(py::object path_obj, py::object trans_obj, agg::rect_d rect,
76+
Py_update_path_extents(py::object path_obj, agg::trans_affine trans, agg::rect_d rect,
8177
py::array_t<double> minpos, bool ignore)
8278
{
8379
mpl::PathIterator path;
84-
agg::trans_affine trans;
8580
bool changed;
8681

8782
if (!convert_path(path_obj.ptr(), &path)) {
8883
throw py::error_already_set();
8984
}
90-
convert_trans_affine(trans_obj, trans);
9185

9286
if (minpos.ndim() != 1) {
9387
throw py::value_error(
@@ -142,18 +136,15 @@ Py_update_path_extents(py::object path_obj, py::object trans_obj, agg::rect_d re
142136
}
143137

144138
static py::tuple
145-
Py_get_path_collection_extents(py::object master_transform_obj, py::object paths_obj,
146-
py::object transforms_obj, py::object offsets_obj,
147-
py::object offset_trans_obj)
139+
Py_get_path_collection_extents(agg::trans_affine master_transform,
140+
py::object paths_obj, py::object transforms_obj,
141+
py::object offsets_obj, agg::trans_affine offset_trans)
148142
{
149-
agg::trans_affine master_transform;
150143
mpl::PathGenerator paths;
151144
numpy::array_view<const double, 3> transforms;
152145
numpy::array_view<const double, 2> offsets;
153-
agg::trans_affine offset_trans;
154146
extent_limits e;
155147

156-
convert_trans_affine(master_transform_obj, master_transform);
157148
if (!convert_pathgen(paths_obj.ptr(), &paths)) {
158149
throw py::error_already_set();
159150
}
@@ -163,7 +154,6 @@ Py_get_path_collection_extents(py::object master_transform_obj, py::object paths
163154
if (!convert_points(offsets_obj.ptr(), &offsets)) {
164155
throw py::error_already_set();
165156
}
166-
convert_trans_affine(offset_trans_obj, offset_trans);
167157

168158
get_path_collection_extents(
169159
master_transform, paths, transforms, offsets, offset_trans, e);
@@ -185,18 +175,15 @@ Py_get_path_collection_extents(py::object master_transform_obj, py::object paths
185175

186176
static py::object
187177
Py_point_in_path_collection(double x, double y, double radius,
188-
py::object master_transform_obj, py::object paths_obj,
178+
agg::trans_affine master_transform, py::object paths_obj,
189179
py::object transforms_obj, py::object offsets_obj,
190-
py::object offset_trans_obj, bool filled)
180+
agg::trans_affine offset_trans, bool filled)
191181
{
192-
agg::trans_affine master_transform;
193182
mpl::PathGenerator paths;
194183
numpy::array_view<const double, 3> transforms;
195184
numpy::array_view<const double, 2> offsets;
196-
agg::trans_affine offset_trans;
197185
std::vector<int> result;
198186

199-
convert_trans_affine(master_transform_obj, master_transform);
200187
if (!convert_pathgen(paths_obj.ptr(), &paths)) {
201188
throw py::error_already_set();
202189
}
@@ -206,7 +193,6 @@ Py_point_in_path_collection(double x, double y, double radius,
206193
if (!convert_points(offsets_obj.ptr(), &offsets)) {
207194
throw py::error_already_set();
208195
}
209-
convert_trans_affine(offset_trans_obj, offset_trans);
210196

211197
point_in_path_collection(x, y, radius, master_transform, paths, transforms, offsets,
212198
offset_trans, filled, result);
@@ -216,22 +202,18 @@ Py_point_in_path_collection(double x, double y, double radius,
216202
}
217203

218204
static bool
219-
Py_path_in_path(py::object a_obj, py::object atrans_obj,
220-
py::object b_obj, py::object btrans_obj)
205+
Py_path_in_path(py::object a_obj, agg::trans_affine atrans,
206+
py::object b_obj, agg::trans_affine btrans)
221207
{
222208
mpl::PathIterator a;
223-
agg::trans_affine atrans;
224209
mpl::PathIterator b;
225-
agg::trans_affine btrans;
226210

227211
if (!convert_path(a_obj.ptr(), &a)) {
228212
throw py::error_already_set();
229213
}
230-
convert_trans_affine(atrans_obj, atrans);
231214
if (!convert_path(b_obj.ptr(), &b)) {
232215
throw py::error_already_set();
233216
}
234-
convert_trans_affine(btrans_obj, btrans);
235217

236218
return path_in_path(a, atrans, b, btrans);
237219
}
@@ -253,12 +235,8 @@ Py_clip_path_to_rect(py::object path_obj, agg::rect_d rect, bool inside)
253235

254236
static py::object
255237
Py_affine_transform(py::array_t<double, py::array::c_style | py::array::forcecast> vertices_arr,
256-
py::object trans_obj)
238+
agg::trans_affine trans)
257239
{
258-
agg::trans_affine trans;
259-
260-
convert_trans_affine(trans_obj, trans);
261-
262240
if (vertices_arr.ndim() == 2) {
263241
auto vertices = vertices_arr.unchecked<2>();
264242

@@ -342,37 +320,33 @@ Py_path_intersects_rectangle(py::object path_obj, double rect_x1, double rect_y1
342320
}
343321

344322
static py::list
345-
Py_convert_path_to_polygons(py::object path_obj, py::object trans_obj,
323+
Py_convert_path_to_polygons(py::object path_obj, agg::trans_affine trans,
346324
double width, double height, bool closed_only)
347325
{
348326
mpl::PathIterator path;
349-
agg::trans_affine trans;
350327
std::vector<Polygon> result;
351328

352329
if (!convert_path(path_obj.ptr(), &path)) {
353330
throw py::error_already_set();
354331
}
355-
convert_trans_affine(trans_obj, trans);
356332

357333
convert_path_to_polygons(path, trans, width, height, closed_only, result);
358334

359335
return convert_polygon_vector(result);
360336
}
361337

362338
static py::tuple
363-
Py_cleanup_path(py::object path_obj, py::object trans_obj, bool remove_nans,
339+
Py_cleanup_path(py::object path_obj, agg::trans_affine trans, bool remove_nans,
364340
agg::rect_d clip_rect, py::object snap_mode_obj, double stroke_width,
365341
std::optional<bool> simplify, bool return_curves, py::object sketch_obj)
366342
{
367343
mpl::PathIterator path;
368-
agg::trans_affine trans;
369344
e_snap_mode snap_mode;
370345
SketchParams sketch;
371346

372347
if (!convert_path(path_obj.ptr(), &path)) {
373348
throw py::error_already_set();
374349
}
375-
convert_trans_affine(trans_obj, trans);
376350
if (!convert_snap(snap_mode_obj.ptr(), &snap_mode)) {
377351
throw py::error_already_set();
378352
}
@@ -432,12 +406,11 @@ postfix : bool
432406
)""";
433407

434408
static py::object
435-
Py_convert_to_string(py::object path_obj, py::object trans_obj, agg::rect_d cliprect,
409+
Py_convert_to_string(py::object path_obj, agg::trans_affine trans, agg::rect_d cliprect,
436410
std::optional<bool> simplify, py::object sketch_obj, int precision,
437411
std::array<std::string, 5> codes_obj, bool postfix)
438412
{
439413
mpl::PathIterator path;
440-
agg::trans_affine trans;
441414
SketchParams sketch;
442415
char *codes[5];
443416
std::string buffer;
@@ -446,7 +419,6 @@ Py_convert_to_string(py::object path_obj, py::object trans_obj, agg::rect_d clip
446419
if (!convert_path(path_obj.ptr(), &path)) {
447420
throw py::error_already_set();
448421
}
449-
convert_trans_affine(trans_obj, trans);
450422
if (!convert_sketch_params(sketch_obj.ptr(), &sketch)) {
451423
throw py::error_already_set();
452424
}

src/py_converters_11.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,34 @@ namespace PYBIND11_NAMESPACE { namespace detail {
5656
return true;
5757
}
5858
};
59+
60+
template <> struct type_caster<agg::trans_affine> {
61+
public:
62+
PYBIND11_TYPE_CASTER(agg::trans_affine, const_name("trans_affine"));
63+
64+
bool load(handle src, bool) {
65+
// If None assume identity transform so leave affine unchanged
66+
if (src.is_none()) {
67+
return true;
68+
}
69+
70+
auto array = py::array_t<double, py::array::c_style>::ensure(src);
71+
if (!array || array.ndim() != 2 ||
72+
array.shape(0) != 3 || array.shape(1) != 3) {
73+
throw std::invalid_argument("Invalid affine transformation matrix");
74+
}
75+
76+
auto buffer = array.data();
77+
value.sx = buffer[0];
78+
value.shx = buffer[1];
79+
value.tx = buffer[2];
80+
value.shy = buffer[3];
81+
value.sy = buffer[4];
82+
value.ty = buffer[5];
83+
84+
return true;
85+
}
86+
};
5987
}} // namespace PYBIND11_NAMESPACE::detail
6088

6189
#endif /* MPL_PY_CONVERTERS_11_H */

0 commit comments

Comments
 (0)