This adds isNullOrEmpty string helper that cheks if string is... well null or empty. It is done to improve readability of the code and better express intent.
2762 lines
88 KiB
C++
2762 lines
88 KiB
C++
/***************************************************************************
|
|
* Copyright (c) 2008 Jürgen Riegel <juergen.riegel@web.de> *
|
|
* *
|
|
* This file is part of the FreeCAD CAx development system. *
|
|
* *
|
|
* This library is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU Library General Public *
|
|
* License as published by the Free Software Foundation; either *
|
|
* version 2 of the License, or (at your option) any later version. *
|
|
* *
|
|
* This library is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU Library General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Library General Public *
|
|
* License along with this library; see the file COPYING.LIB. If not, *
|
|
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
|
* Suite 330, Boston, MA 02111-1307, USA *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "PreCompiled.h"
|
|
#ifndef _PreComp_
|
|
# include <sstream>
|
|
# include <boost/regex.hpp>
|
|
|
|
# include <BRep_Tool.hxx>
|
|
# include <BRepAlgo_NormalProjection.hxx>
|
|
# include <BRepBndLib.hxx>
|
|
# include <BRepBuilderAPI_Copy.hxx>
|
|
# include <BRepBuilderAPI_MakeVertex.hxx>
|
|
# include <BRepBuilderAPI_Transform.hxx>
|
|
# include <BRepClass3d_SolidClassifier.hxx>
|
|
# include <BRepExtrema_DistShapeShape.hxx>
|
|
# include <BRepExtrema_ShapeProximity.hxx>
|
|
# include <BRepExtrema_SupportType.hxx>
|
|
# include <BRepFilletAPI_MakeChamfer.hxx>
|
|
# include <BRepFilletAPI_MakeFillet.hxx>
|
|
# include <BRepGProp.hxx>
|
|
# include <BRepMesh_IncrementalMesh.hxx>
|
|
# include <BRepProj_Projection.hxx>
|
|
# include <BRepTools.hxx>
|
|
# include <Geom_Plane.hxx>
|
|
# include <gp_Ax1.hxx>
|
|
# include <gp_Ax2.hxx>
|
|
# include <gp_Dir.hxx>
|
|
# include <gp_Pln.hxx>
|
|
# include <gp_Pnt.hxx>
|
|
# include <gp_Trsf.hxx>
|
|
# include <GProp_GProps.hxx>
|
|
# include <HLRAppli_ReflectLines.hxx>
|
|
# include <Precision.hxx>
|
|
# include <Poly_Polygon3D.hxx>
|
|
# include <Poly_Triangulation.hxx>
|
|
# include <ShapeAnalysis_ShapeTolerance.hxx>
|
|
# include <ShapeFix_ShapeTolerance.hxx>
|
|
# include <Standard_Version.hxx>
|
|
# include <TopExp.hxx>
|
|
# include <TopExp_Explorer.hxx>
|
|
# include <TopLoc_Location.hxx>
|
|
# include <TopoDS.hxx>
|
|
# include <TopoDS_Iterator.hxx>
|
|
# include <TopTools_IndexedMapOfShape.hxx>
|
|
# include <TopTools_ListIteratorOfListOfShape.hxx>
|
|
# include <TopTools_ListOfShape.hxx>
|
|
#endif
|
|
|
|
#include <App/PropertyStandard.h>
|
|
#include <App/StringHasherPy.h>
|
|
#include <Base/FileInfo.h>
|
|
#include <Base/GeometryPyCXX.h>
|
|
#include <Base/MatrixPy.h>
|
|
#include <Base/PyWrapParseTupleAndKeywords.h>
|
|
#include <Base/Rotation.h>
|
|
#include <Base/Stream.h>
|
|
#include <Base/Tools.h>
|
|
#include <Base/Vector3D.h>
|
|
#include <Base/VectorPy.h>
|
|
|
|
#include <Mod/Part/App/TopoShapePy.h>
|
|
#include <Mod/Part/App/TopoShapePy.cpp>
|
|
|
|
#include <Mod/Part/App/GeometryPy.h>
|
|
#include <Mod/Part/App/PlanePy.h>
|
|
#include <Mod/Part/App/TopoShapeCompoundPy.h>
|
|
#include <Mod/Part/App/TopoShapeCompSolidPy.h>
|
|
#include <Mod/Part/App/TopoShapeEdgePy.h>
|
|
#include <Mod/Part/App/TopoShapeFacePy.h>
|
|
#include <Mod/Part/App/TopoShapeOpCode.h>
|
|
#include <Mod/Part/App/TopoShapeShellPy.h>
|
|
#include <Mod/Part/App/TopoShapeSolidPy.h>
|
|
#include <Mod/Part/App/TopoShapeVertexPy.h>
|
|
#include <Mod/Part/App/TopoShapeWirePy.h>
|
|
|
|
#include "OCCError.h"
|
|
#include "PartPyCXX.h"
|
|
#include "ShapeMapHasher.h"
|
|
#include "TopoShapeMapper.h"
|
|
|
|
|
|
using namespace Part;
|
|
|
|
static Py_hash_t _TopoShapeHash(PyObject* self)
|
|
{
|
|
if (!self) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"descriptor 'hash' of 'Part.TopoShape' object needs an argument");
|
|
return 0;
|
|
}
|
|
if (!static_cast<Base::PyObjectBase*>(self)->isValid()) {
|
|
PyErr_SetString(PyExc_ReferenceError,
|
|
"This object is already deleted most likely through closing a document. "
|
|
"This reference is no longer valid!");
|
|
return 0;
|
|
}
|
|
#if OCC_VERSION_HEX >= 0x070800
|
|
return std::hash<TopoDS_Shape> {}(static_cast<TopoShapePy*>(self)->getTopoShapePtr()->getShape());
|
|
#else
|
|
return static_cast<TopoShapePy*>(self)->getTopoShapePtr()->getShape().HashCode(INT_MAX);
|
|
#endif
|
|
}
|
|
|
|
struct TopoShapePyInit
|
|
{
|
|
TopoShapePyInit()
|
|
{
|
|
TopoShapePy::Type.tp_hash = _TopoShapeHash;
|
|
}
|
|
} _TopoShapePyInit;
|
|
|
|
// returns a string which represents the object e.g. when printed in python
|
|
std::string TopoShapePy::representation() const
|
|
{
|
|
std::stringstream str;
|
|
str << "<Shape object at " << getTopoShapePtr() << ">";
|
|
|
|
return str.str();
|
|
}
|
|
|
|
PyObject *TopoShapePy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
|
|
{
|
|
// create a new instance of TopoShapePy and the Twin object
|
|
return new TopoShapePy(new TopoShape);
|
|
}
|
|
|
|
int TopoShapePy::PyInit(PyObject* args, PyObject* keywds)
|
|
{
|
|
static const std::array<const char*, 5> kwlist{ "shape",
|
|
"op",
|
|
"tag",
|
|
"hasher",
|
|
nullptr };
|
|
long tag = 0;
|
|
PyObject* pyHasher = nullptr;
|
|
const char* op = nullptr;
|
|
PyObject* pcObj = nullptr;
|
|
if (!Base::Wrapped_ParseTupleAndKeywords(args,
|
|
keywds,
|
|
"|OsiO!",
|
|
kwlist,
|
|
&pcObj,
|
|
&op,
|
|
&tag,
|
|
&App::StringHasherPy::Type,
|
|
&pyHasher)) {
|
|
return -1;
|
|
}
|
|
auto& self = *getTopoShapePtr();
|
|
self.Tag = tag;
|
|
if (pyHasher) {
|
|
self.Hasher = static_cast<App::StringHasherPy*>(pyHasher)->getStringHasherPtr();
|
|
}
|
|
auto shapes = getPyShapes(pcObj);
|
|
PY_TRY
|
|
{
|
|
if (shapes.size() == 1 && !op) {
|
|
auto s = shapes.front();
|
|
if (self.Tag) {
|
|
if ((s.Tag && self.Tag != s.Tag)
|
|
|| (self.Hasher && s.getElementMapSize() && self.Hasher != s.Hasher)) {
|
|
s.reTagElementMap(self.Tag, self.Hasher);
|
|
}
|
|
else {
|
|
s.Tag = self.Tag;
|
|
s.Hasher = self.Hasher;
|
|
}
|
|
}
|
|
self = s;
|
|
}
|
|
else if (shapes.size()) {
|
|
if (!op) {
|
|
op = Part::OpCodes::Fuse;
|
|
}
|
|
self.makeElementBoolean(op, shapes);
|
|
}
|
|
}
|
|
_PY_CATCH_OCC(return (-1))
|
|
return 0;
|
|
}
|
|
|
|
PyObject* TopoShapePy::copy(PyObject *args)
|
|
{
|
|
PyObject* copyGeom = Py_True;
|
|
PyObject* copyMesh = Py_False;
|
|
const char* op = nullptr;
|
|
PyObject* pyHasher = nullptr;
|
|
if (!PyArg_ParseTuple(args,
|
|
"|sO!O!O!",
|
|
&op,
|
|
&App::StringHasherPy::Type,
|
|
&pyHasher,
|
|
&PyBool_Type,
|
|
©Geom,
|
|
&PyBool_Type,
|
|
©Mesh)) {
|
|
PyErr_Clear();
|
|
if (!PyArg_ParseTuple(args, "|O!O!", &PyBool_Type, ©Geom, &PyBool_Type, ©Mesh)) {
|
|
return 0;
|
|
}
|
|
}
|
|
if (op && !op[0]) {
|
|
op = nullptr;
|
|
}
|
|
App::StringHasherRef hasher;
|
|
if (pyHasher) {
|
|
hasher = static_cast<App::StringHasherPy*>(pyHasher)->getStringHasherPtr();
|
|
}
|
|
auto& self = *getTopoShapePtr();
|
|
return Py::new_reference_to(shape2pyshape(
|
|
TopoShape(self.Tag, hasher)
|
|
.makeElementCopy(self, op, PyObject_IsTrue(copyGeom), PyObject_IsTrue(copyMesh))));
|
|
}
|
|
|
|
PyObject* TopoShapePy::cleaned(PyObject *args)
|
|
{
|
|
if (!PyArg_ParseTuple(args, ""))
|
|
return nullptr;
|
|
auto& self = *getTopoShapePtr();
|
|
TopoShape copy(self.makeElementCopy());
|
|
if (!copy.isNull()) {
|
|
BRepTools::Clean(copy.getShape()); // remove triangulation
|
|
}
|
|
return Py::new_reference_to(shape2pyshape(copy));
|
|
}
|
|
|
|
PyObject* TopoShapePy::replaceShape(PyObject *args)
|
|
{
|
|
PyObject *l;
|
|
if (!PyArg_ParseTuple(args, "O",&l))
|
|
return nullptr;
|
|
|
|
try {
|
|
Py::Sequence list(l);
|
|
std::vector<std::pair<TopoShape, TopoShape>> shapes;
|
|
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
|
Py::Tuple tuple(*it);
|
|
Py::TopoShape sh1(tuple[0]);
|
|
Py::TopoShape sh2(tuple[1]);
|
|
shapes.push_back(std::make_pair(*sh1.extensionObject()->getTopoShapePtr(),
|
|
*sh2.extensionObject()->getTopoShapePtr()));
|
|
}
|
|
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->replaceElementShape(shapes)));
|
|
}
|
|
catch (const Py::Exception&) {
|
|
return nullptr;
|
|
}
|
|
catch (...) {
|
|
PyErr_SetString(PartExceptionOCCError, "failed to replace shape");
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::removeShape(PyObject *args)
|
|
{
|
|
PyObject *l;
|
|
if (!PyArg_ParseTuple(args, "O",&l))
|
|
return nullptr;
|
|
|
|
try {
|
|
return Py::new_reference_to(
|
|
shape2pyshape(getTopoShapePtr()->removeElementShape(getPyShapes(l))));
|
|
}
|
|
catch (...) {
|
|
PyErr_SetString(PartExceptionOCCError, "failed to remove shape");
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::read(PyObject *args)
|
|
{
|
|
char* Name;
|
|
if (!PyArg_ParseTuple(args, "et","utf-8",&Name))
|
|
return nullptr;
|
|
|
|
std::string EncodedName = std::string(Name);
|
|
PyMem_Free(Name);
|
|
|
|
getTopoShapePtr()->read(EncodedName.c_str());
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* TopoShapePy::writeInventor(PyObject * args, PyObject * keywds)
|
|
{
|
|
static const std::array<const char *, 5> kwlist{"Mode", "Deviation", "Angle", "FaceColors", nullptr};
|
|
|
|
double dev = 0.3, angle = 0.4;
|
|
int mode = 2;
|
|
PyObject *pylist = nullptr;
|
|
if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, "|iddO", kwlist,
|
|
&mode, &dev, &angle, &pylist)) {
|
|
return nullptr;
|
|
}
|
|
|
|
std::vector<App::Color> faceColors;
|
|
if (pylist) {
|
|
App::PropertyColorList prop;
|
|
prop.setPyObject(pylist);
|
|
faceColors = prop.getValues();
|
|
}
|
|
|
|
std::stringstream result;
|
|
BRepMesh_IncrementalMesh(getTopoShapePtr()->getShape(),dev);
|
|
if (mode == 0) {
|
|
getTopoShapePtr()->exportFaceSet(dev, angle, faceColors, result);
|
|
}
|
|
else if (mode == 1) {
|
|
getTopoShapePtr()->exportLineSet(result);
|
|
}
|
|
else {
|
|
getTopoShapePtr()->exportFaceSet(dev, angle, faceColors, result);
|
|
getTopoShapePtr()->exportLineSet(result);
|
|
}
|
|
return Py::new_reference_to(Py::String(result.str()));
|
|
}
|
|
|
|
PyObject* TopoShapePy::exportIges(PyObject *args)
|
|
{
|
|
char* Name;
|
|
if (!PyArg_ParseTuple(args, "et","utf-8",&Name))
|
|
return nullptr;
|
|
|
|
std::string EncodedName = std::string(Name);
|
|
PyMem_Free(Name);
|
|
|
|
try {
|
|
// write iges file
|
|
getTopoShapePtr()->exportIges(EncodedName.c_str());
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError,e.what());
|
|
return nullptr;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* TopoShapePy::exportStep(PyObject *args)
|
|
{
|
|
char* Name;
|
|
if (!PyArg_ParseTuple(args, "et","utf-8",&Name))
|
|
return nullptr;
|
|
|
|
std::string EncodedName = std::string(Name);
|
|
PyMem_Free(Name);
|
|
|
|
try {
|
|
// write step file
|
|
getTopoShapePtr()->exportStep(EncodedName.c_str());
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError,e.what());
|
|
return nullptr;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* TopoShapePy::exportBrep(PyObject *args)
|
|
{
|
|
char* Name;
|
|
if (PyArg_ParseTuple(args, "et","utf-8",&Name)) {
|
|
std::string EncodedName = std::string(Name);
|
|
PyMem_Free(Name);
|
|
|
|
try {
|
|
// write brep file
|
|
getTopoShapePtr()->exportBrep(EncodedName.c_str());
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError,e.what());
|
|
return nullptr;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyErr_Clear();
|
|
|
|
PyObject* input;
|
|
if (PyArg_ParseTuple(args, "O", &input)) {
|
|
try {
|
|
// write brep
|
|
Base::PyStreambuf buf(input);
|
|
std::ostream str(nullptr);
|
|
str.rdbuf(&buf);
|
|
getTopoShapePtr()->exportBrep(str);
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError,e.what());
|
|
return nullptr;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyErr_SetString(PyExc_TypeError, "expect string or file object");
|
|
return nullptr;
|
|
}
|
|
|
|
PyObject* TopoShapePy::exportBinary(PyObject *args)
|
|
{
|
|
char* input;
|
|
if (!PyArg_ParseTuple(args, "s", &input))
|
|
return nullptr;
|
|
|
|
try {
|
|
// read binary brep
|
|
Base::FileInfo fi(input);
|
|
Base::ofstream str(fi, std::ios::out | std::ios::binary);
|
|
getTopoShapePtr()->exportBinary(str);
|
|
str.close();
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError,e.what());
|
|
return nullptr;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* TopoShapePy::dumpToString(PyObject *args)
|
|
{
|
|
if (!PyArg_ParseTuple(args, ""))
|
|
return nullptr;
|
|
|
|
try {
|
|
std::stringstream str;
|
|
getTopoShapePtr()->dump(str);
|
|
return Py::new_reference_to(Py::String(str.str()));
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError,e.what());
|
|
return nullptr;
|
|
}
|
|
catch (const std::exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError,e.what());
|
|
return nullptr;
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::exportBrepToString(PyObject *args)
|
|
{
|
|
if (!PyArg_ParseTuple(args, ""))
|
|
return nullptr;
|
|
|
|
try {
|
|
// write brep file
|
|
std::stringstream str;
|
|
getTopoShapePtr()->exportBrep(str);
|
|
return Py::new_reference_to(Py::String(str.str()));
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError,e.what());
|
|
return nullptr;
|
|
}
|
|
catch (const std::exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError,e.what());
|
|
return nullptr;
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::importBrep(PyObject *args)
|
|
{
|
|
char* Name;
|
|
if (PyArg_ParseTuple(args, "et","utf-8",&Name)) {
|
|
std::string EncodedName = std::string(Name);
|
|
PyMem_Free(Name);
|
|
|
|
try {
|
|
// write brep file
|
|
getTopoShapePtr()->importBrep(EncodedName.c_str());
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError,e.what());
|
|
return nullptr;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyErr_Clear();
|
|
PyObject* input;
|
|
if (PyArg_ParseTuple(args, "O", &input)) {
|
|
try {
|
|
// read brep
|
|
Base::PyStreambuf buf(input);
|
|
std::istream str(nullptr);
|
|
str.rdbuf(&buf);
|
|
getTopoShapePtr()->importBrep(str);
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError,e.what());
|
|
return nullptr;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyErr_SetString(PyExc_TypeError, "expect string or file object");
|
|
return nullptr;
|
|
}
|
|
|
|
PyObject* TopoShapePy::importBinary(PyObject *args)
|
|
{
|
|
char* input;
|
|
if (!PyArg_ParseTuple(args, "s", &input))
|
|
return nullptr;
|
|
|
|
try {
|
|
// read binary brep
|
|
Base::FileInfo fi(input);
|
|
Base::ifstream str(fi, std::ios::in | std::ios::binary);
|
|
getTopoShapePtr()->importBinary(str);
|
|
str.close();
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError,e.what());
|
|
return nullptr;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* TopoShapePy::importBrepFromString(PyObject *args)
|
|
{
|
|
char* input;
|
|
int indicator=1;
|
|
if (!PyArg_ParseTuple(args, "s|i", &input, &indicator))
|
|
return nullptr;
|
|
|
|
try {
|
|
// read brep
|
|
std::stringstream str(input);
|
|
getTopoShapePtr()->importBrep(str,indicator);
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError,e.what());
|
|
return nullptr;
|
|
}
|
|
catch (const std::exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError,e.what());
|
|
return nullptr;
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* TopoShapePy::dumps(PyObject *args) {
|
|
return exportBrepToString(args);
|
|
}
|
|
|
|
|
|
PyObject* TopoShapePy::loads(PyObject *args) {
|
|
if (! getTopoShapePtr()) {
|
|
PyErr_SetString(Base::PyExc_FC_GeneralError,"no c++ object");
|
|
return nullptr;
|
|
}
|
|
else {
|
|
return importBrepFromString(args);
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::exportStl(PyObject *args)
|
|
{
|
|
double deflection = 0.01;
|
|
char* Name;
|
|
if (!PyArg_ParseTuple(args, "et|d","utf-8",&Name,&deflection))
|
|
return nullptr;
|
|
|
|
std::string EncodedName = std::string(Name);
|
|
PyMem_Free(Name);
|
|
|
|
try {
|
|
// write stl file
|
|
getTopoShapePtr()->exportStl(EncodedName.c_str(), deflection);
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError,e.what());
|
|
return nullptr;
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* TopoShapePy::extrude(PyObject *args)
|
|
{
|
|
PyObject *pVec;
|
|
if (!PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type), &pVec))
|
|
return nullptr;
|
|
|
|
try {
|
|
Base::Vector3d vec = static_cast<Base::VectorPy*>(pVec)->value();
|
|
return Py::new_reference_to(
|
|
shape2pyshape(getTopoShapePtr()->makeElementPrism(gp_Vec(vec.x, vec.y, vec.z))));
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::revolve(PyObject *args)
|
|
{
|
|
PyObject *pPos,*pDir;
|
|
double angle=360;
|
|
if (!PyArg_ParseTuple(args, "O!O!|d", &(Base::VectorPy::Type), &pPos, &(Base::VectorPy::Type), &pDir,&angle))
|
|
return nullptr;
|
|
Base::Vector3d pos = static_cast<Base::VectorPy*>(pPos)->value();
|
|
Base::Vector3d dir = static_cast<Base::VectorPy*>(pDir)->value();
|
|
try {
|
|
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementRevolve(
|
|
gp_Ax1(gp_Pnt(pos.x, pos.y, pos.z), gp_Dir(dir.x, dir.y, dir.z)),
|
|
Base::toRadians<double>(angle))));
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::check(PyObject *args)
|
|
{
|
|
PyObject* runBopCheck = Py_False;
|
|
if (!PyArg_ParseTuple(args, "|O!", &(PyBool_Type), &runBopCheck))
|
|
return nullptr;
|
|
|
|
if (!getTopoShapePtr()->getShape().IsNull()) {
|
|
std::stringstream str;
|
|
if (!getTopoShapePtr()->analyze(Base::asBoolean(runBopCheck), str)) {
|
|
PyErr_SetString(PyExc_ValueError, str.str().c_str());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
static PyObject *makeShape(const char *op,const TopoShape &shape, PyObject *args) {
|
|
double tol=0;
|
|
PyObject *pcObj;
|
|
if (!PyArg_ParseTuple(args, "O|d", &pcObj,&tol))
|
|
return 0;
|
|
PY_TRY {
|
|
std::vector<TopoShape> shapes;
|
|
shapes.push_back(shape);
|
|
getPyShapes(pcObj,shapes);
|
|
return Py::new_reference_to(shape2pyshape(TopoShape().makeElementBoolean(op,shapes,0,tol)));
|
|
} PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::fuse(PyObject *args)
|
|
{
|
|
return makeShape(Part::OpCodes::Fuse, *getTopoShapePtr(), args);
|
|
}
|
|
|
|
PyObject* TopoShapePy::multiFuse(PyObject *args)
|
|
{
|
|
return makeShape(Part::OpCodes::Fuse, *getTopoShapePtr(), args);
|
|
}
|
|
|
|
PyObject* TopoShapePy::oldFuse(PyObject *args)
|
|
{
|
|
PyObject *pcObj;
|
|
if (!PyArg_ParseTuple(args, "O!", &(TopoShapePy::Type), &pcObj))
|
|
return nullptr;
|
|
|
|
TopoDS_Shape shape = static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape();
|
|
try {
|
|
// Let's call algorithm computing a fuse operation:
|
|
TopoDS_Shape fusShape = this->getTopoShapePtr()->oldFuse(shape);
|
|
return new TopoShapePy(new TopoShape(fusShape));
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
catch (const std::exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.what());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::common(PyObject *args)
|
|
{
|
|
return makeShape(Part::OpCodes::Common, *getTopoShapePtr(), args);
|
|
}
|
|
|
|
PyObject* TopoShapePy::section(PyObject *args)
|
|
{
|
|
return makeShape(Part::OpCodes::Section, *getTopoShapePtr(), args);
|
|
}
|
|
|
|
PyObject* TopoShapePy::slice(PyObject *args)
|
|
{
|
|
PyObject *dir;
|
|
double d;
|
|
if (!PyArg_ParseTuple(args, "O!d", &(Base::VectorPy::Type), &dir, &d))
|
|
return nullptr;
|
|
|
|
Base::Vector3d vec = Py::Vector(dir, false).toVector();
|
|
|
|
try {
|
|
Py::List wires;
|
|
for (auto& w : getTopoShapePtr()->makeElementSlice(vec, d).getSubTopoShapes(TopAbs_WIRE)) {
|
|
wires.append(shape2pyshape(w));
|
|
}
|
|
return Py::new_reference_to(wires);
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
catch (const std::exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.what());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::slices(PyObject *args)
|
|
{
|
|
PyObject *dir, *dist;
|
|
if (!PyArg_ParseTuple(args, "O!O", &(Base::VectorPy::Type), &dir, &dist))
|
|
return nullptr;
|
|
|
|
try {
|
|
Base::Vector3d vec = Py::Vector(dir, false).toVector();
|
|
Py::Sequence list(dist);
|
|
std::vector<double> d;
|
|
d.reserve(list.size());
|
|
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it)
|
|
d.push_back((double)Py::Float(*it));
|
|
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementSlices(vec, d)));
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
catch (const std::exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.what());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::cut(PyObject *args)
|
|
{
|
|
return makeShape(Part::OpCodes::Cut, *getTopoShapePtr(), args);
|
|
}
|
|
|
|
PyObject* TopoShapePy::generalFuse(PyObject *args)
|
|
{
|
|
double tolerance = 0.0;
|
|
PyObject *pcObj;
|
|
if (!PyArg_ParseTuple(args, "O|d", &pcObj, &tolerance))
|
|
return nullptr;
|
|
|
|
std::vector<std::vector<TopoShape>> modifies;
|
|
std::vector<TopoShape> shapes;
|
|
shapes.push_back(*getTopoShapePtr());
|
|
try {
|
|
getPyShapes(pcObj, shapes);
|
|
TopoShape res;
|
|
res.makeElementGeneralFuse(shapes, modifies, tolerance);
|
|
Py::List mapPy;
|
|
for (auto& mod : modifies) {
|
|
Py::List shapesPy;
|
|
for (auto& sh : mod) {
|
|
shapesPy.append(shape2pyshape(sh));
|
|
}
|
|
mapPy.append(shapesPy);
|
|
}
|
|
Py::Tuple ret(2);
|
|
ret[0] = shape2pyshape(res);
|
|
ret[1] = mapPy;
|
|
return Py::new_reference_to(ret);
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::sewShape(PyObject *args)
|
|
{
|
|
double tolerance = 1.0e-06;
|
|
if (!PyArg_ParseTuple(args, "|d", &tolerance))
|
|
return nullptr;
|
|
|
|
try {
|
|
getTopoShapePtr()->sewShape();
|
|
Py_Return;
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::childShapes(PyObject *args)
|
|
{
|
|
PyObject* cumOri = Py_True;
|
|
PyObject* cumLoc = Py_True;
|
|
if (!PyArg_ParseTuple(args, "|O!O!", &(PyBool_Type), &cumOri, &(PyBool_Type), &cumLoc))
|
|
return nullptr;
|
|
|
|
TopoShape shape = *getTopoShapePtr();
|
|
if (!PyObject_IsTrue(cumOri)) {
|
|
shape.setShape(shape.getShape().Oriented(TopAbs_FORWARD), false);
|
|
}
|
|
if (!PyObject_IsTrue(cumLoc)) {
|
|
shape.setShape(shape.getShape().Located(TopLoc_Location()), false);
|
|
}
|
|
Py::List list;
|
|
PY_TRY
|
|
{
|
|
for (auto& s : shape.getSubTopoShapes()) {
|
|
list.append(shape2pyshape(s));
|
|
}
|
|
return Py::new_reference_to(list);
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
namespace Part {
|
|
// Containers to associate TopAbs_ShapeEnum values to each TopoShape*Py class
|
|
static const std::vector<std::pair<PyTypeObject*, TopAbs_ShapeEnum>> vecTypeShape = {
|
|
{&TopoShapeCompoundPy::Type, TopAbs_COMPOUND},
|
|
{&TopoShapeCompSolidPy::Type, TopAbs_COMPSOLID},
|
|
{&TopoShapeSolidPy::Type, TopAbs_SOLID},
|
|
{&TopoShapeShellPy::Type, TopAbs_SHELL},
|
|
{&TopoShapeFacePy::Type, TopAbs_FACE},
|
|
{&TopoShapeWirePy::Type, TopAbs_WIRE},
|
|
{&TopoShapeEdgePy::Type, TopAbs_EDGE},
|
|
{&TopoShapeVertexPy::Type, TopAbs_VERTEX},
|
|
{&TopoShapePy::Type, TopAbs_SHAPE}
|
|
};
|
|
|
|
static const std::map<PyTypeObject*, TopAbs_ShapeEnum> mapTypeShape(
|
|
vecTypeShape.begin(), vecTypeShape.end());
|
|
|
|
// Returns shape type of a Python type. Similar to TopAbs::ShapeTypeFromString.
|
|
// Returns TopAbs_SHAPE if pyType is not a subclass of any of the TopoShape*Py.
|
|
static TopAbs_ShapeEnum ShapeTypeFromPyType(PyTypeObject* pyType)
|
|
{
|
|
for (const auto & it : vecTypeShape) {
|
|
if (PyType_IsSubtype(pyType, it.first))
|
|
return it.second;
|
|
}
|
|
return TopAbs_SHAPE;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::ancestorsOfType(PyObject *args)
|
|
{
|
|
PyObject *pcObj;
|
|
PyObject *type;
|
|
if (!PyArg_ParseTuple(args, "O!O!", &(TopoShapePy::Type), &pcObj, &PyType_Type, &type))
|
|
return nullptr;
|
|
|
|
try {
|
|
const TopoDS_Shape& model = getTopoShapePtr()->getShape();
|
|
const TopoDS_Shape& shape = static_cast<TopoShapePy*>(pcObj)->
|
|
getTopoShapePtr()->getShape();
|
|
if (model.IsNull() || shape.IsNull()) {
|
|
PyErr_SetString(PyExc_ValueError, "Shape is null");
|
|
return nullptr;
|
|
}
|
|
|
|
PyTypeObject* pyType = reinterpret_cast<PyTypeObject*>(type);
|
|
TopAbs_ShapeEnum shapetype = ShapeTypeFromPyType(pyType);
|
|
if (!PyType_IsSubtype(pyType, &TopoShapePy::Type)) {
|
|
PyErr_SetString(PyExc_TypeError, "type must be a Shape subtype");
|
|
return nullptr;
|
|
}
|
|
|
|
TopTools_IndexedDataMapOfShapeListOfShape mapOfShapeShape;
|
|
TopExp::MapShapesAndAncestors(model, shape.ShapeType(), shapetype, mapOfShapeShape);
|
|
const TopTools_ListOfShape& ancestors = mapOfShapeShape.FindFromKey(shape);
|
|
|
|
Py::List list;
|
|
std::set<Standard_Integer> hashes;
|
|
TopTools_ListIteratorOfListOfShape it(ancestors);
|
|
for (; it.More(); it.Next()) {
|
|
// make sure to avoid duplicates
|
|
Standard_Integer code = ShapeMapHasher{}(it.Value());
|
|
if (hashes.find(code) == hashes.end()) {
|
|
list.append(shape2pyshape(it.Value()));
|
|
hashes.insert(code);
|
|
}
|
|
}
|
|
|
|
return Py::new_reference_to(list);
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::removeInternalWires(PyObject *args)
|
|
{
|
|
double minArea;
|
|
if (!PyArg_ParseTuple(args, "d",&minArea))
|
|
return nullptr;
|
|
|
|
try {
|
|
bool ok = getTopoShapePtr()->removeInternalWires(minArea);
|
|
PyObject* ret = ok ? Py_True : Py_False;
|
|
Py_INCREF(ret);
|
|
return ret;
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::mirror(PyObject *args)
|
|
{
|
|
PyObject *v1, *v2;
|
|
if (!PyArg_ParseTuple(args, "O!O!", &(Base::VectorPy::Type),&v1, &(Base::VectorPy::Type),&v2))
|
|
return nullptr;
|
|
|
|
Base::Vector3d base = Py::Vector(v1,false).toVector();
|
|
Base::Vector3d norm = Py::Vector(v2,false).toVector();
|
|
|
|
try {
|
|
gp_Ax2 ax2(gp_Pnt(base.x,base.y,base.z), gp_Dir(norm.x,norm.y,norm.z));
|
|
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementMirror(ax2)));
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::transformGeometry(PyObject *args)
|
|
{
|
|
PyObject *obj;
|
|
PyObject *cpy = Py_False;
|
|
if (!PyArg_ParseTuple(args, "O!|O!", &(Base::MatrixPy::Type), &obj, &PyBool_Type, &cpy))
|
|
return nullptr;
|
|
|
|
try {
|
|
Base::Matrix4D mat = static_cast<Base::MatrixPy*>(obj)->value();
|
|
TopoDS_Shape shape = this->getTopoShapePtr()->transformGShape(mat, Base::asBoolean(cpy));
|
|
return new TopoShapePy(new TopoShape(shape));
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::transformShape(PyObject *args)
|
|
{
|
|
PyObject *obj;
|
|
PyObject *copy = Py_False;
|
|
PyObject *checkScale = Py_False;
|
|
if (!PyArg_ParseTuple(args, "O!|O!O!", &(Base::MatrixPy::Type),&obj,&(PyBool_Type), ©, &(PyBool_Type), &checkScale))
|
|
return nullptr;
|
|
|
|
Base::Matrix4D mat = static_cast<Base::MatrixPy*>(obj)->value();
|
|
PY_TRY {
|
|
this->getTopoShapePtr()->transformShape(mat, Base::asBoolean(copy), Base::asBoolean(checkScale));
|
|
return IncRef();
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::transformed(PyObject *args, PyObject *keywds)
|
|
{
|
|
static const std::array<const char *, 5> kwlist{"matrix", "copy", "checkScale", "op", nullptr};
|
|
PyObject *pymat;
|
|
PyObject *copy = Py_False;
|
|
PyObject *checkScale = Py_False;
|
|
const char *op = nullptr;
|
|
if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, "O!|O!O!s", kwlist,
|
|
&Base::MatrixPy::Type, &pymat, &PyBool_Type, ©, &PyBool_Type,
|
|
&checkScale, &op)) {
|
|
return nullptr;
|
|
}
|
|
|
|
Base::Matrix4D mat = static_cast<Base::MatrixPy*>(pymat)->value();
|
|
(void)op;
|
|
PY_TRY {
|
|
TopoShape s(*getTopoShapePtr());
|
|
s.transformShape(mat,Base::asBoolean(copy), Base::asBoolean(checkScale));
|
|
return Py::new_reference_to(shape2pyshape(s));
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::translate(PyObject *args)
|
|
{
|
|
PyObject *obj;
|
|
if (!PyArg_ParseTuple(args, "O", &obj))
|
|
return nullptr;
|
|
|
|
Base::Vector3d vec;
|
|
if (PyObject_TypeCheck(obj, &(Base::VectorPy::Type))) {
|
|
vec = static_cast<Base::VectorPy*>(obj)->value();
|
|
}
|
|
else if (PyObject_TypeCheck(obj, &PyTuple_Type)) {
|
|
vec = Base::getVectorFromTuple<double>(obj);
|
|
}
|
|
else {
|
|
PyErr_SetString(PyExc_TypeError, "either vector or tuple expected");
|
|
return nullptr;
|
|
}
|
|
|
|
gp_Trsf mov;
|
|
mov.SetTranslation(gp_Vec(vec.x,vec.y,vec.z));
|
|
TopLoc_Location loc(mov);
|
|
TopoDS_Shape shape = getTopoShapePtr()->getShape();
|
|
shape.Move(loc);
|
|
getTopoShapePtr()->setShape(shape);
|
|
|
|
return IncRef();
|
|
}
|
|
|
|
PyObject* TopoShapePy::rotate(PyObject *args)
|
|
{
|
|
PyObject *obj1, *obj2;
|
|
double angle;
|
|
if (!PyArg_ParseTuple(args, "OOd", &obj1, &obj2, &angle))
|
|
return nullptr;
|
|
|
|
PY_TRY {
|
|
// Vector also supports sequence
|
|
Py::Sequence p1(obj1), p2(obj2);
|
|
// Convert into OCC representation
|
|
gp_Pnt pos = gp_Pnt((double)Py::Float(p1[0]),
|
|
(double)Py::Float(p1[1]),
|
|
(double)Py::Float(p1[2]));
|
|
gp_Dir dir = gp_Dir((double)Py::Float(p2[0]),
|
|
(double)Py::Float(p2[1]),
|
|
(double)Py::Float(p2[2]));
|
|
|
|
gp_Ax1 axis(pos, dir);
|
|
gp_Trsf mov;
|
|
mov.SetRotation(axis, Base::toRadians<double>(angle));
|
|
TopLoc_Location loc(mov);
|
|
TopoDS_Shape shape = getTopoShapePtr()->getShape();
|
|
shape.Move(loc);
|
|
getTopoShapePtr()->setShape(shape);
|
|
|
|
return IncRef();
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::scale(PyObject *args)
|
|
{
|
|
double factor;
|
|
PyObject* p=nullptr;
|
|
if (!PyArg_ParseTuple(args, "d|O!", &factor, &(Base::VectorPy::Type), &p))
|
|
return nullptr;
|
|
|
|
gp_Pnt pos(0,0,0);
|
|
if (p) {
|
|
Base::Vector3d pnt = static_cast<Base::VectorPy*>(p)->value();
|
|
pos.SetX(pnt.x);
|
|
pos.SetY(pnt.y);
|
|
pos.SetZ(pnt.z);
|
|
}
|
|
if (fabs(factor) < Precision::Confusion()) {
|
|
PyErr_SetString(PyExc_ValueError, "scale factor too small");
|
|
return nullptr;
|
|
}
|
|
|
|
PY_TRY {
|
|
const TopoDS_Shape& shape = getTopoShapePtr()->getShape();
|
|
if (!shape.IsNull()) {
|
|
gp_Trsf scl;
|
|
scl.SetScale(pos, factor);
|
|
BRepBuilderAPI_Transform BRepScale(scl);
|
|
bool bCopy = true;
|
|
BRepScale.Perform(shape, bCopy);
|
|
TopoShape copy(*getTopoShapePtr());
|
|
getTopoShapePtr()->makeElementShape(BRepScale, copy);
|
|
}
|
|
return IncRef();
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::translated(PyObject *args)
|
|
{
|
|
Py::Object pyobj(shape2pyshape(*getTopoShapePtr()));
|
|
return static_cast<TopoShapePy*>(pyobj.ptr())->translate(args);
|
|
}
|
|
|
|
PyObject* TopoShapePy::rotated(PyObject *args)
|
|
{
|
|
Py::Object pyobj(shape2pyshape(*getTopoShapePtr()));
|
|
return static_cast<TopoShapePy*>(pyobj.ptr())->rotate(args);
|
|
}
|
|
|
|
PyObject* TopoShapePy::scaled(PyObject *args)
|
|
{
|
|
Py::Object pyobj(shape2pyshape(*getTopoShapePtr()));
|
|
return static_cast<TopoShapePy*>(pyobj.ptr())->scale(args);
|
|
}
|
|
|
|
PyObject* TopoShapePy::makeFillet(PyObject *args)
|
|
{
|
|
// use two radii for all edges
|
|
double radius1, radius2;
|
|
PyObject *obj;
|
|
if (!PyArg_ParseTuple(args, "ddO", &radius1, &radius2, &obj)) {
|
|
PyErr_Clear();
|
|
if (!PyArg_ParseTuple(args, "dO", &radius1, &obj)) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"This method accepts:\n"
|
|
"-- one radius and a list of edges\n"
|
|
"-- two radii and a list of edges");
|
|
return 0;
|
|
}
|
|
radius2 = radius1;
|
|
}
|
|
PY_TRY
|
|
{
|
|
return Py::new_reference_to(shape2pyshape(
|
|
getTopoShapePtr()->makeElementFillet(getPyShapes(obj), radius1, radius2)));
|
|
}
|
|
PY_CATCH_OCC
|
|
PyErr_Clear();
|
|
// use one radius for all edges
|
|
double radius;
|
|
if (PyArg_ParseTuple(args, "dO", &radius, &obj)) {
|
|
try {
|
|
const TopoDS_Shape& shape = this->getTopoShapePtr()->getShape();
|
|
BRepFilletAPI_MakeFillet mkFillet(shape);
|
|
Py::Sequence list(obj);
|
|
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
|
if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) {
|
|
const TopoDS_Shape& edge = static_cast<TopoShapePy*>((*it).ptr())->getTopoShapePtr()->getShape();
|
|
if (edge.ShapeType() == TopAbs_EDGE) {
|
|
//Add edge to fillet algorithm
|
|
mkFillet.Add(radius, TopoDS::Edge(edge));
|
|
}
|
|
}
|
|
}
|
|
return new TopoShapePy(new TopoShape(mkFillet.Shape()));
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyErr_SetString(PyExc_TypeError, "This method accepts:\n"
|
|
"-- one radius and a list of edges\n"
|
|
"-- two radii and a list of edges");
|
|
return nullptr;
|
|
}
|
|
|
|
// TODO: Should this python interface support all three chamfer methods and not just two?
|
|
PyObject* TopoShapePy::makeChamfer(PyObject *args)
|
|
{
|
|
// use two radii for all edges
|
|
double radius1, radius2;
|
|
PyObject *obj;
|
|
if (!PyArg_ParseTuple(args, "ddO", &radius1, &radius2, &obj)) {
|
|
if (!PyArg_ParseTuple(args, "dO", &radius1, &obj)) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"This method accepts:\n"
|
|
"-- one radius and a list of edges\n"
|
|
"-- two radii and a list of edges");
|
|
return 0;
|
|
}
|
|
PyErr_Clear();
|
|
radius2 = radius1;
|
|
}
|
|
PY_TRY
|
|
{
|
|
return Py::new_reference_to(shape2pyshape(
|
|
getTopoShapePtr()->makeElementChamfer(getPyShapes(obj), Part::ChamferType::twoDistances, radius1, radius2)));
|
|
}
|
|
PY_CATCH_OCC
|
|
PyErr_Clear();
|
|
// use one radius for all edges
|
|
// TODO: Should this be using makeElementChamfer to support Toponaming fixes?
|
|
double radius;
|
|
if (PyArg_ParseTuple(args, "dO", &radius, &obj)) {
|
|
try {
|
|
const TopoDS_Shape& shape = this->getTopoShapePtr()->getShape();
|
|
BRepFilletAPI_MakeChamfer mkChamfer(shape);
|
|
TopTools_IndexedMapOfShape mapOfEdges;
|
|
TopTools_IndexedDataMapOfShapeListOfShape mapEdgeFace;
|
|
TopExp::MapShapesAndAncestors(shape, TopAbs_EDGE, TopAbs_FACE, mapEdgeFace);
|
|
TopExp::MapShapes(shape, TopAbs_EDGE, mapOfEdges);
|
|
Py::Sequence list(obj);
|
|
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
|
if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) {
|
|
const TopoDS_Shape& edge = static_cast<TopoShapePy*>((*it).ptr())->getTopoShapePtr()->getShape();
|
|
if (edge.ShapeType() == TopAbs_EDGE) {
|
|
//Add edge to fillet algorithm
|
|
const TopoDS_Face& face = TopoDS::Face(mapEdgeFace.FindFromKey(edge).First());
|
|
mkChamfer.Add(radius, radius, TopoDS::Edge(edge), face);
|
|
}
|
|
}
|
|
}
|
|
return new TopoShapePy(new TopoShape(mkChamfer.Shape()));
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyErr_SetString(PyExc_TypeError, "This method accepts:\n"
|
|
"-- one radius and a list of edges\n"
|
|
"-- two radii and a list of edges");
|
|
return nullptr;
|
|
}
|
|
|
|
PyObject* TopoShapePy::makeThickness(PyObject *args)
|
|
{
|
|
PyObject *obj;
|
|
double offset, tolerance;
|
|
PyObject* inter = Py_False;
|
|
PyObject* self_inter = Py_False;
|
|
short offsetMode = 0, join = 0;
|
|
if (!PyArg_ParseTuple(args, "Odd|O!O!hh", &obj, &offset, &tolerance,
|
|
&(PyBool_Type), &inter, &(PyBool_Type), &self_inter, &offsetMode, &join))
|
|
return nullptr;
|
|
|
|
try {
|
|
return Py::new_reference_to(shape2pyshape(
|
|
getTopoShapePtr()->makeElementThickSolid(getPyShapes(obj),
|
|
offset,
|
|
tolerance,
|
|
PyObject_IsTrue(inter) ? true : false,
|
|
PyObject_IsTrue(self_inter) ? true : false,
|
|
offsetMode,
|
|
static_cast<JoinType>(join))));
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::makeOffsetShape(PyObject *args, PyObject *keywds)
|
|
{
|
|
static const std::array<const char *, 8> kwlist{"offset", "tolerance", "inter", "self_inter", "offsetMode", "join",
|
|
"fill", nullptr};
|
|
double offset, tolerance;
|
|
PyObject *inter = Py_False;
|
|
PyObject *self_inter = Py_False;
|
|
PyObject *fill = Py_False;
|
|
short offsetMode = 0, join = 0;
|
|
if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, "dd|O!O!hhO!", kwlist, &offset, &tolerance,
|
|
&(PyBool_Type), &inter, &(PyBool_Type), &self_inter, &offsetMode, &join,
|
|
&(PyBool_Type), &fill)) {
|
|
return nullptr;
|
|
}
|
|
|
|
try {
|
|
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementOffset(
|
|
offset,
|
|
tolerance,
|
|
PyObject_IsTrue(inter) ? true : false,
|
|
PyObject_IsTrue(self_inter) ? true : false,
|
|
offsetMode,
|
|
static_cast<JoinType>(join),
|
|
PyObject_IsTrue(fill) ? FillType::fill : FillType::noFill)));
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::makeOffset2D(PyObject *args, PyObject *keywds)
|
|
{
|
|
static const std::array<const char *, 6> kwlist {"offset", "join", "fill", "openResult", "intersection", nullptr};
|
|
double offset;
|
|
PyObject* fill = Py_False;
|
|
PyObject* openResult = Py_False;
|
|
PyObject* inter = Py_False;
|
|
short join = 0;
|
|
if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, "d|hO!O!O!", kwlist, &offset, &join,
|
|
&(PyBool_Type), &fill, &(PyBool_Type), &openResult, &(PyBool_Type),
|
|
&inter)) {
|
|
return nullptr;
|
|
}
|
|
|
|
try {
|
|
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementOffset2D(
|
|
offset,
|
|
static_cast<JoinType>(join),
|
|
PyObject_IsTrue(fill) ? FillType::fill : FillType::noFill,
|
|
PyObject_IsTrue(openResult) ? OpenResult::allowOpenResult : OpenResult::noOpenResult,
|
|
PyObject_IsTrue(inter) ? true : false)));
|
|
}
|
|
PY_CATCH_OCC;
|
|
}
|
|
|
|
PyObject* TopoShapePy::reverse(PyObject *args)
|
|
{
|
|
if (!PyArg_ParseTuple(args, ""))
|
|
return nullptr;
|
|
|
|
TopoDS_Shape shape = getTopoShapePtr()->getShape();
|
|
shape.Reverse();
|
|
getTopoShapePtr()->setShape(shape);
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* TopoShapePy::reversed(PyObject *args)
|
|
{
|
|
if (!PyArg_ParseTuple(args, ""))
|
|
return nullptr;
|
|
|
|
TopoDS_Shape shape = getTopoShapePtr()->getShape();
|
|
shape = shape.Reversed();
|
|
|
|
PyTypeObject* type = this->GetType();
|
|
PyObject* cpy = nullptr;
|
|
|
|
// let the type object decide
|
|
if (type->tp_new)
|
|
cpy = type->tp_new(type, this, nullptr);
|
|
if (!cpy) {
|
|
PyErr_SetString(PyExc_TypeError, "failed to create copy of shape");
|
|
return nullptr;
|
|
}
|
|
|
|
if (!shape.IsNull()) {
|
|
static_cast<TopoShapePy*>(cpy)->getTopoShapePtr()->setShape(shape);
|
|
}
|
|
return cpy;
|
|
}
|
|
|
|
PyObject* TopoShapePy::complement(PyObject *args)
|
|
{
|
|
if (!PyArg_ParseTuple(args, ""))
|
|
return nullptr;
|
|
|
|
TopoDS_Shape shape = getTopoShapePtr()->getShape();
|
|
shape.Complement();
|
|
getTopoShapePtr()->setShape(shape);
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* TopoShapePy::nullify(PyObject *args)
|
|
{
|
|
if (!PyArg_ParseTuple(args, ""))
|
|
return nullptr;
|
|
|
|
TopoDS_Shape shape = getTopoShapePtr()->getShape();
|
|
shape.Nullify();
|
|
getTopoShapePtr()->setShape(shape);
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* TopoShapePy::isNull(PyObject *args)
|
|
{
|
|
if (!PyArg_ParseTuple(args, ""))
|
|
return nullptr;
|
|
|
|
bool null = getTopoShapePtr()->isNull();
|
|
return Py_BuildValue("O", (null ? Py_True : Py_False));
|
|
}
|
|
|
|
PyObject* TopoShapePy::isClosed(PyObject *args)
|
|
{
|
|
if (!PyArg_ParseTuple(args, ""))
|
|
return nullptr;
|
|
|
|
try {
|
|
if (getTopoShapePtr()->getShape().IsNull())
|
|
Standard_Failure::Raise("Cannot determine the 'Closed'' flag of an empty shape");
|
|
return Py_BuildValue("O", (getTopoShapePtr()->isClosed() ? Py_True : Py_False));
|
|
}
|
|
catch (...) {
|
|
PyErr_SetString(PyExc_RuntimeError, "check failed, shape may be empty");
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::isEqual(PyObject *args)
|
|
{
|
|
PyObject *pcObj;
|
|
if (!PyArg_ParseTuple(args, "O!", &(TopoShapePy::Type), &pcObj))
|
|
return nullptr;
|
|
|
|
TopoDS_Shape shape = static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape();
|
|
Standard_Boolean test = (getTopoShapePtr()->getShape().IsEqual(shape));
|
|
|
|
return Py_BuildValue("O", (test ? Py_True : Py_False));
|
|
}
|
|
|
|
PyObject* TopoShapePy::isSame(PyObject *args)
|
|
{
|
|
PyObject *pcObj;
|
|
if (!PyArg_ParseTuple(args, "O!", &(TopoShapePy::Type), &pcObj))
|
|
return nullptr;
|
|
|
|
TopoDS_Shape shape = static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape();
|
|
Standard_Boolean test = getTopoShapePtr()->getShape().IsSame(shape);
|
|
|
|
return Py_BuildValue("O", (test ? Py_True : Py_False));
|
|
}
|
|
|
|
PyObject* TopoShapePy::isPartner(PyObject *args)
|
|
{
|
|
PyObject *pcObj;
|
|
if (!PyArg_ParseTuple(args, "O!", &(TopoShapePy::Type), &pcObj))
|
|
return nullptr;
|
|
|
|
TopoDS_Shape shape = static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape();
|
|
Standard_Boolean test = getTopoShapePtr()->getShape().IsPartner(shape);
|
|
|
|
return Py_BuildValue("O", (test ? Py_True : Py_False));
|
|
}
|
|
|
|
PyObject* TopoShapePy::isValid(PyObject *args)
|
|
{
|
|
if (!PyArg_ParseTuple(args, ""))
|
|
return nullptr;
|
|
|
|
PY_TRY {
|
|
return Py_BuildValue("O", (getTopoShapePtr()->isValid() ? Py_True : Py_False));
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::isCoplanar(PyObject *args)
|
|
{
|
|
PyObject *pyObj;
|
|
double tol = -1;
|
|
if (!PyArg_ParseTuple(args, "O!|d", &TopoShapePy::Type, &pyObj, &tol))
|
|
return nullptr;
|
|
|
|
PY_TRY {
|
|
return Py::new_reference_to(Py::Boolean(getTopoShapePtr()->isCoplanar(
|
|
*static_cast<TopoShapePy*>(pyObj)->getTopoShapePtr(),tol)));
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::isInfinite(PyObject *args)
|
|
{
|
|
if (!PyArg_ParseTuple(args, ""))
|
|
return nullptr;
|
|
|
|
PY_TRY {
|
|
return Py::new_reference_to(Py::Boolean(getTopoShapePtr()->isInfinite()));
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::findPlane(PyObject *args)
|
|
{
|
|
double tol = -1;
|
|
if (!PyArg_ParseTuple(args, "|d", &tol))
|
|
return nullptr;
|
|
|
|
PY_TRY {
|
|
gp_Pln pln;
|
|
if (getTopoShapePtr()->findPlane(pln, tol))
|
|
return new PlanePy(new GeomPlane(new Geom_Plane(pln)));
|
|
Py_Return;
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::fix(PyObject *args)
|
|
{
|
|
double prec, mintol, maxtol;
|
|
if (!PyArg_ParseTuple(args, "ddd", &prec, &mintol, &maxtol))
|
|
return nullptr;
|
|
|
|
try {
|
|
return Py_BuildValue("O", (getTopoShapePtr()->fix(prec, mintol, maxtol) ? Py_True : Py_False));
|
|
}
|
|
catch (...) {
|
|
PyErr_SetString(PyExc_RuntimeError, "check failed, shape may be empty");
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::hashCode(PyObject *args)
|
|
{
|
|
int upper = IntegerLast();
|
|
if (!PyArg_ParseTuple(args, "|i",&upper))
|
|
return nullptr;
|
|
|
|
int hc = ShapeMapHasher{}(getTopoShapePtr()->getShape());
|
|
return Py_BuildValue("i", hc);
|
|
}
|
|
|
|
PyObject* TopoShapePy::tessellate(PyObject *args)
|
|
{
|
|
double tolerance;
|
|
PyObject* ok = Py_False;
|
|
if (!PyArg_ParseTuple(args, "d|O!", &tolerance, &PyBool_Type, &ok))
|
|
return nullptr;
|
|
|
|
try {
|
|
std::vector<Base::Vector3d> Points;
|
|
std::vector<Data::ComplexGeoData::Facet> Facets;
|
|
if (Base::asBoolean(ok))
|
|
BRepTools::Clean(getTopoShapePtr()->getShape());
|
|
getTopoShapePtr()->getFaces(Points, Facets,tolerance);
|
|
Py::Tuple tuple(2);
|
|
Py::List vertex;
|
|
for (const auto & Point : Points)
|
|
vertex.append(Py::asObject(new Base::VectorPy(Point)));
|
|
tuple.setItem(0, vertex);
|
|
Py::List facet;
|
|
for (const auto& it : Facets) {
|
|
Py::Tuple f(3);
|
|
f.setItem(0,Py::Long((long)it.I1));
|
|
f.setItem(1,Py::Long((long)it.I2));
|
|
f.setItem(2,Py::Long((long)it.I3));
|
|
facet.append(f);
|
|
}
|
|
tuple.setItem(1, facet);
|
|
return Py::new_reference_to(tuple);
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::project(PyObject *args)
|
|
{
|
|
PyObject *obj;
|
|
|
|
BRepAlgo_NormalProjection algo;
|
|
algo.Init(this->getTopoShapePtr()->getShape());
|
|
if (!PyArg_ParseTuple(args, "O", &obj))
|
|
return nullptr;
|
|
|
|
try {
|
|
Py::Sequence list(obj);
|
|
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
|
if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) {
|
|
const TopoDS_Shape& shape = static_cast<TopoShapePy*>((*it).ptr())->getTopoShapePtr()->getShape();
|
|
algo.Add(shape);
|
|
}
|
|
}
|
|
|
|
algo.Compute3d(Standard_True);
|
|
algo.SetLimit(Standard_True);
|
|
algo.SetParams(1.e-6, 1.e-6, GeomAbs_C1, 14, 10000);
|
|
//algo.SetDefaultParams();
|
|
algo.Build();
|
|
return new TopoShapePy(new TopoShape(algo.Projection()));
|
|
}
|
|
catch (Standard_Failure&) {
|
|
PyErr_SetString(PartExceptionOCCError, "Failed to project shape");
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::makeParallelProjection(PyObject *args)
|
|
{
|
|
PyObject *pShape, *pDir;
|
|
if (!PyArg_ParseTuple(args, "O!O!", &(Part::TopoShapePy::Type), &pShape, &Base::VectorPy::Type, &pDir))
|
|
return nullptr;
|
|
|
|
try {
|
|
const TopoDS_Shape& shape = this->getTopoShapePtr()->getShape();
|
|
const TopoDS_Shape& wire = static_cast<TopoShapePy*>(pShape)->getTopoShapePtr()->getShape();
|
|
Base::Vector3d vec = Py::Vector(pDir,false).toVector();
|
|
BRepProj_Projection proj(wire, shape, gp_Dir(vec.x,vec.y,vec.z));
|
|
TopoDS_Shape projected = proj.Shape();
|
|
return new TopoShapePy(new TopoShape(projected));
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::makePerspectiveProjection(PyObject *args)
|
|
{
|
|
PyObject *pShape, *pDir;
|
|
if (!PyArg_ParseTuple(args, "O!O!", &(Part::TopoShapePy::Type), &pShape, &Base::VectorPy::Type, &pDir))
|
|
return nullptr;
|
|
|
|
try {
|
|
const TopoDS_Shape& shape = this->getTopoShapePtr()->getShape();
|
|
const TopoDS_Shape& wire = static_cast<TopoShapePy*>(pShape)->getTopoShapePtr()->getShape();
|
|
Base::Vector3d vec = Py::Vector(pDir,false).toVector();
|
|
BRepProj_Projection proj(wire, shape, gp_Pnt(vec.x,vec.y,vec.z));
|
|
TopoDS_Shape projected = proj.Shape();
|
|
return new TopoShapePy(new TopoShape(projected));
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
from pivy import coin
|
|
|
|
rot=Gui.ActiveDocument.ActiveView.getCameraOrientation()
|
|
vdir=App.Vector(0,0,-1)
|
|
vdir=rot.multVec(vdir)
|
|
udir=App.Vector(0,1,0)
|
|
udir=rot.multVec(udir)
|
|
|
|
pos=Gui.ActiveDocument.ActiveView.getCameraNode().position.getValue().getValue()
|
|
pos=App.Vector(*pos)
|
|
|
|
shape=App.ActiveDocument.ActiveObject.Shape
|
|
reflect=shape.reflectLines(ViewDir=vdir, ViewPos=pos, UpDir=udir, EdgeType="Sharp", Visible=True, OnShape=False)
|
|
Part.show(reflect)
|
|
*/
|
|
PyObject* TopoShapePy::reflectLines(PyObject *args, PyObject *kwds)
|
|
{
|
|
static const std::array<const char *, 7> kwlist{"ViewDir", "ViewPos", "UpDir", "EdgeType", "Visible", "OnShape",
|
|
nullptr};
|
|
|
|
const char* type="OutLine";
|
|
PyObject* vis = Py_True;
|
|
PyObject* in3d = Py_False;
|
|
PyObject* pPos = nullptr;
|
|
PyObject* pUp = nullptr;
|
|
PyObject *pView;
|
|
if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "O!|O!O!sO!O!", kwlist,
|
|
&Base::VectorPy::Type, &pView, &Base::VectorPy::Type, &pPos,
|
|
&Base::VectorPy::Type,
|
|
&pUp, &type, &PyBool_Type, &vis, &PyBool_Type, &in3d)) {
|
|
return nullptr;
|
|
}
|
|
|
|
try {
|
|
HLRBRep_TypeOfResultingEdge t;
|
|
std::string str = type;
|
|
if (str == "IsoLine")
|
|
t = HLRBRep_IsoLine;
|
|
else if (str == "Rg1Line")
|
|
t = HLRBRep_Rg1Line;
|
|
else if (str == "RgNLine")
|
|
t = HLRBRep_RgNLine;
|
|
else if (str == "Sharp")
|
|
t = HLRBRep_Sharp;
|
|
else
|
|
t = HLRBRep_OutLine;
|
|
|
|
Base::Vector3d p(0.0, 0.0, 0.0);
|
|
if (pPos)
|
|
p = Py::Vector(pPos,false).toVector();
|
|
Base::Vector3d u(0.0, 1.0, 0.0);
|
|
if (pUp)
|
|
u = Py::Vector(pUp,false).toVector();
|
|
|
|
Base::Vector3d v = Py::Vector(pView,false).toVector();
|
|
const TopoDS_Shape& shape = this->getTopoShapePtr()->getShape();
|
|
HLRAppli_ReflectLines reflect(shape);
|
|
reflect.SetAxes(v.x, v.y, v.z, p.x, p.y, p.z, u.x, u.y, u.z);
|
|
reflect.Perform();
|
|
TopoDS_Shape lines = reflect.GetCompoundOf3dEdges(t, Base::asBoolean(vis), Base::asBoolean(in3d));
|
|
return new TopoShapePy(new TopoShape(lines));
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::makeShapeFromMesh(PyObject *args)
|
|
{
|
|
PyObject *tup;
|
|
double tolerance = 1.0e-06;
|
|
PyObject* sewShape = Py_True;
|
|
if (!PyArg_ParseTuple(args, "O!|dO!",&PyTuple_Type, &tup, &tolerance, &PyBool_Type, &sewShape))
|
|
return nullptr;
|
|
|
|
try {
|
|
Py::Tuple tuple(tup);
|
|
Py::Sequence vertex(tuple[0]);
|
|
Py::Sequence facets(tuple[1]);
|
|
|
|
std::vector<Base::Vector3d> Points;
|
|
for (Py::Sequence::iterator it = vertex.begin(); it != vertex.end(); ++it) {
|
|
Py::Vector vec(*it);
|
|
Points.push_back(vec.toVector());
|
|
}
|
|
std::vector<Data::ComplexGeoData::Facet> Facets;
|
|
for (Py::Sequence::iterator it = facets.begin(); it != facets.end(); ++it) {
|
|
Data::ComplexGeoData::Facet face;
|
|
Py::Tuple f(*it);
|
|
face.I1 = (int)Py::Long(f[0]);
|
|
face.I2 = (int)Py::Long(f[1]);
|
|
face.I3 = (int)Py::Long(f[2]);
|
|
Facets.push_back(face);
|
|
}
|
|
|
|
getTopoShapePtr()->setFaces(Points, Facets, tolerance);
|
|
if (Base::asBoolean(sewShape))
|
|
getTopoShapePtr()->sewShape(tolerance);
|
|
|
|
Py_Return;
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::makeEvolved(PyObject *args, PyObject *kwds)
|
|
{
|
|
PyObject* Profile;
|
|
PyObject* AxeProf = Py_True;
|
|
PyObject* Solid = Py_False;
|
|
PyObject* ProfOnSpine = Py_False;
|
|
auto JoinType = JoinType::arc;
|
|
double Tolerance = 0.0000001;
|
|
|
|
static const std::array<const char*, 7> kwds_evolve{"Profile", "Join", "AxeProf", "Solid", "ProfOnSpine", "Tolerance", nullptr};
|
|
if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "O!|iO!O!O!d", kwds_evolve,
|
|
&TopoShapePy::Type, &Profile, &JoinType,
|
|
&PyBool_Type, &AxeProf, &PyBool_Type, &Solid,
|
|
&PyBool_Type, &ProfOnSpine, &Tolerance)) {
|
|
return nullptr;
|
|
}
|
|
try {
|
|
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementEvolve(
|
|
*static_cast<TopoShapePy*>(Profile)->getTopoShapePtr(), JoinType,
|
|
PyObject_IsTrue(AxeProf) ? CoordinateSystem::global : CoordinateSystem::relativeToSpine,
|
|
PyObject_IsTrue(Solid) ? MakeSolid::makeSolid : MakeSolid::noSolid,
|
|
PyObject_IsTrue(ProfOnSpine) ? Spine::on : Spine::notOn,
|
|
Tolerance)));
|
|
} PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::makeWires(PyObject *args) {
|
|
const char *op = nullptr;
|
|
if (!PyArg_ParseTuple(args, "s", &op))
|
|
return nullptr;
|
|
|
|
PY_TRY {
|
|
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeWires(op)));
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::toNurbs(PyObject *args)
|
|
{
|
|
if (!PyArg_ParseTuple(args, ""))
|
|
return nullptr;
|
|
|
|
try {
|
|
// Convert into nurbs
|
|
TopoDS_Shape nurbs = this->getTopoShapePtr()->toNurbs();
|
|
return new TopoShapePy(new TopoShape(nurbs));
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::isInside(PyObject *args)
|
|
{
|
|
PyObject *point;
|
|
double tolerance;
|
|
PyObject* checkFace = Py_False;
|
|
TopAbs_State stateIn = TopAbs_IN;
|
|
if (!PyArg_ParseTuple(args, "O!dO!", &(Base::VectorPy::Type), &point, &tolerance, &PyBool_Type, &checkFace))
|
|
return nullptr;
|
|
|
|
try {
|
|
TopoDS_Shape shape = getTopoShapePtr()->getShape();
|
|
if (shape.IsNull()) {
|
|
PyErr_SetString(PartExceptionOCCError, "Cannot handle null shape");
|
|
return nullptr;
|
|
}
|
|
|
|
Base::Vector3d pnt = static_cast<Base::VectorPy*>(point)->value();
|
|
gp_Pnt vertex = gp_Pnt(pnt.x,pnt.y,pnt.z);
|
|
if (shape.ShapeType() == TopAbs_VERTEX ||
|
|
shape.ShapeType() == TopAbs_EDGE ||
|
|
shape.ShapeType() == TopAbs_WIRE ||
|
|
shape.ShapeType() == TopAbs_FACE) {
|
|
|
|
BRepBuilderAPI_MakeVertex mkVertex(vertex);
|
|
BRepExtrema_DistShapeShape extss;
|
|
extss.LoadS1(mkVertex.Vertex());
|
|
extss.LoadS2(shape);
|
|
if (!extss.Perform()) {
|
|
PyErr_SetString(PartExceptionOCCError, "Failed to determine distance to shape");
|
|
return nullptr;
|
|
}
|
|
Standard_Boolean test = (extss.Value() <= tolerance);
|
|
return Py_BuildValue("O", (test ? Py_True : Py_False));
|
|
}
|
|
else {
|
|
BRepClass3d_SolidClassifier solidClassifier(shape);
|
|
solidClassifier.Perform(vertex, tolerance);
|
|
Standard_Boolean test = (solidClassifier.State() == stateIn);
|
|
|
|
if (Base::asBoolean(checkFace) && solidClassifier.IsOnAFace())
|
|
test = Standard_True;
|
|
return Py_BuildValue("O", (test ? Py_True : Py_False));
|
|
}
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
catch (const std::exception& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.what());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::removeSplitter(PyObject *args)
|
|
{
|
|
if (!PyArg_ParseTuple(args, ""))
|
|
return nullptr;
|
|
|
|
try {
|
|
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementRefine()));
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::getElement(PyObject *args)
|
|
{
|
|
char* input;
|
|
PyObject* silent = Py_False;
|
|
if (!PyArg_ParseTuple(args, "s|O", &input, &silent)) {
|
|
return nullptr;
|
|
}
|
|
try {
|
|
PyObject* res = getTopoShapePtr()->getPySubShape(input, PyObject_IsTrue(silent));
|
|
if (!res) {
|
|
Py_Return;
|
|
}
|
|
return res;
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::countElement(PyObject *args)
|
|
{
|
|
char* input;
|
|
if (!PyArg_ParseTuple(args, "s", &input))
|
|
return nullptr;
|
|
|
|
PY_TRY {
|
|
return Py::new_reference_to(Py::Long((long)getTopoShapePtr()->countSubShapes(input)));
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::getTolerance(PyObject *args)
|
|
{
|
|
int mode;
|
|
PyObject* type = reinterpret_cast<PyObject*>(&TopoShapePy::Type);
|
|
if (!PyArg_ParseTuple(args, "i|O!", &mode, &PyType_Type, &type))
|
|
return nullptr;
|
|
|
|
try {
|
|
TopoDS_Shape shape = this->getTopoShapePtr()->getShape();
|
|
PyTypeObject* pyType = reinterpret_cast<PyTypeObject*>(type);
|
|
TopAbs_ShapeEnum shapetype = ShapeTypeFromPyType(pyType);
|
|
if (!PyType_IsSubtype(pyType, &TopoShapePy::Type) ||
|
|
(shapetype != TopAbs_SHAPE && shapetype != TopAbs_VERTEX &&
|
|
shapetype != TopAbs_EDGE && shapetype != TopAbs_FACE && shapetype != TopAbs_SHELL)) {
|
|
PyErr_SetString(PyExc_TypeError, "shape type must be Shape, Vertex, Edge, Face or Shell");
|
|
return nullptr;
|
|
}
|
|
|
|
ShapeAnalysis_ShapeTolerance analysis;
|
|
double tolerance = analysis.Tolerance(shape, mode, shapetype);
|
|
return PyFloat_FromDouble(tolerance);
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::overTolerance(PyObject *args)
|
|
{
|
|
double value;
|
|
PyObject* type = reinterpret_cast<PyObject*>(&TopoShapePy::Type);
|
|
if (!PyArg_ParseTuple(args, "d|O!", &value, &PyType_Type, &type))
|
|
return nullptr;
|
|
|
|
try {
|
|
TopoDS_Shape shape = this->getTopoShapePtr()->getShape();
|
|
PyTypeObject* pyType = reinterpret_cast<PyTypeObject*>(type);
|
|
TopAbs_ShapeEnum shapetype = ShapeTypeFromPyType(pyType);
|
|
if (!PyType_IsSubtype(pyType, &TopoShapePy::Type) ||
|
|
(shapetype != TopAbs_SHAPE && shapetype != TopAbs_VERTEX &&
|
|
shapetype != TopAbs_EDGE && shapetype != TopAbs_FACE && shapetype != TopAbs_SHELL)) {
|
|
PyErr_SetString(PyExc_TypeError, "shape type must be Shape, Vertex, Edge, Face or Shell");
|
|
return nullptr;
|
|
}
|
|
|
|
ShapeAnalysis_ShapeTolerance analysis;
|
|
Handle(TopTools_HSequenceOfShape) seq = analysis.OverTolerance(shape, value, shapetype);
|
|
Py::Tuple tuple(seq->Length());
|
|
std::size_t index=0;
|
|
for (int i=1; i <= seq->Length(); i++) {
|
|
TopoDS_Shape item = seq->Value(i);
|
|
tuple.setItem(index++, shape2pyshape(item));
|
|
}
|
|
return Py::new_reference_to(tuple);
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::inTolerance(PyObject *args)
|
|
{
|
|
double valmin;
|
|
double valmax;
|
|
PyObject* type = reinterpret_cast<PyObject*>(&TopoShapePy::Type);
|
|
if (!PyArg_ParseTuple(args, "dd|O!", &valmin, &valmax, &PyType_Type, &type))
|
|
return nullptr;
|
|
|
|
try {
|
|
TopoDS_Shape shape = this->getTopoShapePtr()->getShape();
|
|
PyTypeObject* pyType = reinterpret_cast<PyTypeObject*>(type);
|
|
TopAbs_ShapeEnum shapetype = ShapeTypeFromPyType(pyType);
|
|
if (!PyType_IsSubtype(pyType, &TopoShapePy::Type) ||
|
|
(shapetype != TopAbs_SHAPE && shapetype != TopAbs_VERTEX &&
|
|
shapetype != TopAbs_EDGE && shapetype != TopAbs_FACE && shapetype != TopAbs_SHELL)) {
|
|
PyErr_SetString(PyExc_TypeError, "shape type must be Shape, Vertex, Edge, Face or Shell");
|
|
return nullptr;
|
|
}
|
|
|
|
ShapeAnalysis_ShapeTolerance analysis;
|
|
Handle(TopTools_HSequenceOfShape) seq = analysis.InTolerance(shape, valmin, valmax, shapetype);
|
|
Py::Tuple tuple(seq->Length());
|
|
std::size_t index=0;
|
|
for (int i=1; i <= seq->Length(); i++) {
|
|
TopoDS_Shape item = seq->Value(i);
|
|
tuple.setItem(index++, shape2pyshape(item));
|
|
}
|
|
return Py::new_reference_to(tuple);
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::globalTolerance(PyObject *args)
|
|
{
|
|
int mode;
|
|
if (!PyArg_ParseTuple(args, "i", &mode))
|
|
return nullptr;
|
|
|
|
try {
|
|
TopoDS_Shape shape = this->getTopoShapePtr()->getShape();
|
|
ShapeAnalysis_ShapeTolerance analysis;
|
|
analysis.Tolerance(shape, mode);
|
|
double tolerance = analysis.GlobalTolerance(mode);
|
|
|
|
return PyFloat_FromDouble(tolerance);
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::fixTolerance(PyObject *args)
|
|
{
|
|
double value;
|
|
PyObject* type = reinterpret_cast<PyObject*>(&TopoShapePy::Type);
|
|
if (!PyArg_ParseTuple(args, "d|O!", &value, &PyType_Type, &type))
|
|
return nullptr;
|
|
|
|
try {
|
|
TopoDS_Shape shape = this->getTopoShapePtr()->getShape();
|
|
PyTypeObject* pyType = reinterpret_cast<PyTypeObject*>(type);
|
|
TopAbs_ShapeEnum shapetype = ShapeTypeFromPyType(pyType);
|
|
if (!PyType_IsSubtype(pyType, &TopoShapePy::Type)) {
|
|
PyErr_SetString(PyExc_TypeError, "type must be a Shape subtype");
|
|
return nullptr;
|
|
}
|
|
|
|
ShapeFix_ShapeTolerance fix;
|
|
fix.SetTolerance(shape, value, shapetype);
|
|
Py_Return;
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::limitTolerance(PyObject *args)
|
|
{
|
|
double tmin;
|
|
double tmax=0;
|
|
PyObject* type = reinterpret_cast<PyObject*>(&TopoShapePy::Type);
|
|
if (!PyArg_ParseTuple(args, "d|dO!", &tmin, &tmax, &PyType_Type, &type))
|
|
return nullptr;
|
|
|
|
try {
|
|
TopoDS_Shape shape = this->getTopoShapePtr()->getShape();
|
|
PyTypeObject* pyType = reinterpret_cast<PyTypeObject*>(type);
|
|
TopAbs_ShapeEnum shapetype = ShapeTypeFromPyType(pyType);
|
|
if (!PyType_IsSubtype(pyType, &TopoShapePy::Type)) {
|
|
PyErr_SetString(PyExc_TypeError, "type must be a Shape subtype");
|
|
return nullptr;
|
|
}
|
|
|
|
ShapeFix_ShapeTolerance fix;
|
|
Standard_Boolean ok = fix.LimitTolerance(shape, tmin, tmax, shapetype);
|
|
return PyBool_FromLong(ok ? 1 : 0);
|
|
}
|
|
catch (Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* _getSupportIndex(const char* suppStr, TopoShape* ts, TopoDS_Shape suppShape) {
|
|
std::stringstream ss;
|
|
TopoDS_Shape subShape;
|
|
|
|
unsigned long nSubShapes = ts->countSubShapes(suppStr);
|
|
long supportIndex = -1;
|
|
for (unsigned long j=1; j<=nSubShapes; j++){
|
|
ss.str("");
|
|
ss << suppStr << j;
|
|
subShape = ts->getSubShape(ss.str().c_str());
|
|
if (subShape.IsEqual(suppShape)) {
|
|
supportIndex = j-1;
|
|
break;
|
|
}
|
|
}
|
|
return PyLong_FromLong(supportIndex);
|
|
}
|
|
|
|
PyObject* TopoShapePy::proximity(PyObject *args)
|
|
{
|
|
using BRepExtrema_OverlappedSubShapes = BRepExtrema_MapOfIntegerPackedMapOfInteger;
|
|
|
|
PyObject* ps2;
|
|
Standard_Real tol = Precision::Confusion();
|
|
if (!PyArg_ParseTuple(args, "O!|d",&(TopoShapePy::Type), &ps2, &tol))
|
|
return nullptr;
|
|
|
|
const TopoDS_Shape& s1 = getTopoShapePtr()->getShape();
|
|
const TopoDS_Shape& s2 = static_cast<Part::TopoShapePy*>(ps2)->getTopoShapePtr()->getShape();
|
|
if (s1.IsNull()) {
|
|
PyErr_SetString(PyExc_ValueError, "proximity: Shape object is invalid");
|
|
return nullptr;
|
|
}
|
|
if (s2.IsNull()) {
|
|
PyErr_SetString(PyExc_ValueError, "proximity: Shape parameter is invalid");
|
|
return nullptr;
|
|
}
|
|
|
|
BRepExtrema_ShapeProximity proximity;
|
|
proximity.LoadShape1 (s1);
|
|
proximity.LoadShape2 (s2);
|
|
if (tol > 0.0) {
|
|
proximity.SetTolerance (tol);
|
|
}
|
|
|
|
proximity.Perform();
|
|
if (!proximity.IsDone()) {
|
|
PyErr_SetString(PartExceptionOCCError, "BRepExtrema_ShapeProximity failed, make sure the shapes are tessellated");
|
|
return nullptr;
|
|
}
|
|
|
|
Py::List overlappssindex1;
|
|
Py::List overlappssindex2;
|
|
|
|
for (BRepExtrema_OverlappedSubShapes::Iterator anIt1 (proximity.OverlapSubShapes1()); anIt1.More(); anIt1.Next()) {
|
|
overlappssindex1.append(Py::Long(anIt1.Key() + 1));
|
|
}
|
|
for (BRepExtrema_OverlappedSubShapes::Iterator anIt2 (proximity.OverlapSubShapes2()); anIt2.More(); anIt2.Next()) {
|
|
overlappssindex2.append(Py::Long(anIt2.Key() + 1));
|
|
}
|
|
|
|
Py::Tuple tuple(2);
|
|
tuple.setItem(0, overlappssindex1);
|
|
tuple.setItem(1, overlappssindex2);
|
|
return Py::new_reference_to(tuple); //face indexes
|
|
|
|
}
|
|
|
|
PyObject* TopoShapePy::distToShape(PyObject *args)
|
|
{
|
|
PyObject* ps2;
|
|
gp_Pnt P1, P2;
|
|
BRepExtrema_SupportType supportType1, supportType2;
|
|
TopoDS_Shape suppS1, suppS2;
|
|
Standard_Real minDist = -1, t1, t2, u1, v1, u2, v2;
|
|
Standard_Real tol = Precision::Confusion();
|
|
|
|
if (!PyArg_ParseTuple(args, "O!|d",&(TopoShapePy::Type), &ps2, &tol))
|
|
return nullptr;
|
|
|
|
const TopoDS_Shape& s1 = getTopoShapePtr()->getShape();
|
|
TopoShape* ts1 = getTopoShapePtr();
|
|
const TopoDS_Shape& s2 = static_cast<Part::TopoShapePy*>(ps2)->getTopoShapePtr()->getShape();
|
|
TopoShape* ts2 = static_cast<Part::TopoShapePy*>(ps2)->getTopoShapePtr();
|
|
|
|
if (s2.IsNull()) {
|
|
PyErr_SetString(PyExc_TypeError, "distToShape: Shape parameter is invalid");
|
|
return nullptr;
|
|
}
|
|
BRepExtrema_DistShapeShape extss;
|
|
extss.SetDeflection(tol);
|
|
#if OCC_VERSION_HEX >= 0x070600
|
|
extss.SetMultiThread(true);
|
|
#endif
|
|
extss.LoadS1(s1);
|
|
extss.LoadS2(s2);
|
|
try {
|
|
extss.Perform();
|
|
}
|
|
catch (const Standard_Failure& e) {
|
|
PyErr_SetString(PyExc_RuntimeError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
if (!extss.IsDone()) {
|
|
PyErr_SetString(PyExc_RuntimeError, "BRepExtrema_DistShapeShape failed");
|
|
return nullptr;
|
|
}
|
|
Py::List solnPts;
|
|
Py::List solnGeom;
|
|
int count = extss.NbSolution();
|
|
if (count != 0) {
|
|
minDist = extss.Value();
|
|
//extss.Dump(std::cout);
|
|
for (int i=1; i<= count; i++) {
|
|
Py::Object pt1, pt2;
|
|
Py::String suppType1, suppType2;
|
|
Py::Long suppIndex1, suppIndex2;
|
|
Py::Object param1, param2;
|
|
|
|
P1 = extss.PointOnShape1(i);
|
|
pt1 = Py::asObject(new Base::VectorPy(new Base::Vector3d(P1.X(), P1.Y(), P1.Z())));
|
|
supportType1 = extss.SupportTypeShape1(i);
|
|
suppS1 = extss.SupportOnShape1(i);
|
|
switch (supportType1) {
|
|
case BRepExtrema_IsVertex:
|
|
suppType1 = Py::String("Vertex");
|
|
suppIndex1 = Py::asObject(_getSupportIndex("Vertex", ts1, suppS1));
|
|
param1 = Py::None();
|
|
break;
|
|
case BRepExtrema_IsOnEdge:
|
|
suppType1 = Py::String("Edge");
|
|
suppIndex1 = Py::asObject(_getSupportIndex("Edge", ts1, suppS1));
|
|
extss.ParOnEdgeS1(i,t1);
|
|
param1 = Py::Float(t1);
|
|
break;
|
|
case BRepExtrema_IsInFace:
|
|
suppType1 = Py::String("Face");
|
|
suppIndex1 = Py::asObject(_getSupportIndex("Face", ts1, suppS1));
|
|
extss.ParOnFaceS1(i,u1,v1);
|
|
{
|
|
Py::Tuple tup(2);
|
|
tup[0] = Py::Float(u1);
|
|
tup[1] = Py::Float(v1);
|
|
param1 = tup;
|
|
}
|
|
break;
|
|
default:
|
|
Base::Console().Message("distToShape: supportType1 is unknown: %d \n",
|
|
static_cast<int>(supportType1));
|
|
suppType1 = Py::String("Unknown");
|
|
suppIndex1 = -1;
|
|
param1 = Py::None();
|
|
}
|
|
|
|
P2 = extss.PointOnShape2(i);
|
|
pt2 = Py::asObject(new Base::VectorPy(new Base::Vector3d(P2.X(), P2.Y(), P2.Z())));
|
|
supportType2 = extss.SupportTypeShape2(i);
|
|
suppS2 = extss.SupportOnShape2(i);
|
|
switch (supportType2) {
|
|
case BRepExtrema_IsVertex:
|
|
suppType2 = Py::String("Vertex");
|
|
suppIndex2 = Py::asObject(_getSupportIndex("Vertex", ts2, suppS2));
|
|
param2 = Py::None();
|
|
break;
|
|
case BRepExtrema_IsOnEdge:
|
|
suppType2 = Py::String("Edge");
|
|
suppIndex2 = Py::asObject(_getSupportIndex("Edge", ts2, suppS2));
|
|
extss.ParOnEdgeS2(i,t2);
|
|
param2 = Py::Float(t2);
|
|
break;
|
|
case BRepExtrema_IsInFace:
|
|
suppType2 = Py::String("Face");
|
|
suppIndex2 = Py::asObject(_getSupportIndex("Face", ts2, suppS2));
|
|
extss.ParOnFaceS2(i,u2,v2);
|
|
{
|
|
Py::Tuple tup(2);
|
|
tup[0] = Py::Float(u2);
|
|
tup[1] = Py::Float(v2);
|
|
param2 = tup;
|
|
}
|
|
break;
|
|
default:
|
|
Base::Console().Message("distToShape: supportType2 is unknown: %d \n",
|
|
static_cast<int>(supportType2));
|
|
suppType2 = Py::String("Unknown");
|
|
suppIndex2 = -1;
|
|
param2 = Py::None();
|
|
}
|
|
Py::Tuple pts(2);
|
|
pts[0] = pt1;
|
|
pts[1] = pt2;
|
|
solnPts.append(pts);
|
|
|
|
Py::Tuple geom(6);
|
|
geom[0] = suppType1;
|
|
geom[1] = suppIndex1;
|
|
geom[2] = param1;
|
|
geom[3] = suppType2;
|
|
geom[4] = suppIndex2;
|
|
geom[5] = param2;
|
|
|
|
solnGeom.append(geom);
|
|
}
|
|
}
|
|
else {
|
|
PyErr_SetString(PyExc_TypeError, "distToShape: No Solutions Found.");
|
|
return nullptr;
|
|
}
|
|
Py::Tuple ret(3);
|
|
ret[0] = Py::Float(minDist);
|
|
ret[1] = solnPts;
|
|
ret[2] = solnGeom;
|
|
return Py::new_reference_to(ret);
|
|
}
|
|
|
|
PyObject* TopoShapePy::optimalBoundingBox(PyObject *args)
|
|
{
|
|
PyObject* useT = Py_True;
|
|
PyObject* useS = Py_False;
|
|
if (!PyArg_ParseTuple(args, "|O!O!", &PyBool_Type, &useT, &PyBool_Type, &useS)) {
|
|
return nullptr;
|
|
}
|
|
|
|
try {
|
|
TopoDS_Shape shape = this->getTopoShapePtr()->getShape();
|
|
Bnd_Box bounds;
|
|
BRepBndLib::AddOptimal(shape, bounds,
|
|
Base::asBoolean(useT),
|
|
Base::asBoolean(useS));
|
|
bounds.SetGap(0.0);
|
|
Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
|
|
bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
|
|
|
|
Base::BoundBox3d box;
|
|
box.MinX = xMin;
|
|
box.MaxX = xMax;
|
|
box.MinY = yMin;
|
|
box.MaxY = yMax;
|
|
box.MinZ = zMin;
|
|
box.MaxZ = zMax;
|
|
|
|
Py::BoundingBox pybox(box);
|
|
return Py::new_reference_to(pybox);
|
|
}
|
|
catch (const Standard_Failure& e) {
|
|
throw Py::RuntimeError(e.GetMessageString());
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::clearCache(PyObject* args)
|
|
{
|
|
if (!PyArg_ParseTuple(args, "")) {
|
|
return 0;
|
|
}
|
|
getTopoShapePtr()->initCache(1);
|
|
return IncRef();
|
|
}
|
|
|
|
PyObject* TopoShapePy::defeaturing(PyObject *args)
|
|
{
|
|
PyObject *l;
|
|
if (!PyArg_ParseTuple(args, "O",&l))
|
|
return nullptr;
|
|
|
|
try {
|
|
Py::Sequence list(l);
|
|
std::vector<TopoDS_Shape> shapes;
|
|
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
|
Py::TopoShape sh(*it);
|
|
shapes.push_back(
|
|
sh.extensionObject()->getTopoShapePtr()->getShape()
|
|
);
|
|
}
|
|
PyTypeObject* type = this->GetType();
|
|
PyObject* inst = type->tp_new(type, this, nullptr);
|
|
static_cast<TopoShapePy*>(inst)->getTopoShapePtr()->setShape
|
|
(this->getTopoShapePtr()->defeaturing(shapes));
|
|
return inst;
|
|
}
|
|
catch (const Standard_Failure& e) {
|
|
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
PyObject* TopoShapePy::findSubShape(PyObject* args)
|
|
{
|
|
PyObject* pyobj;
|
|
if (!PyArg_ParseTuple(args, "O", &pyobj)) {
|
|
return nullptr;
|
|
}
|
|
|
|
PY_TRY
|
|
{
|
|
Py::List res;
|
|
for (auto& s : getPyShapes(pyobj)) {
|
|
int index = getTopoShapePtr()->findShape(s.getShape());
|
|
if (index > 0) {
|
|
res.append(Py::TupleN(Py::String(s.shapeName()), Py::Long(index)));
|
|
}
|
|
else {
|
|
res.append(Py::TupleN(Py::Object(), Py::Long(0)));
|
|
}
|
|
}
|
|
if (PySequence_Check(pyobj)) {
|
|
return Py::new_reference_to(res);
|
|
}
|
|
return Py::new_reference_to(Py::Object(res[0].ptr()));
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::findSubShapesWithSharedVertex(PyObject* args, PyObject* keywds)
|
|
{
|
|
static const std::array<const char*, 7> kwlist {"shape", "needName", "checkGeometry", "tol", "atol", "singleResult", nullptr};
|
|
PyObject* pyobj;
|
|
PyObject* needName = Py_False;
|
|
PyObject* checkGeometry = Py_True;
|
|
PyObject* singleResult = Py_False;
|
|
double tol = 1e-7;
|
|
double atol = 1e-12;
|
|
if (!Base::Wrapped_ParseTupleAndKeywords(args,
|
|
keywds,
|
|
"O!|OOdd",
|
|
kwlist,
|
|
&Type,
|
|
&pyobj,
|
|
&needName,
|
|
&checkGeometry,
|
|
&tol,
|
|
&atol,
|
|
&singleResult)) {
|
|
return nullptr;
|
|
}
|
|
|
|
PY_TRY
|
|
{
|
|
Py::List res;
|
|
const TopoShape& shape = *static_cast<TopoShapePy*>(pyobj)->getTopoShapePtr();
|
|
Data::SearchOptions options;
|
|
if (PyObject_IsTrue(checkGeometry))
|
|
options.setFlag(Data::SearchOption::CheckGeometry);
|
|
if (PyObject_IsTrue(singleResult))
|
|
options.setFlag(Data::SearchOption::SingleResult);
|
|
if (PyObject_IsTrue(needName)) {
|
|
std::vector<std::string> names;
|
|
auto shapes = getTopoShapePtr()->findSubShapesWithSharedVertex(
|
|
shape,
|
|
&names,
|
|
options,
|
|
tol,
|
|
atol);
|
|
for (std::size_t i = 0; i < shapes.size(); ++i) {
|
|
res.append(Py::TupleN(Py::String(names[i]), shape2pyshape(shapes[i])));
|
|
}
|
|
}
|
|
else {
|
|
for (auto& s : getTopoShapePtr()->findSubShapesWithSharedVertex(
|
|
shape,
|
|
nullptr,
|
|
options,
|
|
tol,
|
|
atol)) {
|
|
res.append(shape2pyshape(s));
|
|
}
|
|
}
|
|
return Py::new_reference_to(res);
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
// End of Methods, Start of Attributes
|
|
|
|
Py::String TopoShapePy::getShapeType() const
|
|
{
|
|
TopoDS_Shape sh = getTopoShapePtr()->getShape();
|
|
if (sh.IsNull())
|
|
throw Py::Exception(Base::PyExc_FC_GeneralError, "cannot determine type of null shape");
|
|
|
|
TopAbs_ShapeEnum type = sh.ShapeType();
|
|
std::string name;
|
|
switch (type) {
|
|
case TopAbs_COMPOUND:
|
|
name = "Compound";
|
|
break;
|
|
case TopAbs_COMPSOLID:
|
|
name = "CompSolid";
|
|
break;
|
|
case TopAbs_SOLID:
|
|
name = "Solid";
|
|
break;
|
|
case TopAbs_SHELL:
|
|
name = "Shell";
|
|
break;
|
|
case TopAbs_FACE:
|
|
name = "Face";
|
|
break;
|
|
case TopAbs_WIRE:
|
|
name = "Wire";
|
|
break;
|
|
case TopAbs_EDGE:
|
|
name = "Edge";
|
|
break;
|
|
case TopAbs_VERTEX:
|
|
name = "Vertex";
|
|
break;
|
|
case TopAbs_SHAPE:
|
|
name = "Shape";
|
|
break;
|
|
}
|
|
|
|
return Py::String(name);
|
|
}
|
|
|
|
Py::String TopoShapePy::getOrientation() const
|
|
{
|
|
TopoDS_Shape sh = getTopoShapePtr()->getShape();
|
|
if (sh.IsNull())
|
|
throw Py::Exception(Base::PyExc_FC_GeneralError, "cannot determine orientation of null shape");
|
|
|
|
TopAbs_Orientation type = sh.Orientation();
|
|
std::string name;
|
|
switch (type) {
|
|
case TopAbs_FORWARD:
|
|
name = "Forward";
|
|
break;
|
|
case TopAbs_REVERSED:
|
|
name = "Reversed";
|
|
break;
|
|
case TopAbs_INTERNAL:
|
|
name = "Internal";
|
|
break;
|
|
case TopAbs_EXTERNAL:
|
|
name = "External";
|
|
break;
|
|
}
|
|
|
|
return Py::String(name);
|
|
}
|
|
|
|
void TopoShapePy::setOrientation(Py::String arg)
|
|
{
|
|
TopoDS_Shape sh = getTopoShapePtr()->getShape();
|
|
if (sh.IsNull())
|
|
throw Py::Exception(Base::PyExc_FC_GeneralError, "cannot determine orientation of null shape");
|
|
|
|
std::string name = static_cast<std::string>(arg);
|
|
TopAbs_Orientation type;
|
|
if (name == "Forward") {
|
|
type = TopAbs_FORWARD;
|
|
}
|
|
else if (name == "Reversed") {
|
|
type = TopAbs_REVERSED;
|
|
}
|
|
else if (name == "Internal") {
|
|
type = TopAbs_INTERNAL;
|
|
}
|
|
else if (name == "External") {
|
|
type = TopAbs_EXTERNAL;
|
|
}
|
|
else {
|
|
throw Py::AttributeError("Invalid orientation type");
|
|
}
|
|
|
|
sh.Orientation(type);
|
|
getTopoShapePtr()->setShape(sh);
|
|
}
|
|
|
|
static Py::List
|
|
getElements(const TopoShape& sh, TopAbs_ShapeEnum type, TopAbs_ShapeEnum avoid = TopAbs_SHAPE)
|
|
{
|
|
Py::List ret;
|
|
for (auto& shape : sh.getSubTopoShapes(type, avoid)) {
|
|
ret.append(shape2pyshape(shape));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
PyObject* TopoShapePy::getChildShapes(PyObject* args)
|
|
{
|
|
const char* type;
|
|
const char* avoid = nullptr;
|
|
if (!PyArg_ParseTuple(args, "s|s", &type, &avoid)) {
|
|
return nullptr;
|
|
}
|
|
|
|
PY_TRY
|
|
{
|
|
return Py::new_reference_to(
|
|
getElements(*getTopoShapePtr(),
|
|
TopoShape::shapeType(type),
|
|
!Base::Tools::isNullOrEmpty(avoid) ? TopoShape::shapeType(avoid) : TopAbs_SHAPE));
|
|
}
|
|
PY_CATCH_OCC;
|
|
}
|
|
|
|
Py::List TopoShapePy::getSubShapes() const
|
|
{
|
|
return getElements(*getTopoShapePtr(), TopAbs_SHAPE);
|
|
}
|
|
|
|
Py::List TopoShapePy::getFaces() const
|
|
{
|
|
return getElements(*getTopoShapePtr(), TopAbs_FACE);
|
|
}
|
|
|
|
Py::List TopoShapePy::getVertexes() const
|
|
{
|
|
return getElements(*getTopoShapePtr(), TopAbs_VERTEX);
|
|
}
|
|
|
|
Py::List TopoShapePy::getShells() const
|
|
{
|
|
return getElements(*getTopoShapePtr(), TopAbs_SHELL);
|
|
}
|
|
|
|
Py::List TopoShapePy::getSolids() const
|
|
{
|
|
return getElements(*getTopoShapePtr(), TopAbs_SOLID);
|
|
}
|
|
|
|
Py::List TopoShapePy::getCompSolids() const
|
|
{
|
|
return getElements(*getTopoShapePtr(), TopAbs_COMPSOLID);
|
|
}
|
|
|
|
Py::List TopoShapePy::getEdges() const
|
|
{
|
|
return getElements(*getTopoShapePtr(), TopAbs_EDGE);
|
|
}
|
|
|
|
Py::List TopoShapePy::getWires() const
|
|
{
|
|
return getElements(*getTopoShapePtr(), TopAbs_WIRE);
|
|
}
|
|
|
|
Py::List TopoShapePy::getCompounds() const
|
|
{
|
|
return getElements(*getTopoShapePtr(), TopAbs_COMPOUND);
|
|
}
|
|
|
|
Py::Float TopoShapePy::getLength() const
|
|
{
|
|
const TopoDS_Shape& shape = getTopoShapePtr()->getShape();
|
|
if (shape.IsNull())
|
|
throw Py::RuntimeError("shape is invalid");
|
|
GProp_GProps props;
|
|
BRepGProp::LinearProperties(shape, props);
|
|
return Py::Float(props.Mass());
|
|
}
|
|
|
|
Py::Float TopoShapePy::getArea() const
|
|
{
|
|
const TopoDS_Shape& shape = getTopoShapePtr()->getShape();
|
|
if (shape.IsNull())
|
|
throw Py::RuntimeError("shape is invalid");
|
|
GProp_GProps props;
|
|
BRepGProp::SurfaceProperties(shape, props);
|
|
return Py::Float(props.Mass());
|
|
}
|
|
|
|
Py::Float TopoShapePy::getVolume() const
|
|
{
|
|
const TopoDS_Shape& shape = getTopoShapePtr()->getShape();
|
|
if (shape.IsNull())
|
|
throw Py::RuntimeError("shape is invalid");
|
|
GProp_GProps props;
|
|
BRepGProp::VolumeProperties(shape, props);
|
|
return Py::Float(props.Mass());
|
|
}
|
|
|
|
PyObject* TopoShapePy::getElementHistory(PyObject* args)
|
|
{
|
|
const char* pyname;
|
|
if (!PyArg_ParseTuple(args, "s", &pyname)) {
|
|
return 0;
|
|
}
|
|
|
|
Data::MappedName name(pyname);
|
|
PY_TRY
|
|
{
|
|
Data::MappedName original;
|
|
std::vector<Data::MappedName> history;
|
|
long tag = getTopoShapePtr()->getElementHistory(name, &original, &history);
|
|
if (!tag) {
|
|
Py_Return;
|
|
}
|
|
Py::Tuple ret(3);
|
|
ret.setItem(0, Py::Long(tag));
|
|
std::string tmp;
|
|
ret.setItem(1, Py::String(original.appendToBuffer(tmp)));
|
|
Py::List pyHistory;
|
|
for (auto& h : history) {
|
|
tmp.clear();
|
|
pyHistory.append(Py::String(h.appendToBuffer(tmp)));
|
|
}
|
|
ret.setItem(2, pyHistory);
|
|
return Py::new_reference_to(ret);
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
struct PyShapeMapper: Part::ShapeMapper
|
|
{
|
|
bool populate(MappingStatus status, PyObject* pyobj)
|
|
{
|
|
if (!pyobj || pyobj == Py_None) {
|
|
return true;
|
|
}
|
|
try {
|
|
Py::Sequence seq(pyobj);
|
|
for (size_t i = 0, count = seq.size(); i < count; ++i) {
|
|
Py::Sequence item(seq[i].ptr());
|
|
if (item.size() != 2) {
|
|
return false;
|
|
}
|
|
|
|
Part::ShapeMapper::populate(status,
|
|
getPyShapes(item[0].ptr()),
|
|
getPyShapes(item[1].ptr()));
|
|
}
|
|
}
|
|
catch (Py::Exception&) {
|
|
PyErr_Clear();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void init(PyObject* g, PyObject* m)
|
|
{
|
|
const char* msg =
|
|
"Expect input mapping to be a list of tuple(srcShape|shapeList, dstShape|shapeList)";
|
|
if (!populate(MappingStatus::Generated, g) || !populate(MappingStatus::Modified, m)) {
|
|
throw Py::TypeError(msg);
|
|
}
|
|
}
|
|
};
|
|
|
|
PyObject* TopoShapePy::mapShapes(PyObject* args)
|
|
{
|
|
PyObject* generated;
|
|
PyObject* modified;
|
|
const char* op = nullptr;
|
|
if (!PyArg_ParseTuple(args, "OO|s", &generated, &modified, &op)) {
|
|
return 0;
|
|
}
|
|
PY_TRY
|
|
{
|
|
PyShapeMapper mapper;
|
|
mapper.init(generated, modified);
|
|
TopoShape& self = *getTopoShapePtr();
|
|
TopoShape s(self.Tag, self.Hasher);
|
|
s.makeShapeWithElementMap(self.getShape(), mapper, mapper.shapes, op);
|
|
self = s;
|
|
return IncRef();
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::mapSubElement(PyObject* args)
|
|
{
|
|
const char* op = nullptr;
|
|
PyObject* sh;
|
|
if (!PyArg_ParseTuple(args, "O|s", &sh, &op)) {
|
|
return 0;
|
|
}
|
|
PY_TRY
|
|
{
|
|
getTopoShapePtr()->mapSubElement(getPyShapes(sh), op);
|
|
return IncRef();
|
|
}
|
|
PY_CATCH_OCC
|
|
}
|
|
|
|
PyObject* TopoShapePy::getCustomAttributes(const char* attr) const
|
|
{
|
|
if (!attr) {
|
|
return nullptr;
|
|
}
|
|
PY_TRY
|
|
{
|
|
TopoDS_Shape res = getTopoShapePtr()->getSubShape(attr, true);
|
|
if (!res.IsNull()) {
|
|
return Py::new_reference_to(shape2pyshape(res));
|
|
}
|
|
}
|
|
PY_CATCH_OCC
|
|
return nullptr;
|
|
}
|
|
|
|
int TopoShapePy::setCustomAttributes(const char* , PyObject *)
|
|
{
|
|
return 0;
|
|
}
|