From 14c98d252e25ea28edea029034009bc05982c962 Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Wed, 1 Feb 2017 12:02:01 +0800 Subject: [PATCH] Path.Area: added python static method setDefaultParams() set/getDefaultParams controls the default parameters used when creating Path.Area object. It also has extra parameter to control Path.Area log level. --- src/Mod/Path/App/Area.cpp | 34 +++++++- src/Mod/Path/App/Area.h | 50 +++++++----- src/Mod/Path/App/AreaParams.h | 11 +++ src/Mod/Path/App/AreaPy.xml | 14 +++- src/Mod/Path/App/AreaPyImp.cpp | 142 ++++++++++++++++++++++----------- 5 files changed, 180 insertions(+), 71 deletions(-) diff --git a/src/Mod/Path/App/Area.cpp b/src/Mod/Path/App/Area.cpp index 794f51059..6e7a6364e 100644 --- a/src/Mod/Path/App/Area.cpp +++ b/src/Mod/Path/App/Area.cpp @@ -111,7 +111,8 @@ TYPESYSTEM_SOURCE(Path::Area, Base::BaseClass); bool Area::s_aborting; Area::Area(const AreaParams *params) -:myHaveFace(false) +:myParams(s_params) +,myHaveFace(false) ,myHaveSolid(false) ,myShapeDone(false) { @@ -731,10 +732,7 @@ void Area::build() { return; } -#ifdef AREA_TRACE_ENABLE TIME_INIT(t); -#endif - getPlane(); try { @@ -1832,3 +1830,31 @@ void Area::toPath(Toolpath &path, const std::list &shapes, } } } + +void Area::abort(bool aborting) { + s_aborting = aborting; +} + +bool Area::aborting() { + return s_aborting; +} + +AreaStaticParams::AreaStaticParams() + :PARAM_INIT(PARAM_FNAME,AREA_PARAMS_EXTRA_CONF) +{} + +AreaStaticParams Area::s_params; + +void Area::setDefaultParams(const AreaStaticParams ¶ms){ + s_params = params; +} + +const AreaStaticParams &Area::getDefaultParams() { + return s_params; +} + +#define AREA_LOG_CHECK_DEFINE(_1,_2,_elem) \ +bool Area::BOOST_PP_CAT(_elem,Enabled)() {\ + return s_params.LogLevel >= BOOST_PP_CAT(LogLevel,_elem);\ +} +BOOST_PP_SEQ_FOR_EACH(AREA_LOG_CHECK_DEFINE,_,AREA_PARAM_LOG_LEVEL) diff --git a/src/Mod/Path/App/Area.h b/src/Mod/Path/App/Area.h index 06a71a972..336562c59 100644 --- a/src/Mod/Path/App/Area.h +++ b/src/Mod/Path/App/Area.h @@ -37,14 +37,14 @@ #include "Path.h" #include "AreaParams.h" -// #define AREA_TRACE_ENABLE - #define _AREA_LOG(_l,_msg) do {\ - std::stringstream str;\ - str << "Path.Area: " << _msg;\ - Base::Console()._l("%s\n",str.str().c_str());\ + if(Area::_l##Enabled()){\ + std::stringstream str;\ + str << "Path.Area: " << _msg;\ + Base::Console()._l("%s\n",str.str().c_str());\ + }\ qApp->sendPostedEvents();\ - if(Area::aborted()) {\ + if(Area::aborting()) {\ Area::abort(false);\ throw Base::AbortException("operation aborted");\ }\ @@ -52,13 +52,13 @@ #define AREA_LOG(_msg) _AREA_LOG(Log,_msg) #define AREA_WARN(_msg) _AREA_LOG(Warning,_msg) +#define AREA_ERR(_msg) _AREA_LOG(Error,_msg) #define AREA_PT(_pt) '('<<(_pt).X()<<", " << (_pt).Y()<<", " << (_pt).Z()<<')' #define AREA_PT2(_pt) '('<<(_pt).x<<", " << (_pt).y<<')' -#ifdef AREA_TRACE_ENABLE -# define AREA_TRACE(_msg) AREA_LOG('('<<__LINE__<<"): " <<_msg) -#else -# define AREA_TRACE(...) do{}while(0) -#endif + +#define AREA_TRACE(_msg) do{\ + if(Area::TraceEnabled()) AREA_LOG('('<<__LINE__<<"): " <<_msg);\ +}while(0) #define AREA_TIME_ENABLE @@ -145,6 +145,12 @@ struct PathExport AreaParams: CAreaParams { AreaParams(); }; +struct PathExport AreaStaticParams: AreaParams { + PARAM_DECLARE(PARAM_FNAME,AREA_PARAMS_EXTRA_CONF); + + AreaStaticParams(); +}; + /** libarea configurator * * It is kind of troublesome with the fact that libarea uses static variables to @@ -199,7 +205,9 @@ protected: bool myHaveSolid; bool myShapeDone; int mySkippedShapes; + static bool s_aborting; + static AreaStaticParams s_params; /** Called internally to combine children shapes for further processing */ void build(); @@ -437,15 +445,19 @@ public: const AreaParams *params=NULL, const gp_Pnt *pstart=NULL, gp_Pnt *pend=NULL, PARAM_ARGS_DEF(PARAM_FARG,AREA_PARAMS_PATH)); - static void abort(bool aborting) { - s_aborting = aborting; - } - - static bool aborted() { - return s_aborting; - } - PARAM_ENUM_DECLARE(AREA_PARAMS_PATH) + + static void abort(bool aborting); + static bool aborting(); + + static void setDefaultParams(const AreaStaticParams ¶ms); + static const AreaStaticParams &getDefaultParams(); + +#define AREA_LOG_CHECK_DECLARE(_1,_2,_elem) \ + static bool BOOST_PP_CAT(_elem,Enabled)(); + BOOST_PP_SEQ_FOR_EACH(AREA_LOG_CHECK_DECLARE,_,AREA_PARAM_LOG_LEVEL) + + PARAM_ENUM_DECLARE(AREA_PARAMS_LOG_LEVEL) }; } //namespace Path diff --git a/src/Mod/Path/App/AreaParams.h b/src/Mod/Path/App/AreaParams.h index c59fa34a1..8dc4be2d2 100644 --- a/src/Mod/Path/App/AreaParams.h +++ b/src/Mod/Path/App/AreaParams.h @@ -209,4 +209,15 @@ AREA_PARAMS_CONF \ AREA_PARAMS_OPCODE +#define AREA_PARAM_LOG_LEVEL (Error)(Warning)(Log)(Trace) +#define AREA_PARAMS_LOG_LEVEL \ + ((enum, log_level, LogLevel, 1, "Area log level", AREA_PARAM_LOG_LEVEL)) + +#define AREA_PARAMS_EXTRA_CONF \ + AREA_PARAMS_LOG_LEVEL + +#define AREA_PARAMS_STATIC_CONF \ + AREA_PARAMS_CONF \ + AREA_PARAMS_EXTRA_CONF + #endif //PATH_AreaParam_H diff --git a/src/Mod/Path/App/AreaPy.xml b/src/Mod/Path/App/AreaPy.xml index 622dbb04a..ad4a0a306 100644 --- a/src/Mod/Path/App/AreaPy.xml +++ b/src/Mod/Path/App/AreaPy.xml @@ -60,6 +60,16 @@ same algorithm + + + + + + + + + + getParamsDesc(as_string=True): Returns a list of supported parameters and their descriptions.\n @@ -79,9 +89,7 @@ same algorithm - abort(aborting=True): Static method to abort any ongoing operation\n -To ensure no stray abortion is left in the previous operaion, it is advised to manually -clear the aborting flag by calling abort(False) before starting a new operation. + diff --git a/src/Mod/Path/App/AreaPyImp.cpp b/src/Mod/Path/App/AreaPyImp.cpp index 29db5f485..3fb7f1089 100644 --- a/src/Mod/Path/App/AreaPyImp.cpp +++ b/src/Mod/Path/App/AreaPyImp.cpp @@ -32,25 +32,68 @@ #include "AreaPy.cpp" -struct AreaDoc { - const char *name; - const char *doc; -}; +static PyObject * areaAbort(PyObject *, PyObject *args, PyObject *kwd) { + static char *kwlist[] = {"aborting", NULL}; + PyObject *pObj = Py_True; + if (!PyArg_ParseTupleAndKeywords(args,kwd,"|O",kwlist,&pObj)) + return 0; + Area::abort(PyObject_IsTrue(pObj)); + return Py_None; +} -/** Generate doc string from parameter definitions - * It will generate doc string and replace the one generated from xml - * */ -static const AreaDoc myDocs[] = { +static PyObject * areaSetParams(PyObject *, PyObject *args, PyObject *kwd) { + + static char *kwlist[] = {PARAM_FIELD_STRINGS(NAME,AREA_PARAMS_STATIC_CONF),NULL}; + + //Declare variables defined in the NAME field of the CONF parameter list + PARAM_PY_DECLARE(PARAM_FNAME,AREA_PARAMS_STATIC_CONF); + + AreaStaticParams params = Area::getDefaultParams(); + +#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 (!PyArg_ParseTupleAndKeywords(args, kwd, + "|" PARAM_PY_KWDS(AREA_PARAMS_STATIC_CONF), kwlist, + PARAM_REF(PARAM_FNAME,AREA_PARAMS_STATIC_CONF))) + return 0; + +#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) + + Area::setDefaultParams(params); + return Py_None; +} + +static PyObject* areaGetParams(PyObject *, PyObject *args) { + if (!PyArg_ParseTuple(args, "")) + return 0; + + const AreaStaticParams ¶ms = Area::getDefaultParams(); + + PyObject *dict = PyDict_New(); +#define AREA_SRC(_param) params.PARAM_FNAME(_param) + PARAM_PY_DICT_SET_VALUE(dict,NAME,AREA_SRC,AREA_PARAMS_STATIC_CONF) + return dict; +} + + +static const PyMethodDef areaOverrides[] = { { - "setParams", + "setParams",NULL,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) }, { - "add", - + "add",NULL,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) @@ -62,24 +105,21 @@ static const AreaDoc myDocs[] = { }, { - "makeOffset", - + "makeOffset",NULL,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), }, { - "makePocket", - + "makePocket",NULL,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), }, { - "makeSections", - + "makeSections",NULL,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) @@ -89,37 +129,46 @@ static const AreaDoc myDocs[] = { "of this Area is used.", }, { - "sortWires", - + "sortWires",NULL,0, "sortWires(index=-1, count=0, start=Vector(), allow_break=False, " PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_SORT) "):\n" - "Returns a tuple (wires,end): sorted wires with minimized travel distance, and the endpoint of the wires.\n" + "Returns a tuple (wires,end): sorted wires with minimized travel distance, and the endpoint\n" + "of the wires.\n" "\n* index (-1): the index of the section. -1 means all sections. No effect on planar shape.\n" "\n* count (0): the number of sections to return. <=0 means all sections starting from index.\n" "\n* start (Vector()): a vector specifies the start point.\n" PARAM_PY_DOC(ARG,AREA_PARAMS_SORT), }, + { + "setDefaultParams",(PyCFunction)areaSetParams, METH_VARARGS|METH_KEYWORDS|METH_STATIC, + "setDefaultParams(" PARAM_PY_ARGS_DOC(NAME,AREA_PARAMS_EXTRA_CONF) ", key=value...):\n" + "Static method to set the default parameters of all following Path.Area, plus the following\n" + "additional parameters.\n" + PARAM_PY_DOC(NAME,AREA_PARAMS_EXTRA_CONF) + }, + { + "getDefaultParams",(PyCFunction)areaGetParams, METH_VARARGS|METH_STATIC, + "getDefaultParams(): Static method to return the current default parameters." + }, + { + "abort",(PyCFunction)areaAbort, METH_VARARGS|METH_KEYWORDS|METH_STATIC, + "abort(aborting=True): Static method to abort any ongoing operation\n" + "\nTo ensure no stray abortion is left in the previous operaion, it is advised to manually clear\n" + "the aborting flag by calling abort(False) before starting a new operation.", + }, }; -static PyObject * abortArea(PyObject *, PyObject *args, PyObject *kwd) { - static char *kwlist[] = {"aborting", NULL}; - PyObject *pObj = Py_True; - if (!PyArg_ParseTupleAndKeywords(args,kwd,"|O",kwlist,&pObj)) - return 0; - Area::abort(PyObject_IsTrue(pObj)); - return Py_None; -} - struct AreaPyModifier { AreaPyModifier() { - for(PyMethodDef &method : Path::AreaPy::Methods) { + for(auto &method : Path::AreaPy::Methods) { if(!method.ml_name) continue; - if(std::strcmp(method.ml_name,"abort")==0) { - method.ml_meth = (PyCFunction)abortArea; - method.ml_flags |= METH_STATIC; - } - for(const AreaDoc &doc : myDocs) { - if(std::strcmp(method.ml_name,doc.name)==0) { - method.ml_doc = doc.doc; + for(auto &entry : areaOverrides) { + if(std::strcmp(method.ml_name,entry.ml_name)==0) { + if(entry.ml_doc) + method.ml_doc = entry.ml_doc; + if(entry.ml_meth) + method.ml_meth = entry.ml_meth; + if(entry.ml_flags) + method.ml_flags = entry.ml_flags; break; } } @@ -344,6 +393,11 @@ PyObject* AreaPy::makeSections(PyObject *args, PyObject *keywds) return Py::new_reference_to(ret); } +PyObject* AreaPy::setDefaultParams(PyObject *, PyObject *) +{ + return 0; +} + PyObject* AreaPy::setParams(PyObject *args, PyObject *keywds) { static char *kwlist[] = {PARAM_FIELD_STRINGS(NAME,AREA_PARAMS_CONF),NULL}; @@ -353,9 +407,6 @@ PyObject* AreaPy::setParams(PyObject *args, PyObject *keywds) AreaParams params = getAreaPtr()->getParams(); -#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_CONF) @@ -365,9 +416,6 @@ PyObject* AreaPy::setParams(PyObject *args, PyObject *keywds) PARAM_REF(PARAM_FNAME,AREA_PARAMS_CONF))) return 0; -#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_CONF) @@ -384,11 +432,15 @@ PyObject* AreaPy::getParams(PyObject *args) const AreaParams ¶ms =getAreaPtr()->getParams(); PyObject *dict = PyDict_New(); -#define AREA_SRC(_param) params.PARAM_FNAME(_param) PARAM_PY_DICT_SET_VALUE(dict,NAME,AREA_SRC,AREA_PARAMS_CONF) return dict; } +PyObject* AreaPy::getDefaultParams(PyObject *) +{ + return 0; +} + PyObject* AreaPy::abort(PyObject *, PyObject *) { return 0; }