FreeCAD

Форк
0
/
MatrixPyImp.cpp 
1117 строк · 30.0 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net>     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23

24
#include "PreCompiled.h"
25

26
// inclusion of the generated files (generated out of MatrixPy.xml)
27
#include "RotationPy.h"
28
#include "VectorPy.h"
29
#include "GeometryPyCXX.h"
30
#include "QuantityPy.h"
31
#include "MatrixPy.h"
32
#include "MatrixPy.cpp"
33

34

35
using namespace Base;
36

37
// returns a string which represents the object e.g. when printed in python
38
std::string MatrixPy::representation() const
39
{
40
    const Base::Matrix4D& m = *(this->getMatrixPtr());
41
    std::stringstream str;
42
    str << "Matrix (";
43
    str << "(" << m[0][0] << "," << m[0][1] << "," << m[0][2] << "," << m[0][3] << ")"
44
        << ",";
45
    str << "(" << m[1][0] << "," << m[1][1] << "," << m[1][2] << "," << m[1][3] << ")"
46
        << ",";
47
    str << "(" << m[2][0] << "," << m[2][1] << "," << m[2][2] << "," << m[2][3] << ")"
48
        << ",";
49
    str << "(" << m[3][0] << "," << m[3][1] << "," << m[3][2] << "," << m[3][3] << ")";
50
    str << ")";
51

52
    return str.str();
53
}
54

55
PyObject* MatrixPy::PyMake(PyTypeObject* /*unused*/, PyObject* /*unused*/, PyObject* /*unused*/)
56
{
57
    // create a new instance of MatrixPy and the Twin object
58
    return new MatrixPy(new Matrix4D);
59
}
60

61
// constructor method
62
int MatrixPy::PyInit(PyObject* args, PyObject* /*kwd*/)
63
{
64
    // NOLINTBEGIN
65
    double a11 = 1.0, a12 = 0.0, a13 = 0.0, a14 = 0.0;
66
    double a21 = 0.0, a22 = 1.0, a23 = 0.0, a24 = 0.0;
67
    double a31 = 0.0, a32 = 0.0, a33 = 1.0, a34 = 0.0;
68
    double a41 = 0.0, a42 = 0.0, a43 = 0.0, a44 = 1.0;
69
    // NOLINTEND
70

71
    // clang-format off
72
    if (PyArg_ParseTuple(args,
73
                         "|dddddddddddddddd",
74
                         &a11, &a12, &a13, &a14,
75
                         &a21, &a22, &a23, &a24,
76
                         &a31, &a32, &a33, &a34,
77
                         &a41, &a42, &a43, &a44)) {
78
        MatrixPy::PointerType ptr = getMatrixPtr();
79
        (*ptr) = Matrix4D(a11, a12, a13, a14,
80
                          a21, a22, a23, a24,
81
                          a31, a32, a33, a34,
82
                          a41, a42, a43, a44);
83
        return 0;
84
    }
85

86
    PyErr_Clear();
87
    PyObject* o {};
88
    if (PyArg_ParseTuple(args, "O!", &(Base::MatrixPy::Type), &o)) {
89
        MatrixPy::PointerType ptr = getMatrixPtr();
90
        (*ptr) = static_cast<MatrixPy*>(o)->value();
91
        return 0;
92
    }
93

94
    PyErr_Clear();
95
    PyObject* o1 {};
96
    PyObject* o2 {};
97
    PyObject* o3 {};
98
    PyObject* o4 {};
99
    if (PyArg_ParseTuple(args, "O!O!O!|O!",
100
                         &(Base::VectorPy::Type), &o1,
101
                         &(Base::VectorPy::Type), &o2,
102
                         &(Base::VectorPy::Type), &o3,
103
                         &(Base::VectorPy::Type), &o4)) {
104
        Base::Vector3d v1 = Py::Vector(o1, false).toVector();
105
        Base::Vector3d v2 = Py::Vector(o2, false).toVector();
106
        Base::Vector3d v3 = Py::Vector(o3, false).toVector();
107
        Base::Vector3d v4;
108
        if (o4) {
109
            v4 = Py::Vector(o4, false).toVector();
110
        }
111
        MatrixPy::PointerType ptr = this->getMatrixPtr();
112

113
        (*ptr)[0][0] = v1.x;
114
        (*ptr)[1][0] = v1.y;
115
        (*ptr)[2][0] = v1.z;
116

117
        (*ptr)[0][1] = v2.x;
118
        (*ptr)[1][1] = v2.y;
119
        (*ptr)[2][1] = v2.z;
120

121
        (*ptr)[0][2] = v3.x;
122
        (*ptr)[1][2] = v3.y;
123
        (*ptr)[2][2] = v3.z;
124

125
        (*ptr)[0][3] = v4.x;
126
        (*ptr)[1][3] = v4.y;
127
        (*ptr)[2][3] = v4.z;
128

129
        return 0;
130
    }
131
    // clang-format on
132

133
    PyErr_SetString(PyExc_TypeError, "Base.Matrix, four Base.Vector or up to 16 floats expected");
134
    return -1;
135
}
136

137
PyObject* MatrixPy::number_add_handler(PyObject* self, PyObject* other)
138
{
139
    if (!PyObject_TypeCheck(self, &(MatrixPy::Type))) {
140
        PyErr_SetString(PyExc_TypeError, "First arg must be Matrix");
141
        return nullptr;
142
    }
143
    if (!PyObject_TypeCheck(other, &(MatrixPy::Type))) {
144
        PyErr_SetString(PyExc_TypeError, "Second arg must be Matrix");
145
        return nullptr;
146
    }
147
    Base::Matrix4D a = static_cast<MatrixPy*>(self)->value();
148
    Base::Matrix4D b = static_cast<MatrixPy*>(other)->value();
149
    return new MatrixPy(a + b);
150
}
151

152
PyObject* MatrixPy::number_subtract_handler(PyObject* self, PyObject* other)
153
{
154
    if (!PyObject_TypeCheck(self, &(MatrixPy::Type))) {
155
        PyErr_SetString(PyExc_TypeError, "First arg must be Matrix");
156
        return nullptr;
157
    }
158
    if (!PyObject_TypeCheck(other, &(MatrixPy::Type))) {
159
        PyErr_SetString(PyExc_TypeError, "Second arg must be Matrix");
160
        return nullptr;
161
    }
162
    Base::Matrix4D a = static_cast<MatrixPy*>(self)->value();
163
    Base::Matrix4D b = static_cast<MatrixPy*>(other)->value();
164
    return new MatrixPy(a - b);
165
}
166

167
PyObject* MatrixPy::number_multiply_handler(PyObject* self, PyObject* other)
168
{
169
    if (PyObject_TypeCheck(self, &(MatrixPy::Type))) {
170
        Base::Matrix4D a = static_cast<MatrixPy*>(self)->value();
171

172
        if (PyObject_TypeCheck(other, &(VectorPy::Type))) {
173
            auto b = static_cast<VectorPy*>(other)->value();
174
            return new VectorPy(a * b);
175
        }
176

177
        if (PyObject_TypeCheck(other, &(RotationPy::Type))) {
178
            auto r = static_cast<RotationPy*>(other)->value();
179
            Matrix4D b;
180
            r.getValue(b);
181
            return new MatrixPy(a * b);
182
        }
183

184
        if (PyObject_TypeCheck(other, &(PlacementPy::Type))) {
185
            auto b = static_cast<PlacementPy*>(other)->value();
186
            return new MatrixPy(a * b.toMatrix());
187
        }
188

189
        if (PyObject_TypeCheck(other, &(MatrixPy::Type))) {
190
            Base::Matrix4D b = static_cast<MatrixPy*>(other)->value();
191
            return new MatrixPy(a * b);
192
        }
193

194
        if (PyNumber_Check(other)) {
195
            double v = PyFloat_AsDouble(other);
196
            return new MatrixPy(a * v);
197
        }
198
    }
199

200
    PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
201
    return nullptr;
202
}
203

204
PyObject* MatrixPy::number_power_handler(PyObject* self, PyObject* other, PyObject* arg)
205
{
206
    if (!PyObject_TypeCheck(self, &(MatrixPy::Type)) ||
207

208
        !PyLong_Check(other) || arg != Py_None) {
209
        PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
210
        return nullptr;
211
    }
212

213
    Base::Matrix4D a = static_cast<MatrixPy*>(self)->value();
214

215
    long b = Py::Int(other);
216
    if (b == 0) {
217
        return new MatrixPy(Matrix4D());
218
    }
219

220
    if (b < 0) {
221
        if (fabs(a.determinant()) > DBL_EPSILON) {
222
            a.inverseGauss();
223
        }
224
        else {
225
            PyErr_SetString(PyExc_RuntimeError, "Cannot invert singular matrix");
226
            return nullptr;
227
        }
228
        b = -b;
229
    }
230

231
    auto res = a;
232
    for (--b; b; --b) {
233
        res *= a;
234
    }
235
    return new MatrixPy(res);
236
}
237

