1
/***************************************************************************
2
* Copyright (c) 2008 Jürgen Riegel <juergen.riegel@web.de> *
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"
26
# include <boost/regex.hpp>
28
# include <BRep_Tool.hxx>
29
# include <BRepAlgo_NormalProjection.hxx>
30
# include <BRepBndLib.hxx>
31
# include <BRepBuilderAPI_Copy.hxx>
32
# include <BRepBuilderAPI_MakeVertex.hxx>
33
# include <BRepBuilderAPI_Transform.hxx>
34
# include <BRepClass3d_SolidClassifier.hxx>
35
# include <BRepExtrema_DistShapeShape.hxx>
36
# include <BRepExtrema_ShapeProximity.hxx>
37
# include <BRepExtrema_SupportType.hxx>
38
# include <BRepFilletAPI_MakeChamfer.hxx>
39
# include <BRepFilletAPI_MakeFillet.hxx>
40
# include <BRepGProp.hxx>
41
# include <BRepMesh_IncrementalMesh.hxx>
42
# include <BRepProj_Projection.hxx>
43
# include <BRepTools.hxx>
44
# include <Geom_Plane.hxx>
50
# include <gp_Trsf.hxx>
51
# include <GProp_GProps.hxx>
52
# include <HLRAppli_ReflectLines.hxx>
53
# include <Precision.hxx>
54
# include <Poly_Polygon3D.hxx>
55
# include <Poly_Triangulation.hxx>
56
# include <ShapeAnalysis_ShapeTolerance.hxx>
57
# include <ShapeFix_ShapeTolerance.hxx>
58
# include <Standard_Version.hxx>
60
# include <TopExp_Explorer.hxx>
61
# include <TopLoc_Location.hxx>
63
# include <TopoDS_Iterator.hxx>
64
# include <TopTools_IndexedMapOfShape.hxx>
65
# include <TopTools_ListIteratorOfListOfShape.hxx>
66
# include <TopTools_ListOfShape.hxx>
69
#include <App/PropertyStandard.h>
70
#include <App/StringHasherPy.h>
71
#include <Base/FileInfo.h>
72
#include <Base/GeometryPyCXX.h>
73
#include <Base/MatrixPy.h>
74
#include <Base/PyWrapParseTupleAndKeywords.h>
75
#include <Base/Rotation.h>
76
#include <Base/Stream.h>
77
#include <Base/Vector3D.h>
78
#include <Base/VectorPy.h>
80
#include <Mod/Part/App/TopoShapePy.h>
81
#include <Mod/Part/App/TopoShapePy.cpp>
83
#include <Mod/Part/App/GeometryPy.h>
84
#include <Mod/Part/App/PlanePy.h>
85
#include <Mod/Part/App/TopoShapeCompoundPy.h>
86
#include <Mod/Part/App/TopoShapeCompSolidPy.h>
87
#include <Mod/Part/App/TopoShapeEdgePy.h>
88
#include <Mod/Part/App/TopoShapeFacePy.h>
89
#include <Mod/Part/App/TopoShapeOpCode.h>
90
#include <Mod/Part/App/TopoShapeShellPy.h>
91
#include <Mod/Part/App/TopoShapeSolidPy.h>
92
#include <Mod/Part/App/TopoShapeVertexPy.h>
93
#include <Mod/Part/App/TopoShapeWirePy.h>
97
#include "ShapeMapHasher.h"
98
#include "TopoShapeMapper.h"
104
#define M_PI 3.14159265358979323846 /* pi */
108
#define M_PI_2 1.57079632679489661923 /* pi/2 */
111
static Py_hash_t _TopoShapeHash(PyObject* self)
114
PyErr_SetString(PyExc_TypeError,
115
"descriptor 'hash' of 'Part.TopoShape' object needs an argument");
118
if (!static_cast<Base::PyObjectBase*>(self)->isValid()) {
119
PyErr_SetString(PyExc_ReferenceError,
120
"This object is already deleted most likely through closing a document. "
121
"This reference is no longer valid!");
124
#if OCC_VERSION_HEX >= 0x070800
125
return std::hash<TopoDS_Shape> {}(static_cast<TopoShapePy*>(self)->getTopoShapePtr()->getShape());
127
return static_cast<TopoShapePy*>(self)->getTopoShapePtr()->getShape().HashCode(INT_MAX);
131
struct TopoShapePyInit
135
TopoShapePy::Type.tp_hash = _TopoShapeHash;
139
// returns a string which represents the object e.g. when printed in python
140
std::string TopoShapePy::representation() const
142
std::stringstream str;
143
str << "<Shape object at " << getTopoShapePtr() << ">";
148
PyObject *TopoShapePy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
150
// create a new instance of TopoShapePy and the Twin object
151
return new TopoShapePy(new TopoShape);
154
int TopoShapePy::PyInit(PyObject* args, PyObject* keywds)
156
static const std::array<const char*, 5> kwlist{ "shape",
162
PyObject* pyHasher = nullptr;
163
const char* op = nullptr;
164
PyObject* pcObj = nullptr;
165
if (!Base::Wrapped_ParseTupleAndKeywords(args,
172
&App::StringHasherPy::Type,
176
auto& self = *getTopoShapePtr();
179
self.Hasher = static_cast<App::StringHasherPy*>(pyHasher)->getStringHasherPtr();
181
auto shapes = getPyShapes(pcObj);
184
if (shapes.size() == 1 && !op) {
185
auto s = shapes.front();
187
if ((s.Tag && self.Tag != s.Tag)
188
|| (self.Hasher && s.getElementMapSize() && self.Hasher != s.Hasher)) {
189
s.reTagElementMap(self.Tag, self.Hasher);
193
s.Hasher = self.Hasher;
198
else if (shapes.size()) {
200
op = Part::OpCodes::Fuse;
202
self.makeElementBoolean(op, shapes);
205
_PY_CATCH_OCC(return (-1))
209
PyObject* TopoShapePy::copy(PyObject *args)
211
PyObject* copyGeom = Py_True;
212
PyObject* copyMesh = Py_False;
213
const char* op = nullptr;
214
PyObject* pyHasher = nullptr;
215
if (!PyArg_ParseTuple(args,
218
&App::StringHasherPy::Type,
225
if (!PyArg_ParseTuple(args, "|O!O!", &PyBool_Type, ©Geom, &PyBool_Type, ©Mesh)) {
232
App::StringHasherRef hasher;
234
hasher = static_cast<App::StringHasherPy*>(pyHasher)->getStringHasherPtr();
236
auto& self = *getTopoShapePtr();
237
return Py::new_reference_to(shape2pyshape(
238
TopoShape(self.Tag, hasher)
239
.makeElementCopy(self, op, PyObject_IsTrue(copyGeom), PyObject_IsTrue(copyMesh))));
242
PyObject* TopoShapePy::cleaned(PyObject *args)
244
if (!PyArg_ParseTuple(args, ""))
246
auto& self = *getTopoShapePtr();
247
TopoShape copy(self.makeElementCopy());
248
if (!copy.isNull()) {
249
BRepTools::Clean(copy.getShape()); // remove triangulation
251
return Py::new_reference_to(shape2pyshape(copy));
254
PyObject* TopoShapePy::replaceShape(PyObject *args)
257
if (!PyArg_ParseTuple(args, "O",&l))
261
Py::Sequence list(l);
262
std::vector<std::pair<TopoShape, TopoShape>> shapes;
263
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
264
Py::Tuple tuple(*it);
265
Py::TopoShape sh1(tuple[0]);
266
Py::TopoShape sh2(tuple[1]);
267
shapes.push_back(std::make_pair(*sh1.extensionObject()->getTopoShapePtr(),
268
*sh2.extensionObject()->getTopoShapePtr()));
270
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->replaceElementShape(shapes)));
272
catch (const Py::Exception&) {
276
PyErr_SetString(PartExceptionOCCError, "failed to replace shape");
281
PyObject* TopoShapePy::removeShape(PyObject *args)
284
if (!PyArg_ParseTuple(args, "O",&l))
288
return Py::new_reference_to(
289
shape2pyshape(getTopoShapePtr()->removeElementShape(getPyShapes(l))));
292
PyErr_SetString(PartExceptionOCCError, "failed to remove shape");
297
PyObject* TopoShapePy::read(PyObject *args)
300
if (!PyArg_ParseTuple(args, "et","utf-8",&Name))
303
std::string EncodedName = std::string(Name);
306
getTopoShapePtr()->read(EncodedName.c_str());
310
PyObject* TopoShapePy::writeInventor(PyObject * args, PyObject * keywds)
312
static const std::array<const char *, 5> kwlist{"Mode", "Deviation", "Angle", "FaceColors", nullptr};
314
double dev = 0.3, angle = 0.4;
316
PyObject *pylist = nullptr;
317
if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, "|iddO", kwlist,
318
&mode, &dev, &angle, &pylist)) {
322
std::vector<App::Color> faceColors;
324
App::PropertyColorList prop;
325
prop.setPyObject(pylist);
326
faceColors = prop.getValues();
329
std::stringstream result;
330
BRepMesh_IncrementalMesh(getTopoShapePtr()->getShape(),dev);
332
getTopoShapePtr()->exportFaceSet(dev, angle, faceColors, result);
334
else if (mode == 1) {
335
getTopoShapePtr()->exportLineSet(result);
338
getTopoShapePtr()->exportFaceSet(dev, angle, faceColors, result);
339
getTopoShapePtr()->exportLineSet(result);
341
return Py::new_reference_to(Py::String(result.str()));
344
PyObject* TopoShapePy::exportIges(PyObject *args)
347
if (!PyArg_ParseTuple(args, "et","utf-8",&Name))
350
std::string EncodedName = std::string(Name);
355
getTopoShapePtr()->exportIges(EncodedName.c_str());
357
catch (const Base::Exception& e) {
358
PyErr_SetString(PartExceptionOCCError,e.what());
365
PyObject* TopoShapePy::exportStep(PyObject *args)
368
if (!PyArg_ParseTuple(args, "et","utf-8",&Name))
371
std::string EncodedName = std::string(Name);
376
getTopoShapePtr()->exportStep(EncodedName.c_str());
378
catch (const Base::Exception& e) {
379
PyErr_SetString(PartExceptionOCCError,e.what());
386
PyObject* TopoShapePy::exportBrep(PyObject *args)
389
if (PyArg_ParseTuple(args, "et","utf-8",&Name)) {
390
std::string EncodedName = std::string(Name);
395
getTopoShapePtr()->exportBrep(EncodedName.c_str());
397
catch (const Base::Exception& e) {
398
PyErr_SetString(PartExceptionOCCError,e.what());
408
if (PyArg_ParseTuple(args, "O", &input)) {
411
Base::PyStreambuf buf(input);
412
std::ostream str(nullptr);
414
getTopoShapePtr()->exportBrep(str);
416
catch (const Base::Exception& e) {
417
PyErr_SetString(PartExceptionOCCError,e.what());
424
PyErr_SetString(PyExc_TypeError, "expect string or file object");
428
PyObject* TopoShapePy::exportBinary(PyObject *args)
431
if (!PyArg_ParseTuple(args, "s", &input))
436
Base::FileInfo fi(input);
437
Base::ofstream str(fi, std::ios::out | std::ios::binary);
438
getTopoShapePtr()->exportBinary(str);
441
catch (const Base::Exception& e) {
442
PyErr_SetString(PartExceptionOCCError,e.what());
449
PyObject* TopoShapePy::dumpToString(PyObject *args)
451
if (!PyArg_ParseTuple(args, ""))
455
std::stringstream str;
456
getTopoShapePtr()->dump(str);
457
return Py::new_reference_to(Py::String(str.str()));
459
catch (const Base::Exception& e) {
460
PyErr_SetString(PartExceptionOCCError,e.what());
463
catch (const std::exception& e) {
464
PyErr_SetString(PartExceptionOCCError,e.what());
467
catch (Standard_Failure& e) {
469
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
474
PyObject* TopoShapePy::exportBrepToString(PyObject *args)
476
if (!PyArg_ParseTuple(args, ""))
481
std::stringstream str;
482
getTopoShapePtr()->exportBrep(str);
483
return Py::new_reference_to(Py::String(str.str()));
485
catch (const Base::Exception& e) {
486
PyErr_SetString(PartExceptionOCCError,e.what());
489
catch (const std::exception& e) {
490
PyErr_SetString(PartExceptionOCCError,e.what());
493
catch (Standard_Failure& e) {
494
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
499
PyObject* TopoShapePy::importBrep(PyObject *args)
502
if (PyArg_ParseTuple(args, "et","utf-8",&Name)) {
503
std::string EncodedName = std::string(Name);
508
getTopoShapePtr()->importBrep(EncodedName.c_str());
510
catch (const Base::Exception& e) {
511
PyErr_SetString(PartExceptionOCCError,e.what());
520
if (PyArg_ParseTuple(args, "O", &input)) {
523
Base::PyStreambuf buf(input);
524
std::istream str(nullptr);
526
getTopoShapePtr()->importBrep(str);
528
catch (const Base::Exception& e) {
529
PyErr_SetString(PartExceptionOCCError,e.what());
536
PyErr_SetString(PyExc_TypeError, "expect string or file object");
540
PyObject* TopoShapePy::importBinary(PyObject *args)
543
if (!PyArg_ParseTuple(args, "s", &input))
548
Base::FileInfo fi(input);
549
Base::ifstream str(fi, std::ios::in | std::ios::binary);
550
getTopoShapePtr()->importBinary(str);
553
catch (const Base::Exception& e) {
554
PyErr_SetString(PartExceptionOCCError,e.what());
561
PyObject* TopoShapePy::importBrepFromString(PyObject *args)
565
if (!PyArg_ParseTuple(args, "s|i", &input, &indicator))
570
std::stringstream str(input);
571
getTopoShapePtr()->importBrep(str,indicator);
573
catch (const Base::Exception& e) {
574
PyErr_SetString(PartExceptionOCCError,e.what());
577
catch (const std::exception& e) {
578
PyErr_SetString(PartExceptionOCCError,e.what());
581
catch (Standard_Failure& e) {
582
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
589
PyObject* TopoShapePy::dumps(PyObject *args) {
590
return exportBrepToString(args);
594
PyObject* TopoShapePy::loads(PyObject *args) {
595
if (! getTopoShapePtr()) {
596
PyErr_SetString(Base::PyExc_FC_GeneralError,"no c++ object");
600
return importBrepFromString(args);
604
PyObject* TopoShapePy::exportStl(PyObject *args)
606
double deflection = 0.01;
608
if (!PyArg_ParseTuple(args, "et|d","utf-8",&Name,&deflection))
611
std::string EncodedName = std::string(Name);
616
getTopoShapePtr()->exportStl(EncodedName.c_str(), deflection);
618
catch (const Base::Exception& e) {
619
PyErr_SetString(PartExceptionOCCError,e.what());
622
catch (Standard_Failure& e) {
623
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
630
PyObject* TopoShapePy::extrude(PyObject *args)
633
if (!PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type), &pVec))
637
Base::Vector3d vec = static_cast<Base::VectorPy*>(pVec)->value();
638
return Py::new_reference_to(
639
shape2pyshape(getTopoShapePtr()->makeElementPrism(gp_Vec(vec.x, vec.y, vec.z))));
641
catch (Standard_Failure& e) {
642
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
647
PyObject* TopoShapePy::revolve(PyObject *args)
649
PyObject *pPos,*pDir;
651
if (!PyArg_ParseTuple(args, "O!O!|d", &(Base::VectorPy::Type), &pPos, &(Base::VectorPy::Type), &pDir,&d))
653
Base::Vector3d pos = static_cast<Base::VectorPy*>(pPos)->value();
654
Base::Vector3d dir = static_cast<Base::VectorPy*>(pDir)->value();
656
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementRevolve(
657
gp_Ax1(gp_Pnt(pos.x, pos.y, pos.z), gp_Dir(dir.x, dir.y, dir.z)),
660
catch (Standard_Failure& e) {
661
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
666
PyObject* TopoShapePy::check(PyObject *args)
668
PyObject* runBopCheck = Py_False;
669
if (!PyArg_ParseTuple(args, "|O!", &(PyBool_Type), &runBopCheck))
672
if (!getTopoShapePtr()->getShape().IsNull()) {
673
std::stringstream str;
674
if (!getTopoShapePtr()->analyze(Base::asBoolean(runBopCheck), str)) {
675
PyErr_SetString(PyExc_ValueError, str.str().c_str());
683
static PyObject *makeShape(const char *op,const TopoShape &shape, PyObject *args) {
686
if (!PyArg_ParseTuple(args, "O|d", &pcObj,&tol))
689
std::vector<TopoShape> shapes;
690
shapes.push_back(shape);
691
getPyShapes(pcObj,shapes);
692
return Py::new_reference_to(shape2pyshape(TopoShape().makeElementBoolean(op,shapes,0,tol)));
696
PyObject* TopoShapePy::fuse(PyObject *args)
698
return makeShape(Part::OpCodes::Fuse, *getTopoShapePtr(), args);
701
PyObject* TopoShapePy::multiFuse(PyObject *args)
703
return makeShape(Part::OpCodes::Fuse, *getTopoShapePtr(), args);
706
PyObject* TopoShapePy::oldFuse(PyObject *args)
709
if (!PyArg_ParseTuple(args, "O!", &(TopoShapePy::Type), &pcObj))
712
TopoDS_Shape shape = static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape();
714
// Let's call algorithm computing a fuse operation:
715
TopoDS_Shape fusShape = this->getTopoShapePtr()->oldFuse(shape);
716
return new TopoShapePy(new TopoShape(fusShape));
718
catch (Standard_Failure& e) {
719
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
722
catch (const std::exception& e) {
723
PyErr_SetString(PartExceptionOCCError, e.what());
728
PyObject* TopoShapePy::common(PyObject *args)
730
return makeShape(Part::OpCodes::Common, *getTopoShapePtr(), args);
733
PyObject* TopoShapePy::section(PyObject *args)
735
return makeShape(Part::OpCodes::Section, *getTopoShapePtr(), args);
738
PyObject* TopoShapePy::slice(PyObject *args)
742
if (!PyArg_ParseTuple(args, "O!d", &(Base::VectorPy::Type), &dir, &d))
745
Base::Vector3d vec = Py::Vector(dir, false).toVector();
749
for (auto& w : getTopoShapePtr()->makeElementSlice(vec, d).getSubTopoShapes(TopAbs_WIRE)) {
750
wires.append(shape2pyshape(w));
752
return Py::new_reference_to(wires);
754
catch (Standard_Failure& e) {
756
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
759
catch (const std::exception& e) {
760
PyErr_SetString(PartExceptionOCCError, e.what());
765
PyObject* TopoShapePy::slices(PyObject *args)
767
PyObject *dir, *dist;
768
if (!PyArg_ParseTuple(args, "O!O", &(Base::VectorPy::Type), &dir, &dist))
772
Base::Vector3d vec = Py::Vector(dir, false).toVector();
773
Py::Sequence list(dist);
774
std::vector<double> d;
775
d.reserve(list.size());
776
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it)
777
d.push_back((double)Py::Float(*it));
778
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementSlices(vec, d)));
780
catch (Standard_Failure& e) {
781
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
784
catch (const std::exception& e) {
785
PyErr_SetString(PartExceptionOCCError, e.what());
790
PyObject* TopoShapePy::cut(PyObject *args)
792
return makeShape(Part::OpCodes::Cut, *getTopoShapePtr(), args);
795
PyObject* TopoShapePy::generalFuse(PyObject *args)
797
double tolerance = 0.0;
799
if (!PyArg_ParseTuple(args, "O|d", &pcObj, &tolerance))
802
std::vector<std::vector<TopoShape>> modifies;
803
std::vector<TopoShape> shapes;
804
shapes.push_back(*getTopoShapePtr());
806
getPyShapes(pcObj, shapes);
808
res.makeElementGeneralFuse(shapes, modifies, tolerance);
810
for (auto& mod : modifies) {
812
for (auto& sh : mod) {
813
shapesPy.append(shape2pyshape(sh));
815
mapPy.append(shapesPy);
818
ret[0] = shape2pyshape(res);
820
return Py::new_reference_to(ret);
825
PyObject* TopoShapePy::sewShape(PyObject *args)
827
double tolerance = 1.0e-06;
828
if (!PyArg_ParseTuple(args, "|d", &tolerance))
832
getTopoShapePtr()->sewShape();
835
catch (Standard_Failure& e) {
836
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
841
PyObject* TopoShapePy::childShapes(PyObject *args)
843
PyObject* cumOri = Py_True;
844
PyObject* cumLoc = Py_True;
845
if (!PyArg_ParseTuple(args, "|O!O!", &(PyBool_Type), &cumOri, &(PyBool_Type), &cumLoc))
848
TopoShape shape = *getTopoShapePtr();
849
if (!PyObject_IsTrue(cumOri)) {
850
shape.setShape(shape.getShape().Oriented(TopAbs_FORWARD), false);
852
if (!PyObject_IsTrue(cumLoc)) {
853
shape.setShape(shape.getShape().Located(TopLoc_Location()), false);
858
for (auto& s : shape.getSubTopoShapes()) {
859
list.append(shape2pyshape(s));
861
return Py::new_reference_to(list);
867
// Containers to associate TopAbs_ShapeEnum values to each TopoShape*Py class
868
static const std::vector<std::pair<PyTypeObject*, TopAbs_ShapeEnum>> vecTypeShape = {
869
{&TopoShapeCompoundPy::Type, TopAbs_COMPOUND},
870
{&TopoShapeCompSolidPy::Type, TopAbs_COMPSOLID},
871
{&TopoShapeSolidPy::Type, TopAbs_SOLID},
872
{&TopoShapeShellPy::Type, TopAbs_SHELL},
873
{&TopoShapeFacePy::Type, TopAbs_FACE},
874
{&TopoShapeWirePy::Type, TopAbs_WIRE},
875
{&TopoShapeEdgePy::Type, TopAbs_EDGE},
876
{&TopoShapeVertexPy::Type, TopAbs_VERTEX},
877
{&TopoShapePy::Type, TopAbs_SHAPE}
880
static const std::map<PyTypeObject*, TopAbs_ShapeEnum> mapTypeShape(
881
vecTypeShape.begin(), vecTypeShape.end());
883
// Returns shape type of a Python type. Similar to TopAbs::ShapeTypeFromString.
884
// Returns TopAbs_SHAPE if pyType is not a subclass of any of the TopoShape*Py.
885
static TopAbs_ShapeEnum ShapeTypeFromPyType(PyTypeObject* pyType)
887
for (const auto & it : vecTypeShape) {
888
if (PyType_IsSubtype(pyType, it.first))
895
PyObject* TopoShapePy::ancestorsOfType(PyObject *args)
899
if (!PyArg_ParseTuple(args, "O!O!", &(TopoShapePy::Type), &pcObj, &PyType_Type, &type))
903
const TopoDS_Shape& model = getTopoShapePtr()->getShape();
904
const TopoDS_Shape& shape = static_cast<TopoShapePy*>(pcObj)->
905
getTopoShapePtr()->getShape();
906
if (model.IsNull() || shape.IsNull()) {
907
PyErr_SetString(PyExc_ValueError, "Shape is null");
911
PyTypeObject* pyType = reinterpret_cast<PyTypeObject*>(type);
912
TopAbs_ShapeEnum shapetype = ShapeTypeFromPyType(pyType);
913
if (!PyType_IsSubtype(pyType, &TopoShapePy::Type)) {
914
PyErr_SetString(PyExc_TypeError, "type must be a Shape subtype");
918
TopTools_IndexedDataMapOfShapeListOfShape mapOfShapeShape;
919
TopExp::MapShapesAndAncestors(model, shape.ShapeType(), shapetype, mapOfShapeShape);
920
const TopTools_ListOfShape& ancestors = mapOfShapeShape.FindFromKey(shape);
923
std::set<Standard_Integer> hashes;
924
TopTools_ListIteratorOfListOfShape it(ancestors);
925
for (; it.More(); it.Next()) {
926
// make sure to avoid duplicates
927
Standard_Integer code = ShapeMapHasher{}(it.Value());
928
if (hashes.find(code) == hashes.end()) {
929
list.append(shape2pyshape(it.Value()));
934
return Py::new_reference_to(list);
936
catch (Standard_Failure& e) {
937
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
942
PyObject* TopoShapePy::removeInternalWires(PyObject *args)
945
if (!PyArg_ParseTuple(args, "d",&minArea))
949
bool ok = getTopoShapePtr()->removeInternalWires(minArea);
950
PyObject* ret = ok ? Py_True : Py_False;
954
catch (Standard_Failure& e) {
955
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
960
PyObject* TopoShapePy::mirror(PyObject *args)
963
if (!PyArg_ParseTuple(args, "O!O!", &(Base::VectorPy::Type),&v1, &(Base::VectorPy::Type),&v2))
966
Base::Vector3d base = Py::Vector(v1,false).toVector();
967
Base::Vector3d norm = Py::Vector(v2,false).toVector();
970
gp_Ax2 ax2(gp_Pnt(base.x,base.y,base.z), gp_Dir(norm.x,norm.y,norm.z));
971
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementMirror(ax2)));
973
catch (Standard_Failure& e) {
974
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
979
PyObject* TopoShapePy::transformGeometry(PyObject *args)
982
PyObject *cpy = Py_False;
983
if (!PyArg_ParseTuple(args, "O!|O!", &(Base::MatrixPy::Type), &obj, &PyBool_Type, &cpy))
987
Base::Matrix4D mat = static_cast<Base::MatrixPy*>(obj)->value();
988
TopoDS_Shape shape = this->getTopoShapePtr()->transformGShape(mat, Base::asBoolean(cpy));
989
return new TopoShapePy(new TopoShape(shape));
991
catch (Standard_Failure& e) {
992
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
997
PyObject* TopoShapePy::transformShape(PyObject *args)
1000
PyObject *copy = Py_False;
1001
PyObject *checkScale = Py_False;
1002
if (!PyArg_ParseTuple(args, "O!|O!O!", &(Base::MatrixPy::Type),&obj,&(PyBool_Type), ©, &(PyBool_Type), &checkScale))
1005
Base::Matrix4D mat = static_cast<Base::MatrixPy*>(obj)->value();
1007
this->getTopoShapePtr()->transformShape(mat, Base::asBoolean(copy), Base::asBoolean(checkScale));
1013
PyObject* TopoShapePy::transformed(PyObject *args, PyObject *keywds)
1015
static const std::array<const char *, 5> kwlist{"matrix", "copy", "checkScale", "op", nullptr};
1017
PyObject *copy = Py_False;
1018
PyObject *checkScale = Py_False;
1019
const char *op = nullptr;
1020
if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, "O!|O!O!s", kwlist,
1021
&Base::MatrixPy::Type, &pymat, &PyBool_Type, ©, &PyBool_Type,
1022
&checkScale, &op)) {
1026
Base::Matrix4D mat = static_cast<Base::MatrixPy*>(pymat)->value();
1029
TopoShape s(*getTopoShapePtr());
1030
s.transformShape(mat,Base::asBoolean(copy), Base::asBoolean(checkScale));
1031
return Py::new_reference_to(shape2pyshape(s));
1036
PyObject* TopoShapePy::translate(PyObject *args)
1039
if (!PyArg_ParseTuple(args, "O", &obj))
1043
if (PyObject_TypeCheck(obj, &(Base::VectorPy::Type))) {
1044
vec = static_cast<Base::VectorPy*>(obj)->value();
1046
else if (PyObject_TypeCheck(obj, &PyTuple_Type)) {
1047
vec = Base::getVectorFromTuple<double>(obj);
1050
PyErr_SetString(PyExc_TypeError, "either vector or tuple expected");
1055
mov.SetTranslation(gp_Vec(vec.x,vec.y,vec.z));
1056
TopLoc_Location loc(mov);
1057
TopoDS_Shape shape = getTopoShapePtr()->getShape();
1059
getTopoShapePtr()->setShape(shape);
1064
PyObject* TopoShapePy::rotate(PyObject *args)
1066
PyObject *obj1, *obj2;
1068
if (!PyArg_ParseTuple(args, "OOd", &obj1, &obj2, &angle))
1072
// Vector also supports sequence
1073
Py::Sequence p1(obj1), p2(obj2);
1074
// Convert into OCC representation
1075
gp_Pnt pos = gp_Pnt((double)Py::Float(p1[0]),
1076
(double)Py::Float(p1[1]),
1077
(double)Py::Float(p1[2]));
1078
gp_Dir dir = gp_Dir((double)Py::Float(p2[0]),
1079
(double)Py::Float(p2[1]),
1080
(double)Py::Float(p2[2]));
1082
gp_Ax1 axis(pos, dir);
1084
mov.SetRotation(axis, angle*(M_PI/180));
1085
TopLoc_Location loc(mov);
1086
TopoDS_Shape shape = getTopoShapePtr()->getShape();
1088
getTopoShapePtr()->setShape(shape);
1095
PyObject* TopoShapePy::scale(PyObject *args)
1098
PyObject* p=nullptr;
1099
if (!PyArg_ParseTuple(args, "d|O!", &factor, &(Base::VectorPy::Type), &p))
1104
Base::Vector3d pnt = static_cast<Base::VectorPy*>(p)->value();
1109
if (fabs(factor) < Precision::Confusion()) {
1110
PyErr_SetString(PyExc_ValueError, "scale factor too small");
1115
const TopoDS_Shape& shape = getTopoShapePtr()->getShape();
1116
if (!shape.IsNull()) {
1118
scl.SetScale(pos, factor);
1119
BRepBuilderAPI_Transform BRepScale(scl);
1121
BRepScale.Perform(shape, bCopy);
1122
TopoShape copy(*getTopoShapePtr());
1123
getTopoShapePtr()->makeElementShape(BRepScale, copy);
1130
PyObject* TopoShapePy::translated(PyObject *args)
1132
Py::Object pyobj(shape2pyshape(*getTopoShapePtr()));
1133
return static_cast<TopoShapePy*>(pyobj.ptr())->translate(args);
1136
PyObject* TopoShapePy::rotated(PyObject *args)
1138
Py::Object pyobj(shape2pyshape(*getTopoShapePtr()));
1139
return static_cast<TopoShapePy*>(pyobj.ptr())->rotate(args);
1142
PyObject* TopoShapePy::scaled(PyObject *args)
1144
Py::Object pyobj(shape2pyshape(*getTopoShapePtr()));
1145
return static_cast<TopoShapePy*>(pyobj.ptr())->scale(args);
1148
PyObject* TopoShapePy::makeFillet(PyObject *args)
1150
// use two radii for all edges
1151
double radius1, radius2;
1153
if (!PyArg_ParseTuple(args, "ddO", &radius1, &radius2, &obj)) {
1155
if (!PyArg_ParseTuple(args, "dO", &radius1, &obj)) {
1156
PyErr_SetString(PyExc_TypeError,
1157
"This method accepts:\n"
1158
"-- one radius and a list of edges\n"
1159
"-- two radii and a list of edges");
1166
return Py::new_reference_to(shape2pyshape(
1167
getTopoShapePtr()->makeElementFillet(getPyShapes(obj), radius1, radius2)));
1171
// use one radius for all edges
1173
if (PyArg_ParseTuple(args, "dO", &radius, &obj)) {
1175
const TopoDS_Shape& shape = this->getTopoShapePtr()->getShape();
1176
BRepFilletAPI_MakeFillet mkFillet(shape);
1177
Py::Sequence list(obj);
1178
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
1179
if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) {
1180
const TopoDS_Shape& edge = static_cast<TopoShapePy*>((*it).ptr())->getTopoShapePtr()->getShape();
1181
if (edge.ShapeType() == TopAbs_EDGE) {
1182
//Add edge to fillet algorithm
1183
mkFillet.Add(radius, TopoDS::Edge(edge));
1187
return new TopoShapePy(new TopoShape(mkFillet.Shape()));
1189
catch (Standard_Failure& e) {
1190
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1195
PyErr_SetString(PyExc_TypeError, "This method accepts:\n"
1196
"-- one radius and a list of edges\n"
1197
"-- two radii and a list of edges");
1201
// TODO: Should this python interface support all three chamfer methods and not just two?
1202
PyObject* TopoShapePy::makeChamfer(PyObject *args)
1204
// use two radii for all edges
1205
double radius1, radius2;
1207
if (!PyArg_ParseTuple(args, "ddO", &radius1, &radius2, &obj)) {
1208
if (!PyArg_ParseTuple(args, "dO", &radius1, &obj)) {
1209
PyErr_SetString(PyExc_TypeError,
1210
"This method accepts:\n"
1211
"-- one radius and a list of edges\n"
1212
"-- two radii and a list of edges");
1220
return Py::new_reference_to(shape2pyshape(
1221
getTopoShapePtr()->makeElementChamfer(getPyShapes(obj), Part::ChamferType::twoDistances, radius1, radius2)));
1225
// use one radius for all edges
1226
// TODO: Should this be using makeElementChamfer to support Toponaming fixes?
1228
if (PyArg_ParseTuple(args, "dO", &radius, &obj)) {
1230
const TopoDS_Shape& shape = this->getTopoShapePtr()->getShape();
1231
BRepFilletAPI_MakeChamfer mkChamfer(shape);
1232
TopTools_IndexedMapOfShape mapOfEdges;
1233
TopTools_IndexedDataMapOfShapeListOfShape mapEdgeFace;
1234
TopExp::MapShapesAndAncestors(shape, TopAbs_EDGE, TopAbs_FACE, mapEdgeFace);
1235
TopExp::MapShapes(shape, TopAbs_EDGE, mapOfEdges);
1236
Py::Sequence list(obj);
1237
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
1238
if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) {
1239
const TopoDS_Shape& edge = static_cast<TopoShapePy*>((*it).ptr())->getTopoShapePtr()->getShape();
1240
if (edge.ShapeType() == TopAbs_EDGE) {
1241
//Add edge to fillet algorithm
1242
const TopoDS_Face& face = TopoDS::Face(mapEdgeFace.FindFromKey(edge).First());
1243
mkChamfer.Add(radius, radius, TopoDS::Edge(edge), face);
1247
return new TopoShapePy(new TopoShape(mkChamfer.Shape()));
1249
catch (Standard_Failure& e) {
1250
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1255
PyErr_SetString(PyExc_TypeError, "This method accepts:\n"
1256
"-- one radius and a list of edges\n"
1257
"-- two radii and a list of edges");
1261
PyObject* TopoShapePy::makeThickness(PyObject *args)
1264
double offset, tolerance;
1265
PyObject* inter = Py_False;
1266
PyObject* self_inter = Py_False;
1267
short offsetMode = 0, join = 0;
1268
if (!PyArg_ParseTuple(args, "Odd|O!O!hh", &obj, &offset, &tolerance,
1269
&(PyBool_Type), &inter, &(PyBool_Type), &self_inter, &offsetMode, &join))
1273
return Py::new_reference_to(shape2pyshape(
1274
getTopoShapePtr()->makeElementThickSolid(getPyShapes(obj),
1277
PyObject_IsTrue(inter) ? true : false,
1278
PyObject_IsTrue(self_inter) ? true : false,
1280
static_cast<JoinType>(join))));
1282
catch (Standard_Failure& e) {
1283
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1288
PyObject* TopoShapePy::makeOffsetShape(PyObject *args, PyObject *keywds)
1290
static const std::array<const char *, 8> kwlist{"offset", "tolerance", "inter", "self_inter", "offsetMode", "join",
1292
double offset, tolerance;
1293
PyObject *inter = Py_False;
1294
PyObject *self_inter = Py_False;
1295
PyObject *fill = Py_False;
1296
short offsetMode = 0, join = 0;
1297
if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, "dd|O!O!hhO!", kwlist, &offset, &tolerance,
1298
&(PyBool_Type), &inter, &(PyBool_Type), &self_inter, &offsetMode, &join,
1299
&(PyBool_Type), &fill)) {
1304
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementOffset(
1307
PyObject_IsTrue(inter) ? true : false,
1308
PyObject_IsTrue(self_inter) ? true : false,
1310
static_cast<JoinType>(join),
1311
PyObject_IsTrue(fill) ? FillType::fill : FillType::noFill)));
1313
catch (Standard_Failure& e) {
1314
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1319
PyObject* TopoShapePy::makeOffset2D(PyObject *args, PyObject *keywds)
1321
static const std::array<const char *, 6> kwlist {"offset", "join", "fill", "openResult", "intersection", nullptr};
1323
PyObject* fill = Py_False;
1324
PyObject* openResult = Py_False;
1325
PyObject* inter = Py_False;
1327
if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, "d|hO!O!O!", kwlist, &offset, &join,
1328
&(PyBool_Type), &fill, &(PyBool_Type), &openResult, &(PyBool_Type),
1334
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementOffset2D(
1336
static_cast<JoinType>(join),
1337
PyObject_IsTrue(fill) ? FillType::fill : FillType::noFill,
1338
PyObject_IsTrue(openResult) ? OpenResult::allowOpenResult : OpenResult::noOpenResult,
1339
PyObject_IsTrue(inter) ? true : false)));
1344
PyObject* TopoShapePy::reverse(PyObject *args)
1346
if (!PyArg_ParseTuple(args, ""))
1349
TopoDS_Shape shape = getTopoShapePtr()->getShape();
1351
getTopoShapePtr()->setShape(shape);
1356
PyObject* TopoShapePy::reversed(PyObject *args)
1358
if (!PyArg_ParseTuple(args, ""))
1361
TopoDS_Shape shape = getTopoShapePtr()->getShape();
1362
shape = shape.Reversed();
1364
PyTypeObject* type = this->GetType();
1365
PyObject* cpy = nullptr;
1367
// let the type object decide
1369
cpy = type->tp_new(type, this, nullptr);
1371
PyErr_SetString(PyExc_TypeError, "failed to create copy of shape");
1375
if (!shape.IsNull()) {
1376
static_cast<TopoShapePy*>(cpy)->getTopoShapePtr()->setShape(shape);
1381
PyObject* TopoShapePy::complement(PyObject *args)
1383
if (!PyArg_ParseTuple(args, ""))
1386
TopoDS_Shape shape = getTopoShapePtr()->getShape();
1388
getTopoShapePtr()->setShape(shape);
1393
PyObject* TopoShapePy::nullify(PyObject *args)
1395
if (!PyArg_ParseTuple(args, ""))
1398
TopoDS_Shape shape = getTopoShapePtr()->getShape();
1400
getTopoShapePtr()->setShape(shape);
1405
PyObject* TopoShapePy::isNull(PyObject *args)
1407
if (!PyArg_ParseTuple(args, ""))
1410
bool null = getTopoShapePtr()->isNull();
1411
return Py_BuildValue("O", (null ? Py_True : Py_False));
1414
PyObject* TopoShapePy::isClosed(PyObject *args)
1416
if (!PyArg_ParseTuple(args, ""))
1420
if (getTopoShapePtr()->getShape().IsNull())
1421
Standard_Failure::Raise("Cannot determine the 'Closed'' flag of an empty shape");
1422
return Py_BuildValue("O", (getTopoShapePtr()->isClosed() ? Py_True : Py_False));
1425
PyErr_SetString(PyExc_RuntimeError, "check failed, shape may be empty");
1430
PyObject* TopoShapePy::isEqual(PyObject *args)
1433
if (!PyArg_ParseTuple(args, "O!", &(TopoShapePy::Type), &pcObj))
1436
TopoDS_Shape shape = static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape();
1437
Standard_Boolean test = (getTopoShapePtr()->getShape().IsEqual(shape));
1439
return Py_BuildValue("O", (test ? Py_True : Py_False));
1442
PyObject* TopoShapePy::isSame(PyObject *args)
1445
if (!PyArg_ParseTuple(args, "O!", &(TopoShapePy::Type), &pcObj))
1448
TopoDS_Shape shape = static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape();
1449
Standard_Boolean test = getTopoShapePtr()->getShape().IsSame(shape);
1451
return Py_BuildValue("O", (test ? Py_True : Py_False));
1454
PyObject* TopoShapePy::isPartner(PyObject *args)
1457
if (!PyArg_ParseTuple(args, "O!", &(TopoShapePy::Type), &pcObj))
1460
TopoDS_Shape shape = static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape();
1461
Standard_Boolean test = getTopoShapePtr()->getShape().IsPartner(shape);
1463
return Py_BuildValue("O", (test ? Py_True : Py_False));
1466
PyObject* TopoShapePy::isValid(PyObject *args)
1468
if (!PyArg_ParseTuple(args, ""))
1472
return Py_BuildValue("O", (getTopoShapePtr()->isValid() ? Py_True : Py_False));
1477
PyObject* TopoShapePy::isCoplanar(PyObject *args)
1481
if (!PyArg_ParseTuple(args, "O!|d", &TopoShapePy::Type, &pyObj, &tol))
1485
return Py::new_reference_to(Py::Boolean(getTopoShapePtr()->isCoplanar(
1486
*static_cast<TopoShapePy*>(pyObj)->getTopoShapePtr(),tol)));
1491
PyObject* TopoShapePy::isInfinite(PyObject *args)
1493
if (!PyArg_ParseTuple(args, ""))
1497
return Py::new_reference_to(Py::Boolean(getTopoShapePtr()->isInfinite()));
1502
PyObject* TopoShapePy::findPlane(PyObject *args)
1505
if (!PyArg_ParseTuple(args, "|d", &tol))
1510
if (getTopoShapePtr()->findPlane(pln, tol))
1511
return new PlanePy(new GeomPlane(new Geom_Plane(pln)));
1517
PyObject* TopoShapePy::fix(PyObject *args)
1519
double prec, mintol, maxtol;
1520
if (!PyArg_ParseTuple(args, "ddd", &prec, &mintol, &maxtol))
1524
return Py_BuildValue("O", (getTopoShapePtr()->fix(prec, mintol, maxtol) ? Py_True : Py_False));
1527
PyErr_SetString(PyExc_RuntimeError, "check failed, shape may be empty");
1532
PyObject* TopoShapePy::hashCode(PyObject *args)
1534
int upper = IntegerLast();
1535
if (!PyArg_ParseTuple(args, "|i",&upper))
1538
int hc = ShapeMapHasher{}(getTopoShapePtr()->getShape());
1539
return Py_BuildValue("i", hc);
1542
PyObject* TopoShapePy::tessellate(PyObject *args)
1545
PyObject* ok = Py_False;
1546
if (!PyArg_ParseTuple(args, "d|O!", &tolerance, &PyBool_Type, &ok))
1550
std::vector<Base::Vector3d> Points;
1551
std::vector<Data::ComplexGeoData::Facet> Facets;
1552
if (Base::asBoolean(ok))
1553
BRepTools::Clean(getTopoShapePtr()->getShape());
1554
getTopoShapePtr()->getFaces(Points, Facets,tolerance);
1557
for (const auto & Point : Points)
1558
vertex.append(Py::asObject(new Base::VectorPy(Point)));
1559
tuple.setItem(0, vertex);
1561
for (const auto& it : Facets) {
1563
f.setItem(0,Py::Long((long)it.I1));
1564
f.setItem(1,Py::Long((long)it.I2));
1565
f.setItem(2,Py::Long((long)it.I3));
1568
tuple.setItem(1, facet);
1569
return Py::new_reference_to(tuple);
1571
catch (Standard_Failure& e) {
1572
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1577
PyObject* TopoShapePy::project(PyObject *args)
1581
BRepAlgo_NormalProjection algo;
1582
algo.Init(this->getTopoShapePtr()->getShape());
1583
if (!PyArg_ParseTuple(args, "O", &obj))
1587
Py::Sequence list(obj);
1588
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
1589
if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) {
1590
const TopoDS_Shape& shape = static_cast<TopoShapePy*>((*it).ptr())->getTopoShapePtr()->getShape();
1595
algo.Compute3d(Standard_True);
1596
algo.SetLimit(Standard_True);
1597
algo.SetParams(1.e-6, 1.e-6, GeomAbs_C1, 14, 10000);
1598
//algo.SetDefaultParams();
1600
return new TopoShapePy(new TopoShape(algo.Projection()));
1602
catch (Standard_Failure&) {
1603
PyErr_SetString(PartExceptionOCCError, "Failed to project shape");
1608
PyObject* TopoShapePy::makeParallelProjection(PyObject *args)
1610
PyObject *pShape, *pDir;
1611
if (!PyArg_ParseTuple(args, "O!O!", &(Part::TopoShapePy::Type), &pShape, &Base::VectorPy::Type, &pDir))
1615
const TopoDS_Shape& shape = this->getTopoShapePtr()->getShape();
1616
const TopoDS_Shape& wire = static_cast<TopoShapePy*>(pShape)->getTopoShapePtr()->getShape();
1617
Base::Vector3d vec = Py::Vector(pDir,false).toVector();
1618
BRepProj_Projection proj(wire, shape, gp_Dir(vec.x,vec.y,vec.z));
1619
TopoDS_Shape projected = proj.Shape();
1620
return new TopoShapePy(new TopoShape(projected));
1622
catch (Standard_Failure& e) {
1623
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1628
PyObject* TopoShapePy::makePerspectiveProjection(PyObject *args)
1630
PyObject *pShape, *pDir;
1631
if (!PyArg_ParseTuple(args, "O!O!", &(Part::TopoShapePy::Type), &pShape, &Base::VectorPy::Type, &pDir))
1635
const TopoDS_Shape& shape = this->getTopoShapePtr()->getShape();
1636
const TopoDS_Shape& wire = static_cast<TopoShapePy*>(pShape)->getTopoShapePtr()->getShape();
1637
Base::Vector3d vec = Py::Vector(pDir,false).toVector();
1638
BRepProj_Projection proj(wire, shape, gp_Pnt(vec.x,vec.y,vec.z));
1639
TopoDS_Shape projected = proj.Shape();
1640
return new TopoShapePy(new TopoShape(projected));
1642
catch (Standard_Failure& e) {
1643
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1649
from pivy import coin
1651
rot=Gui.ActiveDocument.ActiveView.getCameraOrientation()
1652
vdir=App.Vector(0,0,-1)
1653
vdir=rot.multVec(vdir)
1654
udir=App.Vector(0,1,0)
1655
udir=rot.multVec(udir)
1657
pos=Gui.ActiveDocument.ActiveView.getCameraNode().position.getValue().getValue()
1660
shape=App.ActiveDocument.ActiveObject.Shape
1661
reflect=shape.reflectLines(ViewDir=vdir, ViewPos=pos, UpDir=udir, EdgeType="Sharp", Visible=True, OnShape=False)
1664
PyObject* TopoShapePy::reflectLines(PyObject *args, PyObject *kwds)
1666
static const std::array<const char *, 7> kwlist{"ViewDir", "ViewPos", "UpDir", "EdgeType", "Visible", "OnShape",
1669
const char* type="OutLine";
1670
PyObject* vis = Py_True;
1671
PyObject* in3d = Py_False;
1672
PyObject* pPos = nullptr;
1673
PyObject* pUp = nullptr;
1675
if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "O!|O!O!sO!O!", kwlist,
1676
&Base::VectorPy::Type, &pView, &Base::VectorPy::Type, &pPos,
1677
&Base::VectorPy::Type,
1678
&pUp, &type, &PyBool_Type, &vis, &PyBool_Type, &in3d)) {
1683
HLRBRep_TypeOfResultingEdge t;
1684
std::string str = type;
1685
if (str == "IsoLine")
1686
t = HLRBRep_IsoLine;
1687
else if (str == "Rg1Line")
1688
t = HLRBRep_Rg1Line;
1689
else if (str == "RgNLine")
1690
t = HLRBRep_RgNLine;
1691
else if (str == "Sharp")
1694
t = HLRBRep_OutLine;
1696
Base::Vector3d p(0.0, 0.0, 0.0);
1698
p = Py::Vector(pPos,false).toVector();
1699
Base::Vector3d u(0.0, 1.0, 0.0);
1701
u = Py::Vector(pUp,false).toVector();
1703
Base::Vector3d v = Py::Vector(pView,false).toVector();
1704
const TopoDS_Shape& shape = this->getTopoShapePtr()->getShape();
1705
HLRAppli_ReflectLines reflect(shape);
1706
reflect.SetAxes(v.x, v.y, v.z, p.x, p.y, p.z, u.x, u.y, u.z);
1708
TopoDS_Shape lines = reflect.GetCompoundOf3dEdges(t, Base::asBoolean(vis), Base::asBoolean(in3d));
1709
return new TopoShapePy(new TopoShape(lines));
1711
catch (Standard_Failure& e) {
1712
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1717
PyObject* TopoShapePy::makeShapeFromMesh(PyObject *args)
1720
double tolerance = 1.0e-06;
1721
PyObject* sewShape = Py_True;
1722
if (!PyArg_ParseTuple(args, "O!|dO!",&PyTuple_Type, &tup, &tolerance, &PyBool_Type, &sewShape))
1726
Py::Tuple tuple(tup);
1727
Py::Sequence vertex(tuple[0]);
1728
Py::Sequence facets(tuple[1]);
1730
std::vector<Base::Vector3d> Points;
1731
for (Py::Sequence::iterator it = vertex.begin(); it != vertex.end(); ++it) {
1732
Py::Vector vec(*it);
1733
Points.push_back(vec.toVector());
1735
std::vector<Data::ComplexGeoData::Facet> Facets;
1736
for (Py::Sequence::iterator it = facets.begin(); it != facets.end(); ++it) {
1737
Data::ComplexGeoData::Facet face;
1739
face.I1 = (int)Py::Long(f[0]);
1740
face.I2 = (int)Py::Long(f[1]);
1741
face.I3 = (int)Py::Long(f[2]);
1742
Facets.push_back(face);
1745
getTopoShapePtr()->setFaces(Points, Facets, tolerance);
1746
if (Base::asBoolean(sewShape))
1747
getTopoShapePtr()->sewShape(tolerance);
1754
PyObject* TopoShapePy::makeEvolved(PyObject *args, PyObject *kwds)
1757
PyObject* AxeProf = Py_True;
1758
PyObject* Solid = Py_False;
1759
PyObject* ProfOnSpine = Py_False;
1760
auto JoinType = JoinType::arc;
1761
double Tolerance = 0.0000001;
1763
static const std::array<const char*, 7> kwds_evolve{"Profile", "Join", "AxeProf", "Solid", "ProfOnSpine", "Tolerance", nullptr};
1764
if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "O!|iO!O!O!d", kwds_evolve,
1765
&TopoShapePy::Type, &Profile, &JoinType,
1766
&PyBool_Type, &AxeProf, &PyBool_Type, &Solid,
1767
&PyBool_Type, &ProfOnSpine, &Tolerance)) {
1771
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementEvolve(
1772
*static_cast<TopoShapePy*>(Profile)->getTopoShapePtr(), JoinType,
1773
PyObject_IsTrue(AxeProf) ? CoordinateSystem::global : CoordinateSystem::relativeToSpine,
1774
PyObject_IsTrue(Solid) ? MakeSolid::makeSolid : MakeSolid::noSolid,
1775
PyObject_IsTrue(ProfOnSpine) ? Spine::on : Spine::notOn,
1780
PyObject* TopoShapePy::makeWires(PyObject *args) {
1781
const char *op = nullptr;
1782
if (!PyArg_ParseTuple(args, "s", &op))
1786
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeWires(op)));
1791
PyObject* TopoShapePy::toNurbs(PyObject *args)
1793
if (!PyArg_ParseTuple(args, ""))
1797
// Convert into nurbs
1798
TopoDS_Shape nurbs = this->getTopoShapePtr()->toNurbs();
1799
return new TopoShapePy(new TopoShape(nurbs));
1801
catch (Standard_Failure& e) {
1802
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1807
PyObject* TopoShapePy::isInside(PyObject *args)
1811
PyObject* checkFace = Py_False;
1812
TopAbs_State stateIn = TopAbs_IN;
1813
if (!PyArg_ParseTuple(args, "O!dO!", &(Base::VectorPy::Type), &point, &tolerance, &PyBool_Type, &checkFace))
1817
TopoDS_Shape shape = getTopoShapePtr()->getShape();
1818
if (shape.IsNull()) {
1819
PyErr_SetString(PartExceptionOCCError, "Cannot handle null shape");
1823
Base::Vector3d pnt = static_cast<Base::VectorPy*>(point)->value();
1824
gp_Pnt vertex = gp_Pnt(pnt.x,pnt.y,pnt.z);
1825
if (shape.ShapeType() == TopAbs_VERTEX ||
1826
shape.ShapeType() == TopAbs_EDGE ||
1827
shape.ShapeType() == TopAbs_WIRE ||
1828
shape.ShapeType() == TopAbs_FACE) {
1830
BRepBuilderAPI_MakeVertex mkVertex(vertex);
1831
BRepExtrema_DistShapeShape extss;
1832
extss.LoadS1(mkVertex.Vertex());
1833
extss.LoadS2(shape);
1834
if (!extss.Perform()) {
1835
PyErr_SetString(PartExceptionOCCError, "Failed to determine distance to shape");
1838
Standard_Boolean test = (extss.Value() <= tolerance);
1839
return Py_BuildValue("O", (test ? Py_True : Py_False));
1842
BRepClass3d_SolidClassifier solidClassifier(shape);
1843
solidClassifier.Perform(vertex, tolerance);
1844
Standard_Boolean test = (solidClassifier.State() == stateIn);
1846
if (Base::asBoolean(checkFace) && solidClassifier.IsOnAFace())
1847
test = Standard_True;
1848
return Py_BuildValue("O", (test ? Py_True : Py_False));
1851
catch (Standard_Failure& e) {
1852
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1855
catch (const std::exception& e) {
1856
PyErr_SetString(PartExceptionOCCError, e.what());
1861
PyObject* TopoShapePy::removeSplitter(PyObject *args)
1863
if (!PyArg_ParseTuple(args, ""))
1867
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementRefine()));
1869
catch (Standard_Failure& e) {
1870
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1875
PyObject* TopoShapePy::getElement(PyObject *args)
1878
PyObject* silent = Py_False;
1879
if (!PyArg_ParseTuple(args, "s|O", &input, &silent)) {
1883
PyObject* res = getTopoShapePtr()->getPySubShape(input, PyObject_IsTrue(silent));
1892
PyObject* TopoShapePy::countElement(PyObject *args)
1895
if (!PyArg_ParseTuple(args, "s", &input))
1899
return Py::new_reference_to(Py::Int((long)getTopoShapePtr()->countSubShapes(input)));
1904
PyObject* TopoShapePy::getTolerance(PyObject *args)
1907
PyObject* type = reinterpret_cast<PyObject*>(&TopoShapePy::Type);
1908
if (!PyArg_ParseTuple(args, "i|O!", &mode, &PyType_Type, &type))
1912
TopoDS_Shape shape = this->getTopoShapePtr()->getShape();
1913
PyTypeObject* pyType = reinterpret_cast<PyTypeObject*>(type);
1914
TopAbs_ShapeEnum shapetype = ShapeTypeFromPyType(pyType);
1915
if (!PyType_IsSubtype(pyType, &TopoShapePy::Type) ||
1916
(shapetype != TopAbs_SHAPE && shapetype != TopAbs_VERTEX &&
1917
shapetype != TopAbs_EDGE && shapetype != TopAbs_FACE && shapetype != TopAbs_SHELL)) {
1918
PyErr_SetString(PyExc_TypeError, "shape type must be Shape, Vertex, Edge, Face or Shell");
1922
ShapeAnalysis_ShapeTolerance analysis;
1923
double tolerance = analysis.Tolerance(shape, mode, shapetype);
1924
return PyFloat_FromDouble(tolerance);
1926
catch (Standard_Failure& e) {
1927
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1932
PyObject* TopoShapePy::overTolerance(PyObject *args)
1935
PyObject* type = reinterpret_cast<PyObject*>(&TopoShapePy::Type);
1936
if (!PyArg_ParseTuple(args, "d|O!", &value, &PyType_Type, &type))
1940
TopoDS_Shape shape = this->getTopoShapePtr()->getShape();
1941
PyTypeObject* pyType = reinterpret_cast<PyTypeObject*>(type);
1942
TopAbs_ShapeEnum shapetype = ShapeTypeFromPyType(pyType);
1943
if (!PyType_IsSubtype(pyType, &TopoShapePy::Type) ||
1944
(shapetype != TopAbs_SHAPE && shapetype != TopAbs_VERTEX &&
1945
shapetype != TopAbs_EDGE && shapetype != TopAbs_FACE && shapetype != TopAbs_SHELL)) {
1946
PyErr_SetString(PyExc_TypeError, "shape type must be Shape, Vertex, Edge, Face or Shell");
1950
ShapeAnalysis_ShapeTolerance analysis;
1951
Handle(TopTools_HSequenceOfShape) seq = analysis.OverTolerance(shape, value, shapetype);
1952
Py::Tuple tuple(seq->Length());
1953
std::size_t index=0;
1954
for (int i=1; i <= seq->Length(); i++) {
1955
TopoDS_Shape item = seq->Value(i);
1956
tuple.setItem(index++, shape2pyshape(item));
1958
return Py::new_reference_to(tuple);
1960
catch (Standard_Failure& e) {
1961
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
1966
PyObject* TopoShapePy::inTolerance(PyObject *args)
1970
PyObject* type = reinterpret_cast<PyObject*>(&TopoShapePy::Type);
1971
if (!PyArg_ParseTuple(args, "dd|O!", &valmin, &valmax, &PyType_Type, &type))
1975
TopoDS_Shape shape = this->getTopoShapePtr()->getShape();
1976
PyTypeObject* pyType = reinterpret_cast<PyTypeObject*>(type);
1977
TopAbs_ShapeEnum shapetype = ShapeTypeFromPyType(pyType);
1978
if (!PyType_IsSubtype(pyType, &TopoShapePy::Type) ||
1979
(shapetype != TopAbs_SHAPE && shapetype != TopAbs_VERTEX &&
1980
shapetype != TopAbs_EDGE && shapetype != TopAbs_FACE && shapetype != TopAbs_SHELL)) {
1981
PyErr_SetString(PyExc_TypeError, "shape type must be Shape, Vertex, Edge, Face or Shell");
1985
ShapeAnalysis_ShapeTolerance analysis;
1986
Handle(TopTools_HSequenceOfShape) seq = analysis.InTolerance(shape, valmin, valmax, shapetype);
1987
Py::Tuple tuple(seq->Length());
1988
std::size_t index=0;
1989
for (int i=1; i <= seq->Length(); i++) {
1990
TopoDS_Shape item = seq->Value(i);
1991
tuple.setItem(index++, shape2pyshape(item));
1993
return Py::new_reference_to(tuple);
1995
catch (Standard_Failure& e) {
1996
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
2001
PyObject* TopoShapePy::globalTolerance(PyObject *args)
2004
if (!PyArg_ParseTuple(args, "i", &mode))
2008
TopoDS_Shape shape = this->getTopoShapePtr()->getShape();
2009
ShapeAnalysis_ShapeTolerance analysis;
2010
analysis.Tolerance(shape, mode);
2011
double tolerance = analysis.GlobalTolerance(mode);
2013
return PyFloat_FromDouble(tolerance);
2015
catch (Standard_Failure& e) {
2016
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
2021
PyObject* TopoShapePy::fixTolerance(PyObject *args)
2024
PyObject* type = reinterpret_cast<PyObject*>(&TopoShapePy::Type);
2025
if (!PyArg_ParseTuple(args, "d|O!", &value, &PyType_Type, &type))
2029
TopoDS_Shape shape = this->getTopoShapePtr()->getShape();
2030
PyTypeObject* pyType = reinterpret_cast<PyTypeObject*>(type);
2031
TopAbs_ShapeEnum shapetype = ShapeTypeFromPyType(pyType);
2032
if (!PyType_IsSubtype(pyType, &TopoShapePy::Type)) {
2033
PyErr_SetString(PyExc_TypeError, "type must be a Shape subtype");
2037
ShapeFix_ShapeTolerance fix;
2038
fix.SetTolerance(shape, value, shapetype);
2041
catch (Standard_Failure& e) {
2042
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
2047
PyObject* TopoShapePy::limitTolerance(PyObject *args)
2051
PyObject* type = reinterpret_cast<PyObject*>(&TopoShapePy::Type);
2052
if (!PyArg_ParseTuple(args, "d|dO!", &tmin, &tmax, &PyType_Type, &type))
2056
TopoDS_Shape shape = this->getTopoShapePtr()->getShape();
2057
PyTypeObject* pyType = reinterpret_cast<PyTypeObject*>(type);
2058
TopAbs_ShapeEnum shapetype = ShapeTypeFromPyType(pyType);
2059
if (!PyType_IsSubtype(pyType, &TopoShapePy::Type)) {
2060
PyErr_SetString(PyExc_TypeError, "type must be a Shape subtype");
2064
ShapeFix_ShapeTolerance fix;
2065
Standard_Boolean ok = fix.LimitTolerance(shape, tmin, tmax, shapetype);
2066
return PyBool_FromLong(ok ? 1 : 0);
2068
catch (Standard_Failure& e) {
2069
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
2074
PyObject* _getSupportIndex(const char* suppStr, TopoShape* ts, TopoDS_Shape suppShape) {
2075
std::stringstream ss;
2076
TopoDS_Shape subShape;
2078
unsigned long nSubShapes = ts->countSubShapes(suppStr);
2079
long supportIndex = -1;
2080
for (unsigned long j=1; j<=nSubShapes; j++){
2083
subShape = ts->getSubShape(ss.str().c_str());
2084
if (subShape.IsEqual(suppShape)) {
2089
return PyLong_FromLong(supportIndex);
2092
PyObject* TopoShapePy::proximity(PyObject *args)
2094
using BRepExtrema_OverlappedSubShapes = BRepExtrema_MapOfIntegerPackedMapOfInteger;
2097
Standard_Real tol = Precision::Confusion();
2098
if (!PyArg_ParseTuple(args, "O!|d",&(TopoShapePy::Type), &ps2, &tol))
2101
const TopoDS_Shape& s1 = getTopoShapePtr()->getShape();
2102
const TopoDS_Shape& s2 = static_cast<Part::TopoShapePy*>(ps2)->getTopoShapePtr()->getShape();
2104
PyErr_SetString(PyExc_ValueError, "proximity: Shape object is invalid");
2108
PyErr_SetString(PyExc_ValueError, "proximity: Shape parameter is invalid");
2112
BRepExtrema_ShapeProximity proximity;
2113
proximity.LoadShape1 (s1);
2114
proximity.LoadShape2 (s2);
2116
proximity.SetTolerance (tol);
2119
proximity.Perform();
2120
if (!proximity.IsDone()) {
2121
PyErr_SetString(PartExceptionOCCError, "BRepExtrema_ShapeProximity failed, make sure the shapes are tessellated");
2125
Py::List overlappssindex1;
2126
Py::List overlappssindex2;
2128
for (BRepExtrema_OverlappedSubShapes::Iterator anIt1 (proximity.OverlapSubShapes1()); anIt1.More(); anIt1.Next()) {
2129
overlappssindex1.append(Py::Long(anIt1.Key() + 1));
2131
for (BRepExtrema_OverlappedSubShapes::Iterator anIt2 (proximity.OverlapSubShapes2()); anIt2.More(); anIt2.Next()) {
2132
overlappssindex2.append(Py::Long(anIt2.Key() + 1));
2136
tuple.setItem(0, overlappssindex1);
2137
tuple.setItem(1, overlappssindex2);
2138
return Py::new_reference_to(tuple); //face indexes
2142
PyObject* TopoShapePy::distToShape(PyObject *args)
2146
BRepExtrema_SupportType supportType1, supportType2;
2147
TopoDS_Shape suppS1, suppS2;
2148
Standard_Real minDist = -1, t1, t2, u1, v1, u2, v2;
2149
Standard_Real tol = Precision::Confusion();
2151
if (!PyArg_ParseTuple(args, "O!|d",&(TopoShapePy::Type), &ps2, &tol))
2154
const TopoDS_Shape& s1 = getTopoShapePtr()->getShape();
2155
TopoShape* ts1 = getTopoShapePtr();
2156
const TopoDS_Shape& s2 = static_cast<Part::TopoShapePy*>(ps2)->getTopoShapePtr()->getShape();
2157
TopoShape* ts2 = static_cast<Part::TopoShapePy*>(ps2)->getTopoShapePtr();
2160
PyErr_SetString(PyExc_TypeError, "distToShape: Shape parameter is invalid");
2163
BRepExtrema_DistShapeShape extss;
2164
extss.SetDeflection(tol);
2165
#if OCC_VERSION_HEX >= 0x070600
2166
extss.SetMultiThread(true);
2173
catch (const Standard_Failure& e) {
2174
PyErr_SetString(PyExc_RuntimeError, e.GetMessageString());
2177
if (!extss.IsDone()) {
2178
PyErr_SetString(PyExc_RuntimeError, "BRepExtrema_DistShapeShape failed");
2183
int count = extss.NbSolution();
2185
minDist = extss.Value();
2186
//extss.Dump(std::cout);
2187
for (int i=1; i<= count; i++) {
2188
Py::Object pt1, pt2;
2189
Py::String suppType1, suppType2;
2190
Py::Long suppIndex1, suppIndex2;
2191
Py::Object param1, param2;
2193
P1 = extss.PointOnShape1(i);
2194
pt1 = Py::asObject(new Base::VectorPy(new Base::Vector3d(P1.X(), P1.Y(), P1.Z())));
2195
supportType1 = extss.SupportTypeShape1(i);
2196
suppS1 = extss.SupportOnShape1(i);
2197
switch (supportType1) {
2198
case BRepExtrema_IsVertex:
2199
suppType1 = Py::String("Vertex");
2200
suppIndex1 = Py::asObject(_getSupportIndex("Vertex", ts1, suppS1));
2201
param1 = Py::None();
2203
case BRepExtrema_IsOnEdge:
2204
suppType1 = Py::String("Edge");
2205
suppIndex1 = Py::asObject(_getSupportIndex("Edge", ts1, suppS1));
2206
extss.ParOnEdgeS1(i,t1);
2207
param1 = Py::Float(t1);
2209
case BRepExtrema_IsInFace:
2210
suppType1 = Py::String("Face");
2211
suppIndex1 = Py::asObject(_getSupportIndex("Face", ts1, suppS1));
2212
extss.ParOnFaceS1(i,u1,v1);
2215
tup[0] = Py::Float(u1);
2216
tup[1] = Py::Float(v1);
2221
Base::Console().Message("distToShape: supportType1 is unknown: %d \n",
2222
static_cast<int>(supportType1));
2223
suppType1 = Py::String("Unknown");
2225
param1 = Py::None();
2228
P2 = extss.PointOnShape2(i);
2229
pt2 = Py::asObject(new Base::VectorPy(new Base::Vector3d(P2.X(), P2.Y(), P2.Z())));
2230
supportType2 = extss.SupportTypeShape2(i);
2231
suppS2 = extss.SupportOnShape2(i);
2232
switch (supportType2) {
2233
case BRepExtrema_IsVertex:
2234
suppType2 = Py::String("Vertex");
2235
suppIndex2 = Py::asObject(_getSupportIndex("Vertex", ts2, suppS2));
2236
param2 = Py::None();
2238
case BRepExtrema_IsOnEdge:
2239
suppType2 = Py::String("Edge");
2240
suppIndex2 = Py::asObject(_getSupportIndex("Edge", ts2, suppS2));
2241
extss.ParOnEdgeS2(i,t2);
2242
param2 = Py::Float(t2);
2244
case BRepExtrema_IsInFace:
2245
suppType2 = Py::String("Face");
2246
suppIndex2 = Py::asObject(_getSupportIndex("Face", ts2, suppS2));
2247
extss.ParOnFaceS2(i,u2,v2);
2250
tup[0] = Py::Float(u2);
2251
tup[1] = Py::Float(v2);
2256
Base::Console().Message("distToShape: supportType2 is unknown: %d \n",
2257
static_cast<int>(supportType2));
2258
suppType2 = Py::String("Unknown");
2260
param2 = Py::None();
2265
solnPts.append(pts);
2268
geom[0] = suppType1;
2269
geom[1] = suppIndex1;
2271
geom[3] = suppType2;
2272
geom[4] = suppIndex2;
2275
solnGeom.append(geom);
2279
PyErr_SetString(PyExc_TypeError, "distToShape: No Solutions Found.");
2283
ret[0] = Py::Float(minDist);
2286
return Py::new_reference_to(ret);
2289
PyObject* TopoShapePy::optimalBoundingBox(PyObject *args)
2291
PyObject* useT = Py_True;
2292
PyObject* useS = Py_False;
2293
if (!PyArg_ParseTuple(args, "|O!O!", &PyBool_Type, &useT, &PyBool_Type, &useS)) {
2298
TopoDS_Shape shape = this->getTopoShapePtr()->getShape();
2300
BRepBndLib::AddOptimal(shape, bounds,
2301
Base::asBoolean(useT),
2302
Base::asBoolean(useS));
2304
Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
2305
bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
2307
Base::BoundBox3d box;
2315
Py::BoundingBox pybox(box);
2316
return Py::new_reference_to(pybox);
2318
catch (const Standard_Failure& e) {
2319
throw Py::RuntimeError(e.GetMessageString());
2323
PyObject* TopoShapePy::clearCache(PyObject* args)
2325
if (!PyArg_ParseTuple(args, "")) {
2328
getTopoShapePtr()->initCache(1);
2332
PyObject* TopoShapePy::defeaturing(PyObject *args)
2335
if (!PyArg_ParseTuple(args, "O",&l))
2339
Py::Sequence list(l);
2340
std::vector<TopoDS_Shape> shapes;
2341
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
2342
Py::TopoShape sh(*it);
2344
sh.extensionObject()->getTopoShapePtr()->getShape()
2347
PyTypeObject* type = this->GetType();
2348
PyObject* inst = type->tp_new(type, this, nullptr);
2349
static_cast<TopoShapePy*>(inst)->getTopoShapePtr()->setShape
2350
(this->getTopoShapePtr()->defeaturing(shapes));
2353
catch (const Standard_Failure& e) {
2354
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
2359
PyObject* TopoShapePy::findSubShape(PyObject* args)
2362
if (!PyArg_ParseTuple(args, "O", &pyobj)) {
2369
for (auto& s : getPyShapes(pyobj)) {
2370
int index = getTopoShapePtr()->findShape(s.getShape());
2372
res.append(Py::TupleN(Py::String(s.shapeName()), Py::Int(index)));
2375
res.append(Py::TupleN(Py::Object(), Py::Int(0)));
2378
if (PySequence_Check(pyobj)) {
2379
return Py::new_reference_to(res);
2381
return Py::new_reference_to(Py::Object(res[0].ptr()));
2386
PyObject* TopoShapePy::findSubShapesWithSharedVertex(PyObject* args, PyObject* keywds)
2388
static const std::array<const char*, 7> kwlist {"shape", "needName", "checkGeometry", "tol", "atol", "singleResult", nullptr};
2390
PyObject* needName = Py_False;
2391
PyObject* checkGeometry = Py_True;
2392
PyObject* singleResult = Py_False;
2394
double atol = 1e-12;
2395
if (!Base::Wrapped_ParseTupleAndKeywords(args,
2412
const TopoShape& shape = *static_cast<TopoShapePy*>(pyobj)->getTopoShapePtr();
2413
Data::SearchOptions options;
2414
if (PyObject_IsTrue(checkGeometry))
2415
options.setFlag(Data::SearchOption::CheckGeometry);
2416
if (PyObject_IsTrue(singleResult))
2417
options.setFlag(Data::SearchOption::SingleResult);
2418
if (PyObject_IsTrue(needName)) {
2419
std::vector<std::string> names;
2420
auto shapes = getTopoShapePtr()->findSubShapesWithSharedVertex(
2426
for (std::size_t i = 0; i < shapes.size(); ++i) {
2427
res.append(Py::TupleN(Py::String(names[i]), shape2pyshape(shapes[i])));
2431
for (auto& s : getTopoShapePtr()->findSubShapesWithSharedVertex(
2437
res.append(shape2pyshape(s));
2440
return Py::new_reference_to(res);
2445
// End of Methods, Start of Attributes
2447
Py::String TopoShapePy::getShapeType() const
2449
TopoDS_Shape sh = getTopoShapePtr()->getShape();
2451
throw Py::Exception(Base::PyExc_FC_GeneralError, "cannot determine type of null shape");
2453
TopAbs_ShapeEnum type = sh.ShapeType();
2456
case TopAbs_COMPOUND:
2459
case TopAbs_COMPSOLID:
2485
return Py::String(name);
2488
Py::String TopoShapePy::getOrientation() const
2490
TopoDS_Shape sh = getTopoShapePtr()->getShape();
2492
throw Py::Exception(Base::PyExc_FC_GeneralError, "cannot determine orientation of null shape");
2494
TopAbs_Orientation type = sh.Orientation();
2497
case TopAbs_FORWARD:
2500
case TopAbs_REVERSED:
2503
case TopAbs_INTERNAL:
2506
case TopAbs_EXTERNAL:
2511
return Py::String(name);
2514
void TopoShapePy::setOrientation(Py::String arg)
2516
TopoDS_Shape sh = getTopoShapePtr()->getShape();
2518
throw Py::Exception(Base::PyExc_FC_GeneralError, "cannot determine orientation of null shape");
2520
std::string name = static_cast<std::string>(arg);
2521
TopAbs_Orientation type;
2522
if (name == "Forward") {
2523
type = TopAbs_FORWARD;
2525
else if (name == "Reversed") {
2526
type = TopAbs_REVERSED;
2528
else if (name == "Internal") {
2529
type = TopAbs_INTERNAL;
2531
else if (name == "External") {
2532
type = TopAbs_EXTERNAL;
2535
throw Py::AttributeError("Invalid orientation type");
2538
sh.Orientation(type);
2539
getTopoShapePtr()->setShape(sh);
2543
getElements(const TopoShape& sh, TopAbs_ShapeEnum type, TopAbs_ShapeEnum avoid = TopAbs_SHAPE)
2546
for (auto& shape : sh.getSubTopoShapes(type, avoid)) {
2547
ret.append(shape2pyshape(shape));
2552
PyObject* TopoShapePy::getChildShapes(PyObject* args)
2555
const char* avoid = nullptr;
2556
if (!PyArg_ParseTuple(args, "s|s", &type, &avoid)) {
2562
return Py::new_reference_to(
2563
getElements(*getTopoShapePtr(),
2564
TopoShape::shapeType(type),
2565
avoid && avoid[0] ? TopoShape::shapeType(avoid) : TopAbs_SHAPE));
2570
Py::List TopoShapePy::getSubShapes() const
2572
return getElements(*getTopoShapePtr(), TopAbs_SHAPE);
2575
Py::List TopoShapePy::getFaces() const
2577
return getElements(*getTopoShapePtr(), TopAbs_FACE);
2580
Py::List TopoShapePy::getVertexes() const
2582
return getElements(*getTopoShapePtr(), TopAbs_VERTEX);
2585
Py::List TopoShapePy::getShells() const
2587
return getElements(*getTopoShapePtr(), TopAbs_SHELL);
2590
Py::List TopoShapePy::getSolids() const
2592
return getElements(*getTopoShapePtr(), TopAbs_SOLID);
2595
Py::List TopoShapePy::getCompSolids() const
2597
return getElements(*getTopoShapePtr(), TopAbs_COMPSOLID);
2600
Py::List TopoShapePy::getEdges() const
2602
return getElements(*getTopoShapePtr(), TopAbs_EDGE);
2605
Py::List TopoShapePy::getWires() const
2607
return getElements(*getTopoShapePtr(), TopAbs_WIRE);
2610
Py::List TopoShapePy::getCompounds() const
2612
return getElements(*getTopoShapePtr(), TopAbs_COMPOUND);
2615
Py::Float TopoShapePy::getLength() const
2617
const TopoDS_Shape& shape = getTopoShapePtr()->getShape();
2619
throw Py::RuntimeError("shape is invalid");
2621
BRepGProp::LinearProperties(shape, props);
2622
return Py::Float(props.Mass());
2625
Py::Float TopoShapePy::getArea() const
2627
const TopoDS_Shape& shape = getTopoShapePtr()->getShape();
2629
throw Py::RuntimeError("shape is invalid");
2631
BRepGProp::SurfaceProperties(shape, props);
2632
return Py::Float(props.Mass());
2635
Py::Float TopoShapePy::getVolume() const
2637
const TopoDS_Shape& shape = getTopoShapePtr()->getShape();
2639
throw Py::RuntimeError("shape is invalid");
2641
BRepGProp::VolumeProperties(shape, props);
2642
return Py::Float(props.Mass());
2645
PyObject* TopoShapePy::getElementHistory(PyObject* args)
2648
if (!PyArg_ParseTuple(args, "s", &pyname)) {
2652
Data::MappedName name(pyname);
2655
Data::MappedName original;
2656
std::vector<Data::MappedName> history;
2657
long tag = getTopoShapePtr()->getElementHistory(name, &original, &history);
2662
ret.setItem(0, Py::Int(tag));
2664
ret.setItem(1, Py::String(original.appendToBuffer(tmp)));
2666
for (auto& h : history) {
2668
pyHistory.append(Py::String(h.appendToBuffer(tmp)));
2670
ret.setItem(2, pyHistory);
2671
return Py::new_reference_to(ret);
2676
struct PyShapeMapper: Part::ShapeMapper
2678
bool populate(MappingStatus status, PyObject* pyobj)
2680
if (!pyobj || pyobj == Py_None) {
2684
Py::Sequence seq(pyobj);
2685
for (size_t i = 0, count = seq.size(); i < count; ++i) {
2686
Py::Sequence item(seq[i].ptr());
2687
if (item.size() != 2) {
2691
Part::ShapeMapper::populate(status,
2692
getPyShapes(item[0].ptr()),
2693
getPyShapes(item[1].ptr()));
2696
catch (Py::Exception&) {
2703
void init(PyObject* g, PyObject* m)
2706
"Expect input mapping to be a list of tuple(srcShape|shapeList, dstShape|shapeList)";
2707
if (!populate(MappingStatus::Generated, g) || !populate(MappingStatus::Modified, m)) {
2708
throw Py::TypeError(msg);
2713
PyObject* TopoShapePy::mapShapes(PyObject* args)
2715
PyObject* generated;
2717
const char* op = nullptr;
2718
if (!PyArg_ParseTuple(args, "OO|s", &generated, &modified, &op)) {
2723
PyShapeMapper mapper;
2724
mapper.init(generated, modified);
2725
TopoShape& self = *getTopoShapePtr();
2726
TopoShape s(self.Tag, self.Hasher);
2727
s.makeShapeWithElementMap(self.getShape(), mapper, mapper.shapes, op);
2734
PyObject* TopoShapePy::mapSubElement(PyObject* args)
2736
const char* op = nullptr;
2738
if (!PyArg_ParseTuple(args, "O|s", &sh, &op)) {
2743
getTopoShapePtr()->mapSubElement(getPyShapes(sh), op);
2749
PyObject* TopoShapePy::getCustomAttributes(const char* attr) const
2756
TopoDS_Shape res = getTopoShapePtr()->getSubShape(attr, true);
2757
if (!res.IsNull()) {
2758
return Py::new_reference_to(shape2pyshape(res));
2765
int TopoShapePy::setCustomAttributes(const char* , PyObject *)