~yade-dev/yade/0.80

« back to all changes in this revision

Viewing changes to py/3rd-party/pygts-0.3.1/edge.c

  • Committer: Anton Gladky
  • Date: 2012-05-02 21:50:42 UTC
  • Revision ID: gladky.anton@gmail.com-20120502215042-v1fa9r65usqe7kfk
0.80.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* pygts - python package for the manipulation of triangulated surfaces
 
2
 *
 
3
 *   Copyright (C) 2009 Thomas J. Duck
 
4
 *   All rights reserved.
 
5
 *
 
6
 *   Thomas J. Duck <tom.duck@dal.ca>
 
7
 *   Department of Physics and Atmospheric Science,
 
8
 *   Dalhousie University, Halifax, Nova Scotia, Canada, B3H 3J5
 
9
 *
 
10
 * NOTICE
 
11
 *
 
12
 *   This library is free software; you can redistribute it and/or
 
13
 *   modify it under the terms of the GNU Library General Public
 
14
 *   License as published by the Free Software Foundation; either
 
15
 *   version 2 of the License, or (at your option) any later version.
 
16
 *
 
17
 *   This library is distributed in the hope that it will be useful,
 
18
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
19
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
20
 *   Library General Public License for more details.
 
21
 *
 
22
 *   You should have received a copy of the GNU Library General Public
 
23
 *   License along with this library; if not, write to the
 
24
 *   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
25
 *   Boston, MA 02111-1307, USA.
 
26
 */
 
27
 
 
28
#include "pygts.h"
 
29
 
 
30
 
 
31
#if PYGTS_DEBUG
 
32
  #define SELF_CHECK if(!pygts_edge_check((PyObject*)self)) {         \
 
33
                       PyErr_SetString(PyExc_RuntimeError,            \
 
34
                       "problem with self object (internal error)");  \
 
35
                       return NULL;                                   \
 
36
                     }
 
37
#else
 
38
  #define SELF_CHECK
 
39
#endif
 
40
 
 
41
 
 
42
/*-------------------------------------------------------------------------*/
 
43
/* Methods exported to python */
 
44
 
 
45
static PyObject*
 
46
is_ok(PygtsEdge *self, PyObject *args)
 
47
{
 
48
  if(pygts_edge_is_ok(self)) {
 
49
    Py_INCREF(Py_True);
 
50
    return Py_True;
 
51
  }
 
52
  else {
 
53
    Py_INCREF(Py_False);
 
54
    return Py_False;
 
55
  }
 
56
}
 
57
 
 
58
 
 
59
static PyObject*
 
60
is_unattached(PygtsEdge *self, PyObject *args)
 
61
{
 
62
  guint n;
 
63
 
 
64
  SELF_CHECK
 
65
 
 
66
  /* Check for attachments other than to the gtsobj_parent */
 
67
  n = g_slist_length(PYGTS_EDGE_AS_GTS_EDGE(self)->triangles);
 
68
  if( n > 1 ) {
 
69
    Py_INCREF(Py_False);
 
70
    return Py_False;
 
71
  }
 
72
  else if( n == 1 ){
 
73
    Py_INCREF(Py_True);
 
74
    return Py_True;
 
75
  }
 
76
  else {
 
77
    PyErr_SetString(PyExc_RuntimeError,"Edge lost parent (internal error)");
 
78
    return NULL;
 
79
  }
 
80
}
 
81
 
 
82
 
 
83
/* replace() works, but can break Triangles and so is disabled */
 
84
 
 
85
/* static PyObject* */
 
86
/* replace(PygtsEdge *self, PyObject *args) */
 
87
/* { */
 
88
/*   PyObject *e2_; */
 
89
/*   PygtsEdge *e2; */
 
90
/*   GSList *parents=NULL, *i, *cur; */
 
91
 
 
92
/* #if PYGTS_DEBUG */
 
93
/*   if(!pygts_edge_check((PyObject*)self)) { */
 
94
/*     PyErr_SetString(PyExc_TypeError, */
 
95
/*                  "problem with self object (internal error)"); */
 
96
/*     return NULL; */
 
97
/*   } */
 
98
/* #endif */
 
99
 
 
100
/*   /\* Parse the args *\/   */
 
101
/*   if(! PyArg_ParseTuple(args, "O", &e2_) ) { */
 
102
/*     return NULL; */
 
103
/*   } */
 
104
 
 
105
/*   /\* Convert to PygtsObjects *\/ */
 
106
/*   if(!pygts_edge_check(e2_)) { */
 
107
/*     PyErr_SetString(PyExc_TypeError,"expected an Edge"); */
 
108
/*     return NULL; */
 
109
/*   } */
 
110
/*   e2 = PYGTS_EDGE(e2_); */
 
111
 
 
112
/*   if(PYGTS_OBJECT(self)->gtsobj!=PYGTS_OBJECT(e2)->gtsobj) { */
 
113
/*     /\* (Ignore self-replacement) *\/ */
 
114
 
 
115
/*     /\* Detach and save any parent triangles *\/ */
 
116
/*     i = GTS_EDGE(PYGTS_OBJECT(self)->gtsobj)->triangles; */
 
117
/*     while(i!=NULL) { */
 
118
/*       cur = i; */
 
119
/*       i = i->next; */
 
120
/*       if(PYGTS_IS_PARENT_TRIANGLE(cur->data)) { */
 
121
/*      GTS_EDGE(PYGTS_OBJECT(self)->gtsobj)->triangles =  */
 
122
/*        g_slist_remove_link(GTS_EDGE(PYGTS_OBJECT(self)->gtsobj)->triangles, */
 
123
/*                            cur); */
 
124
/*      parents = g_slist_prepend(parents,cur->data); */
 
125
/*      g_slist_free_1(cur); */
 
126
/*       } */
 
127
/*     } */
 
128
 
 
129
/*     /\* Perform the replace operation *\/ */
 
130
/*     gts_edge_replace(GTS_EDGE(PYGTS_OBJECT(self)->gtsobj), */
 
131
/*                   GTS_EDGE(PYGTS_OBJECT(e2)->gtsobj)); */
 
132
 
 
133
/*     /\* Reattach the parent segments *\/ */
 
134
/*     i = parents; */
 
135
/*     while(i!=NULL) { */
 
136
/*       GTS_EDGE(PYGTS_OBJECT(self)->gtsobj)->triangles =  */
 
137
/*      g_slist_prepend(GTS_EDGE(PYGTS_OBJECT(self)->gtsobj)->triangles, */
 
138
/*                      i->data); */
 
139
/*       i = i->next; */
 
140
/*     } */
 
141
/*     g_slist_free(parents); */
 
142
/*   } */
 
143
 
 
144
/* #if PYGTS_DEBUG */
 
145
/*   if(!pygts_edge_check((PyObject*)self)) { */
 
146
/*     PyErr_SetString(PyExc_TypeError, */
 
147
/*                  "problem with self object (internal error)"); */
 
148
/*     return NULL; */
 
149
/*   } */
 
150
/* #endif */
 
151
 
 
152
/*   Py_INCREF(Py_None); */
 
153
/*   return Py_None; */
 
154
/* } */
 
155
 
 
156
 
 
157
static PyObject*
 
158
face_number(PygtsEdge *self, PyObject *args)
 
159
{
 
160
  PyObject *s_;
 
161
  GtsSurface *s;
 
162
 
 
163
  SELF_CHECK
 
164
 
 
165
  /* Parse the args */
 
166
  if(! PyArg_ParseTuple(args, "O", &s_) ) {
 
167
    return NULL;
 
168
  }
 
169
 
 
170
  /* Convert to PygtsObjects */
 
171
  if(!pygts_surface_check(s_)) {
 
172
    PyErr_SetString(PyExc_TypeError,"expected a Surface");
 
173
    return NULL;
 
174
  }
 
175
  s = PYGTS_SURFACE_AS_GTS_SURFACE(s_);
 
176
 
 
177
  return Py_BuildValue("i",
 
178
                       gts_edge_face_number(PYGTS_EDGE_AS_GTS_EDGE(self),s));
 
179
}
 
180
 
 
181
 
 
182
static PyObject*
 
183
belongs_to_tetrahedron(PygtsEdge *self, PyObject *args)
 
184
{
 
185
  SELF_CHECK
 
186
 
 
187
  if(gts_edge_belongs_to_tetrahedron(PYGTS_EDGE_AS_GTS_EDGE(self))) {
 
188
    Py_INCREF(Py_True);
 
189
    return Py_True;
 
190
  }
 
191
  else {
 
192
    Py_INCREF(Py_False);
 
193
    return Py_False;
 
194
  }
 
195
}
 
196
 
 
197
 
 
198
static PyObject*
 
199
is_boundary(PygtsEdge *self, PyObject *args)
 
200
{
 
201
  PyObject *s_;
 
202
  GtsSurface *s;
 
203
 
 
204
  SELF_CHECK
 
205
 
 
206
  /* Parse the args */
 
207
  if(! PyArg_ParseTuple(args, "O", &s_) ) {
 
208
    return NULL;
 
209
  }
 
210
 
 
211
  /* Convert to PygtsObjects */
 
212
  if(!pygts_surface_check(s_)) {
 
213
    PyErr_SetString(PyExc_TypeError,"expected a Surface");
 
214
    return NULL;
 
215
  }
 
216
  s = PYGTS_SURFACE_AS_GTS_SURFACE(s_);
 
217
 
 
218
  /* Make the call and return */
 
219
  if(gts_edge_is_boundary(PYGTS_EDGE_AS_GTS_EDGE(self),s)!=NULL) {
 
220
    Py_INCREF(Py_True);
 
221
    return Py_True;
 
222
  }
 
223
  else {
 
224
    Py_INCREF(Py_False);
 
225
    return Py_False;
 
226
  }
 
227
}
 
228
 
 
229
 
 
230
static PyObject*
 
231
contacts(PygtsEdge *self, PyObject *args)
 
232
{
 
233
  SELF_CHECK
 
234
 
 
235
  return Py_BuildValue("i",
 
236
                       gts_edge_is_contact(PYGTS_EDGE_AS_GTS_EDGE(self)));
 
237
}
 
238
 
 
239
 
 
240
/* Methods table */
 
241
static PyMethodDef methods[] = {
 
242
  {"is_ok", (PyCFunction)is_ok,
 
243
   METH_NOARGS,
 
244
   "True if this Edge e is not degenerate or duplicate.\n"
 
245
   "False otherwise.  Degeneracy implies e.v1.id == e.v2.id.\n"
 
246
   "\n"
 
247
   "Signature: e.is_ok()\n"
 
248
  },  
 
249
 
 
250
  {"is_unattached", (PyCFunction)is_unattached,
 
251
   METH_NOARGS,
 
252
   "True if this Edge e is not part of any Triangle.\n"
 
253
   "\n"
 
254
   "Signature: e.is_unattached()\n"
 
255
  },
 
256
 
 
257
/* Edge replace() method works but results in Triangles that are "not ok";
 
258
 * i.e., they have edges that don't connect.  We don't want that problem
 
259
 * and so the method has been disabled.
 
260
 */
 
261
/*
 
262
  {"replace", (PyCFunction)replace,
 
263
   METH_VARARGS,
 
264
   "Replaces this Edge e1 with Edge e2 in all Triangles that have e1.\n"
 
265
   "Edge e1 itself is left unchanged.\n"
 
266
   "\n"
 
267
   "Signature: e1.replace(e2).\n"
 
268
  },
 
269
*/
 
270
 
 
271
  {"face_number", (PyCFunction)face_number,
 
272
   METH_VARARGS,
 
273
   "Returns number of faces using this Edge e on Surface s.\n"
 
274
   "\n"
 
275
   "Signature: e.face_number(s)\n"
 
276
  },
 
277
 
 
278
  {"is_boundary", (PyCFunction)is_boundary,
 
279
   METH_VARARGS,
 
280
   "Returns True if this Edge e is a boundary on Surface s.\n"
 
281
   "Otherwise False.\n"
 
282
   "\n"
 
283
   "Signature: e.is_boundary(s)\n"
 
284
  },
 
285
 
 
286
  {"belongs_to_tetrahedron", (PyCFunction)belongs_to_tetrahedron,
 
287
   METH_NOARGS,
 
288
   "Returns True if this Edge e belongs to a tetrahedron.\n"
 
289
   "Otherwise False.\n"
 
290
   "\n"
 
291
   "Signature: e.belongs_to_tetrahedron()\n"
 
292
  },
 
293
 
 
294
  {"contacts", (PyCFunction)contacts,
 
295
   METH_NOARGS,
 
296
   "Returns number of sets of connected triangles share this Edge e\n"
 
297
   "as a contact Edge.\n"
 
298
   "\n"
 
299
   "Signature: e.contacts()\n"
 
300
  },
 
301
 
 
302
  {NULL}  /* Sentinel */
 
303
};
 
304
 
 
305
 
 
306
/*-------------------------------------------------------------------------*/
 
307
/* Python type methods */
 
308
 
 
309
static GtsObject* parent(GtsEdge *e1);
 
310
 
 
311
static PyObject *
 
312
new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
313
{
 
314
  PyObject *o;
 
315
  PygtsObject *obj;
 
316
  GtsEdge *tmp;
 
317
  GtsObject *edge=NULL;
 
318
  PyObject *v1_,*v2_;
 
319
  PygtsVertex *v1,*v2;
 
320
  guint alloc_gtsobj = TRUE;
 
321
  guint N;
 
322
 
 
323
  /* Parse the args */
 
324
  if(kwds) {
 
325
    o = PyDict_GetItemString(kwds,"alloc_gtsobj");
 
326
    if(o==Py_False) {
 
327
      alloc_gtsobj = FALSE;
 
328
    }
 
329
    if(o!=NULL) {
 
330
      PyDict_DelItemString(kwds, "alloc_gtsobj");
 
331
    }
 
332
  }
 
333
  if(kwds) {
 
334
    Py_INCREF(Py_False);
 
335
    PyDict_SetItemString(kwds,"alloc_gtsobj", Py_False);
 
336
  }
 
337
 
 
338
  /* Allocate the gtsobj (if needed) */
 
339
  if( alloc_gtsobj ) {
 
340
 
 
341
    /* Parse the args */
 
342
    if( (N = PyTuple_Size(args)) < 2 ) {
 
343
      PyErr_SetString(PyExc_TypeError,"expected two Vertices");
 
344
      return NULL;
 
345
    }
 
346
    v1_ = PyTuple_GET_ITEM(args,0);
 
347
    v2_ = PyTuple_GET_ITEM(args,1);
 
348
 
 
349
    /* Convert to PygtsObjects */
 
350
    if(!pygts_vertex_check(v1_)) {
 
351
      PyErr_SetString(PyExc_TypeError,"expected two Vertices");
 
352
      return NULL;
 
353
    }
 
354
    if(!pygts_vertex_check(v2_)) {
 
355
      PyErr_SetString(PyExc_TypeError,"expected two Vertices");
 
356
      return NULL;
 
357
    }
 
358
    v1 = PYGTS_VERTEX(v1_);
 
359
    v2 = PYGTS_VERTEX(v2_);
 
360
 
 
361
    /* Error check */
 
362
    if(PYGTS_OBJECT(v1)->gtsobj == PYGTS_OBJECT(v2)->gtsobj) {
 
363
      PyErr_SetString(PyExc_ValueError,"Vertices given are the same");
 
364
      return NULL;
 
365
    }
 
366
 
 
367
    /* Create the GtsEdge */
 
368
    edge = GTS_OBJECT(gts_edge_new(gts_edge_class(),
 
369
                                   GTS_VERTEX(v1->gtsobj),
 
370
                                   GTS_VERTEX(v2->gtsobj)));
 
371
    if( edge == NULL )  {
 
372
      PyErr_SetString(PyExc_MemoryError, "could not create Edge");
 
373
      return NULL;
 
374
    }
 
375
 
 
376
    /* Check for duplicate */
 
377
    tmp = gts_edge_is_duplicate(GTS_EDGE(edge));
 
378
    if( tmp != NULL ) {
 
379
      gts_object_destroy(edge);
 
380
      edge = GTS_OBJECT(tmp);
 
381
    }
 
382
 
 
383
    /* If corresponding PyObject found in object table, we are done */
 
384
    if( (obj=g_hash_table_lookup(obj_table,edge)) != NULL ) {
 
385
      Py_INCREF(obj);
 
386
      return (PyObject*)obj;
 
387
    }
 
388
  }
 
389
 
 
390
  /* Chain up */
 
391
  obj = PYGTS_OBJECT(PygtsSegmentType.tp_new(type,args,kwds));
 
392
 
 
393
  if( alloc_gtsobj ) {
 
394
    obj->gtsobj = edge;
 
395
 
 
396
    /* Create a parent GtsTriangle */
 
397
    if( (obj->gtsobj_parent = parent(GTS_EDGE(obj->gtsobj))) == NULL ) {
 
398
      gts_object_destroy(obj->gtsobj);
 
399
      obj->gtsobj = NULL;
 
400
      return NULL;
 
401
    }
 
402
 
 
403
    pygts_object_register(PYGTS_OBJECT(obj));
 
404
  }
 
405
 
 
406
  return (PyObject*)obj;
 
407
}
 
