source: inundation-numpy-branch/triangle/triang.c @ 3031

Last change on this file since 3031 was 2526, checked in by ole, 19 years ago

Moved more general numerical functionality into utilities/numerical_tools.py

File size: 18.1 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;
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  if(!PyArg_ParseTuple(args,(char *)"OOOOOOOO",&hull,&seglist,&holelist,&regionlist,&pointattributelist,&segmarkerlist,&trianglelist,&mode)){
94    return NULL;
95  }
96  if(!PyList_Check(hull)){
97    PyErr_SetString(PyExc_TypeError, 
98                    "incorrect first argument for 'genMesh': list required.");
99    return NULL;
100  }
101  if(!PyList_Check(hull)){
102    PyErr_SetString(PyExc_TypeError,
103                    "incorrect second argument for 'genMesh': list required.");
104    return NULL;
105  }
106  if(!PyList_Check(hull)){
107    PyErr_SetString(PyExc_TypeError,
108                    "incorrect third argument for 'genMesh': list required.");
109    return NULL;
110  }
111  if(!PyList_Check(hull)){
112    PyErr_SetString(PyExc_TypeError,
113                    "incorrect fourth argument for 'genMesh': list required.");
114    return NULL;
115  }
116  if(!PyList_Check(hull)){
117    PyErr_SetString(PyExc_TypeError,
118                    "incorrect fifth argument for 'genMesh': list required.");
119    return NULL;
120  }
121  if(!PyList_Check(hull)){
122    PyErr_SetString(PyExc_TypeError,
123                    "incorrect sixth argument for 'genMesh': list required.");
124    return NULL;
125  }
126  if(!PyList_Check(hull)){
127    PyErr_SetString(PyExc_TypeError,
128                    "incorrect seventh argument for 'genMesh': list required.");
129    return NULL;
130  }
131  if(!PyList_Check(hull)){
132    PyErr_SetString(PyExc_TypeError,
133                    "incorrect eighth argument for 'genMesh': list required.");
134    return NULL;
135  }
136     
137     
138  /* Initialize  points */
139  in.numberofpoints =  PyList_Size(hull); 
140  in.pointlist = (REAL *)malloc(in.numberofpoints*2*sizeof(REAL));
141  in.pointmarkerlist = (int *)NULL; /* malloc(in.numberofpoints*sizeof(int)); */
142     
143  /* Initialize and fill up region list */
144  in.numberofregions = PyList_Size(regionlist);
145 
146  /*printf(" numberofregions %i\n",in.numberofregions );*/
147  in.regionlist = (REAL *)malloc(in.numberofregions*4*sizeof(REAL));
148  for(i=0; i<in.numberofregions;i++){
149    elems = PyList_GetItem(regionlist,i);
150    tuplesize = PySequence_Length(elems);
151    /*printf("tuplesize %i\n",tuplesize);*/
152    if (tuplesize>0){
153      in.regionlist[4*i] = PyFloat_AsDouble(PyTuple_GetItem(elems,0));
154    } else {
155      PyErr_SetString(PyExc_TypeError,
156                      "data sent to trianglemodule error: A region has no x value.");
157      return NULL;
158    }
159    if (tuplesize>1){
160      in.regionlist[4*i+1] = PyFloat_AsDouble(PyTuple_GetItem(elems,1));
161    } else {
162      PyErr_SetString(PyExc_TypeError,
163                    "data sent to trianglemodule error: A region has no y value.");
164      return NULL;
165    }
166    if (tuplesize>2){
167      /* 2 is attribute*/
168      in.regionlist[4*i+2] = PyFloat_AsDouble(PyTuple_GetItem(elems,2));
169    } else {
170      PyErr_SetString(PyExc_TypeError,
171                    "data sent to trianglemodule error: A region has no attribute value.");
172      return NULL;
173    }
174    if (tuplesize>3){
175      in.regionlist[4*i+3] = PyFloat_AsDouble(PyTuple_GetItem(elems,3));
176    } else {
177      /* 0.0 is interpreted as no local max area by triangle  */
178      in.regionlist[4*i+3] = (REAL)0.0;
179    } 
180  }
181 
182  /*Initialize segments */
183  in.numberofsegments = PyList_Size(seglist);
184  in.segmentlist = (int *)malloc(in.numberofsegments*2*sizeof(int));
185  in.segmentmarkerlist = (int *)malloc(in.numberofsegments*sizeof(int));
186
187   
188  /*Initialize triangles */
189  in.numberofcorners = 3;
190  in.numberoftriangles = PyList_Size(trianglelist);
191  if (in.numberoftriangles  != 0) {
192    in.trianglelist = (int *)malloc(in.numberofsegments*3*sizeof(int));
193  } else {
194    in.trianglelist = (int *)NULL;
195  }
196  in.numberoftriangleattributes = 0; 
197  in.triangleattributelist  = (REAL *)NULL; 
198     
199     
200     
201  /*Initialize holes */
202  in.numberofholes = PyList_Size(holelist);
203  if (in.numberofholes != 0) {
204    in.holelist = (REAL *)malloc(in.numberofholes*2*sizeof(REAL));
205  } else {
206    in.holelist = (REAL *)NULL;
207  }     
208     
209  /* Fill up triangle list */
210  index = 0;
211  for(i = 0; i < in.numberoftriangles; i++) {
212    pair =  PyList_GetItem(trianglelist,i);
213    if (3 != PySequence_Length(pair)) {
214      PyErr_SetString(PyExc_TypeError,
215                      "data sent to trianglemodule error:Found a triangle without 3 vertices.");
216      return NULL;
217    }
218    a = (int)PyInt_AsLong(PyTuple_GetItem(pair,0));
219    in.trianglelist[index] = a;
220    index++;
221    b = (int)PyInt_AsLong(PyTuple_GetItem(pair,1));
222    in.trianglelist[index] = b;
223    index++;
224    c = (int)PyInt_AsLong(PyTuple_GetItem(pair,2));
225    in.trianglelist[index] = c;
226    index++;
227  }
228     
229     
230  /*  print the triangle list DEBUGGING
231      printf ("numberoftriangles %i\n", in.numberoftriangles);
232      for(i = 0; i < in.numberoftriangles; i++) {
233      printf("(%i,%i,%i)",in.trianglelist[i* 3+ 0],in.trianglelist[i* 3+ 1], in.trianglelist[i* 3+ 2]);
234      }*/
235     
236  /* Fill up segment list */
237  index = 0;
238  if (in.numberofsegments != PyList_Size(segmarkerlist)) {
239    PyErr_SetString(PyExc_TypeError,
240                    "data sent to trianglemodule error:number of segments doesn't = number of segment attributes.");
241    return NULL;
242  }
243   
244  for(i = 0; i < in.numberofsegments; i++) {
245    pair =  PyList_GetItem(seglist,i);
246    if (2 != PySequence_Length(pair)) {
247      PyErr_SetString(PyExc_TypeError,
248                      "data sent to trianglemodule error:Found a segment without 2 vertices.");
249      return NULL;
250    }
251    a = (int)PyInt_AsLong(PyTuple_GetItem(pair,0));
252    in.segmentlist[index] = a;
253    index++;
254    b = (int)PyInt_AsLong(PyTuple_GetItem(pair,1));
255    in.segmentlist[index] = b;
256    index++;
257    /* Fill up segment marker list */
258    marker =  (int)PyInt_AsLong(PyList_GetItem(segmarkerlist,i));
259    in.segmentmarkerlist[i] = marker;
260  }
261  /* Fill up hole list */
262  index = 0;
263  for(i = 0; i < in.numberofholes; i++) {
264    pair =  PyList_GetItem(holelist,i);
265    if (2 != PySequence_Length(pair)) {
266      PyErr_SetString(PyExc_TypeError,
267                      "data sent to trianglemodule error:Found a pair without 2 vertices.");
268      return NULL;
269    }
270    x = PyFloat_AsDouble(PyTuple_GetItem(pair,0));
271    in.holelist[index] = x;
272    index++;
273    y = PyFloat_AsDouble(PyTuple_GetItem(pair,1));
274    in.holelist[index] = y;
275    index++;
276  }
277     
278  /* Fill up point list */
279  index = 0;
280  for(i = 0; i < in.numberofpoints; i++) {
281    pair =  PyList_GetItem(hull,i);
282    if (2 != PySequence_Length(pair)) {
283      PyErr_SetString(PyExc_TypeError,
284                      "data sent to trianglemodule error:Found a vertex without an x,y values.");
285      return NULL;
286    }
287    x = PyFloat_AsDouble(PyTuple_GetItem(pair,0));
288    in.pointlist[index] = x;
289    index++;
290    y = PyFloat_AsDouble(PyTuple_GetItem(pair,1));
291    in.pointlist[index] = y;
292    index++;
293  }
294
295  /* Initialize  point attributes */
296/*      firstPointAttr = PyList_GetItem(pointattributelist,0); */
297/*      if (firstPointAttr != NULL) { */
298/*        //in.numberofpointattributes = PyList_Size(firstPointAttr); */
299/*        printf("in.numberofpointattributes =%i",PyList_Size(firstPointAttr)); */
300/*        //printf("in.numberofpointattributes =%i",in.numberofpointattributes); */
301/*      } else { */
302/*        printf("(firstPointAttr is NULL\n"); */
303/*        in.pointattributelist = NULL; */
304/*        in.numberofpointattributes = 0; */
305/*      } */
306  n = PyList_Size(pointattributelist);
307  if (n < 0) {
308    in.numberofpointattributes = 0; 
309    in.pointattributelist = (REAL *)NULL;
310  } else {
311    /* Get the # of attributes based on the size of the first point*/
312    firstPointAttr = PyList_GetItem(pointattributelist,0);
313    if (firstPointAttr == NULL) {
314      in.numberofpointattributes = 0; 
315      in.pointattributelist = (REAL *)NULL;
316    } else {
317      in.numberofpointattributes = PyList_Size(firstPointAttr);
318      in.pointattributelist = (REAL *)malloc(in.numberofpoints
319                                             *in.numberofpointattributes
320                                             *sizeof(REAL)); 
321     
322     
323      /* fill the point attribute list */
324      if (in.numberofpointattributes != 0) {
325        for(j = 0; j < in.numberofpoints; j++){
326          Attrlist = PyList_GetItem(pointattributelist,j);
327          if (in.numberofpointattributes != PySequence_Length(Attrlist)) {
328            PyErr_SetString(PyExc_TypeError,
329                            "data sent to trianglemodule error:List size of attributes is different from vertex to vertex.");
330            return NULL;
331          }
332          for(i = 0; i < in.numberofpointattributes; i++){
333            Attr = PyFloat_AsDouble(PyList_GetItem(Attrlist,i));
334            in.pointattributelist[in.numberofpointattributes*j+i]= (REAL)Attr;
335            /*   printf("i =%i\n",i);  */
336            /*   printf("j =%i\n",j);  */
337            /*   printf("in.pointattributelist[4*j+i]
338                 =%f\n",in.pointattributelist[4*j+i]); */
339          }
340        }
341      } 
342    }
343  }
344   
345     
346  /* this half from triangulate*/
347  /* set up the switch arguments to the triangulation routine */
348
349  mod = PyString_AS_STRING(mode);
350     
351         
352  out.pointlist = (REAL *)NULL;
353  out.pointmarkerlist = (int *)NULL;
354  out.numberofpointattributes = in.numberofpointattributes;
355  out.pointattributelist = (REAL *)NULL;
356 
357  out.trianglelist = (int *)NULL;
358  out.triangleattributelist = (REAL *)NULL;                   
359  out.trianglearealist = (REAL *)NULL;                       
360  out.neighborlist = (int *)NULL;
361     
362  out.segmentlist = (int *)NULL;
363  out.segmentmarkerlist = (int *)NULL;
364     
365  out.edgelist = (int *)NULL;
366  out.edgemarkerlist = (int *)NULL;
367     
368  out.holelist = (REAL *)NULL;
369  out.regionlist = (REAL *)NULL;
370   
371  /*printf("\n\nTriangulate input args: %s \n\n", mod); */
372  triangulate(mod, &in, &out, (struct triangulateio *)NULL );
373
374  /*
375    ------- Pass point numbers,coordinates and neighbors back to Python ------
376    we send back a dictionary:                                               
377    { index : [ coordinates, [connections], Attribute ] }
378  */
379  holder = PyDict_New();
380     
381  /* Add pointlist */
382  listsize = out.numberofpoints;
383  holderlist = PyList_New(listsize);
384     
385  for(i=0; i<listsize;i++){
386    PyObject *mlist = Py_BuildValue((char *)"(d,d)", 
387                                    out.pointlist[i*2  ], out.pointlist[i*2+1]); 
388    PyList_SetItem(holderlist,i, mlist);
389  } 
390  ii=PyString_FromString("generatedpointlist");
391  PyDict_SetItem(holder, ii, holderlist); Py_DECREF(ii); Py_DECREF(holderlist);
392   
393  /* Add point marker list */
394  listsize = out.numberofpoints;
395  holderlist = PyList_New(listsize);
396 
397  for(i=0; i<listsize;i++){
398    PyObject *mlist = Py_BuildValue((char *)"d", 
399                                    out.pointmarkerlist[i]);     
400    PyList_SetItem(holderlist,i, mlist); 
401  } 
402  ii=PyString_FromString("generatedpointmarkerlist");
403  PyDict_SetItem(holder, ii, holderlist); Py_DECREF(ii); Py_DECREF(holderlist);
404   
405  /* Add point attribute list */
406  listsize = out.numberofpoints;
407  holderlist = PyList_New(listsize);
408 
409  for(i=0; i<listsize;i++){
410    attsize = out.numberofpointattributes;
411    attributelist = PyList_New(attsize);
412    for(iatt=0; iatt<attsize;iatt++){
413      PyObject *mlist = Py_BuildValue((char *)"d", 
414                                      out.pointattributelist[i*attsize + iatt]);     
415      PyList_SetItem(attributelist,iatt, mlist);
416    }     
417    PyList_SetItem(holderlist,i, attributelist);
418  } 
419  ii=PyString_FromString("generatedpointattributelist");
420  PyDict_SetItem(holder, ii, holderlist); Py_DECREF(ii); Py_DECREF(holderlist); 
421 
422  /* Add triangle list */
423  listsize = out.numberoftriangles;
424  holderlist = PyList_New(listsize);
425  for(i=0; i<listsize;i++){
426    PyObject *mlist = Py_BuildValue((char *)"(i,i,i)", 
427                                    out.trianglelist[i*3  ], out.trianglelist [i*3+1], out.trianglelist [i*3+2]);   
428    PyList_SetItem(holderlist,i, mlist);
429  }   
430  ii=PyString_FromString("generatedtrianglelist");
431  PyDict_SetItem(holder, ii, holderlist); Py_DECREF(ii); Py_DECREF(holderlist);
432     
433     
434  /* Add triangle attribute list */
435  listsize = out.numberoftriangles;
436  holderlist = PyList_New(listsize);
437     
438  for(i=0; i<listsize; i++){
439    attsize = out.numberoftriangleattributes;
440    attributelist = PyList_New(attsize);       
441    for(iatt=0; iatt<attsize;iatt++){
442      PyObject *mlist = Py_BuildValue((char *)"d",out.triangleattributelist[i*attsize + iatt]);     
443      PyList_SetItem(attributelist,iatt, mlist);
444    }     
445    PyList_SetItem(holderlist,i, attributelist);
446  } 
447  ii=PyString_FromString("generatedtriangleattributelist");
448  PyDict_SetItem(holder, ii, holderlist); Py_DECREF(ii); Py_DECREF(holderlist);
449 
450  /* Add segment list */
451  listsize = out.numberofsegments;
452  holderlist = PyList_New(listsize);
453  for(i=0; i<listsize;i++){
454    PyObject *mlist = Py_BuildValue((char *)"(i,i)", 
455                                    out.segmentlist[i*2  ],
456                                    out.segmentlist [i*2+1]);
457    PyList_SetItem(holderlist,i, mlist);
458  }   
459  ii=PyString_FromString("generatedsegmentlist");
460  PyDict_SetItem(holder, ii, holderlist); Py_DECREF(ii); Py_DECREF(holderlist); 
461 
462  /* Add segment marker list */
463  listsize = out.numberofsegments;
464  holderlist = PyList_New(listsize);
465  for(i=0; i<listsize;i++){
466    PyObject *mlist = Py_BuildValue((char *)"i", 
467                                    out.segmentmarkerlist[i]);
468    PyList_SetItem(holderlist,i, mlist);
469  }   
470  ii=PyString_FromString("generatedsegmentmarkerlist");
471  PyDict_SetItem(holder, ii, holderlist); Py_DECREF(ii); Py_DECREF(holderlist); 
472  /* Add triangle neighbor list */
473  if (out.neighborlist != NULL) {
474    listsize = out.numberoftriangles;
475    holderlist = PyList_New(listsize);
476    for(i=0; i<listsize;i++){
477      PyObject *mlist = Py_BuildValue((char *)"(i,i,i)", 
478                                      out.neighborlist[i*3  ],
479                                      out.neighborlist [i*3+1],
480                                      out.neighborlist [i*3+2]);   
481      PyList_SetItem(holderlist,i, mlist);
482    }   
483    ii=PyString_FromString("generatedtriangleneighborlist");
484    PyDict_SetItem(holder, ii, holderlist);
485    Py_DECREF(ii); Py_DECREF(holderlist);
486  }   
487     
488  /* Free in/out structure memory */
489 
490  /* OUT */
491
492  if(!out.pointlist){
493    free(out.pointlist);  out.pointlist=NULL;
494  }
495  if(!out.pointmarkerlist){   
496    free(out.pointmarkerlist); out.pointmarkerlist=NULL;
497  }
498  if(!out.pointattributelist){   
499    free(out.pointattributelist); out.pointattributelist=NULL;
500  }
501   
502 
503  if(!out.trianglelist){   
504    free(out.trianglelist); out.trianglelist=NULL;
505  }
506  if(!out.triangleattributelist){   
507    free(out.triangleattributelist); out.triangleattributelist=NULL;
508  }
509  if(!out.trianglearealist){   
510    free(out.trianglearealist); out.trianglearealist=NULL;
511  }
512  if(!out.neighborlist){   
513    free(out.neighborlist); out.neighborlist=NULL;
514  }
515  if(!out.segmentlist){
516    free(out.segmentlist); out.segmentlist =NULL;
517  }
518  if(!out.segmentmarkerlist){
519    free(out.segmentmarkerlist); out.segmentmarkerlist  =NULL;
520  }
521  if(!out.edgelist){
522    free(out.edgelist);  out.edgelist=NULL;
523  }
524  if(!out.edgemarkerlist){
525    free(out.edgemarkerlist);  out.edgemarkerlist=NULL;
526  }
527  if(!out.holelist){
528    free(out.holelist); out.holelist=NULL;
529  }
530  if(!out.regionlist){
531    free(out.regionlist); out.regionlist=NULL;
532  }
533   
534  /*  IN */
535 
536  if(!in.pointlist){
537    free(in.pointlist);  in.pointlist   =NULL;             
538  }
539  if(!in.pointattributelist){
540    free(in.pointattributelist); in.pointattributelist =NULL;       
541  }
542  if(!in.pointmarkerlist){
543    free(in.pointmarkerlist); in.pointmarkerlist    =NULL;       
544  }
545  if(!in.segmentlist){
546    free(in.segmentlist);  in.segmentlist    =NULL;         
547  }
548  if(!in.segmentmarkerlist){
549    free(in.segmentmarkerlist); in.segmentmarkerlist    =NULL;   
550  }
551  if(!in.regionlist){
552    free(in.regionlist); in.regionlist  =NULL;           
553  }
554  if(!in.holelist){
555    free(in.holelist); in.holelist=NULL;
556  }
557
558  //return Py_BuildValue((char *)"O", holder);
559  return Py_BuildValue((char *)"O", holder);
560}
561
562/* end of my function*/
563
564
565   
566   
567static PyMethodDef triang_methods[] = {
568  {(char *)"genMesh", triang_genMesh, 1, (char *)"Passes hull points to triangle.All arguments are lists.(<hull>,<seglist>,<holelist>,<regionlist>)-><hull>"}, 
569  {NULL,NULL}
570};
571
572void inittriang(){
573  Py_InitModule((char *)"triang",triang_methods);
574}   
Note: See TracBrowser for help on using the repository browser.