openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
filament.cc
Go to the documentation of this file.
1 /*
2  * Filament detection routines
3  */
4 
5 #include "FMatrix.h"
6 #include "filament.h"
7 
8 #ifdef I
9 #undef I
10 #endif
11 
12 // this table is the mass matrix for the 1st subtriangle of the quadrilateral
13 // the rest of the mass matrices are just permutations
14 static const int TriFaces[1][3] = {
15  { 0, 1, 2 }
16 };
17 
18 static const int TetFaces[4][3] = {
19  { 0, 1, 2 },
20  { 0, 1, 3 },
21  { 1, 2, 3 },
22  { 0, 2, 3 }
23 };
24 
25 
26 #define FIL_PTS_FILE 0
27 #define FIL_ELEM_FILE 1
28 #define FIL_DATA_FILE 2
29 
30 const int MAX_ELEM_NODES = 8;
31 const int MAX_ELEM_FACES = 6;
32 
33 // prototypes
34 bool output_filaments(filament *f, FILE *fh[]);
35 
36 bool fl_chkIso(float *d, float th, Elem *e);
37 bool fl_IsoTagFaces (float *d,float th, Elem *e, bool *faceTags );
38 bool fl_IsoTagTetFaces(float *d,float th, bool *faceTags);
39 bool fl_IsoTagTriFaces(float *d,float th, bool *faceTags);
40 bool fl_IsoTagTriangle(float *d, float th, const int idx[]);
41 bool fl_findIsoIntersect(float *d0, float *d1, float th, Point *p, Elem *e );
42 int fl_FindFilament(float *d0, float *d1, float th, Point *lp, Elem *e, singularity *sng);
43 bool fl_triFindPS(float *d0, float *d1, float th, Point *p, Point *PS,int meth);
44 bool fl_triFindPS_Lines(float *d0, float *d1, float th, Point *p, Point *PS);
45 bool fl_triFindPS_ShpFnc(float *d0,float *d1,float th,Point *p,Point *PS);
46 bool fl_findEdgeSection(float d_p0, float d_p1, float th, Point *p0, Point *p1, Point *pSec);
47 void interpoate_vm(int numNodes,float **d,int M,float **rd,float rDist);
48 void interpolateTBuffer(tbuffer *tbf);
49 float fl_triArea( Point *pts );
50 
51 // test point in triangle
52 bool SameSideOfLine (Point pTest, Point p0, Point p1, Point p2);
53 bool PointInTriangle(Point pTest, Point p0, Point p1, Point p2);
54 bool PointInTriangleBarycentric(Point pTest, Point p0, Point p1, Point p2);
55 bool PointInTriangleBarycentric(Point pTest, Point p0, Point p1, Point p2, Point &bcc);
56 bool PtInTriangleBarycentricSP(Point pTest, Point p1, Point p2);
57 bool PtInTriangleBarycentricSP(Point pTest, Point p1, Point p2, Point &bcc);
58 
59 
68 Point
69 UnTransformPoint( Point PTs, Point *opts, Point *spts)
70 {
71  Real whole = fabs(spts[1].x*spts[2].y/2.);
72  Point a[3] = { PTs, spts[1], spts[2] };
73  Real c0 = fl_triArea( a )/whole;
74  Real c2 = fabs(spts[1].x*PTs.y/2.)/whole;
75  if( c0+c2 > 1.02 ){
76  fprintf( stderr, "transformation back failed\n" );
77  }
78  return opts[0]*c0 + opts[2]*c2 + opts[1]*(1-c0-c2);
79 }
80 
81 
91 inline float
93 {
94  return 0.5*mag(cross(pts[1] - pts[0],pts[2] - pts[0]));
95 }
96 
107 Point
108 fl_triNormalLocal( Point *pts, bool u )
109 {
110  Point n=cross(pts[1] - pts[0],pts[2] - pts[0]);
111  return u?normalize(n):n;
112 }
113 
114 
123 void
125 {
126  int numNodes = tbf->nodes;
127  float **d = (float **)(tbf->d );
128  float **rd = (float **)(tbf->dr);
129  int M = tbf->wdth;
130  float rdist = tbf->rdist;
131 
132  interpolate_vm(numNodes,d,M,rd,rdist);
133 }
134 
135 
146 void
147 interpolate_vm(int numNodes,float **d,int M,float **rd,float rdist)
148 {
149  for(int j=0;j<numNodes;j++) {
150  rd[0][j] = d[0 ][j]+rdist*(d[1 ][j]-d[0 ][j]);
151  rd[1][j] = d[M-2][j]+rdist*(d[M-1][j]-d[M-2][j]);
152  }
153 }
154 
155 
170 bool
171 compute_filament(float *d0, float *d1, float vth, ElemList *elst,
172  NodeList *nlst, filament *f, SingularityDetector_t meth)
173 {
174  int PScnt = 0;
175 
176 #pragma omp parallel for
177  for(int i=0;i<elst->NElems; i++) {
178 
179  float d0_elem[MAX_ELEM_NODES];
180  float d1_elem[MAX_ELEM_NODES];
181 
182  Elem &e = elst->Ele[i];
183 
184  if((e.type!=Tri) && (e.type!=Tetra))
185  log_msg(NULL,2,0, "%s: Type in Element %d not supported yet.\n",
186  __func__, i );
187 
188  // copy data at element nodes to local array
189  for(int j=0;j<e.Nnode;j++) {
190  d0_elem[j] = d0[e.N[j]];
191  d1_elem[j] = d1[e.N[j]];
192  }
193 
194  // quick check, are there any isolines/surfaces on the element
195  bool iso0 = fl_chkIso(d0_elem,vth,&e);
196  bool iso1 = fl_chkIso(d1_elem,vth,&e);
197 
198  // if so, analyse in detail
199  if( iso0 && iso1 ) {
200 
201  // possibly a filament, at least we have two isosurfaces/isolines
202  // is this actually a filament?
203  bool ftags0[MAX_ELEM_FACES] = {false};
204  bool ftags1[MAX_ELEM_FACES] = {false};
205 
206  // all faces with with isolines tagged
207  bool tags0 = fl_IsoTagFaces(d0_elem, vth, &e, ftags0 );
208  bool tags1 = fl_IsoTagFaces(d1_elem, vth, &e, ftags1 );
209 
210  Point lp[MAX_ELEM_NODES];
211  for( int j=0; j<e.Nnode; j++ )
212  lp[j] = nlst->Node[e.N[j]];
213 
214  if(tags0 && tags1) {
215 
216  if((e.type==Tri) && (meth==vol_based)) {
217  lp[3] = lp[0] + fl_triNormalLocal(lp,false);
218  d0_elem[3] = d0_elem[0];
219  d1_elem[3] = d1_elem[0];
220  }
221 
222  singularity sng;
223  int FilamentType = fl_FindFilament(d0_elem,d1_elem,vth,lp,&e,&sng);
224 
225  if(FilamentType) {
226 #pragma omp critical
227  f->add_singularity(&sng,i);
228 #pragma omp atomic
229  PScnt++;
230  }
231 
232  //bool isFilament = fl_findIsoIntersect(d0_elem,d1_elem,vth,lp,e);
233  //if(isFilament)
234  // add_singularity2filament(f, elst->ElemGlobInds[i] );
235 
236  }
237  }
238  }
239  f->sort();
240  return PScnt>0;
241 }
242 
243 void
245 {
246  s.push_back(*sng);
247  numPts += sng->ps.type;
248  s.back().ps.eIndx = eIndx;
249 }
250 
251 
252 void
254 {
255  std::sort(s.begin(), s.end(),
256  [] (const singularity& lhs, const singularity& rhs)-> bool{return lhs.ps.eIndx<rhs.ps.eIndx;});
257 }
258 
259 
269 int
270 init_filament_IO(const char *meshname, int numT, FILE *fh[])
271 {
272  int ok = -1;
273 
274  char pname[512], ename[512], dname[512];
275 
276  snprintf(pname, sizeof pname, "%s.pts_t", meshname);
277  snprintf(ename, sizeof ename, "%s.elem_t", meshname);
278  snprintf(dname, sizeof dname, "%s.dat_t", meshname);
279 
280  static int init = 0;
281  if(!init) {
282 
283  FILE *fhp = fopen(pname,"wt"); fh[0] = fhp;
284  FILE *fhe = fopen(ename,"wt"); fh[1] = fhe;
285  FILE *fhd = fopen(dname,"wt"); fh[2] = fhd;
286 
287  if( (fhp==NULL) || (fhe==NULL) || (fhd==NULL) )
288  return ok;
289  else
290  ok = 0;
291 
292  // write comment lines
293  fprintf(fhp,"## Format x y z # singularity type (1=PS || 2=FilSeg) Global element index \n");
294  fprintf(fhp,"%d\n", numT);
295  fprintf(fhe,"## Format Ln p0 p1 || PS p0 \n");
296  fprintf(fhe,"%d\n", numT);
297  fprintf(fhd,"## Format data (matching with pts_t file) \n");
298  fprintf(fhd,"%d\n", numT);
299 
300  init = 1;
301  }
302 
303  return ok;
304 }
305 
306 
307 // temporary debug code
308 int
309 write_connections(ElemList *elst, NodeList *nlst, filament *f, FILE *filHdls[],
310  float t)
311 {
312  static int init = 0;
313 
314  if(!f->num_segs()) return 0;
315 
316  char fname[512];
317  char pname[512], ename[512], dname[512];
318 
319  snprintf(fname, sizeof fname, "filament_%.2f.cnnx", t);
320  FILE *fh = fopen(fname,"wt");
321  fprintf( fh,"%d\n", f->num_segs());
322  int i = 0;
323 
324  for( int i=0; i<f->num_segs(); i++ ) {
325  // pick the first edge of an element
326  Elem &e = elst->Ele[f->s[i].ps.eIndx];
327  //fl_getElem(elst,f->s[i].ps.eIndx,&e);
328  int vtx0 = e.N[0];
329  int vtx1 = e.N[1];
330 
331  fprintf( fh,"%d %d\n", vtx0, vtx1 );
332  }
333  fclose(fh);
334 
335  return f->num_segs();
336 }
337 
338 
347 void
348 write_filaments(filament *f,FILE *filHdls[],float t)
349 {
350  int msg1 = 20;
351  int msg2 = 30;
352  int N = f->num_segs();
353  int numPts = f->num_pts();
354 
355  for(int i=0; i<=FIL_DATA_FILE;i++)
356  fprintf(filHdls[i],"#%.6f\n",t);
357 
358  // preliminary, this needs to be fixed
359  fprintf(filHdls[FIL_PTS_FILE ],"%d\n",numPts);
360  //fprintf(filHdls[FIL_ELEM_FILE],"%d\n",N);
361  fprintf(filHdls[FIL_DATA_FILE],"%d\n",numPts);
362 
363  fprintf(stderr, "%d filament segments found\n",N);
364  if( output_filaments(f,filHdls) ){
365  fprintf(stderr, "Point mismatch at time %.0f\n", t );
366  exit(1);
367  }
368 }
369 
370 
379 bool
380 output_filaments(filament *f, FILE *filHdls[])
381 {
382  int nele=0;
383  for( int i=0; i<f->num_segs(); i++ )
384  if( f->s[i].ps.type != PhaseSingularity ) nele++;
385  fprintf(filHdls[FIL_ELEM_FILE],"%d\n",nele);
386 
387  int ptCnt = 0;
388  for( int i=0; i<f->num_segs(); i++ ){
389  FILE *fhp = filHdls[0], *fhe = filHdls[1], *fhd = filHdls[2];
390 
391  FilSeg fs = f->s[i].fs;
392  fprintf(fhp,"%.3f %.3f %.3f # %d %d\n", fs.p0.x,fs.p0.y,fs.p0.z,
393  fs.type, fs.eIndx);
394  // for now we use the enclosing element index as data
395  // later we use a PS or filament ID
396  fprintf(fhd,"%d\n",fs.eIndx);
397 
398  if(f->s[i].ps.type==PhaseSingularity) {
399  //fprintf(fhe,"PS %d \n", ptCnt++);
400  ptCnt++;
401  }
402  else {
403  // filament segment
404  fprintf(fhp,"%.3f %.3f %.3f # %d %d\n", fs.p1.x,fs.p1.y,fs.p1.z,
405  fs.type, fs.eIndx);
406  fprintf(fhd,"%d\n",fs.eIndx);
407  fprintf(fhe,"Ln %d %d\n", ptCnt, ptCnt+1);
408  ptCnt += 2;
409  }
410  }
411  return ptCnt != f->num_pts();
412 }
413 
414 
419 void
420 close_filament_IO(FILE *fh[])
421 {
422  for(int i=0;i<3;i++)
423  fclose(fh[i]);
424 }
425 
434 bool
435 fl_chkIso(float *d, float th, Elem *e)
436 {
437  if(d[0]>=th) {
438  for(int i=1;i<e->Nnode;i++)
439  if(d[i]<th) {
440  return true;
441  }
442  } else {
443  for(int i=1;i<e->Nnode;i++)
444  if(d[i]>=th) {
445  return true;
446  }
447  }
448  return false;
449 }
450 
451 
461 bool
462 fl_IsoTagFaces(float *d, float th, Elem *e, bool *faceTags )
463 {
464  bool flg = false;
465  switch(e->type) {
466  case Tri:
467  flg = fl_IsoTagTriFaces(d,th,faceTags);
468  break;
469  case Tetra:
470  flg = fl_IsoTagTetFaces(d,th,faceTags);
471  break;
472  default:
473  fprintf(stderr,"%s: Element type not implemented yet.\n", __func__);
474  }
475  return flg;
476 }
477 
478 
488 bool
489 fl_IsoTagTetFaces(float *d,float th, bool *faceTags)
490 {
491  int tagged = 0;
492  for(int i=0;i<4;i++)
493  if((faceTags[i]=fl_IsoTagTriangle(d,th,TetFaces[i])))
494  tagged++;
495 
496  return tagged;
497 }
498 
499 
509 bool
510 fl_IsoTagTriFaces(float *d,float th, bool *faceTags)
511 {
512  return faceTags[0]=fl_IsoTagTriangle(d,th,TriFaces[0]);
513 }
514 
515 
523 bool
524 fl_IsoTagTriangle(float *d, float th, const int idx[])
525 {
526  bool tag = false;
527 
528  if(d[idx[0]]>=th) {
529  if((d[idx[1]]<th) || (d[idx[2]]<th)) tag = true;
530  }
531  else
532  if((d[idx[1]]>=th) || (d[idx[2]]>=th)) tag = true;
533  return tag;
534 }
535 
536 
548 int
549 fl_FindFilament(float *d0,float *d1,float th,Point *lp,Elem *e,singularity *sng)
550 {
551  float d0_[3], d1_[3];
552  Point lp_[3];
553  int FilamentType = 0;
554  Point PhaseS[4];
555  int tagged[] = { 0, 0, 0, 0};
556  int tagIdx[] = {-1,-1,-1,-1};
557 
558  int meth = 1;
559  switch(e->type) {
560  case Tri:
561  if(fl_triFindPS(d0,d1,th,lp,PhaseS,meth)) {
562  int i = 0;
563  tagged[i]++;
564  tagIdx[FilamentType++] = i;
565  }
566  break;
567  case Tetra:
568  for(int i=0;i<4;i++) {
569  for(int j=0;j<3;j++) {
570  d0_[j] = d0[TetFaces[i][j]];
571  d1_[j] = d1[TetFaces[i][j]];
572  lp_[j] = lp[TetFaces[i][j]];
573  }
574  if(fl_triFindPS(d0_,d1_,th,lp_,PhaseS+i,meth)) {
575  tagged[i]++;
576  tagIdx[FilamentType++] = i;
577  if( FilamentType == 2 ) break;
578  }
579  }
580  break;
581  default:
582  fprintf(stderr,"Element type not supported by %s.\n", __func__ );
583  }
584 
585  if(FilamentType) {
586  sng->ps.type = FilamentType;
587  sng->ps.eIndx = 0;
588  sng->ps.p0 = PhaseS[tagIdx[0]];
589  if(FilamentType==2) // Filament segment
590  sng->fs.p1 = PhaseS[tagIdx[1]];
591  }
592 
593  return FilamentType;
594 }
595 
596 
608 bool
609 fl_triFindPS(float *d0, float *d1, float th, Point *lp, Point *PhaseS,
610  int meth)
611 {
612  bool found = false;
613  switch(meth) {
614  case 0:
615  found = fl_triFindPS_ShpFnc(d0,d1,th,lp,PhaseS);
616  break;
617  case 1:
618  default:
619  found = fl_triFindPS_Lines(d0,d1,th,lp,PhaseS);
620  }
621  return found;
622 }
623 
624 
635 bool
636 fl_triFindPS_ShpFnc(float *d0, float *d1, float th, Point *lp, Point *PhaseS)
637 {
638  fprintf(stderr, "Shape function method not implemented yet.\n");
639  return false;
640 }
641 
653 bool
654 fl_triFindPS_Lines(float *d0, float *d1, float th, Point *lp, Point *PhaseS)
655 {
656  bool isPS = false;
657  Point pt[3];
658 
659  // transform matrix into standard position first
660  //static FMatrix fwd = ZERO_FMATRIX, bwd = ZERO_FMATRIX, A = ZERO_FMATRIX;
661 
662  FMatrix A(2,2);
663 
664  /*
665  fl_getTransform3Dto2D(lp,&fwd,&bwd,&t);
666  int numPts = 3;
667  Point t;
668  fl_AffineTransformPoints(lp,pt,numPts,&fwd,&t,true);
669  */
670 
671  // transform to standard position
672  pt[0].set(0,0,0);
673  Point p01 = lp[1] - lp[0];
674  pt[1].set(mag(p01), 0., 0.);
675  Point p02 = lp[2] - lp[0];
676  double ptx = dot(p02,p01)/pt[1].x;
677  pt[2].set(ptx, sqrt(mag2(p02)-ptx*ptx),0.);
678 
679  int tEdg0[] = {0,0,0};
680  int tEdg1[] = {0,0,0};
681  Point tSec0[3], tSec1[3];
682 
683  // do our thingie
684  tEdg0[0] = fl_findEdgeSection(d0[0],d0[1],th,pt+0,pt+1,tSec0+0);
685  tEdg0[1] = fl_findEdgeSection(d0[1],d0[2],th,pt+1,pt+2,tSec0+1);
686  tEdg0[2] = fl_findEdgeSection(d0[0],d0[2],th,pt+0,pt+2,tSec0+2);
687 
688  tEdg1[0] = fl_findEdgeSection(d1[0],d1[1],th,pt+0,pt+1,tSec1+0);
689  tEdg1[1] = fl_findEdgeSection(d1[1],d1[2],th,pt+1,pt+2,tSec1+1);
690  tEdg1[2] = fl_findEdgeSection(d1[0],d1[2],th,pt+0,pt+2,tSec1+2);
691 
692  // singularity found?
693  int t0 = 0;
694  int t1 = 0;
695  int t0s[2], t1s[2];
696  int c0 = 0;
697  int c1 = 0;
698  for(int i=0;i<3;i++) {
699  t0 += tEdg0[i];
700  t1 += tEdg1[i];
701  if(tEdg0[i]) t0s[c0++] = i;
702  if(tEdg1[i]) t1s[c1++] = i;
703  }
704  if((t0==2) && (t1==2)) {
705  // equation in parametrized form
706  // a0, b0: intersection points of isoline 0 with tri
707  // a1, b1: intersection points of isoline 1 with tri
708  //
709  // There are two lines:
710  // l0 = a0 + lambda*(b0-a0) (1)
711  // l1 = a1 + gamma *(b1-a1) (2)
712  //
713  // The intersection is found by solving for l0=l1.
714  // this yields:
715  //
716  // (b0-a0)*lambda - (b1-a1)*gamma = (a1-a0)
717  //
718  // which gives a solution for lambda and gamma.
719  // Either (1) or (2) can be used to find the intersection coordinates
720 
721  Point &a0 = tSec0[t0s[0]];
722  Point &b0 = tSec0[t0s[1]];
723  Point &a1 = tSec1[t1s[0]];
724  Point &b1 = tSec1[t1s[1]];
725 
726  Point b0ma0 = b0 - a0;
727  Point b1ma1 = a1 - b1;
728  Point a1ma0 = a1 - a0;
729 
730  Real b[2];
731  A.Ent[0][0] = b0ma0.x; A.Ent[0][1] = b1ma1.x;
732  A.Ent[1][0] = b0ma0.y; A.Ent[1][1] = b1ma1.y;
733  b[0] = a1ma0.x; b[1] = a1ma0.y;
734 
735  // find params lambda and gamma
736  A.LUD();
737  if(A.decomposed) {
738  // A is not singular
739  A.LUsolve( b );
740 
741  // find intersection
742  Point PSt = a0 + scal_X(b0ma0,b[0]);
743 
744  // check whether PS is within triangle
745  Point bcc;
746 
747  if(PtInTriangleBarycentricSP(PSt,pt[1],pt[2],bcc)) {
748  //fprintf(stderr, "PS transformed found at x = %.2f, y = %.2f.\n", PSt.x, PSt.y );
749 
750  // transform back
751  // fl_AffineTransformPoints(&PSt,PhaseS,1,&bwd,&t,false);
752  // PhaseS[0] = UnTransformPoint(PSt, lp, pt);
753 
754  PhaseS[0] = lp[0]*bcc.x + lp[1]*bcc.y + lp[2]*bcc.z;
755 
756  // fprintf(stderr, "PS real found at x = %.2f, y = %.2f.\n", PhaseS->x, PhaseS->y );
757  isPS = true;
758 
759  bool debug = false;
760  if(debug) {
761  // check back transform - debug only!
762  Point ptb[3];
763  //fl_AffineTransformPoints(pt,ptb,3,&bwd,&t,false);
764  for( int j=0; j<3; j++ )
765  ptb[j] = dot(bcc,pt[j]);
766  }
767  }
768  }
769  }
770  return isPS;
771 }
772 
773 
786 bool
788 {
789  Point cp1 = cross(p1 - p0,pTest - p0);
790  Point cp2 = cross(p1 - p0,p2 - p0);
791  return dot(cp1,cp2)>=0;
792 }
793 
794 
805 bool
807 {
808  if(SameSideOfLine(pTest,p0,p1,p2) &&
809  SameSideOfLine(pTest,p1,p2,p0) &&
810  SameSideOfLine(pTest,p2,p0,p1) )
811  return true;
812  else
813  return false;
814 }
815 
817 bool
819 {
820  Point null;
821  return PtInTriangleBarycentricSP(pTest, p1, p2, null);
822 }
823 
836 bool
838 {
839  // Compute dot products
840  double dot00 = v0.x*v0.x+v0.y*v0.y;
841  double dot01 = v0.x*v1.x;
842  double dot02 = v0.x*v2.x+v0.y*v2.y;
843  double dot11 = v1.x*v1.x;
844  double dot12 = v1.x*v2.x;
845 
846  // Compute barycentric coordinates
847  double invDenom = 1/(dot00*dot11-dot01*dot01);
848  bcc.z = (dot11*dot02-dot01*dot12)*invDenom;
849  if( bcc.z < 0 ) return false;
850  bcc.y = (dot00*dot12-dot01*dot02)*invDenom;
851  bcc.x = 1. - bcc.z - bcc.y;
852 
853  // Check if point is in triangle
854  return (bcc.x>=0) && (bcc.y>=0);
855 }
856 
857 
858 bool
860 {
861  Point null;
862  return PointInTriangleBarycentric(pTest, p0, p1, p2, null);
863 }
864 
876 bool
878 {
879  // Compute vectors
880  Point v0 = p2 - p0;
881  Point v1 = p1 - p0;
882  Point v2 = pTest - p0;
883 
884  // Compute dot products
885  double dot00 = dot(v0,v0);
886  double dot01 = dot(v0,v1);
887  double dot02 = dot(v0,v2);
888  double dot11 = dot(v1,v1);
889  double dot12 = dot(v1,v2);
890 
891  // Compute barycentric coordinates
892  double invDenom = 1/(dot00*dot11-dot01*dot01);
893  bcc.z = (dot11*dot02-dot01*dot12)*invDenom;
894  bcc.y = (dot00*dot12-dot01*dot02)*invDenom;
895  bcc.x = 1. - bcc.z - bcc.y;
896 
897  // Check if point is in triangle
898  return (bcc.x>=0) && (bcc.y>=0) && (bcc.z>=0);
899 }
900 
901 
913 bool
914 fl_findEdgeSection(float d_p0, float d_p1, float th, Point *p0, Point *p1, Point *pSec)
915 {
916  bool hasIso = false;
917 
918  if(d_p0>=th) {
919  if (d_p1<th)
920  hasIso = true;
921  }
922  else {
923  if (d_p1>=th)
924  hasIso = true;
925  }
926 
927  if(hasIso) {
928  Point l = *p1 - *p0;
929  float len = mag(l);
930  float sec = (d_p0-th)/(d_p0-d_p1);
931  *pSec = *p0 + scal_X(l,sec);
932  }
933 
934  return hasIso;
935 }
936 
937 
947 bool
948 fl_findIsoIntersect(float *d0, float *d1, float th, Point *p, Elem *e )
949 {
950  bool isFilament = false;
951 
952  FMatrix M(4,4);
953  FMatrix Id(3,3);
954 
955  for (int i=0;i<4;i++) {
956  M.Ent[i][0] = 1.;
957  M.Ent[i][1] = p[i].x;
958  M.Ent[i][2] = p[i].y;
959  M.Ent[i][3] = p[i].z;
960  }
961 
962  double v0[4], v1[4], vf[4];
963  for(int i=0;i<4;i++) v0[i] = d0[i];
964  for(int i=0;i<4;i++) v1[i] = d1[i];
965 // for(int i=0;i<4;i++) vf[i] = phiIsoFace[i];
966 
967  M.LUD();
968 
969  // find base coefficients V(x,y,z) = a + bx +cy + dz
970  M.LUsolve( v0 );
971  M.LUsolve( v1 );
972 
973  // now we try to intesect the two hyperplanes with isosurface planes
974  // spanned by the faces of the tet, i.e. we assume a face is an isosurface hyperplane
975  int intersect = 0, NFaces = 4;
976  for(int i=0;i<NFaces;i++) {
977  // assign threshold values to nodes which span isosurface
978  for(int j=0;j<4;j++) vf[j] = th+1;
979  for(int j=0;j<3;j++) vf[TetFaces[i][j]] = th;
980 
981  // get base coeffs for this hyperplane
982  M.LUsolve( vf );
983 
984  // fill in rhs which is vth-a
985  double r[3];
986  r[0] = th - v0[0];
987  r[1] = th - v1[0];
988  r[2] = th - vf[0];
989 
990  for(int j=0;j<3;j++) {
991  Id.Ent[0][j] = v0[j+1];
992  Id.Ent[1][j] = v1[j+1];
993  Id.Ent[2][j] = vf[j+1];
994  }
995 
996  Id.LUD( );
997  if(Id.decomposed) {
998  Id.LUsolve( r );
999 
1000  // this is primitive and not exactly correct,
1001  // a proper test of whether the intersection is within the tet or not
1002  // should go here instead
1003  float xmn,xmx,ymn,ymx,zmn,zmx;
1004  xmn = xmx = p[0].x;
1005  ymn = ymx = p[0].y;
1006  zmn = zmx = p[0].z;
1007 
1008  for(int j=1;j<4;j++) {
1009  if(p[j].x<xmn) xmn = p[j].x;
1010  if(p[j].x>xmx) xmx = p[j].x;
1011  if(p[j].y<ymn) ymn = p[j].y;
1012  if(p[j].y>ymx) ymx = p[j].y;
1013  if(p[j].z<zmn) zmn = p[j].z;
1014  if(p[j].z>zmx) zmx = p[j].z;
1015  }
1016 
1017  if((r[0]>=xmn) && (r[0]<=xmx) &&
1018  (r[1]>=ymn) && (r[1]<=ymx) &&
1019  (r[2]>=zmn) && (r[2]<=zmx) ) {
1020  intersect++;
1021  log_msg(NULL,0,0, "Intersection found at [x,y,z]=[%.2f,%.2f,%.2f]",
1022  r[0],r[1],r[2]);
1023  }
1024  }
1025 
1026  }
1027  if( ((e->type==Tri) && (intersect==1)) ||
1028  ((e->type==Tetra) && (intersect==2)) )
1029  isFilament = true;
1030 
1031  return isFilament;
1032 }
1033 
double Real
Definition: DataTypes.h:13
void dot(data_t *x, data_t *y, int n, int nc, FILE *out, bool pt)
perform dot product
Definition: IGBops.cc:550
void normalize(IGBheader *h, FILE *out, T *min, T *max)
normalize pixels over all time
Definition: IGBops.cc:637
bool decomposed
true if decomposed
Definition: FMatrix.h:28
Real ** Ent
matrix entries
Definition: FMatrix.h:27
void LUD()
Definition: FMatrix.cc:320
void LUsolve(Real *)
Definition: FMatrix.cc:355
int numPts
Definition: filament.h:43
int num_segs()
Definition: filament.h:41
int num_pts()
Definition: filament.h:42
void sort()
Definition: filament.cc:253
void add_singularity(singularity *s, int)
Definition: filament.cc:244
std::vector< singularity > s
Definition: filament.h:44
#define FIL_ELEM_FILE
Definition: filament.cc:27
float fl_triArea(Point *pts)
Definition: filament.cc:92
int init_filament_IO(const char *meshname, int numT, FILE *fh[])
Definition: filament.cc:270
void interpolate_vm(int numNodes, float **d, int M, float **rd, float rdist)
Definition: filament.cc:147
Point UnTransformPoint(Point PTs, Point *opts, Point *spts)
Definition: filament.cc:69
bool fl_chkIso(float *d, float th, Elem *e)
Definition: filament.cc:435
int write_connections(ElemList *elst, NodeList *nlst, filament *f, FILE *filHdls[], float t)
Definition: filament.cc:309
int fl_FindFilament(float *d0, float *d1, float th, Point *lp, Elem *e, singularity *sng)
Definition: filament.cc:549
bool PtInTriangleBarycentricSP(Point pTest, Point p1, Point p2)
Definition: filament.cc:818
void interpolateTBuffer(tbuffer *tbf)
Definition: filament.cc:124
#define FIL_DATA_FILE
Definition: filament.cc:28
bool SameSideOfLine(Point pTest, Point p0, Point p1, Point p2)
Definition: filament.cc:787
void interpoate_vm(int numNodes, float **d, int M, float **rd, float rDist)
bool fl_IsoTagFaces(float *d, float th, Elem *e, bool *faceTags)
Definition: filament.cc:462
bool fl_triFindPS_ShpFnc(float *d0, float *d1, float th, Point *p, Point *PS)
Definition: filament.cc:636
void write_filaments(filament *f, FILE *filHdls[], float t)
Definition: filament.cc:348
bool fl_findIsoIntersect(float *d0, float *d1, float th, Point *p, Elem *e)
Definition: filament.cc:948
const int MAX_ELEM_NODES
Definition: filament.cc:30
bool fl_IsoTagTriangle(float *d, float th, const int idx[])
Definition: filament.cc:524
void close_filament_IO(FILE *fh[])
Definition: filament.cc:420
bool PointInTriangle(Point pTest, Point p0, Point p1, Point p2)
Definition: filament.cc:806
const int MAX_ELEM_FACES
Definition: filament.cc:31
bool fl_findEdgeSection(float d_p0, float d_p1, float th, Point *p0, Point *p1, Point *pSec)
Definition: filament.cc:914
bool PointInTriangleBarycentric(Point pTest, Point p0, Point p1, Point p2)
Definition: filament.cc:859
bool compute_filament(float *d0, float *d1, float vth, ElemList *elst, NodeList *nlst, filament *f, SingularityDetector_t meth)
Definition: filament.cc:171
#define FIL_PTS_FILE
Definition: filament.cc:26
bool fl_triFindPS_Lines(float *d0, float *d1, float th, Point *p, Point *PS)
Definition: filament.cc:654
bool fl_IsoTagTetFaces(float *d, float th, bool *faceTags)
Definition: filament.cc:489
bool output_filaments(filament *f, FILE *fh[])
Definition: filament.cc:380
Point fl_triNormalLocal(Point *pts, bool u)
Definition: filament.cc:108
bool fl_IsoTagTriFaces(float *d, float th, bool *faceTags)
Definition: filament.cc:510
bool fl_triFindPS(float *d0, float *d1, float th, Point *p, Point *PS, int meth)
Definition: filament.cc:609
SingularityDetector_t
Definition: filament.h:14
@ vol_based
Definition: filament.h:14
#define log_msg(F, L, O,...)
Definition: filament.h:8
@ PhaseSingularity
Definition: filament.h:15
@ Tri
Definition: filament.h:16
@ Tetra
Definition: filament.h:16
double mag(const Point &vect)
vector magnitude
Definition: SF_container.h:111
Point cross(const Point &a, const Point &b)
cross product
Definition: SF_container.h:84
vec3< V > scal_X(const vec3< V > &a, S k)
Definition: vect.h:150
vec3< POINT_REAL > Point
Definition: vect.h:93
V mag2(const vec3< V > &vect)
Definition: vect.h:138
Integer NElems
number of elements (owned+ghost in case of LOCAL_ELEM)
Definition: filament.h:60
Elem * Ele
Definition: filament.h:61
Definition: filament.h:53
Elem_t type
Definition: filament.h:54
int Nnode
Definition: filament.h:55
int * N
Definition: filament.h:56
Point * Node
list of nodes*
Definition: filament.h:49
Point p1
Definition: filament.h:28
Point p0
Definition: filament.h:27
int eIndx
Definition: filament.h:26
int type
Definition: filament.h:25
Definition: filament.h:18
int type
Definition: filament.h:19
Point p0
Definition: filament.h:21
int eIndx
Definition: filament.h:20
time slice buffer for post processing
Definition: filament.h:66
float ** dr
resampled data buffer
Definition: filament.h:76
int wdth
width of buffer, always 2*h_wdth+1
Definition: filament.h:74
float ** d
data buffer
Definition: filament.h:69
float rdist
rel dist of sample to center
Definition: filament.h:78
int nodes
number of nodes in time slice
Definition: filament.h:72
FilSeg fs
Definition: filament.h:33