wzdelaunay.cxx

来自「有限元学习研究用源代码(老外的),供科研人员参考」· CXX 代码 · 共 548 行 · 第 1/2 页

CXX
548
字号
#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "ibg2.hxx"

void wzCellTypeInit(); 

ibgDelaunayMarker::ibgDelaunayMarker()
  :dsl((1+IBG2CSMAX)*sizeof(int))
  ,dsc(dsl.base)
  ,nsl(3*sizeof(int))
  ,nsc(nsl.base)
  ,nsco(nsc,1)
  ,nscs(nsc,2)
{
  for(int i=0;i<IBG2CSMAX;i++){
    dscl[i].reinitialize(dsc,1+i);
  }
}

void wzDelaunayGenerator::Delaunay(wzpoints plist, cogeometry cog)
{
  wzCellTypeInit();
  initializeDelaunayBox(plist->min,plist->max);
  include(plist);
  try{
    defineRegions(cog);
    createFaces(cog);
  }catch(...){;}
}

void wzDelaunayGenerator::Delaunay(wzpoints plist)
{
  wzCellTypeInit();
  initializeDelaunayBox(plist->min,plist->max);
  include(plist);
}

void wzDelaunayGenerator::include(wzpoints plist)
{
  switch(gdim()){
  case 0: Delaunay0(plist); break;
  case 1: Delaunay1(plist); break;
  case 2: Delaunay2(plist); break;
  case 3: Delaunay3(plist); break;
  }
}

#define ibg2pX(point)		((point).X)
#define ibg2pF(point)		((point).X+wzPointDim)
#define ibg2pI(point)		((point).I)
#define ibg2pSegment(point)	((point).S.index())
#define ibg2pType(point)	((point).S.codim())
#define ibg2pSetSegment(point,tt,uu)	((point).S = wzSegment((wzIndex)(uu),(wzDimension)(tt)))

const wzFloat	ibgDelaunayBig  = 10000.0;
const wzFloat	ibgDelaunayEps  = 2.e-6;
static wzFloat	ibgDelaunayEps2;
static wzFloat	ibgDelaunayEps3;

static int hcn3[16] = {1,3,2,5, 1,5,2,4, 1,4,2,6, 1,6,2,3};
static int hcs3[16] = {0,2,0,4, 0,3,0,1, 0,4,0,2, 0,1,0,3};
static int hcn2[ 6] = {1,3,2,  1,2,4};
static int hcs2[ 6] = {0,2,0,  0,0,1};
static int hcn1[ 2] = {1,2};
static int hcs1[ 2] = {0,0};
static int hcnum[4] = {0,1,2,4};
static int* hcn[ 4] = {0,hcn1,hcn2,hcn3};
static int* hcs[ 4] = {0,hcs1,hcs2,hcs3};
static ibg2CellType hctyp[4] = {wzCellType0Node,wzCellType1Line,wzCellType2Triangle,wzCellType3Tetrahedron};

void wzDelaunayGenerator::initializeDelaunayBox(wzFloat* min, wzFloat* max)
{
  int i,j,c,*n,*s,*hn,*hs;
  wzFloat m[wzPointDim],d0,dd;
  ibgSphere cvert;
  for(i=0;i<xdim();i++){
    Grid.mincoord[i+1] = min[i]; 
    Grid.maxcoord[i+1] = max[i];
  }
  if(gdim()==0) return;
  Grid.points.create(2*gdim());
  for(i=1;i<=hcnum[gdim()];i++){
    j = createCell(hctyp[gdim()]);
  }
  d0 = 0;
  for(i=0;i<xdim();i++){
    m[i] = (min[i]+max[i])/2; dd = max[i]-min[i]; if(dd>d0) d0=dd;
  }
  //  ibgDelaunayEps1 = d0*ibgDelaunayEps;
  ibgDelaunayEps2 = d0*ibgDelaunayEps*(max[0]-min[0])*ibgDelaunayEps;
  ibgDelaunayEps3 = 
    (max[0]-min[0])*ibgDelaunayEps*
    (max[1]-min[1])*ibgDelaunayEps*
    (max[2]-min[2])*ibgDelaunayEps;
  d0 *= ibgDelaunayBig;
  for(i=0;i<gdim();i++){
    for(j=0;j<xdim();j++){
      Grid.Point[2*i+1][j] = Grid.Point[2*i+2][j] = cvert.x1[j] = cvert.x2[j] = m[j];
    }
    Grid.Point[2*i+1][i] -= d0;
    Grid.Point[2*i+2][i] += d0;
    cnc(2*i+1) = cnc(2*i+2) = 1;
    cns(2*i+1,wzIsRegion,0);
    cns(2*i+2,wzIsRegion,0);
  }
  cvert.x1[0] -= d0;
  cvert.x2[0] += d0;
  hn = hcn[gdim()]; hs = hcs[gdim()];
  wzRangeLoop(Grid.cells,c){
    ccv(c)=cvert;
    n = ccn(c); s = ccs(c);
    for(i=0;i<wzCellTypepoints[hctyp[gdim()]];i++){*n++ = *hn++;}
    for(i=0;i<wzCellTypesides [hctyp[gdim()]];i++){*s++ = *hs++;}
  }
}

static int LastUsedCell;

int wzDelaunayGenerator::g1find(wzFloat *xx, int c0)
{
  int *cn0;
  if(ccu(c0)<0){
    c0 = 1;
    while (ccu(c0)<0) c0++;
  }
beg:
  wzAssert(ccu(c0)>=0);
  cn0=ccn(c0);
  if(xx[0]<cnx(cn0[0])[0]) {c0=ccs(c0)[0]; goto beg;} 
  if(xx[0]>cnx(cn0[1])[0]) {c0=ccs(c0)[1]; goto beg;} 
  return LastUsedCell = c0;
}

int wzDelaunayGenerator::g2find(wzFloat *xx, int c0)
{
  int nl,*cn0;
  ibg2CellType t;
  int i;
  wzFloat vv,x1,x2,y1,y2;
  wzFloat* ff[IBG2CSMAX];
  register wzFloat *fj;
  if(ccund(c0)) c0 = LastUsedCell;
  if(ccund(c0)){
    wzRangeLoop(Grid.cells,c0){
      if(ccund(c0)) continue;
      break;
    }
  }
beg:
  wzAssert(!ccund(c0));
  wzAssert(ccu(c0)>=0);
  nl=wzCellTypePoints(t=cct(c0)); cn0=ccn(c0);
  for(i=0;i<nl;i++) ff[i]=cnx(cn0[i]);
  for(i=0;i<nl;i++){
    fj = ff[wzCellTypeSPoint1(t,i,0)];
    x1 = fj[0]-xx[0]; y1=fj[1]-xx[1];
    fj = ff[wzCellTypeSPoint1(t,i,1)];
    x2 = fj[0]-xx[0]; y2=fj[1]-xx[1];
    vv = x1 * y2 - x2 * y1;
    if(vv<-ibgDelaunayEps2) {c0=ccs(c0)[i]; goto beg;}
  }
  return LastUsedCell = c0;
}

int wzDelaunayGenerator::g3find(wzFloat *xx, int c0)
{
  register int nl,*cn0;
  int i,sl;
  ibg2CellType t;
  long double vv,x1,x2,x3,y1,y2,y3,z1,z2,z3,xx0=xx[0],xx1=xx[1],xx2=xx[2];
  wzFloat* ff[IBG2CNMAX];
  register wzFloat *fj;
  if(ccund(c0)) c0 = LastUsedCell;
  if(ccund(c0)){
    wzRangeLoop(Grid.cells,c0){
      if(ccund(c0)) continue;
      break;
    }
  }
beg:
  wzAssert(!ccund(c0));
  wzAssert(ccu(c0)>=0);
  nl=wzCellTypePoints(t=cct(c0)); cn0=ccn(c0);
  for(i=0;i<nl;i++) ff[i]=cnx(cn0[i]);
  sl=wzCellTypeSides(t);
  for(i=0;i<sl;i++){
    fj = ff[wzCellTypeSPoint1(t,i,0)];
    x1 = ((long double)fj[0])-xx0;y1=((long double)fj[1])-xx1;z1=((long double)fj[2])-xx2;
    fj = ff[wzCellTypeSPoint1(t,i,1)];
    x2 = ((long double)fj[0])-xx0;y2=((long double)fj[1])-xx1;z2=((long double)fj[2])-xx2;
    fj = ff[wzCellTypeSPoint1(t,i,2)];
    x3 = ((long double)fj[0])-xx0;y3=((long double)fj[1])-xx1;z3=((long double)fj[2])-xx2;
    vv = x1 * (y2*z3-y3*z2) + x2 * (y3*z1-y1*z3) + x3 * (y1*z2-y2*z1);
    if(vv>ibgDelaunayEps3) {c0=ccs(c0)[i]; goto beg;}
  }
  return LastUsedCell = c0;
}

