FreeCAD

Форк
0
/
TopoShapeEdgePyImp.cpp 
1096 строк · 37.1 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2008 Jürgen Riegel <juergen.riegel@web.de>              *
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 <BRep_Builder.hxx>
26
# include <BRep_Tool.hxx>
27
# include <BRepAdaptor_Curve.hxx>
28
# include <BRepBuilderAPI_MakeEdge.hxx>
29
# include <BRepBuilderAPI_MakeWire.hxx>
30
# include <BRepGProp.hxx>
31
# include <BRepLProp_CLProps.hxx>
32
# include <BRepLProp_CurveTool.hxx>
33
# include <GProp_GProps.hxx>
34
# include <GProp_PrincipalProps.hxx>
35
# include <Geom_Circle.hxx>
36
# include <Geom_Curve.hxx>
37
# include <Geom_Ellipse.hxx>
38
# include <Geom_Hyperbola.hxx>
39
# include <Geom_Parabola.hxx>
40
# include <Geom_Line.hxx>
41
# include <Geom_OffsetCurve.hxx>
42
# include <Geom_Surface.hxx>
43
# include <Geom2d_Curve.hxx>
44
# include <TopLoc_Location.hxx>
45
# include <Poly_Polygon3D.hxx>
46
# include <Poly_Triangulation.hxx>
47
# include <Poly_PolygonOnTriangulation.hxx>
48
# include <TColStd_Array1OfReal.hxx>
49
# include <TopExp.hxx>
50
# include <TopoDS.hxx>
51
# include <TopoDS_Edge.hxx>
52
# include <TopoDS_Shape.hxx>
53
# include <TopoDS_Vertex.hxx>
54
# include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
55
# include <ShapeAnalysis_Edge.hxx>
56
# include <Standard_Failure.hxx>
57
# include <Standard_Version.hxx>
58
# include <GProp_GProps.hxx>
59
# include <GCPnts_AbscissaPoint.hxx>
60
# include <GCPnts_QuasiUniformAbscissa.hxx>
61
# include <GCPnts_QuasiUniformDeflection.hxx>
62
# include <GCPnts_TangentialDeflection.hxx>
63
# include <GCPnts_UniformAbscissa.hxx>
64
# include <GCPnts_UniformDeflection.hxx>
65
#endif // _PreComp_
66

67
#include <Base/GeometryPyCXX.h>
68
#include <Base/PyWrapParseTupleAndKeywords.h>
69
#include <Base/Vector3D.h>
70
#include <Base/VectorPy.h>
71

72
#include <Mod/Part/App/BezierCurvePy.h>
73
#include <Mod/Part/App/BSplineCurvePy.h>
74
#include <Mod/Part/App/CirclePy.h>
75
#include <Mod/Part/App/EllipsePy.h>
76
#include <Mod/Part/App/GeometryPy.h>
77
#include <Mod/Part/App/HyperbolaPy.h>
78
#include <Mod/Part/App/LinePy.h>
79
#include <Mod/Part/App/OffsetCurvePy.h>
80
#include <Mod/Part/App/ParabolaPy.h>
81
#include <Mod/Part/App/TopoShapeEdgePy.h>
82
#include <Mod/Part/App/TopoShapeEdgePy.cpp>
83
#include <Mod/Part/App/TopoShapeFacePy.h>
84
#include <Mod/Part/App/TopoShapeVertexPy.h>
85
#include <Mod/Part/App/TopoShapeWirePy.h>
86

87
#include "Geometry2d.h"
88
#include "OCCError.h"
89
#include "Tools.h"
90

91

92
using namespace Part;
93

94
namespace {
95
const TopoDS_Edge& getTopoDSEdge(const TopoShapeEdgePy* theEdge){
96
    const TopoDS_Edge& e = TopoDS::Edge(theEdge->getTopoShapePtr()->getShape());
97
    if (e.IsNull())
98
        throw Py::ValueError("Edge is null");
99
    return e;
100
}
101
}
102

103
// returns a string which represents the object e.g. when printed in python
104
std::string TopoShapeEdgePy::representation() const
105
{
106
    std::stringstream str;
107
    str << "<Edge object at " << getTopoShapePtr() << ">";
108

109
    return str.str();
110
}
111

112
PyObject *TopoShapeEdgePy::PyMake(struct _typeobject *, PyObject *, PyObject *)  // Python wrapper
113
{
114
    // create a new instance of TopoShapeEdgePy and the Twin object
115
    return new TopoShapeEdgePy(new TopoShape);
116
}
117

118
// constructor method
119
int TopoShapeEdgePy::PyInit(PyObject* args, PyObject* /*kwd*/)
120
{
121
    if (PyArg_ParseTuple(args, "")) {
122
        // Undefined Edge
123
        getTopoShapePtr()->setShape(TopoDS_Edge());
124
        return 0;
125
    }
126

127
    PyErr_Clear();
128
    PyObject *pcObj, *pcObj2;
129
    double first=DBL_MAX, last=DBL_MAX;
130
    if (PyArg_ParseTuple(args, "O!|dd", &(Part::GeometryPy::Type), &pcObj, &first, &last)) {
131
        Geometry* geom = static_cast<GeometryPy*>(pcObj)->getGeometryPtr();
132
        Handle(Geom_Curve) curve = Handle(Geom_Curve)::DownCast(geom->handle());
133
        if (curve.IsNull()) {
134
            PyErr_SetString(PartExceptionOCCError, "geometry is not a curve type");
135
            return -1;
136
        }
137

138
        if (first==DBL_MAX)
139
            first = curve->FirstParameter();
140
        if (last==DBL_MAX)
141
            last = curve->LastParameter();
142

143
        try {
144
            BRepBuilderAPI_MakeEdge mkEdge(curve, first, last);
145
            getTopoShapePtr()->setShape(mkEdge.Edge());
146
            return 0;
147
        }
148
        catch (Standard_Failure& e) {
149

150
            PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
151
            return -1;
152
        }
153
    }
154

155
    PyErr_Clear();
156
    if (PyArg_ParseTuple(args, "O!", &(Part::TopoShapePy::Type), &pcObj)) {
157
        TopoShape* shape = static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr();
158
        if (shape && !shape->getShape().IsNull() && shape->getShape().ShapeType() == TopAbs_EDGE) {
159
            this->getTopoShapePtr()->setShape(shape->getShape());
160
            return 0;
161
        }
162
        else {
163
            PyErr_SetString(PyExc_TypeError, "Shape is not an edge");
164
            return -1;
165
        }
166
    }
167

168
    PyErr_Clear();
169
    if (PyArg_ParseTuple(args, "O!O!", &(Part::TopoShapeVertexPy::Type), &pcObj,
170
                                       &(Part::TopoShapeVertexPy::Type), &pcObj2)) {
171
        TopoShape* shape1 = static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr();
172
        TopoShape* shape2 = static_cast<TopoShapePy*>(pcObj2)->getTopoShapePtr();
173
        const TopoDS_Vertex& v1 = TopoDS::Vertex(shape1->getShape());
174
        const TopoDS_Vertex& v2 = TopoDS::Vertex(shape2->getShape());
175

176
        try {
177
            BRepBuilderAPI_MakeEdge mkEdge(v1, v2);
178
            getTopoShapePtr()->setShape(mkEdge.Edge());
179
            return 0;
180
        }
181
        catch (Standard_Failure& e) {
182

183
            PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
184
            return -1;
185
        }
186
    }
187

188
    PyErr_SetString(PartExceptionOCCError, "Curve or shape expected");
189
    return -1;
190
}
191

192
// ====== Methods  ======================================================================
193

194
PyObject* TopoShapeEdgePy::getParameterByLength(PyObject *args)
195
{
196
    double u;
197
    double t=Precision::Confusion();
198
    if (!PyArg_ParseTuple(args, "d|d",&u,&t))
199
        return nullptr;
200

201
    auto e = getTopoDSEdge(this);
202
    BRepAdaptor_Curve adapt(e);
203

204
    // transform value of [0,Length] to [First,Last]
205
    double first = BRepLProp_CurveTool::FirstParameter(adapt);
206
    double last = BRepLProp_CurveTool::LastParameter(adapt);
207
    if (!Precision::IsInfinite(first) && !Precision::IsInfinite(last)) {
208
        double length = GCPnts_AbscissaPoint::Length(adapt,t);
209

210
        if (u < -length || u > length) {
211
            PyErr_SetString(PyExc_ValueError, "value out of range");
212
            return nullptr;
213
        }
214
        if (u < 0)
215
            u = length+u;
216
        GCPnts_AbscissaPoint abscissaPoint(t,adapt,u,first);
217
        double parm = abscissaPoint.Parameter();
218
        return PyFloat_FromDouble(parm);
219
    }
220

221
    return PyFloat_FromDouble(u);
222
}
223

224
PyObject* TopoShapeEdgePy::valueAt(PyObject *args)
225
{
226
    double u;
227
    if (!PyArg_ParseTuple(args, "d",&u))
228
        return nullptr;
229

230
    auto e = getTopoDSEdge(this);
231
    BRepAdaptor_Curve adapt(e);
232

233
    // Check now the orientation of the edge to make
234
    // sure that we get the right wanted point!
235
    BRepLProp_CLProps prop(adapt,u,0,Precision::Confusion());
236
    const gp_Pnt& V = prop.Value();
237
    return new Base::VectorPy(new Base::Vector3d(V.X(),V.Y(),V.Z()));
238
}
239

240
PyObject* TopoShapeEdgePy::parameters(PyObject *args)
241
{
242
    PyObject* pyface = nullptr;
243
    if (!PyArg_ParseTuple(args, "|O!", &(TopoShapeFacePy::Type), &pyface))
244
        return nullptr;
245

246
    auto e = getTopoDSEdge(this);
247
    TopLoc_Location aLoc;
248
    Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(e, aLoc);
249
    if (!aPoly.IsNull()) {
250
        Py::List list;
251
        if (!aPoly->HasParameters()) {
252
            return Py::new_reference_to(list);
253
        }
254

255
        const TColStd_Array1OfReal& aNodes = aPoly->Parameters();
256
        for (int i=aNodes.Lower(); i<=aNodes.Upper(); i++) {
257
            list.append(Py::Float(aNodes(i)));
258
        }
259

260
        return Py::new_reference_to(list);
261
    }
262
    else if (pyface) {
263
        // build up map edge->face
264
        const TopoDS_Shape& face = static_cast<TopoShapeFacePy*>(pyface)->getTopoShapePtr()->getShape();
265
        TopTools_IndexedDataMapOfShapeListOfShape edge2Face;
266
        TopExp::MapShapesAndAncestors(TopoDS::Face(face), TopAbs_EDGE, TopAbs_FACE, edge2Face);
267
        if (edge2Face.Contains(e)) {
268
            Handle(Poly_Triangulation) aPolyTria = BRep_Tool::Triangulation(TopoDS::Face(face),aLoc);
269
            if (!aPolyTria.IsNull()) {
270
                Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(e, aPolyTria, aLoc);
271
                if (!aPoly.IsNull()) {
272
                    if (!aPoly->HasParameters()) {
273
                        Py::List list;
274
                        return Py::new_reference_to(list);
275
                    }
276

277
                    Handle(TColStd_HArray1OfReal) aNodes = aPoly->Parameters();
278
                    if (!aNodes.IsNull()) {
279
                        Py::List list;
280
                        for (int i=aNodes->Lower(); i<=aNodes->Upper(); i++) {
281
                            list.append(Py::Float(aNodes->Value(i)));
282
                        }
283

284
                        return Py::new_reference_to(list);
285
                    }
286
                }
287
            }
288
        }
289
        else {
290
            PyErr_SetString(PyExc_ValueError, "Edge is not part of the face");
291
            return nullptr;
292
        }
293
    }
294

295
    PyErr_SetString(PyExc_RuntimeError, "Edge has no polygon");
296
    return nullptr;
297
}
298

299
PyObject* TopoShapeEdgePy::parameterAt(PyObject *args)
300
{
301
    PyObject* pnt;
302
    PyObject* face=nullptr;
303
    if (!PyArg_ParseTuple(args, "O!|O!",&TopoShapeVertexPy::Type,&pnt,
304
                                        &TopoShapeFacePy::Type,&face))
305
        return nullptr;
306

307
    try {
308
        const TopoDS_Shape& v = static_cast<TopoShapePy*>(pnt)->getTopoShapePtr()->getShape();
309
        auto e = getTopoDSEdge(this);
310

311
        if (face) {
312
            const TopoDS_Shape& f = static_cast<TopoShapeFacePy*>(face)->getTopoShapePtr()->getShape();
313
            Standard_Real par = BRep_Tool::Parameter(TopoDS::Vertex(v), e, TopoDS::Face(f));
314
            return PyFloat_FromDouble(par);
315
        }
316
        else {
317
            Standard_Real par = BRep_Tool::Parameter(TopoDS::Vertex(v), e);
318
            return PyFloat_FromDouble(par);
319
        }
320
    }
321
    catch (Standard_Failure& e) {
322

323
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
324
        return nullptr;
325
    }
326
}
327

328
PyObject* TopoShapeEdgePy::tangentAt(PyObject *args)
329
{
330
    double u;
331
    if (!PyArg_ParseTuple(args, "d",&u))
332
        return nullptr;
333

334
    auto e = getTopoDSEdge(this);
335
    BRepAdaptor_Curve adapt(e);
336

337
    BRepLProp_CLProps prop(adapt,u,2,Precision::Confusion());
338
    if (prop.IsTangentDefined()) {
339
        gp_Dir dir;
340
        prop.Tangent(dir);
341
        return new Base::VectorPy(new Base::Vector3d(dir.X(),dir.Y(),dir.Z()));
342
    }
343
    else {
344
        PyErr_SetString(PyExc_NotImplementedError, "Tangent not defined at this position!");
345
        return nullptr;
346
    }
347
}
348

349
PyObject* TopoShapeEdgePy::normalAt(PyObject *args)
350
{
351
    double u;
352
    if (!PyArg_ParseTuple(args, "d",&u))
353
        return nullptr;
354

355
    auto e = getTopoDSEdge(this);
356
    BRepAdaptor_Curve adapt(e);
357

358
    try {
359
        BRepLProp_CLProps prop(adapt,u,2,Precision::Confusion());
360
        gp_Dir V ;
361
        prop.Normal(V);
362
        return new Base::VectorPy(new Base::Vector3d(V.X(),V.Y(),V.Z()));
363
    }
364
    catch (Standard_Failure& e) {
365

366
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
367
        return nullptr;
368
    }
369
}
370

371
PyObject* TopoShapeEdgePy::curvatureAt(PyObject *args)
372
{
373
    double u;
374
    if (!PyArg_ParseTuple(args, "d",&u))
375
        return nullptr;
376

377
    auto e = getTopoDSEdge(this);
378
    BRepAdaptor_Curve adapt(e);
379

380
    try {
381
        BRepLProp_CLProps prop(adapt,u,2,Precision::Confusion());
382
        double C = prop.Curvature();
383
        return Py::new_reference_to(Py::Float(C));
384
    }
385
    catch (Standard_Failure& e) {
386

387
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
388
        return nullptr;
389
    }
390
}
391

392
PyObject* TopoShapeEdgePy::centerOfCurvatureAt(PyObject *args)
393
{
394
    double u;
395
    if (!PyArg_ParseTuple(args, "d",&u))
396
        return nullptr;
397

398
    auto e = getTopoDSEdge(this);
399
    BRepAdaptor_Curve adapt(e);
400

401
    try {
402
        BRepLProp_CLProps prop(adapt,u,2,Precision::Confusion());
403
        gp_Pnt V ;
404
        prop.CentreOfCurvature(V);
405
        return new Base::VectorPy(new Base::Vector3d(V.X(),V.Y(),V.Z()));
406
    }
407
    catch (Standard_Failure& e) {
408

409
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
410
        return nullptr;
411
    }
412
}
413

414
PyObject* TopoShapeEdgePy::derivative1At(PyObject *args)
415
{
416
    double u;
417
    if (!PyArg_ParseTuple(args, "d",&u))
418
        return nullptr;
419

420
    auto e = getTopoDSEdge(this);
421
    BRepAdaptor_Curve adapt(e);
422

423
    try {
424
        BRepLProp_CLProps prop(adapt,u,1,Precision::Confusion());
425
        const gp_Vec& V = prop.D1();
426
        return new Base::VectorPy(new Base::Vector3d(V.X(),V.Y(),V.Z()));
427
    }
428
    catch (Standard_Failure& e) {
429

430
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
431
        return nullptr;
432
    }
433
}
434