408
 
 
409
 
 
410
static int
 
411
init(PygtsEdge *self, PyObject *args, PyObject *kwds)
 
412
{
 
413
  gint ret;
 
414
 
 
415
  /* Chain up */
 
416
  if( (ret=PygtsSegmentType.tp_init((PyObject*)self,args,kwds)) != 0 ){
 
417
    return ret;
 
418
  }
 
419
 
 
420
  return 0;
 
421
}
 
422
 
 
423
 
 
424
/* Methods table */
 
425
PyTypeObject PygtsEdgeType = {
 
426
    PyObject_HEAD_INIT(NULL)
 
427
    0,                       /* ob_size */
 
428
    "gts.Edge",              /* tp_name */
 
429
    sizeof(PygtsEdge),       /* tp_basicsize */
 
430
    0,                       /* tp_itemsize */
 
431
    0,                       /* tp_dealloc */
 
432
    0,                       /* tp_print */
 
433
    0,                       /* tp_getattr */
 
434
    0,                       /* tp_setattr */
 
435
    0,                       /* tp_compare */
 
436
    0,                       /* tp_repr */
 
437
    0,                       /* tp_as_number */
 
438
    0,                       /* tp_as_sequence */
 
439
    0,                       /* tp_as_mapping */
 
440
    0,                       /* tp_hash */
 
441
    0,                       /* tp_call */
 
442
    0,                       /* tp_str */
 
443
    0,                       /* tp_getattro */
 
444
    0,                       /* tp_setattro */
 
445
    0,                       /* tp_as_buffer */
 
446
    Py_TPFLAGS_DEFAULT |
 
447
      Py_TPFLAGS_BASETYPE,   /* tp_flags */
 
448
    "Edge object",           /* tp_doc */
 
449
    0,                       /* tp_traverse */
 
450
    0,                       /* tp_clear */
 
451
    0,                       /* tp_richcompare */
 
452
    0,                       /* tp_weaklistoffset */
 
453
    0,                       /* tp_iter */
 
454
    0,                       /* tp_iternext */
 
455
    methods,                 /* tp_methods */
 
456
    0,                       /* tp_members */
 
457
    0,                       /* tp_getset */
 
458
    0,                       /* tp_base */
 
459
    0,                       /* tp_dict */
 
460
    0,                       /* tp_descr_get */
 
461
    0,                       /* tp_descr_set */
 
462
    0,                       /* tp_dictoffset */
 
463
    (initproc)init,          /* tp_init */
 
464
    0,                       /* tp_alloc */
 
465
    (newfunc)new             /* tp_new */
 
466
};
 
467
 
 
468
 
 
469
/*-------------------------------------------------------------------------*/
 
470
/* Pygts functions */
 
471
 
 
472
gboolean 
 
473
pygts_edge_check(PyObject* o)
 
474
{
 
475
  if(! PyObject_TypeCheck(o, &PygtsEdgeType)) {
 
476
    return FALSE;
 
477
  }
 
478
  else {
 
479
#if PYGTS_DEBUG
 
480
    return pygts_edge_is_ok(PYGTS_EDGE(o));
 
481
#else
 
482
    return TRUE;
 
483
#endif
 
484
  }
 
485
}
 
486
 
 
487
gboolean
 
488
pygts_edge_is_ok(PygtsEdge *e)
 
489
{
 
490
  GSList *parent;
 
491
  PygtsObject *obj;
 
492
 
 
493
  obj = PYGTS_OBJECT(e);
 
494
 
 
495
  if(!pygts_segment_is_ok(PYGTS_SEGMENT(e))) return FALSE;
 
496
 
 
497
  /* Check for a valid parent */
 
498
  g_return_val_if_fail(obj->gtsobj_parent!=NULL,FALSE);
 
499
  g_return_val_if_fail(PYGTS_IS_PARENT_TRIANGLE(obj->gtsobj_parent),FALSE);
 
500
  parent = g_slist_find(GTS_EDGE(obj->gtsobj)->triangles,
 
501
                        obj->gtsobj_parent);
 
502
  g_return_val_if_fail(parent!=NULL,FALSE);
 
503
 
 
504
  return TRUE;
 
505
}
 
506
 
 
507
 
 
508
static GtsObject* 
 
509
parent(GtsEdge *e1) {
 
510
  GtsVertex *v1,*v2,*v3;
 
511
  GtsPoint *p1,*p2;
 
512
  GtsEdge *e2, *e3;
 
513
  GtsTriangle *p;
 
514
 
 
515
  /* Create a third vertex for the triangle */
 
516
  v1 = GTS_SEGMENT(e1)->v1;
 
517
  v2 = GTS_SEGMENT(e1)->v2;
 
518
  p1 = GTS_POINT(v1);
 
519
  p2 = GTS_POINT(v2);
 
520
  v3 = gts_vertex_new(pygts_parent_vertex_class(),
 
521
                      p1->x+p2->x,p1->y+p2->y,p1->z+p2->z);
 
522
  if( v3 == NULL ) {
 
523
    PyErr_SetString(PyExc_MemoryError, "could not create Vertex");
 
524
    return NULL;
 
525
  }
 
526
 
 
527
  /* Create another two edges */
 
528
  if( (e2 = gts_edge_new(pygts_parent_edge_class(),v2,v3)) == NULL ) {
 
529
    PyErr_SetString(PyExc_MemoryError, "could not create Edge");
 
530
    return NULL;
 
531
  }
 
532
  if( (e3 = gts_edge_new(pygts_parent_edge_class(),v3,v1)) == NULL ) {
 
533
    PyErr_SetString(PyExc_MemoryError, "could not create Edge");
 
534
    gts_object_destroy(GTS_OBJECT(e2));
 
535
    return NULL;
 
536
  }
 
537
 
 
538
  /* Create and return the parent */
 
539
  if( (p = gts_triangle_new(pygts_parent_triangle_class(),e1,e2,e3)) 
 
540
      == NULL ) {
 
541
    gts_object_destroy(GTS_OBJECT(e2));
 
542
    gts_object_destroy(GTS_OBJECT(e3));
 
543
    PyErr_SetString(PyExc_MemoryError, "could not create Triangle");
 
544
    return NULL;
 
545
  }
 
546
 
 
547
  return GTS_OBJECT(p);
 
548
}
 
