1
/***************************************************************************
2
* Copyright (c) 2016 Werner Mayer <wmayer[at]users.sourceforge.net> *
4
* This file is part of the FreeCAD CAx development system. *
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. *
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. *
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 *
21
***************************************************************************/
23
#include "PreCompiled.h"
25
# include <Geom2d_BSplineCurve.hxx>
26
# include <Geom2dAPI_PointsToBSpline.hxx>
27
# include <Geom2dAPI_Interpolate.hxx>
28
# include <Geom2dConvert_BSplineCurveToBezierCurve.hxx>
29
# include <gp_Pnt2d.hxx>
30
# include <Precision.hxx>
31
# include <TColgp_Array1OfPnt2d.hxx>
32
# include <TColgp_Array1OfVec2d.hxx>
33
# include <TColgp_HArray1OfPnt2d.hxx>
34
# include <TColStd_Array1OfInteger.hxx>
35
# include <TColStd_Array1OfReal.hxx>
36
# include <TColStd_HArray1OfBoolean.hxx>
37
# include <TColStd_HArray1OfReal.hxx>
40
#include <Base/GeometryPyCXX.h>
41
#include <Base/PyWrapParseTupleAndKeywords.h>
43
#include "Geom2d/BSplineCurve2dPy.h"
44
#include "Geom2d/BSplineCurve2dPy.cpp"
45
#include "Geom2d/BezierCurve2dPy.h"
51
// returns a string which represents the object e.g. when printed in python
52
std::string BSplineCurve2dPy::representation() const
54
return "<BSplineCurve2d object>";
57
PyObject *BSplineCurve2dPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
59
// create a new instance of BSplineCurve2dPy and the Twin object
60
return new BSplineCurve2dPy(new Geom2dBSplineCurve);
64
int BSplineCurve2dPy::PyInit(PyObject* args, PyObject* /*kwd*/)
66
if (PyArg_ParseTuple(args, "")) {
70
PyErr_SetString(PyExc_TypeError, "B-spline constructor accepts:\n"
71
"-- empty parameter list\n");
75
PyObject* BSplineCurve2dPy::isRational(PyObject *args)
77
if (!PyArg_ParseTuple(args, ""))
79
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
80
(getGeometry2dPtr()->handle());
81
Standard_Boolean val = curve->IsRational();
82
return PyBool_FromLong(val ? 1 : 0);
85
PyObject* BSplineCurve2dPy::isPeriodic(PyObject *args)
87
if (!PyArg_ParseTuple(args, ""))
89
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
90
(getGeometry2dPtr()->handle());
91
Standard_Boolean val = curve->IsPeriodic();
92
return PyBool_FromLong(val ? 1 : 0);
95
PyObject* BSplineCurve2dPy::isClosed(PyObject *args)
97
if (!PyArg_ParseTuple(args, ""))
99
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
100
(getGeometry2dPtr()->handle());
101
Standard_Boolean val = curve->IsClosed();
102
return PyBool_FromLong(val ? 1 : 0);
105
PyObject* BSplineCurve2dPy::increaseDegree(PyObject * args)
108
if (!PyArg_ParseTuple(args, "i", °ree))
111
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
112
(getGeometry2dPtr()->handle());
113
curve->IncreaseDegree(degree);
116
catch (Standard_Failure& e) {
117
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
122
PyObject* BSplineCurve2dPy::increaseMultiplicity(PyObject * args)
126
if (!PyArg_ParseTuple(args, "ii|i", &start, &end, &mult))
130
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
131
(getGeometry2dPtr()->handle());
134
curve->IncreaseMultiplicity(start, mult);
137
curve->IncreaseMultiplicity(start, end, mult);
142
catch (Standard_Failure& e) {
143
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
148
PyObject* BSplineCurve2dPy::incrementMultiplicity(PyObject * args)
150
int start, end, mult;
151
if (!PyArg_ParseTuple(args, "iii", &start, &end, &mult))
155
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
156
(getGeometry2dPtr()->handle());
157
curve->IncrementMultiplicity(start, end, mult);
159
catch (Standard_Failure& e) {
160
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
167
PyObject* BSplineCurve2dPy::insertKnot(PyObject * args)
172
if (!PyArg_ParseTuple(args, "d|id", &U, &M, &tol)) {
177
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
178
(getGeometry2dPtr()->handle());
179
curve->InsertKnot(U,M,tol);
181
catch (Standard_Failure& e) {
182
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
189
PyObject* BSplineCurve2dPy::insertKnots(PyObject * args)
192
PyObject* add = Py_True;
195
if (!PyArg_ParseTuple(args, "OO|dO!", &obj1,
197
&tol, &PyBool_Type, &add))
201
Py::Sequence knots(obj1);
202
TColStd_Array1OfReal k(1,knots.size());
204
for (Py::Sequence::iterator it = knots.begin(); it != knots.end(); ++it) {
206
k(index++) = (double)val;
208
Py::Sequence mults(obj2);
209
TColStd_Array1OfInteger m(1,mults.size());
211
for (Py::Sequence::iterator it = mults.begin(); it != mults.end(); ++it) {
213
m(index++) = (int)val;
216
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
217
(getGeometry2dPtr()->handle());
218
curve->InsertKnots(k, m, tol, Base::asBoolean(add));
221
catch (Standard_Failure& e) {
222
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
229
PyObject* BSplineCurve2dPy::removeKnot(PyObject * args)
233
if (!PyArg_ParseTuple(args, "iid", &Index, &M, &tol))
237
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
238
(getGeometry2dPtr()->handle());
239
Standard_Boolean ok = curve->RemoveKnot(Index,M,tol);
240
return PyBool_FromLong(ok ? 1 : 0);
242
catch (Standard_Failure& e) {
243
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
248
PyObject* BSplineCurve2dPy::segment(PyObject * args)
251
if (!PyArg_ParseTuple(args, "dd", &u1,&u2))
254
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
255
(getGeometry2dPtr()->handle());
256
curve->Segment(u1,u2);
259
catch (Standard_Failure& e) {
260
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
265
PyObject* BSplineCurve2dPy::setKnot(PyObject * args)
269
if (!PyArg_ParseTuple(args, "id|i", &Index, &K, &M))
272
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
273
(getGeometry2dPtr()->handle());
275
curve->SetKnot(Index, K);
278
curve->SetKnot(Index, K, M);
284
PyObject* BSplineCurve2dPy::getKnot(PyObject * args)
287
if (!PyArg_ParseTuple(args, "i", &Index))
290
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
291
(getGeometry2dPtr()->handle());
292
double M = curve->Knot(Index);
294
return Py_BuildValue("d",M);
297
PyObject* BSplineCurve2dPy::setKnots(PyObject * args)
300
if (!PyArg_ParseTuple(args, "O", &obj))
303
Py::Sequence list(obj);
304
TColStd_Array1OfReal k(1,list.size());
306
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
308
k(index++) = (double)val;
311
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
312
(getGeometry2dPtr()->handle());
316
catch (Standard_Failure& e) {
317
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
322
PyObject* BSplineCurve2dPy::getKnots(PyObject * args)
324
if (!PyArg_ParseTuple(args, ""))
327
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
328
(getGeometry2dPtr()->handle());
329
TColStd_Array1OfReal w(1,curve->NbKnots());
332
for (Standard_Integer i=w.Lower(); i<=w.Upper(); i++) {
333
knots.append(Py::Float(w(i)));
335
return Py::new_reference_to(knots);
337
catch (Standard_Failure& e) {
338
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
343
PyObject* BSplineCurve2dPy::setPole(PyObject * args)
348
if (!PyArg_ParseTuple(args, "iO!|d", &index, Base::Vector2dPy::type_object(), &p, &weight))
350
Base::Vector2d vec = Py::toVector2d(p);
351
gp_Pnt2d pnt(vec.x, vec.y);
353
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
354
(getGeometry2dPtr()->handle());
356
curve->SetPole(index,pnt);
358
curve->SetPole(index,pnt,weight);
361
catch (Standard_Failure& e) {
362
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
367
PyObject* BSplineCurve2dPy::getPole(PyObject * args)
370
if (!PyArg_ParseTuple(args, "i", &index))
373
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
374
(getGeometry2dPtr()->handle());
375
Standard_OutOfRange_Raise_if
376
(index < 1 || index > curve->NbPoles(), "Pole index out of range");
377
gp_Pnt2d pnt = curve->Pole(index);
378
return Py::new_reference_to(Base::Vector2dPy::create(pnt.X(), pnt.Y()));
380
catch (Standard_Failure& e) {
381
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
386
PyObject* BSplineCurve2dPy::getPoles(PyObject * args)
388
if (!PyArg_ParseTuple(args, ""))
391
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
392
(getGeometry2dPtr()->handle());
393
TColgp_Array1OfPnt2d p(1, (int)curve->NbPoles());
397
for (Standard_Integer i=p.Lower(); i<=p.Upper(); i++) {
399
poles.append(Base::Vector2dPy::create(pnt.X(), pnt.Y()));
401
return Py::new_reference_to(poles);
403
catch (Standard_Failure& e) {
404
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
409
PyObject* BSplineCurve2dPy::getPolesAndWeights(PyObject * args)
411
if (!PyArg_ParseTuple(args, ""))
414
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
415
(getGeometry2dPtr()->handle());
416
TColgp_Array1OfPnt2d p(1,curve->NbPoles());
418
TColStd_Array1OfReal w(1,curve->NbPoles());
422
for (Standard_Integer i=p.Lower(); i<=p.Upper(); i++) {
424
double weight = w(i);
426
t.setItem(0, Py::Float(pnt.X()));
427
t.setItem(1, Py::Float(pnt.Y()));
428
t.setItem(2, Py::Float(weight));
431
return Py::new_reference_to(poles);
433
catch (Standard_Failure& e) {
434
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
439
PyObject* BSplineCurve2dPy::setWeight(PyObject * args)
443
if (!PyArg_ParseTuple(args, "id", &index,&weight))
446
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
447
(getGeometry2dPtr()->handle());
448
curve->SetWeight(index,weight);
451
catch (Standard_Failure& e) {
452
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
457
PyObject* BSplineCurve2dPy::getWeight(PyObject * args)
460
if (!PyArg_ParseTuple(args, "i", &index))
463
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
464
(getGeometry2dPtr()->handle());
465
Standard_OutOfRange_Raise_if
466
(index < 1 || index > curve->NbPoles() , "Weight index out of range");
467
double weight = curve->Weight(index);
468
return Py_BuildValue("d", weight);
470
catch (Standard_Failure& e) {
471
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
476
PyObject* BSplineCurve2dPy::getWeights(PyObject * args)
478
if (!PyArg_ParseTuple(args, ""))
481
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
482
(getGeometry2dPtr()->handle());
483
TColStd_Array1OfReal w(1,curve->NbPoles());
486
for (Standard_Integer i=w.Lower(); i<=w.Upper(); i++) {
487
weights.append(Py::Float(w(i)));
489
return Py::new_reference_to(weights);
491
catch (Standard_Failure& e) {
492
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
497
PyObject* BSplineCurve2dPy::getResolution(PyObject * args)
500
if (!PyArg_ParseTuple(args, "d", &tol))
503
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
504
(getGeometry2dPtr()->handle());
506
curve->Resolution(tol,utol);
507
return Py_BuildValue("d",utol);
509
catch (Standard_Failure& e) {
510
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
515
PyObject* BSplineCurve2dPy::movePoint(PyObject * args)
520
if (!PyArg_ParseTuple(args, "dO!ii", &U, Base::Vector2dPy::type_object(),&pnt, &index1, &index2))
523
Base::Vector2d p = Py::toVector2d(pnt);
524
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
525
(getGeometry2dPtr()->handle());
527
curve->MovePoint(U, gp_Pnt2d(p.x,p.y), index1, index2, first, last);
528
return Py_BuildValue("(ii)",first, last);
530
catch (Standard_Failure& e) {
531
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
536
PyObject* BSplineCurve2dPy::setNotPeriodic(PyObject * args)
538
if (!PyArg_ParseTuple(args, ""))
541
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
542
(getGeometry2dPtr()->handle());
543
curve->SetNotPeriodic();
546
catch (Standard_Failure& e) {
547
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
552
PyObject* BSplineCurve2dPy::setPeriodic(PyObject * args)
554
if (!PyArg_ParseTuple(args, ""))
557
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
558
(getGeometry2dPtr()->handle());
559
curve->SetPeriodic();
562
catch (Standard_Failure& e) {
563
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
568
PyObject* BSplineCurve2dPy::setOrigin(PyObject * args)
571
if (!PyArg_ParseTuple(args, "i", &index))
574
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
575
(getGeometry2dPtr()->handle());
576
curve->SetOrigin(index);
579
catch (Standard_Failure& e) {
580
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
585
PyObject* BSplineCurve2dPy::getMultiplicity(PyObject * args)
588
if (!PyArg_ParseTuple(args, "i", &index))
591
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
592
(getGeometry2dPtr()->handle());
593
int mult = curve->Multiplicity(index);
594
return Py_BuildValue("i", mult);
596
catch (Standard_Failure& e) {
598
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
603
PyObject* BSplineCurve2dPy::getMultiplicities(PyObject * args)
605
if (!PyArg_ParseTuple(args, ""))
608
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
609
(getGeometry2dPtr()->handle());
610
TColStd_Array1OfInteger m(1,curve->NbKnots());
611
curve->Multiplicities(m);
613
for (Standard_Integer i=m.Lower(); i<=m.Upper(); i++) {
614
mults.append(Py::Long(m(i)));
616
return Py::new_reference_to(mults);
618
catch (Standard_Failure& e) {
619
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
624
Py::Long BSplineCurve2dPy::getDegree() const
626
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
627
(getGeometry2dPtr()->handle());
628
return Py::Long(curve->Degree());
631
Py::Long BSplineCurve2dPy::getMaxDegree() const
633
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
634
(getGeometry2dPtr()->handle());
635
return Py::Long(curve->MaxDegree());
638
Py::Long BSplineCurve2dPy::getNbPoles() const
640
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
641
(getGeometry2dPtr()->handle());
642
return Py::Long(curve->NbPoles());
645
Py::Long BSplineCurve2dPy::getNbKnots() const
647
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
648
(getGeometry2dPtr()->handle());
649
return Py::Long(curve->NbKnots());
652
Py::Object BSplineCurve2dPy::getStartPoint() const
654
Handle(Geom2d_BSplineCurve) c = Handle(Geom2d_BSplineCurve)::DownCast
655
(getGeometry2dPtr()->handle());
656
gp_Pnt2d pnt = c->StartPoint();
657
return Base::Vector2dPy::create(pnt.X(), pnt.Y());
660
Py::Object BSplineCurve2dPy::getEndPoint() const
662
Handle(Geom2d_BSplineCurve) c = Handle(Geom2d_BSplineCurve)::DownCast
663
(getGeometry2dPtr()->handle());
664
gp_Pnt2d pnt = c->EndPoint();
665
return Base::Vector2dPy::create(pnt.X(), pnt.Y());
668
Py::Object BSplineCurve2dPy::getFirstUKnotIndex() const
670
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
671
(getGeometry2dPtr()->handle());
672
return Py::Long(curve->FirstUKnotIndex());
675
Py::Object BSplineCurve2dPy::getLastUKnotIndex() const
677
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
678
(getGeometry2dPtr()->handle());
679
return Py::Long(curve->LastUKnotIndex());
682
Py::List BSplineCurve2dPy::getKnotSequence() const
684
Handle(Geom2d_BSplineCurve) curve = Handle(Geom2d_BSplineCurve)::DownCast
685
(getGeometry2dPtr()->handle());
686
Standard_Integer m = 0;
687
if (curve->IsPeriodic()) {
688
// knots=poles+2*degree-mult(1)+2
689
m = (int)(curve->NbPoles() + 2*curve->Degree() - curve->Multiplicity(1) + 2);
692
// knots=poles+degree+1
693
for (int i=1; i<= curve->NbKnots(); i++)
694
m += (int)curve->Multiplicity(i);
697
TColStd_Array1OfReal k(1,m);
698
curve->KnotSequence(k);
700
for (Standard_Integer i=k.Lower(); i<=k.Upper(); i++) {
701
list.append(Py::Float(k(i)));
706
PyObject* BSplineCurve2dPy::toBiArcs(PyObject * args)
708
double tolerance = 0.001;
709
if (!PyArg_ParseTuple(args, "d", &tolerance))
712
Geom2dBSplineCurve* curve = getGeom2dBSplineCurvePtr();
713
std::list<Geometry2d*> arcs;
714
arcs = curve->toBiArcs(tolerance);
717
for (auto arc : arcs) {
718
list.append(Py::asObject(arc->getPyObject()));
722
return Py::new_reference_to(list);
724
catch (Standard_Failure& e) {
725
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
730
PyObject* BSplineCurve2dPy::approximate(PyObject *args, PyObject *kwds)
733
Standard_Integer degMin=3;
734
Standard_Integer degMax=8;
735
const char* continuity = "C2";
737
const char* parType = "ChordLength";
738
PyObject* par = nullptr;
743
static const std::array<const char *, 11> kwds_interp{"Points", "DegMax", "Continuity", "Tolerance", "DegMin",
744
"ParamType", "Parameters", "LengthWeight", "CurvatureWeight",
745
"TorsionWeight", nullptr};
747
if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "O|isdisOddd",kwds_interp,
749
&continuity, &tol3d, °Min,
751
&weight1, &weight2, &weight3)) {
756
Py::Sequence list(obj);
757
TColgp_Array1OfPnt2d pnts(1,list.size());
758
Standard_Integer index = 1;
759
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
760
Base::Vector2d vec = Py::toVector2d(*it);
761
pnts(index++) = gp_Pnt2d(vec.x,vec.y);
764
if (degMin > degMax) {
765
Standard_Failure::Raise("DegMin must be lower or equal to DegMax");
769
std::string str = continuity;
772
else if (str == "G1")
774
else if (str == "C1")
776
else if (str == "G2")
778
else if (str == "C2")
780
else if (str == "C3")
782
else if (str == "CN")
787
if (weight1 || weight2 || weight3) {
788
// It seems that this function only works with Continuity = C0, C1 or C2
789
if (!(c == GeomAbs_C0 || c == GeomAbs_C1 || c == GeomAbs_C2)) {
793
Geom2dAPI_PointsToBSpline fit(pnts, weight1, weight2, weight3, degMax, c, tol3d);
794
Handle(Geom2d_BSplineCurve) spline = fit.Curve();
795
if (!spline.IsNull()) {
796
this->getGeom2dBSplineCurvePtr()->setHandle(spline);
800
Standard_Failure::Raise("Smoothing approximation failed");
801
return nullptr; // goes to the catch block
806
Py::Sequence plist(par);
807
TColStd_Array1OfReal parameters(1,plist.size());
808
Standard_Integer index = 1;
809
for (Py::Sequence::iterator it = plist.begin(); it != plist.end(); ++it) {
811
parameters(index++) = static_cast<double>(f);
814
Geom2dAPI_PointsToBSpline fit(pnts, parameters, degMin, degMax, c, tol3d);
815
Handle(Geom2d_BSplineCurve) spline = fit.Curve();
816
if (!spline.IsNull()) {
817
this->getGeom2dBSplineCurvePtr()->setHandle(spline);
821
Standard_Failure::Raise("Approximation with parameters failed");
822
return nullptr; // goes to the catch block
826
Approx_ParametrizationType pt;
827
std::string pstr = parType;
828
if (pstr == "Uniform")
829
pt = Approx_IsoParametric;
830
else if (pstr == "Centripetal")
831
pt = Approx_Centripetal;
833
pt = Approx_ChordLength;
835
Geom2dAPI_PointsToBSpline fit(pnts, pt, degMin, degMax, c, tol3d);
836
Handle(Geom2d_BSplineCurve) spline = fit.Curve();
837
if (!spline.IsNull()) {
838
this->getGeom2dBSplineCurvePtr()->setHandle(spline);
842
Standard_Failure::Raise("failed to approximate points");
843
return nullptr; // goes to the catch block
846
catch (Standard_Failure& e) {
847
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
852
PyObject* BSplineCurve2dPy::getCardinalSplineTangents(PyObject *args, PyObject *kwds)
858
static const std::array<const char *, 3> kwds_interp1 {"Points", "Parameter", nullptr};
859
if (Base::Wrapped_ParseTupleAndKeywords(args, kwds, "Od", kwds_interp1, &pts, ¶meter)) {
860
Py::Sequence list(pts);
861
std::vector<gp_Pnt2d> interpPoints;
862
interpPoints.reserve(list.size());
863
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
864
Base::Vector2d pnt = Py::toVector2d(*it);
865
interpPoints.emplace_back(pnt.x,pnt.y);
868
Geom2dBSplineCurve* bspline = this->getGeom2dBSplineCurvePtr();
869
std::vector<gp_Vec2d> tangents;
870
bspline->getCardinalSplineTangents(interpPoints, parameter, tangents);
873
for (gp_Vec2d it : tangents) {
874
vec.append(Base::Vector2dPy::create(it.X(), it.Y()));
876
return Py::new_reference_to(vec);
880
static const std::array<const char *, 3> kwds_interp2 {"Points", "Parameters", nullptr};
881
if (Base::Wrapped_ParseTupleAndKeywords(args, kwds, "OO", kwds_interp2, &pts, &tgs)) {
882
Py::Sequence list(pts);
883
std::vector<gp_Pnt2d> interpPoints;
884
interpPoints.reserve(list.size());
885
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
886
Base::Vector2d pnt = Py::toVector2d(*it);
887
interpPoints.emplace_back(pnt.x,pnt.y);
890
Py::Sequence list2(tgs);
891
std::vector<double> parameters;
892
parameters.reserve(list2.size());
893
for (Py::Sequence::iterator it = list2.begin(); it != list2.end(); ++it) {
895
parameters.push_back(static_cast<double>(p));
898
Geom2dBSplineCurve* bspline = this->getGeom2dBSplineCurvePtr();
899
std::vector<gp_Vec2d> tangents;
900
bspline->getCardinalSplineTangents(interpPoints, parameters, tangents);
903
for (gp_Vec2d it : tangents) {
904
vec.append(Base::Vector2dPy::create(it.X(), it.Y()));
906
return Py::new_reference_to(vec);
912
PyObject* BSplineCurve2dPy::interpolate(PyObject *args, PyObject *kwds)
915
PyObject* par = nullptr;
916
double tol3d = Precision::Approximation();
917
PyObject* periodic = Py_False;
918
PyObject* t1 = nullptr; PyObject* t2 = nullptr;
919
PyObject* ts = nullptr; PyObject* fl = nullptr;
921
static const std::array<const char *, 9> kwds_interp{"Points", "PeriodicFlag", "Tolerance", "InitialTangent",
922
"FinalTangent", "Tangents", "TangentFlags", "Parameters",
925
if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "O|O!dO!O!OOO",kwds_interp,
926
&obj, &PyBool_Type, &periodic, &tol3d,
927
Base::Vector2dPy::type_object(), &t1,
928
Base::Vector2dPy::type_object(), &t2,
934
Py::Sequence list(obj);
935
Handle(TColgp_HArray1OfPnt2d) interpolationPoints = new TColgp_HArray1OfPnt2d(1, list.size());
936
Standard_Integer index = 1;
937
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
938
Base::Vector2d pnt = Py::toVector2d(*it);
939
interpolationPoints->SetValue(index++, gp_Pnt2d(pnt.x,pnt.y));
942
if (interpolationPoints->Length() < 2) {
943
Standard_Failure::Raise("not enough points given");
946
Handle(TColStd_HArray1OfReal) parameters;
948
Py::Sequence plist(par);
949
parameters = new TColStd_HArray1OfReal(1, plist.size());
950
Standard_Integer pindex = 1;
951
for (Py::Sequence::iterator it = plist.begin(); it != plist.end(); ++it) {
953
parameters->SetValue(pindex++, static_cast<double>(f));
957
std::unique_ptr<Geom2dAPI_Interpolate> aBSplineInterpolation;
958
if (parameters.IsNull()) {
959
aBSplineInterpolation = std::make_unique<Geom2dAPI_Interpolate>(
961
Base::asBoolean(periodic), tol3d
965
aBSplineInterpolation = std::make_unique<Geom2dAPI_Interpolate>(
966
interpolationPoints, parameters,
967
Base::asBoolean(periodic), tol3d
972
Base::Vector2d v1 = Py::toVector2d(t1);
973
Base::Vector2d v2 = Py::toVector2d(t2);
974
gp_Vec2d initTangent(v1.x,v1.y), finalTangent(v2.x,v2.y);
975
aBSplineInterpolation->Load(initTangent, finalTangent);
978
Py::Sequence tlist(ts);
979
TColgp_Array1OfVec2d tangents(1, tlist.size());
980
Standard_Integer index = 1;
981
for (Py::Sequence::iterator it = tlist.begin(); it != tlist.end(); ++it) {
982
Base::Vector2d vec = Py::toVector2d(*it);
983
tangents.SetValue(index++, gp_Vec2d(vec.x,vec.y));
986
Py::Sequence flist(fl);
987
Handle(TColStd_HArray1OfBoolean) tangentFlags = new TColStd_HArray1OfBoolean(1, flist.size());
988
Standard_Integer findex = 1;
989
for (Py::Sequence::iterator it = flist.begin(); it != flist.end(); ++it) {
990
Py::Boolean flag(*it);
991
tangentFlags->SetValue(findex++, static_cast<bool>(flag) ? Standard_True : Standard_False);
994
aBSplineInterpolation->Load(tangents, tangentFlags);
997
aBSplineInterpolation->Perform();
998
if (aBSplineInterpolation->IsDone()) {
999
Handle(Geom2d_BSplineCurve) aBSplineCurve(aBSplineInterpolation->Curve());
1000
this->getGeom2dBSplineCurvePtr()->setHandle(aBSplineCurve);
1004
Standard_Failure::Raise("failed to interpolate points");
1005
return nullptr; // goes to the catch block
1008
catch (Standard_Failure& e) {
1009
std::string err = e.GetMessageString();
1010
if (err.empty()) err = e.DynamicType()->Name();
1011
PyErr_SetString(PartExceptionOCCError, err.c_str());
1016
PyObject* BSplineCurve2dPy::buildFromPoles(PyObject *args)
1020
PyObject* periodic = Py_False;
1021
PyObject* interpolate = Py_False;
1022
if (!PyArg_ParseTuple(args, "O|O!iO!",&obj, &PyBool_Type, &periodic, °ree, &PyBool_Type, interpolate))
1025
Py::Sequence list(obj);
1026
TColgp_Array1OfPnt2d poles(1, list.size());
1027
Standard_Integer index = 1;
1028
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
1029
Base::Vector2d pnt = Py::toVector2d(*it);
1030
poles(index++) = gp_Pnt2d(pnt.x,pnt.y);
1033
if (poles.Length() <= degree)
1034
degree = poles.Length()-1;
1036
if (Base::asBoolean(periodic)) {
1039
if (Base::asBoolean(interpolate)) {
1041
len = poles.Length() - mult + 2;
1045
len = poles.Length() + 1;
1047
TColStd_Array1OfReal knots(1, len);
1048
TColStd_Array1OfInteger mults(1, len);
1049
for (int i=1; i<=knots.Length(); i++){
1050
knots.SetValue(i,(double)(i-1)/(knots.Length()-1));
1051
mults.SetValue(i,1);
1053
mults.SetValue(1, mult);
1054
mults.SetValue(knots.Length(), mult);
1056
Handle(Geom2d_BSplineCurve) spline = new Geom2d_BSplineCurve(poles, knots, mults, degree, Standard_True);
1057
if (!spline.IsNull()) {
1058
this->getGeom2dBSplineCurvePtr()->setHandle(spline);
1062
Standard_Failure::Raise("failed to create spline");
1063
return nullptr; // goes to the catch block
1067
TColStd_Array1OfReal knots(1, poles.Length()+degree+1-2*(degree));
1068
TColStd_Array1OfInteger mults(1, poles.Length()+degree+1-2*(degree));
1069
for (int i=1; i<=knots.Length(); i++){
1070
knots.SetValue(i,(double)(i-1)/(knots.Length()-1));
1071
mults.SetValue(i,1);
1073
mults.SetValue(1, degree+1);
1074
mults.SetValue(knots.Length(), degree+1);
1076
Handle(Geom2d_BSplineCurve) spline = new Geom2d_BSplineCurve(poles, knots, mults, degree, Standard_False);
1077
if (!spline.IsNull()) {
1078
this->getGeom2dBSplineCurvePtr()->setHandle(spline);
1082
Standard_Failure::Raise("failed to create spline");
1083
return nullptr; // goes to the catch block
1087
catch (Standard_Failure& e) {
1088
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1093
PyObject* BSplineCurve2dPy::buildFromPolesMultsKnots(PyObject *args, PyObject *keywds)
1095
static const std::array<const char *, 7> kwlist{"poles", "mults", "knots", "periodic", "degree", "weights",
1097
PyObject* periodic = Py_False;
1098
PyObject* poles = Py_None;
1099
PyObject* mults = Py_None;
1100
PyObject* knots = Py_None;
1101
PyObject* weights = Py_None;
1103
int number_of_poles = 0;
1104
int number_of_knots = 0;
1105
int sum_of_mults = 0;
1106
if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, "O|OOO!iO", kwlist,
1107
&poles, &mults, &knots,
1108
&PyBool_Type, &periodic,
1109
°ree, &weights)) {
1113
// poles have to be present
1114
Py::Sequence list(poles);
1116
number_of_poles = list.size();
1117
if ((number_of_poles) < 2) {
1118
Standard_Failure::Raise("need two or more poles");
1121
TColgp_Array1OfPnt2d occpoles(1, number_of_poles);
1122
Standard_Integer index = 1;
1123
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
1124
Base::Vector2d pnt = Py::toVector2d(*it);
1125
occpoles(index++) = gp_Pnt2d(pnt.x,pnt.y);
1127
//Calculate the number of knots
1128
if (mults != Py_None && knots != Py_None) {
1129
number_of_knots = PyObject_Length(mults);
1130
if (PyObject_Length(knots) != number_of_knots) {
1131
Standard_Failure::Raise("number of knots and mults mismatch");
1136
if (mults != Py_None) {
1137
number_of_knots = PyObject_Length(mults);
1140
if (knots != Py_None) { number_of_knots = PyObject_Length(knots); }
1141
else { //guess number of knots
1142
if (Base::asBoolean(periodic)) {
1143
if (number_of_poles < degree) {degree = number_of_poles+1;}
1144
number_of_knots = number_of_poles+1;
1147
if (number_of_poles <= degree) {degree = number_of_poles-1;}
1148
number_of_knots = number_of_poles-degree+1;
1153
TColStd_Array1OfInteger occmults(1,number_of_knots);
1154
TColStd_Array1OfReal occknots(1,number_of_knots);
1155
TColStd_Array1OfReal occweights(1,number_of_poles);
1156
if (mults != Py_None) { //mults are given
1157
Py::Sequence multssq(mults);
1158
Standard_Integer index = 1;
1159
for (Py::Sequence::iterator it = multssq.begin(); it != multssq.end() && index <= occmults.Length(); ++it) {
1161
if (index < occmults.Length() || !Base::asBoolean(periodic)) {
1162
sum_of_mults += (int)mult; //sum up the mults to compare them against the number of poles later
1164
occmults(index++) = mult;
1167
else { //mults are 1 or degree+1 at the ends
1168
for (int i=1; i<=occmults.Length(); i++){
1169
occmults.SetValue(i,1);
1171
if (!Base::asBoolean(periodic) && occmults.Length() > 0) {
1172
occmults.SetValue(1, degree+1);
1173
occmults.SetValue(occmults.Length(), degree+1);
1174
sum_of_mults = occmults.Length()+2*degree;
1176
else { sum_of_mults = occmults.Length()-1;}
1178
if (knots != Py_None) { //knots are given
1179
Py::Sequence knotssq(knots);
1181
for (Py::Sequence::iterator it = knotssq.begin(); it != knotssq.end() && index <= occknots.Length(); ++it) {
1182
Py::Float knot(*it);
1183
occknots(index++) = knot;
1186
else { // knotes are uniformly spaced 0..1 if not given
1187
for (int i=1; i<=occknots.Length(); i++){
1188
occknots.SetValue(i,(double)(i-1)/(occknots.Length()-1));
1191
if (weights != Py_None) { //weights are given
1192
if (PyObject_Length(weights) != number_of_poles) {
1193
Standard_Failure::Raise("number of poles and weights mismatch");
1195
} //complain about mismatch
1196
Py::Sequence weightssq(weights);
1197
Standard_Integer index = 1;
1198
for (Py::Sequence::iterator it = weightssq.begin(); it != weightssq.end(); ++it) {
1199
Py::Float weight(*it);
1200
occweights(index++) = weight;
1203
else { // weights are 1.0
1204
for (int i=1; i<=occweights.Length(); i++){
1205
occweights.SetValue(i,1.0);
1208
// check if the number of poles matches the sum of mults
1209
if (((Base::asBoolean(periodic)) && sum_of_mults != number_of_poles) ||
1210
(!Base::asBoolean(periodic) && sum_of_mults - degree -1 != number_of_poles)) {
1211
Standard_Failure::Raise("number of poles and sum of mults mismatch");
1215
Handle(Geom2d_BSplineCurve) spline = new Geom2d_BSplineCurve(occpoles, occweights, occknots,
1216
occmults, degree, Base::asBoolean(periodic));
1217
if (!spline.IsNull()) {
1218
this->getGeom2dBSplineCurvePtr()->setHandle(spline);
1222
Standard_Failure::Raise("failed to create spline");
1223
return nullptr; // goes to the catch block
1226
catch (const Standard_Failure& e) {
1227
Standard_CString msg = e.GetMessageString();
1228
PyErr_SetString(PartExceptionOCCError, msg ? msg : "");
1233
PyObject* BSplineCurve2dPy::toBezier(PyObject *args)
1235
if (!PyArg_ParseTuple(args, ""))
1238
Handle(Geom2d_BSplineCurve) spline = Handle(Geom2d_BSplineCurve)::DownCast
1239
(this->getGeom2dBSplineCurvePtr()->handle());
1240
Geom2dConvert_BSplineCurveToBezierCurve crt(spline);
1243
Standard_Integer arcs = crt.NbArcs();
1244
for (Standard_Integer i=1; i<=arcs; i++) {
1245
Handle(Geom2d_BezierCurve) bezier = crt.Arc(i);
1246
list.append(Py::asObject(new BezierCurve2dPy(new Geom2dBezierCurve(bezier))));
1249
return Py::new_reference_to(list);
1252
PyObject* BSplineCurve2dPy::join(PyObject *args)
1255
if (!PyArg_ParseTuple(args, "O!", &BSplineCurve2dPy::Type, &c))
1258
Geom2dBSplineCurve* curve1 = this->getGeom2dBSplineCurvePtr();
1259
BSplineCurve2dPy* curve2 = static_cast<BSplineCurve2dPy*>(c);
1260
Handle(Geom2d_BSplineCurve) spline = Handle(Geom2d_BSplineCurve)::DownCast
1261
(curve2->getGeom2dBSplineCurvePtr()->handle());
1263
bool ok = curve1->join(spline);
1265
return PyBool_FromLong(ok ? 1 : 0);
1268
PyObject* BSplineCurve2dPy::makeC1Continuous(PyObject *args)
1270
double tol = Precision::Approximation();
1271
if (!PyArg_ParseTuple(args, "|d", &tol))
1275
Geom2dBSplineCurve* spline = this->getGeom2dBSplineCurvePtr();
1276
spline->makeC1Continuous(tol);
1279
catch (Standard_Failure& e) {
1280
std::string err = e.GetMessageString();
1281
if (err.empty()) err = e.DynamicType()->Name();
1282
PyErr_SetString(PartExceptionOCCError, err.c_str());
1287
PyObject* BSplineCurve2dPy::getCustomAttributes(const char* /*attr*/) const
1292
int BSplineCurve2dPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)