435
PyObject* TopoShapeEdgePy::derivative2At(PyObject *args)
436
{
437
    double u;
438
    if (!PyArg_ParseTuple(args, "d",&u))
439
        return nullptr;
440

441
    auto e = getTopoDSEdge(this);
442
    BRepAdaptor_Curve adapt(e);
443

444
    try {
445
        BRepLProp_CLProps prop(adapt,u,2,Precision::Confusion());
446
        const gp_Vec& V = prop.D2();
447
        return new Base::VectorPy(new Base::Vector3d(V.X(),V.Y(),V.Z()));
448
    }
449
    catch (Standard_Failure& e) {
450

451
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
452
        return nullptr;
453
    }
454
}
455

456
PyObject* TopoShapeEdgePy::derivative3At(PyObject *args)
457
{
458
    double u;
459
    if (!PyArg_ParseTuple(args, "d",&u))
460
        return nullptr;
461

462
    auto e = getTopoDSEdge(this);
463
    BRepAdaptor_Curve adapt(e);
464

465
    try {
466
        BRepLProp_CLProps prop(adapt,u,3,Precision::Confusion());
467
        const gp_Vec& V = prop.D3();
468
        return new Base::VectorPy(new Base::Vector3d(V.X(),V.Y(),V.Z()));
469
    }
470
    catch (Standard_Failure& e) {
471

472
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
473
        return nullptr;
474
    }
475
}
476

477
PyObject* TopoShapeEdgePy::discretize(PyObject *args, PyObject *kwds)
478
{
479
    try {
480
        BRepAdaptor_Curve adapt(TopoDS::Edge(getTopoShapePtr()->getShape()));
481
        bool uniformAbscissaPoints = false;
482
        bool uniformAbscissaDistance = false;
483
        int numPoints = -1;
484
        double distance = -1;
485
        double first = adapt.FirstParameter();
486
        double last = adapt.LastParameter();
487

488
        // use no kwds
489
        PyObject* dist_or_num;
490
        if (PyArg_ParseTuple(args, "O", &dist_or_num)) {
491
            if (PyLong_Check(dist_or_num)) {
492
                numPoints = PyLong_AsLong(dist_or_num);
493
                uniformAbscissaPoints = true;
494
            }
495
            else if (PyFloat_Check(dist_or_num)) {
496
                distance = PyFloat_AsDouble(dist_or_num);
497
                uniformAbscissaDistance = true;
498
            }
499
            else {
500
                PyErr_SetString(PyExc_TypeError, "Either int or float expected");
501
                return nullptr;
502
            }
503
        }
504
        else {
505
            // use Number kwds
506
            static const std::array<const char *, 4> kwds_numPoints{"Number", "First", "Last", nullptr};
507
            PyErr_Clear();
508
            if (Base::Wrapped_ParseTupleAndKeywords(args, kwds, "i|dd", kwds_numPoints, &numPoints, &first, &last)) {
509
                uniformAbscissaPoints = true;
510
            }
511
            else {
512
                // use Abscissa kwds
513
                static const std::array<const char *, 4> kwds_Distance{"Distance", "First", "Last", nullptr};
514
                PyErr_Clear();
515
                if (Base::Wrapped_ParseTupleAndKeywords(args, kwds, "d|dd", kwds_Distance, &distance, &first, &last)) {
516
                    uniformAbscissaDistance = true;
517
                }
518
            }
519
        }
520

521
        if (uniformAbscissaPoints || uniformAbscissaDistance) {
522
            GCPnts_UniformAbscissa discretizer;
523
            if (uniformAbscissaPoints)
524
                discretizer.Initialize (adapt, numPoints, first, last);
525
            else
526
                discretizer.Initialize (adapt, distance, first, last);
527

528
            if (discretizer.IsDone () && discretizer.NbPoints () > 0) {
529
                Py::List points;
530
                int nbPoints = discretizer.NbPoints ();
531
                for (int i=1; i<=nbPoints; i++) {
532
                    gp_Pnt p = adapt.Value (discretizer.Parameter (i));
533
                    points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z())));
534
                }
535

536
                return Py::new_reference_to(points);
537
            }
538
            else {
539
                PyErr_SetString(PartExceptionOCCError, "Discretization of edge failed");
540
                return nullptr;
541
            }
542
        }
543

544
        // use Deflection kwds
545
        static const std::array<const char *, 4> kwds_Deflection{"Deflection", "First", "Last", nullptr};
546
        PyErr_Clear();
547
        double deflection;
548
        if (Base::Wrapped_ParseTupleAndKeywords(args, kwds, "d|dd", kwds_Deflection, &deflection, &first, &last)) {
549
            GCPnts_UniformDeflection discretizer(adapt, deflection, first, last);
550
            if (discretizer.IsDone () && discretizer.NbPoints () > 0) {
551
                Py::List points;
552
                int nbPoints = discretizer.NbPoints ();
553
                for (int i=1; i<=nbPoints; i++) {
554
                    gp_Pnt p = discretizer.Value (i);
555
                    points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z())));
556
                }
557

558
                return Py::new_reference_to(points);
559
            }
560
            else {
561
                PyErr_SetString(PartExceptionOCCError, "Discretization of edge failed");
562
                return nullptr;
563
            }
564
        }
565

