📄 uni2tri.c
字号:
emax,*e,errfrac;
int *used;
char *ifile="";
FILE *efp=NULL,*ifp;
/* min and max x and z coordinates */
xmin = f2;
zmin = f1;
xmax = f2+(n2-1)*d2;
zmax = f1+(n1-1)*d1;
/* read initial model for interfaces */
if (getparstring("ifile",&ifile)) {
ifp = efopen(ifile,"r");
m = readModel(ifp);
efclose(ifp);
/* check that model is compatible with sampled sloth */
if (ABS(xmin-m->ymin)>0.01*d2)
err("xmin!=m->ymin %g!=%g",xmin,m->ymin);
if (ABS(xmax-m->ymax)>0.01*d2)
err("xmax!=m->ymax %g!=%g",xmax,m->ymax);
if (ABS(zmin-m->xmin)>0.01*d1)
err("zmin!=m->xmin %g!=%g",zmin,m->xmin);
if (ABS(zmax-m->xmax)>0.01*d1)
err("zmax!=m->xmax %g!=%g",zmax,m->xmax);
/* if (xmin!=m->ymin) err("xmin!=m->ymin %g!=%g",xmin,m->ymin);
if (xmax!=m->ymax) err("xmax!=m->ymax %g!=%g",xmax,m->ymax);
if (zmin!=m->xmin) err("zmin!=m->xmin %g!=%g",zmin,m->xmin);
if (zmax!=m->xmax) err("zmax!=m->xmax %g!=%g",zmax,m->xmax);
*/
/* reset epsilon */
/* m->eps = 0.01*MIN(d2,d1);
*//* m->eps *= 0.001;
*/
/* loop over faces */
f = m->f;
do {
/* free face attributes */
free1(f->fa); f->fa = NULL;
/* set sloth at each vertex of face */
setSlothOfVertex(f->eu->vu->v,
n2,d2,f2,n1,d1,f1,s);
setSlothOfVertex(f->eu->euCW->vu->v,
n2,d2,f2,n1,d1,f1,s);
setSlothOfVertex(f->eu->euCCW->vu->v,
n2,d2,f2,n1,d1,f1,s);
/* next face */
f = f->fNext;
} while (f!=m->f);
} else {
/* initialize model */
m = makeModel(zmin,xmin,zmax,xmax);
m->sfa = sizeof(FaceAttributes);
m->eps = 0.01*MIN(d2,d1);
v = nearestVertexInModel(m,NULL,zmin,xmin);
va = (VertexAttributes*) ealloc1(1,sizeof(VertexAttributes));
va->s = s[0][0];
v->va = va;
v = nearestVertexInModel(m,NULL,zmax,xmin);
va = (VertexAttributes*) ealloc1(1,sizeof(VertexAttributes));
va->s = s[0][n1-1];
v->va = va;
v = nearestVertexInModel(m,NULL,zmin,xmax);
va = (VertexAttributes*) ealloc1(1,sizeof(VertexAttributes));
va->s = s[n2-1][0];
v->va = va;
v = nearestVertexInModel(m,NULL,zmax,xmax);
va = (VertexAttributes*) ealloc1(1,sizeof(VertexAttributes));
va->s = s[n2-1][n1-1];
v->va = va;
}
/* check model */
/* fprintf(stderr,"Checking model\n");
checkModel(m);
*/
if (verbose==2)
if ((efp=fopen(efile,"w"))==NULL)
err("Could not open efile=%s!\n",efile);
/* label output columns */
if (verbose) {
fprintf(stderr,"iterations faces "
"max errror norm error\n");
fprintf(stderr,"-------- ----- "
"---------- ----------\n");
}
/* allocate space */
nfalloc = 1024;
e = ealloc1float(nfalloc);
ix = ealloc1int(nfalloc);
iz = ealloc1int(nfalloc);
ind2 = ealloc1int(nfalloc);
used = ealloc1int(nfalloc);
/* count iterations */
im = 0; nv = 0;
/* loop until error is small enough */
do {
/* initialize maximum error */
emax = 0.0;
/* loop over faces */
f = m->f; jf = 0;
do {
/* determine maximum error in triangle */
maxErrorInTri(f,n2,d2,f2,n1,d1,f1,s,
&e[jf],&ix[jf],&iz[jf]);
/* save maximum error */
if (e[jf]>=emax) emax = e[jf];
/* next face */
f = f->fNext; ++jf;
} while (f!=m->f);
/* number of faces */
nf = jf;
/* compute and report maximum error */
errfrac = emax/smax;
if (verbose)
fprintf(stderr," %5d %5d % .6g % .6g\n",
im,nf,emax,errfrac);
if (verbose==2) {
fwrite(&errfrac,sizeof(float),1,efp);
if (im%50==0) fflush(efp);
}
/* if requested, write intermediate model */
if ((mm>0) ? im%mm==0 : 0)
writeIntermediateModel(m,im,mfile);
/* sort errors from largest to smallest */
for (jf=0; jf<nf; ++jf) {
ind2[jf] = jf;
used[jf] = 0;
}
qkisort(nf,e,ind2);
for (jf=0,kf=nf-1; jf<nf/2; ++jf,--kf) {
itemp = ind2[jf];
ind2[jf] = ind2[kf];
ind2[kf] = itemp;
}
/* loop over points of maximum error */
for (jf=0,iv=0; jf<nf; ++jf) {
/* if error is too big, add another vertex */
if (e[ind2[jf]]>errmax) {
/* check that this vertex is not too close */
/* to others previously added at this stage */
for (kf=0,skip=0; kf<jf; ++kf) {
/* if (!used[kf]) continue;
*/ dix = ix[ind2[kf]] - ix[ind2[jf]];
diz = iz[ind2[kf]] - iz[ind2[jf]];
if (ABS(dix)<=tol && ABS(diz)<=tol) {
skip = 1;
break;
}
}
if (skip) continue;
/* do not add if vertex is on a fixed edge */
/* z = f1+iz[ind2[jf]]*d1;
x = f2+ix[ind2[jf]]*d2;
ne = nearestEdgeInModel(m,NULL,z,x);
if (distanceToEdge(ne,z,x)<m->eps && ne->fixed)
continue;
*/
/* add vertex */
v = addVertexToModel(m,
f1+iz[ind2[jf]]*d1,
f2+ix[ind2[jf]]*d2);
if (v==NULL) continue;
/* set vertex attributes */
va = (VertexAttributes*)
ealloc1(1,sizeof(VertexAttributes));
va->s = s[ix[ind2[jf]]][iz[ind2[jf]]];
v->va = va;
/* mark vertex as used, increment counter */
used[jf] = 1;
++iv; ++nv;
}
}
/* Make sure at least one vertex has been added. */
/* This should never be a problem. */
if (iv==0 && emax>errmax) err("added 0 vertices!");
/* Just added iv vertices at this stage, */
/* increasing face count by at most 2*iv. */
/* Allocate more space for vertices if necessary */
if (nf+2*iv>nfalloc) {
nfalloc *= 2;
free1float(e); e = ealloc1float(nfalloc);
free1int(ix); ix = ealloc1int(nfalloc);
free1int(iz); iz = ealloc1int(nfalloc);
free1int(ind2); ind2 = ealloc1int(nfalloc);
free1int(used); used = ealloc1int(nfalloc);
}
/* increment iteration counter */
++im;
} while (emax>errmax);
if (verbose==2) fclose(efp);
if (verbose) fprintf(stderr,"added %d vertices\b",nv);
/* final loop over faces */
f = m->f;
do {
/* allocate face attributes */
fa = (FaceAttributes*)ealloc1(1,sizeof(FaceAttributes));
f->fa = fa;
/* make sloth for triangle */
makeSlothForTri(f,&fa->s00,&fa->dsdx,&fa->dsdz);
/* set density and Q for triangle */
fa->dens = FLT_MAX;
fa->qfac = FLT_MAX;
/* next face */
f = f->fNext;
} while (f!=m->f);
#ifdef COMMENT
/* verify that density and Q are set in all faces */
f = m->f;
do {
fa = f->fa;
fprintf(stderr,"fa->dens=%.25g fa->qfac=%.25g\n",
fa->dens,fa->qfac);
if (fa->dens!=FLT_MAX)
err("density not set in face!\n");
if (fa->qfac!=FLT_MAX)
err("Q not set in face!\n");
f = f->fNext;
} while (f!=m->f);
#endif
/* return model */
return m;
}
/* make sloth function for triangle */
static void makeSlothForTri (Tri *t, float *s00, float *dsdx, float *dsdz)
/*
* Author: Dave Hale
* Modified: Craig Artley
* Fixed bug when computing s00 for non1ero m->xmin and m->ymin
*/
{
VertexAttributes *va;
float x1,z1,x2,z2,x3,z3,s1,s2,s3,
x2mx1,z2mz1,s2ms1,x3mx1,z3mz1,s3ms1,
a,b,det;
x1 = t->eu->vu->v->y;
z1 = t->eu->vu->v->x;
va = t->eu->vu->v->va;
s1 = va->s;
x2 = t->eu->euCW->vu->v->y;
z2 = t->eu->euCW->vu->v->x;
va = t->eu->euCW->vu->v->va;
s2 = va->s;
x3 = t->eu->euCCW->vu->v->y;
z3 = t->eu->euCCW->vu->v->x;
va = t->eu->euCCW->vu->v->va;
s3 = va->s;
x2mx1 = x2-x1; z2mz1 = z2-z1; s2ms1 = s2-s1;
x3mx1 = x3-x1; z3mz1 = z3-z1; s3ms1 = s3-s1;
det = z3mz1*x2mx1-z2mz1*x3mx1;
a = z3mz1*s2ms1-z2mz1*s3ms1;
b = s3ms1*x2mx1-s2ms1*x3mx1;
*dsdx = a/det;
*dsdz = b/det;
*s00 = s2-(*dsdx)*x2-(*dsdz)*z2;
}
#define SWAPVERTEX(I,J) { \
float temp=x##I; x##I=x##J; x##J=temp; \
temp=z##I; z##I=z##J; z##J=temp; \
}
/* determine sample with maximum error in triangle */
static void maxErrorInTri (Tri *t,
int n2, float d2, float f2, int n1, float d1, float f1, float **s,
float *emax, int *ixmax, int *izmax)
/*
* Author: Dave Hale
* Modified: Craig Artley
* Fixed bugs arising when handling triangles with vertical edges.
*/
{
int ixlo=n1,ixhi=n2,izlo,izhi,ix,iz; /* dummy usage */
float s00,dsdx,dsdz,x1,z1,x2,z2,x3,z3,slope21,slope31,slope32,
zlo,zhi,d1lo,d1hi,x,z,e;
/* sloth function for tri */
makeSlothForTri(t,&s00,&dsdx,&dsdz);
/* vertices */
x1 = t->eu->vu->v->y;
z1 = t->eu->vu->v->x;
x2 = t->eu->euCW->vu->v->y;
z2 = t->eu->euCW->vu->v->x;
x3 = t->eu->euCCW->vu->v->y;
z3 = t->eu->euCCW->vu->v->x;
/* sort vertices by increasing x */
if (x1>x2) SWAPVERTEX(1,2);
if (x1>x3) SWAPVERTEX(1,3);
if (x2>x3) SWAPVERTEX(2,3);
/* slopes of edges */
slope21 = (z2-z1)/(x2!=x1?x2-x1:1e-10*d2);
slope31 = (z3-z1)/(x3!=x1?x3-x1:1e-10*d2);
slope32 = (z3-z2)/(x3!=x2?x3-x2:1e-10*d2);
/* x limits and initial x */
ixlo = (x1-f2)/d2;
ixhi = (x3-f2)/d2;
if (f2+ixlo*d2<x1) ixlo++;
/* initial z limits */
zlo = z1+(f2+ixlo*d2-x1)*MIN(slope21,slope31);
zhi = z1+(f2+ixlo*d2-x1)*MAX(slope21,slope31);
d1lo = d2*MIN(slope21,slope31);
d1hi = d2*MAX(slope21,slope31);
/* adjust z limits if the 1-2 edge is vertical */
if (x1==x2 && z1<z2) {
zhi = z2+(f2+ixlo*d2-x2)*slope32;
d1hi = d2*slope32;
}
if (x1==x2 && z1>z2) {
zlo = z2+(f2+ixlo*d2-x2)*slope32;
d1lo = d2*slope32;
}
/* initial error */
*emax = 0.0;
/* loop over sampled x coordinates */
for (ix=ixlo; ix<=ixhi; ++ix) {
/* sampled x coordinate */
x = f2+ix*d2;
/* if right of vertex 2, update z limits */
if (x>x2) {
if (slope21<slope31) {
zlo = z2+(x-x2)*slope32;
d1lo = d2*slope32;
} else {
zhi = z2+(x-x2)*slope32;
d1hi = d2*slope32;
}
}
/* z sample limits */
izlo = (zlo-f1)/d1;
if (f1+izlo*d1<zlo) izlo++;
izhi = (zhi-f1)/d1;
/* loop over samples within limits */
for (iz=izlo; iz<=izhi; ++iz) {
/* sampled z coordinate */
z = f1+iz*d1;
/* update error */
e = s00+x*dsdx+z*dsdz-s[ix][iz];
e = ABS(e);
if (e>=*emax) {
*emax = e;
*ixmax = ix;
*izmax = iz;
}
}
/* increment z limits */
zlo += d1lo;
zhi += d1hi;
}
}
static void writeIntermediateModel (Model *m, int im, char *mfile)
/*
* Author: Craig Artley
*/
{
Face *f;
FaceAttributes *fa;
FILE *mfp;
static char *mexfile=NULL;
/* loop over faces */
f = m->f;
do {
/* make sloth for triangle */
fa = (FaceAttributes*)ealloc1(1,sizeof(FaceAttributes));
f->fa = fa;
makeSlothForTri(f,&fa->s00,&fa->dsdx,&fa->dsdz);
/* next face */
f = f->fNext;
} while (f!=m->f);
/* allocate space for filename plus model number extension, */
/* allowing space for null terminator and possible overflow */
if (mexfile==NULL)
mexfile = ealloc1(strlen(mfile)+10,sizeof(char));
sprintf(mexfile,"%s%.4d",mfile,im);
/* open file, write model, close file */
mfp = efopen(mexfile,"w");
writeModel(m,mfp);
efclose(mfp);
/* loop over faces */
f = m->f;
do {
/* free face atributes */
free1(f->fa); f->fa = NULL;
/* next face */
f = f->fNext;
} while (f!=m->f);
}
static void setSlothOfVertex (Vertex *v,
int n2, float d2, float f2, int n1, float d1, float f1, float **s)
/*
* Author: Craig Artley
*/
{
int ix,iz;
float x,z,xi,zi,fracx,fracz;
VertexAttributes *va;
/* find grid coordinates closest to vertex */
x = v->y; z = v->x;
xi = (x-f2)/d2; zi = (z-f1)/d1;
ix = xi; iz = zi;
fracx = xi-ix; fracz = zi-iz;
/* adjust coordinates at edges of grid */
if (ix<0) {
ix = 0;
fracx = 0.0;
}
if (ix>n2-2) {
ix = n2-2;
fracx = 1.0;
}
if (iz<0) {
iz = 0;
fracz = 0.0;
}
if (iz>n1-2) {
iz = n1-2;
fracz = 1.0;
}
/* allocate space for vertex attributes if necessary */
if (v->va==NULL)
v->va = va = (VertexAttributes*)
ealloc1(1,sizeof(VertexAttributes));
else
va = v->va;
/* compute sloth via bilinear interpolation */
va->s = (1.0-fracx)*((1.0-fracz)*s[ix][iz]+fracz*s[ix][iz+1])
+fracx*((1.0-fracz)*s[ix+1][iz]+fracz*s[ix+1][iz+1]);
}
static void fillsloth (Model *m, int nr, float **sr)
/* fill regions bounded by fixed edges with sloths */
{
int ir;
float x,z,x0,z0,s00,dsdx,dsdz;
Tri *t;
/* loop over regions for which sloth function is specified */
for (ir=0; ir<nr; ++ir) {
/* determine parameters of sloth function */
x = sr[ir][0]; z = sr[ir][1];
x0 = sr[ir][2]; z0 = sr[ir][3];
s00 = sr[ir][4]; dsdx = sr[ir][5]; dsdz = sr[ir][6];
/* adjust v0 for x0 and z0 */
s00 -= x0*dsdx+z0*dsdz;
/* determine triangle containing point (x,z) */
t = insideTriInModel(m,NULL,z,x);
/* flood triangles in region */
setsloth(t,s00,dsdx,dsdz);
}
}
static void setsloth (Tri *t, float s00, float dsdx, float dsdz)
/* recursively set sloth functions in triangles */
{
EdgeUse *eu;
FaceAttributes *fa;
/* if sloth already set, then return */
if ((fa=t->fa)!=NULL)
if (fa->s00==s00 && fa->dsdx==dsdx && fa->dsdz==dsdz)
return;
/* if necessary, allocate space for attributes */
if (fa==NULL)
t->fa = fa = (FaceAttributes*)
ealloc1(1,sizeof(FaceAttributes));
/* set attributes */
fa->s00 = s00;
fa->dsdx = dsdx;
fa->dsdz = dsdz;
/* for each edge not fixed, set attributes in opposite triangle */
eu = t->eu;
do {
if (!eu->e->fixed) setsloth(eu->euMate->f,s00,dsdx,dsdz);
eu = eu->euCW;
} while (eu!=t->eu);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -