3
// classes dealing with exposing actual types, with many switches inside depending on template arguments
5
// methods common for vectors and matrices
6
template<typename MatrixBaseT>
7
class MatrixBaseVisitor: public py::def_visitor<MatrixBaseVisitor<MatrixBaseT> >{
8
typedef typename MatrixBaseT::Scalar Scalar;
10
template<class PyClass>
11
void visit(PyClass& cl) const {
13
.def(py::init<MatrixBaseT>(py::arg("other")))
14
.def("__neg__",&MatrixBaseVisitor::__neg__)
15
.def("__add__",&MatrixBaseVisitor::__add__).def("__iadd__",&MatrixBaseVisitor::__iadd__)
16
.def("__sub__",&MatrixBaseVisitor::__sub__).def("__isub__",&MatrixBaseVisitor::__isub__)
17
.def("__eq__",&MatrixBaseVisitor::__eq__).def("__ne__",&MatrixBaseVisitor::__ne__)
18
.def("__mul__",&MatrixBaseVisitor::__mul__scalar<long>)
19
.def("__imul__",&MatrixBaseVisitor::__imul__scalar<long>)
20
.def("__rmul__",&MatrixBaseVisitor::__rmul__scalar<long>)
21
.def("rows",&MatrixBaseT::rows,"Number of rows.")
22
.def("cols",&MatrixBaseT::cols,"Number of columns.")
24
visit_if_float<Scalar,PyClass>(cl);
25
visit_fixed_or_dynamic<MatrixBaseT,PyClass>(cl);
29
.def("sum",&MatrixBaseT::sum,"Sum of all elements.")
30
.def("maxAbsCoeff",&MatrixBaseVisitor::maxAbsCoeff,"Maximum absolute value over all elements.")
34
template<class PyClass> static string name(PyClass& cl){ return py::extract<string>(cl.attr("__name__"))(); }
35
// for dynamic matrices/vectors
36
template<typename MatrixBaseT2, class PyClass> static void visit_fixed_or_dynamic(PyClass& cl, typename boost::enable_if_c<MatrixBaseT2::RowsAtCompileTime==Eigen::Dynamic>::type* dummy = 0){
37
//std::cerr<<"MatrixBaseVisitor: dynamic MatrixBaseT for "<<name(cl)<<std::endl;
40
// for static matrices/vectors
41
template<typename MatrixBaseT2, class PyClass> static void visit_fixed_or_dynamic(PyClass& cl, typename boost::disable_if_c<MatrixBaseT2::RowsAtCompileTime==Eigen::Dynamic>::type* dummy = 0){
42
//std::cerr<<"MatrixBaseVisitor: fixed MatrixBaseT for "<<name(cl)<<std::endl;
44
.add_static_property("Ones",&MatrixBaseVisitor::Ones)
45
.add_static_property("Zero",&MatrixBaseVisitor::Zero)
46
.def("Random",&MatrixBaseVisitor::Random,"Return an object where all elements are randomly set to values between 0 and 1.").staticmethod("Random")
47
.add_static_property("Identity",&MatrixBaseVisitor::Identity)
50
template<typename Scalar, class PyClass> static void visit_if_float(PyClass& cl, typename boost::enable_if<boost::is_integral<Scalar> >::type* dummy = 0){ /* do nothing */ }
51
template<typename Scalar, class PyClass> static void visit_if_float(PyClass& cl, typename boost::disable_if<boost::is_integral<Scalar> >::type* dummy = 0){
52
// operations with other scalars (Scalar is the floating type, long is the python integer type)
54
.def("__mul__",&MatrixBaseVisitor::__mul__scalar<Scalar>)
55
.def("__rmul__",&MatrixBaseVisitor::__rmul__scalar<Scalar>)
56
.def("__imul__",&MatrixBaseVisitor::__imul__scalar<Scalar>)
57
.def("__div__",&MatrixBaseVisitor::__div__scalar<long>)
58
.def("__idiv__",&MatrixBaseVisitor::__idiv__scalar<long>)
59
.def("__div__",&MatrixBaseVisitor::__div__scalar<Scalar>)
60
.def("__idiv__",&MatrixBaseVisitor::__idiv__scalar<Scalar>)
62
.def("norm",&MatrixBaseT::norm,"Euclidean norm.")
63
.def("__abs__",&MatrixBaseT::norm)
64
.def("squaredNorm",&MatrixBaseT::squaredNorm,"Square of the Euclidean norm.")
65
.def("normalize",&MatrixBaseT::normalize,"Normalize this object in-place.")
66
.def("normalized",&MatrixBaseT::normalized,"Return normalized copy of this object")
67
.def("pruned",&MatrixBaseVisitor::pruned,py::arg("absTol")=1e-6,"Zero all elements which are greater than *absTol*. Negative zeros are not pruned.")
70
// for fixed-size matrices/vectors only
71
static Scalar maxAbsCoeff(const MatrixBaseT& m){ return m.array().abs().maxCoeff(); }
72
static MatrixBaseT Ones(){ return MatrixBaseT::Ones(); }
73
static MatrixBaseT Zero(){ return MatrixBaseT::Zero(); }
74
static MatrixBaseT Random(){ return MatrixBaseT::Random(); }
75
static MatrixBaseT Identity(){ return MatrixBaseT::Identity(); }
77
static bool __eq__(const MatrixBaseT& a, const MatrixBaseT& b){
78
if(a.rows()!=b.rows() || a.cols()!=b.cols()) return false;
79
return a.cwiseEqual(b).all();
81
static bool __ne__(const MatrixBaseT& a, const MatrixBaseT& b){ return !__eq__(a,b); }
82
static MatrixBaseT __neg__(const MatrixBaseT& a){ return -a; };
83
static MatrixBaseT __add__(const MatrixBaseT& a, const MatrixBaseT& b){ return a+b; }
84
static MatrixBaseT __sub__(const MatrixBaseT& a, const MatrixBaseT& b){ return a-b; }
85
static MatrixBaseT __iadd__(MatrixBaseT& a, const MatrixBaseT& b){ a+=b; return a; };
86
static MatrixBaseT __isub__(MatrixBaseT& a, const MatrixBaseT& b){ a-=b; return a; };
88
template<typename Scalar2> static MatrixBaseT __mul__scalar(const MatrixBaseT& a, const Scalar2& scalar){ return a*scalar; }
89
template<typename Scalar2> static MatrixBaseT __imul__scalar(MatrixBaseT& a, const Scalar2& scalar){ a*=scalar; return a; }
90
template<typename Scalar2> static MatrixBaseT __rmul__scalar(const MatrixBaseT& a, const Scalar2& scalar){ return a*scalar; }
91
template<typename Scalar2> static MatrixBaseT __div__scalar(const MatrixBaseT& a, const Scalar2& scalar){ return a/scalar; }
92
template<typename Scalar2> static MatrixBaseT __idiv__scalar(MatrixBaseT& a, const Scalar2& scalar){ a/=scalar; return a; }
94
// we want to keep -0 (rather than replacing it by 0), but that does not work for complex numbers
96
template<typename Scalar> static bool prune_element(const Scalar& num, double absTol, typename boost::disable_if<boost::is_complex<Scalar> >::type* dummy=0){ return std::abs(num)<=absTol || num!=-0; }
97
template<typename Scalar> static bool prune_element(const Scalar& num, double absTol, typename boost::enable_if<boost::is_complex<Scalar> >::type* dummy=0){ return std::abs(num)<=absTol; }
99
static MatrixBaseT pruned(const MatrixBaseT& a, double absTol=1e-6){ // typename MatrixBaseT::Scalar absTol=1e-6){
100
MatrixBaseT ret(MatrixBaseT::Zero(a.rows(),a.cols()));
101
for(Index c=0;c<a.cols();c++){ for(Index r=0;r<a.rows();r++){ if(!prune_element(a(c,r),absTol)) ret(c,r)=a(c,r); } }
106
template<typename VectorT>
107
class VectorVisitor: public py::def_visitor<VectorVisitor<VectorT> >{
108
friend class def_visitor_access;
109
typedef typename VectorT::Scalar Scalar;
110
typedef Eigen::Matrix<Scalar,VectorT::RowsAtCompileTime,VectorT::RowsAtCompileTime> CompatMatrixT;
111
typedef Eigen::Matrix<Scalar,2,1> CompatVec2;
112
typedef Eigen::Matrix<Scalar,3,1> CompatVec3;
113
typedef Eigen::Matrix<Scalar,6,1> CompatVec6;
114
typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1> CompatVecX;
115
enum{Dim=VectorT::RowsAtCompileTime};
117
template<class PyClass>
118
void visit(PyClass& cl) const {
119
MatrixBaseVisitor<VectorT>().visit(cl);
121
.def_pickle(VectorPickle())
122
.def("__setitem__",&VectorVisitor::set_item)
123
.def("__getitem__",&VectorVisitor::get_item)
124
.def("__str__",&VectorVisitor::__str__).def("__repr__",&VectorVisitor::__str__)
125
.def("dot",&VectorVisitor::dot,py::arg("other"),"Dot product with *other*.")
126
.def("outer",&VectorVisitor::outer,py::arg("other"),"Outer product with *other*.")
127
.def("asDiagonal",&VectorVisitor::asDiagonal,"Return diagonal matrix with this vector on the diagonal.")
130
visit_fixed_or_dynamic<VectorT,PyClass>(cl);
132
visit_special_sizes<VectorT,PyClass>(cl);
135
// for dynamic vectors
136
template<typename VectorT2, class PyClass> static void visit_fixed_or_dynamic(PyClass& cl, typename boost::enable_if_c<VectorT2::RowsAtCompileTime==Eigen::Dynamic>::type* dummy = 0){
137
//std::cerr<<"VectorVisitor: dynamic vector for "<<name()<<std::endl;
139
.def("__len__",&VectorVisitor::dyn__len__)
140
.def("resize",&VectorVisitor::resize)
141
.def("Unit",&VectorVisitor::dyn_Unit).staticmethod("Unit")
142
.def("Ones",&VectorVisitor::dyn_Ones).staticmethod("Ones")
143
.def("Zero",&VectorVisitor::dyn_Zero).staticmethod("Zero")
144
.def("Random",&VectorVisitor::dyn_Random,py::arg("len"),"Return vector of given length with all elements set to values between 0 and 1 randomly.").staticmethod("Random")
147
// for fixed-size vectors
148
template<typename VectorT2, class PyClass> static void visit_fixed_or_dynamic(PyClass& cl, typename boost::disable_if_c<VectorT2::RowsAtCompileTime==Eigen::Dynamic>::type* dummy = 0){
149
//std::cerr<<"VectorVisitor: fixed vector for "<<name()<<std::endl;
150
cl.def("__len__",&VectorVisitor::__len__).staticmethod("__len__")
151
.def("Unit",&VectorVisitor::Unit).staticmethod("Unit")
155
// handle specific sizes of vectors separately
158
template<typename VectorT2, class PyClass> static void visit_special_sizes(PyClass& cl, typename boost::enable_if_c<VectorT2::RowsAtCompileTime==2>::type* dummy=0){
160
.def(py::init<typename VectorT2::Scalar,typename VectorT2::Scalar>((py::arg("x"),py::arg("y"))))
161
.add_static_property("UnitX",&VectorVisitor::Vec2_UnitX)
162
.add_static_property("UnitY",&VectorVisitor::Vec2_UnitY)
165
static CompatVec2 Vec2_UnitX(){ return CompatVec2::UnitX(); }
166
static CompatVec2 Vec2_UnitY(){ return CompatVec2::UnitY(); }
169
template<typename VectorT2, class PyClass> static void visit_special_sizes(PyClass& cl, typename boost::enable_if_c<VectorT2::RowsAtCompileTime==3>::type* dummy=0){
171
.def(py::init<typename VectorT2::Scalar,typename VectorT2::Scalar,typename VectorT2::Scalar>((py::arg("x"),py::arg("y"),py::arg("z"))))
172
.def("cross",&VectorVisitor::cross) // cross-product only meaningful for 3-sized vectors
173
.add_static_property("UnitX",&VectorVisitor::Vec3_UnitX)
174
.add_static_property("UnitY",&VectorVisitor::Vec3_UnitY)
175
.add_static_property("UnitZ",&VectorVisitor::Vec3_UnitZ)
177
.def("xy",&VectorVisitor::Vec3_xy).def("yx",&VectorVisitor::Vec3_yx).def("xz",&VectorVisitor::Vec3_xz).def("zx",&VectorVisitor::Vec3_zx).def("yz",&VectorVisitor::Vec3_yz).def("zy",&VectorVisitor::Vec3_zy)
180
static CompatVec3 cross(const CompatVec3& self, const CompatVec3& other){ return self.cross(other); }
181
static CompatVec3 Vec3_UnitX(){ return CompatVec3::UnitX(); }
182
static CompatVec3 Vec3_UnitY(){ return CompatVec3::UnitY(); }
183
static CompatVec3 Vec3_UnitZ(){ return CompatVec3::UnitZ(); }
185
static CompatVec2 Vec3_xy(const CompatVec3& v){ return CompatVec2(v[0],v[1]); }
186
static CompatVec2 Vec3_yx(const CompatVec3& v){ return CompatVec2(v[1],v[0]); }
187
static CompatVec2 Vec3_xz(const CompatVec3& v){ return CompatVec2(v[0],v[2]); }
188
static CompatVec2 Vec3_zx(const CompatVec3& v){ return CompatVec2(v[2],v[0]); }
189
static CompatVec2 Vec3_yz(const CompatVec3& v){ return CompatVec2(v[1],v[2]); }
190
static CompatVec2 Vec3_zy(const CompatVec3& v){ return CompatVec2(v[2],v[1]); }
193
template<typename VectorT2, class PyClass> static void visit_special_sizes(PyClass& cl, typename boost::enable_if_c<VectorT2::RowsAtCompileTime==6>::type* dummy=0){
195
.def("__init__",py::make_constructor(&VectorVisitor::Vec6_fromElements,py::default_call_policies(),(py::arg("v0"),py::arg("v1"),py::arg("v2"),py::arg("v3"),py::arg("v4"),py::arg("v5"))))
196
.def("__init__",py::make_constructor(&VectorVisitor::Vec6_fromHeadTail,py::default_call_policies(),(py::arg("head"),py::arg("tail"))))
197
.def("head",&VectorVisitor::Vec6_head).def("tail",&VectorVisitor::Vec6_tail)
200
// only used with dim==6
201
static CompatVec6* Vec6_fromElements(const Scalar& v0, const Scalar& v1, const Scalar& v2, const Scalar& v3, const Scalar& v4, const Scalar& v5){ CompatVec6* v(new CompatVec6); (*v)<<v0,v1,v2,v3,v4,v5; return v; }
202
static CompatVec6* Vec6_fromHeadTail(const CompatVec3& head, const CompatVec3& tail){ CompatVec6* v(new CompatVec6); (*v)<<head,tail; return v; }
203
static CompatVec3 Vec6_head(const CompatVec6& v){ return v.template head<3>(); }
204
static CompatVec3 Vec6_tail(const CompatVec6& v){ return v.template tail<3>(); }
206
// ctor for dynamic vectors
207
template<typename VectorT2, class PyClass> static void visit_special_sizes(PyClass& cl, typename boost::enable_if_c<VectorT2::RowsAtCompileTime==Eigen::Dynamic>::type* dummy=0){
209
.def("__init__",py::make_constructor(&VecX_fromList,py::default_call_policies(),(py::arg("vv"))))
212
static CompatVecX* VecX_fromList(const std::vector<Scalar>& ii){ CompatVecX* v(new CompatVecX(ii.size())); for(size_t i=0; i<ii.size(); i++) (*v)[i]=ii[i]; return v; }
215
static VectorT dyn_Ones(Index size){ return VectorT::Ones(size); }
216
static VectorT dyn_Zero(Index size){ return VectorT::Zero(size); }
217
static VectorT dyn_Random(Index size){ return VectorT::Random(size); }
218
static VectorT Unit(Index ix){ IDX_CHECK(ix,(Index)Dim); return VectorT::Unit(ix); }
219
static VectorT dyn_Unit(Index size,Index ix){ IDX_CHECK(ix,size); return VectorT::Unit(size,ix); }
220
static bool dyn(){ return Dim==Eigen::Dynamic; }
221
static Index __len__(){ assert(!dyn()); return Dim; }
222
static Index dyn__len__(const VectorT& self){ return self.size(); }
223
static void resize(VectorT& self, Index size){ self.resize(size); }
224
static Scalar dot(const VectorT& self, const VectorT& other){ return self.dot(other); }
225
static CompatMatrixT outer(const VectorT& self, const VectorT& other){ return self*other.transpose(); }
226
static CompatMatrixT asDiagonal(const VectorT& self){ return self.asDiagonal(); }
227
static Scalar get_item(const VectorT& self, Index ix){ IDX_CHECK(ix,dyn()?(Index)self.size():(Index)Dim); return self[ix]; }
228
static void set_item(VectorT& self, Index ix, Scalar value){ IDX_CHECK(ix,dyn()?(Index)self.size():(Index)Dim); self[ix]=value; }
229
struct VectorPickle: py::pickle_suite{
230
static py::tuple getinitargs(const VectorT& x){
231
// if this fails, add supported size to the switch below
232
BOOST_STATIC_ASSERT(Dim==2 || Dim==3 || Dim==6 || Dim==Eigen::Dynamic);
234
case 2: return py::make_tuple(x[0],x[1]);
235
case 3: return py::make_tuple(x[0],x[1],x[2]);
236
case 6: return py::make_tuple(x[0],x[1],x[2],x[3],x[4],x[5]);
237
default: return py::make_tuple(py::list(x));
242
static string __str__(const py::object& obj){
243
std::ostringstream oss;
244
const VectorT& self=py::extract<VectorT>(obj)();
245
bool list=(Dim==Eigen::Dynamic && self.size()>0);
246
oss<<object_class_name(obj)<<(list?"([":"(");
247
Vector_data_stream(self,oss);
248
oss<<(list?"])":")");
252
// not sure why this must be templated now?!
253
template<typename VectorType>
254
static void Vector_data_stream(const VectorType& self, std::ostringstream& oss, int pad=0){
255
for(Index i=0; i<self.size(); i++) oss<<(i==0?"":(((i%3)!=0 || pad>0)?",":", "))<<num_to_string(self.row(i/self.cols())[i%self.cols()],/*pad*/pad);
259
template<typename MatrixT>
260
class MatrixVisitor: public py::def_visitor<MatrixVisitor<MatrixT> >{
261
friend class def_visitor_access;
262
typedef typename MatrixT::Scalar Scalar;
263
typedef typename Eigen::Matrix<Scalar,MatrixT::RowsAtCompileTime,1> CompatVectorT;
264
typedef Eigen::Matrix<Scalar,3,3> CompatMat3;
265
typedef Eigen::Matrix<Scalar,3,1> CompatVec3;
266
typedef Eigen::Matrix<Scalar,6,6> CompatMat6;
267
typedef Eigen::Matrix<Scalar,6,1> CompatVec6;
268
typedef Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> CompatMatX;
269
typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1> CompatVecX;
270
enum{Dim=MatrixT::RowsAtCompileTime};
272
template<class PyClass>
273
void visit(PyClass& cl) const {
274
MatrixBaseVisitor<MatrixT>().visit(cl);
276
.def_pickle(MatrixPickle())
277
.def("__init__",py::make_constructor(&MatrixVisitor::fromDiagonal,py::default_call_policies(),(py::arg("diag"))))
279
.def("determinant",&MatrixT::determinant,"Return matrix determinant.")
280
.def("trace",&MatrixT::trace,"Return sum of diagonal elements.")
281
.def("transpose",&MatrixVisitor::transpose,"Return transposed matrix.")
282
.def("diagonal",&MatrixVisitor::diagonal,"Return diagonal as vector.")
283
.def("row",&MatrixVisitor::row,py::arg("row"),"Return row as vector.")
284
.def("col",&MatrixVisitor::col,py::arg("col"),"Return column as vector.")
285
// matrix*matrix product
286
.def("__mul__",&MatrixVisitor::__mul__).def("__imul__",&MatrixVisitor::__imul__)
287
// matrix*vector product
288
.def("__mul__",&MatrixVisitor::__mul__vec).def("__rmul__",&MatrixVisitor::__mul__vec)
289
.def("__setitem__",&MatrixVisitor::set_row).def("__getitem__",&MatrixVisitor::get_row)
290
.def("__setitem__",&MatrixVisitor::set_item).def("__getitem__",&MatrixVisitor::get_item)
291
.def("__str__",&MatrixVisitor::__str__).def("__repr__",&MatrixVisitor::__str__)
293
visit_if_float<Scalar,PyClass>(cl);
294
visit_fixed_or_dynamic<MatrixT,PyClass>(cl);
295
visit_special_sizes<MatrixT,PyClass>(cl);
297
//std::cerr<<"MatrixVisitor: "<<name()<<std::endl;
301
// for dynamic matrices
302
template<typename MatrixT2, class PyClass> static void visit_fixed_or_dynamic(PyClass& cl, typename boost::enable_if_c<MatrixT2::RowsAtCompileTime==Eigen::Dynamic>::type* dummy = 0){
304
.def("__len__",&MatrixVisitor::dyn__len__)
305
.def("resize",&MatrixVisitor::resize,"Change size of the matrix, keep values of elements which exist in the new matrix",(py::arg("rows"),py::arg("cols")))
306
.def("Ones",&MatrixVisitor::dyn_Ones,(py::arg("rows"),py::arg("cols")),"Create matrix of given dimensions where all elements are set to 1.").staticmethod("Ones")
307
.def("Zero",&MatrixVisitor::dyn_Zero,(py::arg("rows"),py::arg("cols")),"Create zero matrix of given dimensions").staticmethod("Zero")
308
.def("Random",&MatrixVisitor::dyn_Random,(py::arg("rows"),py::arg("cols")),"Create matrix with given dimensions where all elements are set to number between 0 and 1 (uniformly-distributed).").staticmethod("Random")
309
.def("Identity",&MatrixVisitor::dyn_Identity,(py::arg("rank")),"Create identity matrix with given rank (square).").staticmethod("Identity")
312
// for fixed-size matrices
313
template<typename MatrixT2, class PyClass> static void visit_fixed_or_dynamic(PyClass& cl, typename boost::disable_if_c<MatrixT2::RowsAtCompileTime==Eigen::Dynamic>::type* dummy = 0){
314
cl.def("__len__",&MatrixVisitor::__len__).staticmethod("__len__")
318
template<typename Scalar, class PyClass> static void visit_if_float(PyClass& cl, typename boost::enable_if<boost::is_integral<Scalar> >::type* dummy = 0){ /* do nothing */ }
319
template<typename Scalar, class PyClass> static void visit_if_float(PyClass& cl, typename boost::disable_if<boost::is_integral<Scalar> >::type* dummy = 0){
321
// matrix-matrix division?!
322
//.def("__div__",&MatrixBaseVisitor::__div__).def("__idiv__",&MatrixBaseVisitor::__idiv__)
323
.def("inverse",&MatrixVisitor::inverse,"Return inverted matrix.");
324
// decompositions are only meaningful on non-complex numbers
325
visit_if_decompositions_meaningful<Scalar,PyClass>(cl);
327
// for complex numbers, do nothing
328
template<typename Scalar, class PyClass> static void visit_if_decompositions_meaningful(PyClass& cl, typename boost::enable_if<boost::is_complex<Scalar> >::type* dummy = 0){ /* do nothing */ }
329
// for non-complex numbers, define decompositions
330
template<typename Scalar, class PyClass> static void visit_if_decompositions_meaningful(PyClass& cl, typename boost::disable_if<boost::is_complex<Scalar> >::type* dummy = 0){
332
.def("jacobiSVD",&MatrixVisitor::jacobiSVD,"Compute SVD decomposition of square matrix, retuns (U,S,V) such that self=U*S*V.transpose()")
333
.def("svd",&MatrixVisitor::jacobiSVD,"Alias for :obj:`jacobiSVD`.")
334
.def("computeUnitaryPositive",&MatrixVisitor::computeUnitaryPositive,"Compute polar decomposition (unitary matrix U and positive semi-definite symmetric matrix P such that self=U*P).")
335
.def("polarDecomposition",&MatrixVisitor::computeUnitaryPositive,"Alias for :obj:`computeUnitaryPositive`.")
336
.def("selfAdjointEigenDecomposition",&MatrixVisitor::selfAdjointEigenDecomposition,"Compute eigen (spectral) decomposition of symmetric matrix, returns (eigVecs,eigVals). eigVecs is orthogonal Matrix3 with columns ar normalized eigenvectors, eigVals is Vector3 with corresponding eigenvalues. self=eigVecs*diag(eigVals)*eigVecs.transpose().")
337
.def("spectralDecomposition",&MatrixVisitor::selfAdjointEigenDecomposition,"Alias for :obj:`selfAdjointEigenDecomposition`.")
341
// handle specific matrix sizes
343
template<typename MatT2, class PyClass> static void visit_special_sizes(PyClass& cl, typename boost::enable_if_c<MatT2::RowsAtCompileTime==3>::type* dummy=0){
345
.def("__init__",py::make_constructor(&MatrixVisitor::Mat3_fromElements,py::default_call_policies(),(py::arg("m00"),py::arg("m01"),py::arg("m02"),py::arg("m10"),py::arg("m11"),py::arg("m12"),py::arg("m20"),py::arg("m21"),py::arg("m22"))))
346
.def("__init__",py::make_constructor(&MatrixVisitor::Mat3_fromRows,py::default_call_policies(),(py::arg("r0"),py::arg("r1"),py::arg("r2"),py::arg("cols")=false)))
349
static CompatMat3* Mat3_fromElements(const Scalar& m00, const Scalar& m01, const Scalar& m02, const Scalar& m10, const Scalar& m11, const Scalar& m12, const Scalar& m20, const Scalar& m21, const Scalar& m22){ CompatMat3* m(new CompatMat3); (*m)<<m00,m01,m02,m10,m11,m12,m20,m21,m22; return m; }
350
static CompatMat3* Mat3_fromRows(const CompatVec3& l0, const CompatVec3& l1, const CompatVec3& l2, bool cols=false){ CompatMat3* m(new CompatMat3); if(cols){m->col(0)=l0; m->col(1)=l1; m->col(2)=l2; } else {m->row(0)=l0; m->row(1)=l1; m->row(2)=l2;} return m; }
353
template<typename MatT2, class PyClass> static void visit_special_sizes(PyClass& cl, typename boost::enable_if_c<MatT2::RowsAtCompileTime==6>::type* dummy=0){
355
.def("__init__",py::make_constructor(&MatrixVisitor::Mat6_fromBlocks,py::default_call_policies(),(py::arg("ul"),py::arg("ur"),py::arg("ll"),py::arg("lr"))))
356
.def("__init__",py::make_constructor(&MatrixVisitor::Mat6_fromRows,py::default_call_policies(),(py::arg("l0"),py::arg("l1"),py::arg("l2"),py::arg("l3"),py::arg("l4"),py::arg("l5"),py::arg("cols")=false)))
358
.def("ul",&MatrixVisitor::Mat6_ul,"Return upper-left 3x3 block")
359
.def("ur",&MatrixVisitor::Mat6_ur,"Return upper-right 3x3 block")
360
.def("ll",&MatrixVisitor::Mat6_ll,"Return lower-left 3x3 block")
361
.def("lr",&MatrixVisitor::Mat6_lr,"Return lower-right 3x3 block")
364
static CompatMat6* Mat6_fromBlocks(const CompatMat3& ul, const CompatMat3& ur, const CompatMat3& ll, const CompatMat3& lr){ CompatMat6* m(new CompatMat6); (*m)<<ul,ur,ll,lr; return m; }
365
static CompatMat6* Mat6_fromRows(const CompatVec6& l0, const CompatVec6& l1, const CompatVec6& l2, const CompatVec6& l3, const CompatVec6& l4, const CompatVec6& l5, bool cols=false){ CompatMat6* m(new CompatMat6); if(cols){ m->col(0)=l0; m->col(1)=l1; m->col(2)=l2; m->col(3)=l3; m->col(4)=l4; m->col(5)=l5; } else { m->row(0)=l0; m->row(1)=l1; m->row(2)=l2; m->row(3)=l3; m->row(4)=l4; m->row(5)=l5; } return m; }
366
// see http://stackoverflow.com/questions/20870648/error-in-seemingly-correct-template-code-whats-wrong#20870661
367
// on why the template keyword is needed after the m.
368
static CompatMat3 Mat6_ul(const CompatMat6& m){ return m.template topLeftCorner<3,3>(); }
369
static CompatMat3 Mat6_ur(const CompatMat6& m){ return m.template topRightCorner<3,3>(); }
370
static CompatMat3 Mat6_ll(const CompatMat6& m){ return m.template bottomLeftCorner<3,3>(); }
371
static CompatMat3 Mat6_lr(const CompatMat6& m){ return m.template bottomRightCorner<3,3>(); }
374
template<typename MatT2, class PyClass> static void visit_special_sizes(PyClass& cl, typename boost::enable_if_c<MatT2::RowsAtCompileTime==Eigen::Dynamic>::type* dummy=0){
376
.def("__init__",py::make_constructor(&MatrixVisitor::MatX_fromRows,py::default_call_policies(),(py::arg("r0")=CompatVecX(),py::arg("r1")=CompatVecX(),py::arg("r2")=CompatVecX(),py::arg("r3")=CompatVecX(),py::arg("r4")=CompatVecX(),py::arg("r5")=CompatVecX(),py::arg("r6")=CompatVecX(),py::arg("r7")=CompatVecX(),py::arg("r8")=CompatVecX(),py::arg("r9")=CompatVecX(),py::arg("cols")=false)))
377
.def("__init__",py::make_constructor(&MatrixVisitor::MatX_fromRowSeq,py::default_call_policies(),(py::arg("rows"),py::arg("cols")=false)))
381
static CompatMatX* MatX_fromRows(const CompatVecX& r0, const CompatVecX& r1, const CompatVecX& r2, const CompatVecX& r3, const CompatVecX& r4, const CompatVecX& r5, const CompatVecX& r6, const CompatVecX& r7, const CompatVecX& r8, const CompatVecX& r9, bool setCols){
382
/* check vector dimensions */ CompatVecX rr[]={r0,r1,r2,r3,r4,r5,r6,r7,r8,r9};
383
int cols=-1, rows=-1;
384
for(int i=0; i<10; i++){
385
if(rows<0 && rr[i].size()==0) rows=i;
386
if(rows>=0 && rr[i].size()>0) throw std::invalid_argument("Matrix6r: non-empty rows not allowed after first empty row, which marks end of the matrix.");
388
cols=(rows>0?rr[0].size():0);
389
for(int i=1; i<rows; i++) if(rr[i].size()!=cols) throw std::invalid_argument(("Matrix6: all non-empty rows must have the same length (0th row has "+lexical_cast<string>(rr[0].size())+" items, "+lexical_cast<string>(i)+"th row has "+lexical_cast<string>(rr[i].size())+" items)").c_str());
391
m=setCols?new CompatMatX(cols,rows):new CompatMatX(rows,cols);
392
for(int i=0; i<rows; i++){ if(setCols) m->col(i)=rr[i]; else m->row(i)=rr[i]; }
395
static CompatMatX* MatX_fromRowSeq(const std::vector<CompatVecX>& rr, bool setCols){
396
int rows=rr.size(),cols=rr.size()>0?rr[0].size():0;
397
for(int i=1; i<rows; i++) if(rr[i].size()!=cols) throw std::invalid_argument(("MatrixX: all rows must have the same length."));
399
m=setCols?new CompatMatX(cols,rows):new CompatMatX(rows,cols);
400
for(int i=0; i<rows; i++){ if(setCols) m->col(i)=rr[i]; else m->row(i)=rr[i]; }
405
static MatrixT dyn_Ones(Index rows, Index cols){ return MatrixT::Ones(rows,cols); }
406
static MatrixT dyn_Zero(Index rows, Index cols){ return MatrixT::Zero(rows,cols); }
407
static MatrixT dyn_Random(Index rows, Index cols){ return MatrixT::Random(rows,cols); }
408
static MatrixT dyn_Identity(Index rows, Index cols){ return MatrixT::Identity(rows,cols); }
409
static typename MatrixT::Index dyn__len__(MatrixT& a){ return a.rows(); }
410
static typename MatrixT::Index __len__(){ return MatrixT::RowsAtCompileTime; }
411
static MatrixT Identity(){ return MatrixT::Identity(); }
412
static MatrixT transpose(const MatrixT& m){ return m.transpose(); }
413
static CompatVectorT diagonal(const MatrixT& m){ return m.diagonal(); }
414
static MatrixT* fromDiagonal(const CompatVectorT& d){ MatrixT* m(new MatrixT); *m=d.asDiagonal(); return m; }
415
static void resize(MatrixT& self, Index rows, Index cols){ self.resize(rows,cols); }
416
static CompatVectorT get_row(const MatrixT& a, Index ix){ IDX_CHECK(ix,a.rows()); return a.row(ix); }
417
static void set_row(MatrixT& a, Index ix, const CompatVectorT& r){ IDX_CHECK(ix,a.rows()); a.row(ix)=r; }
418
static Scalar get_item(const MatrixT& a, py::tuple _idx){ Index idx[2]; Index mx[2]={a.rows(),a.cols()}; IDX2_CHECKED_TUPLE_INTS(_idx,mx,idx); return a(idx[0],idx[1]); }
419
static void set_item(MatrixT& a, py::tuple _idx, const Scalar& value){ Index idx[2]; Index mx[2]={a.rows(),a.cols()}; IDX2_CHECKED_TUPLE_INTS(_idx,mx,idx); a(idx[0],idx[1])=value; }
421
static MatrixT __imul__(MatrixT& a, const MatrixT& b){ a*=b; return a; };
422
static MatrixT __mul__(const MatrixT& a, const MatrixT& b){ return a*b; }
423
static CompatVectorT __mul__vec(const MatrixT& m, const CompatVectorT& v){ return m*v; }
424
// float matrices only
425
static MatrixT inverse(const MatrixT& m){ return m.inverse(); }
426
static MatrixT __div__(const MatrixT& a, const MatrixT& b){ return a/b; }
427
// static void __idiv__(MatrixT& a, const MatrixT& b){ a/=b; };
428
static CompatVectorT row(const MatrixT& m, Index ix){ IDX_CHECK(ix,m.rows()); return m.row(ix); }
429
static CompatVectorT col(const MatrixT& m, Index ix){ IDX_CHECK(ix,m.cols()); return m.col(ix); }
431
static void ensureSquare(const MatrixT& m){ if(m.rows()!=m.cols()) throw std::runtime_error("Matrix is not square."); }
432
static py::tuple jacobiSVD(const MatrixT& in) {
434
Eigen::JacobiSVD<MatrixT> svd(in, Eigen::ComputeThinU | Eigen::ComputeThinV);
435
return py::make_tuple(svd.matrixU(),svd.matrixV(),MatrixT(svd.singularValues().asDiagonal()));
437
// polar decomposition
438
static py::tuple computeUnitaryPositive(const MatrixT& in) {
440
Eigen::JacobiSVD<MatrixT> svd(in, Eigen::ComputeThinU | Eigen::ComputeThinV);
441
const MatrixT& u=svd.matrixU(); const MatrixT& v=svd.matrixV();
442
MatrixT s=svd.singularValues().asDiagonal();
443
return py::make_tuple(u*v.transpose(),v*s*v.transpose());
445
// eigen decomposition
446
static py::tuple selfAdjointEigenDecomposition(const MatrixT& in) {
448
Eigen::SelfAdjointEigenSolver<MatrixT> a(in);
449
return py::make_tuple(a.eigenvectors(),a.eigenvalues());
451
static bool dyn(){ return Dim==Eigen::Dynamic; }
452
static string __str__(const py::object& obj){
453
std::ostringstream oss;
454
const MatrixT& m=py::extract<MatrixT>(obj)();
455
oss<<object_class_name(obj)<<"(";
456
bool wrap=((dyn() && m.rows()>1) || (!dyn() && m.rows()>3));
457
// non-wrapping fixed-size: flat list of numbers, not rows as tuples (Matrix3)
459
VectorVisitor<CompatVectorT>::template Vector_data_stream<MatrixT>(m,oss,/*pad=*/0);
462
for(Index r=0; r<m.rows(); r++){
463
oss<<(wrap?"\t":"")<<"(";
464
VectorVisitor<CompatVectorT>::template Vector_data_stream<CompatVectorT>(m.row(r),oss,/*pad=*/(wrap?7:0));
465
oss<<")"<<(r<m.rows()-1?",":"")<<(wrap?"\n":"");
471
struct MatrixPickle: py::pickle_suite{
472
static py::tuple getinitargs(const MatrixT& x){
473
// if this fails, add supported size to the switch below
474
BOOST_STATIC_ASSERT(Dim==2 || Dim==3 || Dim==6 || Dim==Eigen::Dynamic);
476
case 2: return py::make_tuple(x(0,0),x(0,1),x(1,0),x(1,1));
477
case 3: return py::make_tuple(x(0,0),x(0,1),x(0,2),x(1,0),x(1,1),x(1,2),x(2,0),x(2,1),x(2,2));
478
case 6: return py::make_tuple(x.row(0),x.row(1),x.row(2),x.row(3),x.row(4),x.row(5));
479
// should return list of rows, which are VectorX
480
default: return py::make_tuple(py::list(x));
487
template<typename Box>
488
class AabbVisitor: public py::def_visitor<AabbVisitor<Box> >{
489
friend class def_visitor_access;
490
typedef typename Box::VectorType VectorType;
491
typedef typename Box::Scalar Scalar;
493
template <class PyClass>
494
void visit(PyClass& cl) const {
496
.def(py::init<Box>(py::arg("other")))
497
.def(py::init<VectorType,VectorType>((py::arg("min"),py::arg("max"))))
498
.def_pickle(BoxPickle())
499
.def("volume",&Box::volume)
500
.def("empty",&Box::isEmpty)
501
.def("center",&AabbVisitor::center)
502
.def("sizes",&AabbVisitor::sizes)
503
.def("contains",&AabbVisitor::containsPt)
504
.def("contains",&AabbVisitor::containsBox)
505
// for the "in" operator
506
.def("__contains__",&AabbVisitor::containsPt)
507
.def("__contains__",&AabbVisitor::containsBox)
508
.def("extend",&AabbVisitor::extendPt)
509
.def("extend",&AabbVisitor::extendBox)
510
.def("clamp",&AabbVisitor::clamp)
511
// return new objects
512
.def("intersection",&Box::intersection)
513
.def("merged",&Box::merged)
514
// those return internal references, which is what we want (FIXME: this is not true, they return copies!!)
515
.add_property("min",&AabbVisitor::min)
516
.add_property("max",&AabbVisitor::max)
517
.def("__len__",&AabbVisitor::len).staticmethod("__len__")
518
.def("__setitem__",&AabbVisitor::set_item).def("__getitem__",&AabbVisitor::get_item)
519
.def("__setitem__",&AabbVisitor::set_minmax).def("__getitem__",&AabbVisitor::get_minmax)
520
.def("__str__",&AabbVisitor::__str__).def("__repr__",&AabbVisitor::__str__)
524
static bool containsPt(const Box& self, const VectorType& pt){ return self.contains(pt); }
525
static bool containsBox(const Box& self, const Box& other){ return self.contains(other); }
526
static void extendPt(Box& self, const VectorType& pt){ self.extend(pt); }
527
static void extendBox(Box& self, const Box& other){ self.extend(other); }
528
static void clamp(Box& self, const Box& other){ self.clamp(other); }
529
static VectorType min(const Box& self){ return self.min(); }
530
static VectorType max(const Box& self){ return self.max(); }
531
static VectorType center(const Box& self){ return self.center(); }
532
static VectorType sizes(const Box& self){ return self.sizes(); }
533
struct BoxPickle: py::pickle_suite{
534
static py::tuple getinitargs(const Box& x){ return py::make_tuple(x.min(),x.max()); }
536
static Index len(){ return Box::AmbientDimAtCompileTime; }
537
// getters and setters
538
static Scalar get_item(const Box& self, py::tuple _idx){ Index idx[2]; Index mx[2]={2,Box::AmbientDimAtCompileTime}; IDX2_CHECKED_TUPLE_INTS(_idx,mx,idx); if(idx[0]==0) return self.min()[idx[1]]; return self.max()[idx[1]]; }
539
static void set_item(Box& self, py::tuple _idx, Scalar value){ Index idx[2]; Index mx[2]={2,Box::AmbientDimAtCompileTime}; IDX2_CHECKED_TUPLE_INTS(_idx,mx,idx); if(idx[0]==0) self.min()[idx[1]]=value; else self.max()[idx[1]]=value; }
540
static VectorType get_minmax(const Box& self, Index idx){ IDX_CHECK(idx,2); if(idx==0) return self.min(); return self.max(); }
541
static void set_minmax(Box& self, Index idx, const VectorType& value){ IDX_CHECK(idx,2); if(idx==0) self.min()=value; else self.max()=value; }
542
static string __str__(const py::object& obj){
543
const Box& self=py::extract<Box>(obj)();
544
std::ostringstream oss; oss<<object_class_name(obj)<<"((";
545
VectorVisitor<VectorType>::template Vector_data_stream<VectorType>(self.min(),oss);
547
VectorVisitor<VectorType>::template Vector_data_stream<VectorType>(self.max(),oss);
553
template<typename QuaternionT>
554
class QuaternionVisitor: public py::def_visitor<QuaternionVisitor<QuaternionT> >{
555
typedef typename QuaternionT::Scalar Scalar;
556
typedef Eigen::Matrix<Scalar,3,1> CompatVec3;
557
typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1> CompatVecX;
558
typedef Eigen::Matrix<Scalar,3,3> CompatMat3;
559
typedef Eigen::AngleAxis<Scalar> AngleAxisT;
561
template<class PyClass>
562
void visit(PyClass& cl) const {
564
.def("__init__",py::make_constructor(&QuaternionVisitor::fromAxisAngle,py::default_call_policies(),(py::arg("axis"),py::arg("angle"))))
565
.def("__init__",py::make_constructor(&QuaternionVisitor::fromAngleAxis,py::default_call_policies(),(py::arg("angle"),py::arg("axis"))))
566
.def("__init__",py::make_constructor(&QuaternionVisitor::fromTwoVectors,py::default_call_policies(),(py::arg("u"),py::arg("v"))))
567
.def(py::init<Scalar,Scalar,Scalar,Scalar>((py::arg("w"),py::arg("x"),py::arg("y"),py::arg("z")),"Initialize from coefficients.\n\n.. note:: The order of coefficients is *w*, *x*, *y*, *z*. The [] operator numbers them differently, 0...4 for *x* *y* *z* *w*!"))
568
.def(py::init<CompatMat3>((py::arg("rotMatrix")))) //,"Initialize from given rotation matrix.")
569
.def(py::init<QuaternionT>((py::arg("other"))))
570
.def_pickle(QuaternionPickle())
572
.add_static_property("Identity",&QuaternionVisitor::Identity)
574
.def("setFromTwoVectors",&QuaternionVisitor::setFromTwoVectors,((py::arg("u"),py::arg("v"))))
575
.def("conjugate",&QuaternionT::conjugate)
576
.def("toAxisAngle",&QuaternionVisitor::toAxisAngle)
577
.def("toAngleAxis",&QuaternionVisitor::toAngleAxis)
578
.def("toRotationMatrix",&QuaternionT::toRotationMatrix)
579
.def("toRotationVector",&QuaternionVisitor::toRotationVector)
580
.def("Rotate",&QuaternionVisitor::Rotate,((py::arg("v"))))
581
.def("inverse",&QuaternionT::inverse)
582
.def("norm",&QuaternionT::norm)
583
.def("normalize",&QuaternionT::normalize)
584
.def("normalized",&QuaternionT::normalized)
585
// .def("random",&QuaternionVisitor::random,"Assign random orientation to the quaternion.")
587
.def(py::self * py::self)
588
.def(py::self *= py::self)
589
.def(py::self * py::other<CompatVec3>())
590
.def("__eq__",&QuaternionVisitor::__eq__).def("__ne__",&QuaternionVisitor::__ne__)
591
.def("__sub__",&QuaternionVisitor::__sub__)
593
.def("__abs__",&QuaternionT::norm)
594
.def("__len__",&QuaternionVisitor::__len__).staticmethod("__len__")
595
.def("__setitem__",&QuaternionVisitor::__setitem__).def("__getitem__",&QuaternionVisitor::__getitem__)
596
.def("__str__",&QuaternionVisitor::__str__).def("__repr__",&QuaternionVisitor::__str__)
600
static QuaternionT* fromAxisAngle(const CompatVec3& axis, const Scalar& angle){ return new QuaternionT(AngleAxisT(angle,axis)); }
601
static QuaternionT* fromAngleAxis(const Scalar& angle, const CompatVec3& axis){ return new QuaternionT(AngleAxisT(angle,axis)); }
602
static QuaternionT* fromTwoVectors(const CompatVec3& u, const CompatVec3& v){ QuaternionT* q(new QuaternionT); q->setFromTwoVectors(u,v); return q; }
604
struct QuaternionPickle: py::pickle_suite{static py::tuple getinitargs(const QuaternionT& x){ return py::make_tuple(x.w(),x.x(),x.y(),x.z());} };
605
static QuaternionT Identity(){ return QuaternionT::Identity(); }
606
static Vector3r Rotate(const QuaternionT& self, const Vector3r& u){ return self*u; }
607
static py::tuple toAxisAngle(const QuaternionT& self){ AngleAxisT aa(self); return py::make_tuple(aa.axis(),aa.angle());}
608
static py::tuple toAngleAxis(const QuaternionT& self){ AngleAxisT aa(self); return py::make_tuple(aa.angle(),aa.axis());}
609
static CompatVec3 toRotationVector(const QuaternionT& self){ AngleAxisT aa(self); return aa.angle()*aa.axis();}
610
static void setFromTwoVectors(QuaternionT& self, const Vector3r& u, const Vector3r& v){ self.setFromTwoVectors(u,v); /*return self;*/ }
612
static bool __eq__(const QuaternionT& u, const QuaternionT& v){ return u.x()==v.x() && u.y()==v.y() && u.z()==v.z() && u.w()==v.w(); }
613
static bool __ne__(const QuaternionT& u, const QuaternionT& v){ return !__eq__(u,v); }
614
static CompatVecX __sub__(const QuaternionT& a, const QuaternionT& b){ CompatVecX r(4); r<<a.w()-b.w(),a.x()-b.x(),a.y()-b.y(),a.z()-b.z(); return r; }
616
static Scalar __getitem__(const QuaternionT & self, Index idx){ IDX_CHECK(idx,4); if(idx==0) return self.x(); if(idx==1) return self.y(); if(idx==2) return self.z(); return self.w(); }
617
static void __setitem__(QuaternionT& self, Index idx, Real value){ IDX_CHECK(idx,4); if(idx==0) self.x()=value; else if(idx==1) self.y()=value; else if(idx==2) self.z()=value; else if(idx==3) self.w()=value; }
618
static string __str__(const py::object& obj){
619
const QuaternionT& self=py::extract<QuaternionT>(obj)();
621
return string(object_class_name(obj)+"((")+num_to_string(aa.axis()[0])+","+num_to_string(aa.axis()[1])+","+num_to_string(aa.axis()[2])+"),"+num_to_string(aa.angle())+")";
623
static Index __len__(){return 4;}