FreeCAD

Форк
0
/
BSplineCurvePyImp.cpp 
1434 строки · 49.2 Кб
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
#include "PreCompiled.h"
24
#ifndef _PreComp_
25
# include <cmath>
26
# include <Geom_BSplineCurve.hxx>
27
# include <GeomAPI_Interpolate.hxx>
28
# include <GeomAPI_PointsToBSpline.hxx>
29
# include <GeomConvert_BSplineCurveToBezierCurve.hxx>
30
# include <gp_Pnt.hxx>
31
# include <Precision.hxx>
32
# include <TColgp_Array1OfPnt.hxx>
33
# include <TColgp_Array1OfVec.hxx>
34
# include <TColgp_HArray1OfPnt.hxx>
35
# include <TColStd_Array1OfInteger.hxx>
36
# include <TColStd_Array1OfReal.hxx>
37
# include <TColStd_HArray1OfBoolean.hxx>
38
# include <TColStd_HArray1OfReal.hxx>
39
#endif
40

41
#include <Base/GeometryPyCXX.h>
42
#include <Base/PyWrapParseTupleAndKeywords.h>
43
#include <Base/VectorPy.h>
44

45
#include "BSplineCurvePy.h"
46
#include "BSplineCurvePy.cpp"
47
#include "BezierCurvePy.h"
48
#include "OCCError.h"
49

50

51
using namespace Part;
52

53
// returns a string which represents the object e.g. when printed in python
54
std::string BSplineCurvePy::representation() const
55
{
56
    return "<BSplineCurve object>";
57
}
58

59
PyObject *BSplineCurvePy::PyMake(struct _typeobject *, PyObject *, PyObject *)  // Python wrapper
60
{
61
    // create a new instance of BSplineCurvePy and the Twin object
62
    return new BSplineCurvePy(new GeomBSplineCurve);
63
}
64

65
// constructor method
66
int BSplineCurvePy::PyInit(PyObject* args, PyObject* kwd)
67
{
68
    if (PyArg_ParseTuple(args, "")) {
69
        return 0;
70
    }
71

72
    PyErr_Clear();
73
    PyObject* obj;
74
    // poles, [ periodic, degree, interpolate ]
75
    // {"poles", "mults", "knots", "periodic", "degree", "weights", "CheckRational", NULL};
76
    obj = buildFromPolesMultsKnots(args, kwd);
77

78
    if (obj) {
79
        Py_DECREF(obj);
80
        return 0;
81
    }
82
    else if (PyErr_ExceptionMatches(PartExceptionOCCError)) {
83
        return -1;
84
    }
85

86
    PyErr_SetString(PyExc_TypeError, "B-spline constructor accepts:\n"
87
        "-- poles, [ periodic, degree, interpolate ]\n"
88
        "-- empty parameter list\n");
89
    return -1;
90
}
91

92
PyObject*  BSplineCurvePy::__reduce__(PyObject *args)
93
{
94
    if (!PyArg_ParseTuple(args, ""))
95
        return nullptr;
96

97
    Py::Tuple tuple(2);
98

99
    // type object to create an instance
100
    Py::Object type(Base::getTypeAsObject(&BSplineCurvePy::Type));
101
    tuple.setItem(0, type);
102

103
    // create an argument tuple to create a copy
104
    Py::Object self(this);
105
    Py::Tuple data(7);
106
    data.setItem(0, Py::Callable(self.getAttr("getPoles")).apply());
107
    data.setItem(1, Py::Callable(self.getAttr("getMultiplicities")).apply());
108
    data.setItem(2, Py::Callable(self.getAttr("getKnots")).apply());
109
    data.setItem(3, Py::Callable(self.getAttr("isPeriodic")).apply());
110
    data.setItem(4, self.getAttr("Degree"));
111
    data.setItem(5, Py::Callable(self.getAttr("getWeights")).apply());
112
    data.setItem(6, Py::Callable(self.getAttr("isRational")).apply());
113
    tuple.setItem(1, data);
114

115
    return Py::new_reference_to(tuple);
116
}
117

118
PyObject* BSplineCurvePy::isRational(PyObject *args)
119
{
120
    if (!PyArg_ParseTuple(args, ""))
121
        return nullptr;
122
    Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
123
        (getGeometryPtr()->handle());
124
    Standard_Boolean val = curve->IsRational();
125
    return PyBool_FromLong(val ? 1 : 0);
126
}
127

128
PyObject* BSplineCurvePy::isPeriodic(PyObject *args)
129
{
130
    if (!PyArg_ParseTuple(args, ""))
131
        return nullptr;
132
    Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
133
        (getGeometryPtr()->handle());
134
    Standard_Boolean val = curve->IsPeriodic();
135
    return PyBool_FromLong(val ? 1 : 0);
136
}
137

138
PyObject* BSplineCurvePy::isClosed(PyObject *args)
139
{
140
    if (!PyArg_ParseTuple(args, ""))
141
        return nullptr;
142
    Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
143
        (getGeometryPtr()->handle());
144
    Standard_Boolean val = curve->IsClosed();
145
    return PyBool_FromLong(val ? 1 : 0);
146
}
147

148
PyObject* BSplineCurvePy::increaseDegree(PyObject * args)
149
{
150
    int degree;
151
    if (!PyArg_ParseTuple(args, "i", &degree))
152
        return nullptr;
153
    PY_TRY {
154
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
155
            (getGeometryPtr()->handle());
156
        curve->IncreaseDegree(degree);
157
        Py_Return;
158
    } PY_CATCH_OCC;
159
}
160

161
PyObject* BSplineCurvePy::increaseMultiplicity(PyObject * args)
162
{
163
    int mult=-1;
164
    int start, end;
165
    if (!PyArg_ParseTuple(args, "ii|i", &start, &end, &mult))
166
        return nullptr;
167

168
    try {
169
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
170
            (getGeometryPtr()->handle());
171
        if (mult == -1) {
172
            mult = end;
173
            curve->IncreaseMultiplicity(start, mult);
174
        }
175
        else {
176
            curve->IncreaseMultiplicity(start, end, mult);
177
        }
178

179
        Py_Return;
180
    }
181
    catch (Standard_Failure& e) {
182
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
183
        return nullptr;
184
    }
185
}
186

187
PyObject* BSplineCurvePy::incrementMultiplicity(PyObject * args)
188
{
189
    int start, end, mult;
190
    if (!PyArg_ParseTuple(args, "iii", &start, &end, &mult))
191
        return nullptr;
192

193
    try {
194
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
195
            (getGeometryPtr()->handle());
196
        curve->IncrementMultiplicity(start, end, mult);
197
    }
198
    catch (Standard_Failure& e) {
199
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
200
        return nullptr;
201
    }
202

203
    Py_Return;
204
}
205