238
PyObject* MatrixPy::richCompare(PyObject* v, PyObject* w, int op)
239
{
240
    if (PyObject_TypeCheck(v, &(MatrixPy::Type)) && PyObject_TypeCheck(w, &(MatrixPy::Type))) {
241
        Matrix4D m1 = static_cast<MatrixPy*>(v)->value();
242
        Matrix4D m2 = static_cast<MatrixPy*>(w)->value();
243

244
        PyObject* res = nullptr;
245
        if (op != Py_EQ && op != Py_NE) {
246
            PyErr_SetString(PyExc_TypeError, "no ordering relation is defined for Matrix");
247
            return nullptr;
248
        }
249
        if (op == Py_EQ) {
250
            res = (m1 == m2) ? Py_True : Py_False;  // NOLINT
251
            Py_INCREF(res);
252
            return res;
253
        }
254

255
        res = (m1 != m2) ? Py_True : Py_False;  // NOLINT
256
        Py_INCREF(res);
257
        return res;
258
    }
259
    // This always returns False
260
    Py_INCREF(Py_NotImplemented);
261
    return Py_NotImplemented;
262
}
263

264
PyObject* MatrixPy::move(PyObject* args)
265
{
266
    double x {};
267
    double y {};
268
    double z {};
269
    Base::Vector3d vec;
270
    PyObject* pcVecObj {};
271

272
    do {  // dummy do..while for cascaded if
273
        if (PyArg_ParseTuple(args, "ddd", &x, &y, &z)) {
274
            vec.x = x;
275
            vec.y = y;
276
            vec.z = z;
277
            break;
278
        }
279
        // clears the error from previous PyArg_ParseTuple()
280
        PyErr_Clear();
281
        if (PyArg_ParseTuple(args, "O!", &PyTuple_Type, &pcVecObj)) {
282
            vec = getVectorFromTuple<double>(pcVecObj);
283
            break;
284
        }
285
        // clears the error from previous PyArg_ParseTuple()
286
        PyErr_Clear();
287
        if (PyArg_ParseTuple(args,
288
                             "O!;three floats, or a tuple, or a vector is needed",
289
                             &(Base::VectorPy::Type),
290
                             &pcVecObj)) {
291
            Base::VectorPy* pcObject = static_cast<Base::VectorPy*>(pcVecObj);
292
            Base::Vector3d* val = pcObject->getVectorPtr();
293
            vec.Set(val->x, val->y, val->z);
294
            break;
295
        }
296
        return nullptr;
297
    } while (false);
298

299
    PY_TRY
300
    {
301
        getMatrixPtr()->move(vec);
302
        Py_Return;
303
    }
304
    PY_CATCH;
305
}
306

307
PyObject* MatrixPy::scale(PyObject* args)
308
{
309
    double x {};
310
    double y {};
311
    double z {};
312
    Base::Vector3d vec;
313
    PyObject* pcVecObj {};
314

315
    do {  // dummy do..while for cascaded if
316
        if (PyArg_ParseTuple(args, "ddd", &x, &y, &z)) {
317
            vec.x = x;
318
            vec.y = y;
319
            vec.z = z;
320
            break;
321
        }
322
        // clears the error from previous PyArg_ParseTuple()
323
        PyErr_Clear();
324
        if (PyArg_ParseTuple(args, "d", &x)) {
325
            vec.x = vec.y = vec.z = x;
326
            break;
327
        }
328
        // clears the error from previous PyArg_ParseTuple()
329
        PyErr_Clear();
330
        if (PyArg_ParseTuple(args, "O!", &PyTuple_Type, &pcVecObj)) {
331
            vec = getVectorFromTuple<double>(pcVecObj);
332
            break;
333
        }
334
        // clears the error from previous PyArg_ParseTuple()
335
        PyErr_Clear();
336
        if (PyArg_ParseTuple(args,
337
                             "O!;one or three floats, or a tuple, or a vector is needed",
338
                             &(Base::VectorPy::Type),
339
                             &pcVecObj)) {
340
            Base::VectorPy* pcObject = static_cast<Base::VectorPy*>(pcVecObj);
341
            Base::Vector3d* val = pcObject->getVectorPtr();
342
            vec.Set(val->x, val->y, val->z);
343
            break;
344
        }
345
        return nullptr;
346
    } while (false);
347

348
    PY_TRY
349
    {
350
        getMatrixPtr()->scale(vec);
351
        Py_Return;
352
    }
353
    PY_CATCH;
354
}
355

356
PyObject* MatrixPy::hasScale(PyObject* args)
357
{
358
    double tol = 0;
359
    if (!PyArg_ParseTuple(args, "|d", &tol)) {
360
        return nullptr;
361
    }
362

363
    ScaleType type = getMatrixPtr()->hasScale(tol);
364
    Py::Module mod("FreeCAD");
365
    return Py::new_reference_to(
366
        mod.callMemberFunction("ScaleType", Py::TupleN(Py::Int(static_cast<int>(type)))));
367
}
368

369
PyObject* MatrixPy::decompose(PyObject* args)
370
{
371
    if (!PyArg_ParseTuple(args, "")) {
372
        return nullptr;
373
    }
374

375
    auto ms = getMatrixPtr()->decompose();
376
    Py::Tuple tuple(4);
377
    for (int i = 0; i < 4; i++) {
378
        tuple.setItem(i, Py::Matrix(ms[i]));
379
    }
380
    return Py::new_reference_to(tuple);
381
}
382

