1
/***************************************************************************
2
* Copyright (c) 2002 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"
25
# include <BRep_Builder.hxx>
26
# include <BRep_Tool.hxx>
27
# include <BRepAdaptor_Curve.hxx>
28
# include <BRepBuilderAPI_MakeEdge.hxx>
29
# include <BRepBuilderAPI_MakeFace.hxx>
30
# include <BRepBuilderAPI_MakePolygon.hxx>
31
# include <BRepBuilderAPI_MakeSolid.hxx>
32
# include <BRepCheck_Analyzer.hxx>
33
# include <BRepFeat_SplitShape.hxx>
34
# include <BRepOffsetAPI_Sewing.hxx>
35
# include <BRepPrim_Wedge.hxx>
36
# include <BRepPrimAPI_MakeBox.hxx>
37
# include <BRepPrimAPI_MakeCone.hxx>
38
# include <BRepPrimAPI_MakeCylinder.hxx>
39
# include <BRepPrimAPI_MakeRevolution.hxx>
40
# include <BRepPrimAPI_MakeSphere.hxx>
41
# include <BRepPrimAPI_MakeTorus.hxx>
42
# include <BRepFill.hxx>
43
# include <BRepFill_Filling.hxx>
44
# include <BRepLib.hxx>
45
# include <BSplCLib.hxx>
47
# include <gp_Circ.hxx>
49
# include <Geom_BSplineSurface.hxx>
50
# include <Geom_Circle.hxx>
51
# include <Geom_Plane.hxx>
52
# include <GeomFill_AppSurf.hxx>
53
# include <GeomFill_Generator.hxx>
54
# include <GeomFill_Line.hxx>
55
# include <GeomFill_SectionGenerator.hxx>
56
# include <Interface_Static.hxx>
57
# include <NCollection_List.hxx>
58
# include <Precision.hxx>
59
# include <ShapeFix.hxx>
60
# include <ShapeBuild_ReShape.hxx>
61
# include <ShapeUpgrade_ShellSewing.hxx>
62
# include <Standard_DomainError.hxx>
63
# include <Standard_Version.hxx>
64
# include <TopExp_Explorer.hxx>
65
# include <TopoDS_Compound.hxx>
66
# include <TopoDS_Edge.hxx>
67
# include <TopoDS_Face.hxx>
68
# include <TopoDS_Shell.hxx>
69
# include <TopoDS_Solid.hxx>
70
# include <TopTools_ListIteratorOfListOfShape.hxx>
72
# include <BRepFill_Generator.hxx>
74
#include <App/Application.h>
75
#include <App/Document.h>
76
#include <App/DocumentObjectPy.h>
77
#include <App/ElementNamingUtils.h>
78
#include <Base/Console.h>
79
#include <Base/Exception.h>
80
#include <Base/FileInfo.h>
81
#include <Base/GeometryPyCXX.h>
82
#include <Base/Interpreter.h>
83
#include <Base/PyWrapParseTupleAndKeywords.h>
84
#include <Base/VectorPy.h>
86
#include "BSplineSurfacePy.h"
87
#include "edgecluster.h"
89
#include "GeometryCurvePy.h"
90
#include "GeometryPy.h"
91
#include "ImportIges.h"
92
#include "ImportStep.h"
94
#include "modelRefine.h"
96
#include "PartFeature.h"
99
#include "TopoShapeCompoundPy.h"
100
#include "TopoShapePy.h"
101
#include "TopoShapeEdgePy.h"
102
#include "TopoShapeFacePy.h"
103
#include "TopoShapeShellPy.h"
104
#include "TopoShapeSolidPy.h"
105
#include "TopoShapeWirePy.h"
106
#include "TopoShapeOpCode.h"
107
#include "TopoShapeMapper.h"
113
extern const char* BRepBuilderAPI_FaceErrorText(BRepBuilderAPI_FaceError fe);
116
#define M_PI 3.14159265358979323846 /* pi */
120
#define M_PI_2 1.57079632679489661923 /* pi/2 */
125
PartExport void getPyShapes(PyObject* obj, std::vector<TopoShape>& shapes)
130
if (PyObject_TypeCheck(obj, &Part::TopoShapePy::Type)) {
131
shapes.push_back(*static_cast<TopoShapePy*>(obj)->getTopoShapePtr());
133
else if (PyObject_TypeCheck(obj, &GeometryPy::Type)) {
134
shapes.emplace_back(static_cast<GeometryPy*>(obj)->getGeometryPtr()->toShape());
136
else if (PySequence_Check(obj)) {
137
Py::Sequence list(obj);
138
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
139
if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) {
140
shapes.push_back(*static_cast<TopoShapePy*>((*it).ptr())->getTopoShapePtr());
142
else if (PyObject_TypeCheck((*it).ptr(), &GeometryPy::Type)) {
144
static_cast<GeometryPy*>((*it).ptr())->getGeometryPtr()->toShape());
147
throw Py::TypeError("expect shape in sequence");
152
throw Py::TypeError("expect shape or sequence of shapes");
156
PartExport std::vector<TopoShape> getPyShapes(PyObject *obj) {
157
std::vector<TopoShape> ret;
158
getPyShapes(obj,ret);
164
std::list<TopoDS_Edge>::iterator it;
168
PartExport std::list<TopoDS_Edge> sort_Edges(double tol3d, std::list<TopoDS_Edge>& edges)
170
tol3d = tol3d * tol3d;
171
std::list<EdgePoints> edge_points;
173
for (std::list<TopoDS_Edge>::iterator it = edges.begin(); it != edges.end(); ++it) {
175
xp.Init(*it,TopAbs_VERTEX);
176
ep.v1 = BRep_Tool::Pnt(TopoDS::Vertex(xp.Current()));
178
ep.v2 = BRep_Tool::Pnt(TopoDS::Vertex(xp.Current()));
181
edge_points.push_back(ep);
184
if (edge_points.empty())
187
std::list<TopoDS_Edge> sorted;
189
first = edge_points.front().v1;
190
last = edge_points.front().v2;
192
sorted.push_back(edge_points.front().edge);
193
edges.erase(edge_points.front().it);
194
edge_points.erase(edge_points.begin());
196
while (!edge_points.empty()) {
197
// search for adjacent edge
198
std::list<EdgePoints>::iterator pEI;
199
for (pEI = edge_points.begin(); pEI != edge_points.end(); ++pEI) {
200
if (pEI->v1.SquareDistance(last) <= tol3d) {
202
sorted.push_back(pEI->edge);
203
edges.erase(pEI->it);
204
edge_points.erase(pEI);
205
pEI = edge_points.begin();
208
else if (pEI->v2.SquareDistance(first) <= tol3d) {
210
sorted.push_front(pEI->edge);
211
edges.erase(pEI->it);
212
edge_points.erase(pEI);
213
pEI = edge_points.begin();
216
else if (pEI->v2.SquareDistance(last) <= tol3d) {
218
Standard_Real first, last;
219
const Handle(Geom_Curve) & curve = BRep_Tool::Curve(pEI->edge, first, last);
220
first = curve->ReversedParameter(first);
221
last = curve->ReversedParameter(last);
222
TopoDS_Edge edgeReversed = BRepBuilderAPI_MakeEdge(curve->Reversed(), last, first);
223
sorted.push_back(edgeReversed);
224
edges.erase(pEI->it);
225
edge_points.erase(pEI);
226
pEI = edge_points.begin();
229
else if (pEI->v1.SquareDistance(first) <= tol3d) {
231
Standard_Real first, last;
232
const Handle(Geom_Curve) & curve = BRep_Tool::Curve(pEI->edge, first, last);
233
first = curve->ReversedParameter(first);
234
last = curve->ReversedParameter(last);
235
TopoDS_Edge edgeReversed = BRepBuilderAPI_MakeEdge(curve->Reversed(), last, first);
236
sorted.push_front(edgeReversed);
237
edges.erase(pEI->it);
238
edge_points.erase(pEI);
239
pEI = edge_points.begin();
244
if ((pEI == edge_points.end()) || (last.SquareDistance(first) <= tol3d)) {
245
// no adjacent edge found or polyline is closed
255
class BRepFeatModule : public Py::ExtensionModule<BRepFeatModule>
258
BRepFeatModule() : Py::ExtensionModule<BRepFeatModule>("BRepFeat")
260
initialize("This is a module working with the BRepFeat package."); // register with Python
264
class BRepOffsetAPIModule : public Py::ExtensionModule<BRepOffsetAPIModule>
267
BRepOffsetAPIModule() : Py::ExtensionModule<BRepOffsetAPIModule>("BRepOffsetAPI")
269
initialize("This is a module working with the BRepOffsetAPI package."); // register with Python
273
class Geom2dModule : public Py::ExtensionModule<Geom2dModule>
276
Geom2dModule() : Py::ExtensionModule<Geom2dModule>("Geom2d")
278
initialize("This is a module working with 2d geometries."); // register with Python
282
class GeomPlateModule : public Py::ExtensionModule<GeomPlateModule>
285
GeomPlateModule() : Py::ExtensionModule<GeomPlateModule>("GeomPlate")
287
initialize("This is a module working with the GeomPlate framework."); // register with Python
291
class HLRBRepModule : public Py::ExtensionModule<HLRBRepModule>
294
HLRBRepModule() : Py::ExtensionModule<HLRBRepModule>("HLRBRep")
296
initialize("This is a module working with the HLRBRep framework."); // register with Python
300
class ShapeFixModule : public Py::ExtensionModule<ShapeFixModule>
303
ShapeFixModule() : Py::ExtensionModule<ShapeFixModule>("ShapeFix")
305
add_varargs_method("sameParameter",&ShapeFixModule::sameParameter,
306
"sameParameter(shape, enforce, prec=0.0)"
308
add_varargs_method("encodeRegularity",&ShapeFixModule::encodeRegularity,
309
"encodeRegularity(shape, tolerance = 1e-10)\n"
311
add_varargs_method("removeSmallEdges",&ShapeFixModule::removeSmallEdges,
312
"removeSmallEdges(shape, tolerance, ReShapeContext)\n"
313
"Removes edges which are less than given tolerance from shape"
315
add_varargs_method("fixVertexPosition",&ShapeFixModule::fixVertexPosition,
316
"fixVertexPosition(shape, tolerance, ReShapeContext)\n"
317
"Fix position of the vertices having tolerance more tnan specified one"
319
add_varargs_method("leastEdgeSize",&ShapeFixModule::leastEdgeSize,
320
"leastEdgeSize(shape)\n"
321
"Calculate size of least edge"
323
initialize("This is a module working with the ShapeFix framework."); // register with Python
327
Py::Object sameParameter(const Py::Tuple& args)
332
if (!PyArg_ParseTuple(args.ptr(), "O!O!|d", &TopoShapePy::Type, &shape, &PyBool_Type, &enforce, &prec))
333
throw Py::Exception();
335
TopoDS_Shape sh = static_cast<TopoShapePy*>(shape)->getTopoShapePtr()->getShape();
336
bool ok = ShapeFix::SameParameter(sh, Base::asBoolean(enforce), prec);
337
return Py::Boolean(ok);
339
Py::Object encodeRegularity(const Py::Tuple& args)
342
double tolang = 1.0e-10;
343
if (!PyArg_ParseTuple(args.ptr(), "O!|d", &TopoShapePy::Type, &shape, &tolang))
344
throw Py::Exception();
346
TopoDS_Shape sh = static_cast<TopoShapePy*>(shape)->getTopoShapePtr()->getShape();
347
ShapeFix::EncodeRegularity(sh, tolang);
350
Py::Object removeSmallEdges(const Py::Tuple& args)
354
if (!PyArg_ParseTuple(args.ptr(), "O!d", &TopoShapePy::Type, &shape, &tol))
355
throw Py::Exception();
357
TopoDS_Shape sh = static_cast<TopoShapePy*>(shape)->getTopoShapePtr()->getShape();
358
Handle(ShapeBuild_ReShape) reshape = new ShapeBuild_ReShape();
359
TopoShape res = ShapeFix::RemoveSmallEdges(sh, tol, reshape);
360
return Py::asObject(res.getPyObject());
362
Py::Object fixVertexPosition(const Py::Tuple& args)
366
if (!PyArg_ParseTuple(args.ptr(), "O!d", &TopoShapePy::Type, &shape, &tol))
367
throw Py::Exception();
369
TopoDS_Shape sh = static_cast<TopoShapePy*>(shape)->getTopoShapePtr()->getShape();
370
Handle(ShapeBuild_ReShape) reshape = new ShapeBuild_ReShape();
371
bool ok = ShapeFix::FixVertexPosition(sh, tol, reshape);
372
return Py::Boolean(ok);
374
Py::Object leastEdgeSize(const Py::Tuple& args)
377
if (!PyArg_ParseTuple(args.ptr(), "O!", &TopoShapePy::Type, &shape))
378
throw Py::Exception();
380
TopoDS_Shape sh = static_cast<TopoShapePy*>(shape)->getTopoShapePtr()->getShape();
381
double len = ShapeFix::LeastEdgeSize(sh);
382
return Py::Float(len);
386
class ShapeUpgradeModule : public Py::ExtensionModule<ShapeUpgradeModule>
389
ShapeUpgradeModule() : Py::ExtensionModule<ShapeUpgradeModule>("ShapeUpgrade")
391
initialize("This is a module working with the ShapeUpgrade framework."); // register with Python
395
class ChFi2dModule : public Py::ExtensionModule<ChFi2dModule>
398
ChFi2dModule() : Py::ExtensionModule<ChFi2dModule>("ChFi2d")
400
initialize("This is a module working with the ChFi2d framework."); // register with Python
404
class Module : public Py::ExtensionModule<Module>
406
BRepFeatModule brepFeat;
407
BRepOffsetAPIModule brepOffsetApi;
409
GeomPlateModule geomPlate;
410
HLRBRepModule HLRBRep;
411
ShapeFixModule shapeFix;
412
ShapeUpgradeModule shapeUpgrade;
415
Module() : Py::ExtensionModule<Module>("Part")
417
add_varargs_method("open",&Module::open,
418
"open(string) -- Create a new document and load the file into the document."
420
add_varargs_method("insert",&Module::insert,
421
"insert(string,string) -- Insert the file into the given document."
423
add_varargs_method("export",&Module::exporter,
424
"export(list,string) -- Export a list of objects into a single file."
426
add_varargs_method("read",&Module::read,
427
"read(string) -- Load the file and return the shape."
429
add_varargs_method("show",&Module::show,
430
"show(shape,[string]) -- Add the shape to the active document or create one if no document exists."
432
add_varargs_method("getFacets",&Module::getFacets,
433
"getFacets(shape): simplified mesh generation"
435
add_keyword_method("makeCompound",&Module::makeCompound,
436
"makeCompound(list) -- Create a compound out of a list of shapes."
438
add_keyword_method("makeShell",&Module::makeShell,
439
"makeShell(list) -- Create a shell out of a list of faces."
441
add_keyword_method("makeFace",&Module::makeFace,
442
"makeFace(list_of_shapes_or_compound, maker_class_name) -- Create a face (faces) using facemaker class.\n"
443
"maker_class_name is a string like 'Part::FaceMakerSimple'."
445
add_keyword_method("makeFilledSurface",&Module::makeFilledSurface,
446
"makeFilledSurface(list of curves, tolerance) -- Create a surface out of a list of curves."
448
add_keyword_method("makeFilledFace",&Module::makeFilledFace,
449
"makeFilledFace(list) -- Create a face out of a list of edges."
451
add_keyword_method("makeSolid",&Module::makeSolid,
452
"makeSolid(shape): Create a solid out of shells of shape. If shape is a compsolid, the overall volume solid is created."
454
add_varargs_method("makePlane",&Module::makePlane,
455
"makePlane(length,width,[pnt,dirZ,dirX]) -- Make a plane\n"
456
"By default pnt=Vector(0,0,0) and dirZ=Vector(0,0,1), dirX is ignored in this case"
458
add_varargs_method("makeBox",&Module::makeBox,
459
"makeBox(length,width,height,[pnt,dir]) -- Make a box located\n"
460
"in pnt with the dimensions (length,width,height)\n"
461
"By default pnt=Vector(0,0,0) and dir=Vector(0,0,1)"
463
add_varargs_method("makeWedge",&Module::makeWedge,
464
"makeWedge(xmin, ymin, zmin, z2min, x2min,\n"
465
"xmax, ymax, zmax, z2max, x2max,[pnt,dir])\n"
466
" -- Make a wedge located in pnt\n"
467
"By default pnt=Vector(0,0,0) and dir=Vector(0,0,1)"
469
add_varargs_method("makeLine",&Module::makeLine,
470
"makeLine(startpnt,endpnt) -- Make a line between two points\n"
473
" startpnt (Vector or tuple): Vector or 3 element tuple \n"
474
" containing the x,y and z coordinates of the start point,\n"
475
" i.e. (x1,y1,z1).\n"
476
" endpnt (Vector or tuple): Vector or 3 element tuple \n"
477
" containing the x,y and z coordinates of the start point,\n"
478
" i.e. (x1,y1,z1).\n"
481
" Edge: Part.Edge object\n"
483
add_varargs_method("makePolygon",&Module::makePolygon,
484
"makePolygon(pntslist) -- Make a polygon from a list of points\n"
487
" pntslist (list(Vector)): list of Vectors representing the \n"
488
" points of the polygon.\n"
491
" Wire: Part.Wire object. If the last point in the list is \n"
492
" not the same as the first point, the Wire will not be \n"
493
" closed and cannot be used to create a face.\n"
495
add_varargs_method("makeCircle",&Module::makeCircle,
496
"makeCircle(radius,[pnt,dir,angle1,angle2]) -- Make a circle with a given radius\n"
497
"By default pnt=Vector(0,0,0), dir=Vector(0,0,1), angle1=0 and angle2=360"
499
add_varargs_method("makeSphere",&Module::makeSphere,
500
"makeSphere(radius,[pnt, dir, angle1,angle2,angle3]) -- Make a sphere with a given radius\n"
501
"By default pnt=Vector(0,0,0), dir=Vector(0,0,1), angle1=0, angle2=90 and angle3=360"
503
add_varargs_method("makeCylinder",&Module::makeCylinder,
504
"makeCylinder(radius,height,[pnt,dir,angle]) -- Make a cylinder with a given radius and height\n"
505
"By default pnt=Vector(0,0,0),dir=Vector(0,0,1) and angle=360"
507
add_varargs_method("makeCone",&Module::makeCone,
508
"makeCone(radius1,radius2,height,[pnt,dir,angle]) -- Make a cone with given radii and height\n"
509
"By default pnt=Vector(0,0,0), dir=Vector(0,0,1) and angle=360"
511
add_varargs_method("makeTorus",&Module::makeTorus,
512
"makeTorus(radius1,radius2,[pnt,dir,angle1,angle2,angle]) -- Make a torus with a given radii and angles\n"
513
"By default pnt=Vector(0,0,0),dir=Vector(0,0,1),angle1=0,angle1=360 and angle=360"
515
add_varargs_method("makeHelix",&Module::makeHelix,
516
"makeHelix(pitch,height,radius,[angle]) -- Make a helix with a given pitch, height and radius\n"
517
"By default a cylindrical surface is used to create the helix. If the fourth parameter is set\n"
518
"(the apex given in degree) a conical surface is used instead"
520
add_varargs_method("makeLongHelix",&Module::makeLongHelix,
521
"makeLongHelix(pitch,height,radius,[angle],[hand]) -- Make a (multi-edge) helix with a given pitch, height and radius\n"
522
"By default a cylindrical surface is used to create the helix. If the fourth parameter is set\n"
523
"(the apex given in degree) a conical surface is used instead."
525
add_varargs_method("makeThread",&Module::makeThread,
526
"makeThread(pitch,depth,height,radius) -- Make a thread with a given pitch, depth, height and radius"
528
add_varargs_method("makeRevolution",&Module::makeRevolution,
529
"makeRevolution(Curve or Edge,[vmin,vmax,angle,pnt,dir,shapetype]) -- Make a revolved shape\n"
530
"by rotating the curve or a portion of it around an axis given by (pnt,dir).\n"
531
"By default vmin/vmax=bounds of the curve, angle=360, pnt=Vector(0,0,0),\n"
532
"dir=Vector(0,0,1) and shapetype=Part.Solid"
534
add_keyword_method("makeRuledSurface",&Module::makeRuledSurface,
535
"makeRuledSurface(Edge|Wire,Edge|Wire) -- Make a ruled surface\n"
536
"Create a ruled surface out of two edges or wires. If wires are used then"
537
"these must have the same number of edges."
539
add_keyword_method("makeShellFromWires",&Module::makeShellFromWires,
540
"makeShellFromWires(Wires) -- Make a shell from wires.\n"
541
"The wires must have the same number of edges."
543
add_keyword_method("makeLoft",&Module::makeLoft,
544
"makeLoft(list of wires,[solid=False,ruled=False,closed=False,maxDegree=5]) -- Create a loft shape."
546
add_varargs_method("makeTube",&Module::makeTube,
547
"makeTube(edge,radius,[continuity,max degree,max segments]) -- Create a tube.\n"
548
"continuity is a string which must be 'C0','C1','C2','C3','CN','G1' or 'G1',"
550
add_varargs_method("makeSweepSurface",&Module::makeSweepSurface,
551
"makeSweepSurface(edge(path),edge(profile),[float]) -- Create a profile along a path."
553
add_varargs_method("makeWireString",&Module::makeWireString,
554
"makeWireString(string,fontdir,fontfile,height,[track]) -- Make list of wires in the form of a string's characters."
556
add_varargs_method("makeSplitShape",&Module::makeSplitShape,
557
"makeSplitShape(shape, list of shape pairs,[check Interior=True]) -> two lists of shapes.\n"
558
"The following shape pairs are supported:\n"
563
"* The face must be part of the specified shape and the edge, wire or compound must\n"
566
"The first list contains the faces that are the left of the projected wires.\n"
567
"The second list contains the left part on the shape.\n\n"
571
"split = [(edges[0],face),(edges[1],face)]\n"
572
"r = Part.makeSplitShape(face, split)\n"
573
"Part.show(r[0][0])\n"
574
"Part.show(r[1][0])\n"
576
add_varargs_method("exportUnits",&Module::exportUnits,
577
"exportUnits([string=MM|M|INCH|FT|MI|KM|MIL|UM|CM|UIN]) -- Set units for exporting STEP/IGES files and returns the units."
579
add_varargs_method("setStaticValue",&Module::setStaticValue,
580
"setStaticValue(string,string|int|float) -- Set a name to a value The value can be a string, int or float."
582
add_varargs_method("cast_to_shape",&Module::cast_to_shape,
583
"cast_to_shape(shape) -- Cast to the actual shape type"
585
add_varargs_method("getSortedClusters",&Module::getSortedClusters,
586
"getSortedClusters(list of edges) -- Helper method to sort and cluster a variety of edges"
588
add_varargs_method("__sortEdges__",&Module::sortEdges,
589
"__sortEdges__(list of edges) -- list of edges\n"
590
"Helper method to sort an unsorted list of edges so that afterwards\n"
591
"the start and end vertex of two consecutive edges are geometrically coincident.\n"
592
"It returns a single list of edges and the algorithm stops after the first set of\n"
593
"connected edges which means that the output list can be smaller than the input list.\n"
594
"The sorted list can be used to create a Wire."
596
add_varargs_method("sortEdges",&Module::sortEdges2,
597
"sortEdges(list of edges, [tol3d]) -- list of lists of edges\n"
598
"It does basically the same as __sortEdges__ but sorts all input edges and thus returns\n"
599
"a list of lists of edges\n"
600
"optional 3D tolerance defaults to Precision::Confusion"
602
add_varargs_method("__toPythonOCC__",&Module::toPythonOCC,
603
"__toPythonOCC__(shape) -- Helper method to convert an internal shape to pythonocc shape"
605
add_varargs_method("__fromPythonOCC__",&Module::fromPythonOCC,
606
"__fromPythonOCC__(occ) -- Helper method to convert a pythonocc shape to an internal shape"
608
add_varargs_method("clearShapeCache",&Module::clearShapeCache,
609
"clearShapeCache() -- Clears internal shape cache"
611
add_keyword_method("getShape",&Module::getShape,
612
"getShape(obj,subname=None,mat=None,needSubElement=False,transform=True,retType=0):\n"
613
"Obtain the TopoShape of a given object with SubName reference\n\n"
614
"* obj: the input object\n"
615
"* subname: dot separated sub-object reference\n"
616
"* mat: the current transformation matrix\n"
617
"* needSubElement: if False, ignore the sub-element (e.g. Face1, Edge1) reference in 'subname'\n"
618
"* transform: if False, then skip obj's transformation. Use this if mat already include obj's\n"
619
" transformation matrix\n"
620
"* retType: 0: return TopoShape,\n"
621
" 1: return (shape,mat,subObj), where subObj is the object referenced in 'subname',\n"
622
" and 'mat' is the accumulated transformation matrix of that sub-object.\n"
623
" 2: same as 1, but make sure 'subObj' is resolved if it is a link.\n"
624
"* refine: refine the returned shape"
626
add_varargs_method("splitSubname",&Module::splitSubname,
627
"splitSubname(subname) -> list(sub,mapped,subElement)\n"
628
"Split the given subname into a list\n\n"
629
"sub: subname without any sub-element reference\n"
630
"mapped: mapped element name, or '' if none\n"
631
"subElement: old style element name, or '' if none"
633
add_varargs_method("joinSubname",&Module::joinSubname,
634
"joinSubname(sub,mapped,subElement) -> subname\n"
636
initialize("This is a module working with shapes."); // register with Python
638
PyModule_AddObject(m_module, "BRepFeat", brepFeat.module().ptr());
639
PyModule_AddObject(m_module, "BRepOffsetAPI", brepOffsetApi.module().ptr());
640
PyModule_AddObject(m_module, "Geom2d", geom2d.module().ptr());
641
PyModule_AddObject(m_module, "GeomPlate", geomPlate.module().ptr());
642
PyModule_AddObject(m_module, "HLRBRep", HLRBRep.module().ptr());
643
PyModule_AddObject(m_module, "ShapeFix", shapeFix.module().ptr());
644
PyModule_AddObject(m_module, "ShapeUpgrade", shapeUpgrade.module().ptr());
645
PyModule_AddObject(m_module, "ChFi2d", chFi2d.module().ptr());
649
Py::Object invoke_method_keyword( void *method_def,
650
const Py::Tuple &args, const Py::Dict &keywords ) override
653
return Py::ExtensionModule<Module>::invoke_method_keyword(method_def, args, keywords);
655
catch (const Standard_Failure &e) {
657
Standard_CString msg = e.GetMessageString();
658
str += typeid(e).name();
660
if (msg) {str += msg;}
661
else {str += "No OCCT Exception Message";}
662
Base::Console().Error("%s\n", str.c_str());
663
throw Py::Exception(Part::PartExceptionOCCError, str);
665
catch (const Base::Exception &e) {
667
str += "FreeCAD exception thrown (";
671
throw Py::RuntimeError(str);
673
catch (const std::exception &e) {
675
str += "C++ exception thrown (";
678
Base::Console().Error("%s\n", str.c_str());
679
throw Py::RuntimeError(str);
683
Py::Object invoke_method_varargs(void *method_def, const Py::Tuple &args) override
686
return Py::ExtensionModule<Module>::invoke_method_varargs(method_def, args);
688
catch (const Standard_Failure &e) {
690
Standard_CString msg = e.GetMessageString();
691
str += typeid(e).name();
693
if (msg) {str += msg;}
694
else {str += "No OCCT Exception Message";}
695
Base::Console().Error("%s\n", str.c_str());
696
throw Py::Exception(Part::PartExceptionOCCError, str);
698
catch (const Base::Exception &e) {
700
str += "FreeCAD exception thrown (";
704
throw Py::RuntimeError(str);
706
catch (const std::exception &e) {
708
str += "C++ exception thrown (";
711
Base::Console().Error("%s\n", str.c_str());
712
throw Py::RuntimeError(str);
716
Py::Object open(const Py::Tuple& args)
719
if (!PyArg_ParseTuple(args.ptr(), "et","utf-8",&Name))
720
throw Py::Exception();
721
std::string EncodedName = std::string(Name);
724
//Base::Console().Log("Open in Part with %s",Name);
725
Base::FileInfo file(EncodedName.c_str());
728
if (file.extension().empty())
729
throw Py::RuntimeError("No file extension");
731
if (file.hasExtension({"stp", "step"})) {
732
// create new document and add Import feature
733
App::Document *pcDoc = App::GetApplication().newDocument();
734
ImportStepParts(pcDoc,EncodedName.c_str());
738
else if (file.hasExtension({"igs", "iges"})) {
739
App::Document *pcDoc = App::GetApplication().newDocument();
740
ImportIgesParts(pcDoc,EncodedName.c_str());
745
shape.read(EncodedName.c_str());
747
// create new document set loaded shape
748
App::Document *pcDoc = App::GetApplication().newDocument(file.fileNamePure().c_str());
749
Part::Feature *object = static_cast<Part::Feature *>(pcDoc->addObject
750
("Part::Feature",file.fileNamePure().c_str()));
751
object->Shape.setValue(shape);
757
Py::Object insert(const Py::Tuple& args)
761
if (!PyArg_ParseTuple(args.ptr(), "ets","utf-8",&Name,&DocName))
762
throw Py::Exception();
764
std::string EncodedName = std::string(Name);
767
//Base::Console().Log("Insert in Part with %s",Name);
768
Base::FileInfo file(EncodedName.c_str());
771
if (file.extension().empty())
772
throw Py::RuntimeError("No file extension");
774
App::Document *pcDoc = App::GetApplication().getDocument(DocName);
776
pcDoc = App::GetApplication().newDocument(DocName);
779
if (file.hasExtension({"stp", "step"})) {
780
ImportStepParts(pcDoc,EncodedName.c_str());
784
else if (file.hasExtension({"igs", "iges"})) {
785
ImportIgesParts(pcDoc,EncodedName.c_str());
790
shape.read(EncodedName.c_str());
792
Part::Feature *object = static_cast<Part::Feature *>(pcDoc->addObject
793
("Part::Feature",file.fileNamePure().c_str()));
794
object->Shape.setValue(shape);
800
Py::Object exporter(const Py::Tuple& args)
804
if (!PyArg_ParseTuple(args.ptr(), "Oet",&object,"utf-8",&Name))
805
throw Py::Exception();
807
std::string EncodedName = std::string(Name);
810
BRep_Builder builder;
811
TopoDS_Compound comp;
812
builder.MakeCompound(comp);
814
Py::Sequence list(object);
815
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
816
PyObject* item = (*it).ptr();
817
if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type))) {
818
App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(item)->getDocumentObjectPtr();
819
if (obj->isDerivedFrom<Part::Feature>()) {
820
Part::Feature* part = static_cast<Part::Feature*>(obj);
821
const TopoDS_Shape& shape = part->Shape.getValue();
823
builder.Add(comp, shape);
826
Base::Console().Message("'%s' is not a shape, export will be ignored.\n", obj->Label.getValue());
831
TopoShape shape(comp);
832
shape.write(EncodedName.c_str());
836
Py::Object read(const Py::Tuple& args)
839
if (!PyArg_ParseTuple(args.ptr(), "et","utf-8",&Name))
840
throw Py::Exception();
842
std::string EncodedName = std::string(Name);
845
TopoShape* shape = new TopoShape();
846
shape->read(EncodedName.c_str());
847
return Py::asObject(new TopoShapePy(shape));
849
Py::Object show(const Py::Tuple& args)
851
PyObject *pcObj = nullptr;
852
const char *name = "Shape";
853
if (!PyArg_ParseTuple(args.ptr(), "O!|s", &(TopoShapePy::Type), &pcObj, &name))
854
throw Py::Exception();
856
App::Document *pcDoc = App::GetApplication().getActiveDocument();
858
pcDoc = App::GetApplication().newDocument();
860
if (PyObject_TypeCheck(pcObj, &TopoShapePy::Type))
861
shape = *static_cast<TopoShapePy *>(pcObj)->getTopoShapePtr();
862
else if (PyObject_TypeCheck(pcObj, &GeometryPy::Type))
863
shape = static_cast<GeometryPy *>(pcObj)->getGeometryPtr()->toShape();
864
else if (PyObject_TypeCheck(pcObj, &App::DocumentObjectPy::Type)) {
865
auto obj = static_cast<App::DocumentObjectPy *>(pcObj)->getDocumentObjectPtr();
866
shape = Feature::getTopoShape(obj);
868
throw Py::TypeError("Expects argument of type DocumentObject, Shape, or Geometry");
870
Part::Feature *pcFeature = static_cast<Part::Feature*>(pcDoc->addObject("Part::Feature", name));
872
pcFeature->Shape.setValue(shape);
873
pcFeature->purgeTouched();
874
return Py::asObject(pcFeature->getPyObject());
876
Py::Object getFacets(const Py::Tuple& args)
880
if (!PyArg_ParseTuple(args.ptr(), "O", &shape))
881
throw Py::Exception();
882
auto theShape = static_cast<Part::TopoShapePy*>(shape)->getTopoShapePtr()->getShape();
883
for (TopExp_Explorer ex(theShape, TopAbs_FACE); ex.More(); ex.Next()) {
884
TopoDS_Face currentFace = TopoDS::Face(ex.Current());
886
std::vector<gp_Pnt> points;
887
std::vector<Poly_Triangle> facets;
888
if (Tools::getTriangulation(currentFace, points, facets)) {
889
for (const auto& it : facets) {
890
Standard_Integer n1,n2,n3;
893
gp_Pnt p1 = points[n1];
894
gp_Pnt p2 = points[n2];
895
gp_Pnt p3 = points[n3];
897
// TODO: verify if tolerance should be hard coded
898
if (!p1.IsEqual(p2, 0.01) && !p2.IsEqual(p3, 0.01) && !p3.IsEqual(p1, 0.01)) {
899
PyObject *t1 = PyTuple_Pack(3, PyFloat_FromDouble(p1.X()), PyFloat_FromDouble(p1.Y()), PyFloat_FromDouble(p1.Z()));
900
PyObject *t2 = PyTuple_Pack(3, PyFloat_FromDouble(p2.X()), PyFloat_FromDouble(p2.Y()), PyFloat_FromDouble(p2.Z()));
901
PyObject *t3 = PyTuple_Pack(3, PyFloat_FromDouble(p3.X()), PyFloat_FromDouble(p3.Y()), PyFloat_FromDouble(p3.Z()));
902
list.append(Py::asObject(PyTuple_Pack(3, t1, t2, t3)));
909
Py::Object makeCompound(const Py::Tuple& args, const Py::Dict &kwds)
912
PyObject* force = Py_True;
913
TopoShape::SingleShapeCompoundCreationPolicy
914
policy; // = TopoShape::SingleShapeCompoundCreationPolicy::forceCompound;
915
PyObject* module = PyImport_ImportModule("PartEnums");
916
PyObject* policyEnum =
917
PyObject_GetAttrString(module, (char*)"SingleShapeCompoundCreationPolicy");
918
const char* op = nullptr;
919
const std::array<const char*, 4> kwd_list = {"shapes", "force", "op", nullptr};
920
if (!Base::Wrapped_ParseTupleAndKeywords(args.ptr(),
928
throw Py::Exception();
931
policy = static_cast<TopoShape::SingleShapeCompoundCreationPolicy>(PyLong_AsLong(force));
932
Py_DECREF(policyEnum);
934
return shape2pyshape(Part::TopoShape().makeElementCompound(getPyShapes(pcObj), op, policy));
936
Py::Object makeShell(const Py::Tuple& args, const Py::Dict &kwds)
939
const char* op = nullptr;
940
const std::array<const char*, 3> kwd_list = {"shapes", "op", nullptr};
941
if (!Base::Wrapped_ParseTupleAndKeywords(args.ptr(),
947
throw Py::Exception();
949
return shape2pyshape(
950
Part::TopoShape().makeElementBoolean(Part::OpCodes::Shell, getPyShapes(obj), op));
952
Py::Object makeFace(const Py::Tuple& args, const Py::Dict &kwds)
955
const char* className = nullptr;
956
const char* op = nullptr;
957
const std::array<const char*, 4> kwd_list = {"shapes", "class_name", "op", nullptr};
958
if (!Base::Wrapped_ParseTupleAndKeywords(args.ptr(),
965
throw Py::Exception();
967
return shape2pyshape(TopoShape().makeElementFace(getPyShapes(obj), op, className));
971
void parseSequence(PyObject *pyObj, const char *err, F f)
973
if (pyObj != Py_None) {
974
if (!PySequence_Check(pyObj))
975
throw Py::TypeError(err);
976
Py::Sequence seq(pyObj);
977
for (Py::Sequence::iterator it = seq.begin(); it != seq.end(); ++it) {
978
if (!PySequence_Check((*it).ptr()))
979
throw Py::TypeError(err);
980
Py::Sequence tuple((*it).ptr());
981
if (tuple.size() != 2)
982
throw Py::TypeError(err);
983
auto iter = tuple.begin();
984
if (!PyObject_TypeCheck((*iter).ptr(), &(Part::TopoShapePy::Type)))
985
throw Py::TypeError(err);
986
const TopoDS_Shape& sh = static_cast<TopoShapePy*>((*iter).ptr())->getTopoShapePtr()->getShape();
987
f(sh, (*iter).ptr(), err);
993
Py::Object makeFilledSurface(const Py::Tuple &args, const Py::Dict &kwds)
995
TopoShape::BRepFillingParams params;
996
PyObject* obj = nullptr;
997
PyObject* pySurface = Py_None;
998
PyObject* supports = Py_None;
999
PyObject* orders = Py_None;
1000
PyObject* anisotropy = params.anisotropy ? Py_True : Py_False;
1001
const char* op = nullptr;
1002
const std::array<const char*, 16> kwd_list = {"shapes",
1018
if (!Base::Wrapped_ParseTupleAndKeywords(args.ptr(),
1020
"O|O!OOIIIOddddIIs",
1036
throw Py::Exception();
1038
params.anisotropy = PyObject_IsTrue(anisotropy);
1040
if (pySurface != Py_None) {
1041
surface = *static_cast<TopoShapePy*>(pySurface)->getTopoShapePtr();
1043
parseSequence(supports,
1044
"Expects 'supports' to be a sequence of tuple(shape, shape)",
1045
[&](const TopoDS_Shape& s, PyObject* value, const char* err) {
1046
if (!PyObject_TypeCheck(value, &(Part::TopoShapePy::Type))) {
1047
throw Py::TypeError(err);
1049
params.supports[s] =
1050
static_cast<TopoShapePy*>(value)->getTopoShapePtr()->getShape();
1052
parseSequence(orders,
1053
"Expects 'orders' to be a sequence of tuple(shape, PartEnums.Shape)",
1054
[&](const TopoDS_Shape& s, PyObject* value, const char* err) {
1055
if (!PyLong_Check(value)) {
1056
throw Py::ValueError(err);
1058
int order = Py::Int(value);
1059
params.orders[s] = static_cast<TopoShape::Continuity>(order);
1062
auto shapes = getPyShapes(obj);
1063
if (shapes.empty()) {
1064
throw Py::ValueError("No input shape");
1066
return shape2pyshape(
1067
TopoShape(0, shapes.front().Hasher).makeElementFilledFace(shapes, params, op));
1070
Py::Object makeFilledFace(const Py::Tuple& args, const Py::Dict &kwds)
1072
TopoShape::BRepFillingParams params;
1073
PyObject* obj = nullptr;
1074
PyObject* pySurface = Py_None;
1075
PyObject* supports = Py_None;
1076
PyObject* orders = Py_None;
1077
PyObject* anisotropy = params.anisotropy ? Py_True : Py_False;
1078
const char* op = nullptr;
1079
const std::array<const char*, 16> kwd_list = {"shapes",
1095
if (!Base::Wrapped_ParseTupleAndKeywords(args.ptr(),
1097
"O|O!OOIIIOddddIIs",
1113
throw Py::Exception();
1115
params.anisotropy = PyObject_IsTrue(anisotropy);
1117
if (pySurface != Py_None) {
1118
surface = *static_cast<TopoShapePy*>(pySurface)->getTopoShapePtr();
1120
parseSequence(supports,
1121
"Expects 'supports' to be a sequence of tuple(shape, shape)",
1122
[&](const TopoDS_Shape& s, PyObject* value, const char* err) {
1123
if (!PyObject_TypeCheck(value, &(Part::TopoShapePy::Type))) {
1124
throw Py::TypeError(err);
1126
params.supports[s] =
1127
static_cast<TopoShapePy*>(value)->getTopoShapePtr()->getShape();
1129
parseSequence(orders,
1130
"Expects 'orders' to be a sequence of tuple(shape, PartEnums.Shape)",
1131
[&](const TopoDS_Shape& s, PyObject* value, const char* err) {
1132
if (!PyLong_Check(value)) {
1133
throw Py::ValueError(err);
1135
int order = Py::Int(value);
1136
params.orders[s] = static_cast<TopoShape::Continuity>(order);
1139
auto shapes = getPyShapes(obj);
1140
if (shapes.empty()) {
1141
throw Py::ValueError("No input shape");
1143
return shape2pyshape(
1144
TopoShape(0, shapes.front().Hasher).makeElementFilledFace(shapes, params, op));
1147
Py::Object makeSolid(const Py::Tuple& args, const Py::Dict &kwds)
1150
const char* op = nullptr;
1151
const std::array<const char*, 3> kwd_list = {"shape", "op", nullptr};
1152
if (!Base::Wrapped_ParseTupleAndKeywords(args.ptr(),
1156
&(TopoShapePy::Type),
1159
throw Py::Exception();
1161
return shape2pyshape(
1162
TopoShape().makeElementSolid(*static_cast<TopoShapePy*>(obj)->getTopoShapePtr(), op));
1165
Py::Object makePlane(const Py::Tuple& args)
1167
double length, width;
1168
PyObject *pPnt=nullptr, *pDirZ=nullptr, *pDirX=nullptr;
1169
if (!PyArg_ParseTuple(args.ptr(), "dd|O!O!O!", &length, &width,
1170
&(Base::VectorPy::Type), &pPnt,
1171
&(Base::VectorPy::Type), &pDirZ,
1172
&(Base::VectorPy::Type), &pDirX))
1173
throw Py::Exception();
1175
if (length < Precision::Confusion()) {
1176
throw Py::ValueError("length of plane too small");
1178
if (width < Precision::Confusion()) {
1179
throw Py::ValueError("width of plane too small");
1186
Base::Vector3d pnt = static_cast<Base::VectorPy*>(pPnt)->value();
1187
p.SetCoord(pnt.x, pnt.y, pnt.z);
1190
Base::Vector3d vec = static_cast<Base::VectorPy*>(pDirZ)->value();
1191
d.SetCoord(vec.x, vec.y, vec.z);
1193
Handle(Geom_Plane) aPlane;
1195
Base::Vector3d vec = static_cast<Base::VectorPy*>(pDirX)->value();
1197
dx.SetCoord(vec.x, vec.y, vec.z);
1198
aPlane = new Geom_Plane(gp_Ax3(p, d, dx));
1201
aPlane = new Geom_Plane(p, d);
1204
BRepBuilderAPI_MakeFace Face(aPlane, 0.0, length, 0.0, width, Precision::Confusion() );
1205
return Py::asObject(new TopoShapeFacePy(new TopoShape((Face.Face()))));
1207
catch (Standard_DomainError&) {
1208
throw Py::Exception(PartExceptionOCCDomainError, "creation of plane failed");
1210
catch (Standard_Failure&) {
1211
throw Py::Exception(PartExceptionOCCError, "creation of plane failed");
1214
Py::Object makeBox(const Py::Tuple& args)
1216
double length, width, height;
1217
PyObject *pPnt=nullptr, *pDir=nullptr;
1218
if (!PyArg_ParseTuple(args.ptr(), "ddd|O!O!",
1219
&length, &width, &height,
1220
&(Base::VectorPy::Type), &pPnt,
1221
&(Base::VectorPy::Type), &pDir))
1222
throw Py::Exception();
1224
if (length < Precision::Confusion()) {
1225
throw Py::ValueError("length of box too small");
1227
if (width < Precision::Confusion()) {
1228
throw Py::ValueError("width of box too small");
1230
if (height < Precision::Confusion()) {
1231
throw Py::ValueError("height of box too small");
1238
Base::Vector3d pnt = static_cast<Base::VectorPy*>(pPnt)->value();
1239
p.SetCoord(pnt.x, pnt.y, pnt.z);
1242
Base::Vector3d vec = static_cast<Base::VectorPy*>(pDir)->value();
1243
d.SetCoord(vec.x, vec.y, vec.z);
1245
BRepPrimAPI_MakeBox mkBox(gp_Ax2(p,d), length, width, height);
1246
TopoDS_Shape ResultShape = mkBox.Shape();
1247
return Py::asObject(new TopoShapeSolidPy(new TopoShape(ResultShape)));
1249
catch (Standard_DomainError&) {
1250
throw Py::Exception(PartExceptionOCCDomainError, "creation of box failed");
1253
Py::Object makeWedge(const Py::Tuple& args)
1255
double xmin, ymin, zmin, z2min, x2min, xmax, ymax, zmax, z2max, x2max;
1256
PyObject *pPnt=nullptr, *pDir=nullptr;
1257
if (!PyArg_ParseTuple(args.ptr(), "dddddddddd|O!O!",
1258
&xmin, &ymin, &zmin, &z2min, &x2min, &xmax, &ymax, &zmax, &z2max, &x2max,
1259
&(Base::VectorPy::Type), &pPnt, &(Base::VectorPy::Type), &pDir))
1260
throw Py::Exception();
1262
double dx = xmax-xmin;
1263
double dy = ymax-ymin;
1264
double dz = zmax-zmin;
1265
double dz2 = z2max-z2min;
1266
double dx2 = x2max-x2min;
1267
if (dx < Precision::Confusion()) {
1268
throw Py::ValueError("delta x of wedge too small");
1270
if (dy < Precision::Confusion()) {
1271
throw Py::ValueError("delta y of wedge too small");
1273
if (dz < Precision::Confusion()) {
1274
throw Py::ValueError("delta z of wedge too small");
1277
throw Py::ValueError("delta z2 of wedge is negative");
1280
throw Py::ValueError("delta x2 of wedge is negative");
1287
Base::Vector3d pnt = static_cast<Base::VectorPy*>(pPnt)->value();
1288
p.SetCoord(pnt.x, pnt.y, pnt.z);
1291
Base::Vector3d vec = static_cast<Base::VectorPy*>(pDir)->value();
1292
d.SetCoord(vec.x, vec.y, vec.z);
1294
BRepPrim_Wedge mkWedge(gp_Ax2(p,d), xmin, ymin, zmin, z2min, x2min, xmax, ymax, zmax, z2max, x2max);
1295
BRepBuilderAPI_MakeSolid mkSolid;
1296
mkSolid.Add(mkWedge.Shell());
1297
return Py::asObject(new TopoShapeSolidPy(new TopoShape(mkSolid.Solid())));
1299
catch (Standard_DomainError&) {
1300
throw Py::Exception(PartExceptionOCCDomainError, "creation of wedge failed");
1303
Py::Object makeLine(const Py::Tuple& args)
1305
PyObject *obj1, *obj2;
1306
if (!PyArg_ParseTuple(args.ptr(), "OO", &obj1, &obj2))
1307
throw Py::Exception();
1309
Base::Vector3d pnt1, pnt2;
1310
if (PyObject_TypeCheck(obj1, &(Base::VectorPy::Type))) {
1311
pnt1 = static_cast<Base::VectorPy*>(obj1)->value();
1313
else if (PyObject_TypeCheck(obj1, &PyTuple_Type)) {
1314
pnt1 = Base::getVectorFromTuple<double>(obj1);
1317
throw Py::TypeError("first argument must either be vector or tuple");
1319
if (PyObject_TypeCheck(obj2, &(Base::VectorPy::Type))) {
1320
pnt2 = static_cast<Base::VectorPy*>(obj2)->value();
1322
else if (PyObject_TypeCheck(obj2, &PyTuple_Type)) {
1323
pnt2 = Base::getVectorFromTuple<double>(obj2);
1326
throw Py::TypeError("second argument must either be vector or tuple");
1329
// Create directly the underlying line geometry
1330
BRepBuilderAPI_MakeEdge makeEdge(gp_Pnt(pnt1.x, pnt1.y, pnt1.z),
1331
gp_Pnt(pnt2.x, pnt2.y, pnt2.z));
1333
const char *error=nullptr;
1334
switch (makeEdge.Error())
1336
case BRepBuilderAPI_EdgeDone:
1338
case BRepBuilderAPI_PointProjectionFailed:
1339
error = "Point projection failed";
1341
case BRepBuilderAPI_ParameterOutOfRange:
1342
error = "Parameter out of range";
1344
case BRepBuilderAPI_DifferentPointsOnClosedCurve:
1345
error = "Different points on closed curve";
1347
case BRepBuilderAPI_PointWithInfiniteParameter:
1348
error = "Point with infinite parameter";
1350
case BRepBuilderAPI_DifferentsPointAndParameter:
1351
error = "Different point and parameter";
1353
case BRepBuilderAPI_LineThroughIdenticPoints:
1354
error = "Line through identical points";
1359
throw Py::Exception(PartExceptionOCCError, error);
1362
TopoDS_Edge edge = makeEdge.Edge();
1363
return Py::asObject(new TopoShapeEdgePy(new TopoShape(edge)));
1365
Py::Object makePolygon(const Py::Tuple& args)
1368
PyObject *pclosed=Py_False;
1369
if (!PyArg_ParseTuple(args.ptr(), "O|O!", &pcObj, &(PyBool_Type), &pclosed))
1370
throw Py::Exception();
1372
BRepBuilderAPI_MakePolygon mkPoly;
1374
Py::Sequence list(pcObj);
1375
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
1376
if (PyObject_TypeCheck((*it).ptr(), &(Base::VectorPy::Type))) {
1377
Base::Vector3d v = static_cast<Base::VectorPy*>((*it).ptr())->value();
1378
mkPoly.Add(gp_Pnt(v.x,v.y,v.z));
1380
else if (PyObject_TypeCheck((*it).ptr(), &PyTuple_Type)) {
1381
Base::Vector3d v = Base::getVectorFromTuple<double>((*it).ptr());
1382
mkPoly.Add(gp_Pnt(v.x,v.y,v.z));
1386
if (!mkPoly.IsDone())
1387
Standard_Failure::Raise("Cannot create polygon because less than two vertices are given");
1389
// if the polygon should be closed
1390
if (Base::asBoolean(pclosed)) {
1391
if (!mkPoly.FirstVertex().IsSame(mkPoly.LastVertex())) {
1392
mkPoly.Add(mkPoly.FirstVertex());
1396
return Py::asObject(new TopoShapeWirePy(new TopoShape(mkPoly.Wire())));
1398
catch (Standard_Failure& e) {
1399
throw Py::Exception(PartExceptionOCCError, e.GetMessageString());
1402
Py::Object makeCircle(const Py::Tuple& args)
1404
double radius, angle1=0.0, angle2=360;
1405
PyObject *pPnt=nullptr, *pDir=nullptr;
1406
if (!PyArg_ParseTuple(args.ptr(), "d|O!O!dd",
1408
&(Base::VectorPy::Type), &pPnt,
1409
&(Base::VectorPy::Type), &pDir,
1411
throw Py::Exception();
1417
Base::Vector3d pnt = static_cast<Base::VectorPy*>(pPnt)->value();
1418
loc.SetCoord(pnt.x, pnt.y, pnt.z);
1421
Base::Vector3d vec = static_cast<Base::VectorPy*>(pDir)->value();
1422
dir.SetCoord(vec.x, vec.y, vec.z);
1424
gp_Ax1 axis(loc, dir);
1426
circle.SetAxis(axis);
1427
circle.SetRadius(radius);
1429
Handle(Geom_Circle) hCircle = new Geom_Circle (circle);
1430
BRepBuilderAPI_MakeEdge aMakeEdge(hCircle, angle1*(M_PI/180), angle2*(M_PI/180));
1431
TopoDS_Edge edge = aMakeEdge.Edge();
1432
return Py::asObject(new TopoShapeEdgePy(new TopoShape(edge)));
1434
catch (Standard_Failure&) {
1435
throw Py::Exception(PartExceptionOCCError, "creation of circle failed");
1438
Py::Object makeSphere(const Py::Tuple& args)
1440
double radius, angle1=-90, angle2=90, angle3=360;
1441
PyObject *pPnt=nullptr, *pDir=nullptr;
1442
if (!PyArg_ParseTuple(args.ptr(), "d|O!O!ddd",
1444
&(Base::VectorPy::Type), &pPnt,
1445
&(Base::VectorPy::Type), &pDir,
1446
&angle1, &angle2, &angle3))
1447
throw Py::Exception();
1453
Base::Vector3d pnt = static_cast<Base::VectorPy*>(pPnt)->value();
1454
p.SetCoord(pnt.x, pnt.y, pnt.z);
1457
Base::Vector3d vec = static_cast<Base::VectorPy*>(pDir)->value();
1458
d.SetCoord(vec.x, vec.y, vec.z);
1460
BRepPrimAPI_MakeSphere mkSphere(gp_Ax2(p,d), radius, angle1*(M_PI/180), angle2*(M_PI/180), angle3*(M_PI/180));
1461
TopoDS_Shape shape = mkSphere.Shape();
1462
return Py::asObject(new TopoShapeSolidPy(new TopoShape(shape)));
1464
catch (Standard_DomainError&) {
1465
throw Py::Exception(PartExceptionOCCDomainError, "creation of sphere failed");
1468
Py::Object makeCylinder(const Py::Tuple& args)
1470
double radius, height, angle=360;
1471
PyObject *pPnt=nullptr, *pDir=nullptr;
1472
if (!PyArg_ParseTuple(args.ptr(), "dd|O!O!d",
1474
&(Base::VectorPy::Type), &pPnt,
1475
&(Base::VectorPy::Type), &pDir,
1477
throw Py::Exception();
1483
Base::Vector3d pnt = static_cast<Base::VectorPy*>(pPnt)->value();
1484
p.SetCoord(pnt.x, pnt.y, pnt.z);
1487
Base::Vector3d vec = static_cast<Base::VectorPy*>(pDir)->value();
1488
d.SetCoord(vec.x, vec.y, vec.z);
1490
BRepPrimAPI_MakeCylinder mkCyl(gp_Ax2(p,d),radius, height, angle*(M_PI/180));
1491
TopoDS_Shape shape = mkCyl.Shape();
1492
return Py::asObject(new TopoShapeSolidPy(new TopoShape(shape)));
1494
catch (Standard_DomainError&) {
1495
throw Py::Exception(PartExceptionOCCDomainError, "creation of cylinder failed");
1498
Py::Object makeCone(const Py::Tuple& args)
1500
double radius1, radius2, height, angle=360;
1501
PyObject *pPnt=nullptr, *pDir=nullptr;
1502
if (!PyArg_ParseTuple(args.ptr(), "ddd|O!O!d",
1503
&radius1, &radius2, &height,
1504
&(Base::VectorPy::Type), &pPnt,
1505
&(Base::VectorPy::Type), &pDir,
1507
throw Py::Exception();
1513
Base::Vector3d pnt = static_cast<Base::VectorPy*>(pPnt)->value();
1514
p.SetCoord(pnt.x, pnt.y, pnt.z);
1517
Base::Vector3d vec = static_cast<Base::VectorPy*>(pDir)->value();
1518
d.SetCoord(vec.x, vec.y, vec.z);
1520
BRepPrimAPI_MakeCone mkCone(gp_Ax2(p,d),radius1, radius2, height, angle*(M_PI/180));
1521
TopoDS_Shape shape = mkCone.Shape();
1522
return Py::asObject(new TopoShapeSolidPy(new TopoShape(shape)));
1524
catch (Standard_DomainError&) {
1525
throw Py::Exception(PartExceptionOCCDomainError, "creation of cone failed");
1528
Py::Object makeTorus(const Py::Tuple& args)
1530
double radius1, radius2, angle1=0.0, angle2=360, angle=360;
1531
PyObject *pPnt=nullptr, *pDir=nullptr;
1532
if (!PyArg_ParseTuple(args.ptr(), "dd|O!O!ddd",
1534
&(Base::VectorPy::Type), &pPnt,
1535
&(Base::VectorPy::Type), &pDir,
1536
&angle1, &angle2, &angle))
1537
throw Py::Exception();
1543
Base::Vector3d pnt = static_cast<Base::VectorPy*>(pPnt)->value();
1544
p.SetCoord(pnt.x, pnt.y, pnt.z);
1547
Base::Vector3d vec = static_cast<Base::VectorPy*>(pDir)->value();
1548
d.SetCoord(vec.x, vec.y, vec.z);
1550
BRepPrimAPI_MakeTorus mkTorus(gp_Ax2(p,d), radius1, radius2, angle1*(M_PI/180), angle2*(M_PI/180), angle*(M_PI/180));
1551
const TopoDS_Shape& shape = mkTorus.Shape();
1552
return Py::asObject(new TopoShapeSolidPy(new TopoShape(shape)));
1554
catch (Standard_DomainError&) {
1555
throw Py::Exception(PartExceptionOCCDomainError, "creation of torus failed");
1558
Py::Object makeHelix(const Py::Tuple& args)
1560
double pitch, height, radius, angle=-1.0;
1561
PyObject *pleft=Py_False;
1562
PyObject *pvertHeight=Py_False;
1563
if (!PyArg_ParseTuple(args.ptr(), "ddd|dO!O!",
1564
&pitch, &height, &radius, &angle,
1565
&(PyBool_Type), &pleft,
1566
&(PyBool_Type), &pvertHeight))
1567
throw Py::Exception();
1571
Standard_Boolean anIsLeft = Base::asBoolean(pleft);
1572
Standard_Boolean anIsVertHeight = Base::asBoolean(pvertHeight);
1573
TopoDS_Shape wire = helix.makeHelix(pitch, height, radius, angle,
1574
anIsLeft, anIsVertHeight);
1575
return Py::asObject(new TopoShapeWirePy(new TopoShape(wire)));
1577
catch (Standard_Failure& e) {
1578
throw Py::Exception(PartExceptionOCCError, e.GetMessageString());
1581
Py::Object makeLongHelix(const Py::Tuple& args)
1583
double pitch, height, radius, angle=-1.0;
1584
PyObject *pleft=Py_False;
1585
if (!PyArg_ParseTuple(args.ptr(), "ddd|dO!", &pitch, &height, &radius, &angle,
1586
&(PyBool_Type), &pleft)) {
1587
throw Py::RuntimeError("Part.makeLongHelix fails on parms");
1592
Standard_Boolean anIsLeft = Base::asBoolean(pleft);
1593
TopoDS_Shape wire = helix.makeLongHelix(pitch, height, radius, angle, anIsLeft);
1594
return Py::asObject(new TopoShapeWirePy(new TopoShape(wire)));
1596
catch (Standard_Failure& e) {
1597
throw Py::Exception(PartExceptionOCCError, e.GetMessageString());
1600
Py::Object makeThread(const Py::Tuple& args)
1602
double pitch, depth, height, radius;
1603
if (!PyArg_ParseTuple(args.ptr(), "dddd", &pitch, &depth, &height, &radius))
1604
throw Py::Exception();
1608
TopoDS_Shape wire = helix.makeThread(pitch, depth, height, radius);
1609
return Py::asObject(new TopoShapeWirePy(new TopoShape(wire)));
1611
catch (Standard_Failure& e) {
1612
throw Py::Exception(PartExceptionOCCError, e.GetMessageString());
1615
Py::Object makeRevolution(const Py::Tuple& args)
1617
double vmin = DBL_MAX, vmax=-DBL_MAX;
1619
PyObject *pPnt=nullptr, *pDir=nullptr, *pCrv;
1620
Handle(Geom_Curve) curve;
1621
PyObject* defaultType = Base::getTypeAsObject(&Part::TopoShapeSolidPy::Type);
1622
PyObject* type = defaultType;
1625
if (PyArg_ParseTuple(args.ptr(), "O!|dddO!O!O!", &(GeometryPy::Type), &pCrv,
1626
&vmin, &vmax, &angle,
1627
&(Base::VectorPy::Type), &pPnt,
1628
&(Base::VectorPy::Type), &pDir,
1629
&(PyType_Type), &type)) {
1630
GeometryPy* pcGeo = static_cast<GeometryPy*>(pCrv);
1631
curve = Handle(Geom_Curve)::DownCast
1632
(pcGeo->getGeometryPtr()->handle());
1633
if (curve.IsNull()) {
1634
throw Py::Exception(PyExc_TypeError, "geometry is not a curve");
1636
if (vmin == DBL_MAX)
1637
vmin = curve->FirstParameter();
1639
if (vmax == -DBL_MAX)
1640
vmax = curve->LastParameter();
1645
if (PyArg_ParseTuple(args.ptr(), "O!|dddO!O!O!", &(TopoShapePy::Type), &pCrv,
1646
&vmin, &vmax, &angle,
1647
&(Base::VectorPy::Type), &pPnt,
1648
&(Base::VectorPy::Type), &pDir,
1649
&(PyType_Type), &type)) {
1650
const TopoDS_Shape& shape = static_cast<TopoShapePy*>(pCrv)->getTopoShapePtr()->getShape();
1651
if (shape.IsNull()) {
1652
throw Py::Exception(PartExceptionOCCError, "shape is empty");
1655
if (shape.ShapeType() != TopAbs_EDGE) {
1656
throw Py::Exception(PartExceptionOCCError, "shape is not an edge");
1659
const TopoDS_Edge& edge = TopoDS::Edge(shape);
1660
BRepAdaptor_Curve adapt(edge);
1662
const Handle(Geom_Curve)& hCurve = adapt.Curve().Curve();
1663
// Apply placement of the shape to the curve
1664
TopLoc_Location loc = edge.Location();
1665
curve = Handle(Geom_Curve)::DownCast(hCurve->Transformed(loc.Transformation()));
1666
if (curve.IsNull()) {
1667
throw Py::Exception(PartExceptionOCCError, "invalid curve in edge");
1670
if (vmin == DBL_MAX)
1671
vmin = adapt.FirstParameter();
1672
if (vmax == -DBL_MAX)
1673
vmax = adapt.LastParameter();
1677
// invalid arguments
1678
throw Py::TypeError("Expected arguments are:\n"
1679
"Curve or Edge, [float, float, float, Vector, Vector, ShapeType]");
1687
Base::Vector3d pnt = static_cast<Base::VectorPy*>(pPnt)->value();
1688
p.SetCoord(pnt.x, pnt.y, pnt.z);
1691
Base::Vector3d vec = static_cast<Base::VectorPy*>(pDir)->value();
1692
d.SetCoord(vec.x, vec.y, vec.z);
1695
PyObject* shellType = Base::getTypeAsObject(&Part::TopoShapeShellPy::Type);
1696
PyObject* faceType = Base::getTypeAsObject(&Part::TopoShapeFacePy::Type);
1698
BRepPrimAPI_MakeRevolution mkRev(gp_Ax2(p,d),curve, vmin, vmax, angle*(M_PI/180));
1699
if (type == defaultType) {
1700
TopoDS_Shape shape = mkRev.Solid();
1701
return Py::asObject(new TopoShapeSolidPy(new TopoShape(shape)));
1703
else if (type == shellType) {
1704
TopoDS_Shape shape = mkRev.Shell();
1705
return Py::asObject(new TopoShapeShellPy(new TopoShape(shape)));
1707
else if (type == faceType) {
1708
TopoDS_Shape shape = mkRev.Face();
1709
return Py::asObject(new TopoShapeFacePy(new TopoShape(shape)));
1712
TopoDS_Shape shape = mkRev.Shape();
1713
return Py::asObject(new TopoShapePy(new TopoShape(shape)));
1716
catch (Standard_DomainError&) {
1717
throw Py::Exception(PartExceptionOCCDomainError, "creation of revolved shape failed");
1721
Py::Object makeRuledSurface(const Py::Tuple& args, const Py::Dict &kwds)
1723
const char* op = nullptr;
1724
int orientation = 0;
1725
PyObject *sh1, *sh2;
1726
const std::array<const char*, 5> kwd_list = {"path",
1731
if (!Base::Wrapped_ParseTupleAndKeywords(args.ptr(),
1735
&(TopoShapePy::Type),
1737
&(TopoShapePy::Type),
1741
throw Py::Exception();
1744
std::vector<TopoShape> shapes;
1745
shapes.push_back(*static_cast<TopoShapePy*>(sh1)->getTopoShapePtr());
1746
shapes.push_back(*static_cast<TopoShapePy*>(sh2)->getTopoShapePtr());
1747
return shape2pyshape(TopoShape().makeElementRuledSurface(shapes, orientation, op));
1750
Py::Object makeShellFromWires(const Py::Tuple& args, const Py::Dict &kwds)
1753
const char* op = nullptr;
1754
const std::array<const char*, 3> kwd_list = {"shape", "op", nullptr};
1755
if (!Base::Wrapped_ParseTupleAndKeywords(args.ptr(),
1761
throw Py::Exception();
1764
return shape2pyshape(
1765
TopoShape().makeElementShellFromWires(getPyShapes(pylist), /*silent*/ false, op));
1767
catch (Standard_Failure&) {
1768
throw Py::Exception(PartExceptionOCCError, "creation of shell failed");
1772
Py::Object makeTube(const Py::Tuple& args)
1776
double tolerance=0.001;
1777
const char* scont = "C0";
1779
int maxsegment = 30;
1782
if (!PyArg_ParseTuple(args.ptr(), "O!d|sii", &(TopoShapePy::Type), &pshape, &radius, &scont, &maxdegree, &maxsegment))
1783
throw Py::Exception();
1785
std::string str_cont = scont;
1787
if (str_cont == "C0")
1788
cont = (int)GeomAbs_C0;
1789
else if (str_cont == "C1")
1790
cont = (int)GeomAbs_C1;
1791
else if (str_cont == "C2")
1792
cont = (int)GeomAbs_C2;
1793
else if (str_cont == "C3")
1794
cont = (int)GeomAbs_C3;
1795
else if (str_cont == "CN")
1796
cont = (int)GeomAbs_CN;
1797
else if (str_cont == "G1")
1798
cont = (int)GeomAbs_G1;
1799
else if (str_cont == "G2")
1800
cont = (int)GeomAbs_G2;
1802
cont = (int)GeomAbs_C0;
1805
const TopoDS_Shape& path_shape = static_cast<TopoShapePy*>(pshape)->getTopoShapePtr()->getShape();
1806
TopoShape myShape(path_shape);
1807
TopoDS_Shape face = myShape.makeTube(radius, tolerance, cont, maxdegree, maxsegment);
1808
return Py::asObject(new TopoShapeFacePy(new TopoShape(face)));
1810
catch (Standard_Failure& e) {
1811
throw Py::Exception(PartExceptionOCCError, e.GetMessageString());
1814
Py::Object makeSweepSurface(const Py::Tuple& args)
1816
PyObject *path, *profile;
1817
double tolerance=0.001;
1821
if (!PyArg_ParseTuple(args.ptr(), "O!O!|di", &(TopoShapePy::Type), &path,
1822
&(TopoShapePy::Type), &profile,
1823
&tolerance, &fillMode))
1824
throw Py::Exception();
1827
TopoShape mShape = *static_cast<TopoShapePy*>(path)->getTopoShapePtr();
1828
// makeSweep uses GeomFill_Pipe which does not support shape
1829
// history. So use makEPipeShell() as a replacement
1830
return shape2pyshape(
1831
TopoShape(0, mShape.Hasher)
1832
.makeElementPipeShell(
1833
{mShape, *static_cast<TopoShapePy*>(profile)->getTopoShapePtr()},
1834
Part::MakeSolid::noSolid,
1836
TransitionMode::Transformed,
1840
catch (Standard_Failure& e) {
1841
throw Py::Exception(PartExceptionOCCError, e.GetMessageString());
1845
Py::Object makeLoft(const Py::Tuple& args, const Py::Dict &kwds)
1848
PyObject *psolid=Py_False;
1849
PyObject *pruled=Py_False;
1850
PyObject *pclosed=Py_False;
1853
const char* op = nullptr;
1854
const std::array<const char*, 7> kwd_list =
1855
{"shapes", "solid", "ruled", "closed", "max_degree", "op", nullptr};
1856
if (!Base::Wrapped_ParseTupleAndKeywords(args.ptr(),
1870
throw Py::Exception();
1872
Standard_Boolean anIsSolid = PyObject_IsTrue(psolid) ? Standard_True : Standard_False;
1873
Standard_Boolean anIsRuled = PyObject_IsTrue(pruled) ? Standard_True : Standard_False;
1874
Standard_Boolean anIsClosed = PyObject_IsTrue(pclosed) ? Standard_True : Standard_False;
1875
return shape2pyshape(TopoShape().makeElementLoft(
1877
anIsSolid ? Part::IsSolid::solid : Part::IsSolid::notSolid,
1878
anIsRuled ? Part::IsRuled::ruled : Part::IsRuled::notRuled,
1879
anIsClosed ? Part::IsClosed::closed : Part::IsClosed::notClosed,
1884
Py::Object makeSplitShape(const Py::Tuple& args)
1888
PyObject* checkInterior = Py_True;
1889
if (!PyArg_ParseTuple(args.ptr(), "O!O|O!", &(TopoShapePy::Type), &shape, &list,
1890
&PyBool_Type, &checkInterior))
1891
throw Py::Exception();
1894
std::vector<TopoShape> sources;
1895
sources.push_back(*static_cast<TopoShapePy*>(shape)->getTopoShapePtr());
1896
TopoDS_Shape initShape = static_cast<TopoShapePy*>
1897
(shape)->getTopoShapePtr()->getShape();
1898
BRepFeat_SplitShape splitShape(initShape);
1899
splitShape.SetCheckInterior(Base::asBoolean(checkInterior));
1901
Py::Sequence seq(list);
1902
for (Py::Sequence::iterator it = seq.begin(); it != seq.end(); ++it) {
1903
Py::Tuple tuple(*it);
1904
Py::TopoShape sh1(tuple[0]);
1905
Py::TopoShape sh2(tuple[1]);
1906
sources.push_back(*sh1.extensionObject()->getTopoShapePtr());
1907
const TopoDS_Shape& shape1= sh1.extensionObject()->getTopoShapePtr()->getShape();
1908
const TopoDS_Shape& shape2= sh2.extensionObject()->getTopoShapePtr()->getShape();
1909
if (shape1.IsNull() || shape2.IsNull())
1910
throw Py::RuntimeError("Cannot add null shape");
1911
if (shape2.ShapeType() == TopAbs_FACE) {
1912
if (shape1.ShapeType() == TopAbs_EDGE) {
1913
splitShape.Add(TopoDS::Edge(shape1), TopoDS::Face(shape2));
1915
else if (shape1.ShapeType() == TopAbs_WIRE) {
1916
splitShape.Add(TopoDS::Wire(shape1), TopoDS::Face(shape2));
1918
else if (shape1.ShapeType() == TopAbs_COMPOUND) {
1919
splitShape.Add(TopoDS::Compound(shape1), TopoDS::Face(shape2));
1922
throw Py::TypeError("First item in tuple must be Edge, Wire or Compound");
1925
else if (shape2.ShapeType() == TopAbs_EDGE) {
1926
if (shape1.ShapeType() == TopAbs_EDGE) {
1927
splitShape.Add(TopoDS::Edge(shape1), TopoDS::Edge(shape2));
1930
throw Py::TypeError("First item in tuple must be Edge");
1934
throw Py::TypeError("Second item in tuple must be Face or Edge");
1939
const TopTools_ListOfShape& d = splitShape.DirectLeft();
1940
const TopTools_ListOfShape& l = splitShape.Left();
1944
MapperMaker mapper(splitShape);
1945
for (TopTools_ListIteratorOfListOfShape it(d); it.More(); it.Next()) {
1946
TopoShape s(0, sources.front().Hasher);
1947
list1.append(shape2pyshape(
1948
s.makeShapeWithElementMap(it.Value(), mapper, sources, Part::OpCodes::Split)));
1950
for (TopTools_ListIteratorOfListOfShape it(l); it.More(); it.Next()) {
1951
TopoShape s(0, sources.front().Hasher);
1952
list2.append(shape2pyshape(
1953
s.makeShapeWithElementMap(it.Value(), mapper, sources, Part::OpCodes::Split)));
1956
tuple.setItem(0, list1);
1957
tuple.setItem(1, list2);
1960
catch (Standard_Failure& e) {
1961
throw Py::Exception(PartExceptionOCCError, e.GetMessageString());
1964
Py::Object makeWireString(const Py::Tuple& args)
1969
const char* fontfile;
1970
const char* fontspec;
1971
bool useFontSpec = false;
1975
Py_UNICODE *unichars = nullptr;
1980
if (PyArg_ParseTuple(args.ptr(), "Ossd|d", &intext, // compatibility with old version
1985
useFontSpec = false;
1989
if (PyArg_ParseTuple(args.ptr(), "Osd|d", &intext,
1996
throw Py::TypeError("** makeWireString bad args.");
2001
if (PyBytes_Check(intext)) {
2002
PyObject *p = Base::PyAsUnicodeObject(PyBytes_AsString(intext));
2004
throw Py::TypeError("** makeWireString can't convert PyString.");
2007
pysize = PyUnicode_GetLength(p);
2008
#if PY_VERSION_HEX < 0x03090000
2009
unichars = PyUnicode_AS_UNICODE(p);
2012
//PyUNICODE is only 16 bits on Windows (wchar_t), so passing 32 bit UCS4
2013
//will result in unknown glyph in even positions, and wrong characters in
2015
unichars = (Py_UNICODE*)PyUnicode_AsWideCharString(p, &pysize);
2017
unichars = (Py_UNICODE *)PyUnicode_AsUCS4Copy(p);
2021
else if (PyUnicode_Check(intext)) {
2022
pysize = PyUnicode_GetLength(intext);
2024
#if PY_VERSION_HEX < 0x03090000
2025
unichars = PyUnicode_AS_UNICODE(intext);
2028
//PyUNICODE is only 16 bits on Windows (wchar_t), so passing 32 bit UCS4
2029
//will result in unknown glyph in even positions, and wrong characters in
2031
unichars = (Py_UNICODE*)PyUnicode_AsWideCharString(intext, &pysize);
2033
unichars = (Py_UNICODE *)PyUnicode_AsUCS4Copy(intext);
2038
throw Py::TypeError("** makeWireString bad text parameter");
2043
CharList = FT2FC(unichars,pysize,fontspec,height,track);
2046
CharList = FT2FC(unichars,pysize,dir,fontfile,height,track);
2048
#if PY_VERSION_HEX >= 0x03090000
2050
PyMem_Free(unichars);
2054
catch (Standard_DomainError&) { // Standard_DomainError is OCC error.
2055
throw Py::Exception(PartExceptionOCCDomainError, "makeWireString failed - Standard_DomainError");
2057
catch (std::runtime_error& e) { // FT2 or FT2FC errors
2058
throw Py::Exception(PartExceptionOCCError, e.what());
2061
return Py::asObject(CharList);
2063
throw Py::RuntimeError("FreeCAD compiled without FreeType support! This method is disabled...");
2066
Py::Object exportUnits(const Py::Tuple& args)
2069
if (!PyArg_ParseTuple(args.ptr(), "|s", &unit))
2070
throw Py::Exception();
2073
if (!Interface::writeIgesUnit(unit)) {
2074
throw Py::RuntimeError("Failed to set 'write.iges.unit'");
2076
if (!Interface::writeStepUnit(unit)) {
2077
throw Py::RuntimeError("Failed to set 'write.step.unit'");
2082
dict.setItem("write.iges.unit", Py::String(Interface::writeIgesUnit()));
2083
dict.setItem("write.step.unit", Py::String(Interface::writeStepUnit()));
2086
Py::Object setStaticValue(const Py::Tuple& args)
2089
if (PyArg_ParseTuple(args.ptr(), "ss", &name, &cval)) {
2090
if (!Interface_Static::SetCVal(name, cval)) {
2091
std::stringstream str;
2092
str << "Failed to set '" << name << "'";
2093
throw Py::RuntimeError(str.str());
2099
PyObject* index_or_value;
2100
if (PyArg_ParseTuple(args.ptr(), "sO", &name, &index_or_value)) {
2101
if (PyLong_Check(index_or_value)) {
2102
int ival = (int)PyLong_AsLong(index_or_value);
2103
if (!Interface_Static::SetIVal(name, ival)) {
2104
std::stringstream str;
2105
str << "Failed to set '" << name << "'";
2106
throw Py::RuntimeError(str.str());
2110
else if (PyFloat_Check(index_or_value)) {
2111
double rval = PyFloat_AsDouble(index_or_value);
2112
if (!Interface_Static::SetRVal(name, rval)) {
2113
std::stringstream str;
2114
str << "Failed to set '" << name << "'";
2115
throw Py::RuntimeError(str.str());
2121
throw Py::TypeError("First argument must be string and must be either string, int or float");
2123
Py::Object cast_to_shape(const Py::Tuple& args)
2126
if (PyArg_ParseTuple(args.ptr(),"O!",&(Part::TopoShapePy::Type), &object)) {
2127
TopoShape* ptr = static_cast<TopoShapePy*>(object)->getTopoShapePtr();
2128
return Py::asObject(ptr->getPyObject());
2131
throw Py::Exception();
2133
Py::Object getSortedClusters(const Py::Tuple& args)
2136
if (!PyArg_ParseTuple(args.ptr(), "O", &obj)) {
2137
throw Py::Exception(PartExceptionOCCError, "list of edges expected");
2140
Py::Sequence list(obj);
2141
std::vector<TopoDS_Edge> edges;
2142
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
2143
PyObject* item = (*it).ptr();
2144
if (PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) {
2145
const TopoDS_Shape& sh = static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape();
2146
if (sh.ShapeType() == TopAbs_EDGE)
2147
edges.push_back(TopoDS::Edge(sh));
2149
throw Py::TypeError("shape is not an edge");
2153
throw Py::TypeError("item is not a shape");
2157
Edgecluster acluster(edges);
2158
tEdgeClusterVector aclusteroutput = acluster.GetClusters();
2161
for (const auto & it : aclusteroutput) {
2163
for (const auto& it1 : it) {
2164
add_list.append(Py::Object(new TopoShapeEdgePy(new TopoShape(it1)),true));
2166
root_list.append(add_list);
2171
Py::Object sortEdges(const Py::Tuple& args)
2174
if (!PyArg_ParseTuple(args.ptr(), "O", &obj)) {
2175
throw Py::TypeError("list of edges expected");
2178
Py::Sequence list(obj);
2179
std::list<TopoDS_Edge> edges;
2180
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
2181
PyObject* item = (*it).ptr();
2182
if (PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) {
2183
const TopoDS_Shape& sh = static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape();
2184
if (sh.ShapeType() == TopAbs_EDGE)
2185
edges.push_back(TopoDS::Edge(sh));
2187
throw Py::TypeError("shape is not an edge");
2191
throw Py::TypeError("item is not a shape");
2195
std::list<TopoDS_Edge> sorted = sort_Edges(Precision::Confusion(), edges);
2196
Py::List sorted_list;
2197
for (const auto & it : sorted) {
2198
sorted_list.append(Py::Object(new TopoShapeEdgePy(new TopoShape(it)),true));
2203
Py::Object sortEdges2(const Py::Tuple& args)
2206
double tol3d = Precision::Confusion();
2207
if (!PyArg_ParseTuple(args.ptr(), "O|d", &obj, &tol3d)) {
2208
throw Py::Exception(PartExceptionOCCError, "list of edges expected");
2211
Py::Sequence list(obj);
2212
std::list<TopoDS_Edge> edges;
2213
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
2214
PyObject* item = (*it).ptr();
2215
if (PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) {
2216
const TopoDS_Shape& sh = static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape();
2217
if (sh.ShapeType() == TopAbs_EDGE)
2218
edges.push_back(TopoDS::Edge(sh));
2220
throw Py::TypeError("shape is not an edge");
2224
throw Py::TypeError("item is not a shape");
2229
while(!edges.empty()) {
2230
std::list<TopoDS_Edge> sorted = sort_Edges(tol3d, edges);
2231
Py::List sorted_list;
2232
for (const auto & it : sorted) {
2233
sorted_list.append(Py::Object(new TopoShapeEdgePy(new TopoShape(it)),true));
2235
root_list.append(sorted_list);
2239
Py::Object toPythonOCC(const Py::Tuple& args)
2242
if (!PyArg_ParseTuple(args.ptr(), "O!", &(TopoShapePy::Type), &pcObj))
2243
throw Py::Exception();
2246
TopoDS_Shape* shape = new TopoDS_Shape();
2247
(*shape) = static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape();
2248
PyObject* proxy = nullptr;
2249
proxy = Base::Interpreter().createSWIGPointerObj("OCC.TopoDS", "TopoDS_Shape *", static_cast<void*>(shape), 1);
2250
return Py::asObject(proxy);
2252
catch (const Base::Exception& e) {
2253
throw Py::Exception(PartExceptionOCCError, e.what());
2256
Py::Object fromPythonOCC(const Py::Tuple& args)
2259
if (!PyArg_ParseTuple(args.ptr(), "O", &proxy))
2260
throw Py::Exception();
2264
TopoShape* shape = new TopoShape();
2265
Base::Interpreter().convertSWIGPointerObj("OCC.TopoDS","TopoDS_Shape *", proxy, &ptr, 0);
2266
TopoDS_Shape* s = static_cast<TopoDS_Shape*>(ptr);
2267
shape->setShape(*s);
2268
return Py::asObject(new TopoShapePy(shape));
2270
catch (const Base::Exception& e) {
2271
throw Py::Exception(PartExceptionOCCError, e.what());
2275
Py::Object getShape(const Py::Tuple& args, const Py::Dict &kwds) {
2277
const char *subname = nullptr;
2278
PyObject *pyMat = nullptr;
2279
PyObject *needSubElement = Py_False;
2280
PyObject *transform = Py_True;
2281
PyObject *noElementMap = Py_False;
2282
PyObject *refine = Py_False;
2284
static const std::array<const char *, 9> kwd_list{"obj", "subname", "mat",
2285
"needSubElement", "transform", "retType", "noElementMap",
2287
if (!Base::Wrapped_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), "O!|sO!O!O!hO!O!", kwd_list,
2288
&App::DocumentObjectPy::Type, &pObj, &subname,
2289
&Base::MatrixPy::Type, &pyMat,
2290
&PyBool_Type, &needSubElement,
2291
&PyBool_Type, &transform, &retType,
2292
&PyBool_Type, &noElementMap,
2293
&PyBool_Type, &refine)) {
2294
throw Py::Exception();
2297
App::DocumentObject *obj =
2298
static_cast<App::DocumentObjectPy*>(pObj)->getDocumentObjectPtr();
2299
App::DocumentObject *subObj = nullptr;
2302
mat = *static_cast<Base::MatrixPy*>(pyMat)->getMatrixPtr();
2303
auto shape = Feature::getTopoShape(obj,subname,Base::asBoolean(needSubElement),
2304
&mat,&subObj,retType==2,Base::asBoolean(transform),
2305
Base::asBoolean(noElementMap));
2306
if (Base::asBoolean(refine)) {
2307
shape = TopoShape(0, shape.Hasher).makeElementRefine(shape);
2309
Py::Object sret(shape2pyshape(shape));
2313
return Py::TupleN(sret,Py::asObject(new Base::MatrixPy(new Base::Matrix4D(mat))),
2314
subObj?Py::Object(subObj->getPyObject(),true):Py::Object());
2317
Py::Object clearShapeCache(const Py::Tuple &args) {
2318
if (!PyArg_ParseTuple(args.ptr(),""))
2319
throw Py::Exception();
2320
Part::Feature::clearShapeCache();
2321
return Py::Object();
2324
Py::Object splitSubname(const Py::Tuple& args) {
2325
const char *subname;
2326
if (!PyArg_ParseTuple(args.ptr(), "s",&subname))
2327
throw Py::Exception();
2328
auto element = Data::findElementName(subname);
2329
std::string sub(subname,element-subname);
2331
list.append(Py::String(sub));
2332
const char *dot = strchr(element,'.');
2334
dot = element+strlen(element);
2335
const char *mapped = Data::isMappedElement(element);
2337
list.append(Py::String(std::string(mapped,dot-mapped)));
2339
list.append(Py::String());
2341
list.append(Py::String(dot+1));
2343
list.append(Py::String(element));
2345
list.append(Py::String());
2349
Py::Object joinSubname(const Py::Tuple& args) {
2352
const char *element;
2353
if (!PyArg_ParseTuple(args.ptr(), "sss",&sub,&mapped,&element))
2354
throw Py::Exception();
2355
std::string subname(sub);
2356
if (!subname.empty() && subname[subname.size()-1]!='.')
2358
if (mapped && mapped[0]) {
2359
if (!Data::isMappedElement(mapped))
2360
subname += Data::ELEMENT_MAP_PREFIX;
2363
if (element && element[0]) {
2364
if (!subname.empty() && subname[subname.size()-1]!='.')
2368
return Py::String(subname);
2372
PyObject* initModule()
2374
return Base::Interpreter().addModule(new Module);