23
#include "PreCompiled.h"
25
# include <Approx_Curve3d.hxx>
26
# include <BRepAdaptor_CompCurve.hxx>
27
# include <BRepBuilderAPI_FindPlane.hxx>
28
# include <BRepBuilderAPI_MakeWire.hxx>
29
# include <BRepGProp.hxx>
30
# include <BRepOffsetAPI_MakeOffset.hxx>
31
# include <BRepTools_WireExplorer.hxx>
32
# include <GProp_GProps.hxx>
33
# include <GProp_PrincipalProps.hxx>
34
# include <GCPnts_QuasiUniformAbscissa.hxx>
35
# include <GCPnts_QuasiUniformDeflection.hxx>
36
# include <GCPnts_TangentialDeflection.hxx>
37
# include <GCPnts_UniformAbscissa.hxx>
38
# include <GCPnts_UniformDeflection.hxx>
39
# include <Precision.hxx>
40
# include <ShapeAlgo_AlgoContainer.hxx>
41
# include <ShapeFix_Wire.hxx>
44
# include <TopoDS_Wire.hxx>
46
#include <BRepOffsetAPI_MakeEvolved.hxx>
48
#include <Base/GeometryPyCXX.h>
49
#include <Base/PyWrapParseTupleAndKeywords.h>
51
#include <Mod/Part/App/BSplineCurvePy.h>
52
#include <Mod/Part/App/TopoShapeFacePy.h>
53
#include <Mod/Part/App/TopoShapeWirePy.h>
54
#include <Mod/Part/App/TopoShapeWirePy.cpp>
62
extern Py::Object shape2pyshape(const TopoDS_Shape &shape);
67
std::string TopoShapeWirePy::representation() const
69
std::stringstream str;
70
str << "<Wire object at " << getTopoShapePtr() << ">";
75
PyObject *TopoShapeWirePy::PyMake(struct _typeobject *, PyObject *, PyObject *)
78
return new TopoShapeWirePy(new TopoShape);
82
int TopoShapeWirePy::PyInit(PyObject* args, PyObject* )
84
if (PyArg_ParseTuple(args, "")) {
86
getTopoShapePtr()->setShape(TopoDS_Wire());
92
if (PyArg_ParseTuple(args, "O!", &(Part::TopoShapePy::Type), &pcObj)) {
93
BRepBuilderAPI_MakeWire mkWire;
94
const TopoDS_Shape& sh = static_cast<Part::TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape();
96
PyErr_SetString(PyExc_TypeError, "given shape is invalid");
99
if (sh.ShapeType() == TopAbs_EDGE)
100
mkWire.Add(TopoDS::Edge(sh));
101
else if (sh.ShapeType() == TopAbs_WIRE)
102
mkWire.Add(TopoDS::Wire(sh));
104
PyErr_SetString(PyExc_TypeError, "shape is neither edge nor wire");
109
getTopoShapePtr()->setShape(mkWire.Wire());
112
catch (Standard_Failure& e) {
114
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
120
if (PyArg_ParseTuple(args, "O", &pcObj)) {
121
if(!Py::Object(pcObj).isList() && !Py::Object(pcObj).isTuple()) {
122
PyErr_SetString(PyExc_TypeError, "object is neither a list nor a tuple");
126
BRepBuilderAPI_MakeWire mkWire;
127
Py::Sequence list(pcObj);
128
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
129
PyObject* item = (*it).ptr();
130
if (PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) {
131
const TopoDS_Shape& sh = static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape();
133
PyErr_SetString(PyExc_TypeError, "given shape is invalid");
136
if (sh.ShapeType() == TopAbs_EDGE)
137
mkWire.Add(TopoDS::Edge(sh));
138
else if (sh.ShapeType() == TopAbs_WIRE)
139
mkWire.Add(TopoDS::Wire(sh));
141
PyErr_SetString(PyExc_TypeError, "shape is neither edge nor wire");
146
PyErr_SetString(PyExc_TypeError, "item is not a shape");
152
getTopoShapePtr()->setShape(mkWire.Wire());
155
catch (Standard_Failure& e) {
157
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
162
PyErr_SetString(PartExceptionOCCError, "edge or wire or list of edges and wires expected");
166
PyObject* TopoShapeWirePy::add(PyObject *args)
169
if (!PyArg_ParseTuple(args, "O!",&(TopoShapePy::Type), &edge))
171
const TopoDS_Wire& w = TopoDS::Wire(getTopoShapePtr()->getShape());
172
BRepBuilderAPI_MakeWire mkWire(w);
174
const TopoDS_Shape& sh = static_cast<Part::TopoShapePy*>(edge)->getTopoShapePtr()->getShape();
176
PyErr_SetString(PyExc_TypeError, "given shape is invalid");
179
if (sh.ShapeType() == TopAbs_EDGE)
180
mkWire.Add(TopoDS::Edge(sh));
181
else if (sh.ShapeType() == TopAbs_WIRE)
182
mkWire.Add(TopoDS::Wire(sh));
184
PyErr_SetString(PyExc_TypeError, "shape is neither edge nor wire");
189
getTopoShapePtr()->setShape(mkWire.Wire());
192
catch (Standard_Failure& e) {
194
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
199
PyObject* TopoShapeWirePy::fixWire(PyObject *args)
201
PyObject* face=nullptr;
202
double tol = Precision::Confusion();
203
if (!PyArg_ParseTuple(args, "|O!d",&(TopoShapeFacePy::Type), &face, &tol))
208
const TopoDS_Wire& w = TopoDS::Wire(getTopoShapePtr()->getShape());
211
const TopoDS_Face& f = TopoDS::Face(static_cast<TopoShapePy*>(face)->getTopoShapePtr()->getShape());
212
aFix.Init(w, f, tol);
215
aFix.SetPrecision(tol);
222
getTopoShapePtr()->setShape(aFix.Wire());
226
catch (Standard_Failure& e) {
228
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
233
PyObject* TopoShapeWirePy::makeOffset(PyObject *args)
236
if (!PyArg_ParseTuple(args, "d",&dist))
238
const TopoDS_Wire& w = TopoDS::Wire(getTopoShapePtr()->getShape());
239
BRepBuilderAPI_FindPlane findPlane(w);
240
if (!findPlane.Found()) {
241
PyErr_SetString(PartExceptionOCCError, "No planar wire");
245
BRepOffsetAPI_MakeOffset mkOffset(w);
246
mkOffset.Perform(dist);
248
return new TopoShapePy(new TopoShape(mkOffset.Shape()));
251
PyObject* TopoShapeWirePy::makePipe(PyObject *args)
254
if (PyArg_ParseTuple(args, "O!", &(Part::TopoShapePy::Type), &pShape)) {
256
TopoDS_Shape profile = static_cast<TopoShapePy*>(pShape)->getTopoShapePtr()->getShape();
257
TopoDS_Shape shape = this->getTopoShapePtr()->makePipe(profile);
258
return new TopoShapePy(new TopoShape(shape));
260
catch (Standard_Failure& e) {
262
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
270
PyObject* TopoShapeWirePy::makePipeShell(PyObject *args)
273
PyObject *make_solid = Py_False;
274
PyObject *is_Frenet = Py_False;
277
if (PyArg_ParseTuple(args, "O|O!O!i", &obj,
278
&PyBool_Type, &make_solid,
279
&PyBool_Type, &is_Frenet,
282
TopTools_ListOfShape sections;
283
Py::Sequence list(obj);
284
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
285
if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) {
286
const TopoDS_Shape& shape = static_cast<TopoShapePy*>((*it).ptr())->getTopoShapePtr()->getShape();
287
sections.Append(shape);
290
TopoDS_Shape shape = this->getTopoShapePtr()->makePipeShell(sections,
291
Base::asBoolean(make_solid), Base::asBoolean(is_Frenet), transition);
292
return new TopoShapePy(new TopoShape(shape));
294
catch (Standard_Failure& e) {
296
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
311
PyObject* TopoShapeWirePy::makeEvolved(PyObject *args, PyObject *kwds)
314
PyObject* AxeProf = Py_True;
315
PyObject* Solid = Py_False;
316
PyObject* ProfOnSpine = Py_False;
317
int JoinType = int(GeomAbs_Arc);
318
double Tolerance = 0.0000001;
320
static const std::array<const char *, 7> kwds_evolve{"Profile", "Join", "AxeProf", "Solid", "ProfOnSpine",
321
"Tolerance", nullptr};
322
if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "O!|iO!O!O!d", kwds_evolve,
323
&TopoShapeWirePy::Type, &Profile, &JoinType,
324
&PyBool_Type, &AxeProf, &PyBool_Type, &Solid,
325
&PyBool_Type, &ProfOnSpine, &Tolerance)) {
329
const TopoDS_Wire& spine = TopoDS::Wire(getTopoShapePtr()->getShape());
330
BRepBuilderAPI_FindPlane findPlane(spine);
331
if (!findPlane.Found()) {
332
PyErr_SetString(PartExceptionOCCError, "No planar wire");
336
const TopoDS_Wire& profile = TopoDS::Wire(static_cast<TopoShapeWirePy*>(Profile)->getTopoShapePtr()->getShape());
338
GeomAbs_JoinType joinType;
340
case GeomAbs_Tangent:
341
joinType = GeomAbs_Tangent;
343
case GeomAbs_Intersection:
344
joinType = GeomAbs_Intersection;
347
joinType = GeomAbs_Arc;
352
BRepOffsetAPI_MakeEvolved evolved(spine, profile, joinType,
353
Base::asBoolean(AxeProf),
354
Base::asBoolean(Solid),
355
Base::asBoolean(ProfOnSpine),
357
TopoDS_Shape shape = evolved.Shape();
358
return Py::new_reference_to(shape2pyshape(shape));
360
catch (Standard_Failure& e) {
361
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
366
PyObject* TopoShapeWirePy::makeHomogenousWires(PyObject *args)
369
if (!PyArg_ParseTuple(args, "O!",&(Part::TopoShapeWirePy::Type),&wire))
373
const TopoDS_Wire& w1 = TopoDS::Wire(getTopoShapePtr()->getShape());
374
const TopoDS_Wire& w2 = TopoDS::Wire(static_cast<TopoShapePy*>(wire)->getTopoShapePtr()->getShape());
375
ShapeAlgo_AlgoContainer shapeAlgo;
376
if (shapeAlgo.HomoWires(w1,w2,o1,o2,Standard_True)) {
377
getTopoShapePtr()->setShape(o1);
378
return new TopoShapeWirePy(new TopoShape(o2));
385
catch (Standard_Failure& e) {
387
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
392
PyObject* TopoShapeWirePy::approximate(PyObject *args, PyObject *kwds)
394
double tol2d = gp::Resolution();
395
double tol3d = 0.0001;
396
int maxseg=10, maxdeg=3;
398
static const std::array<const char *, 5> kwds_approx{"Tol2d", "Tol3d", "MaxSegments", "MaxDegree", nullptr};
399
if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "|ddii", kwds_approx, &tol2d, &tol3d, &maxseg, &maxdeg)) {
403
BRepAdaptor_CompCurve adapt(TopoDS::Wire(getTopoShapePtr()->getShape()));
404
auto hcurve = adapt.Trim(adapt.FirstParameter(),
405
adapt.LastParameter(),
407
Approx_Curve3d approx(hcurve, tol3d, GeomAbs_C0, maxseg, maxdeg);
408
if (approx.IsDone()) {
409
return new BSplineCurvePy(new GeomBSplineCurve(approx.Curve()));
412
PyErr_SetString(PartExceptionOCCError, "failed to approximate wire");
416
catch (Standard_Failure&) {
417
PyErr_SetString(PartExceptionOCCError, "failed to approximate wire");
422
PyObject* TopoShapeWirePy::discretize(PyObject *args, PyObject *kwds)
425
BRepAdaptor_CompCurve adapt(TopoDS::Wire(getTopoShapePtr()->getShape()));
426
bool uniformAbscissaPoints = false;
427
bool uniformAbscissaDistance = false;
429
double distance = -1;
430
double first = adapt.FirstParameter();
431
double last = adapt.LastParameter();
434
PyObject* dist_or_num;
435
if (PyArg_ParseTuple(args, "O", &dist_or_num)) {
436
if (PyLong_Check(dist_or_num)) {
437
numPoints = PyLong_AsLong(dist_or_num);
438
uniformAbscissaPoints = true;
440
else if (PyFloat_Check(dist_or_num)) {
441
distance = PyFloat_AsDouble(dist_or_num);
442
uniformAbscissaDistance = true;
445
PyErr_SetString(PyExc_TypeError, "Either int or float expected");
451
static const std::array<const char *, 4> kwds_numPoints{"Number", "First", "Last", nullptr};
453
if (Base::Wrapped_ParseTupleAndKeywords(args, kwds, "i|dd", kwds_numPoints, &numPoints, &first, &last)) {
454
uniformAbscissaPoints = true;
458
static const std::array<const char *, 4> kwds_Distance{"Distance", "First", "Last", nullptr};
460
if (Base::Wrapped_ParseTupleAndKeywords(args, kwds, "d|dd", kwds_Distance, &distance, &first, &last)) {
461
uniformAbscissaDistance = true;
466
if (uniformAbscissaPoints || uniformAbscissaDistance) {
467
GCPnts_UniformAbscissa discretizer;
468
if (uniformAbscissaPoints)
469
discretizer.Initialize (adapt, numPoints, first, last);
471
discretizer.Initialize (adapt, distance, first, last);
473
if (discretizer.IsDone () && discretizer.NbPoints () > 0) {
475
int nbPoints = discretizer.NbPoints ();
476
for (int i=1; i<=nbPoints; i++) {
477
gp_Pnt p = adapt.Value (discretizer.Parameter (i));
478
points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z())));
481
return Py::new_reference_to(points);
484
PyErr_SetString(PartExceptionOCCError, "Discretization of wire failed");
490
static const std::array<const char *, 4> kwds_Deflection{"Deflection", "First", "Last", nullptr};
493
if (Base::Wrapped_ParseTupleAndKeywords(args, kwds, "d|dd", kwds_Deflection, &deflection, &first, &last)) {
494
GCPnts_UniformDeflection discretizer(adapt, deflection, first, last);
495
if (discretizer.IsDone () && discretizer.NbPoints () > 0) {
497
int nbPoints = discretizer.NbPoints ();
498
for (int i=1; i<=nbPoints; i++) {
499
gp_Pnt p = discretizer.Value (i);
500
points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z())));
503
return Py::new_reference_to(points);
506
PyErr_SetString(PartExceptionOCCError, "Discretization of wire failed");
512
static const std::array<const char *, 6> kwds_TangentialDeflection{"Angular", "Curvature", "First", "Last",
517
int minimumPoints = 2;
518
if (Base::Wrapped_ParseTupleAndKeywords(args, kwds, "dd|ddi", kwds_TangentialDeflection,
519
&angular, &curvature, &first, &last, &minimumPoints)) {
520
GCPnts_TangentialDeflection discretizer(adapt, first, last, angular, curvature, minimumPoints);
521
if (discretizer.NbPoints () > 0) {
523
int nbPoints = discretizer.NbPoints ();
524
for (int i=1; i<=nbPoints; i++) {
525
gp_Pnt p = discretizer.Value (i);
526
points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z())));
529
return Py::new_reference_to(points);
532
PyErr_SetString(PartExceptionOCCError, "Discretization of wire failed");
538
static const std::array<const char *, 4> kwds_QuasiNumPoints{"QuasiNumber", "First", "Last", nullptr};
541
if (Base::Wrapped_ParseTupleAndKeywords(args, kwds, "i|dd", kwds_QuasiNumPoints,
542
&quasiNumPoints, &first, &last)) {
543
GCPnts_QuasiUniformAbscissa discretizer(adapt, quasiNumPoints, first, last);
544
if (discretizer.NbPoints () > 0) {
546
int nbPoints = discretizer.NbPoints ();
547
for (int i=1; i<=nbPoints; i++) {
548
gp_Pnt p = adapt.Value (discretizer.Parameter (i));
549
points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z())));
552
return Py::new_reference_to(points);
555
PyErr_SetString(PartExceptionOCCError, "Discretization of wire failed");
561
static const std::array<const char *, 4> kwds_QuasiDeflection{"QuasiDeflection", "First", "Last", nullptr};
563
double quasiDeflection;
564
if (Base::Wrapped_ParseTupleAndKeywords(args, kwds, "d|dd", kwds_QuasiDeflection,
565
&quasiDeflection, &first, &last)) {
566
GCPnts_QuasiUniformDeflection discretizer(adapt, quasiDeflection, first, last);
567
if (discretizer.NbPoints () > 0) {
569
int nbPoints = discretizer.NbPoints ();
570
for (int i=1; i<=nbPoints; i++) {
571
gp_Pnt p = discretizer.Value (i);
572
points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z())));
575
return Py::new_reference_to(points);
578
PyErr_SetString(PartExceptionOCCError, "Discretization of wire failed");
583
catch (const Base::Exception& e) {
584
PyErr_SetString(PartExceptionOCCError, e.what());
588
PyErr_SetString(PartExceptionOCCError,"Wrong arguments");
592
Py::String TopoShapeWirePy::getContinuity() const
594
BRepAdaptor_CompCurve adapt(TopoDS::Wire(getTopoShapePtr()->getShape()));
596
switch (adapt.Continuity()) {
620
return Py::String(cont);
623
Py::Object TopoShapeWirePy::getMass() const
626
BRepGProp::LinearProperties(getTopoShapePtr()->getShape(), props);
627
double c = props.Mass();
631
Py::Object TopoShapeWirePy::getCenterOfMass() const
634
BRepGProp::LinearProperties(getTopoShapePtr()->getShape(), props);
635
gp_Pnt c = props.CentreOfMass();
636
return Py::Vector(Base::Vector3d(c.X(),c.Y(),c.Z()));
639
Py::Object TopoShapeWirePy::getMatrixOfInertia() const
642
BRepGProp::LinearProperties(getTopoShapePtr()->getShape(), props);
643
gp_Mat m = props.MatrixOfInertia();
645
for (int i=0; i<3; i++) {
646
for (int j=0; j<3; j++) {
647
mat[i][j] = m(i+1,j+1);
650
return Py::Matrix(mat);
653
Py::Object TopoShapeWirePy::getStaticMoments() const
656
BRepGProp::LinearProperties(getTopoShapePtr()->getShape(), props);
657
Standard_Real lx,ly,lz;
658
props.StaticMoments(lx,ly,lz);
660
tuple.setItem(0, Py::Float(lx));
661
tuple.setItem(1, Py::Float(ly));
662
tuple.setItem(2, Py::Float(lz));
666
Py::Dict TopoShapeWirePy::getPrincipalProperties() const
669
BRepGProp::LinearProperties(getTopoShapePtr()->getShape(), props);
670
GProp_PrincipalProps pprops = props.PrincipalProperties();
673
dict.setItem("SymmetryAxis", Py::Boolean(pprops.HasSymmetryAxis() ? true : false));
674
dict.setItem("SymmetryPoint", Py::Boolean(pprops.HasSymmetryPoint() ? true : false));
675
Standard_Real lx,ly,lz;
676
pprops.Moments(lx,ly,lz);
678
tuple.setItem(0, Py::Float(lx));
679
tuple.setItem(1, Py::Float(ly));
680
tuple.setItem(2, Py::Float(lz));
681
dict.setItem("Moments",tuple);
682
dict.setItem("FirstAxisOfInertia",Py::Vector(Base::convertTo
683
<Base::Vector3d>(pprops.FirstAxisOfInertia())));
684
dict.setItem("SecondAxisOfInertia",Py::Vector(Base::convertTo
685
<Base::Vector3d>(pprops.SecondAxisOfInertia())));
686
dict.setItem("ThirdAxisOfInertia",Py::Vector(Base::convertTo
687
<Base::Vector3d>(pprops.ThirdAxisOfInertia())));
689
Standard_Real Rxx,Ryy,Rzz;
690
pprops.RadiusOfGyration(Rxx,Ryy,Rzz);
692
rog.setItem(0, Py::Float(Rxx));
693
rog.setItem(1, Py::Float(Ryy));
694
rog.setItem(2, Py::Float(Rzz));
695
dict.setItem("RadiusOfGyration",rog);
699
Py::List TopoShapeWirePy::getOrderedEdges() const
703
BRepTools_WireExplorer xp(TopoDS::Wire(getTopoShapePtr()->getShape()));
705
ret.append(shape2pyshape(xp.Current()));
712
Py::List TopoShapeWirePy::getOrderedVertexes() const
716
TopoDS_Wire wire = TopoDS::Wire(getTopoShapePtr()->getShape());
717
BRepTools_WireExplorer xp(wire);
719
ret.append(shape2pyshape(xp.CurrentVertex()));
724
TopoDS_Vertex Vfirst, Vlast;
725
TopExp::Vertices(wire, Vfirst, Vlast);
726
if (!Vfirst.IsNull() && !Vlast.IsNull()) {
727
if (!Vfirst.IsSame(Vlast)) {
728
ret.append(shape2pyshape(Vlast));
735
PyObject *TopoShapeWirePy::getCustomAttributes(const char* ) const
740
int TopoShapeWirePy::setCustomAttributes(const char* , PyObject* )