383
PyObject* MatrixPy::nullify()
384
{
385
    PY_TRY
386
    {
387
        getMatrixPtr()->nullify();
388
        Py_Return;
389
    }
390
    PY_CATCH;
391
}
392

393
PyObject* MatrixPy::isNull()
394
{
395
    PY_TRY
396
    {
397
        bool ok = getMatrixPtr()->isNull();
398
        return Py::new_reference_to(Py::Boolean(ok));
399
    }
400
    PY_CATCH;
401
}
402

403
PyObject* MatrixPy::unity()
404
{
405
    PY_TRY
406
    {
407
        getMatrixPtr()->setToUnity();
408
        Py_Return;
409
    }
410
    PY_CATCH;
411
}
412

413
PyObject* MatrixPy::isUnity(PyObject* args)
414
{
415
    double tol = 0.0;
416
    if (!PyArg_ParseTuple(args, "|d", &tol)) {
417
        return nullptr;
418
    }
419

420
    PY_TRY
421
    {
422
        bool ok = getMatrixPtr()->isUnity(tol);
423
        return Py::new_reference_to(Py::Boolean(ok));
424
    }
425
    PY_CATCH;
426
}
427

428
PyObject* MatrixPy::transform(PyObject* args)
429
{
430
    Base::Vector3d vec;
431
    Matrix4D mat;
432
    PyObject* pcVecObj {};
433
    PyObject* pcMatObj {};
434

435
    if (!PyArg_ParseTuple(
436
            args,
437
            "O!O!: a transform point (Vector) and a transform matrix (Matrix) is needed",
438
            &(Base::VectorPy::Type),
439
            &pcVecObj,
440
            &(MatrixPy::Type),
441
            &pcMatObj)) {
442
        return nullptr;
443
    }
444

445
    Base::VectorPy* pcObject = static_cast<Base::VectorPy*>(pcVecObj);
446
    Base::Vector3d* val = pcObject->getVectorPtr();
447
    vec.Set(val->x, val->y, val->z);
448
    mat = *(static_cast<MatrixPy*>(pcMatObj)->getMatrixPtr());
449

450
    getMatrixPtr()->transform(vec, mat);
451
    Py_Return;
452
}
453

454
PyObject* MatrixPy::col(PyObject* args)
455
{
456
    int index {};
457
    if (!PyArg_ParseTuple(args, "i", &index)) {
458
        return nullptr;
459
    }
460

461
    if (index < 0 || index > 3) {
462
        PyErr_SetString(PyExc_ValueError, "Index expected in the range [0, 3]");
463
        return nullptr;
464
    }
465

466
    Matrix4D* mat = getMatrixPtr();
467
    Base::Vector3d v = mat->getCol(index);
468
    return Py::new_reference_to(Py::Vector(v));
469
}
470

471
PyObject* MatrixPy::setCol(PyObject* args)
472
{
473
    int index {};
474
    PyObject* o {};
475
    if (!PyArg_ParseTuple(args, "iO!", &index, &(VectorPy::Type), &o)) {
476
        return nullptr;
477
    }
478

479
    if (index < 0 || index > 3) {
480
        PyErr_SetString(PyExc_ValueError, "Index expected in the range [0, 3]");
481
        return nullptr;
482
    }
483

484
    Base::Vector3d v = Py::Vector(o, false).toVector();
485
    Matrix4D* mat = getMatrixPtr();
486
    mat->setCol(index, v);
487
    Py_Return;
488
}
489

490
PyObject* MatrixPy::row(PyObject* args)
491
{
492
    int index {};
493
    if (!PyArg_ParseTuple(args, "i", &index)) {
494
        return nullptr;
495
    }
496

497
    if (index < 0 || index > 3) {
498
        PyErr_SetString(PyExc_ValueError, "Index expected in the range [0, 3]");
499
        return nullptr;
500
    }
501

502
    Matrix4D* mat = getMatrixPtr();
503
    Base::Vector3d v = mat->getRow(index);
504
    return Py::new_reference_to(Py::Vector(v));
505
}
506

507
PyObject* MatrixPy::setRow(PyObject* args)
508
{
509
    int index {};
510
    PyObject* o {};
511
    if (!PyArg_ParseTuple(args, "iO!", &index, &(VectorPy::Type), &o)) {
512
        return nullptr;
513
    }
514

515
    if (index < 0 || index > 3) {
516
        PyErr_SetString(PyExc_ValueError, "Index expected in the range [0, 3]");
517
        return nullptr;
518
    }
519

520
    Base::Vector3d v = Py::Vector(o, false).toVector();
521
    Matrix4D* mat = getMatrixPtr();
522
    mat->setRow(index, v);
523
    Py_Return;
524
}
525