566
        // use TangentialDeflection kwds
567
        static const std::array<const char *, 6> kwds_TangentialDeflection {"Angular", "Curvature", "First", "Last",
568
                                                                            "Minimum", nullptr};
569
        PyErr_Clear();
570
        double angular;
571
        double curvature;
572
        int minimumPoints = 2;
573
        if (Base::Wrapped_ParseTupleAndKeywords(args, kwds, "dd|ddi", kwds_TangentialDeflection, &angular, &curvature,
574
                                                &first, &last, &minimumPoints)) {
575
            GCPnts_TangentialDeflection discretizer(adapt, first, last, angular, curvature, minimumPoints);
576
            if (discretizer.NbPoints () > 0) {
577
                Py::List points;
578
                int nbPoints = discretizer.NbPoints ();
579
                for (int i=1; i<=nbPoints; i++) {
580
                    gp_Pnt p = discretizer.Value (i);
581
                    points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z())));
582
                }
583

584
                return Py::new_reference_to(points);
585
            }
586
            else {
587
                PyErr_SetString(PartExceptionOCCError, "Discretization of edge failed");
588
                return nullptr;
589
            }
590
        }
591

592
        // use QuasiNumber kwds
593
        static const std::array<const char *, 4> kwds_QuasiNumPoints{"QuasiNumber", "First", "Last", nullptr};
594
        PyErr_Clear();
595
        int quasiNumPoints;
596
        if (Base::Wrapped_ParseTupleAndKeywords(args, kwds, "i|dd", kwds_QuasiNumPoints, &quasiNumPoints, &first,
597
                                                &last)) {
598
            GCPnts_QuasiUniformAbscissa discretizer(adapt, quasiNumPoints, first, last);
599
            if (discretizer.NbPoints () > 0) {
600
                Py::List points;
601
                int nbPoints = discretizer.NbPoints ();
602
                for (int i=1; i<=nbPoints; i++) {
603
                    gp_Pnt p = adapt.Value (discretizer.Parameter (i));
604
                    points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z())));
605
                }
606

607
                return Py::new_reference_to(points);
608
            }
609
            else {
610
                PyErr_SetString(PartExceptionOCCError, "Discretization of edge failed");
611
                return nullptr;
612
            }
613
        }
614

615
        // use QuasiDeflection kwds
616
        static const std::array<const char *, 4> kwds_QuasiDeflection{"QuasiDeflection", "First", "Last", nullptr};
617
        PyErr_Clear();
618
        double quasiDeflection;
619
        if (Base::Wrapped_ParseTupleAndKeywords(args, kwds, "d|dd", kwds_QuasiDeflection,
620
                                                &quasiDeflection, &first, &last)) {
621
            GCPnts_QuasiUniformDeflection discretizer(adapt, quasiDeflection, first, last);
622
            if (discretizer.NbPoints () > 0) {
623
                Py::List points;
624
                int nbPoints = discretizer.NbPoints ();
625
                for (int i=1; i<=nbPoints; i++) {
626
                    gp_Pnt p = discretizer.Value (i);
627
                    points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z())));
628
                }
629

630
                return Py::new_reference_to(points);
631
            }
632
            else {
633
                PyErr_SetString(PartExceptionOCCError, "Discretization of edge failed");
634
                return nullptr;
635
            }
636
        }
637
    }
638
    catch (const Base::Exception& e) {
639
        PyErr_SetString(PartExceptionOCCError, e.what());
640
        return nullptr;
641
    }
642

643
    PyErr_SetString(PartExceptionOCCError,"Wrong arguments");
644
    return nullptr;
645
}
646

647
PyObject* TopoShapeEdgePy::countNodes(PyObject *args)
648
{
649
    if (!PyArg_ParseTuple(args, ""))
650
        return nullptr;
651

652
    const TopoDS_Shape& shape = this->getTopoShapePtr()->getShape();
653
    TopoDS_Edge aEdge = TopoDS::Edge(shape);
654
    TopLoc_Location aLoc;
655
    const Handle(Poly_Polygon3D)& aPoly = BRep_Tool::Polygon3D(aEdge, aLoc);
656
    int count = 0;
657
    if (!aPoly.IsNull()) {
658
        count = aPoly->NbNodes();
659
    }
660

661
    return Py::new_reference_to(Py::Long(count));
662
}
663

