Blender  V3.3
BPy_Operators.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "BPy_Operators.h"
8 
10 #include "BPy_Convert.h"
11 #include "BPy_StrokeShader.h"
12 #include "BPy_UnaryPredicate0D.h"
13 #include "BPy_UnaryPredicate1D.h"
18 
19 #include <sstream>
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 using namespace Freestyle;
26 
28 
29 //-------------------MODULE INITIALIZATION--------------------------------
30 int Operators_Init(PyObject *module)
31 {
32  if (module == nullptr) {
33  return -1;
34  }
35 
36  if (PyType_Ready(&Operators_Type) < 0) {
37  return -1;
38  }
39  Py_INCREF(&Operators_Type);
40  PyModule_AddObject(module, "Operators", (PyObject *)&Operators_Type);
41 
42  return 0;
43 }
44 
45 //------------------------INSTANCE METHODS ----------------------------------
46 
47 PyDoc_STRVAR(Operators_doc,
48  "Class defining the operators used in a style module. There are five\n"
49  "types of operators: Selection, chaining, splitting, sorting and\n"
50  "creation. All these operators are user controlled through functors,\n"
51  "predicates and shaders that are taken as arguments.");
52 
53 static void Operators_dealloc(BPy_Operators *self)
54 {
55  Py_TYPE(self)->tp_free((PyObject *)self);
56 }
57 
58 PyDoc_STRVAR(Operators_select_doc,
59  ".. staticmethod:: select(pred)\n"
60  "\n"
61  " Selects the ViewEdges of the ViewMap verifying a specified\n"
62  " condition.\n"
63  "\n"
64  " :arg pred: The predicate expressing this condition.\n"
65  " :type pred: :class:`UnaryPredicate1D`");
66 
67 static PyObject *Operators_select(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
68 {
69  static const char *kwlist[] = {"pred", nullptr};
70  PyObject *obj = nullptr;
71 
72  if (!PyArg_ParseTupleAndKeywords(
73  args, kwds, "O!", (char **)kwlist, &UnaryPredicate1D_Type, &obj)) {
74  return nullptr;
75  }
76  if (!((BPy_UnaryPredicate1D *)obj)->up1D) {
77  PyErr_SetString(PyExc_TypeError,
78  "Operators.select(): 1st argument: invalid UnaryPredicate1D object");
79  return nullptr;
80  }
81  if (Operators::select(*(((BPy_UnaryPredicate1D *)obj)->up1D)) < 0) {
82  if (!PyErr_Occurred()) {
83  PyErr_SetString(PyExc_RuntimeError, "Operators.select() failed");
84  }
85  return nullptr;
86  }
87  Py_RETURN_NONE;
88 }
89 
90 PyDoc_STRVAR(Operators_chain_doc,
91  ".. staticmethod:: chain(it, pred, modifier)\n"
92  " chain(it, pred)\n"
93  "\n"
94  " Builds a set of chains from the current set of ViewEdges. Each\n"
95  " ViewEdge of the current list starts a new chain. The chaining\n"
96  " operator then iterates over the ViewEdges of the ViewMap using the\n"
97  " user specified iterator. This operator only iterates using the\n"
98  " increment operator and is therefore unidirectional.\n"
99  "\n"
100  " :arg it: The iterator on the ViewEdges of the ViewMap. It contains\n"
101  " the chaining rule.\n"
102  " :type it: :class:`ViewEdgeIterator`\n"
103  " :arg pred: The predicate on the ViewEdge that expresses the\n"
104  " stopping condition.\n"
105  " :type pred: :class:`UnaryPredicate1D`\n"
106  " :arg modifier: A function that takes a ViewEdge as argument and\n"
107  " that is used to modify the processed ViewEdge state (the\n"
108  " timestamp incrementation is a typical illustration of such a modifier).\n"
109  " If this argument is not given, the time stamp is automatically managed.\n"
110  " :type modifier: :class:`UnaryFunction1DVoid`\n");
111 
112 static PyObject *Operators_chain(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
113 {
114  static const char *kwlist[] = {"it", "pred", "modifier", nullptr};
115  PyObject *obj1 = nullptr, *obj2 = nullptr, *obj3 = nullptr;
116 
117  if (!PyArg_ParseTupleAndKeywords(args,
118  kwds,
119  "O!O!|O!",
120  (char **)kwlist,
122  &obj1,
124  &obj2,
126  &obj3)) {
127  return nullptr;
128  }
129  if (!((BPy_ChainingIterator *)obj1)->c_it) {
130  PyErr_SetString(PyExc_TypeError,
131  "Operators.chain(): 1st argument: invalid ChainingIterator object");
132  return nullptr;
133  }
134  if (!((BPy_UnaryPredicate1D *)obj2)->up1D) {
135  PyErr_SetString(PyExc_TypeError,
136  "Operators.chain(): 2nd argument: invalid UnaryPredicate1D object");
137  return nullptr;
138  }
139  if (!obj3) {
140  if (Operators::chain(*(((BPy_ChainingIterator *)obj1)->c_it),
141  *(((BPy_UnaryPredicate1D *)obj2)->up1D)) < 0) {
142  if (!PyErr_Occurred()) {
143  PyErr_SetString(PyExc_RuntimeError, "Operators.chain() failed");
144  }
145  return nullptr;
146  }
147  }
148  else {
149  if (!((BPy_UnaryFunction1DVoid *)obj3)->uf1D_void) {
150  PyErr_SetString(PyExc_TypeError,
151  "Operators.chain(): 3rd argument: invalid UnaryFunction1DVoid object");
152  return nullptr;
153  }
154  if (Operators::chain(*(((BPy_ChainingIterator *)obj1)->c_it),
155  *(((BPy_UnaryPredicate1D *)obj2)->up1D),
156  *(((BPy_UnaryFunction1DVoid *)obj3)->uf1D_void)) < 0) {
157  if (!PyErr_Occurred()) {
158  PyErr_SetString(PyExc_RuntimeError, "Operators.chain() failed");
159  }
160  return nullptr;
161  }
162  }
163  Py_RETURN_NONE;
164 }
165 
166 PyDoc_STRVAR(Operators_bidirectional_chain_doc,
167  ".. staticmethod:: bidirectional_chain(it, pred)\n"
168  " bidirectional_chain(it)\n"
169  "\n"
170  " Builds a set of chains from the current set of ViewEdges. Each\n"
171  " ViewEdge of the current list potentially starts a new chain. The\n"
172  " chaining operator then iterates over the ViewEdges of the ViewMap\n"
173  " using the user specified iterator. This operator iterates both using\n"
174  " the increment and decrement operators and is therefore bidirectional.\n"
175  " This operator works with a ChainingIterator which contains the\n"
176  " chaining rules. It is this last one which can be told to chain only\n"
177  " edges that belong to the selection or not to process twice a ViewEdge\n"
178  " during the chaining. Each time a ViewEdge is added to a chain, its\n"
179  " chaining time stamp is incremented. This allows you to keep track of\n"
180  " the number of chains to which a ViewEdge belongs to.\n"
181  "\n"
182  " :arg it: The ChainingIterator on the ViewEdges of the ViewMap. It\n"
183  " contains the chaining rule.\n"
184  " :type it: :class:`ChainingIterator`\n"
185  " :arg pred: The predicate on the ViewEdge that expresses the stopping condition.\n"
186  " This parameter is optional, you make not want to pass a stopping criterion\n"
187  " when the stopping criterion is already contained in the iterator definition.\n"
188  " :type pred: :class:`UnaryPredicate1D`\n");
189 
190 static PyObject *Operators_bidirectional_chain(BPy_Operators * /*self*/,
191  PyObject *args,
192  PyObject *kwds)
193 {
194  static const char *kwlist[] = {"it", "pred", nullptr};
195  PyObject *obj1 = nullptr, *obj2 = nullptr;
196 
197  if (!PyArg_ParseTupleAndKeywords(args,
198  kwds,
199  "O!|O!",
200  (char **)kwlist,
202  &obj1,
204  &obj2)) {
205  return nullptr;
206  }
207  if (!((BPy_ChainingIterator *)obj1)->c_it) {
208  PyErr_SetString(
209  PyExc_TypeError,
210  "Operators.bidirectional_chain(): 1st argument: invalid ChainingIterator object");
211  return nullptr;
212  }
213  if (!obj2) {
214  if (Operators::bidirectionalChain(*(((BPy_ChainingIterator *)obj1)->c_it)) < 0) {
215  if (!PyErr_Occurred()) {
216  PyErr_SetString(PyExc_RuntimeError, "Operators.bidirectional_chain() failed");
217  }
218  return nullptr;
219  }
220  }
221  else {
222  if (!((BPy_UnaryPredicate1D *)obj2)->up1D) {
223  PyErr_SetString(
224  PyExc_TypeError,
225  "Operators.bidirectional_chain(): 2nd argument: invalid UnaryPredicate1D object");
226  return nullptr;
227  }
229  *(((BPy_UnaryPredicate1D *)obj2)->up1D)) < 0) {
230  if (!PyErr_Occurred()) {
231  PyErr_SetString(PyExc_RuntimeError, "Operators.bidirectional_chain() failed");
232  }
233  return nullptr;
234  }
235  }
236  Py_RETURN_NONE;
237 }
238 
239 PyDoc_STRVAR(Operators_sequential_split_doc,
240  ".. staticmethod:: sequential_split(starting_pred, stopping_pred, sampling=0.0)\n"
241  " sequential_split(pred, sampling=0.0)\n"
242  "\n"
243  " Splits each chain of the current set of chains in a sequential way.\n"
244  " The points of each chain are processed (with a specified sampling)\n"
245  " sequentially. The first point of the initial chain is the\n"
246  " first point of one of the resulting chains. The splitting ends when\n"
247  " no more chain can start.\n"
248  "\n"
249  " .. tip::\n"
250  "\n"
251  " By specifying a starting and stopping predicate allows\n"
252  " the chains to overlap rather than chains partitioning.\n"
253  "\n"
254  " :arg starting_pred: The predicate on a point that expresses the\n"
255  " starting condition. Each time this condition is verified, a new chain begins\n"
256  " :type starting_pred: :class:`UnaryPredicate0D`\n"
257  " :arg stopping_pred: The predicate on a point that expresses the\n"
258  " stopping condition. The chain ends as soon as this predicate is verified.\n"
259  " :type stopping_pred: :class:`UnaryPredicate0D`\n"
260  " :arg pred: The predicate on a point that expresses the splitting condition.\n"
261  " Each time the condition is verified, the chain is split into two chains.\n"
262  " The resulting set of chains is a partition of the initial chain\n"
263  " :type pred: :class:`UnaryPredicate0D`\n"
264  " :arg sampling: The resolution used to sample the chain for the\n"
265  " predicates evaluation. (The chain is not actually resampled;\n"
266  " a virtual point only progresses along the curve using this\n"
267  " resolution.)\n"
268  " :type sampling: float\n");
269 
270 static PyObject *Operators_sequential_split(BPy_Operators * /*self*/,
271  PyObject *args,
272  PyObject *kwds)
273 {
274  static const char *kwlist_1[] = {"starting_pred", "stopping_pred", "sampling", nullptr};
275  static const char *kwlist_2[] = {"pred", "sampling", nullptr};
276  PyObject *obj1 = nullptr, *obj2 = nullptr;
277  float f = 0.0f;
278 
279  if (PyArg_ParseTupleAndKeywords(args,
280  kwds,
281  "O!O!|f",
282  (char **)kwlist_1,
284  &obj1,
286  &obj2,
287  &f)) {
288  if (!((BPy_UnaryPredicate0D *)obj1)->up0D) {
289  PyErr_SetString(
290  PyExc_TypeError,
291  "Operators.sequential_split(): 1st argument: invalid UnaryPredicate0D object");
292  return nullptr;
293  }
294  if (!((BPy_UnaryPredicate0D *)obj2)->up0D) {
295  PyErr_SetString(
296  PyExc_TypeError,
297  "Operators.sequential_split(): 2nd argument: invalid UnaryPredicate0D object");
298  return nullptr;
299  }
300  if (Operators::sequentialSplit(*(((BPy_UnaryPredicate0D *)obj1)->up0D),
301  *(((BPy_UnaryPredicate0D *)obj2)->up0D),
302  f) < 0) {
303  if (!PyErr_Occurred()) {
304  PyErr_SetString(PyExc_RuntimeError, "Operators.sequential_split() failed");
305  }
306  return nullptr;
307  }
308  }
309  else if ((void)PyErr_Clear(),
310  (void)(f = 0.0f),
311  PyArg_ParseTupleAndKeywords(
312  args, kwds, "O!|f", (char **)kwlist_2, &UnaryPredicate0D_Type, &obj1, &f)) {
313  if (!((BPy_UnaryPredicate0D *)obj1)->up0D) {
314  PyErr_SetString(
315  PyExc_TypeError,
316  "Operators.sequential_split(): 1st argument: invalid UnaryPredicate0D object");
317  return nullptr;
318  }
319  if (Operators::sequentialSplit(*(((BPy_UnaryPredicate0D *)obj1)->up0D), f) < 0) {
320  if (!PyErr_Occurred()) {
321  PyErr_SetString(PyExc_RuntimeError, "Operators.sequential_split() failed");
322  }
323  return nullptr;
324  }
325  }
326  else {
327  PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
328  return nullptr;
329  }
330  Py_RETURN_NONE;
331 }
332 
334  Operators_recursive_split_doc,
335  ".. staticmethod:: recursive_split(func, pred_1d, sampling=0.0)\n"
336  " recursive_split(func, pred_0d, pred_1d, sampling=0.0)\n"
337  "\n"
338  " Splits the current set of chains in a recursive way. We process the\n"
339  " points of each chain (with a specified sampling) to find the point\n"
340  " minimizing a specified function. The chain is split in two at this\n"
341  " point and the two new chains are processed in the same way. The\n"
342  " recursivity level is controlled through a predicate 1D that expresses\n"
343  " a stopping condition on the chain that is about to be processed.\n"
344  "\n"
345  " The user can also specify a 0D predicate to make a first selection on the points\n"
346  " that can potentially be split. A point that doesn't verify the 0D\n"
347  " predicate won't be candidate in realizing the min.\n"
348  "\n"
349  " :arg func: The Unary Function evaluated at each point of the chain.\n"
350  " The splitting point is the point minimizing this function.\n"
351  " :type func: :class:`UnaryFunction0DDouble`\n"
352  " :arg pred_0d: The Unary Predicate 0D used to select the candidate\n"
353  " points where the split can occur. For example, it is very likely\n"
354  " that would rather have your chain splitting around its middle\n"
355  " point than around one of its extremities. A 0D predicate working\n"
356  " on the curvilinear abscissa allows to add this kind of constraints.\n"
357  " :type pred_0d: :class:`UnaryPredicate0D`\n"
358  " :arg pred_1d: The Unary Predicate expressing the recursivity stopping\n"
359  " condition. This predicate is evaluated for each curve before it\n"
360  " actually gets split. If pred_1d(chain) is true, the curve won't be\n"
361  " split anymore.\n"
362  " :type pred_1d: :class:`UnaryPredicate1D`\n"
363  " :arg sampling: The resolution used to sample the chain for the\n"
364  " predicates evaluation. (The chain is not actually resampled; a\n"
365  " virtual point only progresses along the curve using this\n"
366  " resolution.)\n"
367  " :type sampling: float\n");
368 
369 static PyObject *Operators_recursive_split(BPy_Operators * /*self*/,
370  PyObject *args,
371  PyObject *kwds)
372 {
373  static const char *kwlist_1[] = {"func", "pred_1d", "sampling", nullptr};
374  static const char *kwlist_2[] = {"func", "pred_0d", "pred_1d", "sampling", nullptr};
375  PyObject *obj1 = nullptr, *obj2 = nullptr, *obj3 = nullptr;
376  float f = 0.0f;
377 
378  if (PyArg_ParseTupleAndKeywords(args,
379  kwds,
380  "O!O!|f",
381  (char **)kwlist_1,
383  &obj1,
385  &obj2,
386  &f)) {
387  if (!((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double) {
388  PyErr_SetString(
389  PyExc_TypeError,
390  "Operators.recursive_split(): 1st argument: invalid UnaryFunction0DDouble object");
391  return nullptr;
392  }
393  if (!((BPy_UnaryPredicate1D *)obj2)->up1D) {
394  PyErr_SetString(
395  PyExc_TypeError,
396  "Operators.recursive_split(): 2nd argument: invalid UnaryPredicate1D object");
397  return nullptr;
398  }
399  if (Operators::recursiveSplit(*(((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double),
400  *(((BPy_UnaryPredicate1D *)obj2)->up1D),
401  f) < 0) {
402  if (!PyErr_Occurred()) {
403  PyErr_SetString(PyExc_RuntimeError, "Operators.recursive_split() failed");
404  }
405  return nullptr;
406  }
407  }
408  else if ((void)PyErr_Clear(),
409  (void)(f = 0.0f),
410  PyArg_ParseTupleAndKeywords(args,
411  kwds,
412  "O!O!O!|f",
413  (char **)kwlist_2,
415  &obj1,
417  &obj2,
419  &obj3,
420  &f)) {
421  if (!((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double) {
422  PyErr_SetString(
423  PyExc_TypeError,
424  "Operators.recursive_split(): 1st argument: invalid UnaryFunction0DDouble object");
425  return nullptr;
426  }
427  if (!((BPy_UnaryPredicate0D *)obj2)->up0D) {
428  PyErr_SetString(
429  PyExc_TypeError,
430  "Operators.recursive_split(): 2nd argument: invalid UnaryPredicate0D object");
431  return nullptr;
432  }
433  if (!((BPy_UnaryPredicate1D *)obj3)->up1D) {
434  PyErr_SetString(
435  PyExc_TypeError,
436  "Operators.recursive_split(): 3rd argument: invalid UnaryPredicate1D object");
437  return nullptr;
438  }
439  if (Operators::recursiveSplit(*(((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double),
440  *(((BPy_UnaryPredicate0D *)obj2)->up0D),
441  *(((BPy_UnaryPredicate1D *)obj3)->up1D),
442  f) < 0) {
443  if (!PyErr_Occurred()) {
444  PyErr_SetString(PyExc_RuntimeError, "Operators.recursive_split() failed");
445  }
446  return nullptr;
447  }
448  }
449  else {
450  PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
451  return nullptr;
452  }
453  Py_RETURN_NONE;
454 }
455 
456 PyDoc_STRVAR(Operators_sort_doc,
457  ".. staticmethod:: sort(pred)\n"
458  "\n"
459  " Sorts the current set of chains (or viewedges) according to the\n"
460  " comparison predicate given as argument.\n"
461  "\n"
462  " :arg pred: The binary predicate used for the comparison.\n"
463  " :type pred: :class:`BinaryPredicate1D`");
464 
465 static PyObject *Operators_sort(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
466 {
467  static const char *kwlist[] = {"pred", nullptr};
468  PyObject *obj = nullptr;
469 
470  if (!PyArg_ParseTupleAndKeywords(
471  args, kwds, "O!", (char **)kwlist, &BinaryPredicate1D_Type, &obj)) {
472  return nullptr;
473  }
474  if (!((BPy_BinaryPredicate1D *)obj)->bp1D) {
475  PyErr_SetString(PyExc_TypeError,
476  "Operators.sort(): 1st argument: invalid BinaryPredicate1D object");
477  return nullptr;
478  }
479  if (Operators::sort(*(((BPy_BinaryPredicate1D *)obj)->bp1D)) < 0) {
480  if (!PyErr_Occurred()) {
481  PyErr_SetString(PyExc_RuntimeError, "Operators.sort() failed");
482  }
483  return nullptr;
484  }
485  Py_RETURN_NONE;
486 }
487 
488 PyDoc_STRVAR(Operators_create_doc,
489  ".. staticmethod:: create(pred, shaders)\n"
490  "\n"
491  " Creates and shades the strokes from the current set of chains. A\n"
492  " predicate can be specified to make a selection pass on the chains.\n"
493  "\n"
494  " :arg pred: The predicate that a chain must verify in order to be\n"
495  " transform as a stroke.\n"
496  " :type pred: :class:`UnaryPredicate1D`\n"
497  " :arg shaders: The list of shaders used to shade the strokes.\n"
498  " :type shaders: list of :class:`StrokeShader` objects");
499 
500 static PyObject *Operators_create(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
501 {
502  static const char *kwlist[] = {"pred", "shaders", nullptr};
503  PyObject *obj1 = nullptr, *obj2 = nullptr;
504 
505  if (!PyArg_ParseTupleAndKeywords(args,
506  kwds,
507  "O!O!",
508  (char **)kwlist,
510  &obj1,
511  &PyList_Type,
512  &obj2)) {
513  return nullptr;
514  }
515  if (!((BPy_UnaryPredicate1D *)obj1)->up1D) {
516  PyErr_SetString(PyExc_TypeError,
517  "Operators.create(): 1st argument: invalid UnaryPredicate1D object");
518  return nullptr;
519  }
520  vector<StrokeShader *> shaders;
521  shaders.reserve(PyList_Size(obj2));
522  for (int i = 0; i < PyList_Size(obj2); i++) {
523  PyObject *py_ss = PyList_GET_ITEM(obj2, i);
524  if (!BPy_StrokeShader_Check(py_ss)) {
525  PyErr_SetString(PyExc_TypeError,
526  "Operators.create(): 2nd argument must be a list of StrokeShader objects");
527  return nullptr;
528  }
529  StrokeShader *shader = ((BPy_StrokeShader *)py_ss)->ss;
530  if (!shader) {
531  stringstream ss;
532  ss << "Operators.create(): item " << (i + 1)
533  << " of the shaders list is invalid likely due to missing call of "
534  "StrokeShader.__init__()";
535  PyErr_SetString(PyExc_TypeError, ss.str().c_str());
536  return nullptr;
537  }
538  shaders.push_back(shader);
539  }
540  if (Operators::create(*(((BPy_UnaryPredicate1D *)obj1)->up1D), shaders) < 0) {
541  if (!PyErr_Occurred()) {
542  PyErr_SetString(PyExc_RuntimeError, "Operators.create() failed");
543  }
544  return nullptr;
545  }
546  Py_RETURN_NONE;
547 }
548 
549 PyDoc_STRVAR(Operators_reset_doc,
550  ".. staticmethod:: reset(delete_strokes=True)\n"
551  "\n"
552  " Resets the line stylization process to the initial state. The results of\n"
553  " stroke creation are accumulated if **delete_strokes** is set to False.\n"
554  "\n"
555  " :arg delete_strokes: Delete the strokes that are currently stored.\n"
556  " :type delete_strokes: bool\n");
557 
558 static PyObject *Operators_reset(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
559 {
560  static const char *kwlist[] = {"delete_strokes", nullptr};
561  PyObject *obj1 = nullptr;
562  if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &PyBool_Type, &obj1)) {
563  // true is the default
564  Operators::reset(obj1 ? bool_from_PyBool(obj1) : true);
565  }
566  else {
567  PyErr_SetString(PyExc_RuntimeError, "Operators.reset() failed");
568  return nullptr;
569  }
570  Py_RETURN_NONE;
571 }
572 
573 PyDoc_STRVAR(Operators_get_viewedge_from_index_doc,
574  ".. staticmethod:: get_viewedge_from_index(i)\n"
575  "\n"
576  " Returns the ViewEdge at the index in the current set of ViewEdges.\n"
577  "\n"
578  " :arg i: index (0 <= i < Operators.get_view_edges_size()).\n"
579  " :type i: int\n"
580  " :return: The ViewEdge object.\n"
581  " :rtype: :class:`ViewEdge`");
582 
584  PyObject *args,
585  PyObject *kwds)
586 {
587  static const char *kwlist[] = {"i", nullptr};
588  unsigned int i;
589 
590  if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", (char **)kwlist, &i)) {
591  return nullptr;
592  }
593  if (i >= Operators::getViewEdgesSize()) {
594  PyErr_SetString(PyExc_IndexError, "index out of range");
595  return nullptr;
596  }
598 }
599 
600 PyDoc_STRVAR(Operators_get_chain_from_index_doc,
601  ".. staticmethod:: get_chain_from_index(i)\n"
602  "\n"
603  " Returns the Chain at the index in the current set of Chains.\n"
604  "\n"
605  " :arg i: index (0 <= i < Operators.get_chains_size()).\n"
606  " :type i: int\n"
607  " :return: The Chain object.\n"
608  " :rtype: :class:`Chain`");
609 
610 static PyObject *Operators_get_chain_from_index(BPy_Operators * /*self*/,
611  PyObject *args,
612  PyObject *kwds)
613 {
614  static const char *kwlist[] = {"i", nullptr};
615  unsigned int i;
616 
617  if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", (char **)kwlist, &i)) {
618  return nullptr;
619  }
620  if (i >= Operators::getChainsSize()) {
621  PyErr_SetString(PyExc_IndexError, "index out of range");
622  return nullptr;
623  }
625 }
626 
627 PyDoc_STRVAR(Operators_get_stroke_from_index_doc,
628  ".. staticmethod:: get_stroke_from_index(i)\n"
629  "\n"
630  " Returns the Stroke at the index in the current set of Strokes.\n"
631  "\n"
632  " :arg i: index (0 <= i < Operators.get_strokes_size()).\n"
633  " :type i: int\n"
634  " :return: The Stroke object.\n"
635  " :rtype: :class:`Stroke`");
636 
637 static PyObject *Operators_get_stroke_from_index(BPy_Operators * /*self*/,
638  PyObject *args,
639  PyObject *kwds)
640 {
641  static const char *kwlist[] = {"i", nullptr};
642  unsigned int i;
643 
644  if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", (char **)kwlist, &i)) {
645  return nullptr;
646  }
647  if (i >= Operators::getStrokesSize()) {
648  PyErr_SetString(PyExc_IndexError, "index out of range");
649  return nullptr;
650  }
652 }
653 
654 PyDoc_STRVAR(Operators_get_view_edges_size_doc,
655  ".. staticmethod:: get_view_edges_size()\n"
656  "\n"
657  " Returns the number of ViewEdges.\n"
658  "\n"
659  " :return: The number of ViewEdges.\n"
660  " :rtype: int");
661 
662 static PyObject *Operators_get_view_edges_size(BPy_Operators * /*self*/)
663 {
664  return PyLong_FromLong(Operators::getViewEdgesSize());
665 }
666 
667 PyDoc_STRVAR(Operators_get_chains_size_doc,
668  ".. staticmethod:: get_chains_size()\n"
669  "\n"
670  " Returns the number of Chains.\n"
671  "\n"
672  " :return: The number of Chains.\n"
673  " :rtype: int");
674 
675 static PyObject *Operators_get_chains_size(BPy_Operators * /*self*/)
676 {
677  return PyLong_FromLong(Operators::getChainsSize());
678 }
679 
680 PyDoc_STRVAR(Operators_get_strokes_size_doc,
681  ".. staticmethod:: get_strokes_size()\n"
682  "\n"
683  " Returns the number of Strokes.\n"
684  "\n"
685  " :return: The number of Strokes.\n"
686  " :rtype: int");
687 
688 static PyObject *Operators_get_strokes_size(BPy_Operators * /*self*/)
689 {
690  return PyLong_FromLong(Operators::getStrokesSize());
691 }
692 
693 /*----------------------Operators instance definitions ----------------------------*/
694 static PyMethodDef BPy_Operators_methods[] = {
695  {"select",
696  (PyCFunction)Operators_select,
697  METH_VARARGS | METH_KEYWORDS | METH_STATIC,
698  Operators_select_doc},
699  {"chain",
700  (PyCFunction)Operators_chain,
701  METH_VARARGS | METH_KEYWORDS | METH_STATIC,
702  Operators_chain_doc},
703  {"bidirectional_chain",
704  (PyCFunction)Operators_bidirectional_chain,
705  METH_VARARGS | METH_KEYWORDS | METH_STATIC,
706  Operators_bidirectional_chain_doc},
707  {"sequential_split",
708  (PyCFunction)Operators_sequential_split,
709  METH_VARARGS | METH_KEYWORDS | METH_STATIC,
710  Operators_sequential_split_doc},
711  {"recursive_split",
712  (PyCFunction)Operators_recursive_split,
713  METH_VARARGS | METH_KEYWORDS | METH_STATIC,
714  Operators_recursive_split_doc},
715  {"sort",
716  (PyCFunction)Operators_sort,
717  METH_VARARGS | METH_KEYWORDS | METH_STATIC,
718  Operators_sort_doc},
719  {"create",
720  (PyCFunction)Operators_create,
721  METH_VARARGS | METH_KEYWORDS | METH_STATIC,
722  Operators_create_doc},
723  {"reset",
724  (PyCFunction)Operators_reset,
725  METH_VARARGS | METH_KEYWORDS | METH_STATIC,
726  Operators_reset_doc},
727  {"get_viewedge_from_index",
729  METH_VARARGS | METH_KEYWORDS | METH_STATIC,
730  Operators_get_viewedge_from_index_doc},
731  {"get_chain_from_index",
732  (PyCFunction)Operators_get_chain_from_index,
733  METH_VARARGS | METH_KEYWORDS | METH_STATIC,
734  Operators_get_chain_from_index_doc},
735  {"get_stroke_from_index",
736  (PyCFunction)Operators_get_stroke_from_index,
737  METH_VARARGS | METH_KEYWORDS | METH_STATIC,
738  Operators_get_stroke_from_index_doc},
739  {"get_view_edges_size",
740  (PyCFunction)Operators_get_view_edges_size,
741  METH_NOARGS | METH_STATIC,
742  Operators_get_view_edges_size_doc},
743  {"get_chains_size",
744  (PyCFunction)Operators_get_chains_size,
745  METH_NOARGS | METH_STATIC,
746  Operators_get_chains_size_doc},
747  {"get_strokes_size",
748  (PyCFunction)Operators_get_strokes_size,
749  METH_NOARGS | METH_STATIC,
750  Operators_get_strokes_size_doc},
751  {nullptr, nullptr, 0, nullptr},
752 };
753 
754 /*-----------------------BPy_Operators type definition ------------------------------*/
755 
756 PyTypeObject Operators_Type = {
757  PyVarObject_HEAD_INIT(nullptr, 0) "Operators", /* tp_name */
758  sizeof(BPy_Operators), /* tp_basicsize */
759  0, /* tp_itemsize */
760  (destructor)Operators_dealloc, /* tp_dealloc */
761  0, /* tp_vectorcall_offset */
762  nullptr, /* tp_getattr */
763  nullptr, /* tp_setattr */
764  nullptr, /* tp_reserved */
765  nullptr, /* tp_repr */
766  nullptr, /* tp_as_number */
767  nullptr, /* tp_as_sequence */
768  nullptr, /* tp_as_mapping */
769  nullptr, /* tp_hash */
770  nullptr, /* tp_call */
771  nullptr, /* tp_str */
772  nullptr, /* tp_getattro */
773  nullptr, /* tp_setattro */
774  nullptr, /* tp_as_buffer */
775  Py_TPFLAGS_DEFAULT, /* tp_flags */
776  Operators_doc, /* tp_doc */
777  nullptr, /* tp_traverse */
778  nullptr, /* tp_clear */
779  nullptr, /* tp_richcompare */
780  0, /* tp_weaklistoffset */
781  nullptr, /* tp_iter */
782  nullptr, /* tp_iternext */
783  BPy_Operators_methods, /* tp_methods */
784  nullptr, /* tp_members */
785  nullptr, /* tp_getset */
786  nullptr, /* tp_base */
787  nullptr, /* tp_dict */
788  nullptr, /* tp_descr_get */
789  nullptr, /* tp_descr_set */
790  0, /* tp_dictoffset */
791  nullptr, /* tp_init */
792  nullptr, /* tp_alloc */
793  PyType_GenericNew, /* tp_new */
794 };
795 
797 
798 #ifdef __cplusplus
799 }
800 #endif
PyTypeObject BinaryPredicate1D_Type
PyTypeObject ChainingIterator_Type
PyObject * BPy_Chain_from_Chain(Chain &c)
bool bool_from_PyBool(PyObject *b)
PyObject * BPy_Stroke_from_Stroke(Stroke &s)
PyObject * BPy_ViewEdge_from_ViewEdge(ViewEdge &ve)
static PyObject * Operators_get_viewedge_from_index(BPy_Operators *, PyObject *args, PyObject *kwds)
static PyObject * Operators_get_view_edges_size(BPy_Operators *)
static PyMethodDef BPy_Operators_methods[]
int Operators_Init(PyObject *module)
static PyObject * Operators_create(BPy_Operators *, PyObject *args, PyObject *kwds)
static PyObject * Operators_sort(BPy_Operators *, PyObject *args, PyObject *kwds)
static PyObject * Operators_get_chain_from_index(BPy_Operators *, PyObject *args, PyObject *kwds)
PyDoc_STRVAR(Operators_doc, "Class defining the operators used in a style module. There are five\n" "types of operators: Selection, chaining, splitting, sorting and\n" "creation. All these operators are user controlled through functors,\n" "predicates and shaders that are taken as arguments.")
static PyObject * Operators_get_stroke_from_index(BPy_Operators *, PyObject *args, PyObject *kwds)
static PyObject * Operators_get_strokes_size(BPy_Operators *)
static PyObject * Operators_get_chains_size(BPy_Operators *)
static PyObject * Operators_select(BPy_Operators *, PyObject *args, PyObject *kwds)
static PyObject * Operators_reset(BPy_Operators *, PyObject *args, PyObject *kwds)
static PyObject * Operators_recursive_split(BPy_Operators *, PyObject *args, PyObject *kwds)
static PyObject * Operators_chain(BPy_Operators *, PyObject *args, PyObject *kwds)
static PyObject * Operators_bidirectional_chain(BPy_Operators *, PyObject *args, PyObject *kwds)
static void Operators_dealloc(BPy_Operators *self)
PyTypeObject Operators_Type
static PyObject * Operators_sequential_split(BPy_Operators *, PyObject *args, PyObject *kwds)
#define BPy_StrokeShader_Check(v)
PyTypeObject UnaryFunction0DDouble_Type
PyTypeObject UnaryFunction1DVoid_Type
PyTypeObject UnaryPredicate0D_Type
PyTypeObject UnaryPredicate1D_Type
static int sort(BinaryPredicate1D &pred)
Definition: Operators.cpp:1054
static int select(UnaryPredicate1D &pred)
Definition: Operators.cpp:26
static int chain(ViewEdgeInternal::ViewEdgeIterator &it, UnaryPredicate1D &pred, UnaryFunction1D_void &modifier)
Definition: Operators.cpp:68
static void reset(bool removeStrokes=true)
Definition: Operators.cpp:1303
static ViewEdge * getViewEdgeFromIndex(unsigned i)
Definition: Operators.h:220
static int sequentialSplit(UnaryPredicate0D &startingPred, UnaryPredicate0D &stoppingPred, float sampling=0.0f)
Definition: Operators.cpp:580
static int recursiveSplit(UnaryFunction0D< double > &func, UnaryPredicate1D &pred, float sampling=0)
Definition: Operators.cpp:790
static unsigned getViewEdgesSize()
Definition: Operators.h:235
static int bidirectionalChain(ChainingIterator &it, UnaryPredicate1D &pred)
Definition: Operators.cpp:315
static Stroke * getStrokeFromIndex(unsigned i)
Definition: Operators.h:230
static Chain * getChainFromIndex(unsigned i)
Definition: Operators.h:225
static int create(UnaryPredicate1D &pred, vector< StrokeShader * > shaders)
Definition: Operators.cpp:1259
static unsigned getStrokesSize()
Definition: Operators.h:245
static unsigned getChainsSize()
Definition: Operators.h:240
inherits from class Rep
Definition: AppCanvas.cpp:18
static struct PyModuleDef module
Definition: python.cpp:972