526
PyObject* MatrixPy::diagonal()
527
{
528
    Matrix4D* mat = getMatrixPtr();
529
    Base::Vector3d v = mat->diagonal();
530
    return Py::new_reference_to(Py::Vector(v));
531
}
532

533
PyObject* MatrixPy::setDiagonal(PyObject* args)
534
{
535
    PyObject* o {};
536
    if (!PyArg_ParseTuple(args, "O!", &(VectorPy::Type), &o)) {
537
        return nullptr;
538
    }
539

540
    Base::Vector3d v = Py::Vector(o, false).toVector();
541
    Matrix4D* mat = getMatrixPtr();
542
    mat->setDiagonal(v);
543
    Py_Return;
544
}
545

546
PyObject* MatrixPy::rotateX(PyObject* args)
547
{
548
    double angle = 0;
549
    do {
550
        PyObject* object {};
551
        if (PyArg_ParseTuple(args, "O!", &(Base::QuantityPy::Type), &object)) {
552
            Quantity* q = static_cast<Base::QuantityPy*>(object)->getQuantityPtr();
553
            if (q->getUnit() == Base::Unit::Angle) {
554
                angle = q->getValueAs(Base::Quantity::Radian);
555
                break;
556
            }
557
        }
558

559
        PyErr_Clear();
560
        if (PyArg_ParseTuple(args, "d: angle to rotate (double) needed", &angle)) {
561
            break;
562
        }
563

564
        PyErr_SetString(PyExc_TypeError, "For angle either float or Quantity expected");
565
        return nullptr;
566
    } while (false);
567

568
    PY_TRY
569
    {
570
        getMatrixPtr()->rotX(angle);
571
        Py_Return;
572
    }
573
    PY_CATCH;
574
}
575

576
PyObject* MatrixPy::rotateY(PyObject* args)
577
{
578
    double angle = 0;
579
    do {
580
        PyObject* object {};
581
        if (PyArg_ParseTuple(args, "O!", &(Base::QuantityPy::Type), &object)) {
582
            Quantity* q = static_cast<Base::QuantityPy*>(object)->getQuantityPtr();
583
            if (q->getUnit() == Base::Unit::Angle) {
584
                angle = q->getValueAs(Base::Quantity::Radian);
585
                break;
586
            }
587
        }
588

589
        PyErr_Clear();
590
        if (PyArg_ParseTuple(args, "d: angle to rotate (double) needed", &angle)) {
591
            break;
592
        }
593

594
        PyErr_SetString(PyExc_TypeError, "For angle either float or Quantity expected");
595
        return nullptr;
596
    } while (false);
597

598
    PY_TRY
599
    {
600
        getMatrixPtr()->rotY(angle);
601
        Py_Return;
602
    }
603
    PY_CATCH;
604
}
605

606
PyObject* MatrixPy::rotateZ(PyObject* args)
607
{
608
    double angle = 0;
609
    do {
610
        PyObject* object {};
611
        if (PyArg_ParseTuple(args, "O!", &(Base::QuantityPy::Type), &object)) {
612
            Quantity* q = static_cast<Base::QuantityPy*>(object)->getQuantityPtr();
613
            if (q->getUnit() == Base::Unit::Angle) {
614
                angle = q->getValueAs(Base::Quantity::Radian);
615
                break;
616
            }
617
        }
618

619
        PyErr_Clear();
620
        if (PyArg_ParseTuple(args, "d: angle to rotate (double) needed", &angle)) {
621
            break;
622
        }
623

624
        PyErr_SetString(PyExc_TypeError, "For angle either float or Quantity expected");
625
        return nullptr;
626
    } while (false);
627

628
    PY_TRY
629
    {
630
        getMatrixPtr()->rotZ(angle);
631
        Py_Return;
632
    }
633
    PY_CATCH;
634
}
635

636
PyObject* MatrixPy::multiply(PyObject* args)
637
{
638
    PyObject* o {};
639
    if (PyArg_ParseTuple(args, "O!", &(MatrixPy::Type), &o)) {
640
        Matrix4D mat = (*getMatrixPtr()) * static_cast<Base::MatrixPy*>(o)->value();
641
        return new MatrixPy(new Matrix4D(mat));
642
    }
643

644
    PyErr_Clear();
645
    if (PyArg_ParseTuple(args, "O!", &(VectorPy::Type), &o)) {
646
        Vector3d vec = (*getMatrixPtr()) * static_cast<Base::VectorPy*>(o)->value();
647
        return new VectorPy(new Vector3d(vec));
648
    }
649

650
    PyErr_SetString(PyExc_TypeError, "either vector or matrix expected");
651
    return nullptr;
652
}
653

