QXRD  0.11.16
Classes | Macros | Functions
triangulate.c File Reference

(Commit a65ccc9... : jennings : 2016-03-15 14:00:18 -0500)

#include <stdlib.h>
Include dependency graph for triangulate.c:

Go to the source code of this file.

Classes

struct  ITRIANGLE
 
struct  IEDGE
 
struct  XYZ
 

Macros

#define FALSE   0
 
#define TRUE   1
 
#define EPSILON   1e-10
 

Functions

int Triangulate (int nv, XYZ *pxyz, ITRIANGLE *v, int *ntri)
 
int CircumCircle (double xp, double yp, double x1, double y1, double x2, double y2, double x3, double y3, double *xc, double *yc, double *rsqr)
 

Macro Definition Documentation

#define EPSILON   1e-10

Definition at line 5 of file triangulate.c.

Referenced by CircumCircle().

#define FALSE   0

Definition at line 3 of file triangulate.c.

Referenced by CircumCircle(), QxrdDetectorPerkinElmer::startDetector(), and Triangulate().

#define TRUE   1

Definition at line 4 of file triangulate.c.

Referenced by CircumCircle(), and Triangulate().

Function Documentation

int CircumCircle ( double  xp,
double  yp,
double  x1,
double  y1,
double  x2,
double  y2,
double  x3,
double  y3,
double *  xc,
double *  yc,
double *  rsqr 
)

Definition at line 227 of file triangulate.c.

References EPSILON, FALSE, and TRUE.

Referenced by Triangulate().

230 {
231  double m1,m2,mx1,mx2,my1,my2;
232  double dx,dy,drsqr;
233  double fabsy1y2 = fabs(y1-y2);
234  double fabsy2y3 = fabs(y2-y3);
235 
236  /* Check for coincident points */
237  if (fabsy1y2 < EPSILON && fabsy2y3 < EPSILON)
238  return(FALSE);
239 
240  if (fabsy1y2 < EPSILON) {
241  m2 = - (x3-x2) / (y3-y2);
242  mx2 = (x2 + x3) / 2.0;
243  my2 = (y2 + y3) / 2.0;
244  *xc = (x2 + x1) / 2.0;
245  *yc = m2 * (*xc - mx2) + my2;
246  } else if (fabsy2y3 < EPSILON) {
247  m1 = - (x2-x1) / (y2-y1);
248  mx1 = (x1 + x2) / 2.0;
249  my1 = (y1 + y2) / 2.0;
250  *xc = (x3 + x2) / 2.0;
251  *yc = m1 * (*xc - mx1) + my1;
252  } else {
253  m1 = - (x2-x1) / (y2-y1);
254  m2 = - (x3-x2) / (y3-y2);
255  mx1 = (x1 + x2) / 2.0;
256  mx2 = (x2 + x3) / 2.0;
257  my1 = (y1 + y2) / 2.0;
258  my2 = (y2 + y3) / 2.0;
259  *xc = (m1 * mx1 - m2 * mx2 + my2 - my1) / (m1 - m2);
260  if (fabsy1y2 > fabsy2y3) {
261  *yc = m1 * (*xc - mx1) + my1;
262  } else {
263  *yc = m2 * (*xc - mx2) + my2;
264  }
265  }
266 
267  dx = x2 - *xc;
268  dy = y2 - *yc;
269  *rsqr = dx*dx + dy*dy;
270 
271  dx = xp - *xc;
272  dy = yp - *yc;
273  drsqr = dx*dx + dy*dy;
274 
275  // Original
276  //return((drsqr <= *rsqr) ? TRUE : FALSE);
277  // Proposed by Chuck Morris
278  return((drsqr - *rsqr) <= EPSILON ? TRUE : FALSE);
279 }
#define FALSE
Definition: triangulate.c:3
#define TRUE
Definition: triangulate.c:4
#define EPSILON
Definition: triangulate.c:5

Here is the caller graph for this function:

int Triangulate ( int  nv,
XYZ pxyz,
ITRIANGLE v,
int *  ntri 
)

Definition at line 41 of file triangulate.c.

References CircumCircle(), FALSE, ITRIANGLE::p1, IEDGE::p1, ITRIANGLE::p2, IEDGE::p2, ITRIANGLE::p3, TRUE, XYZ::x, XYZ::y, and XYZ::z.

Referenced by QxrdCenterFinder::calculateCalibration().