664
PyObject* TopoShapeEdgePy::split(PyObject *args)
665
{
666
    PyObject* float_or_list;
667
    if (!PyArg_ParseTuple(args, "O", &float_or_list))
668
        return nullptr;
669

670
    try {
671
        BRepAdaptor_Curve adapt(TopoDS::Edge(getTopoShapePtr()->getShape()));
672
        Standard_Real f = adapt.FirstParameter();
673
        Standard_Real l = adapt.LastParameter();
674

675
        std::vector<Standard_Real> par;
676
        par.push_back(f);
677
        if (PyFloat_Check(float_or_list)) {
678
            double val = PyFloat_AsDouble(float_or_list);
679
            if (val == f || val == l) {
680
                PyErr_SetString(PyExc_ValueError, "Cannot split edge at start or end point");
681
                return nullptr;
682
            }
683
            else if (val < f || val > l) {
684
                PyErr_SetString(PyExc_ValueError, "Value out of parameter range");
685
                return nullptr;
686
            }
687
            par.push_back(val);
688
        }
689
        else if (PySequence_Check(float_or_list)) {
690
            Py::Sequence list(float_or_list);
691
            for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
692
                double val = (double)Py::Float(*it);
693
                if (val == f || val == l) {
694
                    PyErr_SetString(PyExc_ValueError, "Cannot split edge at start or end point");
695
                    return nullptr;
696
                }
697
                else if (val < f || val > l) {
698
                    PyErr_SetString(PyExc_ValueError, "Value out of parameter range");
699
                    return nullptr;
700
                }
701
                par.push_back(val);
702
            }
703
        }
704
        else {
705
            PyErr_SetString(PyExc_TypeError, "Either float or list of floats expected");
706
            return nullptr;
707
        }
708

709
        par.push_back(l);
710
        std::sort(par.begin(), par.end());
711

712
        BRepBuilderAPI_MakeWire mkWire;
713
        Handle(Geom_Curve) c = adapt.Curve().Curve();
714
        const TopoDS_Edge& edge = TopoDS::Edge(this->getTopoShapePtr()->getShape());
715
        BRep_Builder builder;
716
        TopoDS_Edge e;
717
        std::vector<Standard_Real>::iterator end = par.end() - 1;
718
        for (std::vector<Standard_Real>::iterator it = par.begin(); it != end; ++it) {
719
            BRepBuilderAPI_MakeEdge mke(c, it[0], it[1]);
720
            e =  mke.Edge();
721
            builder.Transfert(edge, e);
722
            builder.Range(e, it[0], it[1], false);
723
            mkWire.Add(e);
724
        }
725

726
        return new TopoShapeWirePy(new TopoShape(mkWire.Shape()));
727
    }
728
    catch (Standard_Failure& e) {
729

730
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
731
        return nullptr;
732
    }
733
}
734

735
PyObject* TopoShapeEdgePy::isSeam(PyObject *args)
736
{
737
    PyObject* face;
738
    if (!PyArg_ParseTuple(args, "O!", &TopoShapeFacePy::Type, &face))
739
        return nullptr;
740

741
    try {
742
        const TopoDS_Edge& e = TopoDS::Edge(this->getTopoShapePtr()->getShape());
743
        const TopoDS_Face& f = TopoDS::Face(static_cast<TopoShapeFacePy*>(face)->getTopoShapePtr()->getShape());
744

745
        ShapeAnalysis_Edge sa;
746
        Standard_Boolean ok = sa.IsSeam(e, f);
747
        return PyBool_FromLong(ok ? 1 : 0);
748
    }
749
    catch (Standard_Failure& e) {
750

751
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
752
        return nullptr;
753
    }
754
}
755

756
PyObject* TopoShapeEdgePy::firstVertex(PyObject *args)
757
{
758
    PyObject* orient = Py_False;
759
    if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &orient))
760
        return nullptr;
761
    auto e = getTopoDSEdge(this);
762
    TopoDS_Vertex v = TopExp::FirstVertex(e, Base::asBoolean(orient));
763
    return new TopoShapeVertexPy(new TopoShape(v));
764
}
765

766
PyObject* TopoShapeEdgePy::lastVertex(PyObject *args)
767
{
768
    PyObject* orient = Py_False;
769
    if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &orient))
770
        return nullptr;
771
    auto e = getTopoDSEdge(this);
772
    TopoDS_Vertex v = TopExp::LastVertex(e, Base::asBoolean(orient));
773
    return new TopoShapeVertexPy(new TopoShape(v));
774
}
775

776
// ====== Attributes ======================================================================
777

778
Py::String TopoShapeEdgePy::getContinuity() const
779
{
780
    BRepAdaptor_Curve adapt(TopoDS::Edge(getTopoShapePtr()->getShape()));
781
    std::string cont;
782
    switch (adapt.Continuity()) {
783
    case GeomAbs_C0:
784
        cont = "C0";
785
        break;
786
    case GeomAbs_G1:
787
        cont = "G1";
788
        break;
789
    case GeomAbs_C1:
790
        cont = "C1";
791
        break;
792
    case GeomAbs_G2:
793
        cont = "G2";
794
        break;
795
    case GeomAbs_C2:
796
        cont = "C2";
797
        break;
798
    case GeomAbs_C3:
799
        cont = "C3";
800
        break;
801
    case GeomAbs_CN:
802
        cont = "CN";
803
        break;
804
    }
805

806
    return Py::String(cont);
807
}
808

809
Py::Float TopoShapeEdgePy::getTolerance() const
810
{
811
    auto e = getTopoDSEdge(this);
812
    return Py::Float(BRep_Tool::Tolerance(e));
813
}
814

815
void TopoShapeEdgePy::setTolerance(Py::Float tol)
816
{
817
    BRep_Builder aBuilder;
818
    auto e = getTopoDSEdge(this);
819
    aBuilder.UpdateEdge(e, (double)tol);
820
}
821

822
Py::Float TopoShapeEdgePy::getLength() const
823
{
824
    auto e = getTopoDSEdge(this);
825
    BRepAdaptor_Curve adapt(e);
826
    return Py::Float(GCPnts_AbscissaPoint::Length(adapt, Precision::Confusion()));
827
}
828

829
#include <App/Application.h>
830
#include <Mod/Part/App/LineSegmentPy.h>
831

