#include #include #include #include /* Useful definitions */ #define dsqf(u1,v1,u2,v2) ((u2-u1)*(u2-u1) + (v2-v1)*(v2-v1)) #define spdt(u1,v1,u2,v2,u3,v3) ((u2-u1)*(u3-u1) + (v2-v1)*(v3-v1)) #define vpdt(u1,v1,u2,v2,u3,v3) ((v3-v1)*(u2-u1) - (u3-u1)*(v2-v1)) #define ESPLN 1.0e-6 #define MAXOF(a,b) ((a > b) ? a : b) #define MINOF(a,b) ((a > b) ? b : a) /* There's a bug in here somewhere - don't do this! */ #define NREP 0 /* Declarations */ static int idxchg(); /* C THIS SUBROUTINE PERFORMS TRIANGULATION. IT DIVIDES THE X-Y C PLANE INTO A NUMBER OF TRIANGLES ACCORDING TO GIVEN DATA C POINTS IN THE PLANE, DETERMINES LINE SEGMENTS THAT FORM THE C BORDER OF DATA AREA, AND DETERMINES THE TRIANGLE NUMBERS C CORRESPONDING TO THE BORDER LINE SEGMENTS. C AT COMPLETION, POINT NUMBERS OF THE VERTEXES OF EACH TRIANGLE C ARE LISTED COUNTER-CLOCKWISE. POINT NUMBERS OF THE END POINTS C OF EACH BORDER LINE SEGMENT ARE LISTED COUNTER-CLOCKWISE, C LISTING ORDER OF THE LINE SEGMENTS BEING COUNTER-CLOCKWISE. C THIS SUBROUTINE CALLS THE IDXCHG FUNCTION. C THE INPUT PARAMETERS ARE C NDP = NUMBER OF DATA POINTS, C XD = ARRAY OF DIMENSION NDP CONTAINING THE C X COORDINATES OF THE DATA POINTS, C YD = ARRAY OF DIMENSION NDP CONTAINING THE C Y COORDINATES OF THE DATA POINTS. C THE OUTPUT PARAMETERS ARE C NT = NUMBER OF TRIANGLES, C IPT = INTEGER ARRAY OF DIMENSION 6*NDP-15, WHERE THE C POINT NUMBERS OF THE VERTEXES OF THE (IT)TH C TRIANGLE ARE TO BE STORED AS THE (3*IT-2)ND, C (3*IT-1)ST, AND (3*IT)TH ELEMENTS, C IT=1,2,...,NT, C NL = NUMBER OF BORDER LINE SEGMENTS, C IPL = INTEGER ARRAY OF DIMENSION 6*NDP, WHERE THE C POINT NUMBERS OF THE END POINTS OF THE (IL)TH C BORDER LINE SEGMENT AND ITS RESPECTIVE TRIANGLE C NUMBER ARE TO BE STORED AS THE (3*IL-2)ND, C (3*IL-1)ST, AND (3*IL)TH ELEMENTS, C IL=1,2,..., NL. C THE OTHER PARAMETERS ARE C IWL = INTEGER ARRAY OF DIMENSION 18*NDP USED C INTERNALLY AS A WORK AREA, C IWP = INTEGER ARRAY OF DIMENSION NDP USED C INTERNALLY AS A WORK AREA, C WK = ARRAY OF DIMENSION NDP USED INTERNALLY AS A C WORK AREA. C C HISTORY THE ORIGINAL VERSION OF BIVAR WAS WRITTEN BY C HIROSHI AKIMA IN AUGUST 1975 AND REWRITTEN BY C HIM IN LATE 1976. IT WAS INCORPORATED INTO C NCAR'S PUBLIC SOFTWARE LIBRARIES IN JANUARY C 1977. IN AUGUST 1984 A NEW VERSION OF BIVAR, C INCORPORATING CHANGES DESCRIBED IN THE ROCKY C MOUNTAIN JOURNAL OF MATHEMATICS ARTICLE CITED C BELOW, WAS OBTAINED FROM DR. AKIMA BY MICHAEL C PERNICE OF NCAR'S SCIENTIFIC COMPUTING C DIVISION, WHO EVALUATED IT AND MADE IT C AVAILABLE IN FEBRUARY, 1985. * * Converted to C on 1/20/93, by Kenny Toh. * This routine was originally written in Fortran. */ int idtang(ndp, xd, yd, nt, ipt0, nl, ipl0) int ndp; /* Number of data points */ double *xd; /* x-coordinates of data points */ double *yd; /* y-coordinates of data points */ int *nt; /* No of triangles created */ int **ipt0; /* Point numbers of vertices */ int *nl; /* Number of border line segmts */ int **ipl0; /* Point numbers of line segmts */ { double *wk; /* double-precision work array */ int *iwp, *iwl; /* integer work array */ int *ipt, *ipl; /* Local arrays */ double xdmp, ydmp; double dsqmn, dsqi; double wts, sp, vp; double x1, y1, x2, y2, x3, y3; int ipmn1, ipmn2, ip1, ip2, ip3, jp1, jp2, ip, jp; int jpmn, jpc, its, FOUND; int nt0, ntt3; int nl0, nlt3; int ixvs, ixvspv, iliv, ilvs, nlsh, nlsht3, jl1, jl2; int jwl, il, ilt3, ipl1, ipl2, it, itt3, nln, nlnt3, ipti, nlf; int ntt3p3, irep, ilf, itt3r, ipt1, ipt2, ipt3, itf[3]; int it1t3, it2t3, ipti1, ipti2, iplj1, iplj2, jlt3, nlfc, ntf; int jwl1mn, nlft2, jwl1; /* error check */ if (ndp < 4) { (void) fprintf(stderr, " ***Error - input parameter ndp out of range\n"); return(0); } /* print message if more than 50 points */ if (ndp >= 50) { (void) fprintf(stdout," Trying to triangulate %d points\n",ndp); (void) fprintf(stdout," Hmmm... This may take some time...\n"); } /* Create the work arrays */ wk = (double *)malloc((unsigned int)(ndp*sizeof(double))); iwp = (int *)malloc((unsigned int)(ndp*sizeof(int ))); ipt = (int *)malloc((unsigned int)((6*ndp-15+1)*sizeof(int ))); ipl = (int *)malloc((unsigned int)((6*ndp +1)*sizeof(int ))); iwl = (int *)malloc((unsigned int)((18*ndp +1)*sizeof(int ))); if (!wk || !iwp || !(ipt) || !(ipl) || !(iwl)) { (void) fprintf(stderr," ***Malloc error!\n"); if (wk ) free((char *)wk); if (iwp) free((char *)iwp); if (ipt) free((char *)ipt); if (ipl) free((char *)ipl); if (iwl) free((char *)iwl); return(0); } /* Find the closest pair of datapoints and their midpoint */ dsqmn = dsqf(xd[0],yd[0],xd[1],yd[1]); ipmn1 = 0; ipmn2 = 1; for (ip1=0; ip1 (fabs(sp)*ESPLN)) { FOUND = 1; jp1 = jp; its = iwp[jp]; wts = wk[jp]; } } if (!FOUND) { (void) fprintf(stderr," ***Error! All collinear data points\n"); if (wk ) free((char *)wk); if (iwp) free((char *)iwp); if (ipt) free((char *)ipt); if (ipl) free((char *)ipl); if (iwl) free((char *)iwl); return(0); } if (jp1 != 2) { /* Shift the registers * its and wts contain the values at index jp1 */ for (jpc=3; jpc<=jp1; jpc++) { jp = jp1 + 3 - jpc; iwp[jp] = iwp[jp-1]; wk [jp] = wk [jp-1]; } iwp[2] = its; wk[2] = wts; } #ifdef DEBUG (void) printf("\nAfter collinear modification:\n"); for (ip=2; ip= 50) { (void) fprintf(stdout," Done! Found %d triangles\n",nt0); } /* Return */ return(1); } /* C THIS FUNCTION DETERMINES WHETHER OR NOT THE EXCHANGE OF TWO C TRIANGLES IS NECESSARY ON THE BASIS OF MAX-MIN-ANGLE CRITERION C BY C. L. LAWSON. C THE INPUT PARAMETERS ARE C X,Y = ARRAYS CONTAINING THE COORDINATES OF THE DATA C POINTS, C I1,I2,I3,I4 = POINT NUMBERS OF FOUR POINTS P1, P2, C P3, AND P4 THAT FORM A QUADRILATERAL WITH P3 C AND P4 CONNECTED DIAGONALLY. C THIS FUNCTION RETURNS AN INTEGER VALUE 1 (ONE) WHEN AN EX- C CHANGE IS NECESSARY, AND 0 (ZERO) OTHERWISE. C DECLARATION STATEMENTS */ static int idxchg(x,y,i1,i2,i3,i4) double *x, *y; /* Coordinate arrays */ int i1,i2,i3,i4; { double x1, y1, x2, y2, x3, y3, x4, y4; double u1, u2, u3, u4; double a1sq, a2sq, a3sq, a4sq; double b1sq, b2sq, b3sq, b4sq; double c1sq, c2sq, c3sq, c4sq; double s1sq, s2sq, s3sq, s4sq; int idx; /* Preliminary processing */ x1 = x[i1]; y1 = y[i1]; x2 = x[i2]; y2 = y[i2]; x3 = x[i3]; y3 = y[i3]; x4 = x[i4]; y4 = y[i4]; /* Calculation */ idx = 0; u3 = (y2-y3)*(x1-x3) - (x2-x3)*(y1-y3); u4 = (y1-y4)*(x2-x4) - (x1-x4)*(y2-y4); if (u3*u4 <= 0.0) return(idx); /* More Calculation */ u1 = (y3-y1)*(x4-x1) - (x3-x1)*(y4-y1); u2 = (y4-y2)*(x3-x2) - (x4-x2)*(y3-y2); a1sq = dsqf(x1,y1,x3,y3); b1sq = dsqf(x1,y1,x4,y4); c1sq = dsqf(x3,y3,x4,y4); a2sq = dsqf(x2,y2,x4,y4); b2sq = dsqf(x2,y2,x3,y3); c2sq = c1sq; a3sq = b2sq; b3sq = a1sq; c3sq = dsqf(x2,y2,x1,y1); a4sq = b1sq; b4sq = a2sq; c4sq = c3sq; s1sq = u1*u1/(c1sq*MAXOF(a1sq,b1sq)); s2sq = u2*u2/(c2sq*MAXOF(a2sq,b2sq)); s3sq = u3*u3/(c3sq*MAXOF(a3sq,b3sq)); s4sq = u4*u4/(c4sq*MAXOF(a4sq,b4sq)); if ((MINOF(s3sq,s4sq)-MINOF(s1sq,s2sq)) > ESPLN) idx = 1; return(idx); }