206
PyObject* BSplineCurvePy::insertKnot(PyObject * args)
207
{
208
    double U, tol = 0.0;
209
    int M=1;
210
    PyObject* add = Py_True;
211
    if (!PyArg_ParseTuple(args, "d|idO!", &U, &M, &tol, &PyBool_Type, &add))
212
        return nullptr;
213

214
    try {
215
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
216
            (getGeometryPtr()->handle());
217
        curve->InsertKnot(U, M, tol, Base::asBoolean(add));
218
    }
219
    catch (Standard_Failure& e) {
220
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
221
        return nullptr;
222
    }
223

224
    Py_Return;
225
}
226

227
PyObject* BSplineCurvePy::insertKnots(PyObject * args)
228
{
229
    double tol = 0.0;
230
    PyObject* add = Py_True;
231
    PyObject* obj1;
232
    PyObject* obj2;
233
    if (!PyArg_ParseTuple(args, "OO|dO!", &obj1,
234
                                          &obj2,
235
                                          &tol, &PyBool_Type, &add))
236
        return nullptr;
237

238
    try {
239
        Py::Sequence knots(obj1);
240
        TColStd_Array1OfReal k(1, knots.size());
241
        int index=1;
242
        for (Py::Sequence::iterator it = knots.begin(); it != knots.end(); ++it) {
243
            Py::Float val(*it);
244
            k(index++) = (double)val;
245
        }
246
        Py::Sequence mults(obj2);
247
        TColStd_Array1OfInteger m(1, mults.size());
248
        index=1;
249
        for (Py::Sequence::iterator it = mults.begin(); it != mults.end(); ++it) {
250
            Py::Long val(*it);
251
            m(index++) = (int)val;
252
        }
253

254
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
255
            (getGeometryPtr()->handle());
256
        curve->InsertKnots(k, m, tol, Base::asBoolean(add));
257
        Py_Return;
258
    }
259
    catch (Standard_Failure& e) {
260
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
261
        return nullptr;
262
    }
263

264
    Py_Return;
265
}
266

267
PyObject* BSplineCurvePy::removeKnot(PyObject * args)
268
{
269
    double tol;
270
    int Index, M;
271
    if (!PyArg_ParseTuple(args, "iid", &Index, &M, &tol))
272
        return nullptr;
273

274
    try {
275
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
276
            (getGeometryPtr()->handle());
277
        Standard_Boolean ok = curve->RemoveKnot(Index, M, tol);
278
        return PyBool_FromLong(ok ? 1 : 0);
279
    }
280
    catch (Standard_Failure& e) {
281
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
282
        return nullptr;
283
    }
284
}
285

286
PyObject* BSplineCurvePy::segment(PyObject * args)
287
{
288
    double u1, u2;
289
    if (!PyArg_ParseTuple(args, "dd", &u1, &u2))
290
        return nullptr;
291
    try {
292
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
293
            (getGeometryPtr()->handle());
294
        Handle(Geom_BSplineCurve) tempCurve = Handle(Geom_BSplineCurve)::DownCast
295
            (curve->Copy());
296
        tempCurve->Segment(u1, u2);
297
        if (std::abs(tempCurve->FirstParameter()-u1) > Precision::Approximation() ||
298
            std::abs(tempCurve->LastParameter()-u2) > Precision::Approximation()) {
299
            Standard_Failure::Raise("Failed to segment BSpline curve");
300
            return nullptr;
301
        }
302
        else {
303
            curve->Segment(u1, u2);
304
        }
305
        Py_Return;
306
    }
307
    catch (Standard_Failure& e) {
308
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
309
        return nullptr;
310
    }
311
}
312

313
PyObject* BSplineCurvePy::setKnot(PyObject * args)
314
{
315
    int Index, M=-1;
316
    double K;
317
    if (!PyArg_ParseTuple(args, "id|i", &Index, &K, &M))
318
        return nullptr;
319

320
    try {
321
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
322
            (getGeometryPtr()->handle());
323
        if (M == -1) {
324
            curve->SetKnot(Index, K);
325
        }
326
        else {
327
            curve->SetKnot(Index, K, M);
328
        }
329

330
        Py_Return;
331
    }
332
    catch (Standard_Failure& e) {
333
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
334
        return nullptr;
335
    }
336
}
337

338
PyObject* BSplineCurvePy::getKnot(PyObject * args)
339
{
340
    int Index;
341
    if (!PyArg_ParseTuple(args, "i", &Index))
342
        return nullptr;
343

344
    try {
345
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
346
            (getGeometryPtr()->handle());
347
        double M = curve->Knot(Index);
348

349
        return Py_BuildValue("d",M);
350
    }
351
    catch (Standard_Failure& e) {
352
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
353
        return nullptr;
354
    }
355
}
356

357
PyObject* BSplineCurvePy::setKnots(PyObject * args)
358
{
359
    PyObject* obj;
360
    if (!PyArg_ParseTuple(args, "O", &obj))
361
        return nullptr;
362
    try {
363
        Py::Sequence list(obj);
364
        TColStd_Array1OfReal k(1,list.size());
365
        int index=1;
366
        for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
367
            Py::Float val(*it);
368
            k(index++) = (double)val;
369
        }
370

371
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
372
            (getGeometryPtr()->handle());
373
        curve->SetKnots(k);
374
        Py_Return;
375
    }
376
    catch (Standard_Failure& e) {
377
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
378
        return nullptr;
379
    }
380
}
381

382
PyObject* BSplineCurvePy::getKnots(PyObject * args)
383
{
384
    if (!PyArg_ParseTuple(args, ""))
385
        return nullptr;
386
    try {
387
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
388
            (getGeometryPtr()->handle());
389
        TColStd_Array1OfReal w(1,curve->NbKnots());
390
        curve->Knots(w);
391
        Py::List knots;
392
        for (Standard_Integer i=w.Lower(); i<=w.Upper(); i++) {
393
            knots.append(Py::Float(w(i)));
394
        }
395
        return Py::new_reference_to(knots);
396
    }
397
    catch (Standard_Failure& e) {
398
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
399
        return nullptr;
400
    }
401
}
402

403
PyObject* BSplineCurvePy::setPole(PyObject * args)
404
{
405
    int index;
406
    double weight=-1.0;
407
    PyObject* p;
408
    if (!PyArg_ParseTuple(args, "iO!|d", &index, &(Base::VectorPy::Type), &p, &weight))
409
        return nullptr;
410
    Base::Vector3d vec = static_cast<Base::VectorPy*>(p)->value();
411
    gp_Pnt pnt(vec.x, vec.y, vec.z);
412
    try {
413
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
414
            (getGeometryPtr()->handle());
415
        if (weight < 0.0)
416
            curve->SetPole(index,pnt);
417
        else
418
            curve->SetPole(index,pnt,weight);
419
        Py_Return;
420
    }
421
    catch (Standard_Failure& e) {
422
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
423
        return nullptr;
424
    }
425
}
426