832
Py::Object TopoShapeEdgePy::getCurve() const
833
{
834
    auto e = getTopoDSEdge(this);
835
    BRepAdaptor_Curve adapt(e);
836
    Base::PyObjectBase* curve = nullptr;
837
    switch(adapt.GetType())
838
    {
839
    case GeomAbs_Line:
840
        {
841
            GeomLine* line = new GeomLine();
842
            Handle(Geom_Line) this_curv = Handle(Geom_Line)::DownCast
843
                (line->handle());
844
            this_curv->SetLin(adapt.Line());
845
            curve = new LinePy(line);
846
            break;
847
        }
848
    case GeomAbs_Circle:
849
        {
850
            GeomCircle* circle = new GeomCircle();
851
            Handle(Geom_Circle) this_curv = Handle(Geom_Circle)::DownCast
852
                (circle->handle());
853
            this_curv->SetCirc(adapt.Circle());
854
            //Standard_Real dd = adapt.FirstParameter();
855
            //Standard_Real ee = adapt.LastParameter();
856
            curve = new CirclePy(circle);
857
            break;
858
        }
859
    case GeomAbs_Ellipse:
860
        {
861
            GeomEllipse* elips = new GeomEllipse();
862
            Handle(Geom_Ellipse) this_curv = Handle(Geom_Ellipse)::DownCast
863
                (elips->handle());
864
            this_curv->SetElips(adapt.Ellipse());
865
            curve = new EllipsePy(elips);
866
            break;
867
        }
868
    case GeomAbs_Hyperbola:
869
        {
870
            GeomHyperbola* hypr = new GeomHyperbola();
871
            Handle(Geom_Hyperbola) this_curv = Handle(Geom_Hyperbola)::DownCast
872
                (hypr->handle());
873
            this_curv->SetHypr(adapt.Hyperbola());
874
            curve = new HyperbolaPy(hypr);
875
            break;
876
        }
877
    case GeomAbs_Parabola:
878
        {
879
            GeomParabola* parab = new GeomParabola();
880
            Handle(Geom_Parabola) this_curv = Handle(Geom_Parabola)::DownCast
881
                (parab->handle());
882
            this_curv->SetParab(adapt.Parabola());
883
            curve = new ParabolaPy(parab);
884
            break;
885
        }
886
    case GeomAbs_BezierCurve:
887
        {
888
            GeomBezierCurve* bezier = new GeomBezierCurve(adapt.Bezier());
889
            curve = new BezierCurvePy(bezier);
890
            break;
891
        }
892
    case GeomAbs_BSplineCurve:
893
        {
894
            GeomBSplineCurve* bspline = new GeomBSplineCurve(adapt.BSpline());
895
            curve = new BSplineCurvePy(bspline);
896
            break;
897
        }
898
    case GeomAbs_OffsetCurve:
899
        {
900
            Standard_Real first, last;
901
            Handle(Geom_Curve) c = BRep_Tool::Curve(e, first, last);
902
            Handle(Geom_OffsetCurve) off = Handle(Geom_OffsetCurve)::DownCast(c);
903
            if (!off.IsNull()) {
904
                GeomOffsetCurve* offset = new GeomOffsetCurve(off);
905
                curve = new OffsetCurvePy(offset);
906
                break;
907
            }
908
            else {
909
                throw Py::RuntimeError("Failed to convert to offset curve");
910
            }
911
        }
912
    case GeomAbs_OtherCurve:
913
        break;
914
    }
915

916
    if (curve) {
917
        curve->setNotTracking();
918
        return Py::asObject(curve);
919
    }
920

921
    throw Py::TypeError("undefined curve type");
922
}
923

924
Py::Tuple TopoShapeEdgePy::getParameterRange() const
925
{
926
    auto e = getTopoDSEdge(this);
927
    BRepAdaptor_Curve adapt(e);
928
    double u = adapt.FirstParameter();
929
    double v = adapt.LastParameter();
930

931
    Py::Tuple t(2);
932
    t.setItem(0, Py::Float(u));
933
    t.setItem(1, Py::Float(v));
934
    return t;
935
}
936

937
Py::Float TopoShapeEdgePy::getFirstParameter() const
938
{
939
    auto e = getTopoDSEdge(this);
940
    BRepAdaptor_Curve adapt(e);
941
    double t = adapt.FirstParameter();
942
    return Py::Float(t);
943
}
944

945
Py::Float TopoShapeEdgePy::getLastParameter() const
946
{
947
    auto e = getTopoDSEdge(this);
948
    BRepAdaptor_Curve adapt(e);
949
    double t = adapt.LastParameter();
950
    return Py::Float(t);
951
}
952

953
Py::Object TopoShapeEdgePy::getMass() const
954
{
955
    GProp_GProps props;
956
    BRepGProp::LinearProperties(getTopoShapePtr()->getShape(), props);
957
    double c = props.Mass();
958
    return Py::Float(c);
959
}
960

961
Py::Object TopoShapeEdgePy::getCenterOfMass() const
962
{
963
    GProp_GProps props;
964
    BRepGProp::LinearProperties(getTopoShapePtr()->getShape(), props);
965
    gp_Pnt c = props.CentreOfMass();
966
    return Py::Vector(Base::Vector3d(c.X(),c.Y(),c.Z()));
967
}
968

969
Py::Object TopoShapeEdgePy::getMatrixOfInertia() const
970
{
971
    GProp_GProps props;
972
    BRepGProp::LinearProperties(getTopoShapePtr()->getShape(), props);
973
    gp_Mat m = props.MatrixOfInertia();
974
    Base::Matrix4D mat;
975
    for (int i=0; i<3; i++) {
976
        for (int j=0; j<3; j++) {
977
            mat[i][j] = m(i+1,j+1);
978
        }
979
    }
980
    return Py::Matrix(mat);
981
}
982

