Blender  V2.93
BPy_SVertex.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_SVertex.h"
22 
23 #include "../BPy_Convert.h"
24 #include "../BPy_Id.h"
25 #include "../Interface1D/BPy_FEdge.h"
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 using namespace Freestyle;
32 
34 
35 /*----------------------SVertex methods ----------------------------*/
36 
37 PyDoc_STRVAR(SVertex_doc,
38  "Class hierarchy: :class:`Interface0D` > :class:`SVertex`\n"
39  "\n"
40  "Class to define a vertex of the embedding.\n"
41  "\n"
42  ".. method:: __init__()\n"
43  " __init__(brother)\n"
44  " __init__(point_3d, id)\n"
45  "\n"
46  " Builds a :class:`SVertex` using the default constructor,\n"
47  " copy constructor or the overloaded constructor which builds"
48  " a :class:`SVertex` from 3D coordinates and an Id.\n"
49  "\n"
50  " :arg brother: A SVertex object.\n"
51  " :type brother: :class:`SVertex`\n"
52  " :arg point_3d: A three-dimensional vector.\n"
53  " :type point_3d: :class:`mathutils.Vector`\n"
54  " :arg id: An Id object.\n"
55  " :type id: :class:`Id`");
56 
57 static int SVertex_init(BPy_SVertex *self, PyObject *args, PyObject *kwds)
58 {
59  static const char *kwlist_1[] = {"brother", nullptr};
60  static const char *kwlist_2[] = {"point_3d", "id", nullptr};
61  PyObject *obj = nullptr;
62  float v[3];
63 
64  if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &SVertex_Type, &obj)) {
65  if (!obj) {
66  self->sv = new SVertex();
67  }
68  else {
69  self->sv = new SVertex(*(((BPy_SVertex *)obj)->sv));
70  }
71  }
72  else if ((void)PyErr_Clear(),
73  PyArg_ParseTupleAndKeywords(
74  args, kwds, "O&O!", (char **)kwlist_2, convert_v3, v, &Id_Type, &obj)) {
75  Vec3r point_3d(v[0], v[1], v[2]);
76  self->sv = new SVertex(point_3d, *(((BPy_Id *)obj)->id));
77  }
78  else {
79  PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
80  return -1;
81  }
82  self->py_if0D.if0D = self->sv;
83  self->py_if0D.borrowed = false;
84  return 0;
85 }
86 
87 PyDoc_STRVAR(SVertex_add_normal_doc,
88  ".. method:: add_normal(normal)\n"
89  "\n"
90  " Adds a normal to the SVertex's set of normals. If the same normal\n"
91  " is already in the set, nothing changes.\n"
92  "\n"
93  " :arg normal: A three-dimensional vector.\n"
94  " :type normal: :class:`mathutils.Vector`, list or tuple of 3 real numbers");
95 
96 static PyObject *SVertex_add_normal(BPy_SVertex *self, PyObject *args, PyObject *kwds)
97 {
98  static const char *kwlist[] = {"normal", nullptr};
99  PyObject *py_normal;
100  Vec3r n;
101 
102  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &py_normal)) {
103  return nullptr;
104  }
105  if (!Vec3r_ptr_from_PyObject(py_normal, n)) {
106  PyErr_SetString(PyExc_TypeError,
107  "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
108  return nullptr;
109  }
110  self->sv->AddNormal(n);
111  Py_RETURN_NONE;
112 }
113 
114 PyDoc_STRVAR(SVertex_add_fedge_doc,
115  ".. method:: add_fedge(fedge)\n"
116  "\n"
117  " Add an FEdge to the list of edges emanating from this SVertex.\n"
118  "\n"
119  " :arg fedge: An FEdge.\n"
120  " :type fedge: :class:`FEdge`");
121 
122 static PyObject *SVertex_add_fedge(BPy_SVertex *self, PyObject *args, PyObject *kwds)
123 {
124  static const char *kwlist[] = {"fedge", nullptr};
125  PyObject *py_fe;
126 
127  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &FEdge_Type, &py_fe)) {
128  return nullptr;
129  }
130  self->sv->AddFEdge(((BPy_FEdge *)py_fe)->fe);
131  Py_RETURN_NONE;
132 }
133 
134 // virtual bool operator== (const SVertex &brother)
135 
136 static PyMethodDef BPy_SVertex_methods[] = {
137  {"add_normal",
138  (PyCFunction)SVertex_add_normal,
139  METH_VARARGS | METH_KEYWORDS,
140  SVertex_add_normal_doc},
141  {"add_fedge",
142  (PyCFunction)SVertex_add_fedge,
143  METH_VARARGS | METH_KEYWORDS,
144  SVertex_add_fedge_doc},
145  {nullptr, nullptr, 0, nullptr},
146 };
147 
148 /*----------------------mathutils callbacks ----------------------------*/
149 
150 /* subtype */
151 #define MATHUTILS_SUBTYPE_POINT3D 1
152 #define MATHUTILS_SUBTYPE_POINT2D 2
153 
155 {
156  if (!BPy_SVertex_Check(bmo->cb_user)) {
157  return -1;
158  }
159  return 0;
160 }
161 
162 static int SVertex_mathutils_get(BaseMathObject *bmo, int subtype)
163 {
164  BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user;
165  switch (subtype) {
167  bmo->data[0] = self->sv->getX();
168  bmo->data[1] = self->sv->getY();
169  bmo->data[2] = self->sv->getZ();
170  break;
172  bmo->data[0] = self->sv->getProjectedX();
173  bmo->data[1] = self->sv->getProjectedY();
174  bmo->data[2] = self->sv->getProjectedZ();
175  break;
176  default:
177  return -1;
178  }
179  return 0;
180 }
181 
182 static int SVertex_mathutils_set(BaseMathObject *bmo, int subtype)
183 {
184  BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user;
185  switch (subtype) {
187  Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]);
188  self->sv->setPoint3D(p);
189  } break;
191  Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]);
192  self->sv->setPoint2D(p);
193  } break;
194  default:
195  return -1;
196  }
197  return 0;
198 }
199 
200 static int SVertex_mathutils_get_index(BaseMathObject *bmo, int subtype, int index)
201 {
202  BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user;
203  switch (subtype) {
205  switch (index) {
206  case 0:
207  bmo->data[0] = self->sv->getX();
208  break;
209  case 1:
210  bmo->data[1] = self->sv->getY();
211  break;
212  case 2:
213  bmo->data[2] = self->sv->getZ();
214  break;
215  default:
216  return -1;
217  }
218  break;
220  switch (index) {
221  case 0:
222  bmo->data[0] = self->sv->getProjectedX();
223  break;
224  case 1:
225  bmo->data[1] = self->sv->getProjectedY();
226  break;
227  case 2:
228  bmo->data[2] = self->sv->getProjectedZ();
229  break;
230  default:
231  return -1;
232  }
233  break;
234  default:
235  return -1;
236  }
237  return 0;
238 }
239 
240 static int SVertex_mathutils_set_index(BaseMathObject *bmo, int subtype, int index)
241 {
242  BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user;
243  switch (subtype) {
245  Vec3r p(self->sv->point3D());
246  p[index] = bmo->data[index];
247  self->sv->setPoint3D(p);
248  } break;
250  Vec3r p(self->sv->point2D());
251  p[index] = bmo->data[index];
252  self->sv->setPoint2D(p);
253  } break;
254  default:
255  return -1;
256  }
257  return 0;
258 }
259 
266 };
267 
268 static unsigned char SVertex_mathutils_cb_index = -1;
269 
271 {
273 }
274 
275 /*----------------------SVertex get/setters ----------------------------*/
276 
277 PyDoc_STRVAR(SVertex_point_3d_doc,
278  "The 3D coordinates of the SVertex.\n"
279  "\n"
280  ":type: :class:`mathutils.Vector`");
281 
282 static PyObject *SVertex_point_3d_get(BPy_SVertex *self, void *UNUSED(closure))
283 {
286 }
287 
288 static int SVertex_point_3d_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure))
289 {
290  float v[3];
291  if (mathutils_array_parse(v, 3, 3, value, "value must be a 3-dimensional vector") == -1) {
292  return -1;
293  }
294  Vec3r p(v[0], v[1], v[2]);
295  self->sv->setPoint3D(p);
296  return 0;
297 }
298 
299 PyDoc_STRVAR(SVertex_point_2d_doc,
300  "The projected 3D coordinates of the SVertex.\n"
301  "\n"
302  ":type: :class:`mathutils.Vector`");
303 
304 static PyObject *SVertex_point_2d_get(BPy_SVertex *self, void *UNUSED(closure))
305 {
308 }
309 
310 static int SVertex_point_2d_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure))
311 {
312  float v[3];
313  if (mathutils_array_parse(v, 3, 3, value, "value must be a 3-dimensional vector") == -1) {
314  return -1;
315  }
316  Vec3r p(v[0], v[1], v[2]);
317  self->sv->setPoint2D(p);
318  return 0;
319 }
320 
321 PyDoc_STRVAR(SVertex_id_doc,
322  "The Id of this SVertex.\n"
323  "\n"
324  ":type: :class:`Id`");
325 
326 static PyObject *SVertex_id_get(BPy_SVertex *self, void *UNUSED(closure))
327 {
328  Id id(self->sv->getId());
329  return BPy_Id_from_Id(id); // return a copy
330 }
331 
332 static int SVertex_id_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure))
333 {
334  if (!BPy_Id_Check(value)) {
335  PyErr_SetString(PyExc_TypeError, "value must be an Id");
336  return -1;
337  }
338  self->sv->setId(*(((BPy_Id *)value)->id));
339  return 0;
340 }
341 
342 PyDoc_STRVAR(SVertex_normals_doc,
343  "The normals for this Vertex as a list. In a sharp surface, an SVertex\n"
344  "has exactly one normal. In a smooth surface, an SVertex can have any\n"
345  "number of normals.\n"
346  "\n"
347  ":type: list of :class:`mathutils.Vector` objects");
348 
349 static PyObject *SVertex_normals_get(BPy_SVertex *self, void *UNUSED(closure))
350 {
351  PyObject *py_normals;
352  set<Vec3r> normals = self->sv->normals();
353  set<Vec3r>::iterator it;
354  py_normals = PyList_New(normals.size());
355  unsigned int i = 0;
356 
357  for (it = normals.begin(); it != normals.end(); it++) {
358  Vec3r v(*it);
359  PyList_SET_ITEM(py_normals, i++, Vector_from_Vec3r(v));
360  }
361  return py_normals;
362 }
363 
364 PyDoc_STRVAR(SVertex_normals_size_doc,
365  "The number of different normals for this SVertex.\n"
366  "\n"
367  ":type: int");
368 
369 static PyObject *SVertex_normals_size_get(BPy_SVertex *self, void *UNUSED(closure))
370 {
371  return PyLong_FromLong(self->sv->normalsSize());
372 }
373 
374 PyDoc_STRVAR(SVertex_viewvertex_doc,
375  "If this SVertex is also a ViewVertex, this property refers to the\n"
376  "ViewVertex, and None otherwise.\n"
377  "\n"
378  ":type: :class:`ViewVertex`");
379 
380 static PyObject *SVertex_viewvertex_get(BPy_SVertex *self, void *UNUSED(closure))
381 {
382  ViewVertex *vv = self->sv->viewvertex();
383  if (vv) {
385  }
386  Py_RETURN_NONE;
387 }
388 
389 PyDoc_STRVAR(SVertex_curvatures_doc,
390  "Curvature information expressed in the form of a seven-element tuple\n"
391  "(K1, e1, K2, e2, Kr, er, dKr), where K1 and K2 are scalar values\n"
392  "representing the first (maximum) and second (minimum) principal\n"
393  "curvatures at this SVertex, respectively; e1 and e2 are\n"
394  "three-dimensional vectors representing the first and second principal\n"
395  "directions, i.e. the directions of the normal plane where the\n"
396  "curvature takes its maximum and minimum values, respectively; and Kr,\n"
397  "er and dKr are the radial curvature, radial direction, and the\n"
398  "derivative of the radial curvature at this SVertex, respectively.\n"
399  "\n"
400  ":type: tuple");
401 
402 static PyObject *SVertex_curvatures_get(BPy_SVertex *self, void *UNUSED(closure))
403 {
404  const CurvatureInfo *info = self->sv->getCurvatureInfo();
405  if (!info) {
406  Py_RETURN_NONE;
407  }
408  Vec3r e1(info->e1.x(), info->e1.y(), info->e1.z());
409  Vec3r e2(info->e2.x(), info->e2.y(), info->e2.z());
410  Vec3r er(info->er.x(), info->er.y(), info->er.z());
411  PyObject *retval = PyTuple_New(7);
412  PyTuple_SET_ITEMS(retval,
413  PyFloat_FromDouble(info->K1),
414  PyFloat_FromDouble(info->K2),
415  Vector_from_Vec3r(e1),
416  Vector_from_Vec3r(e2),
417  PyFloat_FromDouble(info->Kr),
418  Vector_from_Vec3r(er),
419  PyFloat_FromDouble(info->dKr));
420  return retval;
421 }
422 
423 static PyGetSetDef BPy_SVertex_getseters[] = {
424  {"point_3d",
425  (getter)SVertex_point_3d_get,
426  (setter)SVertex_point_3d_set,
427  SVertex_point_3d_doc,
428  nullptr},
429  {"point_2d",
430  (getter)SVertex_point_2d_get,
431  (setter)SVertex_point_2d_set,
432  SVertex_point_2d_doc,
433  nullptr},
434  {"id", (getter)SVertex_id_get, (setter)SVertex_id_set, SVertex_id_doc, nullptr},
435  {"normals", (getter)SVertex_normals_get, (setter) nullptr, SVertex_normals_doc, nullptr},
436  {"normals_size",
437  (getter)SVertex_normals_size_get,
438  (setter) nullptr,
439  SVertex_normals_size_doc,
440  nullptr},
441  {"viewvertex",
442  (getter)SVertex_viewvertex_get,
443  (setter) nullptr,
444  SVertex_viewvertex_doc,
445  nullptr},
446  {"curvatures",
447  (getter)SVertex_curvatures_get,
448  (setter) nullptr,
449  SVertex_curvatures_doc,
450  nullptr},
451  {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
452 };
453 
454 /*-----------------------BPy_SVertex type definition ------------------------------*/
455 PyTypeObject SVertex_Type = {
456  PyVarObject_HEAD_INIT(nullptr, 0) "SVertex", /* tp_name */
457  sizeof(BPy_SVertex), /* tp_basicsize */
458  0, /* tp_itemsize */
459  nullptr, /* tp_dealloc */
460  0, /* tp_vectorcall_offset */
461  nullptr, /* tp_getattr */
462  nullptr, /* tp_setattr */
463  nullptr, /* tp_reserved */
464  nullptr, /* tp_repr */
465  nullptr, /* tp_as_number */
466  nullptr, /* tp_as_sequence */
467  nullptr, /* tp_as_mapping */
468  nullptr, /* tp_hash */
469  nullptr, /* tp_call */
470  nullptr, /* tp_str */
471  nullptr, /* tp_getattro */
472  nullptr, /* tp_setattro */
473  nullptr, /* tp_as_buffer */
474  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
475  SVertex_doc, /* tp_doc */
476  nullptr, /* tp_traverse */
477  nullptr, /* tp_clear */
478  nullptr, /* tp_richcompare */
479  0, /* tp_weaklistoffset */
480  nullptr, /* tp_iter */
481  nullptr, /* tp_iternext */
482  BPy_SVertex_methods, /* tp_methods */
483  nullptr, /* tp_members */
484  BPy_SVertex_getseters, /* tp_getset */
485  &Interface0D_Type, /* tp_base */
486  nullptr, /* tp_dict */
487  nullptr, /* tp_descr_get */
488  nullptr, /* tp_descr_set */
489  0, /* tp_dictoffset */
490  (initproc)SVertex_init, /* tp_init */
491  nullptr, /* tp_alloc */
492  nullptr, /* tp_new */
493 };
494 
496 
497 #ifdef __cplusplus
498 }
499 #endif
#define UNUSED(x)
PyObject * BPy_Id_from_Id(Id &id)
int convert_v3(PyObject *obj, void *v)
bool Vec3r_ptr_from_PyObject(PyObject *obj, Vec3r &vec)
PyObject * Any_BPy_ViewVertex_from_ViewVertex(ViewVertex &vv)
PyObject * Vector_from_Vec3r(Vec3r &vec)
Definition: BPy_Convert.cpp:95
PyTypeObject FEdge_Type
Definition: BPy_FEdge.cpp:358
PyTypeObject Id_Type
Definition: BPy_Id.cpp:171
#define BPy_Id_Check(v)
Definition: BPy_Id.h:39
PyTypeObject Interface0D_Type
static int SVertex_point_2d_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure))
static PyObject * SVertex_curvatures_get(BPy_SVertex *self, void *UNUSED(closure))
#define MATHUTILS_SUBTYPE_POINT3D
static unsigned char SVertex_mathutils_cb_index
#define MATHUTILS_SUBTYPE_POINT2D
static PyObject * SVertex_add_fedge(BPy_SVertex *self, PyObject *args, PyObject *kwds)
void SVertex_mathutils_register_callback()
static PyObject * SVertex_point_3d_get(BPy_SVertex *self, void *UNUSED(closure))
static PyObject * SVertex_point_2d_get(BPy_SVertex *self, void *UNUSED(closure))
static PyObject * SVertex_normals_size_get(BPy_SVertex *self, void *UNUSED(closure))
static int SVertex_point_3d_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure))
static PyObject * SVertex_id_get(BPy_SVertex *self, void *UNUSED(closure))
static int SVertex_id_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure))
PyTypeObject SVertex_Type
static int SVertex_mathutils_set_index(BaseMathObject *bmo, int subtype, int index)
static PyMethodDef BPy_SVertex_methods[]
static int SVertex_init(BPy_SVertex *self, PyObject *args, PyObject *kwds)
Definition: BPy_SVertex.cpp:57
static PyObject * SVertex_add_normal(BPy_SVertex *self, PyObject *args, PyObject *kwds)
Definition: BPy_SVertex.cpp:96
static Mathutils_Callback SVertex_mathutils_cb
static PyObject * SVertex_viewvertex_get(BPy_SVertex *self, void *UNUSED(closure))
static int SVertex_mathutils_get(BaseMathObject *bmo, int subtype)
PyDoc_STRVAR(SVertex_doc, "Class hierarchy: :class:`Interface0D` > :class:`SVertex`\n" "\n" "Class to define a vertex of the embedding.\n" "\n" ".. method:: __init__()\n" " __init__(brother)\n" " __init__(point_3d, id)\n" "\n" " Builds a :class:`SVertex` using the default constructor,\n" " copy constructor or the overloaded constructor which builds" " a :class:`SVertex` from 3D coordinates and an Id.\n" "\n" " :arg brother: A SVertex object.\n" " :type brother: :class:`SVertex`\n" " :arg point_3d: A three-dimensional vector.\n" " :type point_3d: :class:`mathutils.Vector`\n" " :arg id: An Id object.\n" " :type id: :class:`Id`")
static int SVertex_mathutils_set(BaseMathObject *bmo, int subtype)
static PyObject * SVertex_normals_get(BPy_SVertex *self, void *UNUSED(closure))
static int SVertex_mathutils_get_index(BaseMathObject *bmo, int subtype, int index)
static int SVertex_mathutils_check(BaseMathObject *bmo)
static PyGetSetDef BPy_SVertex_getseters[]
#define BPy_SVertex_Check(v)
Definition: BPy_SVertex.h:35
ATTR_WARN_UNUSED_RESULT const BMVert * v
PyObject * self
Definition: bpy_driver.c:185
value_type x() const
Definition: VecMat.h:532
value_type z() const
Definition: VecMat.h:552
value_type y() const
Definition: VecMat.h:542
static float normals[][3]
uchar Mathutils_RegisterCallback(Mathutils_Callback *cb)
Definition: mathutils.c:584
int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
Definition: mathutils.c:118
PyObject * Vector_CreatePyObject_cb(PyObject *cb_user, int size, uchar cb_type, uchar cb_subtype)
inherits from class Rep
Definition: AppCanvas.cpp:32
#define PyTuple_SET_ITEMS(op_arg,...)
Definition: BPy_Id.h:42