654
PyObject* MatrixPy::multVec(PyObject* args)
655
{
656
    PyObject* obj {};
657
    if (!PyArg_ParseTuple(args, "O!", &(VectorPy::Type), &obj)) {
658
        return nullptr;
659
    }
660

661
    Base::Vector3d vec(static_cast<VectorPy*>(obj)->value());
662
    getMatrixPtr()->multVec(vec, vec);
663
    return new VectorPy(new Vector3d(vec));
664
}
665

666
PyObject* MatrixPy::invert()
667
{
668
    PY_TRY
669
    {
670
        if (fabs(getMatrixPtr()->determinant()) > DBL_EPSILON) {
671
            getMatrixPtr()->inverseGauss();
672
            Py_Return;
673
        }
674

675
        PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot invert singular matrix");
676
        return nullptr;
677
    }
678
    PY_CATCH;
679
}
680

681
PyObject* MatrixPy::inverse()
682
{
683
    PY_TRY
684
    {
685
        if (fabs(getMatrixPtr()->determinant()) > DBL_EPSILON) {
686
            Base::Matrix4D m = *getMatrixPtr();
687
            m.inverseGauss();
688
            return new MatrixPy(m);
689
        }
690

691
        PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot invert singular matrix");
692
        return nullptr;
693
    }
694
    PY_CATCH;
695
}
696

697
PyObject* MatrixPy::determinant()
698
{
699
    return PyFloat_FromDouble(getMatrixPtr()->determinant());
700
}
701

702
PyObject* MatrixPy::submatrix(PyObject* args)
703
{
704
    int dim {};
705
    if (!PyArg_ParseTuple(args, "i", &dim)) {
706
        return nullptr;
707
    }
708

709
    if (dim < 1 || dim > 4) {
710
        PyErr_SetString(PyExc_IndexError, "Dimension out of range");
711
        return nullptr;
712
    }
713

714
    const Base::Matrix4D& mat = *getMatrixPtr();
715
    Base::Matrix4D sub;
716
    switch (dim) {
717
        case 1:
718
            sub[0][0] = mat[0][0];
719
            break;
720
        case 2:
721
            sub[0][0] = mat[0][0];
722
            sub[0][1] = mat[0][1];
723
            sub[1][0] = mat[1][0];
724
            sub[1][1] = mat[1][1];
725
            break;
726
        case 3:
727
            sub[0][0] = mat[0][0];
728
            sub[0][1] = mat[0][1];
729
            sub[0][2] = mat[0][2];
730
            sub[1][0] = mat[1][0];
731
            sub[1][1] = mat[1][1];
732
            sub[1][2] = mat[1][2];
733
            sub[2][0] = mat[2][0];
734
            sub[2][1] = mat[2][1];
735
            sub[2][2] = mat[2][2];
736
            break;
737
        default:
738
            sub = mat;
739
            break;
740
    }
741

742
    return new MatrixPy(sub);
743
}
744

745
PyObject* MatrixPy::isOrthogonal(PyObject* args)
746
{
747
    double eps = 1.0e-06;
748
    if (!PyArg_ParseTuple(args, "|d", &eps)) {
749
        return nullptr;
750
    }
751

752
    const Base::Matrix4D& mat = *getMatrixPtr();
753
    Base::Matrix4D trp = mat;
754
    trp.transpose();
755
    trp = trp * mat;
756

757
    bool ok = true;
758
    double mult = trp[0][0];
759
    for (unsigned short i = 0; i < 4 && ok; i++) {
760
        for (unsigned short j = 0; j < 4 && ok; j++) {
761
            if (i != j) {
762
                if (fabs(trp[i][j]) > eps) {
763
                    ok = false;
764
                    break;
765
                }
766
            }
767
            else {  // the main diagonal
768
                if (fabs(trp[i][j] - mult) > eps) {
769
                    ok = false;
770
                    break;
771
                }
772
            }
773
        }
774
    }
775

776
    return Py::new_reference_to(Py::Float(ok ? mult : 0.0));
777
}
778

779
PyObject* MatrixPy::transposed()
780
{
781
    PY_TRY
782
    {
783
        Base::Matrix4D m = *getMatrixPtr();
784
        m.transpose();
785
        return new MatrixPy(m);
786
    }
787
    PY_CATCH;
788
}
789

790
PyObject* MatrixPy::transpose()
791
{
792
    PY_TRY
793
    {
794
        getMatrixPtr()->transpose();
795
        Py_Return;
796
    }
797
    PY_CATCH;
798
}
799

800
PyObject* MatrixPy::analyze()
801
{
802
    PY_TRY
803
    {
804
        std::string type = getMatrixPtr()->analyse();
805
        return PyUnicode_FromString(type.c_str());
806
    }
807
    PY_CATCH;
808
}
809

810
Py::Float MatrixPy::getA11() const
811
{
812
    double val = (*this->getMatrixPtr())[0][0];
813
    return Py::Float(val);
814
}
815