983
Py::Object TopoShapeEdgePy::getStaticMoments() const
984
{
985
    GProp_GProps props;
986
    BRepGProp::LinearProperties(getTopoShapePtr()->getShape(), props);
987
    Standard_Real lx,ly,lz;
988
    props.StaticMoments(lx,ly,lz);
989
    Py::Tuple tuple(3);
990
    tuple.setItem(0, Py::Float(lx));
991
    tuple.setItem(1, Py::Float(ly));
992
    tuple.setItem(2, Py::Float(lz));
993
    return tuple;
994
}
995

996
Py::Dict TopoShapeEdgePy::getPrincipalProperties() const
997
{
998
    GProp_GProps props;
999
    BRepGProp::LinearProperties(getTopoShapePtr()->getShape(), props);
1000
    GProp_PrincipalProps pprops = props.PrincipalProperties();
1001

1002
    Py::Dict dict;
1003
    dict.setItem("SymmetryAxis", Py::Boolean(pprops.HasSymmetryAxis() ? true : false));
1004
    dict.setItem("SymmetryPoint", Py::Boolean(pprops.HasSymmetryPoint() ? true : false));
1005
    Standard_Real lx,ly,lz;
1006
    pprops.Moments(lx,ly,lz);
1007
    Py::Tuple tuple(3);
1008
    tuple.setItem(0, Py::Float(lx));
1009
    tuple.setItem(1, Py::Float(ly));
1010
    tuple.setItem(2, Py::Float(lz));
1011
    dict.setItem("Moments",tuple);
1012
    dict.setItem("FirstAxisOfInertia",Py::Vector(Base::convertTo
1013
        <Base::Vector3d>(pprops.FirstAxisOfInertia())));
1014
    dict.setItem("SecondAxisOfInertia",Py::Vector(Base::convertTo
1015
        <Base::Vector3d>(pprops.SecondAxisOfInertia())));
1016
    dict.setItem("ThirdAxisOfInertia",Py::Vector(Base::convertTo
1017
        <Base::Vector3d>(pprops.ThirdAxisOfInertia())));
1018

1019
    Standard_Real Rxx,Ryy,Rzz;
1020
    pprops.RadiusOfGyration(Rxx,Ryy,Rzz);
1021
    Py::Tuple rog(3);
1022
    rog.setItem(0, Py::Float(Rxx));
1023
    rog.setItem(1, Py::Float(Ryy));
1024
    rog.setItem(2, Py::Float(Rzz));
1025
    dict.setItem("RadiusOfGyration",rog);
1026
    return dict;
1027
}
1028

1029
Py::Boolean TopoShapeEdgePy::getClosed() const
1030
{
1031
    if (getTopoShapePtr()->getShape().IsNull())
1032
        throw Py::RuntimeError("Cannot determine the 'Closed'' flag of an empty shape");
1033
    Standard_Boolean ok = BRep_Tool::IsClosed(getTopoShapePtr()->getShape());
1034
    return Py::Boolean(ok ? true : false);
1035
}
1036

1037
Py::Boolean TopoShapeEdgePy::getDegenerated() const
1038
{
1039
    Standard_Boolean ok = BRep_Tool::Degenerated(TopoDS::Edge(getTopoShapePtr()->getShape()));
1040
    return Py::Boolean(ok ? true : false);
1041
}
1042

1043
PyObject* TopoShapeEdgePy::curveOnSurface(PyObject *args)
1044
{
1045
    int idx;
1046
    if (!PyArg_ParseTuple(args, "i", &idx))
1047
        return nullptr;
1048

1049
    try {
1050
        TopoDS_Edge edge = TopoDS::Edge(getTopoShapePtr()->getShape());
1051
        Handle(Geom2d_Curve) curve;
1052
        Handle(Geom_Surface) surf;
1053
        TopLoc_Location loc;
1054
        Standard_Real first, last;
1055

1056
        BRep_Tool::CurveOnSurface(edge, curve, surf, loc, first, last, idx+1);
1057
        if (curve.IsNull())
1058
            Py_Return;
1059
        std::unique_ptr<Part::Geom2dCurve> geo2d(makeFromCurve2d(curve));
1060
        if (!geo2d)
1061
            Py_Return;
1062
        std::unique_ptr<Part::GeomSurface> geosurf(makeFromSurface(surf));
1063
        if (!geosurf)
1064
            Py_Return;
1065

1066
        gp_Trsf trsf = loc.Transformation();
1067
        gp_XYZ pos = trsf.TranslationPart();
1068
        gp_XYZ axis;
1069
        Standard_Real angle;
1070
        trsf.GetRotation(axis, angle);
1071
        Base::Rotation rot(Base::Vector3d(axis.X(), axis.Y(), axis.Z()), angle);
1072
        Base::Placement placement(Base::Vector3d(pos.X(), pos.Y(), pos.Z()), rot);
1073

1074
        Py::Tuple tuple(5);
1075
        tuple.setItem(0, Py::asObject(geo2d->getPyObject()));
1076
        tuple.setItem(1, Py::asObject(geosurf->getPyObject()));
1077
        tuple.setItem(2, Py::asObject(new Base::PlacementPy(placement)));
1078
        tuple.setItem(3, Py::Float(first));
1079
        tuple.setItem(4, Py::Float(last));
1080
        return Py::new_reference_to(tuple);
1081
    }
1082
    catch (Standard_Failure& e) {
1083
        PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1084
        return nullptr;
1085
    }
1086
}
1087

1088
PyObject *TopoShapeEdgePy::getCustomAttributes(const char* /*attr*/) const
1089
{
1090
    return nullptr;
1091
}
1092

1093
int TopoShapeEdgePy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
1094
{
1095
    return 0;
1096
}
1097

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

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

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

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