549
 
 
550
 
 
551
PygtsEdge *
 
552
pygts_edge_new(GtsEdge *e)
 
553
{
 
554
  PyObject *args, *kwds;
 
555
  PygtsObject *edge;
 
556
 
 
557
  /* Check for Edge in the object table */
 
558
  if( (edge = PYGTS_OBJECT(g_hash_table_lookup(obj_table,GTS_OBJECT(e)))) 
 
559
      !=NULL ) {
 
560
    Py_INCREF(edge);
 
561
    return PYGTS_EDGE(edge);
 
562
  }
 
563
 
 
564
  /* Build a new Edge */
 
565
  args = Py_BuildValue("OO",Py_None,Py_None);
 
566
  kwds = Py_BuildValue("{s:O}","alloc_gtsobj",Py_False);
 
567
  edge = PYGTS_EDGE(PygtsEdgeType.tp_new(&PygtsEdgeType, args, kwds));
 
568
  Py_DECREF(args);
 
569
  Py_DECREF(kwds);
 
570
  if( edge == NULL ) {
 
571
    PyErr_SetString(PyExc_MemoryError,"could not create Edge");
 
572
    return NULL;
 
573
  }
 
574
  edge->gtsobj = GTS_OBJECT(e);
 
575
 
 
576
  /* Attach the parent */
 
577
  if( (edge->gtsobj_parent = parent(e)) == NULL ) {
 
578
    Py_DECREF(edge);
 
579
    return NULL;
 
580
  }
 
581
 
 
582
  /* Register and return */
 
583
  pygts_object_register(edge);
 
584
  return PYGTS_EDGE(edge);
 
585
}
 
586
 
 
587
 
 
588
GtsTriangleClass*
 
589
pygts_parent_triangle_class(void)
 
590
{
 
591
  static GtsTriangleClass *klass = NULL;
 
592
  GtsObjectClass *super = NULL;
 
593
 
 
594
  if (klass == NULL) {
 
595
 
 
596
    super = GTS_OBJECT_CLASS(gts_triangle_class());
 
597
 
 
598
    GtsObjectClassInfo pygts_parent_triangle_info = {
 
599
      "PygtsParentTriangle",
 
600
      sizeof(PygtsParentTriangle),
 
601
      sizeof(GtsTriangleClass),
 
602
      (GtsObjectClassInitFunc)(super->info.class_init_func),
 
603
      (GtsObjectInitFunc)(super->info.object_init_func),
 
604
      (GtsArgSetFunc) NULL,
 
605
      (GtsArgGetFunc) NULL
 
606
    };
 
607
    klass = gts_object_class_new(gts_object_class(),
 
608
                                 &pygts_parent_triangle_info);
 
609
  }
 
610
 
 
611
  return klass;
 
612
}
 
613
 
 
614
 
 
615
GtsEdgeClass*
 
616
pygts_parent_edge_class(void)
 
617
{
 
618
  static GtsEdgeClass *klass = NULL;
 
619
  GtsObjectClass *super = NULL;
 
620
 
 
621
  if (klass == NULL) {
 
622
 
 
623
    super = GTS_OBJECT_CLASS(pygts_parent_segment_class());
 
624
 
 
625
    GtsObjectClassInfo pygts_parent_edge_info = {
 
626
      "PygtsParentEdge",
 
627
      sizeof(PygtsParentEdge),
 
628
      sizeof(GtsEdgeClass),
 
629
      (GtsObjectClassInitFunc)(super->info.class_init_func),
 
630
      (GtsObjectInitFunc)(super->info.object_init_func),
 
631
      (GtsArgSetFunc) NULL,
 
632
      (GtsArgGetFunc) NULL
 
633
    };
 
634
    klass = gts_object_class_new(gts_object_class(),
 
635
                                 &pygts_parent_edge_info);
 
636
  }
 
637
 
 
638
  return klass;
 
639
}