427
PyObject* BSplineCurvePy::getPole(PyObject * args)
428
{
429
    int index;
430
    if (!PyArg_ParseTuple(args, "i", &index))
431
        return nullptr;
432
    try {
433
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
434
            (getGeometryPtr()->handle());
435
        Standard_OutOfRange_Raise_if
436
            (index < 1 || index > curve->NbPoles(), "Pole index out of range");
437
        gp_Pnt pnt = curve->Pole(index);
438
        Base::VectorPy* vec = new Base::VectorPy(Base::Vector3d(
439
            pnt.X(), pnt.Y(), pnt.Z()));
440
        return vec;
441
    }
442
    catch (Standard_Failure& e) {
443
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
444
        return nullptr;
445
    }
446
}
447

448
PyObject* BSplineCurvePy::getPoles(PyObject * args)
449
{
450
    if (!PyArg_ParseTuple(args, ""))
451
        return nullptr;
452
    try {
453
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
454
            (getGeometryPtr()->handle());
455
        TColgp_Array1OfPnt p(1,curve->NbPoles());
456
        curve->Poles(p);
457
        Py::List poles;
458
        for (Standard_Integer i=p.Lower(); i<=p.Upper(); i++) {
459
            gp_Pnt pnt = p(i);
460
            Base::VectorPy* vec = new Base::VectorPy(Base::Vector3d(
461
                pnt.X(), pnt.Y(), pnt.Z()));
462
            poles.append(Py::asObject(vec));
463
        }
464
        return Py::new_reference_to(poles);
465
    }
466
    catch (Standard_Failure& e) {
467
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
468
        return nullptr;
469
    }
470
}
471

472
PyObject* BSplineCurvePy::getPolesAndWeights(PyObject * args)
473
{
474
    if (!PyArg_ParseTuple(args, ""))
475
        return nullptr;
476
    try {
477
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
478
            (getGeometryPtr()->handle());
479
        TColgp_Array1OfPnt p(1,curve->NbPoles());
480
        curve->Poles(p);
481
        TColStd_Array1OfReal w(1,curve->NbPoles());
482
        curve->Weights(w);
483

484
        Py::List poles;
485
        for (Standard_Integer i=p.Lower(); i<=p.Upper(); i++) {
486
            gp_Pnt pnt = p(i);
487
            double weight = w(i);
488
            Py::Tuple t(4);
489
            t.setItem(0, Py::Float(pnt.X()));
490
            t.setItem(1, Py::Float(pnt.Y()));
491
            t.setItem(2, Py::Float(pnt.Z()));
492
            t.setItem(3, Py::Float(weight));
493
            poles.append(t);
494
        }
495
        return Py::new_reference_to(poles);
496
    }
497
    catch (Standard_Failure& e) {
498
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
499
        return nullptr;
500
    }
501
}
502

503
PyObject* BSplineCurvePy::setWeight(PyObject * args)
504
{
505
    int index;
506
    double weight;
507
    if (!PyArg_ParseTuple(args, "id", &index,&weight))
508
        return nullptr;
509
    try {
510
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
511
            (getGeometryPtr()->handle());
512
        curve->SetWeight(index,weight);
513
        Py_Return;
514
    }
515
    catch (Standard_Failure& e) {
516
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
517
        return nullptr;
518
    }
519
}
520

521
PyObject* BSplineCurvePy::getWeight(PyObject * args)
522
{
523
    int index;
524
    if (!PyArg_ParseTuple(args, "i", &index))
525
        return nullptr;
526
    try {
527
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
528
            (getGeometryPtr()->handle());
529
        Standard_OutOfRange_Raise_if
530
            (index < 1 || index > curve->NbPoles() , "Weight index out of range");
531
        double weight = curve->Weight(index);
532
        return Py_BuildValue("d", weight);
533
    }
534
    catch (Standard_Failure& e) {
535
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
536
        return nullptr;
537
    }
538
}
539

540
PyObject* BSplineCurvePy::getWeights(PyObject * args)
541
{
542
    if (!PyArg_ParseTuple(args, ""))
543
        return nullptr;
544
    try {
545
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
546
            (getGeometryPtr()->handle());
547
        TColStd_Array1OfReal w(1,curve->NbPoles());
548
        curve->Weights(w);
549
        Py::List weights;
550
        for (Standard_Integer i=w.Lower(); i<=w.Upper(); i++) {
551
            weights.append(Py::Float(w(i)));
552
        }
553
        return Py::new_reference_to(weights);
554
    }
555
    catch (Standard_Failure& e) {
556
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
557
        return nullptr;
558
    }
559
}
560

561
PyObject* BSplineCurvePy::getResolution(PyObject * args)
562
{
563
    double tol;
564
    if (!PyArg_ParseTuple(args, "d", &tol))
565
        return nullptr;
566
    try {
567
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
568
            (getGeometryPtr()->handle());
569
        double utol;
570
        curve->Resolution(tol,utol);
571
        return Py_BuildValue("d",utol);
572
    }
573
    catch (Standard_Failure& e) {
574
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
575
        return nullptr;
576
    }
577
}
578

579
PyObject* BSplineCurvePy::movePoint(PyObject * args)
580
{
581
    double U;
582
    int index1, index2;
583
    PyObject* pnt;
584
    if (!PyArg_ParseTuple(args, "dO!ii", &U, &(Base::VectorPy::Type),&pnt, &index1, &index2))
585
        return nullptr;
586
    try {
587
        Base::Vector3d p = static_cast<Base::VectorPy*>(pnt)->value();
588
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
589
            (getGeometryPtr()->handle());
590
        int first, last;
591
        curve->MovePoint(U, gp_Pnt(p.x,p.y,p.z), index1, index2, first, last);
592
        return Py_BuildValue("(ii)",first, last);
593
    }
594
    catch (Standard_Failure& e) {
595
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
596
        return nullptr;
597
    }
598
}
599

600
PyObject* BSplineCurvePy::setNotPeriodic(PyObject * args)
601
{
602
    if (!PyArg_ParseTuple(args, ""))
603
        return nullptr;
604
    try {
605
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
606
            (getGeometryPtr()->handle());
607
        curve->SetNotPeriodic();
608
        Py_Return;
609
    }
610
    catch (Standard_Failure& e) {
611
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
612
        return nullptr;
613
    }
614
}
615

