Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/freestyle/intern/python/Interface0D')
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp246
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp448
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h36
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp199
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp338
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h35
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp143
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp222
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h31
12 files changed, 1791 insertions, 0 deletions
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
new file mode 100644
index 00000000000..3e2cc495785
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
@@ -0,0 +1,246 @@
+#include "BPy_CurvePoint.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface0D/BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*----------------------CurvePoint methods----------------------------*/
+
+PyDoc_STRVAR(CurvePoint_doc,
+"Class hierarchy: :class:`Interface0D` > :class:`CurvePoint`\n"
+"\n"
+"Class to represent a point of a curve. A CurvePoint can be any point\n"
+"of a 1D curve (it doesn't have to be a vertex of the curve). Any\n"
+":class:`Interface1D` is built upon ViewEdges, themselves built upon\n"
+"FEdges. Therefore, a curve is basically a polyline made of a list of\n"
+":class:`SVertex` objects. Thus, a CurvePoint is built by linearly\n"
+"interpolating two :class:`SVertex` instances. CurvePoint can be used\n"
+"as virtual points while querying 0D information along a curve at a\n"
+"given resolution.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Defult constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A CurvePoint object.\n"
+" :type iBrother: :class:`CurvePoint`\n"
+"\n"
+".. method:: __init__(iA, iB, t2d)\n"
+"\n"
+" Builds a CurvePoint from two SVertex and an interpolation parameter.\n"
+"\n"
+" :arg iA: The first SVertex.\n"
+" :type iA: :class:`SVertex`\n"
+" :arg iB: The second SVertex.\n"
+" :type iB: :class:`SVertex`\n"
+" :arg t2d: A 2D interpolation parameter used to linearly interpolate\n"
+" iA and iB.\n"
+" :type t2d: float\n"
+"\n"
+".. method:: __init__(iA, iB, t2d)\n"
+"\n"
+" Builds a CurvePoint from two CurvePoint and an interpolation\n"
+" parameter.\n"
+"\n"
+" :arg iA: The first CurvePoint.\n"
+" :type iA: :class:`CurvePoint`\n"
+" :arg iB: The second CurvePoint.\n"
+" :type iB: :class:`CurvePoint`\n"
+" :arg t2d: The 2D interpolation parameter used to linearly\n"
+" interpolate iA and iB.\n"
+" :type t2d: float");
+
+static int CurvePoint_init(BPy_CurvePoint *self, PyObject *args, PyObject *kwds)
+{
+
+ PyObject *obj1 = 0, *obj2 = 0 , *obj3 = 0;
+
+ if (! PyArg_ParseTuple(args, "|OOO!", &obj1, &obj2, &PyFloat_Type, &obj3) )
+ return -1;
+
+ if( !obj1 ){
+ self->cp = new CurvePoint();
+
+ } else if( !obj2 && BPy_CurvePoint_Check(obj1) ) {
+ self->cp = new CurvePoint( *(((BPy_CurvePoint *) obj1)->cp) );
+
+ } else if( obj3 && BPy_SVertex_Check(obj1) && BPy_SVertex_Check(obj2) ) {
+ self->cp = new CurvePoint( ((BPy_SVertex *) obj1)->sv,
+ ((BPy_SVertex *) obj2)->sv,
+ PyFloat_AsDouble( obj3 ) );
+
+ } else if( obj3 && BPy_CurvePoint_Check(obj1) && BPy_CurvePoint_Check(obj2) ) {
+ CurvePoint *cp1 = ((BPy_CurvePoint *) obj1)->cp;
+ CurvePoint *cp2 = ((BPy_CurvePoint *) obj2)->cp;
+ if( !cp1 || cp1->A() == 0 || cp1->B() == 0 ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid CurvePoint object");
+ return -1;
+ }
+ if( !cp2 || cp2->A() == 0 || cp2->B() == 0 ) {
+ PyErr_SetString(PyExc_TypeError, "argument 2 is an invalid CurvePoint object");
+ return -1;
+ }
+ self->cp = new CurvePoint( cp1, cp2, PyFloat_AsDouble( obj3 ) );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_if0D.if0D = self->cp;
+ self->py_if0D.borrowed = 0;
+
+ return 0;
+}
+
+///bool operator== (const CurvePoint &b)
+
+static PyMethodDef BPy_CurvePoint_methods[] = {
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------CurvePoint get/setters ----------------------------*/
+
+PyDoc_STRVAR(CurvePoint_first_svertex_doc,
+"The first SVertex upon which the CurvePoint is built.\n"
+"\n"
+":type: int");
+
+static PyObject *CurvePoint_first_svertex_get(BPy_CurvePoint *self, void *UNUSED(closure))
+{
+ SVertex *A = self->cp->A();
+ if (A)
+ return BPy_SVertex_from_SVertex(*A);
+ Py_RETURN_NONE;
+}
+
+static int CurvePoint_first_svertex_set(BPy_CurvePoint *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_SVertex_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
+ return -1;
+ }
+ self->cp->setA(((BPy_SVertex *)value)->sv);
+ return 0;
+}
+
+PyDoc_STRVAR(CurvePoint_second_svertex_doc,
+"The second SVertex upon which the CurvePoint is built.\n"
+"\n"
+":type: int");
+
+static PyObject *CurvePoint_second_svertex_get(BPy_CurvePoint *self, void *UNUSED(closure))
+{
+ SVertex *B = self->cp->B();
+ if (B)
+ return BPy_SVertex_from_SVertex(*B);
+ Py_RETURN_NONE;
+}
+
+static int CurvePoint_second_svertex_set(BPy_CurvePoint *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_SVertex_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
+ return -1;
+ }
+ self->cp->setB(((BPy_SVertex *)value)->sv);
+ return 0;
+}
+
+PyDoc_STRVAR(CurvePoint_t2d_doc,
+"The 2D interpolation parameter.\n"
+"\n"
+":type: float");
+
+static PyObject *CurvePoint_t2d_get(BPy_CurvePoint *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->cp->t2d());
+}
+
+static int CurvePoint_t2d_set(BPy_CurvePoint *self, PyObject *value, void *UNUSED(closure))
+{
+ float scalar;
+ if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, "value must be a number");
+ return -1;
+ }
+ self->cp->setT2d(scalar);
+ return 0;
+}
+
+PyDoc_STRVAR(CurvePoint_curvature_fredo_doc,
+"The angle (Fredo's curvature) in radians.\n"
+"\n"
+":type: float");
+
+static PyObject *CurvePoint_curvature_fredo_get(BPy_CurvePoint *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->cp->curvatureFredo());
+}
+
+// todo - CurvePoint.directionFredo()
+
+static PyGetSetDef BPy_CurvePoint_getseters[] = {
+ {(char *)"first_svertex", (getter)CurvePoint_first_svertex_get, (setter)CurvePoint_first_svertex_set, (char *)CurvePoint_first_svertex_doc, NULL},
+ {(char *)"second_svertex", (getter)CurvePoint_second_svertex_get, (setter)CurvePoint_second_svertex_set, (char *)CurvePoint_second_svertex_doc, NULL},
+ {(char *)"t2d", (getter)CurvePoint_t2d_get, (setter)CurvePoint_t2d_set, (char *)CurvePoint_t2d_doc, NULL},
+ {(char *)"curvature_fredo", (getter)CurvePoint_curvature_fredo_get, (setter)NULL, (char *)CurvePoint_curvature_fredo_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_CurvePoint type definition ------------------------------*/
+PyTypeObject CurvePoint_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "CurvePoint", /* tp_name */
+ sizeof(BPy_CurvePoint), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ CurvePoint_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_CurvePoint_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_CurvePoint_getseters, /* tp_getset */
+ &Interface0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)CurvePoint_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h
new file mode 100644
index 00000000000..b4c22645503
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_CURVEPOINT_H
+#define FREESTYLE_PYTHON_CURVEPOINT_H
+
+#include "../BPy_Interface0D.h"
+#include "../../stroke/Curve.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject CurvePoint_Type;
+
+#define BPy_CurvePoint_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &CurvePoint_Type) )
+
+/*---------------------------Python BPy_CurvePoint structure definition----------*/
+typedef struct {
+ BPy_Interface0D py_if0D;
+ CurvePoint *cp;
+} BPy_CurvePoint;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CURVEPOINT_H */
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
new file mode 100644
index 00000000000..0d0a772b4e5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
@@ -0,0 +1,448 @@
+#include "BPy_SVertex.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Id.h"
+#include "../Interface1D/BPy_FEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*----------------------SVertex methods ----------------------------*/
+
+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"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A SVertex object.\n"
+" :type iBrother: :class:`SVertex`\n"
+"\n"
+".. method:: __init__(iPoint3D, id)\n"
+"\n"
+" Builds a SVertex from 3D coordinates and an Id.\n"
+"\n"
+" :arg iPoint3D: A three-dimensional vector.\n"
+" :type iPoint3D: :class:`mathutils.Vector`\n"
+" :arg id: An Id object.\n"
+" :type id: :class:`Id`");
+
+static int SVertex_init(BPy_SVertex *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *py_point = 0;
+ BPy_Id *py_id = 0;
+
+ if (!PyArg_ParseTuple(args, "|OO!", &py_point, &Id_Type, &py_id))
+ return -1;
+
+ if (!py_point) {
+ self->sv = new SVertex();
+
+ } else if (!py_id && BPy_SVertex_Check(py_point)) {
+ self->sv = new SVertex( *(((BPy_SVertex *)py_point)->sv) );
+
+ } else if (py_point && py_id) {
+ Vec3r *v = Vec3r_ptr_from_PyObject(py_point);
+ if (!v) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return -1;
+ }
+ self->sv = new SVertex(*v, *(py_id->id));
+ delete v;
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_if0D.if0D = self->sv;
+ self->py_if0D.borrowed = 0;
+
+ return 0;
+}
+
+PyDoc_STRVAR(SVertex_add_normal_doc,
+".. method:: add_normal(n)\n"
+"\n"
+" Adds a normal to the SVertex's set of normals. If the same normal\n"
+" is already in the set, nothing changes.\n"
+"\n"
+" :arg n: A three-dimensional vector.\n"
+" :type n: :class:`mathutils.Vector`, list or tuple of 3 real numbers");
+
+static PyObject *SVertex_add_normal( BPy_SVertex *self , PyObject *args) {
+ PyObject *py_normal;
+
+ if (!PyArg_ParseTuple(args, "O", &py_normal))
+ return NULL;
+ Vec3r *n = Vec3r_ptr_from_PyObject(py_normal);
+ if (!n) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->sv->AddNormal(*n);
+ delete n;
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(SVertex_add_fedge_doc,
+".. method:: add_fedge(fe)\n"
+"\n"
+" Add an FEdge to the list of edges emanating from this SVertex.\n"
+"\n"
+" :arg fe: An FEdge.\n"
+" :type fe: :class:`FEdge`");
+
+static PyObject *SVertex_add_fedge( BPy_SVertex *self , PyObject *args) {
+ PyObject *py_fe;
+
+ if (!PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe))
+ return NULL;
+
+ self->sv->AddFEdge(((BPy_FEdge *)py_fe)->fe);
+
+ Py_RETURN_NONE;
+}
+
+// virtual bool operator== (const SVertex &iBrother)
+
+static PyMethodDef BPy_SVertex_methods[] = {
+ {"add_normal", (PyCFunction)SVertex_add_normal, METH_VARARGS, SVertex_add_normal_doc},
+ {"add_fedge", (PyCFunction)SVertex_add_fedge, METH_VARARGS, SVertex_add_fedge_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------mathutils callbacks ----------------------------*/
+
+/* subtype */
+#define MATHUTILS_SUBTYPE_POINT3D 1
+#define MATHUTILS_SUBTYPE_POINT2D 2
+
+static int SVertex_mathutils_check(BaseMathObject *bmo)
+{
+ if (!BPy_SVertex_Check(bmo->cb_user))
+ return -1;
+ return 0;
+}
+
+static int SVertex_mathutils_get(BaseMathObject *bmo, int subtype)
+{
+ BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_POINT3D:
+ bmo->data[0] = self->sv->getX();
+ bmo->data[1] = self->sv->getY();
+ bmo->data[2] = self->sv->getZ();
+ break;
+ case MATHUTILS_SUBTYPE_POINT2D:
+ bmo->data[0] = self->sv->getProjectedX();
+ bmo->data[1] = self->sv->getProjectedY();
+ bmo->data[2] = self->sv->getProjectedZ();
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int SVertex_mathutils_set(BaseMathObject *bmo, int subtype)
+{
+ BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_POINT3D:
+ {
+ Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]);
+ self->sv->setPoint3D(p);
+ }
+ break;
+ case MATHUTILS_SUBTYPE_POINT2D:
+ {
+ Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]);
+ self->sv->setPoint2D(p);
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int SVertex_mathutils_get_index(BaseMathObject *bmo, int subtype, int index)
+{
+ BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_POINT3D:
+ switch (index) {
+ case 0: bmo->data[0] = self->sv->getX(); break;
+ case 1: bmo->data[1] = self->sv->getY(); break;
+ case 2: bmo->data[2] = self->sv->getZ(); break;
+ default:
+ return -1;
+ }
+ break;
+ case MATHUTILS_SUBTYPE_POINT2D:
+ switch (index) {
+ case 0: bmo->data[0] = self->sv->getProjectedX(); break;
+ case 1: bmo->data[1] = self->sv->getProjectedY(); break;
+ case 2: bmo->data[2] = self->sv->getProjectedZ(); break;
+ default:
+ return -1;
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int SVertex_mathutils_set_index(BaseMathObject *bmo, int subtype, int index)
+{
+ BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_POINT3D:
+ {
+ Vec3r p(self->sv->point3D());
+ p[index] = bmo->data[index];
+ self->sv->setPoint3D(p);
+ }
+ break;
+ case MATHUTILS_SUBTYPE_POINT2D:
+ {
+ Vec3r p(self->sv->point2D());
+ p[index] = bmo->data[index];
+ self->sv->setPoint2D(p);
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static Mathutils_Callback SVertex_mathutils_cb = {
+ SVertex_mathutils_check,
+ SVertex_mathutils_get,
+ SVertex_mathutils_set,
+ SVertex_mathutils_get_index,
+ SVertex_mathutils_set_index
+};
+
+static unsigned char SVertex_mathutils_cb_index = -1;
+
+void SVertex_mathutils_register_callback()
+{
+ SVertex_mathutils_cb_index = Mathutils_RegisterCallback(&SVertex_mathutils_cb);
+}
+
+/*----------------------SVertex get/setters ----------------------------*/
+
+PyDoc_STRVAR(SVertex_point_3d_doc,
+"The 3D coordinates of the SVertex.\n"
+"\n"
+":type: mathutils.Vector");
+
+static PyObject *SVertex_point_3d_get(BPy_SVertex *self, void *UNUSED(closure))
+{
+ return Vector_CreatePyObject_cb((PyObject *)self, 3, SVertex_mathutils_cb_index, MATHUTILS_SUBTYPE_POINT3D);
+}
+
+static int SVertex_point_3d_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ float v[3];
+ if (!float_array_from_PyObject(value, v, 3)) {
+ PyErr_SetString(PyExc_ValueError, "value must be a 3-dimensional vector");
+ return -1;
+ }
+ Vec3r p(v[0], v[1], v[2]);
+ self->sv->setPoint3D(p);
+ return 0;
+}
+
+PyDoc_STRVAR(SVertex_point_2d_doc,
+"The projected 3D coordinates of the SVertex.\n"
+"\n"
+":type: mathutils.Vector");
+
+static PyObject *SVertex_point_2d_get(BPy_SVertex *self, void *UNUSED(closure))
+{
+ return Vector_CreatePyObject_cb((PyObject *)self, 3, SVertex_mathutils_cb_index, MATHUTILS_SUBTYPE_POINT2D);
+}
+
+static int SVertex_point_2d_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ float v[3];
+ if (!float_array_from_PyObject(value, v, 3)) {
+ PyErr_SetString(PyExc_ValueError, "value must be a 3-dimensional vector");
+ return -1;
+ }
+ Vec3r p(v[0], v[1], v[2]);
+ self->sv->setPoint2D(p);
+ return 0;
+}
+
+PyDoc_STRVAR(SVertex_id_doc,
+"The Id of this SVertex.\n"
+"\n"
+":type: :class:`Id`");
+
+static PyObject *SVertex_id_get(BPy_SVertex *self, void *UNUSED(closure))
+{
+ Id id(self->sv->getId());
+ return BPy_Id_from_Id(id); // return a copy
+}
+
+static int SVertex_id_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_Id_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an Id");
+ return -1;
+ }
+ self->sv->setId(*(((BPy_Id *)value)->id));
+ return 0;
+}
+
+PyDoc_STRVAR(SVertex_normals_doc,
+"The normals for this Vertex as a list. In a sharp surface, an SVertex\n"
+"has exactly one normal. In a smooth surface, an SVertex can have any\n"
+"number of normals.\n"
+"\n"
+":type: list of :class:`mathutils.Vector` objects");
+
+static PyObject *SVertex_normals_get(BPy_SVertex *self, void *UNUSED(closure))
+{
+ PyObject *py_normals;
+ set< Vec3r > normals;
+
+ py_normals = PyList_New(0);
+ normals = self->sv->normals();
+ for (set< Vec3r >::iterator set_iterator = normals.begin(); set_iterator != normals.end(); set_iterator++) {
+ Vec3r v(*set_iterator);
+ PyList_Append(py_normals, Vector_from_Vec3r(v));
+ }
+ return py_normals;
+}
+
+PyDoc_STRVAR(SVertex_normals_size_doc,
+"The number of different normals for this SVertex.\n"
+"\n"
+":type: int");
+
+static PyObject *SVertex_normals_size_get(BPy_SVertex *self, void *UNUSED(closure))
+{
+ return PyLong_FromLong(self->sv->normalsSize());
+}
+
+PyDoc_STRVAR(SVertex_viewvertex_doc,
+"If this SVertex is also a ViewVertex, this property refers to the\n"
+"ViewVertex, and None otherwise.\n"
+":type: :class:`ViewVertex`");
+
+static PyObject *SVertex_viewvertex_get(BPy_SVertex *self, void *UNUSED(closure))
+{
+ ViewVertex *vv = self->sv->viewvertex();
+ if (vv)
+ return Any_BPy_ViewVertex_from_ViewVertex(*vv);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(SVertex_curvatures_doc,
+"Curvature information expressed in the form of a seven-element tuple\n"
+"(K1, e1, K2, e2, Kr, er, dKr), where K1 and K2 are scalar values\n"
+"representing the first (maximum) and second (minimum) principal\n"
+"curvatures at this SVertex, respectively; e1 and e2 are\n"
+"three-dimensional vectors representing the first and second principal\n"
+"directions, i.e. the directions of the normal plane where the\n"
+"curvature takes its maximum and minimum values, respectively; and Kr,\n"
+"er and dKr are the radial curvature, radial direction, and the\n"
+"derivative of the radial curvature at this SVertex, repectively.\n"
+"\n"
+":type: tuple");
+
+static PyObject *SVertex_curvatures_get(BPy_SVertex *self, void *UNUSED(closure))
+{
+ const CurvatureInfo *info = self->sv->getCurvatureInfo();
+ if (!info)
+ Py_RETURN_NONE;
+ Vec3r e1(info->e1.x(), info->e1.y(), info->e1.z());
+ Vec3r e2(info->e2.x(), info->e2.y(), info->e2.z());
+ Vec3r er(info->er.x(), info->er.y(), info->er.z());
+ PyObject *retval = PyTuple_New(7);
+ PyTuple_SET_ITEM(retval, 0, PyFloat_FromDouble(info->K1));
+ PyTuple_SET_ITEM(retval, 2, Vector_from_Vec3r(e1));
+ PyTuple_SET_ITEM(retval, 1, PyFloat_FromDouble(info->K2));
+ PyTuple_SET_ITEM(retval, 3, Vector_from_Vec3r(e2));
+ PyTuple_SET_ITEM(retval, 4, PyFloat_FromDouble(info->Kr));
+ PyTuple_SET_ITEM(retval, 5, Vector_from_Vec3r(er));
+ PyTuple_SET_ITEM(retval, 6, PyFloat_FromDouble(info->dKr));
+ return retval;
+}
+
+static PyGetSetDef BPy_SVertex_getseters[] = {
+ {(char *)"point_3d", (getter)SVertex_point_3d_get, (setter)SVertex_point_3d_set, (char *)SVertex_point_3d_doc, NULL},
+ {(char *)"point_2d", (getter)SVertex_point_2d_get, (setter)SVertex_point_2d_set, (char *)SVertex_point_2d_doc, NULL},
+ {(char *)"id", (getter)SVertex_id_get, (setter)SVertex_id_set, (char *)SVertex_id_doc, NULL},
+ {(char *)"normals", (getter)SVertex_normals_get, (setter)NULL, (char *)SVertex_normals_doc, NULL},
+ {(char *)"normals_size", (getter)SVertex_normals_size_get, (setter)NULL, (char *)SVertex_normals_size_doc, NULL},
+ {(char *)"viewvertex", (getter)SVertex_viewvertex_get, (setter)NULL, (char *)SVertex_viewvertex_doc, NULL},
+ {(char *)"curvatures", (getter)SVertex_curvatures_get, (setter)NULL, (char *)SVertex_curvatures_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_SVertex type definition ------------------------------*/
+PyTypeObject SVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SVertex", /* tp_name */
+ sizeof(BPy_SVertex), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ SVertex_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_SVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_SVertex_getseters, /* tp_getset */
+ &Interface0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SVertex_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h
new file mode 100644
index 00000000000..61c65659a5e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_SVERTEX_H
+#define FREESTYLE_PYTHON_SVERTEX_H
+
+#include "../../view_map/Silhouette.h"
+#include "../BPy_Interface0D.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SVertex_Type;
+
+#define BPy_SVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SVertex_Type) )
+
+/*---------------------------Python BPy_SVertex structure definition----------*/
+typedef struct {
+ BPy_Interface0D py_if0D;
+ SVertex *sv;
+} BPy_SVertex;
+
+/*---------------------------Python BPy_SVertex visible prototypes-----------*/
+
+void SVertex_mathutils_register_callback();
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_SVERTEX_H */
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp
new file mode 100644
index 00000000000..4fabfc508db
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp
@@ -0,0 +1,199 @@
+#include "BPy_ViewVertex.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+#include "../BPy_Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*----------------------ViewVertex methods----------------------------*/
+
+PyDoc_STRVAR(ViewVertex_doc,
+"Class hierarchy: :class:`Interface0D` > :class:`ViewVertex`\n"
+"\n"
+"Class to define a view vertex. A view vertex is a feature vertex\n"
+"corresponding to a point of the image graph, where the characteristics\n"
+"of an edge (e.g., nature and visibility) might change. A\n"
+":class:`ViewVertex` can be of two kinds: A :class:`TVertex` when it\n"
+"corresponds to the intersection between two ViewEdges or a\n"
+":class:`NonTVertex` when it corresponds to a vertex of the initial\n"
+"input mesh (it is the case for vertices such as corners for example).\n"
+"Thus, this class can be specialized into two classes, the\n"
+":class:`TVertex` class and the :class:`NonTVertex` class.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A ViewVertex object.\n"
+" :type iBrother: :class:`ViewVertex`");
+
+static int ViewVertex_init(BPy_ViewVertex *self, PyObject *args, PyObject *kwds)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return -1;
+ self->vv = 0; // ViewVertex is abstract
+ self->py_if0D.if0D = self->vv;
+ self->py_if0D.borrowed = 0;
+ return 0;
+}
+
+PyDoc_STRVAR(ViewVertex_edges_begin_doc,
+".. method:: edges_begin()\n"
+"\n"
+" Returns an iterator over the ViewEdges that goes to or comes from\n"
+" this ViewVertex pointing to the first ViewEdge of the list. The\n"
+" orientedViewEdgeIterator allows to iterate in CCW order over these\n"
+" ViewEdges and to get the orientation for each ViewEdge\n"
+" (incoming/outgoing).\n"
+"\n"
+" :return: An orientedViewEdgeIterator pointing to the first ViewEdge.\n"
+" :rtype: :class:`orientedViewEdgeIterator`");
+
+static PyObject * ViewVertex_edges_begin(BPy_ViewVertex *self)
+{
+ if (!self->vv)
+ Py_RETURN_NONE;
+ ViewVertexInternal::orientedViewEdgeIterator ove_it(self->vv->edgesBegin());
+ return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator(ove_it, 0);
+}
+
+PyDoc_STRVAR(ViewVertex_edges_end_doc,
+".. method:: edges_end()\n"
+"\n"
+" Returns an orientedViewEdgeIterator over the ViewEdges around this\n"
+" ViewVertex, pointing after the last ViewEdge.\n"
+"\n"
+" :return: An orientedViewEdgeIterator pointing after the last ViewEdge.\n"
+" :rtype: :class:`orientedViewEdgeIterator`");
+
+static PyObject * ViewVertex_edges_end(BPy_ViewVertex *self)
+{
+#if 0
+ if (!self->vv)
+ Py_RETURN_NONE;
+ ViewVertexInternal::orientedViewEdgeIterator ove_it(self->vv->edgesEnd());
+ return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator(ove_it, 1);
+#else
+ PyErr_SetString(PyExc_NotImplementedError, "edges_end method currently disabled");
+ return NULL;
+#endif
+}
+
+PyDoc_STRVAR(ViewVertex_edges_iterator_doc,
+".. method:: edges_iterator(iEdge)\n"
+"\n"
+" Returns an orientedViewEdgeIterator pointing to the ViewEdge given\n"
+" as argument.\n"
+"\n"
+" :arg iEdge: A ViewEdge object.\n"
+" :type iEdge: :class:`ViewEdge`\n"
+" :return: An orientedViewEdgeIterator pointing to the given ViewEdge.\n"
+" :rtype: :class:`orientedViewEdgeIterator`");
+
+static PyObject * ViewVertex_edges_iterator(BPy_ViewVertex *self, PyObject *args)
+{
+ PyObject *py_ve;
+
+ if (!self->vv)
+ Py_RETURN_NONE;
+ if (!PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve))
+ return NULL;
+ ViewEdge *ve = ((BPy_ViewEdge *)py_ve)->ve;
+ ViewVertexInternal::orientedViewEdgeIterator ove_it(self->vv->edgesIterator(ve));
+ return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator(ove_it, 0);
+}
+
+static PyMethodDef BPy_ViewVertex_methods[] = {
+ {"edges_begin", (PyCFunction)ViewVertex_edges_begin, METH_NOARGS, ViewVertex_edges_begin_doc},
+ {"edges_end", (PyCFunction)ViewVertex_edges_end, METH_NOARGS, ViewVertex_edges_end_doc},
+ {"edges_iterator", (PyCFunction)ViewVertex_edges_iterator, METH_VARARGS, ViewVertex_edges_iterator_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------ViewVertex get/setters ----------------------------*/
+
+PyDoc_STRVAR(ViewVertex_nature_doc,
+"The nature of this ViewVertex.\n"
+"\n"
+":type: :class:`Nature`");
+
+static PyObject *ViewVertex_nature_get(BPy_ViewVertex *self, void *UNUSED(closure))
+{
+ Nature::VertexNature nature = self->vv->getNature();
+ if (PyErr_Occurred())
+ return NULL;
+ return BPy_Nature_from_Nature(nature); // return a copy
+}
+
+static int ViewVertex_nature_set(BPy_ViewVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_Nature_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be a Nature");
+ return -1;
+ }
+ self->vv->setNature(PyLong_AsLong((PyObject *)&((BPy_Nature *)value)->i));
+ return 0;
+}
+
+static PyGetSetDef BPy_ViewVertex_getseters[] = {
+ {(char *)"nature", (getter)ViewVertex_nature_get, (setter)ViewVertex_nature_set, (char *)ViewVertex_nature_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_ViewVertex type definition ------------------------------*/
+PyTypeObject ViewVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewVertex", /* tp_name */
+ sizeof(BPy_ViewVertex), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ViewVertex_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ViewVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_ViewVertex_getseters, /* tp_getset */
+ &Interface0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewVertex_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h
new file mode 100644
index 00000000000..26c06b50d71
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_VIEWVERTEX_H
+#define FREESTYLE_PYTHON_VIEWVERTEX_H
+
+#include "../../view_map/ViewMap.h"
+#include "../BPy_Interface0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ViewVertex_Type;
+
+#define BPy_ViewVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewVertex_Type) )
+
+/*---------------------------Python BPy_ViewVertex structure definition----------*/
+typedef struct {
+ BPy_Interface0D py_if0D;
+ ViewVertex *vv;
+} BPy_ViewVertex;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_VIEWVERTEX_H */
diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
new file mode 100644
index 00000000000..ad83a6933c3
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
@@ -0,0 +1,338 @@
+#include "BPy_StrokeVertex.h"
+
+#include "../../BPy_Freestyle.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_StrokeAttribute.h"
+#include "../../Interface0D/BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../../python/mathutils/mathutils.h" /* for Vector callbacks */
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(StrokeVertex_doc,
+"Class hierarchy: :class:`Interface0D` > :class:`CurvePoint` > :class:`StrokeVertex`\n"
+"\n"
+"Class to define a stroke vertex.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A StrokeVertex object.\n"
+" :type iBrother: :class:`StrokeVertex`\n"
+"\n"
+".. method:: __init__(iA, iB, t3)\n"
+"\n"
+" Builds a stroke vertex from 2 stroke vertices and an interpolation\n"
+" parameter.\n"
+"\n"
+" :arg iA: The first StrokeVertex.\n"
+" :type iA: :class:`StrokeVertex`\n"
+" :arg iB: The second StrokeVertex.\n"
+" :type iB: :class:`StrokeVertex`\n"
+" :arg t3: An interpolation parameter.\n"
+" :type t3: float\n"
+"\n"
+".. method:: __init__(iPoint)\n"
+"\n"
+" Builds a stroke vertex from a CurvePoint\n"
+"\n"
+" :arg iPoint: A CurvePoint object.\n"
+" :type iPoint: :class:`CurvePoint`\n"
+"\n"
+".. method:: __init__(iSVertex)\n"
+"\n"
+" Builds a stroke vertex from a SVertex\n"
+"\n"
+" :arg iSVertex: An SVertex object.\n"
+" :type iSVertex: :class:`SVertex`\n"
+"\n"
+".. method:: __init__(iSVertex, iAttribute)\n"
+"\n"
+" Builds a stroke vertex from an SVertex and a StrokeAttribute object.\n"
+"\n"
+" :arg iSVertex: An SVertex object.\n"
+" :type iSVertex: :class:`SVertex`\n"
+" :arg iAttribute: A StrokeAttribute object.\n"
+" :type iAttribute: :class:`StrokeAttribute`");
+
+static int StrokeVertex_init(BPy_StrokeVertex *self, PyObject *args, PyObject *kwds)
+{
+
+ PyObject *obj1 = 0, *obj2 = 0 , *obj3 = 0;
+
+ if (!PyArg_ParseTuple(args, "|OOO!", &obj1, &obj2, &PyFloat_Type, &obj3))
+ return -1;
+
+ if (!obj1){
+ self->sv = new StrokeVertex();
+
+ } else if (!obj2 && BPy_StrokeVertex_Check(obj1) && ((BPy_StrokeVertex *) obj1)->sv) {
+ self->sv = new StrokeVertex( *(((BPy_StrokeVertex *) obj1)->sv) );
+
+ } else if (!obj2 && BPy_CurvePoint_Check(obj1) && ((BPy_CurvePoint *) obj1)->cp) {
+ self->sv = new StrokeVertex( ((BPy_CurvePoint *) obj1)->cp );
+
+ } else if (!obj2 && BPy_SVertex_Check(obj1) && ((BPy_SVertex *) obj1)->sv) {
+ self->sv = new StrokeVertex( ((BPy_SVertex *) obj1)->sv );
+
+ } else if (obj3 && BPy_StrokeVertex_Check(obj1) && BPy_StrokeVertex_Check(obj2)) {
+ StrokeVertex *sv1 = ((BPy_StrokeVertex *) obj1)->sv;
+ StrokeVertex *sv2 = ((BPy_StrokeVertex *) obj2)->sv;
+ if (!sv1 || (sv1->A() == 0 && sv1->B() == 0)) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid StrokeVertex object");
+ return -1;
+ }
+ if (!sv2 || (sv2->A() == 0 && sv2->B() == 0)) {
+ PyErr_SetString(PyExc_TypeError, "argument 2 is an invalid StrokeVertex object");
+ return -1;
+ }
+ self->sv = new StrokeVertex(sv1, sv2, PyFloat_AsDouble(obj3));
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_cp.cp = self->sv;
+ self->py_cp.py_if0D.if0D = self->sv;
+ self->py_cp.py_if0D.borrowed = 0;
+
+ return 0;
+}
+
+// real operator[] (const int i) const
+// real & operator[] (const int i)
+
+/*----------------------StrokeVertex instance definitions ----------------------------*/
+static PyMethodDef BPy_StrokeVertex_methods[] = {
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------mathutils callbacks ----------------------------*/
+
+static int StrokeVertex_mathutils_check(BaseMathObject *bmo)
+{
+ if (!BPy_StrokeVertex_Check(bmo->cb_user))
+ return -1;
+ return 0;
+}
+
+static int StrokeVertex_mathutils_get(BaseMathObject *bmo, int subtype)
+{
+ BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user;
+ bmo->data[0] = (float)self->sv->x();
+ bmo->data[1] = (float)self->sv->y();
+ return 0;
+}
+
+static int StrokeVertex_mathutils_set(BaseMathObject *bmo, int subtype)
+{
+ BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user;
+ self->sv->setX((real)bmo->data[0]);
+ self->sv->setY((real)bmo->data[1]);
+ return 0;
+}
+
+static int StrokeVertex_mathutils_get_index(BaseMathObject *bmo, int subtype, int index)
+{
+ BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user;
+ switch (index) {
+ case 0: bmo->data[0] = (float)self->sv->x(); break;
+ case 1: bmo->data[1] = (float)self->sv->y(); break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int StrokeVertex_mathutils_set_index(BaseMathObject *bmo, int subtype, int index)
+{
+ BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user;
+ switch (index) {
+ case 0: self->sv->setX((real)bmo->data[0]); break;
+ case 1: self->sv->setY((real)bmo->data[1]); break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static Mathutils_Callback StrokeVertex_mathutils_cb = {
+ StrokeVertex_mathutils_check,
+ StrokeVertex_mathutils_get,
+ StrokeVertex_mathutils_set,
+ StrokeVertex_mathutils_get_index,
+ StrokeVertex_mathutils_set_index
+};
+
+static unsigned char StrokeVertex_mathutils_cb_index = -1;
+
+void StrokeVertex_mathutils_register_callback()
+{
+ StrokeVertex_mathutils_cb_index = Mathutils_RegisterCallback(&StrokeVertex_mathutils_cb);
+}
+
+/*----------------------StrokeVertex get/setters ----------------------------*/
+
+PyDoc_STRVAR(StrokeVertex_attribute_doc,
+"StrokeAttribute for this StrokeVertex.\n"
+"\n"
+":type: StrokeAttribute");
+
+static PyObject *StrokeVertex_attribute_get(BPy_StrokeVertex *self, void *UNUSED(closure))
+{
+ return BPy_StrokeAttribute_from_StrokeAttribute(self->sv->attribute());
+}
+
+static int StrokeVertex_attribute_set(BPy_StrokeVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_StrokeAttribute_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be a StrokeAttribute object");
+ return -1;
+ }
+ self->sv->setAttribute(*(((BPy_StrokeAttribute *)value)->sa));
+ return 0;
+}
+
+PyDoc_STRVAR(StrokeVertex_curvilinear_abscissa_doc,
+"Curvilinear abscissa of this StrokeVertex in the Stroke.\n"
+"\n"
+":type: float");
+
+static PyObject *StrokeVertex_curvilinear_abscissa_get(BPy_StrokeVertex *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->sv->curvilinearAbscissa());
+}
+
+static int StrokeVertex_curvilinear_abscissa_set(BPy_StrokeVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ float scalar;
+ if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
+ PyErr_SetString(PyExc_TypeError, "value must be a number");
+ return -1;
+ }
+ self->sv->setCurvilinearAbscissa(scalar);
+ return 0;
+}
+
+PyDoc_STRVAR(StrokeVertex_point_doc,
+"2D point coordinates.\n"
+"\n"
+":type: mathutils.Vector");
+
+static PyObject *StrokeVertex_point_get(BPy_StrokeVertex *self, void *UNUSED(closure))
+{
+ return Vector_CreatePyObject_cb((PyObject *)self, 2, StrokeVertex_mathutils_cb_index, 0);
+}
+
+static int StrokeVertex_point_set(BPy_StrokeVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ float v[2];
+ if (!float_array_from_PyObject(value, v, 2)) {
+ PyErr_SetString(PyExc_ValueError, "value must be a 2-dimensional vector");
+ return -1;
+ }
+ self->sv->setX(v[0]);
+ self->sv->setY(v[1]);
+ return 0;
+}
+
+PyDoc_STRVAR(StrokeVertex_stroke_length_doc,
+"Stroke length (it is only a value retained by the StrokeVertex,\n"
+"and it won't change the real stroke length).\n"
+"\n"
+":type: float");
+
+static PyObject *StrokeVertex_stroke_length_get(BPy_StrokeVertex *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->sv->strokeLength());
+}
+
+static int StrokeVertex_stroke_length_set(BPy_StrokeVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ float scalar;
+ if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
+ PyErr_SetString(PyExc_TypeError, "value must be a number");
+ return -1;
+ }
+ self->sv->setStrokeLength(scalar);
+ return 0;
+}
+
+PyDoc_STRVAR(StrokeVertex_u_doc,
+"Curvilinear abscissa of this StrokeVertex in the Stroke.\n"
+"\n"
+":type: float");
+
+static PyObject *StrokeVertex_u_get(BPy_StrokeVertex *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->sv->u());
+}
+
+static PyGetSetDef BPy_StrokeVertex_getseters[] = {
+ {(char *)"attribute", (getter)StrokeVertex_attribute_get, (setter)StrokeVertex_attribute_set, (char *)StrokeVertex_attribute_doc, NULL},
+ {(char *)"curvilinear_abscissa", (getter)StrokeVertex_curvilinear_abscissa_get, (setter)StrokeVertex_curvilinear_abscissa_set, (char *)StrokeVertex_curvilinear_abscissa_doc, NULL},
+ {(char *)"point", (getter)StrokeVertex_point_get, (setter)StrokeVertex_point_set, (char *)StrokeVertex_point_doc, NULL},
+ {(char *)"stroke_length", (getter)StrokeVertex_stroke_length_get, (setter)StrokeVertex_stroke_length_set, (char *)StrokeVertex_stroke_length_doc, NULL},
+ {(char *)"u", (getter)StrokeVertex_u_get, (setter)NULL, (char *)StrokeVertex_u_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_StrokeVertex type definition ------------------------------*/
+PyTypeObject StrokeVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "StrokeVertex", /* tp_name */
+ sizeof(BPy_StrokeVertex), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ StrokeVertex_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_StrokeVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_StrokeVertex_getseters, /* tp_getset */
+ &CurvePoint_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)StrokeVertex_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h
new file mode 100644
index 00000000000..a1cf3e80662
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h
@@ -0,0 +1,35 @@
+#ifndef FREESTYLE_PYTHON_STROKEVERTEX_H
+#define FREESTYLE_PYTHON_STROKEVERTEX_H
+
+#include "../BPy_CurvePoint.h"
+#include "../../../stroke/Stroke.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject StrokeVertex_Type;
+
+#define BPy_StrokeVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &StrokeVertex_Type) )
+
+/*---------------------------Python BPy_StrokeVertex structure definition----------*/
+typedef struct {
+ BPy_CurvePoint py_cp;
+ StrokeVertex *sv;
+} BPy_StrokeVertex;
+
+/*---------------------------Python BPy_StrokeVertex visible prototypes-----------*/
+
+void StrokeVertex_mathutils_register_callback();
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_STROKEVERTEX_H */
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp
new file mode 100644
index 00000000000..a0e0717ef37
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp
@@ -0,0 +1,143 @@
+#include "BPy_NonTVertex.h"
+
+#include "../../BPy_Convert.h"
+#include "../BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*----------------------NonTVertex methods ----------------------------*/
+
+PyDoc_STRVAR(NonTVertex_doc,
+"Class hierarchy: :class:`Interface0D` > :class:`ViewVertex` > :class:`NonTVertex`\n"
+"\n"
+"View vertex for corners, cusps, etc. associated to a single SVertex.\n"
+"Can be associated to 2 or more view edges.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A NonTVertex object.\n"
+" :type iBrother: :class:`NonTVertex`\n"
+"\n"
+".. method:: __init__(iSVertex)\n"
+"\n"
+" Builds a NonTVertex from a SVertex.\n"
+"\n"
+" :arg iSVertex: An SVertex object.\n"
+" :type iSVertex: :class:`SVertex`");
+
+static int NonTVertex_init(BPy_NonTVertex *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTuple(args, "|O!", &SVertex_Type, &obj))
+ return -1;
+
+ if (!obj) {
+ self->ntv = new NonTVertex();
+
+ } else if(((BPy_SVertex *)obj)->sv) {
+ self->ntv = new NonTVertex(((BPy_SVertex *)obj)->sv);
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return -1;
+ }
+
+ self->py_vv.vv = self->ntv;
+ self->py_vv.py_if0D.if0D = self->ntv;
+ self->py_vv.py_if0D.borrowed = 0;
+
+ return 0;
+}
+
+static PyMethodDef BPy_NonTVertex_methods[] = {
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------NonTVertex get/setters ----------------------------*/
+
+PyDoc_STRVAR(NonTVertex_svertex_doc,
+"The SVertex on top of which this NonTVertex is built.\n"
+"\n"
+":type: :class:`SVertex`");
+
+static PyObject *NonTVertex_svertex_get(BPy_NonTVertex *self, void *UNUSED(closure))
+{
+ SVertex *v = self->ntv->svertex();
+ if (v)
+ return BPy_SVertex_from_SVertex(*v);
+ Py_RETURN_NONE;
+}
+
+static int NonTVertex_svertex_set(BPy_NonTVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_SVertex_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
+ return -1;
+ }
+ self->ntv->setSVertex(((BPy_SVertex *)value)->sv);
+ return 0;
+}
+
+static PyGetSetDef BPy_NonTVertex_getseters[] = {
+ {(char *)"svertex", (getter)NonTVertex_svertex_get, (setter)NonTVertex_svertex_set, (char *)NonTVertex_svertex_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_NonTVertex type definition ------------------------------*/
+PyTypeObject NonTVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "NonTVertex", /* tp_name */
+ sizeof(BPy_NonTVertex), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ NonTVertex_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_NonTVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_NonTVertex_getseters, /* tp_getset */
+ &ViewVertex_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)NonTVertex_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h
new file mode 100644
index 00000000000..071194d2d42
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_NONTVERTEX_H
+#define FREESTYLE_PYTHON_NONTVERTEX_H
+
+#include "../BPy_ViewVertex.h"
+#include "../../../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject NonTVertex_Type;
+
+#define BPy_NonTVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &NonTVertex_Type) )
+
+/*---------------------------Python BPy_NonTVertex structure definition----------*/
+typedef struct {
+ BPy_ViewVertex py_vv;
+ NonTVertex *ntv;
+} BPy_NonTVertex;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_NONTVERTEX_H */
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp
new file mode 100644
index 00000000000..55c8b64d13c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp
@@ -0,0 +1,222 @@
+#include "BPy_TVertex.h"
+
+#include "../../BPy_Convert.h"
+#include "../BPy_SVertex.h"
+#include "../../BPy_Id.h"
+#include "../../Interface1D/BPy_FEdge.h"
+#include "../../Interface1D/BPy_ViewEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*----------------------TVertex methods ----------------------------*/
+
+PyDoc_STRVAR(TVertex_doc,
+"Class hierarchy: :class:`Interface0D` > :class:`ViewVertex` > :class:`TVertex`\n"
+"\n"
+"Class to define a T vertex, i.e. an intersection between two edges.\n"
+"It points towards two SVertex and four ViewEdges. Among the\n"
+"ViewEdges, two are front and the other two are back. Basically a\n"
+"front edge hides part of a back edge. So, among the back edges, one\n"
+"is of invisibility N and the other of invisibility N+1.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A TVertex object.\n"
+" :type iBrother: :class:`TVertex`");
+
+static int TVertex_init(BPy_TVertex *self, PyObject *args, PyObject *kwds)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return -1;
+ self->tv = new TVertex();
+ self->py_vv.vv = self->tv;
+ self->py_vv.py_if0D.if0D = self->tv;
+ self->py_vv.py_if0D.borrowed = 0;
+ return 0;
+}
+
+PyDoc_STRVAR(TVertex_get_svertex_doc,
+".. method:: get_svertex(iFEdge)\n"
+"\n"
+" Returns the SVertex (among the 2) belonging to the given FEdge.\n"
+"\n"
+" :arg iFEdge: An FEdge object.\n"
+" :type iFEdge: :class:`FEdge`\n"
+" :return: The SVertex belonging to the given FEdge.\n"
+" :rtype: :class:`SVertex`");
+
+static PyObject * TVertex_get_svertex( BPy_TVertex *self, PyObject *args)
+{
+ PyObject *py_fe;
+
+ if (!PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe))
+ return NULL;
+ SVertex *sv = self->tv->getSVertex(((BPy_FEdge *)py_fe)->fe);
+ if (sv)
+ return BPy_SVertex_from_SVertex(*sv);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(TVertex_get_mate_doc,
+".. method:: get_mate(iEdgeA)\n"
+"\n"
+" Returns the mate edge of the ViewEdge given as argument. If the\n"
+" ViewEdge is frontEdgeA, frontEdgeB is returned. If the ViewEdge is\n"
+" frontEdgeB, frontEdgeA is returned. Same for back edges.\n"
+"\n"
+" :arg iEdgeA: A ViewEdge object.\n"
+" :type iEdgeA: :class:`ViewEdge`\n"
+" :return: The mate edge of the given ViewEdge.\n"
+" :rtype: :class:`ViewEdge`");
+
+static PyObject * TVertex_get_mate( BPy_TVertex *self, PyObject *args)
+{
+ PyObject *py_ve;
+
+ if (!PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve))
+ return NULL;
+ ViewEdge *ve = self->tv->mate(((BPy_ViewEdge *)py_ve)->ve);
+ if (ve)
+ return BPy_ViewEdge_from_ViewEdge(*ve);
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef BPy_TVertex_methods[] = {
+ {"get_svertex", (PyCFunction)TVertex_get_svertex, METH_VARARGS, TVertex_get_svertex_doc},
+ {"get_mate", (PyCFunction)TVertex_get_mate, METH_VARARGS, TVertex_get_mate_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------TVertex get/setters ----------------------------*/
+
+PyDoc_STRVAR(TVertex_front_svertex_doc,
+"The SVertex that is closer to the viewpoint.\n"
+"\n"
+":type: :class:`SVertex`");
+
+static PyObject *TVertex_front_svertex_get(BPy_TVertex *self, void *UNUSED(closure))
+{
+ SVertex *v = self->tv->frontSVertex();
+ if (v)
+ return BPy_SVertex_from_SVertex(*v);
+ Py_RETURN_NONE;
+}
+
+static int TVertex_front_svertex_set(BPy_TVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_SVertex_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
+ return -1;
+ }
+ self->tv->setFrontSVertex(((BPy_SVertex *)value)->sv);
+ return 0;
+}
+
+PyDoc_STRVAR(TVertex_back_svertex_doc,
+"The SVertex that is further away from the viewpoint.\n"
+"\n"
+":type: :class:`SVertex`");
+
+static PyObject *TVertex_back_svertex_get(BPy_TVertex *self, void *UNUSED(closure))
+{
+ SVertex *v = self->tv->backSVertex();
+ if (v)
+ return BPy_SVertex_from_SVertex(*v);
+ Py_RETURN_NONE;
+}
+
+static int TVertex_back_svertex_set(BPy_TVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_SVertex_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
+ return -1;
+ }
+ self->tv->setBackSVertex(((BPy_SVertex *)value)->sv);
+ return 0;
+}
+
+PyDoc_STRVAR(TVertex_id_doc,
+"The Id of this TVertex.\n"
+"\n"
+":type: :class:`Id`");
+
+static PyObject *TVertex_id_get(BPy_TVertex *self, void *UNUSED(closure))
+{
+ Id id(self->tv->getId());
+ return BPy_Id_from_Id(id); // return a copy
+}
+
+static int TVertex_id_set(BPy_TVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_Id_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an Id");
+ return -1;
+ }
+ self->tv->setId(*(((BPy_Id *)value)->id));
+ return 0;
+}
+
+static PyGetSetDef BPy_TVertex_getseters[] = {
+ {(char *)"front_svertex", (getter)TVertex_front_svertex_get, (setter)TVertex_front_svertex_set, (char *)TVertex_front_svertex_doc, NULL},
+ {(char *)"back_svertex", (getter)TVertex_back_svertex_get, (setter)TVertex_back_svertex_set, (char *)TVertex_back_svertex_doc, NULL},
+ {(char *)"id", (getter)TVertex_id_get, (setter)TVertex_id_set, (char *)TVertex_id_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_TVertex type definition ------------------------------*/
+PyTypeObject TVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TVertex", /* tp_name */
+ sizeof(BPy_TVertex), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ TVertex_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_TVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_TVertex_getseters, /* tp_getset */
+ &ViewVertex_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TVertex_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h
new file mode 100644
index 00000000000..12fe5c0cb43
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_TVERTEX_H
+#define FREESTYLE_PYTHON_TVERTEX_H
+
+#include "../BPy_ViewVertex.h"
+#include "../../../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TVertex_Type;
+
+#define BPy_TVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TVertex_Type) )
+
+/*---------------------------Python BPy_TVertex structure definition----------*/
+typedef struct {
+ BPy_ViewVertex py_vv;
+ TVertex *tv;
+} BPy_TVertex;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_TVERTEX_H */