All: Reformat according to new standard
This commit is contained in:
committed by
Kacper Donat
parent
eafd18dac0
commit
25c3ba7338
@@ -49,44 +49,44 @@
|
||||
#include "FeaturePath.h"
|
||||
|
||||
|
||||
#define PATH_CATCH \
|
||||
catch (Standard_Failure & e) \
|
||||
{ \
|
||||
std::string str; \
|
||||
Standard_CString msg = e.GetMessageString(); \
|
||||
str += typeid(e).name(); \
|
||||
str += " "; \
|
||||
if (msg) { \
|
||||
str += msg; \
|
||||
} \
|
||||
else { \
|
||||
str += "No OCCT Exception Message"; \
|
||||
} \
|
||||
Base::Console().error(str.c_str()); \
|
||||
PyErr_SetString(Part::PartExceptionOCCError, str.c_str()); \
|
||||
} \
|
||||
catch (Base::Exception & e) \
|
||||
{ \
|
||||
std::string str; \
|
||||
str += "FreeCAD exception thrown ("; \
|
||||
str += e.what(); \
|
||||
str += ")"; \
|
||||
e.reportException(); \
|
||||
PyErr_SetString(Base::PyExc_FC_GeneralError, str.c_str()); \
|
||||
} \
|
||||
catch (std::exception & e) \
|
||||
{ \
|
||||
std::string str; \
|
||||
str += "STL exception thrown ("; \
|
||||
str += e.what(); \
|
||||
str += ")"; \
|
||||
Base::Console().error(str.c_str()); \
|
||||
PyErr_SetString(Base::PyExc_FC_GeneralError, str.c_str()); \
|
||||
} \
|
||||
catch (const char* e) \
|
||||
{ \
|
||||
PyErr_SetString(Base::PyExc_FC_GeneralError, e); \
|
||||
} \
|
||||
#define PATH_CATCH \
|
||||
catch (Standard_Failure & e) \
|
||||
{ \
|
||||
std::string str; \
|
||||
Standard_CString msg = e.GetMessageString(); \
|
||||
str += typeid(e).name(); \
|
||||
str += " "; \
|
||||
if (msg) { \
|
||||
str += msg; \
|
||||
} \
|
||||
else { \
|
||||
str += "No OCCT Exception Message"; \
|
||||
} \
|
||||
Base::Console().error(str.c_str()); \
|
||||
PyErr_SetString(Part::PartExceptionOCCError, str.c_str()); \
|
||||
} \
|
||||
catch (Base::Exception & e) \
|
||||
{ \
|
||||
std::string str; \
|
||||
str += "FreeCAD exception thrown ("; \
|
||||
str += e.what(); \
|
||||
str += ")"; \
|
||||
e.reportException(); \
|
||||
PyErr_SetString(Base::PyExc_FC_GeneralError, str.c_str()); \
|
||||
} \
|
||||
catch (std::exception & e) \
|
||||
{ \
|
||||
std::string str; \
|
||||
str += "STL exception thrown ("; \
|
||||
str += e.what(); \
|
||||
str += ")"; \
|
||||
Base::Console().error(str.c_str()); \
|
||||
PyErr_SetString(Base::PyExc_FC_GeneralError, str.c_str()); \
|
||||
} \
|
||||
catch (const char* e) \
|
||||
{ \
|
||||
PyErr_SetString(Base::PyExc_FC_GeneralError, e); \
|
||||
} \
|
||||
throw Py::Exception();
|
||||
|
||||
namespace PathApp
|
||||
@@ -111,49 +111,60 @@ public:
|
||||
Module()
|
||||
: Py::ExtensionModule<Module>("PathApp")
|
||||
{
|
||||
add_varargs_method("write",
|
||||
&Module::write,
|
||||
"write(object,filename): Exports a given path object to a GCode file");
|
||||
add_varargs_method(
|
||||
"write",
|
||||
&Module::write,
|
||||
"write(object,filename): Exports a given path object to a GCode file"
|
||||
);
|
||||
add_varargs_method(
|
||||
"read",
|
||||
&Module::read,
|
||||
"read(filename,[document]): Imports a GCode file into the given document");
|
||||
add_varargs_method("show",
|
||||
&Module::show,
|
||||
"show(path,[string]): Add the path to the active document or create one "
|
||||
"if no document exists");
|
||||
add_varargs_method("fromShape",
|
||||
&Module::fromShape,
|
||||
"fromShape(Shape): Returns a Path object from a Part Shape (deprecated "
|
||||
"- use fromShapes() instead)");
|
||||
"read(filename,[document]): Imports a GCode file into the given document"
|
||||
);
|
||||
add_varargs_method(
|
||||
"show",
|
||||
&Module::show,
|
||||
"show(path,[string]): Add the path to the active document or create one "
|
||||
"if no document exists"
|
||||
);
|
||||
add_varargs_method(
|
||||
"fromShape",
|
||||
&Module::fromShape,
|
||||
"fromShape(Shape): Returns a Path object from a Part Shape (deprecated "
|
||||
"- use fromShapes() instead)"
|
||||
);
|
||||
add_keyword_method(
|
||||
"fromShapes",
|
||||
&Module::fromShapes,
|
||||
"fromShapes(shapes, start=Vector(), return_end=False" PARAM_PY_ARGS_DOC(
|
||||
ARG,
|
||||
AREA_PARAMS_PATH) ")\n"
|
||||
"\nReturns a Path object from a list of shapes\n"
|
||||
"\n* shapes: input list of shapes.\n"
|
||||
"\n* start (Vector()): feed start position, and also serves as a "
|
||||
"hint of path entry.\n"
|
||||
"\n* return_end (False): if True, returns tuple (path, "
|
||||
"endPosition).\n" PARAM_PY_DOC(ARG, AREA_PARAMS_PATH));
|
||||
AREA_PARAMS_PATH
|
||||
) ")\n"
|
||||
"\nReturns a Path object from a list of shapes\n"
|
||||
"\n* shapes: input list of shapes.\n"
|
||||
"\n* start (Vector()): feed start position, and also serves as a "
|
||||
"hint of path entry.\n"
|
||||
"\n* return_end (False): if True, returns tuple (path, "
|
||||
"endPosition).\n" PARAM_PY_DOC(ARG, AREA_PARAMS_PATH)
|
||||
);
|
||||
add_keyword_method(
|
||||
"sortWires",
|
||||
&Module::sortWires,
|
||||
"sortWires(shapes, start=Vector(), " PARAM_PY_ARGS_DOC(ARG, AREA_PARAMS_ARC_PLANE)
|
||||
PARAM_PY_ARGS_DOC(
|
||||
ARG,
|
||||
AREA_PARAMS_SORT) ")\n"
|
||||
"\nReturns (wires,end), where 'wires' is sorted across Z "
|
||||
"value and with optimized travel distance,\n"
|
||||
"and 'end' is the ending position of the whole wires. If "
|
||||
"arc_plane==1, it returns (wires,end,arc_plane),\n"
|
||||
"where arc_plane is the found plane if any, or unchanged.\n"
|
||||
"\n* shapes: input shape list\n"
|
||||
"\n* start (Vector()): optional start "
|
||||
"position.\n" PARAM_PY_DOC(ARG, AREA_PARAMS_ARC_PLANE)
|
||||
PARAM_PY_DOC(ARG, AREA_PARAMS_SORT));
|
||||
AREA_PARAMS_SORT
|
||||
) ")\n"
|
||||
"\nReturns (wires,end), where 'wires' is sorted across Z "
|
||||
"value and with optimized travel distance,\n"
|
||||
"and 'end' is the ending position of the whole wires. If "
|
||||
"arc_plane==1, it returns (wires,end,arc_plane),\n"
|
||||
"where arc_plane is the found plane if any, or unchanged.\n"
|
||||
"\n* shapes: input shape list\n"
|
||||
"\n* start (Vector()): optional start "
|
||||
"position.\n" PARAM_PY_DOC(ARG, AREA_PARAMS_ARC_PLANE)
|
||||
PARAM_PY_DOC(ARG, AREA_PARAMS_SORT)
|
||||
);
|
||||
initialize("This module is the Path module."); // register with Python
|
||||
|
||||
PyModule_AddObject(m_module, "Voronoi", voronoi.module().ptr());
|
||||
@@ -175,8 +186,8 @@ private:
|
||||
Base::FileInfo file(EncodedName.c_str());
|
||||
|
||||
if (PyObject_TypeCheck(pObj, &(App::DocumentObjectPy::Type))) {
|
||||
App::DocumentObject* obj =
|
||||
static_cast<App::DocumentObjectPy*>(pObj)->getDocumentObjectPtr();
|
||||
App::DocumentObject* obj
|
||||
= static_cast<App::DocumentObjectPy*>(pObj)->getDocumentObjectPtr();
|
||||
if (obj->isDerivedFrom<Path::Feature>()) {
|
||||
const Path::Toolpath& path = static_cast<Path::Feature*>(obj)->Path.getValue();
|
||||
std::string gcode = path.toGCode();
|
||||
@@ -368,24 +379,26 @@ private:
|
||||
"start",
|
||||
"return_end",
|
||||
PARAM_FIELD_STRINGS(ARG, AREA_PARAMS_PATH),
|
||||
nullptr};
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(args.ptr(),
|
||||
kwds.ptr(),
|
||||
"O|O!O!" PARAM_PY_KWDS(AREA_PARAMS_PATH),
|
||||
kwd_list,
|
||||
&pShapes,
|
||||
&(Base::VectorPy::Type),
|
||||
&start,
|
||||
&PyBool_Type,
|
||||
&return_end,
|
||||
PARAM_REF(PARAM_FARG, AREA_PARAMS_PATH))) {
|
||||
nullptr
|
||||
};
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(
|
||||
args.ptr(),
|
||||
kwds.ptr(),
|
||||
"O|O!O!" PARAM_PY_KWDS(AREA_PARAMS_PATH),
|
||||
kwd_list,
|
||||
&pShapes,
|
||||
&(Base::VectorPy::Type),
|
||||
&start,
|
||||
&PyBool_Type,
|
||||
&return_end,
|
||||
PARAM_REF(PARAM_FARG, AREA_PARAMS_PATH)
|
||||
)) {
|
||||
throw Py::Exception();
|
||||
}
|
||||
|
||||
std::list<TopoDS_Shape> shapes;
|
||||
if (PyObject_TypeCheck(pShapes, &(Part::TopoShapePy::Type))) {
|
||||
shapes.push_back(
|
||||
static_cast<Part::TopoShapePy*>(pShapes)->getTopoShapePtr()->getShape());
|
||||
shapes.push_back(static_cast<Part::TopoShapePy*>(pShapes)->getTopoShapePtr()->getShape());
|
||||
}
|
||||
else if (PyObject_TypeCheck(pShapes, &(PyList_Type))
|
||||
|| PyObject_TypeCheck(pShapes, &(PyTuple_Type))) {
|
||||
@@ -396,8 +409,7 @@ private:
|
||||
PyErr_SetString(PyExc_TypeError, "non-shape object in sequence");
|
||||
throw Py::Exception();
|
||||
}
|
||||
shapes.push_back(
|
||||
static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape());
|
||||
shapes.push_back(static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,11 +422,13 @@ private:
|
||||
try {
|
||||
gp_Pnt pend;
|
||||
std::unique_ptr<Path::Toolpath> path(new Path::Toolpath);
|
||||
Path::Area::toPath(*path,
|
||||
shapes,
|
||||
start ? &pstart : nullptr,
|
||||
&pend,
|
||||
PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_PATH));
|
||||
Path::Area::toPath(
|
||||
*path,
|
||||
shapes,
|
||||
start ? &pstart : nullptr,
|
||||
&pend,
|
||||
PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_PATH)
|
||||
);
|
||||
if (!Base::asBoolean(return_end)) {
|
||||
return Py::asObject(new Path::PathPy(path.release()));
|
||||
}
|
||||
@@ -422,7 +436,8 @@ private:
|
||||
tuple.setItem(0, Py::asObject(new Path::PathPy(path.release())));
|
||||
tuple.setItem(
|
||||
1,
|
||||
Py::asObject(new Base::VectorPy(Base::Vector3d(pend.X(), pend.Y(), pend.Z()))));
|
||||
Py::asObject(new Base::VectorPy(Base::Vector3d(pend.X(), pend.Y(), pend.Z())))
|
||||
);
|
||||
return tuple;
|
||||
}
|
||||
PATH_CATCH
|
||||
@@ -439,24 +454,25 @@ private:
|
||||
"start",
|
||||
PARAM_FIELD_STRINGS(ARG, AREA_PARAMS_ARC_PLANE),
|
||||
PARAM_FIELD_STRINGS(ARG, AREA_PARAMS_SORT),
|
||||
nullptr};
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(args.ptr(),
|
||||
kwds.ptr(),
|
||||
"O|O!" PARAM_PY_KWDS(AREA_PARAMS_ARC_PLANE)
|
||||
PARAM_PY_KWDS(AREA_PARAMS_SORT),
|
||||
kwd_list,
|
||||
&pShapes,
|
||||
&(Base::VectorPy::Type),
|
||||
&start,
|
||||
PARAM_REF(PARAM_FARG, AREA_PARAMS_ARC_PLANE),
|
||||
PARAM_REF(PARAM_FARG, AREA_PARAMS_SORT))) {
|
||||
nullptr
|
||||
};
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(
|
||||
args.ptr(),
|
||||
kwds.ptr(),
|
||||
"O|O!" PARAM_PY_KWDS(AREA_PARAMS_ARC_PLANE) PARAM_PY_KWDS(AREA_PARAMS_SORT),
|
||||
kwd_list,
|
||||
&pShapes,
|
||||
&(Base::VectorPy::Type),
|
||||
&start,
|
||||
PARAM_REF(PARAM_FARG, AREA_PARAMS_ARC_PLANE),
|
||||
PARAM_REF(PARAM_FARG, AREA_PARAMS_SORT)
|
||||
)) {
|
||||
throw Py::Exception();
|
||||
}
|
||||
|
||||
std::list<TopoDS_Shape> shapes;
|
||||
if (PyObject_TypeCheck(pShapes, &(Part::TopoShapePy::Type))) {
|
||||
shapes.push_back(
|
||||
static_cast<Part::TopoShapePy*>(pShapes)->getTopoShapePtr()->getShape());
|
||||
shapes.push_back(static_cast<Part::TopoShapePy*>(pShapes)->getTopoShapePtr()->getShape());
|
||||
}
|
||||
else if (PyObject_TypeCheck(pShapes, &(PyList_Type))
|
||||
|| PyObject_TypeCheck(pShapes, &(PyTuple_Type))) {
|
||||
@@ -467,8 +483,7 @@ private:
|
||||
PyErr_SetString(PyExc_TypeError, "non-shape object in sequence");
|
||||
throw Py::Exception();
|
||||
}
|
||||
shapes.push_back(
|
||||
static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape());
|
||||
shapes.push_back(static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -480,14 +495,15 @@ private:
|
||||
|
||||
try {
|
||||
bool need_arc_plane = arc_plane == Path::Area::ArcPlaneAuto;
|
||||
std::list<TopoDS_Shape> wires =
|
||||
Path::Area::sortWires(shapes,
|
||||
start != nullptr,
|
||||
&pstart,
|
||||
&pend,
|
||||
nullptr,
|
||||
&arc_plane,
|
||||
PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_SORT));
|
||||
std::list<TopoDS_Shape> wires = Path::Area::sortWires(
|
||||
shapes,
|
||||
start != nullptr,
|
||||
&pstart,
|
||||
&pend,
|
||||
nullptr,
|
||||
&arc_plane,
|
||||
PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_SORT)
|
||||
);
|
||||
Py::List list;
|
||||
for (auto& wire : wires) {
|
||||
list.append(Part::shape2pyshape(TopoDS::Wire(wire)));
|
||||
@@ -497,7 +513,8 @@ private:
|
||||
ret.setItem(0, list);
|
||||
ret.setItem(
|
||||
1,
|
||||
Py::asObject(new Base::VectorPy(Base::Vector3d(pend.X(), pend.Y(), pend.Z()))));
|
||||
Py::asObject(new Base::VectorPy(Base::Vector3d(pend.X(), pend.Y(), pend.Z())))
|
||||
);
|
||||
if (need_arc_plane) {
|
||||
ret.setItem(2, Py::Long(arc_plane));
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -61,8 +61,8 @@ struct PathExport AreaParams: CAreaParams
|
||||
|
||||
bool operator==(const AreaParams& other) const
|
||||
{
|
||||
#define AREA_COMPARE(_param) \
|
||||
if (PARAM_FIELD(NAME, _param) != other.PARAM_FIELD(NAME, _param)) \
|
||||
#define AREA_COMPARE(_param) \
|
||||
if (PARAM_FIELD(NAME, _param) != other.PARAM_FIELD(NAME, _param)) \
|
||||
return false;
|
||||
PARAM_FOREACH(AREA_COMPARE, AREA_PARAMS_CAREA);
|
||||
PARAM_FOREACH(AREA_COMPARE, AREA_PARAMS_AREA);
|
||||
@@ -160,9 +160,11 @@ protected:
|
||||
*
|
||||
* See #AREA_PARAMS_OFFSET for description of the arguments.
|
||||
*/
|
||||
void makeOffset(std::list<std::shared_ptr<CArea>>& areas,
|
||||
PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_OFFSET),
|
||||
bool from_center = false);
|
||||
void makeOffset(
|
||||
std::list<std::shared_ptr<CArea>>& areas,
|
||||
PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_OFFSET),
|
||||
bool from_center = false
|
||||
);
|
||||
|
||||
/** Make a pocket of the combined shape
|
||||
*
|
||||
@@ -227,10 +229,12 @@ public:
|
||||
* If more than one offset is requested, a compound shape is return
|
||||
* containing all offset shapes as wires regardless of \c Fill setting.
|
||||
*/
|
||||
TopoDS_Shape makeOffset(int index = -1,
|
||||
PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_OFFSET),
|
||||
int reoirent = 0,
|
||||
bool from_center = false);
|
||||
TopoDS_Shape makeOffset(
|
||||
int index = -1,
|
||||
PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_OFFSET),
|
||||
int reoirent = 0,
|
||||
bool from_center = false
|
||||
);
|
||||
|
||||
/** Make a pocket of the combined shape
|
||||
*
|
||||
@@ -250,15 +254,19 @@ public:
|
||||
* See #AREA_PARAMS_EXTRA for description of the arguments. Currently, there
|
||||
* is only one argument, namely \c mode for section mode.
|
||||
*/
|
||||
std::vector<std::shared_ptr<Area>>
|
||||
makeSections(PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_SECTION_EXTRA),
|
||||
const std::vector<double>& heights = std::vector<double>(),
|
||||
const TopoDS_Shape& plane = TopoDS_Shape());
|
||||
std::vector<std::shared_ptr<Area>> makeSections(
|
||||
PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_SECTION_EXTRA),
|
||||
const std::vector<double>& heights = std::vector<double>(),
|
||||
const TopoDS_Shape& plane = TopoDS_Shape()
|
||||
);
|
||||
|
||||
std::shared_ptr<Area>
|
||||
getClearedArea(const Toolpath* path, double diameter, double zmax, Base::BoundBox3d bbox);
|
||||
std::shared_ptr<Area> getRestArea(std::vector<std::shared_ptr<Area>> clearedAreas,
|
||||
double diameter);
|
||||
std::shared_ptr<Area> getClearedArea(
|
||||
const Toolpath* path,
|
||||
double diameter,
|
||||
double zmax,
|
||||
Base::BoundBox3d bbox
|
||||
);
|
||||
std::shared_ptr<Area> getRestArea(std::vector<std::shared_ptr<Area>> clearedAreas, double diameter);
|
||||
TopoDS_Shape toTopoShape();
|
||||
|
||||
/** Config this Area object */
|
||||
@@ -308,11 +316,13 @@ public:
|
||||
* \arg \c to_edges: if true, discretize all curves, and insert as open
|
||||
* line segments
|
||||
* */
|
||||
static void addWire(CArea& area,
|
||||
const TopoDS_Wire& wire,
|
||||
const gp_Trsf* trsf = nullptr,
|
||||
double deflection = 0.01,
|
||||
bool to_edges = false);
|
||||
static void addWire(
|
||||
CArea& area,
|
||||
const TopoDS_Wire& wire,
|
||||
const gp_Trsf* trsf = nullptr,
|
||||
double deflection = 0.01,
|
||||
bool to_edges = false
|
||||
);
|
||||
|
||||
/** Add a OCC generic shape to CArea
|
||||
*
|
||||
@@ -331,15 +341,17 @@ public:
|
||||
* \return Returns the number of non coplaner. Planar testing only happens
|
||||
* if \c plane is supplied
|
||||
* */
|
||||
static int addShape(CArea& area,
|
||||
const TopoDS_Shape& shape,
|
||||
const gp_Trsf* trsf = nullptr,
|
||||
double deflection = 0.01,
|
||||
const TopoDS_Shape* plane = nullptr,
|
||||
bool force_coplanar = true,
|
||||
CArea* areaOpen = nullptr,
|
||||
bool to_edges = false,
|
||||
bool reorient = true);
|
||||
static int addShape(
|
||||
CArea& area,
|
||||
const TopoDS_Shape& shape,
|
||||
const gp_Trsf* trsf = nullptr,
|
||||
double deflection = 0.01,
|
||||
const TopoDS_Shape* plane = nullptr,
|
||||
bool force_coplanar = true,
|
||||
CArea* areaOpen = nullptr,
|
||||
bool to_edges = false,
|
||||
bool reorient = true
|
||||
);
|
||||
|
||||
/** Convert curves in CArea into an OCC shape
|
||||
*
|
||||
@@ -348,8 +360,12 @@ public:
|
||||
* \arg \c trsf: optional transform matrix to transform the shape back into
|
||||
* its original position.
|
||||
* */
|
||||
static TopoDS_Shape
|
||||
toShape(const CArea& area, bool fill, const gp_Trsf* trsf = nullptr, int reoirent = 0);
|
||||
static TopoDS_Shape toShape(
|
||||
const CArea& area,
|
||||
bool fill,
|
||||
const gp_Trsf* trsf = nullptr,
|
||||
int reoirent = 0
|
||||
);
|
||||
|
||||
/** Convert a single curve into an OCC wire
|
||||
*
|
||||
@@ -357,8 +373,7 @@ public:
|
||||
* \arg \c trsf: optional transform matrix to transform the shape back into
|
||||
* its original position.
|
||||
* */
|
||||
static TopoDS_Shape
|
||||
toShape(const CCurve& curve, const gp_Trsf* trsf = nullptr, int reorient = 0);
|
||||
static TopoDS_Shape toShape(const CCurve& curve, const gp_Trsf* trsf = nullptr, int reorient = 0);
|
||||
|
||||
/** Check if two OCC shape is coplanar */
|
||||
static bool isCoplanar(const TopoDS_Shape& s1, const TopoDS_Shape& s2);
|
||||
@@ -383,13 +398,15 @@ public:
|
||||
*
|
||||
* \return sorted wires
|
||||
*/
|
||||
static std::list<TopoDS_Shape> sortWires(const std::list<TopoDS_Shape>& shapes,
|
||||
bool has_start = false,
|
||||
gp_Pnt* pstart = nullptr,
|
||||
gp_Pnt* pend = nullptr,
|
||||
double* stepdown_hint = nullptr,
|
||||
short* arc_plane = nullptr,
|
||||
PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_SORT));
|
||||
static std::list<TopoDS_Shape> sortWires(
|
||||
const std::list<TopoDS_Shape>& shapes,
|
||||
bool has_start = false,
|
||||
gp_Pnt* pstart = nullptr,
|
||||
gp_Pnt* pend = nullptr,
|
||||
double* stepdown_hint = nullptr,
|
||||
short* arc_plane = nullptr,
|
||||
PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_SORT)
|
||||
);
|
||||
|
||||
/** Convert a list of wires to gcode
|
||||
*
|
||||
@@ -400,16 +417,20 @@ public:
|
||||
*
|
||||
* See #AREA_PARAMS_PATH for other arguments
|
||||
*/
|
||||
static void toPath(Toolpath& path,
|
||||
const std::list<TopoDS_Shape>& shapes,
|
||||
const gp_Pnt* pstart = nullptr,
|
||||
gp_Pnt* pend = nullptr,
|
||||
PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_PATH));
|
||||
static void toPath(
|
||||
Toolpath& path,
|
||||
const std::list<TopoDS_Shape>& shapes,
|
||||
const gp_Pnt* pstart = nullptr,
|
||||
gp_Pnt* pend = nullptr,
|
||||
PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_PATH)
|
||||
);
|
||||
|
||||
static int project(TopoDS_Shape& out,
|
||||
const TopoDS_Shape& in,
|
||||
const AreaParams* params = nullptr,
|
||||
const TopoDS_Shape* work_plane = nullptr);
|
||||
static int project(
|
||||
TopoDS_Shape& out,
|
||||
const TopoDS_Shape& in,
|
||||
const AreaParams* params = nullptr,
|
||||
const TopoDS_Shape* work_plane = nullptr
|
||||
);
|
||||
|
||||
static void setWireOrientation(TopoDS_Wire& wire, const gp_Dir& dir, bool ccw);
|
||||
|
||||
@@ -421,8 +442,7 @@ public:
|
||||
static void setDefaultParams(const AreaStaticParams& params);
|
||||
static const AreaStaticParams& getDefaultParams();
|
||||
|
||||
static void
|
||||
showShape(const TopoDS_Shape& shape, const char* name, const char* fmt = nullptr, ...);
|
||||
static void showShape(const TopoDS_Shape& shape, const char* name, const char* fmt = nullptr, ...);
|
||||
};
|
||||
|
||||
} // namespace Path
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -51,7 +51,8 @@ static PyObject* areaSetParams(PyObject*, PyObject* args, PyObject* kwd)
|
||||
|
||||
static const std::array<const char*, 43> kwlist {
|
||||
PARAM_FIELD_STRINGS(NAME, AREA_PARAMS_STATIC_CONF),
|
||||
nullptr};
|
||||
nullptr
|
||||
};
|
||||
|
||||
if (args && PySequence_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "Non-keyword argument is not supported");
|
||||
@@ -62,21 +63,23 @@ static PyObject* areaSetParams(PyObject*, PyObject* args, PyObject* kwd)
|
||||
|
||||
AreaStaticParams params = Area::getDefaultParams();
|
||||
|
||||
#define AREA_SET(_param) \
|
||||
#define AREA_SET(_param) \
|
||||
PARAM_FNAME(_param) = PARAM_TYPED(PARAM_PY_CAST_, _param)(params.PARAM_FNAME(_param));
|
||||
// populate the CONF variables with params
|
||||
PARAM_FOREACH(AREA_SET, AREA_PARAMS_STATIC_CONF)
|
||||
|
||||
// Parse arguments to overwrite CONF variables
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(args,
|
||||
kwd,
|
||||
"|" PARAM_PY_KWDS(AREA_PARAMS_STATIC_CONF),
|
||||
kwlist,
|
||||
PARAM_REF(PARAM_FNAME, AREA_PARAMS_STATIC_CONF))) {
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(
|
||||
args,
|
||||
kwd,
|
||||
"|" PARAM_PY_KWDS(AREA_PARAMS_STATIC_CONF),
|
||||
kwlist,
|
||||
PARAM_REF(PARAM_FNAME, AREA_PARAMS_STATIC_CONF)
|
||||
)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#define AREA_GET(_param) \
|
||||
#define AREA_GET(_param) \
|
||||
params.PARAM_FNAME(_param) = PARAM_TYPED(PARAM_CAST_PY_, _param)(PARAM_FNAME(_param));
|
||||
// populate 'params' with the CONF variables
|
||||
PARAM_FOREACH(AREA_GET, AREA_PARAMS_STATIC_CONF)
|
||||
@@ -122,30 +125,31 @@ static const PyMethodDef areaOverrides[] = {
|
||||
nullptr,
|
||||
0,
|
||||
"setParam(key=value...): Set algorithm parameters. You can call getParamsDesc() to \n"
|
||||
"get a list of supported parameters and their descriptions.\n" PARAM_PY_DOC(NAME,
|
||||
AREA_PARAMS_CONF)},
|
||||
"get a list of supported parameters and their descriptions.\n" PARAM_PY_DOC(NAME, AREA_PARAMS_CONF)},
|
||||
{
|
||||
"add",
|
||||
nullptr,
|
||||
0,
|
||||
"add((shape...)," PARAM_PY_ARGS_DOC(
|
||||
ARG,
|
||||
AREA_PARAMS_OPCODE) "):\n"
|
||||
"Add TopoShape(s) with given operation code\n" PARAM_PY_DOC(
|
||||
ARG,
|
||||
AREA_PARAMS_OPCODE) "\nThe first shape's wires will be unioned "
|
||||
"together regardless of the op code given\n"
|
||||
"(except for 'Compound'). Subsequent "
|
||||
"shape's wire will be combined using the "
|
||||
"op code.\n"
|
||||
"All shape wires shall be coplanar, and "
|
||||
"are used to determine a working plane for "
|
||||
"face\n"
|
||||
"making and offsetting. You can call "
|
||||
"setPlane() to supply a reference shape to "
|
||||
"determine\n"
|
||||
"the workplane in case the added shapes "
|
||||
"are all colinear lines.\n",
|
||||
AREA_PARAMS_OPCODE
|
||||
) "):\n"
|
||||
"Add TopoShape(s) with given operation code\n" PARAM_PY_DOC(
|
||||
ARG,
|
||||
AREA_PARAMS_OPCODE
|
||||
) "\nThe first shape's wires will be unioned "
|
||||
"together regardless of the op code given\n"
|
||||
"(except for 'Compound'). Subsequent "
|
||||
"shape's wire will be combined using the "
|
||||
"op code.\n"
|
||||
"All shape wires shall be coplanar, and "
|
||||
"are used to determine a working plane for "
|
||||
"face\n"
|
||||
"making and offsetting. You can call "
|
||||
"setPlane() to supply a reference shape to "
|
||||
"determine\n"
|
||||
"the workplane in case the added shapes "
|
||||
"are all colinear lines.\n",
|
||||
},
|
||||
|
||||
{
|
||||
@@ -154,11 +158,11 @@ static const PyMethodDef areaOverrides[] = {
|
||||
0,
|
||||
"makeOffset(index=-1, " PARAM_PY_ARGS_DOC(
|
||||
ARG,
|
||||
AREA_PARAMS_OFFSET) "):\n"
|
||||
"Make an 2D offset of the shape.\n"
|
||||
"\n* index (-1): the index of the section. -1 means all sections. "
|
||||
"No effect on planar shape.\n" PARAM_PY_DOC(ARG,
|
||||
AREA_PARAMS_OFFSET),
|
||||
AREA_PARAMS_OFFSET
|
||||
) "):\n"
|
||||
"Make an 2D offset of the shape.\n"
|
||||
"\n* index (-1): the index of the section. -1 means all sections. "
|
||||
"No effect on planar shape.\n" PARAM_PY_DOC(ARG, AREA_PARAMS_OFFSET),
|
||||
},
|
||||
{
|
||||
"makePocket",
|
||||
@@ -166,11 +170,11 @@ static const PyMethodDef areaOverrides[] = {
|
||||
0,
|
||||
"makePocket(index=-1, " PARAM_PY_ARGS_DOC(
|
||||
ARG,
|
||||
AREA_PARAMS_POCKET) "):\n"
|
||||
"Generate pocket toolpath of the shape.\n"
|
||||
"\n* index (-1): the index of the section. -1 means all sections. "
|
||||
"No effect on planar shape.\n" PARAM_PY_DOC(ARG,
|
||||
AREA_PARAMS_POCKET),
|
||||
AREA_PARAMS_POCKET
|
||||
) "):\n"
|
||||
"Generate pocket toolpath of the shape.\n"
|
||||
"\n* index (-1): the index of the section. -1 means all sections. "
|
||||
"No effect on planar shape.\n" PARAM_PY_DOC(ARG, AREA_PARAMS_POCKET),
|
||||
},
|
||||
{
|
||||
"makeSections",
|
||||
@@ -178,25 +182,27 @@ static const PyMethodDef areaOverrides[] = {
|
||||
0,
|
||||
"makeSections(" PARAM_PY_ARGS_DOC(
|
||||
ARG,
|
||||
AREA_PARAMS_SECTION_EXTRA) ", heights=[], plane=None):\n"
|
||||
"Make a list of area holding the sectioned children shapes "
|
||||
"on given heights\n" PARAM_PY_DOC(
|
||||
ARG,
|
||||
AREA_PARAMS_SECTION_EXTRA) "\n* heights ([]): a list of "
|
||||
"section heights, the "
|
||||
"meaning of the value is "
|
||||
"determined by 'mode'.\n"
|
||||
"If not specified, the "
|
||||
"current SectionCount, and "
|
||||
"SectionOffset of this Area "
|
||||
"is used.\n"
|
||||
"\n* plane (None): optional "
|
||||
"shape to specify a section "
|
||||
"plane. If not give, the "
|
||||
"current workplane\n"
|
||||
"of this Area is used if "
|
||||
"section mode is "
|
||||
"'Workplane'.",
|
||||
AREA_PARAMS_SECTION_EXTRA
|
||||
) ", heights=[], plane=None):\n"
|
||||
"Make a list of area holding the sectioned children shapes "
|
||||
"on given heights\n" PARAM_PY_DOC(
|
||||
ARG,
|
||||
AREA_PARAMS_SECTION_EXTRA
|
||||
) "\n* heights ([]): a list of "
|
||||
"section heights, the "
|
||||
"meaning of the value is "
|
||||
"determined by 'mode'.\n"
|
||||
"If not specified, the "
|
||||
"current SectionCount, and "
|
||||
"SectionOffset of this Area "
|
||||
"is used.\n"
|
||||
"\n* plane (None): optional "
|
||||
"shape to specify a section "
|
||||
"plane. If not give, the "
|
||||
"current workplane\n"
|
||||
"of this Area is used if "
|
||||
"section mode is "
|
||||
"'Workplane'.",
|
||||
},
|
||||
{
|
||||
"getClearedArea",
|
||||
@@ -321,13 +327,7 @@ PyObject* AreaPy::getShape(PyObject* args, PyObject* keywds)
|
||||
PyObject* pcObj = Py_False;
|
||||
short index = -1;
|
||||
static const std::array<const char*, 3> kwlist {"index", "rebuild", nullptr};
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(args,
|
||||
keywds,
|
||||
"|hO!",
|
||||
kwlist,
|
||||
&index,
|
||||
&PyBool_Type,
|
||||
&pcObj)) {
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, "|hO!", kwlist, &index, &PyBool_Type, &pcObj)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -349,16 +349,20 @@ PyObject* AreaPy::add(PyObject* args, PyObject* keywds)
|
||||
// Strangely, PyArg_ParseTupleAndKeywords requires all arguments to be keyword based,
|
||||
// even non-optional ones? That doesn't make sense in python. Seems only in python 3
|
||||
// they added '$' to address that issue.
|
||||
static const std::array<const char*, 3> kwlist {"shape",
|
||||
PARAM_FIELD_STRINGS(ARG, AREA_PARAMS_OPCODE),
|
||||
nullptr};
|
||||
static const std::array<const char*, 3> kwlist {
|
||||
"shape",
|
||||
PARAM_FIELD_STRINGS(ARG, AREA_PARAMS_OPCODE),
|
||||
nullptr
|
||||
};
|
||||
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(args,
|
||||
keywds,
|
||||
"O|" PARAM_PY_KWDS(AREA_PARAMS_OPCODE),
|
||||
kwlist,
|
||||
&pcObj,
|
||||
PARAM_REF(PARAM_FARG, AREA_PARAMS_OPCODE))) {
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(
|
||||
args,
|
||||
keywds,
|
||||
"O|" PARAM_PY_KWDS(AREA_PARAMS_OPCODE),
|
||||
kwlist,
|
||||
&pcObj,
|
||||
PARAM_REF(PARAM_FARG, AREA_PARAMS_OPCODE)
|
||||
)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -381,8 +385,7 @@ PyObject* AreaPy::add(PyObject* args, PyObject* keywds)
|
||||
}
|
||||
for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) {
|
||||
PyObject* item = (*it).ptr();
|
||||
getAreaPtr()->add(GET_TOPOSHAPE(item),
|
||||
PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_OPCODE));
|
||||
getAreaPtr()->add(GET_TOPOSHAPE(item), PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_OPCODE));
|
||||
}
|
||||
Py_INCREF(this);
|
||||
return this;
|
||||
@@ -397,9 +400,11 @@ PyObject* AreaPy::add(PyObject* args, PyObject* keywds)
|
||||
PyObject* AreaPy::makeOffset(PyObject* args, PyObject* keywds)
|
||||
{
|
||||
// Generate a keyword string defined in the ARG field of OFFSET parameter list
|
||||
static const std::array<const char*, 6> kwlist {"index",
|
||||
PARAM_FIELD_STRINGS(ARG, AREA_PARAMS_OFFSET),
|
||||
nullptr};
|
||||
static const std::array<const char*, 6> kwlist {
|
||||
"index",
|
||||
PARAM_FIELD_STRINGS(ARG, AREA_PARAMS_OFFSET),
|
||||
nullptr
|
||||
};
|
||||
short index = -1;
|
||||
|
||||
// Declare variables defined in the ARG field of the OFFSET parameter list with
|
||||
@@ -407,20 +412,22 @@ PyObject* AreaPy::makeOffset(PyObject* args, PyObject* keywds)
|
||||
PARAM_PY_DECLARE_INIT(PARAM_FARG, AREA_PARAMS_OFFSET)
|
||||
|
||||
// Parse arguments to overwrite the defaults
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(args,
|
||||
keywds,
|
||||
"|h" PARAM_PY_KWDS(AREA_PARAMS_OFFSET),
|
||||
kwlist,
|
||||
&index,
|
||||
PARAM_REF(PARAM_FARG, AREA_PARAMS_OFFSET))) {
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(
|
||||
args,
|
||||
keywds,
|
||||
"|h" PARAM_PY_KWDS(AREA_PARAMS_OFFSET),
|
||||
kwlist,
|
||||
&index,
|
||||
PARAM_REF(PARAM_FARG, AREA_PARAMS_OFFSET)
|
||||
)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PY_TRY
|
||||
{
|
||||
// Expand the variable as function call arguments
|
||||
TopoDS_Shape resultShape =
|
||||
getAreaPtr()->makeOffset(index, PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_OFFSET));
|
||||
TopoDS_Shape resultShape
|
||||
= getAreaPtr()->makeOffset(index, PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_OFFSET));
|
||||
return Py::new_reference_to(Part::shape2pyshape(resultShape));
|
||||
}
|
||||
PY_CATCH_OCC
|
||||
@@ -428,28 +435,32 @@ PyObject* AreaPy::makeOffset(PyObject* args, PyObject* keywds)
|
||||
|
||||
PyObject* AreaPy::makePocket(PyObject* args, PyObject* keywds)
|
||||
{
|
||||
static const std::array<const char*, 11> kwlist {"index",
|
||||
PARAM_FIELD_STRINGS(ARG, AREA_PARAMS_POCKET),
|
||||
nullptr};
|
||||
static const std::array<const char*, 11> kwlist {
|
||||
"index",
|
||||
PARAM_FIELD_STRINGS(ARG, AREA_PARAMS_POCKET),
|
||||
nullptr
|
||||
};
|
||||
short index = -1;
|
||||
|
||||
PARAM_PY_DECLARE_INIT(PARAM_FARG, AREA_PARAMS_POCKET)
|
||||
// Override pocket mode default
|
||||
mode = Area::PocketModeZigZagOffset;
|
||||
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(args,
|
||||
keywds,
|
||||
"|h" PARAM_PY_KWDS(AREA_PARAMS_POCKET),
|
||||
kwlist,
|
||||
&index,
|
||||
PARAM_REF(PARAM_FARG, AREA_PARAMS_POCKET))) {
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(
|
||||
args,
|
||||
keywds,
|
||||
"|h" PARAM_PY_KWDS(AREA_PARAMS_POCKET),
|
||||
kwlist,
|
||||
&index,
|
||||
PARAM_REF(PARAM_FARG, AREA_PARAMS_POCKET)
|
||||
)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PY_TRY
|
||||
{
|
||||
TopoDS_Shape resultShape =
|
||||
getAreaPtr()->makePocket(index, PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_POCKET));
|
||||
TopoDS_Shape resultShape
|
||||
= getAreaPtr()->makePocket(index, PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_POCKET));
|
||||
return Py::new_reference_to(Part::shape2pyshape(resultShape));
|
||||
}
|
||||
PY_CATCH_OCC
|
||||
@@ -461,20 +472,23 @@ PyObject* AreaPy::makeSections(PyObject* args, PyObject* keywds)
|
||||
PARAM_FIELD_STRINGS(ARG, AREA_PARAMS_SECTION_EXTRA),
|
||||
"heights",
|
||||
"plane",
|
||||
nullptr};
|
||||
nullptr
|
||||
};
|
||||
PyObject* heights = nullptr;
|
||||
PyObject* plane = nullptr;
|
||||
|
||||
PARAM_PY_DECLARE_INIT(PARAM_FARG, AREA_PARAMS_SECTION_EXTRA)
|
||||
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(args,
|
||||
keywds,
|
||||
"|" PARAM_PY_KWDS(AREA_PARAMS_SECTION_EXTRA) "OO!",
|
||||
kwlist,
|
||||
PARAM_REF(PARAM_FARG, AREA_PARAMS_SECTION_EXTRA),
|
||||
&heights,
|
||||
&(Part::TopoShapePy::Type),
|
||||
&plane)) {
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(
|
||||
args,
|
||||
keywds,
|
||||
"|" PARAM_PY_KWDS(AREA_PARAMS_SECTION_EXTRA) "OO!",
|
||||
kwlist,
|
||||
PARAM_REF(PARAM_FARG, AREA_PARAMS_SECTION_EXTRA),
|
||||
&heights,
|
||||
&(Part::TopoShapePy::Type),
|
||||
&plane
|
||||
)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -499,16 +513,16 @@ PyObject* AreaPy::makeSections(PyObject* args, PyObject* keywds)
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"heights must be of type float or list/tuple of float");
|
||||
PyErr_SetString(PyExc_TypeError, "heights must be of type float or list/tuple of float");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Area>> sections =
|
||||
getAreaPtr()->makeSections(PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_SECTION_EXTRA),
|
||||
h,
|
||||
plane ? GET_TOPOSHAPE(plane) : TopoDS_Shape());
|
||||
std::vector<std::shared_ptr<Area>> sections = getAreaPtr()->makeSections(
|
||||
PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_SECTION_EXTRA),
|
||||
h,
|
||||
plane ? GET_TOPOSHAPE(plane) : TopoDS_Shape()
|
||||
);
|
||||
|
||||
Py::List ret;
|
||||
for (auto& area : sections) {
|
||||
@@ -534,8 +548,8 @@ if (!PyObject_TypeCheck(pyBbox, &(Base::BoundBoxPy::Type))) {
|
||||
}
|
||||
const PathPy* path = static_cast<PathPy*>(pyPath);
|
||||
const Py::BoundingBox bbox(pyBbox, false);
|
||||
std::shared_ptr<Area> clearedArea =
|
||||
getAreaPtr()->getClearedArea(path->getToolpathPtr(), diameter, zmax, bbox.getValue());
|
||||
std::shared_ptr<Area> clearedArea
|
||||
= getAreaPtr()->getClearedArea(path->getToolpathPtr(), diameter, zmax, bbox.getValue());
|
||||
auto pyClearedArea = Py::asObject(new AreaPy(new Area(*clearedArea, true)));
|
||||
return Py::new_reference_to(pyClearedArea);
|
||||
}
|
||||
@@ -557,8 +571,7 @@ if (pyClearedAreas && PyObject_TypeCheck(pyClearedAreas, &PyList_Type)) {
|
||||
PyErr_SetString(PyExc_TypeError, "cleared areas must only contain AreaPy type");
|
||||
return nullptr;
|
||||
}
|
||||
clearedAreas.push_back(
|
||||
std::make_shared<Area>(*static_cast<AreaPy*>(item)->getAreaPtr(), true));
|
||||
clearedAreas.push_back(std::make_shared<Area>(*static_cast<AreaPy*>(item)->getAreaPtr(), true));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -576,8 +589,7 @@ return Py::new_reference_to(pyRestArea);
|
||||
PY_CATCH_OCC
|
||||
}
|
||||
|
||||
PyObject* AreaPy::toTopoShape(PyObject* args) {
|
||||
PY_TRY {if (!PyArg_ParseTuple(args, "")) return nullptr;
|
||||
PyObject* AreaPy::toTopoShape(PyObject* args) {PY_TRY {if (!PyArg_ParseTuple(args, "")) return nullptr;
|
||||
return Py::new_reference_to(Part::shape2pyshape(getAreaPtr()->toTopoShape()));
|
||||
}
|
||||
PY_CATCH_OCC
|
||||
@@ -590,8 +602,10 @@ PyObject* AreaPy::setDefaultParams(PyObject*, PyObject*)
|
||||
|
||||
PyObject* AreaPy::setParams(PyObject* args, PyObject* keywds)
|
||||
{
|
||||
static const std::array<const char*, 43> kwlist {PARAM_FIELD_STRINGS(NAME, AREA_PARAMS_CONF),
|
||||
nullptr};
|
||||
static const std::array<const char*, 43> kwlist {
|
||||
PARAM_FIELD_STRINGS(NAME, AREA_PARAMS_CONF),
|
||||
nullptr
|
||||
};
|
||||
|
||||
// Declare variables defined in the NAME field of the CONF parameter list
|
||||
PARAM_PY_DECLARE(PARAM_FNAME, AREA_PARAMS_CONF);
|
||||
@@ -602,11 +616,13 @@ PyObject* AreaPy::setParams(PyObject* args, PyObject* keywds)
|
||||
PARAM_FOREACH(AREA_SET, AREA_PARAMS_CONF)
|
||||
|
||||
// Parse arguments to overwrite CONF variables
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(args,
|
||||
keywds,
|
||||
"|" PARAM_PY_KWDS(AREA_PARAMS_CONF),
|
||||
kwlist,
|
||||
PARAM_REF(PARAM_FNAME, AREA_PARAMS_CONF))) {
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(
|
||||
args,
|
||||
keywds,
|
||||
"|" PARAM_PY_KWDS(AREA_PARAMS_CONF),
|
||||
kwlist,
|
||||
PARAM_REF(PARAM_FNAME, AREA_PARAMS_CONF)
|
||||
)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -103,8 +103,7 @@ std::string Command::toGCode(int precision, bool padzero) const
|
||||
}
|
||||
double scale = std::pow(10.0, precision + 1);
|
||||
std::int64_t iscale = static_cast<std::int64_t>(scale) / 10;
|
||||
for (std::map<std::string, double>::const_iterator i = Parameters.begin();
|
||||
i != Parameters.end();
|
||||
for (std::map<std::string, double>::const_iterator i = Parameters.begin(); i != Parameters.end();
|
||||
++i) {
|
||||
if (i->first == "N") {
|
||||
continue;
|
||||
@@ -284,8 +283,7 @@ Command Command::transform(const Base::Placement& other)
|
||||
plac.getRotation().getYawPitchRoll(aval, bval, cval);
|
||||
Command c = Command();
|
||||
c.Name = Name;
|
||||
for (std::map<std::string, double>::const_iterator i = Parameters.begin();
|
||||
i != Parameters.end();
|
||||
for (std::map<std::string, double>::const_iterator i = Parameters.begin(); i != Parameters.end();
|
||||
++i) {
|
||||
std::string k = i->first;
|
||||
double v = i->second;
|
||||
@@ -314,8 +312,7 @@ Command Command::transform(const Base::Placement& other)
|
||||
|
||||
void Command::scaleBy(double factor)
|
||||
{
|
||||
for (std::map<std::string, double>::const_iterator i = Parameters.begin();
|
||||
i != Parameters.end();
|
||||
for (std::map<std::string, double>::const_iterator i = Parameters.begin(); i != Parameters.end();
|
||||
++i) {
|
||||
switch (i->first[0]) {
|
||||
case 'X':
|
||||
|
||||
@@ -50,20 +50,23 @@ public:
|
||||
void Restore(Base::XMLReader& /*reader*/) override;
|
||||
|
||||
// specific methods
|
||||
Base::Placement getPlacement(const Base::Vector3d pos = Base::Vector3d())
|
||||
const; // returns a placement from the x,y,z,a,b,c parameters
|
||||
Base::Placement getPlacement(
|
||||
const Base::Vector3d pos = Base::Vector3d()
|
||||
) const; // returns a placement from the x,y,z,a,b,c parameters
|
||||
Base::Vector3d getCenter() const; // returns a 3d vector from the i,j,k parameters
|
||||
void setCenter(const Base::Vector3d&,
|
||||
bool clockwise = true); // sets the center coordinates and the command name
|
||||
std::string
|
||||
toGCode(int precision = 6,
|
||||
bool padzero = true) const; // returns a GCode string representation of the command
|
||||
void setFromGCode(
|
||||
const std::string&); // sets the parameters from the contents of the given GCode string
|
||||
void setFromPlacement(
|
||||
const Base::Placement&); // sets the parameters from the contents of the given placement
|
||||
bool
|
||||
has(const std::string&) const; // returns true if the given string exists in the parameters
|
||||
void setCenter(
|
||||
const Base::Vector3d&,
|
||||
bool clockwise = true
|
||||
); // sets the center coordinates and the command name
|
||||
std::string toGCode(
|
||||
int precision = 6,
|
||||
bool padzero = true
|
||||
) const; // returns a GCode string representation of the command
|
||||
void setFromGCode(const std::string&); // sets the parameters from the contents of the given
|
||||
// GCode string
|
||||
void setFromPlacement(const Base::Placement&); // sets the parameters from the contents of the
|
||||
// given placement
|
||||
bool has(const std::string&) const; // returns true if the given string exists in the parameters
|
||||
Command transform(const Base::Placement&); // returns a transformed copy of this command
|
||||
double getValue(const std::string& name) const; // returns the value of a given parameter
|
||||
void scaleBy(double factor); // scales the receiver - use for imperial/metric conversions
|
||||
|
||||
@@ -73,13 +73,7 @@ int CommandPy::PyInit(PyObject* args, PyObject* kwd)
|
||||
PyObject* parameters = nullptr;
|
||||
const char* name = "";
|
||||
static const std::array<const char*, 3> kwlist {"name", "parameters", nullptr};
|
||||
if (Base::Wrapped_ParseTupleAndKeywords(args,
|
||||
kwd,
|
||||
"|sO!",
|
||||
kwlist,
|
||||
&name,
|
||||
&PyDict_Type,
|
||||
¶meters)) {
|
||||
if (Base::Wrapped_ParseTupleAndKeywords(args, kwd, "|sO!", kwlist, &name, &PyDict_Type, ¶meters)) {
|
||||
std::string sname(name);
|
||||
boost::to_upper(sname);
|
||||
try {
|
||||
@@ -123,13 +117,15 @@ int CommandPy::PyInit(PyObject* args, PyObject* kwd)
|
||||
}
|
||||
PyErr_Clear(); // set by PyArg_ParseTuple()
|
||||
|
||||
if (Base::Wrapped_ParseTupleAndKeywords(args,
|
||||
kwd,
|
||||
"|sO!",
|
||||
kwlist,
|
||||
&name,
|
||||
&(Base::PlacementPy::Type),
|
||||
¶meters)) {
|
||||
if (Base::Wrapped_ParseTupleAndKeywords(
|
||||
args,
|
||||
kwd,
|
||||
"|sO!",
|
||||
kwlist,
|
||||
&name,
|
||||
&(Base::PlacementPy::Type),
|
||||
¶meters
|
||||
)) {
|
||||
std::string sname(name);
|
||||
boost::to_upper(sname);
|
||||
try {
|
||||
@@ -241,16 +237,14 @@ PyObject* CommandPy::setFromGCode(PyObject* args)
|
||||
|
||||
Py::Object CommandPy::getPlacement() const
|
||||
{
|
||||
return Py::asObject(
|
||||
new Base::PlacementPy(new Base::Placement(getCommandPtr()->getPlacement())));
|
||||
return Py::asObject(new Base::PlacementPy(new Base::Placement(getCommandPtr()->getPlacement())));
|
||||
}
|
||||
|
||||
void CommandPy::setPlacement(Py::Object arg)
|
||||
{
|
||||
Py::Type PlacementType(Base::getTypeAsObject(&(Base::PlacementPy::Type)));
|
||||
if (arg.isType(PlacementType)) {
|
||||
getCommandPtr()->setFromPlacement(
|
||||
*static_cast<Base::PlacementPy*>((*arg))->getPlacementPtr());
|
||||
getCommandPtr()->setFromPlacement(*static_cast<Base::PlacementPy*>((*arg))->getPlacementPtr());
|
||||
parameters_copy_dict.clear();
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -83,7 +83,8 @@ App::DocumentObjectExecReturn* FeatureArea::execute()
|
||||
for (std::vector<App::DocumentObject*>::iterator it = links.begin(); it != links.end(); ++it) {
|
||||
if (!(*it && (*it)->isDerivedFrom<Part::Feature>())) {
|
||||
return new App::DocumentObjectExecReturn(
|
||||
"Linked object is not a Part object (has no Shape).");
|
||||
"Linked object is not a Part object (has no Shape)."
|
||||
);
|
||||
}
|
||||
TopoDS_Shape shape = static_cast<Part::Feature*>(*it)->Shape.getShape().getShape();
|
||||
if (shape.IsNull()) {
|
||||
@@ -105,8 +106,10 @@ App::DocumentObjectExecReturn* FeatureArea::execute()
|
||||
myArea.setPlane(workPlane);
|
||||
|
||||
for (std::vector<App::DocumentObject*>::iterator it = links.begin(); it != links.end(); ++it) {
|
||||
myArea.add(static_cast<Part::Feature*>(*it)->Shape.getShape().getShape(),
|
||||
PARAM_PROP_ARGS(AREA_PARAMS_OPCODE));
|
||||
myArea.add(
|
||||
static_cast<Part::Feature*>(*it)->Shape.getShape().getShape(),
|
||||
PARAM_PROP_ARGS(AREA_PARAMS_OPCODE)
|
||||
);
|
||||
}
|
||||
|
||||
myShapes.clear();
|
||||
@@ -185,13 +188,15 @@ FeatureAreaView::FeatureAreaView()
|
||||
(0),
|
||||
"Section",
|
||||
App::Prop_None,
|
||||
"The start index of the section to show, negative value for reverse index from bottom");
|
||||
"The start index of the section to show, negative value for reverse index from bottom"
|
||||
);
|
||||
ADD_PROPERTY_TYPE(
|
||||
SectionCount,
|
||||
(1),
|
||||
"Section",
|
||||
App::Prop_None,
|
||||
"Number of sections to show, 0 to show all section starting from SectionIndex");
|
||||
"Number of sections to show, 0 to show all section starting from SectionIndex"
|
||||
);
|
||||
}
|
||||
|
||||
std::list<TopoDS_Shape> FeatureAreaView::getShapes()
|
||||
|
||||
@@ -52,30 +52,35 @@ PyObject* FeatureAreaPy::getArea(PyObject* args)
|
||||
|
||||
PyObject* FeatureAreaPy::setParams(PyObject* args, PyObject* keywds)
|
||||
{
|
||||
static const std::array<const char*, 43> kwlist {PARAM_FIELD_STRINGS(NAME, AREA_PARAMS_CONF),
|
||||
nullptr};
|
||||
static const std::array<const char*, 43> kwlist {
|
||||
PARAM_FIELD_STRINGS(NAME, AREA_PARAMS_CONF),
|
||||
nullptr
|
||||
};
|
||||
|
||||
// Declare variables defined in the NAME field of the CONF parameter list
|
||||
PARAM_PY_DECLARE(PARAM_FNAME, AREA_PARAMS_CONF);
|
||||
|
||||
FeatureArea* feature = getFeatureAreaPtr();
|
||||
|
||||
#define AREA_SET(_param) \
|
||||
PARAM_FNAME(_param) = \
|
||||
PARAM_TYPED(PARAM_PY_CAST_, _param)(feature->PARAM_FNAME(_param).getValue());
|
||||
#define AREA_SET(_param) \
|
||||
PARAM_FNAME(_param) = PARAM_TYPED(PARAM_PY_CAST_, _param)( \
|
||||
feature->PARAM_FNAME(_param).getValue() \
|
||||
);
|
||||
// populate the CONF variables with values in properties
|
||||
PARAM_FOREACH(AREA_SET, AREA_PARAMS_CONF)
|
||||
|
||||
// Parse arguments to overwrite CONF variables
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(args,
|
||||
keywds,
|
||||
"|" PARAM_PY_KWDS(AREA_PARAMS_CONF),
|
||||
kwlist,
|
||||
PARAM_REF(PARAM_FNAME, AREA_PARAMS_CONF))) {
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(
|
||||
args,
|
||||
keywds,
|
||||
"|" PARAM_PY_KWDS(AREA_PARAMS_CONF),
|
||||
kwlist,
|
||||
PARAM_REF(PARAM_FNAME, AREA_PARAMS_CONF)
|
||||
)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#define AREA_GET(_param) \
|
||||
#define AREA_GET(_param) \
|
||||
feature->PARAM_FNAME(_param).setValue(PARAM_TYPED(PARAM_CAST_PY_, _param)(PARAM_FNAME(_param)));
|
||||
// populate properties with the CONF variables
|
||||
PARAM_FOREACH(AREA_GET, AREA_PARAMS_CONF)
|
||||
@@ -98,7 +103,8 @@ void FeatureAreaPy::setWorkPlane(Py::Object obj)
|
||||
throw Py::TypeError(error);
|
||||
}
|
||||
getFeatureAreaPtr()->setWorkPlane(
|
||||
static_cast<Part::TopoShapePy*>(p)->getTopoShapePtr()->getShape());
|
||||
static_cast<Part::TopoShapePy*>(p)->getTopoShapePtr()->getShape()
|
||||
);
|
||||
}
|
||||
|
||||
PyObject* FeatureAreaPy::getCustomAttributes(const char* /*attr*/) const
|
||||
|
||||
@@ -34,11 +34,7 @@ PROPERTY_SOURCE(Path::Feature, App::GeoFeature)
|
||||
|
||||
Feature::Feature()
|
||||
{
|
||||
ADD_PROPERTY_TYPE(Path,
|
||||
(Path::Toolpath()),
|
||||
"Base",
|
||||
App::Prop_None,
|
||||
"The path data of this feature");
|
||||
ADD_PROPERTY_TYPE(Path, (Path::Toolpath()), "Base", App::Prop_None, "The path data of this feature");
|
||||
}
|
||||
|
||||
Feature::~Feature()
|
||||
|
||||
@@ -36,11 +36,13 @@ PROPERTY_SOURCE(Path::FeatureCompound, Path::Feature)
|
||||
FeatureCompound::FeatureCompound()
|
||||
{
|
||||
ADD_PROPERTY_TYPE(Group, (nullptr), "Base", Prop_None, "Ordered list of paths to combine");
|
||||
ADD_PROPERTY_TYPE(UsePlacements,
|
||||
(false),
|
||||
"Base",
|
||||
Prop_None,
|
||||
"Specifies if the placements of children must be computed");
|
||||
ADD_PROPERTY_TYPE(
|
||||
UsePlacements,
|
||||
(false),
|
||||
"Base",
|
||||
Prop_None,
|
||||
"Specifies if the placements of children must be computed"
|
||||
);
|
||||
}
|
||||
|
||||
FeatureCompound::~FeatureCompound()
|
||||
@@ -53,11 +55,10 @@ App::DocumentObjectExecReturn* FeatureCompound::execute()
|
||||
|
||||
for (std::vector<DocumentObject*>::const_iterator it = Paths.begin(); it != Paths.end(); ++it) {
|
||||
if ((*it)->isDerivedFrom<Path::Feature>()) {
|
||||
const std::vector<Command*>& cmds =
|
||||
static_cast<Path::Feature*>(*it)->Path.getValue().getCommands();
|
||||
const std::vector<Command*>& cmds
|
||||
= static_cast<Path::Feature*>(*it)->Path.getValue().getCommands();
|
||||
const Base::Placement pl = static_cast<Path::Feature*>(*it)->Placement.getValue();
|
||||
for (std::vector<Command*>::const_iterator it2 = cmds.begin(); it2 != cmds.end();
|
||||
++it2) {
|
||||
for (std::vector<Command*>::const_iterator it2 = cmds.begin(); it2 != cmds.end(); ++it2) {
|
||||
if (UsePlacements.getValue()) {
|
||||
result.addCommand((*it2)->transform(pl));
|
||||
}
|
||||
|
||||
@@ -44,15 +44,15 @@ PyObject* FeaturePathCompoundPy::addObject(PyObject* args)
|
||||
}
|
||||
|
||||
DocumentObjectPy* docObj = static_cast<DocumentObjectPy*>(object);
|
||||
if (!docObj->getDocumentObjectPtr()
|
||||
|| !docObj->getDocumentObjectPtr()->isAttachedToDocument()) {
|
||||
if (!docObj->getDocumentObjectPtr() || !docObj->getDocumentObjectPtr()->isAttachedToDocument()) {
|
||||
PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot add an invalid object");
|
||||
return nullptr;
|
||||
}
|
||||
if (docObj->getDocumentObjectPtr()->getDocument()
|
||||
!= getFeaturePathCompoundPtr()->getDocument()) {
|
||||
PyErr_SetString(Base::PyExc_FC_GeneralError,
|
||||
"Cannot add an object from another document to this group");
|
||||
if (docObj->getDocumentObjectPtr()->getDocument() != getFeaturePathCompoundPtr()->getDocument()) {
|
||||
PyErr_SetString(
|
||||
Base::PyExc_FC_GeneralError,
|
||||
"Cannot add an object from another document to this group"
|
||||
);
|
||||
return nullptr;
|
||||
}
|
||||
if (docObj->getDocumentObjectPtr() == this->getFeaturePathCompoundPtr()) {
|
||||
@@ -93,15 +93,15 @@ PyObject* FeaturePathCompoundPy::removeObject(PyObject* args)
|
||||
}
|
||||
|
||||
DocumentObjectPy* docObj = static_cast<DocumentObjectPy*>(object);
|
||||
if (!docObj->getDocumentObjectPtr()
|
||||
|| !docObj->getDocumentObjectPtr()->isAttachedToDocument()) {
|
||||
if (!docObj->getDocumentObjectPtr() || !docObj->getDocumentObjectPtr()->isAttachedToDocument()) {
|
||||
PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot remove an invalid object");
|
||||
return nullptr;
|
||||
}
|
||||
if (docObj->getDocumentObjectPtr()->getDocument()
|
||||
!= getFeaturePathCompoundPtr()->getDocument()) {
|
||||
PyErr_SetString(Base::PyExc_FC_GeneralError,
|
||||
"Cannot remove an object from another document from this group");
|
||||
if (docObj->getDocumentObjectPtr()->getDocument() != getFeaturePathCompoundPtr()->getDocument()) {
|
||||
PyErr_SetString(
|
||||
Base::PyExc_FC_GeneralError,
|
||||
"Cannot remove an object from another document from this group"
|
||||
);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,11 +38,7 @@ PARAM_ENUM_STRING_DECLARE(static const char* Enums, AREA_PARAMS_PATH)
|
||||
FeatureShape::FeatureShape()
|
||||
{
|
||||
ADD_PROPERTY(Sources, (nullptr));
|
||||
ADD_PROPERTY_TYPE(StartPoint,
|
||||
(Base::Vector3d()),
|
||||
"Path",
|
||||
App::Prop_None,
|
||||
"Feed start position");
|
||||
ADD_PROPERTY_TYPE(StartPoint, (Base::Vector3d()), "Path", App::Prop_None, "Feed start position");
|
||||
ADD_PROPERTY_TYPE(UseStartPoint, (false), "Path", App::Prop_None, "Enable feed start position");
|
||||
PARAM_PROP_ADD("Path", AREA_PARAMS_PATH);
|
||||
PARAM_PROP_SET_ENUM(Enums, AREA_PARAMS_PATH);
|
||||
@@ -75,11 +71,13 @@ App::DocumentObjectExecReturn* FeatureShape::execute()
|
||||
shapes.push_back(shape);
|
||||
}
|
||||
|
||||
Area::toPath(path,
|
||||
shapes,
|
||||
UseStartPoint.getValue() ? &pstart : nullptr,
|
||||
nullptr,
|
||||
PARAM_PROP_ARGS(AREA_PARAMS_PATH));
|
||||
Area::toPath(
|
||||
path,
|
||||
shapes,
|
||||
UseStartPoint.getValue() ? &pstart : nullptr,
|
||||
nullptr,
|
||||
PARAM_PROP_ARGS(AREA_PARAMS_PATH)
|
||||
);
|
||||
|
||||
Path.setValue(path);
|
||||
return App::DocumentObject::StdReturn;
|
||||
|
||||
@@ -355,12 +355,12 @@
|
||||
#define PARAM_DECLARE_INIT(_src, _seq) BOOST_PP_SEQ_FOR_EACH(PARAM_DECLARE_INIT_, _src, _seq)
|
||||
|
||||
|
||||
#define PARAM_ENUM_DECLARE_enum_(_1, _name, _i, _elem) \
|
||||
#define PARAM_ENUM_DECLARE_enum_(_1, _name, _i, _elem) \
|
||||
BOOST_PP_COMMA_IF(_i) BOOST_PP_CAT(_name, _elem)
|
||||
|
||||
#define PARAM_ENUM_DECLARE_enum(_param) \
|
||||
enum \
|
||||
{ \
|
||||
#define PARAM_ENUM_DECLARE_enum(_param) \
|
||||
enum \
|
||||
{ \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_ENUM_DECLARE_enum_, PARAM_FNAME(_param), PARAM_FSEQ(_param)) \
|
||||
};
|
||||
|
||||
@@ -396,23 +396,22 @@
|
||||
#define PARAM_ENUM_CONVERT_enum(...)
|
||||
#define PARAM_ENUM_CONVERT_enum2 PARAM_ENUM_CONVERT_SINGLE
|
||||
|
||||
#define PARAM_ENUM_CONVERT_enum_(_dst, _name, _prefix, _elem) \
|
||||
case BOOST_PP_CAT(_name, _elem): \
|
||||
_dst = BOOST_PP_CAT(_prefix, _elem); \
|
||||
#define PARAM_ENUM_CONVERT_enum_(_dst, _name, _prefix, _elem) \
|
||||
case BOOST_PP_CAT(_name, _elem): \
|
||||
_dst = BOOST_PP_CAT(_prefix, _elem); \
|
||||
break;
|
||||
|
||||
#define PARAM_ENUM_CONVERT__(_1, _args, _i, _elem) \
|
||||
PARAM_ENUM_CONVERT_enum_(BOOST_PP_TUPLE_ELEM(0, _args), \
|
||||
BOOST_PP_TUPLE_ELEM(1, _args), \
|
||||
BOOST_PP_TUPLE_ELEM(2, _args), \
|
||||
_elem);
|
||||
#define PARAM_ENUM_CONVERT__(_1, _args, _i, _elem) \
|
||||
PARAM_ENUM_CONVERT_enum_( \
|
||||
BOOST_PP_TUPLE_ELEM(0, _args), \
|
||||
BOOST_PP_TUPLE_ELEM(1, _args), \
|
||||
BOOST_PP_TUPLE_ELEM(2, _args), \
|
||||
_elem \
|
||||
);
|
||||
|
||||
#define PARAM_ENUM_CONVERT_(_1, _args, _param) \
|
||||
PARAM_TYPED(PARAM_ENUM_CONVERT_, _param) \
|
||||
(BOOST_PP_TUPLE_ELEM(0, _args), \
|
||||
BOOST_PP_TUPLE_ELEM(1, _args), \
|
||||
BOOST_PP_TUPLE_ELEM(2, _args), \
|
||||
_param)
|
||||
#define PARAM_ENUM_CONVERT_(_1, _args, _param) \
|
||||
PARAM_TYPED(PARAM_ENUM_CONVERT_, _param) \
|
||||
(BOOST_PP_TUPLE_ELEM(0, _args), BOOST_PP_TUPLE_ELEM(1, _args), BOOST_PP_TUPLE_ELEM(2, _args), _param)
|
||||
|
||||
/** Convert single enum parameter value into user defined enum type
|
||||
*
|
||||
@@ -421,18 +420,20 @@
|
||||
* for more detail. Make sure the outer parenthesis of \c _param is stripped,
|
||||
* i.e. not double but single parenthesis
|
||||
*/
|
||||
#define PARAM_ENUM_CONVERT_SINGLE(_src, _dst, _default, _param) \
|
||||
PARAM_FENUM_TYPE(_param) _dst(_param); \
|
||||
switch (_src(_param)) { \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_ENUM_CONVERT__, \
|
||||
(_dst(_param), PARAM_FNAME(_param), PARAM_FENUM_PREFIX(_param)), \
|
||||
PARAM_FSEQ(_param)) \
|
||||
default: \
|
||||
_default(_param); \
|
||||
#define PARAM_ENUM_CONVERT_SINGLE(_src, _dst, _default, _param) \
|
||||
PARAM_FENUM_TYPE(_param) _dst(_param); \
|
||||
switch (_src(_param)) { \
|
||||
BOOST_PP_SEQ_FOR_EACH_I( \
|
||||
PARAM_ENUM_CONVERT__, \
|
||||
(_dst(_param), PARAM_FNAME(_param), PARAM_FENUM_PREFIX(_param)), \
|
||||
PARAM_FSEQ(_param) \
|
||||
) \
|
||||
default: \
|
||||
_default(_param); \
|
||||
}
|
||||
|
||||
/** Default handling in #PARAM_ENUM_CONVERT and #PARAM_ENUM_CHECK*/
|
||||
#define PARAM_ENUM_EXCEPT(_param) \
|
||||
#define PARAM_ENUM_EXCEPT(_param) \
|
||||
throw Base::ValueError("invalid value for enum " PARAM_FNAME_STR(_param))
|
||||
|
||||
/** @} */
|
||||
@@ -500,7 +501,7 @@
|
||||
* The above code assumes you've already defined \a Test1 and \a Test2 some
|
||||
* where as the source variable.
|
||||
*/
|
||||
#define PARAM_ENUM_CONVERT(_src, _dst, _default, _seq) \
|
||||
#define PARAM_ENUM_CONVERT(_src, _dst, _default, _seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_ENUM_CONVERT_, (_src, _dst, _default), _seq)
|
||||
|
||||
|
||||
@@ -511,19 +512,19 @@
|
||||
#define PARAM_ENUM_CHECK_enum PARAM_ENUM_CHECK_SINGLE
|
||||
#define PARAM_ENUM_CHECK_enum2 PARAM_ENUM_CHECK_SINGLE
|
||||
|
||||
#define PARAM_ENUM_CHECK_enum_(_1, _name, _i, _elem) \
|
||||
case BOOST_PP_CAT(_name, _elem): \
|
||||
#define PARAM_ENUM_CHECK_enum_(_1, _name, _i, _elem) \
|
||||
case BOOST_PP_CAT(_name, _elem): \
|
||||
break;
|
||||
|
||||
#define PARAM_ENUM_CHECK_(_1, _args, _param) \
|
||||
PARAM_TYPED(PARAM_ENUM_CHECK_, _param) \
|
||||
#define PARAM_ENUM_CHECK_(_1, _args, _param) \
|
||||
PARAM_TYPED(PARAM_ENUM_CHECK_, _param) \
|
||||
(BOOST_PP_TUPLE_ELEM(0, _args), BOOST_PP_TUPLE_ELEM(1, _args), _param)
|
||||
|
||||
#define PARAM_ENUM_CHECK_SINGLE(_src, _default, _param) \
|
||||
switch (_src(_param)) { \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_ENUM_CHECK_enum_, PARAM_FNAME(_param), PARAM_FSEQ(_param)) \
|
||||
default: \
|
||||
_default(_param); \
|
||||
#define PARAM_ENUM_CHECK_SINGLE(_src, _default, _param) \
|
||||
switch (_src(_param)) { \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_ENUM_CHECK_enum_, PARAM_FNAME(_param), PARAM_FSEQ(_param)) \
|
||||
default: \
|
||||
_default(_param); \
|
||||
}
|
||||
|
||||
/* Validate enum type parameters
|
||||
@@ -545,7 +546,7 @@
|
||||
*
|
||||
* \arg \c _seq: Parameter sequence
|
||||
*/
|
||||
#define PARAM_ENUM_CHECK(_src, _default, _seq) \
|
||||
#define PARAM_ENUM_CHECK(_src, _default, _seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_ENUM_CHECK_, (_src, _default), _seq)
|
||||
|
||||
|
||||
@@ -556,11 +557,11 @@
|
||||
#define PARAM_ENUM_STRING_DECLARE_enum2 PARAM_ENUM_STRING_DECLARE_enum
|
||||
|
||||
/** Helper for #PARAM_ENUM_STRING_DECLARE */
|
||||
#define PARAM_ENUM_STRING_DECLARE_enum(_prefix, _param) \
|
||||
#define PARAM_ENUM_STRING_DECLARE_enum(_prefix, _param) \
|
||||
BOOST_PP_CAT(_prefix, PARAM_FNAME(_param))[] = {PARAM_FSEQ_STR(_param), NULL};
|
||||
|
||||
/** Helper for #PARAM_ENUM_STRING_DECLARE */
|
||||
#define PARAM_ENUM_STRING_DECLARE_(_1, _prefix, _param) \
|
||||
#define PARAM_ENUM_STRING_DECLARE_(_1, _prefix, _param) \
|
||||
PARAM_TYPED(PARAM_ENUM_STRING_DECLARE_, _param)(_prefix, _param)
|
||||
|
||||
/** Make \c enum string list
|
||||
@@ -575,7 +576,7 @@
|
||||
* PARAM_ENUM_STRING_DECLARE(static const char *Enum, MyParamsSeq)
|
||||
* \ingroup ParamEnumHelper
|
||||
*/
|
||||
#define PARAM_ENUM_STRING_DECLARE(_prefix, _seq) \
|
||||
#define PARAM_ENUM_STRING_DECLARE(_prefix, _seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_ENUM_STRING_DECLARE_, _prefix, _seq)
|
||||
|
||||
|
||||
@@ -597,8 +598,8 @@
|
||||
|
||||
|
||||
/** Helper for #PARAM_OP */
|
||||
#define PARAM_OP_(_, _args, _param) \
|
||||
BOOST_PP_TUPLE_ELEM(0, _args) \
|
||||
#define PARAM_OP_(_, _args, _param) \
|
||||
BOOST_PP_TUPLE_ELEM(0, _args) \
|
||||
(_param) BOOST_PP_TUPLE_ELEM(1, _args) BOOST_PP_TUPLE_ELEM(2, _args)(_param);
|
||||
|
||||
/** Perform operation on two instance of each parameter in a sequence
|
||||
@@ -622,7 +623,7 @@
|
||||
|
||||
|
||||
/** Helper for #PARAM_ARGS_DEF */
|
||||
#define PARAM_ARGS_DEF_(_, _src, _i, _param) \
|
||||
#define PARAM_ARGS_DEF_(_, _src, _i, _param) \
|
||||
BOOST_PP_COMMA_IF(_i) PARAM_TYPE(_param) _src(_param) = PARAM_FDEF(_param)
|
||||
|
||||
/** Declare the parameters as function argument list with defaults.
|
||||
@@ -670,13 +671,13 @@
|
||||
#define PARAM_PY_DOC_enum_(_i, _elem) BOOST_PP_IF(_i, ",", " ") #_i "=" #_elem
|
||||
|
||||
/** Generate doc for an enum parameter */
|
||||
#define PARAM_PY_DOC_enum(_field, _param) \
|
||||
"\n* " PARAM_FIELD_STR(_field, _param) "(" PARAM_FDEF_STR(_param) "):" PARAM_FOREACH_I( \
|
||||
PARAM_PY_DOC_enum_, \
|
||||
PARAM_FSEQ(_param)) ". " PARAM_FDOC(_param) "\n"
|
||||
#define PARAM_PY_DOC_enum(_field, _param) \
|
||||
"\n* " PARAM_FIELD_STR(_field, _param) "(" PARAM_FDEF_STR( \
|
||||
_param \
|
||||
) "):" PARAM_FOREACH_I(PARAM_PY_DOC_enum_, PARAM_FSEQ(_param)) ". " PARAM_FDOC(_param) "\n"
|
||||
|
||||
/* Generate doc for other type of parameter */
|
||||
#define PARAM_PY_DOC_short(_field, _param) \
|
||||
#define PARAM_PY_DOC_short(_field, _param) \
|
||||
"\n* " PARAM_FIELD_STR(_field, _param) "(" PARAM_FDEF_STR(_param) "): " PARAM_FDOC(_param) "\n"
|
||||
#define PARAM_PY_DOC_long PARAM_PY_DOC_short
|
||||
#define PARAM_PY_DOC_double PARAM_PY_DOC_short
|
||||
@@ -692,7 +693,7 @@
|
||||
|
||||
|
||||
/** Helper for #PARAM_PY_ARGS_DOC */
|
||||
#define PARAM_PY_ARGS_DOC_(_, _field, _i, _param) \
|
||||
#define PARAM_PY_ARGS_DOC_(_, _field, _i, _param) \
|
||||
BOOST_PP_IF(_i, ", ", " ") PARAM_FIELD_STR(_field, _param) "=" PARAM_FDEF_STR(_param)
|
||||
|
||||
/** Generate argument list string
|
||||
@@ -741,7 +742,7 @@
|
||||
|
||||
|
||||
/** Helper for #PARAM_PY_FIELDS */
|
||||
#define PARAM_PY_FIELDS_(_1, _src, _i, _param) \
|
||||
#define PARAM_PY_FIELDS_(_1, _src, _i, _param) \
|
||||
BOOST_PP_COMMA_IF(_i) PARAM_TYPED(PARAM_CAST_PY_, _param)(_src(_param))
|
||||
|
||||
/** Expand to a comma separated list of the given field in the sequence
|
||||
@@ -756,13 +757,13 @@
|
||||
|
||||
|
||||
/** Helper for #PARAM_FIELD_STRINGS */
|
||||
#define PARAM_FIELD_STRINGS_(_1, _field, _i, _param) \
|
||||
#define PARAM_FIELD_STRINGS_(_1, _field, _i, _param) \
|
||||
BOOST_PP_COMMA_IF(_i) PARAM_FIELD_STR(_field, _param)
|
||||
|
||||
/** Expand to a list of stringified fields
|
||||
* \ingroup ParamStringizer ParamPy
|
||||
*/
|
||||
#define PARAM_FIELD_STRINGS(_field, _seq) \
|
||||
#define PARAM_FIELD_STRINGS(_field, _seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_FIELD_STRINGS_, _field, _seq)
|
||||
|
||||
|
||||
@@ -804,8 +805,8 @@
|
||||
#define PARAM_PY_INIT_enum2(_v) _v
|
||||
|
||||
/** Helper for #PARAM_PY_DECLARE_INIT */
|
||||
#define PARAM_PY_DECLARE_INIT_(_1, _src, _param) \
|
||||
PARAM_TYPED(PARAM_PY_TYPE_, _param) \
|
||||
#define PARAM_PY_DECLARE_INIT_(_1, _src, _param) \
|
||||
PARAM_TYPED(PARAM_PY_TYPE_, _param) \
|
||||
_src(_param) = PARAM_TYPED(PARAM_PY_INIT_, _param)(PARAM_FDEF(_param));
|
||||
|
||||
/** Declare field variables of Python c type with initialization to default
|
||||
@@ -845,10 +846,12 @@
|
||||
#define PARAM_PY_STR(_field, _param) PyUnicode_FromString(PARAM_FIELD_STR(_field, _param))
|
||||
|
||||
/** Helper for #PARAM_PY_DICT_SET_VALUE */
|
||||
#define PARAM_PY_DICT_SET_VALUE_(_1, _args, _param) \
|
||||
PyDict_SetItem(BOOST_PP_TUPLE_ELEM(0, _args), \
|
||||
PARAM_PY_STR(BOOST_PP_TUPLE_ELEM(1, _args), _param), \
|
||||
PARAM_TYPED(PARAM_CAST_PYOBJ_, _param)(BOOST_PP_TUPLE_ELEM(2, _args)(_param)));
|
||||
#define PARAM_PY_DICT_SET_VALUE_(_1, _args, _param) \
|
||||
PyDict_SetItem( \
|
||||
BOOST_PP_TUPLE_ELEM(0, _args), \
|
||||
PARAM_PY_STR(BOOST_PP_TUPLE_ELEM(1, _args), _param), \
|
||||
PARAM_TYPED(PARAM_CAST_PYOBJ_, _param)(BOOST_PP_TUPLE_ELEM(2, _args)(_param)) \
|
||||
);
|
||||
|
||||
/** Populate a Python dict with a structure variable
|
||||
*
|
||||
@@ -865,17 +868,17 @@
|
||||
* \endcode
|
||||
* \ingroup ParamPy
|
||||
*/
|
||||
#define PARAM_PY_DICT_SET_VALUE(_dict, _field, _src, _seq) \
|
||||
#define PARAM_PY_DICT_SET_VALUE(_dict, _field, _src, _seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DICT_SET_VALUE_, (_dict, _field, _src), _seq)
|
||||
|
||||
|
||||
#define PARAM_PY_DICT_DOC_enum_(_i, _elem) BOOST_PP_IF(_i, ",", " ") #_i "=" #_elem
|
||||
|
||||
/** Generate doc for an enum parameter */
|
||||
#define PARAM_PY_DICT_DOC_enum(_param) \
|
||||
"(" PARAM_FDEF_STR(_param) ") - " PARAM_FOREACH_I( \
|
||||
PARAM_PY_DOC_enum_, \
|
||||
PARAM_FSEQ(_param)) ".\n" PARAM_FDOC(_param) "\n"
|
||||
#define PARAM_PY_DICT_DOC_enum(_param) \
|
||||
"(" PARAM_FDEF_STR( \
|
||||
_param \
|
||||
) ") - " PARAM_FOREACH_I(PARAM_PY_DOC_enum_, PARAM_FSEQ(_param)) ".\n" PARAM_FDOC(_param) "\n"
|
||||
|
||||
/* Generate doc for other type of parameter */
|
||||
#define PARAM_PY_DICT_DOC_(_param) "(" PARAM_FDEF_STR(_param) ") - " PARAM_FDOC(_param) "\n"
|
||||
@@ -888,10 +891,12 @@
|
||||
#define PARAM_PY_DICT_DOC_enum2 PARAM_PY_DICT_DOC_enum
|
||||
|
||||
/** Helper for #PARAM_PY_DICT_SET_DOC */
|
||||
#define PARAM_PY_DICT_SET_DOC_(_1, _args, _param) \
|
||||
PyDict_SetItem(BOOST_PP_TUPLE_ELEM(0, _args), \
|
||||
PARAM_PY_STR(BOOST_PP_TUPLE_ELEM(1, _args), _param), \
|
||||
PyUnicode_FromString(PARAM_TYPED(PARAM_PY_DICT_DOC_, _param)(_param)));
|
||||
#define PARAM_PY_DICT_SET_DOC_(_1, _args, _param) \
|
||||
PyDict_SetItem( \
|
||||
BOOST_PP_TUPLE_ELEM(0, _args), \
|
||||
PARAM_PY_STR(BOOST_PP_TUPLE_ELEM(1, _args), _param), \
|
||||
PyUnicode_FromString(PARAM_TYPED(PARAM_PY_DICT_DOC_, _param)(_param)) \
|
||||
);
|
||||
|
||||
/** Populate a Python dict with the doc field of the parameter sequence
|
||||
*
|
||||
@@ -906,7 +911,7 @@
|
||||
* \endcode
|
||||
* \ingroup ParamDoc
|
||||
*/
|
||||
#define PARAM_PY_DICT_SET_DOC(_dict, _field, _seq) \
|
||||
#define PARAM_PY_DICT_SET_DOC(_dict, _field, _seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DICT_SET_DOC_, (_dict, _field), _seq)
|
||||
|
||||
|
||||
@@ -931,22 +936,25 @@
|
||||
#define PARAM_PROP_DECLARE(_seq) PARAM_FOREACH(PARAM_PROP_DECLARE_, _seq)
|
||||
|
||||
/** Replace FreeCAD #ADD_PROPERTY_TYPE to fix singifying macro */
|
||||
#define PARAM_ADD_PROPERTY_TYPE(_prop_, _defaultval_, _group_, _type_, _Docu_) \
|
||||
do { \
|
||||
this->_prop_.setValue _defaultval_; \
|
||||
this->_prop_.setContainer(this); \
|
||||
propertyData.addProperty( \
|
||||
static_cast<App::PropertyContainer*>(this), \
|
||||
BOOST_PP_STRINGIZE(_prop_), &this->_prop_, (_group_), (_type_), (_Docu_)); \
|
||||
#define PARAM_ADD_PROPERTY_TYPE(_prop_, _defaultval_, _group_, _type_, _Docu_) \
|
||||
do { \
|
||||
this->_prop_.setValue _defaultval_; \
|
||||
this->_prop_.setContainer(this); \
|
||||
propertyData.addProperty( \
|
||||
static_cast<App::PropertyContainer*>(this), \
|
||||
BOOST_PP_STRINGIZE(_prop_), &this->_prop_, (_group_), (_type_), (_Docu_) \
|
||||
); \
|
||||
} while (0)
|
||||
|
||||
/** Generic property adding */
|
||||
#define PARAM_PROP_ADD_(_group, _param) \
|
||||
PARAM_ADD_PROPERTY_TYPE(PARAM_FNAME(_param), \
|
||||
(PARAM_FDEF(_param)), \
|
||||
_group, \
|
||||
App::Prop_None, \
|
||||
PARAM_FDOC(_param));
|
||||
#define PARAM_PROP_ADD_(_group, _param) \
|
||||
PARAM_ADD_PROPERTY_TYPE( \
|
||||
PARAM_FNAME(_param), \
|
||||
(PARAM_FDEF(_param)), \
|
||||
_group, \
|
||||
App::Prop_None, \
|
||||
PARAM_FDOC(_param) \
|
||||
);
|
||||
|
||||
#define PARAM_PROP_ADD_short PARAM_PROP_ADD_
|
||||
#define PARAM_PROP_ADD_long PARAM_PROP_ADD_
|
||||
@@ -955,15 +963,17 @@
|
||||
#define PARAM_PROP_ADD_enum2 PARAM_PROP_ADD_enum
|
||||
|
||||
/** Add \c enum type parameter as property */
|
||||
#define PARAM_PROP_ADD_enum(_group, _param) \
|
||||
PARAM_ADD_PROPERTY_TYPE(PARAM_FNAME(_param), \
|
||||
((long)PARAM_FDEF(_param)), \
|
||||
_group, \
|
||||
App::Prop_None, \
|
||||
PARAM_FDOC(_param));
|
||||
#define PARAM_PROP_ADD_enum(_group, _param) \
|
||||
PARAM_ADD_PROPERTY_TYPE( \
|
||||
PARAM_FNAME(_param), \
|
||||
((long)PARAM_FDEF(_param)), \
|
||||
_group, \
|
||||
App::Prop_None, \
|
||||
PARAM_FDOC(_param) \
|
||||
);
|
||||
|
||||
/** Helper for #PARAM_PROP_ADD */
|
||||
#define PARAM_PROP_ADD_TYPED(_1, _group, _i, _param) \
|
||||
#define PARAM_PROP_ADD_TYPED(_1, _group, _i, _param) \
|
||||
PARAM_TYPED(PARAM_PROP_ADD_, _param)(_group, _param)
|
||||
|
||||
/** Add FreeCAD properties
|
||||
@@ -978,17 +988,17 @@
|
||||
#define PARAM_PROP_SET_ENUM_enum2 PARAM_PROP_SET_ENUM_enum
|
||||
|
||||
/** Setup \c enum type parameter */
|
||||
#define PARAM_PROP_SET_ENUM_enum(_prefix, _param) \
|
||||
#define PARAM_PROP_SET_ENUM_enum(_prefix, _param) \
|
||||
PARAM_FNAME(_param).setEnums(BOOST_PP_CAT(_prefix, PARAM_FNAME(_param)));
|
||||
|
||||
/** Helper for #PARAM_PROP_SET_ENUM */
|
||||
#define PARAM_PROP_SET_ENUM_TYPED(_1, _prefix, _param) \
|
||||
#define PARAM_PROP_SET_ENUM_TYPED(_1, _prefix, _param) \
|
||||
PARAM_TYPED(PARAM_PROP_SET_ENUM_, _param)(_prefix, _param)
|
||||
|
||||
/* Setup the \c enum string list for \c enum type properties
|
||||
* \ingroup ParamProperty
|
||||
*/
|
||||
#define PARAM_PROP_SET_ENUM(_prefix, _seq) \
|
||||
#define PARAM_PROP_SET_ENUM(_prefix, _seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_PROP_SET_ENUM_TYPED, _prefix, _seq)
|
||||
|
||||
|
||||
@@ -1007,8 +1017,8 @@
|
||||
|
||||
|
||||
/** Helper for #PARAM_PROP_TOUCHED */
|
||||
#define PARAM_PROP_TOUCHED_(_param) \
|
||||
if (PARAM_FNAME(_param).isTouched()) \
|
||||
#define PARAM_PROP_TOUCHED_(_param) \
|
||||
if (PARAM_FNAME(_param).isTouched()) \
|
||||
return 1;
|
||||
|
||||
/** Returns 1 if any properties is touched
|
||||
|
||||
@@ -152,7 +152,8 @@ double Toolpath::getCycleTime(double hFeed, double vFeed, double hRapid, double
|
||||
// check the feedrates are set
|
||||
if ((hFeed == 0) || (vFeed == 0)) {
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/CAM");
|
||||
"User parameter:BaseApp/Preferences/Mod/CAM"
|
||||
);
|
||||
if (!hGrp->GetBool("WarningsSuppressAllSpeeds", true)) {
|
||||
Base::Console().warning("Feed Rate Error: Check Tool Controllers have Feed Rates");
|
||||
}
|
||||
@@ -222,31 +223,37 @@ public:
|
||||
BoundBoxSegmentVisitor()
|
||||
{}
|
||||
|
||||
void g0(int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts) override
|
||||
void g0(
|
||||
int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts
|
||||
) override
|
||||
{
|
||||
(void)id;
|
||||
processPt(last);
|
||||
processPts(pts);
|
||||
processPt(next);
|
||||
}
|
||||
void g1(int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts) override
|
||||
void g1(
|
||||
int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts
|
||||
) override
|
||||
{
|
||||
(void)id;
|
||||
processPt(last);
|
||||
processPts(pts);
|
||||
processPt(next);
|
||||
}
|
||||
void g23(int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts,
|
||||
const Base::Vector3d& center) override
|
||||
void g23(
|
||||
int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts,
|
||||
const Base::Vector3d& center
|
||||
) override
|
||||
{
|
||||
(void)id;
|
||||
(void)center;
|
||||
@@ -254,12 +261,14 @@ public:
|
||||
processPts(pts);
|
||||
processPt(next);
|
||||
}
|
||||
void g8x(int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts,
|
||||
const std::deque<Base::Vector3d>& p,
|
||||
const std::deque<Base::Vector3d>& q) override
|
||||
void g8x(
|
||||
int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts,
|
||||
const std::deque<Base::Vector3d>& p,
|
||||
const std::deque<Base::Vector3d>& q
|
||||
) override
|
||||
{
|
||||
(void)id;
|
||||
(void)q; // always within the bounds of p
|
||||
@@ -304,8 +313,7 @@ Base::BoundBox3d Toolpath::getBoundBox() const
|
||||
return visitor.bb;
|
||||
}
|
||||
|
||||
static void
|
||||
bulkAddCommand(const std::string& gcodestr, std::vector<Command*>& commands, bool& inches)
|
||||
static void bulkAddCommand(const std::string& gcodestr, std::vector<Command*>& commands, bool& inches)
|
||||
{
|
||||
Command* cmd = new Command();
|
||||
cmd->setFromGCode(gcodestr);
|
||||
|
||||
@@ -62,9 +62,8 @@ public:
|
||||
double getLength(); // return the Length (mm) of the Path
|
||||
double getCycleTime(double, double, double, double); // return the Cycle Time (s) of the Path
|
||||
void recalculate(); // recalculates the points
|
||||
void
|
||||
setFromGCode(const std::string); // sets the path from the contents of the given GCode string
|
||||
std::string toGCode() const; // gets a gcode string representation from the Path
|
||||
void setFromGCode(const std::string); // sets the path from the contents of the given GCode string
|
||||
std::string toGCode() const; // gets a gcode string representation from the Path
|
||||
Base::BoundBox3d getBoundBox() const;
|
||||
|
||||
// shortcut functions
|
||||
|
||||
@@ -62,8 +62,7 @@ int PathPy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
||||
Py::List list(pcObj);
|
||||
for (Py::List::iterator it = list.begin(); it != list.end(); ++it) {
|
||||
if (PyObject_TypeCheck((*it).ptr(), &(Path::CommandPy::Type))) {
|
||||
Path::Command& cmd =
|
||||
*static_cast<Path::CommandPy*>((*it).ptr())->getCommandPtr();
|
||||
Path::Command& cmd = *static_cast<Path::CommandPy*>((*it).ptr())->getCommandPtr();
|
||||
getToolpathPtr()->addCommand(cmd);
|
||||
}
|
||||
else {
|
||||
@@ -91,7 +90,8 @@ Py::List PathPy::getCommands() const
|
||||
Py::List list;
|
||||
for (unsigned int i = 0; i < getToolpathPtr()->getSize(); i++) {
|
||||
list.append(
|
||||
Py::asObject(new Path::CommandPy(new Path::Command(getToolpathPtr()->getCommand(i)))));
|
||||
Py::asObject(new Path::CommandPy(new Path::Command(getToolpathPtr()->getCommand(i))))
|
||||
);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -36,9 +36,11 @@
|
||||
namespace Path
|
||||
{
|
||||
|
||||
Base::Vector3d compensateRotation(const Base::Vector3d& pt,
|
||||
const Base::Rotation& rot,
|
||||
const Base::Vector3d& center)
|
||||
Base::Vector3d compensateRotation(
|
||||
const Base::Vector3d& pt,
|
||||
const Base::Rotation& rot,
|
||||
const Base::Vector3d& center
|
||||
)
|
||||
{
|
||||
Base::Vector3d ptRotated;
|
||||
rot.multVec(pt - center, ptRotated);
|
||||
@@ -60,10 +62,12 @@ void PathSegmentVisitor::setup(const Base::Vector3d& last)
|
||||
(void)last;
|
||||
}
|
||||
|
||||
void PathSegmentVisitor::g0(int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts)
|
||||
void PathSegmentVisitor::g0(
|
||||
int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts
|
||||
)
|
||||
{
|
||||
(void)id;
|
||||
(void)last;
|
||||
@@ -71,10 +75,12 @@ void PathSegmentVisitor::g0(int id,
|
||||
(void)pts;
|
||||
}
|
||||
|
||||
void PathSegmentVisitor::g1(int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts)
|
||||
void PathSegmentVisitor::g1(
|
||||
int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts
|
||||
)
|
||||
{
|
||||
(void)id;
|
||||
(void)last;
|
||||
@@ -82,11 +88,13 @@ void PathSegmentVisitor::g1(int id,
|
||||
(void)pts;
|
||||
}
|
||||
|
||||
void PathSegmentVisitor::g23(int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts,
|
||||
const Base::Vector3d& center)
|
||||
void PathSegmentVisitor::g23(
|
||||
int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts,
|
||||
const Base::Vector3d& center
|
||||
)
|
||||
{
|
||||
(void)id;
|
||||
(void)last;
|
||||
@@ -95,12 +103,14 @@ void PathSegmentVisitor::g23(int id,
|
||||
(void)center;
|
||||
}
|
||||
|
||||
void PathSegmentVisitor::g8x(int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts,
|
||||
const std::deque<Base::Vector3d>& p,
|
||||
const std::deque<Base::Vector3d>& q)
|
||||
void PathSegmentVisitor::g8x(
|
||||
int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts,
|
||||
const std::deque<Base::Vector3d>& p,
|
||||
const std::deque<Base::Vector3d>& q
|
||||
)
|
||||
{
|
||||
(void)id;
|
||||
(void)last;
|
||||
@@ -129,7 +139,8 @@ void PathSegmentWalker::walk(PathSegmentVisitor& cb, const Base::Vector3d& start
|
||||
}
|
||||
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Part");
|
||||
"User parameter:BaseApp/Preferences/Mod/Part"
|
||||
);
|
||||
float deviation = hGrp->GetFloat("MeshDeviation", 0.2);
|
||||
|
||||
Base::Vector3d rotCenter = tp.getCenter();
|
||||
@@ -186,8 +197,10 @@ void PathSegmentWalker::walk(PathSegmentVisitor& cb, const Base::Vector3d& start
|
||||
if ((name == "G0") || (name == "G00") || (name == "G1") || (name == "G01")) {
|
||||
// straight line
|
||||
if (nrot != lrot) {
|
||||
double amax = std::max(fmod(fabs(a - A), 360),
|
||||
std::max(fmod(fabs(b - B), 360), fmod(fabs(c - C), 360)));
|
||||
double amax = std::max(
|
||||
fmod(fabs(a - A), 360),
|
||||
std::max(fmod(fabs(b - B), 360), fmod(fabs(c - C), 360))
|
||||
);
|
||||
double angle = Base::toRadians(amax);
|
||||
int segments = std::max(ARC_MIN_SEGMENTS, 3.0 / (deviation / angle));
|
||||
|
||||
@@ -262,14 +275,15 @@ void PathSegmentWalker::walk(PathSegmentVisitor& cb, const Base::Vector3d& start
|
||||
angle = std::numbers::pi * 2;
|
||||
}
|
||||
|
||||
double amax = std::max(fmod(fabs(a - A), 360),
|
||||
std::max(fmod(fabs(b - B), 360), fmod(fabs(c - C), 360)));
|
||||
double amax = std::max(
|
||||
fmod(fabs(a - A), 360),
|
||||
std::max(fmod(fabs(b - B), 360), fmod(fabs(c - C), 360))
|
||||
);
|
||||
|
||||
int segments = std::max(
|
||||
ARC_MIN_SEGMENTS,
|
||||
3.0
|
||||
/ (deviation
|
||||
/ std::max(angle, amax))); // we use a rather simple rule here, provisorily
|
||||
3.0 / (deviation / std::max(angle, amax))
|
||||
); // we use a rather simple rule here, provisorily
|
||||
double dZ = (next.*pz - last.*pz) / segments; // How far each segment will helix in Z
|
||||
|
||||
double dangle = angle / segments;
|
||||
@@ -329,8 +343,10 @@ void PathSegmentWalker::walk(PathSegmentVisitor& cb, const Base::Vector3d& start
|
||||
p1.*pz = last.*pz;
|
||||
|
||||
if (nrot != lrot) {
|
||||
double amax = std::max(fmod(fabs(a - A), 360),
|
||||
std::max(fmod(fabs(b - B), 360), fmod(fabs(c - C), 360)));
|
||||
double amax = std::max(
|
||||
fmod(fabs(a - A), 360),
|
||||
std::max(fmod(fabs(b - B), 360), fmod(fabs(c - C), 360))
|
||||
);
|
||||
double angle = Base::toRadians(amax);
|
||||
int segments = std::max(ARC_MIN_SEGMENTS, 3.0 / (deviation / angle));
|
||||
|
||||
|
||||
@@ -44,25 +44,33 @@ public:
|
||||
|
||||
virtual void setup(const Base::Vector3d& last);
|
||||
|
||||
virtual void g0(int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts);
|
||||
virtual void g1(int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts);
|
||||
virtual void g23(int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts,
|
||||
const Base::Vector3d& center);
|
||||
virtual void g8x(int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts,
|
||||
const std::deque<Base::Vector3d>& p,
|
||||
const std::deque<Base::Vector3d>& q);
|
||||
virtual void g0(
|
||||
int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts
|
||||
);
|
||||
virtual void g1(
|
||||
int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts
|
||||
);
|
||||
virtual void g23(
|
||||
int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts,
|
||||
const Base::Vector3d& center
|
||||
);
|
||||
virtual void g8x(
|
||||
int id,
|
||||
const Base::Vector3d& last,
|
||||
const Base::Vector3d& next,
|
||||
const std::deque<Base::Vector3d>& pts,
|
||||
const std::deque<Base::Vector3d>& p,
|
||||
const std::deque<Base::Vector3d>& q
|
||||
);
|
||||
virtual void g38(int id, const Base::Vector3d& last, const Base::Vector3d& next);
|
||||
};
|
||||
|
||||
|
||||
@@ -112,8 +112,9 @@ void Voronoi::diagram_type::reIndex()
|
||||
}
|
||||
}
|
||||
|
||||
Voronoi::point_type
|
||||
Voronoi::diagram_type::retrievePoint(const Voronoi::diagram_type::cell_type* cell) const
|
||||
Voronoi::point_type Voronoi::diagram_type::retrievePoint(
|
||||
const Voronoi::diagram_type::cell_type* cell
|
||||
) const
|
||||
{
|
||||
Voronoi::diagram_type::cell_type::source_index_type index = cell->source_index();
|
||||
Voronoi::diagram_type::cell_type::source_category_type category = cell->source_category();
|
||||
@@ -129,11 +130,11 @@ Voronoi::diagram_type::retrievePoint(const Voronoi::diagram_type::cell_type* cel
|
||||
}
|
||||
}
|
||||
|
||||
Voronoi::segment_type
|
||||
Voronoi::diagram_type::retrieveSegment(const Voronoi::diagram_type::cell_type* cell) const
|
||||
Voronoi::segment_type Voronoi::diagram_type::retrieveSegment(
|
||||
const Voronoi::diagram_type::cell_type* cell
|
||||
) const
|
||||
{
|
||||
Voronoi::diagram_type::cell_type::source_index_type index =
|
||||
cell->source_index() - points.size();
|
||||
Voronoi::diagram_type::cell_type::source_index_type index = cell->source_index() - points.size();
|
||||
return segments[index];
|
||||
}
|
||||
|
||||
@@ -195,11 +196,13 @@ long Voronoi::numVertices() const
|
||||
void Voronoi::construct()
|
||||
{
|
||||
vd->clear();
|
||||
construct_voronoi(vd->points.begin(),
|
||||
vd->points.end(),
|
||||
vd->segments.begin(),
|
||||
vd->segments.end(),
|
||||
static_cast<voronoi_diagram_type*>(vd));
|
||||
construct_voronoi(
|
||||
vd->points.begin(),
|
||||
vd->points.end(),
|
||||
vd->segments.begin(),
|
||||
vd->segments.end(),
|
||||
static_cast<voronoi_diagram_type*>(vd)
|
||||
);
|
||||
vd->reIndex();
|
||||
}
|
||||
|
||||
@@ -225,8 +228,7 @@ void Voronoi::colorExterior(const Voronoi::diagram_type::edge_type* edge, std::s
|
||||
|
||||
void Voronoi::colorExterior(Voronoi::color_type color)
|
||||
{
|
||||
for (diagram_type::const_edge_iterator it = vd->edges().begin(); it != vd->edges().end();
|
||||
++it) {
|
||||
for (diagram_type::const_edge_iterator it = vd->edges().begin(); it != vd->edges().end(); ++it) {
|
||||
if (it->is_infinite()) {
|
||||
colorExterior(&(*it), color);
|
||||
}
|
||||
@@ -235,8 +237,7 @@ void Voronoi::colorExterior(Voronoi::color_type color)
|
||||
|
||||
void Voronoi::colorTwins(Voronoi::color_type color)
|
||||
{
|
||||
for (diagram_type::const_edge_iterator it = vd->edges().begin(); it != vd->edges().end();
|
||||
++it) {
|
||||
for (diagram_type::const_edge_iterator it = vd->edges().begin(); it != vd->edges().end(); ++it) {
|
||||
if (!it->color()) {
|
||||
auto twin = it->twin();
|
||||
if (!twin->color()) {
|
||||
@@ -248,8 +249,9 @@ void Voronoi::colorTwins(Voronoi::color_type color)
|
||||
|
||||
double Voronoi::diagram_type::angleOfSegment(int i, Voronoi::diagram_type::angle_map_t* angle) const
|
||||
{
|
||||
Voronoi::diagram_type::angle_map_t::const_iterator a =
|
||||
angle ? angle->find(i) : Voronoi::diagram_type::angle_map_t::const_iterator();
|
||||
Voronoi::diagram_type::angle_map_t::const_iterator a = angle
|
||||
? angle->find(i)
|
||||
: Voronoi::diagram_type::angle_map_t::const_iterator();
|
||||
if (!angle || a == angle->end()) {
|
||||
Voronoi::point_type p0 = low(segments[i]);
|
||||
Voronoi::point_type p1 = high(segments[i]);
|
||||
@@ -294,8 +296,7 @@ void Voronoi::colorColinear(Voronoi::color_type color, double degree)
|
||||
Voronoi::diagram_type::angle_map_t angle;
|
||||
int psize = vd->points.size();
|
||||
|
||||
for (diagram_type::const_edge_iterator it = vd->edges().begin(); it != vd->edges().end();
|
||||
++it) {
|
||||
for (diagram_type::const_edge_iterator it = vd->edges().begin(); it != vd->edges().end(); ++it) {
|
||||
int i0 = it->cell()->source_index() - psize;
|
||||
int i1 = it->twin()->cell()->source_index() - psize;
|
||||
if (it->color() == 0 && it->cell()->contains_segment()
|
||||
|
||||
@@ -78,8 +78,10 @@ PyObject* VoronoiCellPy::richCompare(PyObject* lhs, PyObject* rhs, int op)
|
||||
return cmp;
|
||||
}
|
||||
|
||||
const Voronoi::voronoi_diagram_type::cell_type* getCellFromPy(VoronoiCellPy* c,
|
||||
bool throwIfNotBound = true)
|
||||
const Voronoi::voronoi_diagram_type::cell_type* getCellFromPy(
|
||||
VoronoiCellPy* c,
|
||||
bool throwIfNotBound = true
|
||||
)
|
||||
{
|
||||
auto self = c->getVoronoiCellPtr();
|
||||
if (self->isBound()) {
|
||||
|
||||
@@ -49,8 +49,10 @@ Voronoi::point_type pointFromVertex(const Voronoi::vertex_type v)
|
||||
return pt;
|
||||
}
|
||||
|
||||
Voronoi::point_type orthognalProjection(const Voronoi::point_type& point,
|
||||
const Voronoi::segment_type& segment)
|
||||
Voronoi::point_type orthognalProjection(
|
||||
const Voronoi::point_type& point,
|
||||
const Voronoi::segment_type& segment
|
||||
)
|
||||
{
|
||||
// move segment so it goes through the origin (s)
|
||||
Voronoi::point_type offset;
|
||||
@@ -124,10 +126,12 @@ double signedDistanceBetween(const pt0_type& p0, const pt1_type& p1, double scal
|
||||
}
|
||||
|
||||
|
||||
void addDistanceBetween(const Voronoi::diagram_type::vertex_type* v0,
|
||||
const Voronoi::point_type& p1,
|
||||
Py::List* list,
|
||||
double scale)
|
||||
void addDistanceBetween(
|
||||
const Voronoi::diagram_type::vertex_type* v0,
|
||||
const Voronoi::point_type& p1,
|
||||
Py::List* list,
|
||||
double scale
|
||||
)
|
||||
{
|
||||
if (v0) {
|
||||
list->append(Py::Float(distanceBetween(*v0, p1, scale)));
|
||||
@@ -138,10 +142,12 @@ void addDistanceBetween(const Voronoi::diagram_type::vertex_type* v0,
|
||||
}
|
||||
}
|
||||
|
||||
void addProjectedDistanceBetween(const Voronoi::diagram_type::vertex_type* v0,
|
||||
const Voronoi::segment_type& segment,
|
||||
Py::List* list,
|
||||
double scale)
|
||||
void addProjectedDistanceBetween(
|
||||
const Voronoi::diagram_type::vertex_type* v0,
|
||||
const Voronoi::segment_type& segment,
|
||||
Py::List* list,
|
||||
double scale
|
||||
)
|
||||
{
|
||||
if (v0) {
|
||||
Voronoi::point_type p0;
|
||||
@@ -158,10 +164,7 @@ void addProjectedDistanceBetween(const Voronoi::diagram_type::vertex_type* v0,
|
||||
}
|
||||
}
|
||||
|
||||
bool addDistancesToPoint(const VoronoiEdge* edge,
|
||||
Voronoi::point_type p,
|
||||
Py::List* list,
|
||||
double scale)
|
||||
bool addDistancesToPoint(const VoronoiEdge* edge, Voronoi::point_type p, Py::List* list, double scale)
|
||||
{
|
||||
addDistanceBetween(edge->ptr->vertex0(), p, list, scale);
|
||||
addDistanceBetween(edge->ptr->vertex1(), p, list, scale);
|
||||
@@ -190,9 +193,7 @@ bool pointsMatch(const Voronoi::point_type& p0, const Voronoi::point_type& p1, d
|
||||
return 1e-6 > distanceBetween(p0, p1, scale);
|
||||
}
|
||||
|
||||
bool isPointOnSegment(const Voronoi::point_type& point,
|
||||
const Voronoi::segment_type& segment,
|
||||
double scale)
|
||||
bool isPointOnSegment(const Voronoi::point_type& point, const Voronoi::segment_type& segment, double scale)
|
||||
{
|
||||
return pointsMatch(point, low(segment), scale) || pointsMatch(point, high(segment), scale);
|
||||
}
|
||||
@@ -286,8 +287,10 @@ PyObject* VoronoiEdgePy::richCompare(PyObject* lhs, PyObject* rhs, int op)
|
||||
return cmp;
|
||||
}
|
||||
|
||||
const Voronoi::voronoi_diagram_type::edge_type* getEdgeFromPy(VoronoiEdgePy* e,
|
||||
bool throwIfNotBound = true)
|
||||
const Voronoi::voronoi_diagram_type::edge_type* getEdgeFromPy(
|
||||
VoronoiEdgePy* e,
|
||||
bool throwIfNotBound = true
|
||||
)
|
||||
{
|
||||
auto self = e->getVoronoiEdgePtr();
|
||||
if (self->isBound()) {
|
||||
|
||||
@@ -176,11 +176,13 @@ using coordinate_map_t = std::map<int32_t, std::set<int32_t>>;
|
||||
|
||||
#define VORONOI_USE_EXTERIOR_CACHE 1
|
||||
|
||||
static bool callbackWithVertex(Voronoi::diagram_type* dia,
|
||||
PyObject* callback,
|
||||
const Voronoi::diagram_type::vertex_type* v,
|
||||
bool& bail,
|
||||
exterior_map_t& cache)
|
||||
static bool callbackWithVertex(
|
||||
Voronoi::diagram_type* dia,
|
||||
PyObject* callback,
|
||||
const Voronoi::diagram_type::vertex_type* v,
|
||||
bool& bail,
|
||||
exterior_map_t& cache
|
||||
)
|
||||
{
|
||||
bool rc = false;
|
||||
if (!bail && v->color() == 0) {
|
||||
@@ -275,8 +277,10 @@ PyObject* VoronoiPy::colorColinear(PyObject* args)
|
||||
Voronoi::color_type color = 0;
|
||||
double degree = 10.;
|
||||
if (!PyArg_ParseTuple(args, "k|d", &color, °ree)) {
|
||||
throw Py::RuntimeError("colorColinear requires an integer (color) and optionally a "
|
||||
"derivation in degrees argument (default 10)");
|
||||
throw Py::RuntimeError(
|
||||
"colorColinear requires an integer (color) and optionally a "
|
||||
"derivation in degrees argument (default 10)"
|
||||
);
|
||||
}
|
||||
getVoronoiPtr()->colorColinear(color, degree);
|
||||
|
||||
@@ -306,8 +310,7 @@ PyObject* VoronoiPy::getPoints(PyObject* args) const
|
||||
Voronoi* vo = getVoronoiPtr();
|
||||
Py::List list;
|
||||
for (auto it = vo->vd->points.begin(); it != vo->vd->points.end(); ++it) {
|
||||
list.append(
|
||||
Py::asObject(new Base::VectorPy(new Base::Vector3d(vo->vd->scaledVector(*it, z)))));
|
||||
list.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(vo->vd->scaledVector(*it, z)))));
|
||||
}
|
||||
return Py::new_reference_to(list);
|
||||
}
|
||||
|
||||
@@ -79,8 +79,10 @@ PyObject* VoronoiVertexPy::richCompare(PyObject* lhs, PyObject* rhs, int op)
|
||||
return cmp;
|
||||
}
|
||||
|
||||
const Voronoi::voronoi_diagram_type::vertex_type* getVertexFromPy(VoronoiVertexPy* v,
|
||||
bool throwIfNotBound = true)
|
||||
const Voronoi::voronoi_diagram_type::vertex_type* getVertexFromPy(
|
||||
VoronoiVertexPy* v,
|
||||
bool throwIfNotBound = true
|
||||
)
|
||||
{
|
||||
auto self = v->getVoronoiVertexPtr();
|
||||
if (self->isBound()) {
|
||||
@@ -155,9 +157,9 @@ PyObject* VoronoiVertexPy::toPoint(PyObject* args) const
|
||||
}
|
||||
VoronoiVertex* v = getVoronoiVertexPtr();
|
||||
if (v->isBound()) {
|
||||
return new Base::VectorPy(new Base::Vector3d(v->ptr->x() / v->dia->getScale(),
|
||||
v->ptr->y() / v->dia->getScale(),
|
||||
z));
|
||||
return new Base::VectorPy(
|
||||
new Base::Vector3d(v->ptr->x() / v->dia->getScale(), v->ptr->y() / v->dia->getScale(), z)
|
||||
);
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
Reference in New Issue
Block a user