int   wzDelaunayGenerator::Delaunay0(wzpoints list)
{
  int c = createCell(wzCellType0Node);
  int n = Grid.points.append();
  ccn(c)[0]=n; cnc(n) = c;
  wzPoint& p = Grid.Point[ccn(c)[0]];
  p = list->Point[list->first()];
  return wzSuccess;
}

int   wzDelaunayGenerator::Delaunay1(wzpoints list)
{
  int n,n0,c0,c1,cs,no,nb,nshift;
  n0 = nb = Grid.points.append(list->length());
  nshift = nb - list->first(); n0--;
  wzRangeLoop(*list,n){
    n0++;
    Grid.Point[n0]=list->Point[n];
    // Suche nach einer Zelle, die n0 enth"alt: 
    no = list->Near[n] + nshift;
    if(no<nb) no = n0-1;
    c0=g1find(cnx(n0),cnc(no));
    c1 = createCell(wzCellType1Line);
    ccs(c1)[1] = cs = ccs(c0)[1];
    ccs(c0)[1] = ccs(cs)[0] = c1;
    ccs(c1)[0] = c0;  
    ccn(c1)[1] = ccn(c0)[1];
    ccn(c1)[0] = ccn(c0)[1] = n0;
    cnc(n0)    = c1;
    ccu(c1)    = ccu(c0)    = 0;
  }
  return wzSuccess;
}

int   wzDelaunayGenerator::Delaunay2(wzpoints list)
{
  int n,s,s0,sh,ms,i,i0,ih,j,del;
  int n0,no,nb,nt,nshift,nh,c0,c1,cc,ct,ch,co,cl;
  int *cs0,*cs1,*csi,*csj,*csh,*cn0,*cni,*cnj,*cnh,*ss,*se;
  wzFloat *cx1,*cx2;
  wzFloat x,y,x1,x2,y1,y2;
  wzFloat l1,l2,det,mx,my;
  ibg2CellType t,t0,t1,th,tt;
  wzPoint nd;
  ibgSphere v;
  int dsi,ds0,dsh,nsi;
  LastUsedCell=0;
  n0 = nb = Grid.points.append(list->length());
  nshift = nb - list->first(); n0--;
  wzRangeLoop(*list,n){
    n0++;
    Grid.Point[n0]=list->Point[n];
    // Suche nach einer Zelle, die n0 enth"alt: 
    no = list->Near[n] + nshift;
    if(no<nb) no = n0-1;
    c0=g2find(cnx(n0),cnc(no));
    x=cnx(n0)[0]; y=cnx(n0)[1];
    nsl=0; dsl=0; dsi=1; dsc[++dsl]=c0; ccu(c0)= -dsl;
    while(dsi<=dsl){
      c0  = dsc[dsi];
      cs0 = ccs(c0); ms=wzCellTypeSides((t0=cct(c0)));
      cn0 = ccn(c0);
      for(s=0;s<ms;s++){
	cc= cs0[s];
	if(cc<=0) {del=0; goto deltest;}
	if(ccu(cc)<0) {(dscl[s])[dsi]= -1; continue;}
	v = ccv(cc); t = cct(cc);
	if((    (v.x1[0]-x)*(v.x2[0]-x)
		+   (v.x1[1]-y)*(v.x2[1]-y)) < ibgDelaunayEps2)	del=1;
	else							del=0;
      deltest:
	if(del){
	  dsc[++dsl] = cc; ccu(cc) = -dsl;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?