616
PyObject* BSplineCurvePy::setPeriodic(PyObject * args)
617
{
618
    if (!PyArg_ParseTuple(args, ""))
619
        return nullptr;
620
    try {
621
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
622
            (getGeometryPtr()->handle());
623
        curve->SetPeriodic();
624
        Py_Return;
625
    }
626
    catch (Standard_Failure& e) {
627
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
628
        return nullptr;
629
    }
630
}
631

632
PyObject* BSplineCurvePy::setOrigin(PyObject * args)
633
{
634
    int index;
635
    if (!PyArg_ParseTuple(args, "i", &index))
636
        return nullptr;
637
    try {
638
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
639
            (getGeometryPtr()->handle());
640
        curve->SetOrigin(index);
641
        Py_Return;
642
    }
643
    catch (Standard_Failure& e) {
644
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
645
        return nullptr;
646
    }
647
}
648

649
PyObject* BSplineCurvePy::getMultiplicity(PyObject * args)
650
{
651
    int index;
652
    if (!PyArg_ParseTuple(args, "i", &index))
653
        return nullptr;
654
    try {
655
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
656
            (getGeometryPtr()->handle());
657
        int mult = curve->Multiplicity(index);
658
        return Py_BuildValue("i", mult);
659
    }
660
    catch (Standard_Failure& e) {
661
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
662
        return nullptr;
663
    }
664
}
665

666
PyObject* BSplineCurvePy::getMultiplicities(PyObject * args)
667
{
668
    if (!PyArg_ParseTuple(args, ""))
669
        return nullptr;
670
    try {
671
        Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
672
            (getGeometryPtr()->handle());
673
        TColStd_Array1OfInteger m(1,curve->NbKnots());
674
        curve->Multiplicities(m);
675
        Py::List mults;
676
        for (Standard_Integer i=m.Lower(); i<=m.Upper(); i++) {
677
            mults.append(Py::Long(m(i)));
678
        }
679
        return Py::new_reference_to(mults);
680
    }
681
    catch (Standard_Failure& e) {
682
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
683
        return nullptr;
684
    }
685
}
686
Py::Long BSplineCurvePy::getDegree() const
687
{
688
    Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
689
        (getGeometryPtr()->handle());
690
    return Py::Long(curve->Degree());
691
}
692

693
Py::Long BSplineCurvePy::getMaxDegree() const
694
{
695
    Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
696
        (getGeometryPtr()->handle());
697
    return Py::Long(curve->MaxDegree());
698
}
699

700
Py::Long BSplineCurvePy::getNbPoles() const
701
{
702
    Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
703
        (getGeometryPtr()->handle());
704
    return Py::Long(curve->NbPoles());
705
}
706

707
Py::Long BSplineCurvePy::getNbKnots() const
708
{
709
    Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
710
        (getGeometryPtr()->handle());
711
    return Py::Long(curve->NbKnots());
712
}
713

714
Py::Object BSplineCurvePy::getStartPoint() const
715
{
716
    Handle(Geom_BSplineCurve) c = Handle(Geom_BSplineCurve)::DownCast
717
        (getGeometryPtr()->handle());
718
    gp_Pnt pnt = c->StartPoint();
719
    return Py::Vector(Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z()));
720
}
721

722
Py::Object BSplineCurvePy::getEndPoint() const
723
{
724
    Handle(Geom_BSplineCurve) c = Handle(Geom_BSplineCurve)::DownCast
725
        (getGeometryPtr()->handle());
726
    gp_Pnt pnt = c->EndPoint();
727
    return Py::Vector(Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z()));
728
}
729

730
Py::Object BSplineCurvePy::getFirstUKnotIndex() const
731
{
732
    Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
733
        (getGeometryPtr()->handle());
734
    return Py::Long(curve->FirstUKnotIndex());
735
}
736

737
Py::Object BSplineCurvePy::getLastUKnotIndex() const
738
{
739
    Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
740
        (getGeometryPtr()->handle());
741
    return Py::Long(curve->LastUKnotIndex());
742
}
743

744
Py::List BSplineCurvePy::getKnotSequence() const
745
{
746
    Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast
747
        (getGeometryPtr()->handle());
748
    Standard_Integer m = 0;
749
    if (curve->IsPeriodic()) {
750
        // knots=poles+2*degree-mult(1)+2
751
        m = curve->NbPoles() + 2*curve->Degree() - curve->Multiplicity(1) + 2;
752
    }
753
    else {
754
        // knots=poles+degree+1
755
        for (int i=1; i<= curve->NbKnots(); i++)
756
            m += curve->Multiplicity(i);
757
    }
758

759
    TColStd_Array1OfReal k(1,m);
760
    curve->KnotSequence(k);
761
    Py::List list;
762
    for (Standard_Integer i=k.Lower(); i<=k.Upper(); i++) {
763
        list.append(Py::Float(k(i)));
764
    }
765
    return list;
766
}
767

768
PyObject* BSplineCurvePy::toBiArcs(PyObject * args)
769
{
770
    double tolerance = 0.001;
771
    if (!PyArg_ParseTuple(args, "d", &tolerance))
772
        return nullptr;
773
    try {
774
        GeomBSplineCurve* curve = getGeomBSplineCurvePtr();
775
        std::list<Geometry*> arcs;
776
        arcs = curve->toBiArcs(tolerance);
777

778
        Py::List list;
779
        for (auto arc : arcs) {
780
            list.append(Py::asObject(arc->getPyObject()));
781
            delete arc;
782
        }
783

784
        return Py::new_reference_to(list);
785
    }
786
    catch (Standard_Failure& e) {
787
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
788
        return nullptr;
789
    }
790
}
791

792
PyObject* BSplineCurvePy::approximate(PyObject *args, PyObject *kwds)
793
{
794
    PyObject *obj;
795
    Standard_Integer degMin = 3;
796
    Standard_Integer degMax = 8;
797
    Standard_Integer segMax = 8;
798
    const char *continuity = "C2";
799
    double tol3d = 1e-3;
800
    const char *parType = "ChordLength";
801
    PyObject *par = nullptr;
802
    double weight1 = 0;
803
    double weight2 = 0;
804
    double weight3 = 0;
805

806
    // Approximate this curve with a given continuity and degree
807
    static const std::array<const char *, 5> kwds_reapprox{"MaxDegree", "MaxSegments", "Continuity", "Tolerance",
808
                                                           nullptr};
809
    if (Base::Wrapped_ParseTupleAndKeywords(args, kwds, "i|isd", kwds_reapprox,
810
                                            &tol3d, &degMax, &segMax, &continuity)) {
811

812
        GeomAbs_Shape c;
813
        std::string str = continuity;
814
        if (str == "C0")
815
            c = GeomAbs_C0;
816
        else if (str == "G1")
817
            c = GeomAbs_G1;
818
        else if (str == "C1")
819
            c = GeomAbs_C1;
820
        else if (str == "G2")
821
            c = GeomAbs_G2;
822
        else if (str == "C2")
823
            c = GeomAbs_C2;
824
        else if (str == "C3")
825
            c = GeomAbs_C3;
826
        else if (str == "CN")
827
            c = GeomAbs_CN;
828
        else
829
            c = GeomAbs_C2;
830

831
        this->getGeomBSplineCurvePtr()->approximate(tol3d, segMax, degMax, c);
832
        Py_Return;
833
    }
834

835
    // Approximate a list of points
836
    //
837
    static const std::array<const char *, 11> kwds_interp{"Points", "DegMax", "Continuity", "Tolerance", "DegMin",
838
                                                          "ParamType", "Parameters", "LengthWeight", "CurvatureWeight",
839
                                                          "TorsionWeight", nullptr};
840

841
    PyErr_Clear();
842
    if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "O|isdisOddd", kwds_interp,
843
                                             &obj, &degMax,
844
                                             &continuity, &tol3d, &degMin,
845
                                             &parType, &par,
846
                                             &weight1, &weight2, &weight3)) {
847
        return nullptr;
848
    }
849

850
    try {
851
        Py::Sequence list(obj);
852
        TColgp_Array1OfPnt pnts(1, list.size());
853
        Standard_Integer index = 1;
854
        for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
855
            Base::Vector3d vec = Py::Vector(*it).toVector();
856
            pnts(index++) = gp_Pnt(vec.x,vec.y,vec.z);
857
        }
858

859
        if (degMin > degMax) {
860
            Standard_Failure::Raise("DegMin must be lower or equal to DegMax");
861
        }
862

863
        GeomAbs_Shape c;
864
        std::string str = continuity;
865
        if (str == "C0")
866
            c = GeomAbs_C0;
867
        else if (str == "G1")
868
            c = GeomAbs_G1;
869
        else if (str == "C1")
870
            c = GeomAbs_C1;
871
        else if (str == "G2")
872
            c = GeomAbs_G2;
873
        else if (str == "C2")
874
            c = GeomAbs_C2;
875
        else if (str == "C3")
876
            c = GeomAbs_C3;
877
        else if (str == "CN")
878
            c = GeomAbs_CN;
879
        else
880
            c = GeomAbs_C2;
881

882
        if (weight1 || weight2 || weight3) {
883
            // It seems that this function only works with Continuity = C0, C1 or C2
884
            GeomAPI_PointsToBSpline fit(pnts, weight1, weight2, weight3, degMax, c, tol3d);
885
            Handle(Geom_BSplineCurve) spline = fit.Curve();
886
            if (!spline.IsNull()) {
887
                this->getGeomBSplineCurvePtr()->setHandle(spline);
888
                Py_Return;
889
            }
890
            else {
891
                Standard_Failure::Raise("Smoothing approximation failed");
892
                return nullptr; // goes to the catch block
893
            }
894
        }
895

896
        if (par) {
897
            Py::Sequence plist(par);
898
            TColStd_Array1OfReal parameters(1,plist.size());
899
            Standard_Integer index = 1;
900
            for (Py::Sequence::iterator it = plist.begin(); it != plist.end(); ++it) {
901
                Py::Float f(*it);
902
                parameters(index++) = static_cast<double>(f);
903
            }
904

905
            GeomAPI_PointsToBSpline fit(pnts, parameters, degMin, degMax, c, tol3d);
906
            Handle(Geom_BSplineCurve) spline = fit.Curve();
907
            if (!spline.IsNull()) {
908
                this->getGeomBSplineCurvePtr()->setHandle(spline);
909
                Py_Return;
910
            }
911
            else {
912
                Standard_Failure::Raise("Approximation with parameters failed");
913
                return nullptr; // goes to the catch block
914
            }
915
        }
916

917
        Approx_ParametrizationType pt;
918
        std::string pstr = parType;
919
        if (pstr == "Uniform")
920
            pt = Approx_IsoParametric;
921
        else if (pstr == "Centripetal")
922
            pt = Approx_Centripetal;
923
        else
924
            pt = Approx_ChordLength;
925

926
        GeomAPI_PointsToBSpline fit(pnts, pt, degMin, degMax, c, tol3d);
927
        Handle(Geom_BSplineCurve) spline = fit.Curve();
928
        if (!spline.IsNull()) {
929
            this->getGeomBSplineCurvePtr()->setHandle(spline);
930
            Py_Return;
931
        }
932
        else {
933
            Standard_Failure::Raise("failed to approximate points");
934
            return nullptr; // goes to the catch block
935
        }
936
    }
937
    catch (Standard_Failure& e) {
938
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
939
        return nullptr;
940
    }
941
}
942

943
PyObject* BSplineCurvePy::getCardinalSplineTangents(PyObject *args, PyObject *kwds)
944
{
945
    PyObject* pts;
946
    PyObject* tgs;
947
    double parameter;
948

949
    static const std::array<const char *, 3> kwds_interp1 {"Points", "Parameter", nullptr};
950
    if (Base::Wrapped_ParseTupleAndKeywords(args, kwds, "Od",kwds_interp1, &pts, &parameter)) {
951
        Py::Sequence list(pts);
952
        std::vector<gp_Pnt> interpPoints;
953
        interpPoints.reserve(list.size());
954
        for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
955
            Py::Vector v(*it);
956
            Base::Vector3d pnt = v.toVector();
957
            interpPoints.emplace_back(pnt.x,pnt.y,pnt.z);
958
        }
959

960
        GeomBSplineCurve* bspline = this->getGeomBSplineCurvePtr();
961
        std::vector<gp_Vec> tangents;
962
        bspline->getCardinalSplineTangents(interpPoints, parameter, tangents);
963

964
        Py::List vec;
965
        for (gp_Vec it : tangents)
966
            vec.append(Py::Vector(Base::Vector3d(it.X(), it.Y(), it.Z())));
967
        return Py::new_reference_to(vec);
968
    }
969

970
    PyErr_Clear();
971
    static const std::array<const char *, 3> kwds_interp2 {"Points", "Parameters", nullptr};
972
    if (Base::Wrapped_ParseTupleAndKeywords(args, kwds, "OO",kwds_interp2, &pts, &tgs)) {
973
        Py::Sequence list(pts);
974
        std::vector<gp_Pnt> interpPoints;
975
        interpPoints.reserve(list.size());
976
        for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
977
            Py::Vector v(*it);
978
            Base::Vector3d pnt = v.toVector();
979
            interpPoints.emplace_back(pnt.x,pnt.y,pnt.z);
980
        }
981

982
        Py::Sequence list2(tgs);
983
        std::vector<double> parameters;
984
        parameters.reserve(list2.size());
985
        for (Py::Sequence::iterator it = list2.begin(); it != list2.end(); ++it) {
986
            Py::Float p(*it);
987
            parameters.push_back(static_cast<double>(p));
988
        }