816
void MatrixPy::setA11(Py::Float arg)
817
{
818
    (*this->getMatrixPtr())[0][0] = static_cast<double>(arg);
819
}
820

821
Py::Float MatrixPy::getA12() const
822
{
823
    double val = (*this->getMatrixPtr())[0][1];
824
    return Py::Float(val);
825
}
826

827
void MatrixPy::setA12(Py::Float arg)
828
{
829
    (*this->getMatrixPtr())[0][1] = static_cast<double>(arg);
830
}
831

832
Py::Float MatrixPy::getA13() const
833
{
834
    double val = (*this->getMatrixPtr())[0][2];
835
    return Py::Float(val);
836
}
837

838
void MatrixPy::setA13(Py::Float arg)
839
{
840
    (*this->getMatrixPtr())[0][2] = static_cast<double>(arg);
841
}
842

843
Py::Float MatrixPy::getA14() const
844
{
845
    double val = (*this->getMatrixPtr())[0][3];
846
    return Py::Float(val);
847
}
848

849
void MatrixPy::setA14(Py::Float arg)
850
{
851
    (*this->getMatrixPtr())[0][3] = static_cast<double>(arg);
852
}
853

854
Py::Float MatrixPy::getA21() const
855
{
856
    double val = (*this->getMatrixPtr())[1][0];
857
    return Py::Float(val);
858
}
859

860
void MatrixPy::setA21(Py::Float arg)
861
{
862
    (*this->getMatrixPtr())[1][0] = static_cast<double>(arg);
863
}
864

865
Py::Float MatrixPy::getA22() const
866
{
867
    double val = (*this->getMatrixPtr())[1][1];
868
    return Py::Float(val);
869
}
870

871
void MatrixPy::setA22(Py::Float arg)
872
{
873
    (*this->getMatrixPtr())[1][1] = static_cast<double>(arg);
874
}
875

876
Py::Float MatrixPy::getA23() const
877
{
878
    double val = (*this->getMatrixPtr())[1][2];
879
    return Py::Float(val);
880
}
881

882
void MatrixPy::setA23(Py::Float arg)
883
{
884
    (*this->getMatrixPtr())[1][2] = static_cast<double>(arg);
885
}
886

887
Py::Float MatrixPy::getA24() const
888
{
889
    double val = (*this->getMatrixPtr())[1][3];
890
    return Py::Float(val);
891
}
892

893
void MatrixPy::setA24(Py::Float arg)
894
{
895
    (*this->getMatrixPtr())[1][3] = static_cast<double>(arg);
896
}
897

898
Py::Float MatrixPy::getA31() const
899
{
900
    double val = (*this->getMatrixPtr())[2][0];
901
    return Py::Float(val);
902
}
903

904
void MatrixPy::setA31(Py::Float arg)
905
{
906
    (*this->getMatrixPtr())[2][0] = static_cast<double>(arg);
907
}
908

909
Py::Float MatrixPy::getA32() const
910
{
911
    double val = (*this->getMatrixPtr())[2][1];
912
    return Py::Float(val);
913
}
914

915
void MatrixPy::setA32(Py::Float arg)
916
{
917
    (*this->getMatrixPtr())[2][1] = static_cast<double>(arg);
918
}
919

920
Py::Float MatrixPy::getA33() const
921
{
922
    double val = (*this->getMatrixPtr())[2][2];
923
    return Py::Float(val);
924
}
925

926
void MatrixPy::setA33(Py::Float arg)
927
{
928
    (*this->getMatrixPtr())[2][2] = static_cast<double>(arg);
929
}
930

931
Py::Float MatrixPy::getA34() const
932
{
933
    double val = (*this->getMatrixPtr())[2][3];
934
    return Py::Float(val);
935
}
936

937
void MatrixPy::setA34(Py::Float arg)
938
{
939
    (*this->getMatrixPtr())[2][3] = static_cast<double>(arg);
940
}
941

942
Py::Float MatrixPy::getA41() const
943
{
944
    double val = (*this->getMatrixPtr())[3][0];
945
    return Py::Float(val);
946
}
947

948
void MatrixPy::setA41(Py::Float arg)
949
{
950
    (*this->getMatrixPtr())[3][0] = static_cast<double>(arg);
951
}
952

953
Py::Float MatrixPy::getA42() const
954
{
955
    double val = (*this->getMatrixPtr())[3][1];
956
    return Py::Float(val);
957
}
958

959
void MatrixPy::setA42(Py::Float arg)
960
{
961
    (*this->getMatrixPtr())[3][1] = static_cast<double>(arg);
962
}
963

964
Py::Float MatrixPy::getA43() const
965
{
966
    double val = (*this->getMatrixPtr())[3][2];
967
    return Py::Float(val);
968
}
969

