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