Blender  V3.3
BPy_StrokeVertexIterator.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
8 
9 #include "../BPy_Convert.h"
10 #include "../Interface1D/BPy_Stroke.h"
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
17 using namespace Freestyle;
18 
20 
21 //------------------------INSTANCE METHODS ----------------------------------
22 
23 PyDoc_STRVAR(StrokeVertexIterator_doc,
24  "Class hierarchy: :class:`Iterator` > :class:`StrokeVertexIterator`\n"
25  "\n"
26  "Class defining an iterator designed to iterate over the\n"
27  ":class:`StrokeVertex` of a :class:`Stroke`. An instance of a\n"
28  "StrokeVertexIterator can be obtained from a Stroke by calling\n"
29  "iter(), stroke_vertices_begin() or stroke_vertices_begin(). It is iterating\n"
30  "over the same vertices as an :class:`Interface0DIterator`. The difference\n"
31  "resides in the object access: an Interface0DIterator only allows\n"
32  "access to an Interface0D while one might need to access the\n"
33  "specialized StrokeVertex type. In this case, one should use a\n"
34  "StrokeVertexIterator. To call functions of the UnaryFuntion0D type,\n"
35  "a StrokeVertexIterator can be converted to an Interface0DIterator by\n"
36  "by calling Interface0DIterator(it).\n"
37  "\n"
38  ".. method:: __init__()\n"
39  " __init__(brother)\n"
40  "\n"
41  " Creates a :class:`StrokeVertexIterator` using either the\n"
42  " default constructor or the copy constructor.\n"
43  "\n"
44  " :arg brother: A StrokeVertexIterator object.\n"
45  " :type brother: :class:`StrokeVertexIterator`");
46 
48  PyObject *args,
49  PyObject *kwds)
50 {
51  static const char *kwlist_1[] = {"brother", nullptr};
52  static const char *kwlist_2[] = {"stroke", nullptr};
53  PyObject *brother = nullptr, *stroke = nullptr;
54 
55  if (PyArg_ParseTupleAndKeywords(
56  args, kwds, "O!", (char **)kwlist_1, &StrokeVertexIterator_Type, &brother)) {
57  self->sv_it = new StrokeInternal::StrokeVertexIterator(
58  *(((BPy_StrokeVertexIterator *)brother)->sv_it));
59  self->reversed = ((BPy_StrokeVertexIterator *)brother)->reversed;
60  self->at_start = ((BPy_StrokeVertexIterator *)brother)->at_start;
61  }
62 
63  else if ((void)PyErr_Clear(),
64  PyArg_ParseTupleAndKeywords(
65  args, kwds, "|O!", (char **)kwlist_2, &Stroke_Type, &stroke)) {
66  if (!stroke) {
67  self->sv_it = new StrokeInternal::StrokeVertexIterator();
68  }
69  else {
70  self->sv_it = new StrokeInternal::StrokeVertexIterator(
71  ((BPy_Stroke *)stroke)->s->strokeVerticesBegin());
72  }
73  self->reversed = false;
74  self->at_start = true;
75  }
76  else {
77  PyErr_SetString(PyExc_TypeError, "argument 1 must be StrokeVertexIterator or Stroke");
78  return -1;
79  }
80  self->py_it.it = self->sv_it;
81  return 0;
82 }
83 
85 {
86  Py_INCREF(self);
87  self->at_start = true;
88  return (PyObject *)self;
89 }
90 
92 {
93  /* Because Freestyle iterators for which it.isEnd() holds true have no valid object
94  * (they point to the past-the-end element and can't be dereferenced), we have to check
95  * iterators for validity.
96  * Additionally, the at_start attribute is used to keep Freestyle iterator objects
97  * and Python for loops in sync. */
98 
99  if (self->reversed) {
100  if (self->sv_it->isBegin()) {
101  PyErr_SetNone(PyExc_StopIteration);
102  return nullptr;
103  }
104  self->sv_it->decrement();
105  }
106  else {
107  /* If sv_it.isEnd() is true, the iterator can't be incremented. */
108  if (self->sv_it->isEnd()) {
109  PyErr_SetNone(PyExc_StopIteration);
110  return nullptr;
111  }
112  /* If at the start of the iterator, only return the object
113  * and don't increment, to keep for-loops in sync */
114  if (self->at_start) {
115  self->at_start = false;
116  }
117  /* If sv_it.atLast() is true, the iterator is currently pointing to the final valid element.
118  * Incrementing it further would lead to a state that the iterator can't be dereferenced. */
119  else if (self->sv_it->atLast()) {
120  PyErr_SetNone(PyExc_StopIteration);
121  return nullptr;
122  }
123  else {
124  self->sv_it->increment();
125  }
126  }
127  StrokeVertex *sv = self->sv_it->operator->();
129 }
130 
131 /*----------------------StrokeVertexIterator methods ----------------------------*/
132 
133 PyDoc_STRVAR(StrokeVertexIterator_incremented_doc,
134  ".. method:: incremented()\n"
135  "\n"
136  " Returns a copy of an incremented StrokeVertexIterator.\n"
137  "\n"
138  " :return: A StrokeVertexIterator pointing the next StrokeVertex.\n"
139  " :rtype: :class:`StrokeVertexIterator`");
140 
142 {
143  if (self->sv_it->isEnd()) {
144  PyErr_SetString(PyExc_RuntimeError, "cannot increment any more");
145  return nullptr;
146  }
148  copy.increment();
150 }
151 
152 PyDoc_STRVAR(StrokeVertexIterator_decremented_doc,
153  ".. method:: decremented()\n"
154  "\n"
155  " Returns a copy of a decremented StrokeVertexIterator.\n"
156  "\n"
157  " :return: A StrokeVertexIterator pointing the previous StrokeVertex.\n"
158  " :rtype: :class:`StrokeVertexIterator`");
159 
161 {
162  if (self->sv_it->isBegin()) {
163  PyErr_SetString(PyExc_RuntimeError, "cannot decrement any more");
164  return nullptr;
165  }
167  copy.decrement();
169 }
170 
171 PyDoc_STRVAR(StrokeVertexIterator_reversed_doc,
172  ".. method:: reversed()\n"
173  "\n"
174  " Returns a StrokeVertexIterator that traverses stroke vertices in the\n"
175  " reversed order.\n"
176  "\n"
177  " :return: A StrokeVertexIterator traversing stroke vertices backward.\n"
178  " :rtype: :class:`StrokeVertexIterator`");
179 
181 {
183 }
184 
185 static PyMethodDef BPy_StrokeVertexIterator_methods[] = {
186  {"incremented",
188  METH_NOARGS,
189  StrokeVertexIterator_incremented_doc},
190  {"decremented",
192  METH_NOARGS,
193  StrokeVertexIterator_decremented_doc},
194  {"reversed",
195  (PyCFunction)StrokeVertexIterator_reversed,
196  METH_NOARGS,
197  StrokeVertexIterator_reversed_doc},
198  {nullptr, nullptr, 0, nullptr},
199 };
200 
201 /*----------------------StrokeVertexIterator get/setters ----------------------------*/
202 
203 PyDoc_STRVAR(StrokeVertexIterator_object_doc,
204  "The StrokeVertex object currently pointed to by this iterator.\n"
205  "\n"
206  ":type: :class:`StrokeVertex`");
207 
209  void *UNUSED(closure))
210 {
211  if (self->sv_it->isEnd()) {
212  PyErr_SetString(PyExc_RuntimeError, "iteration has stopped");
213  return nullptr;
214  }
215  StrokeVertex *sv = self->sv_it->operator->();
216  if (sv) {
218  }
219  Py_RETURN_NONE;
220 }
221 
222 PyDoc_STRVAR(StrokeVertexIterator_t_doc,
223  "The curvilinear abscissa of the current point.\n"
224  "\n"
225  ":type: float");
226 
227 static PyObject *StrokeVertexIterator_t_get(BPy_StrokeVertexIterator *self, void *UNUSED(closure))
228 {
229  return PyFloat_FromDouble(self->sv_it->t());
230 }
231 
232 PyDoc_STRVAR(StrokeVertexIterator_u_doc,
233  "The point parameter at the current point in the stroke (0 <= u <= 1).\n"
234  "\n"
235  ":type: float");
236 
237 static PyObject *StrokeVertexIterator_u_get(BPy_StrokeVertexIterator *self, void *UNUSED(closure))
238 {
239  return PyFloat_FromDouble(self->sv_it->u());
240 }
241 
242 PyDoc_STRVAR(StrokeVertexIterator_at_last_doc,
243  "True if the iterator points to the last valid element.\n"
244  "For its counterpart (pointing to the first valid element), use it.is_begin.\n"
245  "\n"
246  ":type: bool");
247 
249 {
250  return PyBool_from_bool(self->sv_it->atLast());
251 }
252 
253 static PyGetSetDef BPy_StrokeVertexIterator_getseters[] = {
254  {"object",
256  (setter) nullptr,
257  StrokeVertexIterator_object_doc,
258  nullptr},
259  {"t",
261  (setter) nullptr,
262  StrokeVertexIterator_t_doc,
263  nullptr},
264  {"u",
266  (setter) nullptr,
267  StrokeVertexIterator_u_doc,
268  nullptr},
269  {"at_last",
271  (setter) nullptr,
272  StrokeVertexIterator_at_last_doc,
273  nullptr},
274  {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
275 };
276 
277 /*-----------------------BPy_StrokeVertexIterator type definition ------------------------------*/
278 
280  PyVarObject_HEAD_INIT(nullptr, 0) "StrokeVertexIterator", /* tp_name */
281  sizeof(BPy_StrokeVertexIterator), /* tp_basicsize */
282  0, /* tp_itemsize */
283  nullptr, /* tp_dealloc */
284  0, /* tp_vectorcall_offset */
285  nullptr, /* tp_getattr */
286  nullptr, /* tp_setattr */
287  nullptr, /* tp_reserved */
288  nullptr, /* tp_repr */
289  nullptr, /* tp_as_number */
290  nullptr, /* tp_as_sequence */
291  nullptr, /* tp_as_mapping */
292  nullptr, /* tp_hash */
293  nullptr, /* tp_call */
294  nullptr, /* tp_str */
295  nullptr, /* tp_getattro */
296  nullptr, /* tp_setattro */
297  nullptr, /* tp_as_buffer */
298  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
299  StrokeVertexIterator_doc, /* tp_doc */
300  nullptr, /* tp_traverse */
301  nullptr, /* tp_clear */
302  nullptr, /* tp_richcompare */
303  0, /* tp_weaklistoffset */
304  (getiterfunc)StrokeVertexIterator_iter, /* tp_iter */
305  (iternextfunc)StrokeVertexIterator_iternext, /* tp_iternext */
306  BPy_StrokeVertexIterator_methods, /* tp_methods */
307  nullptr, /* tp_members */
308  BPy_StrokeVertexIterator_getseters, /* tp_getset */
309  &Iterator_Type, /* tp_base */
310  nullptr, /* tp_dict */
311  nullptr, /* tp_descr_get */
312  nullptr, /* tp_descr_set */
313  0, /* tp_dictoffset */
314  (initproc)StrokeVertexIterator_init, /* tp_init */
315  nullptr, /* tp_alloc */
316  nullptr, /* tp_new */
317 };
318 
320 
321 #ifdef __cplusplus
322 }
323 #endif
#define UNUSED(x)
PyObject * PyBool_from_bool(bool b)
Definition: BPy_Convert.cpp:59
PyObject * BPy_StrokeVertex_from_StrokeVertex(StrokeVertex &sv)
PyObject * BPy_StrokeVertexIterator_from_StrokeVertexIterator(StrokeInternal::StrokeVertexIterator &sv_it, bool reversed)
PyTypeObject Iterator_Type
static int StrokeVertexIterator_init(BPy_StrokeVertexIterator *self, PyObject *args, PyObject *kwds)
static PyObject * StrokeVertexIterator_at_last_get(BPy_StrokeVertexIterator *self)
static PyObject * StrokeVertexIterator_reversed(BPy_StrokeVertexIterator *self)
static PyObject * StrokeVertexIterator_iternext(BPy_StrokeVertexIterator *self)
static PyObject * StrokeVertexIterator_t_get(BPy_StrokeVertexIterator *self, void *UNUSED(closure))
static PyObject * StrokeVertexIterator_decremented(BPy_StrokeVertexIterator *self)
PyTypeObject StrokeVertexIterator_Type
static PyObject * StrokeVertexIterator_object_get(BPy_StrokeVertexIterator *self, void *UNUSED(closure))
static PyGetSetDef BPy_StrokeVertexIterator_getseters[]
static PyMethodDef BPy_StrokeVertexIterator_methods[]
static PyObject * StrokeVertexIterator_incremented(BPy_StrokeVertexIterator *self)
static PyObject * StrokeVertexIterator_iter(BPy_StrokeVertexIterator *self)
static PyObject * StrokeVertexIterator_u_get(BPy_StrokeVertexIterator *self, void *UNUSED(closure))
PyDoc_STRVAR(StrokeVertexIterator_doc, "Class hierarchy: :class:`Iterator` > :class:`StrokeVertexIterator`\n" "\n" "Class defining an iterator designed to iterate over the\n" ":class:`StrokeVertex` of a :class:`Stroke`. An instance of a\n" "StrokeVertexIterator can be obtained from a Stroke by calling\n" "iter(), stroke_vertices_begin() or stroke_vertices_begin(). It is iterating\n" "over the same vertices as an :class:`Interface0DIterator`. The difference\n" "resides in the object access: an Interface0DIterator only allows\n" "access to an Interface0D while one might need to access the\n" "specialized StrokeVertex type. In this case, one should use a\n" "StrokeVertexIterator. To call functions of the UnaryFuntion0D type,\n" "a StrokeVertexIterator can be converted to an Interface0DIterator by\n" "by calling Interface0DIterator(it).\n" "\n" ".. method:: __init__()\n" " __init__(brother)\n" "\n" " Creates a :class:`StrokeVertexIterator` using either the\n" " default constructor or the copy constructor.\n" "\n" " :arg brother: A StrokeVertexIterator object.\n" " :type brother: :class:`StrokeVertexIterator`")
PyTypeObject Stroke_Type
Definition: BPy_Stroke.cpp:487
PyObject * self
Definition: bpy_driver.c:165
inherits from class Rep
Definition: AppCanvas.cpp:18
static void copy(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)