970
void MatrixPy::setA43(Py::Float arg)
971
{
972
    (*this->getMatrixPtr())[3][2] = static_cast<double>(arg);
973
}
974

975
Py::Float MatrixPy::getA44() const
976
{
977
    double val = (*this->getMatrixPtr())[3][3];
978
    return Py::Float(val);
979
}
980

981
void MatrixPy::setA44(Py::Float arg)
982
{
983
    (*this->getMatrixPtr())[3][3] = static_cast<double>(arg);
984
}
985

986
Py::Sequence MatrixPy::getA() const
987
{
988
    double mat[16];
989
    this->getMatrixPtr()->getMatrix(mat);
990
    Py::Tuple tuple(16);
991
    for (int i = 0; i < 16; i++) {
992
        tuple[i] = Py::Float(mat[i]);
993
    }
994
    return std::move(tuple);
995
}
996

997
void MatrixPy::setA(Py::Sequence arg)
998
{
999
    double mat[16];
1000
    this->getMatrixPtr()->getMatrix(mat);
1001

1002
    int index = 0;
1003
    for (Py::Sequence::iterator it = arg.begin(); it != arg.end() && index < 16; ++it) {
1004
        mat[index++] = static_cast<double>(Py::Float(*it));
1005
    }
1006

1007
    this->getMatrixPtr()->setMatrix(mat);
1008
}
1009

1010
PyObject* MatrixPy::getCustomAttributes(const char* /*attr*/) const
1011
{
1012
    return nullptr;
1013
}
1014

1015
int MatrixPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
1016
{
1017
    return 0;
1018
}
1019

1020
PyObject* MatrixPy::number_divide_handler(PyObject* /*self*/, PyObject* /*other*/)
1021
{
1022
    PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
1023
    return nullptr;
1024
}
1025

1026
PyObject* MatrixPy::number_remainder_handler(PyObject* /*self*/, PyObject* /*other*/)
1027
{
1028
    PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
1029
    return nullptr;
1030
}
1031

1032
PyObject* MatrixPy::number_divmod_handler(PyObject* /*self*/, PyObject* /*other*/)
1033
{
1034
    PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
1035
    return nullptr;
1036
}
1037

1038
PyObject* MatrixPy::number_negative_handler(PyObject* self)
1039
{
1040
    if (!PyObject_TypeCheck(self, &(MatrixPy::Type))) {
1041
        PyErr_SetString(PyExc_TypeError, "arg must be Matrix");
1042
        return nullptr;
1043
    }
1044

1045
    Base::Matrix4D a = static_cast<MatrixPy*>(self)->value();
1046
    return new MatrixPy(a * -1);
1047
}
1048

1049
PyObject* MatrixPy::number_positive_handler(PyObject* self)
1050
{
1051
    if (!PyObject_TypeCheck(self, &(MatrixPy::Type))) {
1052
        PyErr_SetString(PyExc_TypeError, "arg must be Matrix");
1053
        return nullptr;
1054
    }
1055

1056
    Base::Matrix4D a = static_cast<MatrixPy*>(self)->value();
1057
    return new MatrixPy(a);
1058
}
1059

1060
PyObject* MatrixPy::number_absolute_handler(PyObject* /*self*/)
1061
{
1062
    PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
1063
    return nullptr;
1064
}
1065

1066
int MatrixPy::number_nonzero_handler(PyObject* /*self*/)
1067
{
1068
    return 1;
1069
}
1070

1071
PyObject* MatrixPy::number_invert_handler(PyObject* /*self*/)
1072
{
1073
    PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
1074
    return nullptr;
1075
}
1076

1077
PyObject* MatrixPy::number_lshift_handler(PyObject* /*self*/, PyObject* /*other*/)
1078
{
1079
    PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
1080
    return nullptr;
1081
}
1082

1083
PyObject* MatrixPy::number_rshift_handler(PyObject* /*self*/, PyObject* /*other*/)
1084
{
1085
    PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
1086
    return nullptr;
1087
}
1088

1089
PyObject* MatrixPy::number_and_handler(PyObject* /*self*/, PyObject* /*other*/)
1090
{
1091
    PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
1092
    return nullptr;
1093
}
1094

1095
PyObject* MatrixPy::number_xor_handler(PyObject* /*self*/, PyObject* /*other*/)
1096
{
1097
    PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
1098
    return nullptr;
1099
}
1100

1101
PyObject* MatrixPy::number_or_handler(PyObject* /*self*/, PyObject* /*other*/)
1102
{
1103
    PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
1104
    return nullptr;
1105
}
1106

1107
PyObject* MatrixPy::number_int_handler(PyObject* /*self*/)
1108
{
1109
    PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
1110
    return nullptr;
1111
}
1112

1113
PyObject* MatrixPy::number_float_handler(PyObject* /*self*/)
1114
{
1115
    PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
1116
    return nullptr;
1117
}
1118

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.