989

990
        GeomBSplineCurve* bspline = this->getGeomBSplineCurvePtr();
991
        std::vector<gp_Vec> tangents;
992
        bspline->getCardinalSplineTangents(interpPoints, parameters, tangents);
993

994
        Py::List vec;
995
        for (gp_Vec it : tangents)
996
            vec.append(Py::Vector(Base::Vector3d(it.X(), it.Y(), it.Z())));
997
        return Py::new_reference_to(vec);
998
    }
999

1000
    return nullptr;
1001
}
1002

1003
PyObject* BSplineCurvePy::interpolate(PyObject *args, PyObject *kwds)
1004
{
1005
    PyObject* obj;
1006
    PyObject* par = nullptr;
1007
    double tol3d = Precision::Approximation();
1008
    PyObject* periodic = Py_False;
1009
    PyObject* t1 = nullptr; PyObject* t2 = nullptr;
1010
    PyObject* ts = nullptr; PyObject* fl = nullptr;
1011
    PyObject* scale = Py_True;
1012

1013
    static const std::array<const char *, 10> kwds_interp{"Points", "PeriodicFlag", "Tolerance", "InitialTangent",
1014
                                                          "FinalTangent", "Tangents", "TangentFlags", "Parameters",
1015
                                                          "Scale", nullptr};
1016

1017
    if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "O|O!dO!O!OOOO!", kwds_interp,
1018
                                             &obj, &PyBool_Type, &periodic, &tol3d,
1019
                                             &Base::VectorPy::Type, &t1,
1020
                                             &Base::VectorPy::Type, &t2,
1021
                                             &ts, &fl, &par, &PyBool_Type, &scale)) {
1022
        return nullptr;
1023
    }
1024

1025
    try {
1026
        Py::Sequence list(obj);
1027
        Handle(TColgp_HArray1OfPnt) interpolationPoints = new TColgp_HArray1OfPnt(1, list.size());
1028
        Standard_Integer index = 1;
1029
        for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
1030
            Py::Vector v(*it);
1031
            Base::Vector3d pnt = v.toVector();
1032
            interpolationPoints->SetValue(index++, gp_Pnt(pnt.x,pnt.y,pnt.z));
1033
        }
1034

1035
        if (interpolationPoints->Length() < 2) {
1036
            Standard_Failure::Raise("not enough points given");
1037
        }
1038

1039
        Handle(TColStd_HArray1OfReal) parameters;
1040
        if (par) {
1041
            Py::Sequence plist(par);
1042
            parameters = new TColStd_HArray1OfReal(1, plist.size());
1043
            Standard_Integer pindex = 1;
1044
            for (Py::Sequence::iterator it = plist.begin(); it != plist.end(); ++it) {
1045
                Py::Float f(*it);
1046
                parameters->SetValue(pindex++, static_cast<double>(f));
1047
            }
1048
        }
1049

1050
        std::unique_ptr<GeomAPI_Interpolate> aBSplineInterpolation;
1051
        if (parameters.IsNull()) {
1052
            aBSplineInterpolation = std::make_unique<GeomAPI_Interpolate>(interpolationPoints,
1053
                Base::asBoolean(periodic), tol3d);
1054
        }
1055
        else {
1056
            aBSplineInterpolation = std::make_unique<GeomAPI_Interpolate>(interpolationPoints, parameters,
1057
                Base::asBoolean(periodic), tol3d);
1058
        }
1059

1060
        if (t1 && t2) {
1061
            Base::Vector3d v1 = Py::Vector(t1,false).toVector();
1062
            Base::Vector3d v2 = Py::Vector(t2,false).toVector();
1063
            gp_Vec initTangent(v1.x,v1.y,v1.z), finalTangent(v2.x,v2.y,v2.z);
1064
            aBSplineInterpolation->Load(initTangent, finalTangent, Base::asBoolean(scale));
1065
        }
1066
        else if (ts && fl) {
1067
            Py::Sequence tlist(ts);
1068
            TColgp_Array1OfVec tangents(1, tlist.size());
1069
            Standard_Integer index = 1;
1070
            for (Py::Sequence::iterator it = tlist.begin(); it != tlist.end(); ++it) {
1071
                Py::Vector v(*it);
1072
                Base::Vector3d vec = v.toVector();
1073
                tangents.SetValue(index++, gp_Vec(vec.x,vec.y,vec.z));
1074
            }
1075

1076
            Py::Sequence flist(fl);
1077
            Handle(TColStd_HArray1OfBoolean) tangentFlags = new TColStd_HArray1OfBoolean(1, flist.size());
1078
            Standard_Integer findex = 1;
1079
            for (Py::Sequence::iterator it = flist.begin(); it != flist.end(); ++it) {
1080
                Py::Boolean flag(*it);
1081
                tangentFlags->SetValue(findex++, static_cast<bool>(flag) ? Standard_True : Standard_False);
1082
            }
1083

1084
            aBSplineInterpolation->Load(tangents, tangentFlags, Base::asBoolean(scale));
1085
        }
1086

1087
        aBSplineInterpolation->Perform();
1088
        if (aBSplineInterpolation->IsDone()) {
1089
            Handle(Geom_BSplineCurve) aBSplineCurve(aBSplineInterpolation->Curve());
1090
            this->getGeomBSplineCurvePtr()->setHandle(aBSplineCurve);
1091
            Py_Return;
1092
        }
1093
        else {
1094
            Standard_Failure::Raise("failed to interpolate points");
1095
            return nullptr; // goes to the catch block
1096
        }
1097
    }
1098
    catch (Standard_Failure& e) {
1099
        std::string err = e.GetMessageString();
1100
        if (err.empty()) err = e.DynamicType()->Name();
1101
        PyErr_SetString(PartExceptionOCCError, err.c_str());
1102
        return nullptr;
1103
    }
1104
}
1105

