CAM: Add annotations support to Command constructor and Python bindings
This commit introduces support for passing an 'annotations' dictionary
to the Command class constructor and its Python bindings. The annotations
dictionary can contain string or numeric values for each key, allowing for
richer metadata on CAM commands. Each annotation must be provided as a
key-value pair within a dictionary.
Examples:
cmd = Command("G1", {"X": 10.0, "Y": 5.0}, {"note": "Rapid move"})
cmd = Command("G2", {"X": 20.0, "Y": 15.0}, {"priority": 1})
cmd = Command("G3", {"X": 30.0, "Y": 25.0}, {"note": "Arc move", "speed": 1500})
cmd = Command("G0", {"X": 0.0, "Y": 0.0}, {})
cmd = Command("G0", {"X": 0.0, "Y": 0.0})
cmd = Command("G1", {"X": 10.0, "Y": 5.0}, annotations={"note": "Rapid move"})
src/Mod/CAM/App/Command.cpp:
- Added new Command constructor accepting annotations
src/Mod/CAM/App/Command.h:
- Declared new Command constructor with annotations parameter
src/Mod/CAM/App/Command.pyi:
- Updated docstring to describe annotations argument
src/Mod/CAM/App/CommandPyImp.cpp:
- Extended Python init to parse and set annotations dictionary
This commit is contained in:
@@ -47,6 +47,16 @@ Command::Command(const char* name, const std::map<std::string, double>& paramete
|
||||
, Annotations()
|
||||
{}
|
||||
|
||||
Command::Command(
|
||||
const char* name,
|
||||
const std::map<std::string, double>& parameters,
|
||||
const std::map<std::string, std::variant<std::string, double>>& annotations
|
||||
)
|
||||
: Name(name)
|
||||
, Parameters(parameters)
|
||||
, Annotations(annotations)
|
||||
{}
|
||||
|
||||
Command::Command()
|
||||
: Annotations()
|
||||
{}
|
||||
|
||||
@@ -44,6 +44,11 @@ public:
|
||||
// constructors
|
||||
Command();
|
||||
Command(const char* name, const std::map<std::string, double>& parameters);
|
||||
Command(
|
||||
const char* name,
|
||||
const std::map<std::string, double>& parameters,
|
||||
const std::map<std::string, std::variant<std::string, double>>& annotations
|
||||
);
|
||||
~Command() override;
|
||||
// from base class
|
||||
unsigned int getMemSize() const override;
|
||||
|
||||
@@ -13,10 +13,11 @@ from Base.Placement import Placement
|
||||
@class_declarations("mutable Py::Dict parameters_copy_dict;")
|
||||
class Command(Persistence):
|
||||
"""
|
||||
Command([name],[parameters]): Represents a basic Gcode command
|
||||
Command([name],[parameters],[annotations]): Represents a basic Gcode command
|
||||
name (optional) is the name of the command, ex. G1
|
||||
parameters (optional) is a dictionary containing string:number
|
||||
pairs, or a placement, or a vector
|
||||
annotations (optional) is a dictionary containing string:string or string:number pairs
|
||||
"""
|
||||
|
||||
@constmethod
|
||||
|
||||
@@ -71,9 +71,20 @@ PyObject* CommandPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Pytho
|
||||
int CommandPy::PyInit(PyObject* args, PyObject* kwd)
|
||||
{
|
||||
PyObject* parameters = nullptr;
|
||||
PyObject* annotations = 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)) {
|
||||
static const std::array<const char*, 4> kwlist {"name", "parameters", "annotations", nullptr};
|
||||
if (Base::Wrapped_ParseTupleAndKeywords(
|
||||
args,
|
||||
kwd,
|
||||
"|sO!O!",
|
||||
kwlist,
|
||||
&name,
|
||||
&PyDict_Type,
|
||||
¶meters,
|
||||
&PyDict_Type,
|
||||
&annotations
|
||||
)) {
|
||||
std::string sname(name);
|
||||
boost::to_upper(sname);
|
||||
try {
|
||||
@@ -112,16 +123,54 @@ int CommandPy::PyInit(PyObject* args, PyObject* kwd)
|
||||
}
|
||||
getCommandPtr()->Parameters[ckey] = cvalue;
|
||||
}
|
||||
|
||||
// Parse annotations
|
||||
pos = 0;
|
||||
while (annotations && PyDict_Next(annotations, &pos, &key, &value)) {
|
||||
std::string ckey;
|
||||
if (PyUnicode_Check(key)) {
|
||||
ckey = PyUnicode_AsUTF8(key);
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(
|
||||
PyExc_TypeError,
|
||||
"The annotations dictionary can only contain string keys"
|
||||
);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (PyUnicode_Check(value)) {
|
||||
std::string cvalue = PyUnicode_AsUTF8(value);
|
||||
getCommandPtr()->setAnnotation(ckey, cvalue);
|
||||
}
|
||||
else if (PyObject_TypeCheck(value, &(PyLong_Type))) {
|
||||
double cvalue = (double)PyLong_AsLong(value);
|
||||
getCommandPtr()->setAnnotation(ckey, cvalue);
|
||||
}
|
||||
else if (PyObject_TypeCheck(value, &(PyFloat_Type))) {
|
||||
double cvalue = PyFloat_AsDouble(value);
|
||||
getCommandPtr()->setAnnotation(ckey, cvalue);
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(
|
||||
PyExc_TypeError,
|
||||
"The annotations dictionary can only contain string or number values"
|
||||
);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
parameters_copy_dict.clear();
|
||||
return 0;
|
||||
}
|
||||
PyErr_Clear(); // set by PyArg_ParseTuple()
|
||||
|
||||
static const std::array<const char*, 3> kwlist_placement {"name", "parameters", nullptr};
|
||||
if (Base::Wrapped_ParseTupleAndKeywords(
|
||||
args,
|
||||
kwd,
|
||||
"|sO!",
|
||||
kwlist,
|
||||
kwlist_placement,
|
||||
&name,
|
||||
&(Base::PlacementPy::Type),
|
||||
¶meters
|
||||
|
||||
Reference in New Issue
Block a user