1 #ifdef NANOGUI_PYTHON
2 
3 #include "python.h"
4 
register_eigen(py::module & m)5 void register_eigen(py::module &m) {
6     py::handle vector2i = py::detail::get_type_handle(typeid(Vector2i), false);
7     if (!vector2i) {
8         py::class_<Vector2i>(m, "Vector2i")
9             .def(py::init<int, int>())
10             .def("__init__", [](Vector2i &v, py::list l) {
11                 if (l.size() != 2)
12                     throw std::runtime_error("Incompatible list size!");
13                 new (&v) Vector2i(
14                     l[0].cast<int>(),
15                     l[1].cast<int>()
16                 );
17             })
18             .def("__init__", [](Vector2i &v, py::tuple t) {
19                 if (t.size() != 2)
20                     throw std::runtime_error("Incompatible tuple size!");
21                 new (&v) Vector2i(
22                     t[0].cast<int>(),
23                     t[1].cast<int>()
24                 );
25             })
26             .def_property("x", [](const Vector2i &v) { return v.x(); }, [](Vector2i &v, int x) { v.x() = x; })
27             .def_property("y", [](const Vector2i &v) { return v.y(); }, [](Vector2i &v, int y) { v.y() = y; })
28             .def("__getitem__", [](const Vector2i &m, size_t i) {
29                 if (i >= (size_t) m.size())
30                     throw py::index_error();
31                 return m[i];
32              })
33             .def("__setitem__", [](Vector2i &m, size_t i, int v) {
34                 if (i >= (size_t) m.size())
35                     throw py::index_error();
36                 m[i] = v;
37              });
38 
39         py::implicitly_convertible<py::list, Vector2i>();
40         py::implicitly_convertible<py::tuple, Vector2i>();
41     } else {
42         /* Don't create a new type if some other library has already
43            exposed (potentially much fancier) Eigen Python bindings */
44         m.attr("Vector2i") = vector2i;
45     }
46 
47     py::handle vector2f = py::detail::get_type_handle(typeid(Vector2f), false);
48     if (!vector2f) {
49         py::class_<Vector2f>(m, "Vector2f")
50             .def(py::init<float, float>())
51             .def("__init__", [](Vector2f &v, py::list l) {
52                 if (l.size() != 2)
53                     throw std::runtime_error("Incompatible list size!");
54                 new (&v) Vector2i(
55                     l[0].cast<float>(),
56                     l[1].cast<float>()
57                 );
58             })
59             .def("__init__", [](Vector2f &v, py::tuple t) {
60                 if (t.size() != 2)
61                     throw std::runtime_error("Incompatible tuple size!");
62                 new (&v) Vector2i(
63                     t[0].cast<float>(),
64                     t[1].cast<float>()
65                 );
66             })
67             .def_property("x", [](const Vector2f &v) { return v.x(); }, [](Vector2f &v, float x) { v.x() = x; })
68             .def_property("y", [](const Vector2f &v) { return v.y(); }, [](Vector2f &v, float y) { v.y() = y; })
69             .def("__getitem__", [](const Vector2f &m, size_t i) {
70                 if (i >= (size_t) m.size())
71                     throw py::index_error();
72                 return m[i];
73              })
74             .def("__setitem__", [](Vector2f &m, size_t i, float v) {
75                 if (i >= (size_t) m.size())
76                     throw py::index_error();
77                 m[i] = v;
78              });
79         py::implicitly_convertible<py::list, Vector2f>();
80         py::implicitly_convertible<py::tuple, Vector2f>();
81     } else {
82         /* Don't create a new type if some other library has already
83            exposed (potentially much fancier) Eigen Python bindings */
84         m.attr("Vector2f") = vector2f;
85     }
86 
87     py::handle vectorXf = py::detail::get_type_handle(typeid(VectorXf), false);
88     if (!vectorXf) {
89         py::class_<VectorXf>(m, "VectorXf")
90             .def(py::init<>())
91             .def(py::init<int>())
92             .def("resize", [](VectorXf &v, int i) { v.resize(i); })
93             .def("__init__", [](VectorXf &v, const std::vector<float> &v2) {
94                 new (&v) VectorXf(v2.size());
95                 memcpy(v.data(), &v2[0], sizeof(float) * v2.size());
96             })
97             .def("__init__", [](VectorXf &v, py::buffer b) {
98                 py::buffer_info info = b.request();
99                 if (info.format != py::format_descriptor<float>::value) {
100                     throw std::runtime_error("Incompatible buffer format!");
101                 } else if (info.ndim == 1 && info.strides[0] == sizeof(float)) {
102                     new (&v) VectorXf(info.shape[0]);
103                     memcpy(v.data(), info.ptr, sizeof(float) * info.shape[0]);
104                 } else if (info.ndim == 2 && ((info.shape[0] == 1 && info.strides[0] == sizeof(float))
105                                            || (info.shape[1] == 1 && info.strides[1] == sizeof(float)))) {
106                     new (&v) VectorXf(info.shape[0] * info.shape[1]);
107                     memcpy(v.data(), info.ptr, sizeof(float) * info.shape[0] * info.shape[1]);
108                 } else {
109                     throw std::runtime_error("Incompatible buffer dimension!");
110                 }
111             })
112             .def("size", [](const VectorXf &v) { return v.size(); })
113             .def("__repr__", [](const VectorXf &v) {
114                 std::ostringstream oss;
115                 oss << v.transpose();
116                 return oss.str();
117             })
118             .def("__getitem__", [](const VectorXf &m, size_t i) {
119                 if (i >= (size_t) m.size())
120                     throw py::index_error();
121                 return m[i];
122              })
123             .def("__setitem__", [](VectorXf &m, size_t i, float v) {
124                 if (i >= (size_t) m.size())
125                     throw py::index_error();
126                 m[i] = v;
127              })
128 
129             /* Buffer access for interacting with NumPy */
130             .def_buffer([](VectorXf &m) -> py::buffer_info {
131                 return py::buffer_info(
132                     m.data(),               /* Pointer to buffer */
133                     sizeof(float),          /* Size of one scalar */
134                     /* Python struct-style format descriptor */
135                     py::format_descriptor<float>::value,
136                     1,                      /* Number of dimensions */
137                     { (size_t) m.size() },  /* Buffer dimensions */
138                     { sizeof(float) }       /* Strides (in bytes) for each index */
139                 );
140              });
141         py::implicitly_convertible<std::vector<float>, VectorXf>();
142     } else {
143         /* Don't create a new type if some other library has already
144            exposed (potentially much fancier) Eigen Python bindings */
145         m.attr("VectorXf") = vectorXf;
146     }
147 
148     py::class_<Color>(m, "Color", D(Color))
149         .def(py::init<float, float, float, float>(), D(Color, Color, 7))
150         .def(py::init<float, float>(), D(Color, Color, 5))
151         .def("contrastingColor", &Color::contrastingColor, D(Color, contrastingColor))
152         .def_property("r",
153             [](const Color &c) { return c.r(); },
154             [](Color &c, float v) { c.r() = v; },
155             D(Color, r))
156         .def_property("g",
157             [](const Color &c) { return c.g(); },
158             [](Color &c, float v) { c.g() = v; },
159             D(Color, g))
160         .def_property("b",
161             [](const Color &c) { return c.b(); },
162             [](Color &c, float v) { c.b() = v; },
163             D(Color, b));
164 }
165 #endif
166