1106
PyObject* BSplineCurvePy::buildFromPoles(PyObject *args)
1107
{
1108
    PyObject* obj;
1109
    int degree = 3;
1110
    PyObject* periodic = Py_False;
1111
    PyObject* interpolate = Py_False;
1112
    if (!PyArg_ParseTuple(args, "O|O!iO!",&obj, &PyBool_Type, &periodic, &degree, &PyBool_Type, interpolate))
1113
        return nullptr;
1114
    try {
1115
        Py::Sequence list(obj);
1116
        TColgp_Array1OfPnt poles(1, list.size());
1117
        Standard_Integer index = 1;
1118
        for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
1119
            Py::Vector v(*it);
1120
            Base::Vector3d pnt = v.toVector();
1121
            poles(index++) = gp_Pnt(pnt.x,pnt.y,pnt.z);
1122
        }
1123

1124
        if (poles.Length() <= degree)
1125
            degree = poles.Length()-1;
1126

1127
        if (Base::asBoolean(periodic)) {
1128
            int mult;
1129
            int len;
1130
            if (Base::asBoolean(interpolate)) {
1131
                mult = degree;
1132
                len = poles.Length() - mult + 2;
1133
            }
1134
            else {
1135
                mult = 1;
1136
                len = poles.Length() + 1;
1137
            }
1138
            TColStd_Array1OfReal knots(1, len);
1139
            TColStd_Array1OfInteger mults(1, len);
1140
            for (int i=1; i<=knots.Length(); i++){
1141
                knots.SetValue(i,(double)(i-1)/(knots.Length()-1));
1142
                mults.SetValue(i,1);
1143
            }
1144
            mults.SetValue(1, mult);
1145
            mults.SetValue(knots.Length(), mult);
1146

1147
            Handle(Geom_BSplineCurve) spline = new Geom_BSplineCurve(poles, knots, mults, degree, Standard_True);
1148
            if (!spline.IsNull()) {
1149
                this->getGeomBSplineCurvePtr()->setHandle(spline);
1150
                Py_Return;
1151
            }
1152
            else {
1153
                Standard_Failure::Raise("failed to create spline");
1154
                return nullptr; // goes to the catch block
1155
            }
1156
        }
1157
        else {
1158
            TColStd_Array1OfReal knots(1, poles.Length()+degree+1-2*(degree));
1159
            TColStd_Array1OfInteger mults(1, poles.Length()+degree+1-2*(degree));
1160
            for (int i=1; i<=knots.Length(); i++){
1161
                knots.SetValue(i,(double)(i-1)/(knots.Length()-1));
1162
                mults.SetValue(i,1);
1163
            }
1164
            mults.SetValue(1, degree+1);
1165
            mults.SetValue(knots.Length(), degree+1);
1166

1167
            Handle(Geom_BSplineCurve) spline = new Geom_BSplineCurve(poles, knots, mults, degree, Standard_False);
1168
            if (!spline.IsNull()) {
1169
                this->getGeomBSplineCurvePtr()->setHandle(spline);
1170
                Py_Return;
1171
            }
1172
            else {
1173
                Standard_Failure::Raise("failed to create spline");
1174
                return nullptr; // goes to the catch block
1175
            }
1176
        }
1177
    }
1178
    catch (Standard_Failure& e) {
1179
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1180
        return nullptr;
1181
    }
1182
}
1183

1184
PyObject* BSplineCurvePy::buildFromPolesMultsKnots(PyObject *args, PyObject *keywds)
1185
{
1186
    static const std::array<const char *, 8> kwlist{"poles", "mults", "knots", "periodic", "degree", "weights",
1187
                                                    "CheckRational", nullptr};
1188
    PyObject* periodic = Py_False; // NOLINT
1189
    PyObject* CheckRational = Py_True; // NOLINT
1190
    PyObject* poles = Py_None;
1191
    PyObject* mults = Py_None;
1192
    PyObject* knots = Py_None;
1193
    PyObject* weights = Py_None;
1194
    int degree = 3;
1195
    int number_of_poles = 0;
1196
    int number_of_knots = 0;
1197
    int sum_of_mults = 0;
1198
    if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, "O|OOO!iOO!", kwlist,
1199
                                             &poles, &mults, &knots,
1200
                                             &PyBool_Type, &periodic,
1201
                                             &degree, &weights,
1202
                                             &PyBool_Type, &CheckRational)) {
1203
        return nullptr;
1204
    }
1205
    try {
1206
        // poles have to be present
1207
        Py::Sequence list(poles);
1208

1209
        number_of_poles = list.size();
1210
        if ((number_of_poles) < 2) {
1211
            Standard_Failure::Raise("need two or more poles");
1212
            return nullptr;
1213
        }
1214
        TColgp_Array1OfPnt occpoles(1, number_of_poles);
1215
        Standard_Integer index = 1;
1216
        for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
1217
            Py::Vector v(*it);
1218
            Base::Vector3d pnt = v.toVector();
1219
            occpoles(index++) = gp_Pnt(pnt.x,pnt.y,pnt.z);
1220
        }
1221
        //Calculate the number of knots
1222
        if (mults != Py_None && knots != Py_None) {
1223
            number_of_knots = PyObject_Length(mults);
1224
            if (PyObject_Length(knots) != number_of_knots) {
1225
                Standard_Failure::Raise("number of knots and mults mismatch");
1226
                return nullptr;
1227
            }
1228
        }
1229
        else {
1230
            if (mults != Py_None) {
1231
                number_of_knots = PyObject_Length(mults);
1232
            }
1233
            else {
1234
                if (knots != Py_None) { number_of_knots = PyObject_Length(knots); }
1235
                else { //guess number of knots
1236
                    if (Base::asBoolean(periodic)) {
1237
                        if (number_of_poles < degree) {degree = number_of_poles;}
1238
                        number_of_knots = number_of_poles+1;
1239
                    }
1240
                    else {
1241
                        if (number_of_poles <= degree) {degree = number_of_poles-1;}
1242
                        number_of_knots = number_of_poles-degree+1;
1243
                    }
1244
                }
1245
            }
1246
        }
1247
        TColStd_Array1OfInteger occmults(1,number_of_knots);
1248
        TColStd_Array1OfReal occknots(1,number_of_knots);
1249
        TColStd_Array1OfReal occweights(1,number_of_poles);
1250
        if (mults != Py_None) { //mults are given
1251
            Py::Sequence multssq(mults);
1252
            Standard_Integer index = 1;
1253
            for (Py::Sequence::iterator it = multssq.begin(); it != multssq.end() && index <= occmults.Length(); ++it) {
1254
                Py::Long mult(*it);
1255
                if (index < occmults.Length() || !Base::asBoolean(periodic)) {
1256
                    sum_of_mults += static_cast<int>(mult); //sum up the mults to compare them against the number of poles later
1257
                }
1258
                occmults(index++) = static_cast<int>(mult);
1259
            }
1260
        }
1261
        else { //mults are 1 or degree+1 at the ends
1262
            for (int i=1; i<=occmults.Length(); i++){
1263
                occmults.SetValue(i,1);
1264
            }
1265
            if (!Base::asBoolean(periodic) && occmults.Length() > 0) {
1266
                occmults.SetValue(1, degree+1);
1267
                occmults.SetValue(occmults.Length(), degree+1);
1268
                sum_of_mults = occmults.Length()+2*degree;
1269
            }
1270
            else {
1271
                sum_of_mults = occmults.Length()-1;
1272
            }
1273
        }
1274
        // check multiplicity of inner knots
