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