source: inundation/mesh_engine/triang.c @ 3031

Last change on this file since 3031 was 3023, checked in by duncan, 19 years ago

setting file as head

File size: 19.6 KB
Line 
1/* this appears to be necessary to run on Linux */
2
3#undef _STDLIB_H_
4#define _STDLIB_H_
5
6
7/*
8    This code is based on code by A. Pletzer
9
10    This code interfaces pmesh directly with "triangle", a general       
11    purpose triangulation code. In doing so, Python data structures         
12    are passed to C for  use by "triangle" and the results are then         
13    converted back. This was accomplished using the Python/C API.           
14                                                                           
15    I. Lists of points,edges,holes, and regions must normally be
16     created for proper triangulation. However, if there are no holes,
17     the  hole list need not be specified (however, a
18     measure of control over the shape of the convex hull is lost;
19     triangle decides).
20     
21     points list: [(x1,y1),(x2,y2),...] (Tuples of doubles)                 
22     edge list: [(Ea,Eb),(Ef,Eg),...] (Tuples of integers)                   
23     hole list: [(x1,y1),...](Tuples of doubles, one inside each hole region)
24     regionlist: [ (x1,y1,index,area),...] (Tuple of doubles)               
25     pointattributelist:[ (a1,a2..),...] (Tuple of lists)
26     mode: String - the commands sent to triangle
27         
28     This is all that is needed to accomplish an intial triangulation.       
29     A dictionary of the Triangle output is returned.                                   
30     Precondition
31     End list in the pointattributelist has to have the same length
32     
33    Compilation can be done as follows                                       
34                   
35    c++ -I/usr/local/include/python1.5 -shared -o triangmodule.so           
36    triangmodule.c triangle.o                                                */
37
38
39#ifdef SINGLE 
40#define REAL float
41#else 
42#define REAL double
43#endif
44
45#include "triangle.h"
46
47#ifndef _STDLIB_H_
48#ifndef _WIN32
49extern "C" void *malloc(); 
50extern "C" void free(); 
51#endif
52#endif 
53
54#include "Python.h"
55
56
57
58 static PyObject *triang_genMesh(PyObject *self, PyObject *args){
59     
60  /* Mesh generation routine
61     pre-conditions:
62     mode must have a 'z' switch, to avoid segmentation faults
63  */
64   
65  struct triangulateio in,out;
66
67  PyObject *hull;
68  PyObject *seglist;
69  PyObject *holelist;
70  PyObject *regionlist;
71  PyObject *trianglelist;
72  PyObject *mode;
73  PyObject *firstPointAttr;
74  PyObject *pointattributelist;
75  PyObject *segmarkerlist;
76  PyObject *Attrlist;
77  REAL Attr;
78  int i, j, iatt, n, write_here;
79  int a,b,c;
80  int marker;
81  int tuplesize;
82   
83  int index = 0;
84  double x,y;
85  PyObject *elems;
86  PyObject *pair;
87     
88  char *mod;
89  PyObject *holder, *holderlist, *attributelist;
90  int listsize,attsize ;
91  PyObject  *ii;
92 
93  int *points_connected;
94       
95  if(!PyArg_ParseTuple(args,(char *)"OOOOOOOO",&hull,&seglist,&holelist,&regionlist,&pointattributelist,&segmarkerlist,&trianglelist,&mode)){
96    return NULL;
97  }
98  if(!PyList_Check(hull)){
99    PyErr_SetString(PyExc_TypeError, 
100                    "incorrect first argument for 'genMesh': list required.");
101    return NULL;
102  }
103  if(!PyList_Check(hull)){
104    PyErr_SetString(PyExc_TypeError,
105                    "incorrect second argument for 'genMesh': list required.");
106    return NULL;
107  }
108  if(!PyList_Check(hull)){
109    PyErr_SetString(PyExc_TypeError,
110                    "incorrect third argument for 'genMesh': list required.");
111    return NULL;
112  }
113  if(!PyList_Check(hull)){
114    PyErr_SetString(PyExc_TypeError,
115                    "incorrect fourth argument for 'genMesh': list required.");
116    return NULL;
117  }
118  if(!PyList_Check(hull)){
119    PyErr_SetString(PyExc_TypeError,
120                    "incorrect fifth argument for 'genMesh': list required.");
121    return NULL;
122  }
123  if(!PyList_Check(hull)){
124    PyErr_SetString(PyExc_TypeError,
125                    "incorrect sixth argument for 'genMesh': list required.");
126    return NULL;
127  }
128  if(!PyList_Check(hull)){
129    PyErr_SetString(PyExc_TypeError,
130                    "incorrect seventh argument for 'genMesh': list required.");
131    return NULL;
132  }
133  if(!PyList_Check(hull)){
134    PyErr_SetString(PyExc_TypeError,
135                    "incorrect eighth argument for 'genMesh': list required.");
136    return NULL;
137  }
138     
139  /* printf("starting\n"); */   
140     
141  /* Initialize  points */
142  in.numberofpoints =  PyList_Size(hull); 
143  in.pointlist = (REAL *)malloc(in.numberofpoints*2*sizeof(REAL));
144  in.pointmarkerlist = (int *)NULL; /* malloc(in.numberofpoints*sizeof(int)); */
145     
146  /* Initialize and fill up region list */
147  in.numberofregions = PyList_Size(regionlist);
148 
149  /*printf(" numberofregions %i\n",in.numberofregions );*/
150  in.regionlist = (REAL *)malloc(in.numberofregions*4*sizeof(REAL));
151  for(i=0; i<in.numberofregions;i++){
152    elems = PyList_GetItem(regionlist,i);
153    tuplesize = PySequence_Length(elems);
154    /*printf("tuplesize %i\n",tuplesize);*/
155    if (tuplesize>0){
156      in.regionlist[4*i] = PyFloat_AsDouble(PyTuple_GetItem(elems,0));
157    } else {
158      PyErr_SetString(PyExc_TypeError,
159                      "data sent to trianglemodule error: A region has no x value.");
160      return NULL;
161    }
162    if (tuplesize>1){
163      in.regionlist[4*i+1] = PyFloat_AsDouble(PyTuple_GetItem(elems,1));
164    } else {
165      PyErr_SetString(PyExc_TypeError,
166                    "data sent to trianglemodule error: A region has no y value.");
167      return NULL;
168    }
169    if (tuplesize>2){
170      /* 2 is attribute*/
171      in.regionlist[4*i+2] = PyFloat_AsDouble(PyTuple_GetItem(elems,2));
172    } else {
173      PyErr_SetString(PyExc_TypeError,
174                    "data sent to trianglemodule error: A region has no attribute value.");
175      return NULL;
176    }
177    if (tuplesize>3){
178      in.regionlist[4*i+3] = PyFloat_AsDouble(PyTuple_GetItem(elems,3));
179    } else {
180      /* 0.0 is interpreted as no local max area by triangle  */
181      in.regionlist[4*i+3] = (REAL)0.0;
182    } 
183  }
184 
185  /*Initialize segments */
186  in.numberofsegments = PyList_Size(seglist);
187  in.segmentlist = (int *)malloc(in.numberofsegments*2*sizeof(int));
188  in.segmentmarkerlist = (int *)malloc(in.numberofsegments*sizeof(int));
189
190   
191  /*Initialize triangles */
192  in.numberofcorners = 3;
193  in.numberoftriangles = PyList_Size(trianglelist);
194  if (in.numberoftriangles  != 0) {
195    in.trianglelist = (int *)malloc(in.numberofsegments*3*sizeof(int));
196  } else {
197    in.trianglelist = (int *)NULL;
198  }
199  in.numberoftriangleattributes = 0; 
200  in.triangleattributelist  = (REAL *)NULL; 
201     
202     
203     
204  /*Initialize holes */
205  in.numberofholes = PyList_Size(holelist);
206  if (in.numberofholes != 0) {
207    in.holelist = (REAL *)malloc(in.numberofholes*2*sizeof(REAL));
208  } else {
209    in.holelist = (REAL *)NULL;
210  }     
211     
212  /* Fill up triangle list */
213  index = 0;
214  for(i = 0; i < in.numberoftriangles; i++) {
215    pair =  PyList_GetItem(trianglelist,i);
216    if (3 != PySequence_Length(pair)) {
217      PyErr_SetString(PyExc_TypeError,
218                      "data sent to trianglemodule error:Found a triangle without 3 vertices.");
219      return NULL;
220    }
221    a = (int)PyInt_AsLong(PyTuple_GetItem(pair,0));
222    in.trianglelist[index] = a;
223    index++;
224    b = (int)PyInt_AsLong(PyTuple_GetItem(pair,1));
225    in.trianglelist[index] = b;
226    index++;
227    c = (int)PyInt_AsLong(PyTuple_GetItem(pair,2));
228    in.trianglelist[index] = c;
229    index++;
230  }
231     
232     
233  /*  print the triangle list DEBUGGING
234      printf ("numberoftriangles %i\n", in.numberoftriangles);
235      for(i = 0; i < in.numberoftriangles; i++) {
236      printf("(%i,%i,%i)",in.trianglelist[i* 3+ 0],in.trianglelist[i* 3+ 1], in.trianglelist[i* 3+ 2]);
237      }*/
238     
239  /* Fill up segment list */
240  index = 0;
241  if (in.numberofsegments != PyList_Size(segmarkerlist)) {
242    PyErr_SetString(PyExc_TypeError,
243                    "data sent to trianglemodule error:number of segments doesn't = number of segment attributes.");
244    return NULL;
245  }
246   
247  for(i = 0; i < in.numberofsegments; i++) {
248    pair =  PyList_GetItem(seglist,i);
249    if (2 != PySequence_Length(pair)) {
250      PyErr_SetString(PyExc_TypeError,
251                      "data sent to trianglemodule error:Found a segment without 2 vertices.");
252      return NULL;
253    }
254    a = (int)PyInt_AsLong(PyTuple_GetItem(pair,0));
255    in.segmentlist[index] = a;
256    index++;
257    b = (int)PyInt_AsLong(PyTuple_GetItem(pair,1));
258    in.segmentlist[index] = b;
259    index++;
260    /* Fill up segment marker list */
261    marker =  (int)PyInt_AsLong(PyList_GetItem(segmarkerlist,i));
262    in.segmentmarkerlist[i] = marker;
263  }
264  /* Fill up hole list */
265  index = 0;
266  for(i = 0; i < in.numberofholes; i++) {
267    pair =  PyList_GetItem(holelist,i);
268    if (2 != PySequence_Length(pair)) {
269      PyErr_SetString(PyExc_TypeError,
270                      "data sent to trianglemodule error:Found a pair without 2 vertices.");
271      return NULL;
272    }
273    x = PyFloat_AsDouble(PyTuple_GetItem(pair,0));
274    in.holelist[index] = x;
275    index++;
276    y = PyFloat_AsDouble(PyTuple_GetItem(pair,1));
277    in.holelist[index] = y;
278    index++;
279  }
280     
281  /* Fill up point list */
282  index = 0;
283  for(i = 0; i < in.numberofpoints; i++) {
284    pair =  PyList_GetItem(hull,i);
285    if (2 != PySequence_Length(pair)) {
286      PyErr_SetString(PyExc_TypeError,
287                      "data sent to trianglemodule error:Found a vertex without an x,y values.");
288      return NULL;
289    }
290    x = PyFloat_AsDouble(PyTuple_GetItem(pair,0));
291    in.pointlist[index] = x;
292    index++;
293    y = PyFloat_AsDouble(PyTuple_GetItem(pair,1));
294    in.pointlist[index] = y;
295    index++;
296  }
297
298  /* Initialize  point attributes */
299/*      firstPointAttr = PyList_GetItem(pointattributelist,0); */
300/*      if (firstPointAttr != NULL) { */
301/*        //in.numberofpointattributes = PyList_Size(firstPointAttr); */
302/*        printf("in.numberofpointattributes =%i",PyList_Size(firstPointAttr)); */
303/*        //printf("in.numberofpointattributes =%i",in.numberofpointattributes); */
304/*      } else { */
305/*        printf("(firstPointAttr is NULL\n"); */
306/*        in.pointattributelist = NULL; */
307/*        in.numberofpointattributes = 0; */
308/*      } */
309  n = PyList_Size(pointattributelist);
310  if (n < 0) {
311    in.numberofpointattributes = 0; 
312    in.pointattributelist = (REAL *)NULL;
313  } else {
314    /* Get the # of attributes based on the size of the first point*/
315    firstPointAttr = PyList_GetItem(pointattributelist,0);
316    if (firstPointAttr == NULL) {
317      in.numberofpointattributes = 0; 
318      in.pointattributelist = (REAL *)NULL;
319    } else {
320      in.numberofpointattributes = PyList_Size(firstPointAttr);
321      in.pointattributelist = (REAL *)malloc(in.numberofpoints
322                                             *in.numberofpointattributes
323                                             *sizeof(REAL)); 
324     
325     
326      /* fill the point attribute list */
327      if (in.numberofpointattributes != 0) {
328        for(j = 0; j < in.numberofpoints; j++){
329          Attrlist = PyList_GetItem(pointattributelist,j);
330          if (in.numberofpointattributes != PySequence_Length(Attrlist)) {
331            PyErr_SetString(PyExc_TypeError,
332                            "data sent to trianglemodule error:List size of attributes is different from vertex to vertex.");
333            return NULL;
334          }
335          for(i = 0; i < in.numberofpointattributes; i++){
336            Attr = PyFloat_AsDouble(PyList_GetItem(Attrlist,i));
337            in.pointattributelist[in.numberofpointattributes*j+i]= (REAL)Attr;
338            /*   printf("i =%i\n",i);  */
339            /*   printf("j =%i\n",j);  */
340            /*   printf("in.pointattributelist[4*j+i]
341                 =%f\n",in.pointattributelist[4*j+i]); */
342          }
343        }
344      } 
345    }
346  }
347   
348     
349  /* this half from triangulate*/
350  /* set up the switch arguments to the triangulation routine */
351
352  mod = PyString_AS_STRING(mode);
353     
354         
355  out.pointlist = (REAL *)NULL;
356  out.pointmarkerlist = (int *)NULL;
357  out.numberofpointattributes = in.numberofpointattributes;
358  out.pointattributelist = (REAL *)NULL;
359 
360  out.trianglelist = (int *)NULL;
361  out.triangleattributelist = (REAL *)NULL;                   
362  out.trianglearealist = (REAL *)NULL;                       
363  out.neighborlist = (int *)NULL;
364     
365  out.segmentlist = (int *)NULL;
366  out.segmentmarkerlist = (int *)NULL;
367     
368  out.edgelist = (int *)NULL;
369  out.edgemarkerlist = (int *)NULL;
370     
371  out.holelist = (REAL *)NULL;
372  out.regionlist = (REAL *)NULL;
373   
374 
375  /*printf("\n\nTriangulate input args: %s \n\n", mod); */
376  triangulate(mod, &in, &out, (struct triangulateio *)NULL );
377
378  /*
379    ------- Pass point numbers,coordinates and neighbors back to Python ------
380    we send back a dictionary:                                               
381    { index : [ coordinates, [connections], Attribute ] }
382  */
383  holder = PyDict_New();
384     
385  /* list of int's, used to keep track of which verts are connected to
386     triangles. */
387  points_connected = (int *)malloc(out.numberofpoints*sizeof(int));
388 
389  /* Add pointlist */
390  listsize = out.numberofpoints;
391  holderlist = PyList_New(listsize);
392     
393  for(i=0; i<listsize;i++){
394    PyObject *mlist = Py_BuildValue((char *)"(d,d)", 
395                                    out.pointlist[i*2  ], out.pointlist[i*2+1]); 
396    PyList_SetItem(holderlist,i, mlist);
397    points_connected[i] = 0;
398  } 
399  ii=PyString_FromString("generatedpointlist");
400  PyDict_SetItem(holder, ii, holderlist); Py_DECREF(ii); Py_DECREF(holderlist);
401   
402  /* Add point marker list */
403  listsize = out.numberofpoints;
404  holderlist = PyList_New(listsize);
405 
406  for(i=0; i<listsize;i++){
407    PyObject *mlist = Py_BuildValue((char *)"d", 
408                                    out.pointmarkerlist[i]);     
409    PyList_SetItem(holderlist,i, mlist); 
410  } 
411  ii=PyString_FromString("generatedpointmarkerlist");
412  PyDict_SetItem(holder, ii, holderlist); Py_DECREF(ii); Py_DECREF(holderlist);
413   
414  /* Add point attribute list */
415  listsize = out.numberofpoints;
416  holderlist = PyList_New(listsize);
417 
418  for(i=0; i<listsize;i++){
419    attsize = out.numberofpointattributes;
420    attributelist = PyList_New(attsize);
421    for(iatt=0; iatt<attsize;iatt++){
422      PyObject *mlist = Py_BuildValue((char *)"d", 
423                                      out.pointattributelist[i*attsize + iatt]);     
424      PyList_SetItem(attributelist,iatt, mlist);
425    }     
426    PyList_SetItem(holderlist,i, attributelist);
427  } 
428  ii=PyString_FromString("generatedpointattributelist");
429  PyDict_SetItem(holder, ii, holderlist); Py_DECREF(ii); Py_DECREF(holderlist); 
430 
431 
432  /* Add triangle list */
433  listsize = out.numberoftriangles;
434  holderlist = PyList_New(listsize);
435  for(i=0; i<listsize;i++){
436    PyObject *mlist = Py_BuildValue((char *)"(i,i,i)", 
437                                    out.trianglelist[i*3  ], out.trianglelist [i*3+1], out.trianglelist [i*3+2]);   
438    PyList_SetItem(holderlist,i, mlist);
439    /* printf(" A vert index %i\n",out.trianglelist[i*3] );
440    printf(" A vert index %i\n",out.trianglelist[i*3+1] );
441    printf(" A vert index %i\n",out.trianglelist[i*3+2] ); */
442    points_connected[out.trianglelist[i*3]] = 1;
443    points_connected[out.trianglelist[i*3+1]] = 1;
444    points_connected[out.trianglelist[i*3+2]] = 1;
445  }   
446  ii=PyString_FromString("generatedtrianglelist");
447  PyDict_SetItem(holder, ii, holderlist); Py_DECREF(ii); Py_DECREF(holderlist);
448 
449  /* convert the points_connected vector from a true(1) false(0) vector, where
450     index is the vert, to a vector of the lone verts, at the beggining
451     of the vector. */
452  write_here = 0;   
453  for(i=0; i<out.numberofpoints;i++){
454    if (0 == points_connected[i]) {
455      points_connected[write_here] = i;
456      write_here ++;
457    }
458  }   
459  /* printf(" ******************** \n" );
460  for(i=0; i<write_here;i++){
461    printf(" A vert index %i\n",points_connected[i] );
462    } */
463 
464  listsize = write_here;
465  holderlist = PyList_New(listsize);
466  for(i=0; i<listsize;i++){
467   PyObject *mlist = Py_BuildValue((char *)"i", points_connected[i]);   
468    PyList_SetItem(holderlist,i, mlist);
469  }
470  ii=PyString_FromString("lonepointlist");
471  PyDict_SetItem(holder, ii, holderlist); Py_DECREF(ii); Py_DECREF(holderlist); 
472     
473  /* Add triangle attribute list */
474  listsize = out.numberoftriangles;
475  holderlist = PyList_New(listsize);
476     
477  for(i=0; i<listsize; i++){
478    attsize = out.numberoftriangleattributes;
479    attributelist = PyList_New(attsize);       
480    for(iatt=0; iatt<attsize;iatt++){
481      PyObject *mlist = Py_BuildValue((char *)"d",out.triangleattributelist[i*attsize + iatt]);     
482      PyList_SetItem(attributelist,iatt, mlist);
483    }     
484    PyList_SetItem(holderlist,i, attributelist);
485  } 
486  ii=PyString_FromString("generatedtriangleattributelist");
487  PyDict_SetItem(holder, ii, holderlist); Py_DECREF(ii); Py_DECREF(holderlist);
488 
489  /* Add segment list */
490  listsize = out.numberofsegments;
491  holderlist = PyList_New(listsize);
492  for(i=0; i<listsize;i++){
493    PyObject *mlist = Py_BuildValue((char *)"(i,i)", 
494                                    out.segmentlist[i*2  ],
495                                    out.segmentlist [i*2+1]);
496    PyList_SetItem(holderlist,i, mlist);
497  }   
498  ii=PyString_FromString("generatedsegmentlist");
499  PyDict_SetItem(holder, ii, holderlist); Py_DECREF(ii); Py_DECREF(holderlist); 
500 
501  /* Add segment marker list */
502  listsize = out.numberofsegments;
503  holderlist = PyList_New(listsize);
504  for(i=0; i<listsize;i++){
505    PyObject *mlist = Py_BuildValue((char *)"i", 
506                                    out.segmentmarkerlist[i]);
507    PyList_SetItem(holderlist,i, mlist);
508  }   
509  ii=PyString_FromString("generatedsegmentmarkerlist");
510  PyDict_SetItem(holder, ii, holderlist); Py_DECREF(ii); Py_DECREF(holderlist); 
511  /* Add triangle neighbor list */
512  if (out.neighborlist != NULL) {
513    listsize = out.numberoftriangles;
514    holderlist = PyList_New(listsize);
515    for(i=0; i<listsize;i++){
516      PyObject *mlist = Py_BuildValue((char *)"(i,i,i)", 
517                                      out.neighborlist[i*3  ],
518                                      out.neighborlist [i*3+1],
519                                      out.neighborlist [i*3+2]);   
520      PyList_SetItem(holderlist,i, mlist);
521    }   
522    ii=PyString_FromString("generatedtriangleneighborlist");
523    PyDict_SetItem(holder, ii, holderlist);
524    Py_DECREF(ii); Py_DECREF(holderlist);
525  }   
526     
527  /* Free in/out structure memory */
528 
529  /* OUT */
530
531  if(!out.pointlist){
532    free(out.pointlist);  out.pointlist=NULL;
533  }
534  if(!out.pointmarkerlist){   
535    free(out.pointmarkerlist); out.pointmarkerlist=NULL;
536  }
537  if(!out.pointattributelist){   
538    free(out.pointattributelist); out.pointattributelist=NULL;
539  }
540   
541 
542  if(!out.trianglelist){   
543    free(out.trianglelist); out.trianglelist=NULL;
544  }
545  if(!out.triangleattributelist){   
546    free(out.triangleattributelist); out.triangleattributelist=NULL;
547  }
548  if(!out.trianglearealist){   
549    free(out.trianglearealist); out.trianglearealist=NULL;
550  }
551  if(!out.neighborlist){   
552    free(out.neighborlist); out.neighborlist=NULL;
553  }
554  if(!out.segmentlist){
555    free(out.segmentlist); out.segmentlist =NULL;
556  }
557  if(!out.segmentmarkerlist){
558    free(out.segmentmarkerlist); out.segmentmarkerlist  =NULL;
559  }
560  if(!out.edgelist){
561    free(out.edgelist);  out.edgelist=NULL;
562  }
563  if(!out.edgemarkerlist){
564    free(out.edgemarkerlist);  out.edgemarkerlist=NULL;
565  }
566  if(!out.holelist){
567    free(out.holelist); out.holelist=NULL;
568  }
569  if(!out.regionlist){
570    free(out.regionlist); out.regionlist=NULL;
571  }
572  if(!points_connected ){
573    free(points_connected ); points_connected =NULL;
574  }
575   
576 
577 
578  /*  IN */
579 
580  if(!in.pointlist){
581    free(in.pointlist);  in.pointlist   =NULL;             
582  }
583  if(!in.pointattributelist){
584    free(in.pointattributelist); in.pointattributelist =NULL;       
585  }
586  if(!in.pointmarkerlist){
587    free(in.pointmarkerlist); in.pointmarkerlist    =NULL;       
588  }
589  if(!in.segmentlist){
590    free(in.segmentlist);  in.segmentlist    =NULL;         
591  }
592  if(!in.segmentmarkerlist){
593    free(in.segmentmarkerlist); in.segmentmarkerlist    =NULL;   
594  }
595  if(!in.regionlist){
596    free(in.regionlist); in.regionlist  =NULL;           
597  }
598  if(!in.holelist){
599    free(in.holelist); in.holelist=NULL;
600  }
601
602  //return Py_BuildValue((char *)"O", holder);
603  return Py_BuildValue((char *)"O", holder);
604}
605
606/* end of my function*/
607
608
609   
610   
611static PyMethodDef triang_methods[] = {
612  {(char *)"genMesh", triang_genMesh, 1, (char *)"Passes hull points to triangle.All arguments are lists.(<hull>,<seglist>,<holelist>,<regionlist>)-><hull>"}, 
613  {NULL,NULL}
614};
615
616void inittriang(){
617  Py_InitModule((char *)"triang",triang_methods);
618}   
Note: See TracBrowser for help on using the repository browser.