1275
        for (Standard_Integer i=2; i < occmults.Length(); i++) {
1276
            if (occmults(i) > degree) {
1277
                Standard_Failure::Raise("multiplicity of inner knot higher than degree");
1278
            }
1279
        }
1280
        if (knots != Py_None) { //knots are given
1281
            Py::Sequence knotssq(knots);
1282
            index = 1;
1283
            for (Py::Sequence::iterator it = knotssq.begin(); it != knotssq.end() && index <= occknots.Length(); ++it) {
1284
                Py::Float knot(*it);
1285
                occknots(index++) = knot;
1286
            }
1287
        }
1288
        else { // knotes are uniformly spaced 0..1 if not given
1289
            for (int i=1; i<=occknots.Length(); i++){
1290
                occknots.SetValue(i,(double)(i-1)/(occknots.Length()-1));
1291
            }
1292
        }
1293
        if (weights != Py_None) { //weights are given
1294
            if (PyObject_Length(weights) != number_of_poles) {
1295
                Standard_Failure::Raise("number of poles and weights mismatch");
1296
                return nullptr;
1297
            } //complain about mismatch
1298
            Py::Sequence weightssq(weights);
1299
            Standard_Integer index = 1;
1300
            for (Py::Sequence::iterator it = weightssq.begin(); it != weightssq.end(); ++it) {
1301
                Py::Float weight(*it);
1302
                occweights(index++) = weight;
1303
            }
1304
        }
1305
        else { // weights are 1.0
1306
            for (int i=1; i<=occweights.Length(); i++){
1307
                occweights.SetValue(i,1.0);
1308
            }
1309
        }
1310
        // check if the number of poles matches the sum of mults
1311
        if ((Base::asBoolean(periodic) && sum_of_mults != number_of_poles) ||
1312
            (!Base::asBoolean(periodic) && sum_of_mults - degree -1 != number_of_poles)) {
1313
            Standard_Failure::Raise("number of poles and sum of mults mismatch");
1314
            return(nullptr);
1315
        }
1316

1317
        Handle(Geom_BSplineCurve) spline = new Geom_BSplineCurve(occpoles,occweights,occknots,occmults,degree,
1318
            Base::asBoolean(periodic), Base::asBoolean(CheckRational));
1319
        if (!spline.IsNull()) {
1320
            this->getGeomBSplineCurvePtr()->setHandle(spline);
1321
            Py_Return;
1322
        }
1323
        else {
1324
            Standard_Failure::Raise("failed to create spline");
1325
            return nullptr; // goes to the catch block
1326
        }
1327
    }
1328
    catch (const Standard_Failure& e) {
1329
        Standard_CString msg = e.GetMessageString();
1330
        PyErr_SetString(PartExceptionOCCError, msg  ? msg : "");
1331
        return nullptr;
1332
    }
1333
}
1334

1335

1336
PyObject* BSplineCurvePy::toBezier(PyObject *args)
1337
{
1338
    if (!PyArg_ParseTuple(args, ""))
1339
        return nullptr;
1340

1341
    try {
1342
        Handle(Geom_BSplineCurve) spline = Handle(Geom_BSplineCurve)::DownCast
1343
            (this->getGeomBSplineCurvePtr()->handle());
1344
        GeomConvert_BSplineCurveToBezierCurve crt(spline);
1345

1346
        Py::List list;
1347
        Standard_Integer arcs = crt.NbArcs();
1348
        for (Standard_Integer i=1; i<=arcs; i++) {
1349
            Handle(Geom_BezierCurve) bezier = crt.Arc(i);
1350
            list.append(Py::asObject(new BezierCurvePy(new GeomBezierCurve(bezier))));
1351
        }
1352

1353
        return Py::new_reference_to(list);
1354
    }
1355
    catch (Standard_Failure& e) {
1356
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1357
        return nullptr;
1358
    }
1359
}
1360

1361
PyObject* BSplineCurvePy::join(PyObject *args)
1362
{
1363
    PyObject* c;
1364
    if (!PyArg_ParseTuple(args, "O!", &BSplineCurvePy::Type, &c))
1365
        return nullptr;
1366

1367
    try {
1368
        GeomBSplineCurve* curve1 = this->getGeomBSplineCurvePtr();
1369
        BSplineCurvePy* curve2 = static_cast<BSplineCurvePy*>(c);
1370
        Handle(Geom_BSplineCurve) spline = Handle(Geom_BSplineCurve)::DownCast
1371
            (curve2->getGeomBSplineCurvePtr()->handle());
1372

1373
        bool ok = curve1->join(spline);
1374

1375
        return PyBool_FromLong(ok ? 1 : 0);
1376
    }
1377
    catch (Standard_Failure& e) {
1378
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1379
        return nullptr;
1380
    }
1381
}
1382

1383
PyObject* BSplineCurvePy::makeC1Continuous(PyObject *args)
1384
{
1385
    double tol = Precision::Approximation();
1386
    double ang_tol = 1.0e-7;
1387
    if (!PyArg_ParseTuple(args, "|dd", &tol, &ang_tol))
1388
        return nullptr;
1389

1390
    try {
1391
        GeomBSplineCurve* spline = this->getGeomBSplineCurvePtr();
1392
        spline->makeC1Continuous(tol, ang_tol);
1393
        Py_Return;
1394
    }
1395
    catch (Standard_Failure& e) {
1396
        std::string err = e.GetMessageString();
1397
        if (err.empty()) err = e.DynamicType()->Name();
1398
        PyErr_SetString(PartExceptionOCCError, err.c_str());
1399
        return nullptr;
1400
    }
1401
}
1402

1403
PyObject* BSplineCurvePy::scaleKnotsToBounds(PyObject *args)
1404
{
1405
    double u0=0.0;
1406
    double u1=1.0;
1407
    if (!PyArg_ParseTuple(args, "|dd", &u0, &u1))
1408
        return nullptr;
1409
    try {
1410
        if (u0 >= u1) {
1411
            Standard_Failure::Raise("Bad parameter range");
1412
            return nullptr;
1413
        }
1414
        GeomBSplineCurve* curve = getGeomBSplineCurvePtr();
1415
        curve->scaleKnotsToBounds(u0, u1);
1416
        Py_Return;
1417
    }
1418
    catch (Standard_Failure& e) {
1419
        std::string err = e.GetMessageString();
1420
        if (err.empty()) err = e.DynamicType()->Name();
1421
        PyErr_SetString(PartExceptionOCCError, err.c_str());
1422
        return nullptr;
1423
    }
1424
}
1425

1426
PyObject* BSplineCurvePy::getCustomAttributes(const char* /*attr*/) const
1427
{
1428
    return nullptr;
1429
}
1430

1431
int BSplineCurvePy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
1432
{
1433
    return 0;
1434
}
1435

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

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

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

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