42 {
43  int *complete = NULL;
44  IEDGE *edges = NULL;
45  int nedge = 0;
46  int trimax,emax = 200;
47  int status = 0;
48 
49  int inside;
50  int i,j,k;
51  double xp,yp,x1,y1,x2,y2,x3,y3,xc,yc,r;
52  double xmin,xmax,ymin,ymax,xmid,ymid;
53  double dx,dy,dmax;
54 
55  /* Allocate memory for the completeness list, flag for each triangle */
56  trimax = 4 * nv;
57  if ((complete = malloc(trimax*sizeof(int))) == NULL) {
58  status = 1;
59  goto skip;
60  }
61 
62  /* Allocate memory for the edge list */
63  if ((edges = malloc(emax*(long)sizeof(IEDGE))) == NULL) {
64  status = 2;
65  goto skip;
66  }
67 
68  /*
69  Find the maximum and minimum vertex bounds.
70  This is to allow calculation of the bounding triangle
71  */
72  xmin = pxyz[0].x;
73  ymin = pxyz[0].y;
74  xmax = xmin;
75  ymax = ymin;
76  for (i=1;i<nv;i++) {
77  if (pxyz[i].x < xmin) xmin = pxyz[i].x;
78  if (pxyz[i].x > xmax) xmax = pxyz[i].x;
79  if (pxyz[i].y < ymin) ymin = pxyz[i].y;
80  if (pxyz[i].y > ymax) ymax = pxyz[i].y;
81  }
82  dx = xmax - xmin;
83  dy = ymax - ymin;
84  dmax = (dx > dy) ? dx : dy;
85  xmid = (xmax + xmin) / 2.0;
86  ymid = (ymax + ymin) / 2.0;
87 
88  /*
89  Set up the supertriangle
90  This is a triangle which encompasses all the sample points.
91  The supertriangle coordinates are added to the end of the
92  vertex list. The supertriangle is the first triangle in
93  the triangle list.
94  */
95  pxyz[nv+0].x = xmid - 20 * dmax;
96  pxyz[nv+0].y = ymid - dmax;
97  pxyz[nv+0].z = 0.0;
98  pxyz[nv+1].x = xmid;
99  pxyz[nv+1].y = ymid + 20 * dmax;
100  pxyz[nv+1].z = 0.0;
101  pxyz[nv+2].x = xmid + 20 * dmax;
102  pxyz[nv+2].y = ymid - dmax;
103  pxyz[nv+2].z = 0.0;
104  v[0].p1 = nv;
105  v[0].p2 = nv+1;
106  v[0].p3 = nv+2;
107  complete[0] = FALSE;
108  *ntri = 1;
109 
110  /*
111  Include each point one at a time into the existing mesh
112  */
113  for (i=0;i<nv;i++) {
114 
115  xp = pxyz[i].x;
116  yp = pxyz[i].y;
117  nedge = 0;
118 
119  /*
120  Set up the edge buffer.
121  If the point (xp,yp) lies inside the circumcircle then the
122  three edges of that triangle are added to the edge buffer
123  and that triangle is removed.
124  */
125  for (j=0;j<(*ntri);j++) {
126  if (complete[j])
127  continue;
128  x1 = pxyz[v[j].p1].x;
129  y1 = pxyz[v[j].p1].y;
130  x2 = pxyz[v[j].p2].x;
131  y2 = pxyz[v[j].p2].y;
132  x3 = pxyz[v[j].p3].x;
133  y3 = pxyz[v[j].p3].y;
134  inside = CircumCircle(xp,yp,x1,y1,x2,y2,x3,y3,&xc,&yc,&r);
135  if (xc < xp && ((xp-xc)*(xp-xc)) > r)
136  complete[j] = TRUE;
137  if (inside) {
138  /* Check that we haven't exceeded the edge list size */
139  if (nedge+3 >= emax) {
140  emax += 100;
141  if ((edges = realloc(edges,emax*(long)sizeof(IEDGE))) == NULL) {
142  status = 3;
143  goto skip;
144  }
145  }
146  edges[nedge+0].p1 = v[j].p1;
147  edges[nedge+0].p2 = v[j].p2;
148  edges[nedge+1].p1 = v[j].p2;
149  edges[nedge+1].p2 = v[j].p3;
150  edges[nedge+2].p1 = v[j].p3;
151  edges[nedge+2].p2 = v[j].p1;
152  nedge += 3;
153  v[j] = v[(*ntri)-1];
154  complete[j] = complete[(*ntri)-1];
155  (*ntri)--;
156  j--;
157  }
158  }
159 
160  /*
161  Tag multiple edges
162  Note: if all triangles are specified anticlockwise then all
163  interior edges are opposite pointing in direction.
164  */
165  for (j=0;j<nedge-1;j++) {
166  for (k=j+1;k<nedge;k++) {
167  if ((edges[j].p1 == edges[k].p2) && (edges[j].p2 == edges[k].p1)) {
168  edges[j].p1 = -1;
169  edges[j].p2 = -1;
170  edges[k].p1 = -1;
171  edges[k].p2 = -1;
172  }
173  /* Shouldn't need the following, see note above */
174  if ((edges[j].p1 == edges[k].p1) && (edges[j].p2 == edges[k].p2)) {
175  edges[j].p1 = -1;
176  edges[j].p2 = -1;
177  edges[k].p1 = -1;
178  edges[k].p2 = -1;
179  }
180  }
181  }
182 
183  /*
184  Form new triangles for the current point
185  Skipping over any tagged edges.
186  All edges are arranged in clockwise order.
187  */
188  for (j=0;j<nedge;j++) {
189  if (edges[j].p1 < 0 || edges[j].p2 < 0)
190  continue;
191  if ((*ntri) >= trimax) {
192  status = 4;
193  goto skip;
194  }
195  v[*ntri].p1 = edges[j].p1;
196  v[*ntri].p2 = edges[j].p2;
197  v[*ntri].p3 = i;
198  complete[*ntri] = FALSE;
199  (*ntri)++;
200  }
201  }
202 
203  /*
204  Remove triangles with supertriangle vertices
205  These are triangles which have a vertex number greater than nv
206  */
207  for (i=0;i<(*ntri);i++) {
208  if (v[i].p1 >= nv || v[i].p2 >= nv || v[i].p3 >= nv) {
209  v[i] = v[(*ntri)-1];
210  (*ntri)--;
211  i--;
212  }
213  }
214 
215 skip:
216  free(edges);
217  free(complete);
218  return(status);
219 }
int p2
Definition: triangulate.c:11
#define FALSE
Definition: triangulate.c:3
int CircumCircle(double xp, double yp, double x1, double y1, double x2, double y2, double x3, double y3, double *xc, double *yc, double *rsqr)
Definition: triangulate.c:227
double x
Definition: triangulate.c:14
#define TRUE
Definition: triangulate.c:4
double z
Definition: triangulate.c:14
double y
Definition: triangulate.c:14
int p1
Definition: triangulate.c:11

Here is the call graph for this function:

Here is the caller graph for this function: