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 void 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 (0=PS || 1=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  output_filaments(f,filHdls);
365 }
366 
367 
374 void
375 output_filaments(filament *f, FILE *filHdls[])
376 {
377  int nele=0;
378  for( int i=0; i<f->num_segs(); i++ )
379  if( f->s[i].ps.type != PhaseSingularity ) nele++;
380  fprintf(filHdls[FIL_ELEM_FILE],"%d\n",nele);
381 
382  int ptCnt = 0;
383  for( int i=0; i<f->num_segs(); i++ ){
384  FILE *fhp = filHdls[0], *fhe = filHdls[1], *fhd = filHdls[2];
385 
386  FilSeg fs = f->s[i].fs;
387  fprintf(fhp,"%.3f %.3f %.3f # %d %d\n", fs.p0.x,fs.p0.y,fs.p0.z,
388  fs.type, fs.eIndx);
389  // for now we use the enclosing element index as data
390  // later we use a PS or filament ID
391  fprintf(fhd,"%d\n",fs.eIndx);
392 
393  if(f->s[i].ps.type==PhaseSingularity) {
394  //fprintf(fhe,"PS %d \n", ptCnt++);
395  ptCnt++;
396  }
397  else {
398  // filament segment
399  fprintf(fhp,"%.3f %.3f %.3f # %d %d\n", fs.p1.x,fs.p1.y,fs.p1.z,
400  fs.type, fs.eIndx);
401  fprintf(fhd,"%d\n",fs.eIndx);
402  fprintf(fhe,"Ln %d %d\n", ptCnt, ptCnt+1);
403  ptCnt += 2;
404  }
405  }
406 }
407 
408 
413 void
414 close_filament_IO(FILE *fh[])
415 {
416  for(int i=0;i<3;i++)
417  fclose(fh[i]);
418 }
419 
428 bool
429 fl_chkIso(float *d, float th, Elem *e)
430 {
431  if(d[0]>=th) {
432  for(int i=1;i<e->Nnode;i++)
433  if(d[i]<th) {
434  return true;
435  }
436  } else {
437  for(int i=1;i<e->Nnode;i++)
438  if(d[i]>=th) {
439  return true;
440  }
441  }
442  return false;
443 }
444 
445 
455 bool
456 fl_IsoTagFaces(float *d, float th, Elem *e, bool *faceTags )
457 {
458  bool flg = false;
459  switch(e->type) {
460  case Tri:
461  flg = fl_IsoTagTriFaces(d,th,faceTags);
462  break;
463  case Tetra:
464  flg = fl_IsoTagTetFaces(d,th,faceTags);
465  break;
466  default:
467  fprintf(stderr,"%s: Element type not implemented yet.\n", __func__);
468  }
469  return flg;
470 }
471 
472 
482 bool
483 fl_IsoTagTetFaces(float *d,float th, bool *faceTags)
484 {
485  int tagged = 0;
486  for(int i=0;i<4;i++)
487  if((faceTags[i]=fl_IsoTagTriangle(d,th,TetFaces[i])))
488  tagged++;
489 
490  return tagged;
491 }
492 
493 
503 bool
504 fl_IsoTagTriFaces(float *d,float th, bool *faceTags)
505 {
506  int tagged = 0;
507  for(int i=0;i<3;i++)
508  if((faceTags[i]=fl_IsoTagTriangle(d,th,TriFaces[i])))
509  tagged++;
510 
511  return tagged;
512 }
513 
514 
522 bool
523 fl_IsoTagTriangle(float *d, float th, const int idx[])
524 {
525  bool tag = false;
526 
527  if(d[idx[0]]>=th) {
528  if((d[idx[1]]<th) || (d[idx[2]]<th)) tag = true;
529  }
530  else
531  if((d[idx[1]]>=th) || (d[idx[2]]>=th)) tag = true;
532  return tag;
533 }
534 
535 
547 int
548 fl_FindFilament(float *d0,float *d1,float th,Point *lp,Elem *e,singularity *sng)
549 {
550  float d0_[3], d1_[3];
551  Point lp_[3];
552  int FilamentType = 0;
553  Point PhaseS[4];
554  int tagged[] = { 0, 0, 0, 0};
555  int tagIdx[] = {-1,-1,-1,-1};
556 
557  int meth = 1;
558  switch(e->type) {
559  case Tri:
560  if(fl_triFindPS(d0,d1,th,lp,PhaseS,meth)) {
561  int i = 0;
562  tagged[i]++;
563  tagIdx[FilamentType++] = i;
564  }
565  break;
566  case Tetra:
567  for(int i=0;i<4;i++) {
568  for(int j=0;j<3;j++) {
569  d0_[j] = d0[TetFaces[i][j]];
570  d1_[j] = d1[TetFaces[i][j]];
571  lp_[j] = lp[TetFaces[i][j]];
572  }
573  if(fl_triFindPS(d0_,d1_,th,lp_,PhaseS+i,meth)) {
574  tagged[i]++;
575  tagIdx[FilamentType++] = i;
576  }
577  }
578  break;
579  default:
580  fprintf(stderr,"Element type not supported by %s.\n", __func__ );
581  }
582 
583  if(FilamentType) {
584  sng->ps.type = FilamentType;
585  sng->ps.eIndx = 0;
586  sng->ps.p0 = PhaseS[tagIdx[0]];
587  if(FilamentType==2) // Filament segment
588  sng->fs.p1 = PhaseS[tagIdx[1]];
589  }
590 
591  return FilamentType;
592 }
593 
594 
606 bool
607 fl_triFindPS(float *d0, float *d1, float th, Point *lp, Point *PhaseS,
608  int meth)
609 {
610  bool found = false;
611  switch(meth) {
612  case 0:
613  found = fl_triFindPS_ShpFnc(d0,d1,th,lp,PhaseS);
614  break;
615  case 1:
616  default:
617  found = fl_triFindPS_Lines(d0,d1,th,lp,PhaseS);
618  }
619  return found;
620 }
621 
622 
633 bool
634 fl_triFindPS_ShpFnc(float *d0, float *d1, float th, Point *lp, Point *PhaseS)
635 {
636  fprintf(stderr, "Shape function method not implemented yet.\n");
637  return false;
638 }
639 
651 bool
652 fl_triFindPS_Lines(float *d0, float *d1, float th, Point *lp, Point *PhaseS)
653 {
654  bool isPS = false;
655  Point pt[3];
656 
657  // transform matrix into standard position first
658  //static FMatrix fwd = ZERO_FMATRIX, bwd = ZERO_FMATRIX, A = ZERO_FMATRIX;
659 
660  FMatrix A(2,2);
661 
662  /*
663  fl_getTransform3Dto2D(lp,&fwd,&bwd,&t);
664  int numPts = 3;
665  Point t;
666  fl_AffineTransformPoints(lp,pt,numPts,&fwd,&t,true);
667  */
668 
669  // transform to standard position
670  pt[0].set(0,0,0);
671  Point p01 = lp[1] - lp[0];
672  pt[1].set(mag(p01), 0., 0.);
673  Point p02 = lp[2] - lp[0];
674  double ptx = dot(p02,p01)/pt[1].x;
675  pt[2].set(ptx, sqrt(mag2(p02)-ptx*ptx),0.);
676 
677  int tEdg0[] = {0,0,0};
678  int tEdg1[] = {0,0,0};
679  Point tSec0[3], tSec1[3];
680 
681  // do our thingie
682  tEdg0[0] = fl_findEdgeSection(d0[0],d0[1],th,pt+0,pt+1,tSec0+0);
683  tEdg0[1] = fl_findEdgeSection(d0[1],d0[2],th,pt+1,pt+2,tSec0+1);
684  tEdg0[2] = fl_findEdgeSection(d0[0],d0[2],th,pt+0,pt+2,tSec0+2);
685 
686  tEdg1[0] = fl_findEdgeSection(d1[0],d1[1],th,pt+0,pt+1,tSec1+0);
687  tEdg1[1] = fl_findEdgeSection(d1[1],d1[2],th,pt+1,pt+2,tSec1+1);
688  tEdg1[2] = fl_findEdgeSection(d1[0],d1[2],th,pt+0,pt+2,tSec1+2);
689 
690  // singularity found?
691  int t0 = 0;
692  int t1 = 0;
693  int t0s[2], t1s[2];
694  int c0 = 0;
695  int c1 = 0;
696  for(int i=0;i<3;i++) {
697  t0 += tEdg0[i];
698  t1 += tEdg1[i];
699  if(tEdg0[i]) t0s[c0++] = i;
700  if(tEdg1[i]) t1s[c1++] = i;
701  }
702  if((t0==2) && (t1==2)) {
703  // equation in parametrized form
704  // a0, b0: intersection points of isoline 0 with tri
705  // a1, b1: intersection points of isoline 1 with tri
706  //
707  // There are two lines:
708  // l0 = a0 + lambda*(b0-a0) (1)
709  // l1 = a1 + gamma *(b1-a1) (2)
710  //
711  // The intersection is found by solving for l0=l1.
712  // this yields:
713  //
714  // (b0-a0)*lambda - (b1-a1)*gamma = (a1-a0)
715  //
716  // which gives a solution for lambda and gamma.
717  // Either (1) or (2) can be used to find the intersection coordinates
718 
719  Point &a0 = tSec0[t0s[0]];
720  Point &b0 = tSec0[t0s[1]];
721  Point &a1 = tSec1[t1s[0]];
722  Point &b1 = tSec1[t1s[1]];
723 
724  Point b0ma0 = b0 - a0;
725  Point b1ma1 = a1 - b1;
726  Point a1ma0 = a1 - a0;
727 
728  Real b[2];
729  A.Ent[0][0] = b0ma0.x; A.Ent[0][1] = b1ma1.x;
730  A.Ent[1][0] = b0ma0.y; A.Ent[1][1] = b1ma1.y;
731  b[0] = a1ma0.x; b[1] = a1ma0.y;
732 
733  // find params lambda and gamma
734  A.LUD();
735  if(A.decomposed) {
736  // A is not singular
737  A.LUsolve( b );
738 
739  // find intersection
740  Point PSt = a0 + scal_X(b0ma0,b[0]);
741 
742  // check whether PS is within triangle
743  Point bcc;
744 
745  if(PtInTriangleBarycentricSP(PSt,pt[1],pt[2],bcc)) {
746  //fprintf(stderr, "PS transformed found at x = %.2f, y = %.2f.\n", PSt.x, PSt.y );
747 
748  // transform back
749  // fl_AffineTransformPoints(&PSt,PhaseS,1,&bwd,&t,false);
750  // PhaseS[0] = UnTransformPoint(PSt, lp, pt);
751 
752  PhaseS[0] = lp[0]*bcc.x + lp[1]*bcc.y + lp[2]*bcc.z;
753 
754  // fprintf(stderr, "PS real found at x = %.2f, y = %.2f.\n", PhaseS->x, PhaseS->y );
755  isPS = true;
756 
757  bool debug = false;
758  if(debug) {
759  // check back transform - debug only!
760  Point ptb[3];
761  //fl_AffineTransformPoints(pt,ptb,3,&bwd,&t,false);
762  for( int j=0; j<3; j++ )
763  ptb[j] = dot(bcc,pt[j]);
764  }
765  }
766  }
767  }
768  return isPS;
769 }
770 
771 
784 bool
786 {
787  Point cp1 = cross(p1 - p0,pTest - p0);
788  Point cp2 = cross(p1 - p0,p2 - p0);
789  return dot(cp1,cp2)>=0;
790 }
791 
792 
803 bool
805 {
806  if(SameSideOfLine(pTest,p0,p1,p2) &&
807  SameSideOfLine(pTest,p1,p2,p0) &&
808  SameSideOfLine(pTest,p2,p0,p1) )
809  return true;
810  else
811  return false;
812 }
813 
815 bool
817 {
818  Point null;
819  return PtInTriangleBarycentricSP(pTest, p1, p2, null);
820 }
821 
834 bool
836 {
837  // Compute dot products
838  double dot00 = v0.x*v0.x+v0.y*v0.y;
839  double dot01 = v0.x*v1.x;
840  double dot02 = v0.x*v2.x+v0.y*v2.y;
841  double dot11 = v1.x*v1.x;
842  double dot12 = v1.x*v2.x;
843 
844  // Compute barycentric coordinates
845  double invDenom = 1/(dot00*dot11-dot01*dot01);
846  bcc.z = (dot11*dot02-dot01*dot12)*invDenom;
847  if( bcc.z < 0 ) return false;
848  bcc.y = (dot00*dot12-dot01*dot02)*invDenom;
849  bcc.x = 1. - bcc.z - bcc.y;
850 
851  // Check if point is in triangle
852  return (bcc.x>=0) && (bcc.y>=0);
853 }
854 
855 
856 bool
858 {
859  Point null;
860  return PointInTriangleBarycentric(pTest, p0, p1, p2, null);
861 }
862 
874 bool
876 {
877  // Compute vectors
878  Point v0 = p2 - p0;
879  Point v1 = p1 - p0;
880  Point v2 = pTest - p0;
881 
882  // Compute dot products
883  double dot00 = dot(v0,v0);
884  double dot01 = dot(v0,v1);
885  double dot02 = dot(v0,v2);
886  double dot11 = dot(v1,v1);
887  double dot12 = dot(v1,v2);
888 
889  // Compute barycentric coordinates
890  double invDenom = 1/(dot00*dot11-dot01*dot01);
891  bcc.z = (dot11*dot02-dot01*dot12)*invDenom;
892  bcc.y = (dot00*dot12-dot01*dot02)*invDenom;
893  bcc.x = 1. - bcc.z - bcc.y;
894 
895  // Check if point is in triangle
896  return (bcc.x>=0) && (bcc.y>=0) && (bcc.z>=0);
897 }
898 
899 
911 bool
912 fl_findEdgeSection(float d_p0, float d_p1, float th, Point *p0, Point *p1, Point *pSec)
913 {
914  bool hasIso = false;
915 
916  if(d_p0>=th) {
917  if (d_p1<th)
918  hasIso = true;
919  }
920  else {
921  if (d_p1>=th)
922  hasIso = true;
923  }
924 
925  if(hasIso) {
926  Point l = *p1 - *p0;
927  float len = mag(l);
928  float sec = (d_p0-th)/(d_p0-d_p1);
929  *pSec = *p0 + scal_X(l,sec);
930  }
931 
932  return hasIso;
933 }
934 
935 
945 bool
946 fl_findIsoIntersect(float *d0, float *d1, float th, Point *p, Elem *e )
947 {
948  bool isFilament = false;
949 
950  FMatrix M(4,4);
951  FMatrix Id(3,3);
952 
953  for (int i=0;i<4;i++) {
954  M.Ent[i][0] = 1.;
955  M.Ent[i][1] = p[i].x;
956  M.Ent[i][2] = p[i].y;
957  M.Ent[i][3] = p[i].z;
958  }
959 
960  double v0[4], v1[4], vf[4];
961  for(int i=0;i<4;i++) v0[i] = d0[i];
962  for(int i=0;i<4;i++) v1[i] = d1[i];
963 // for(int i=0;i<4;i++) vf[i] = phiIsoFace[i];
964 
965  M.LUD();
966 
967  // find base coefficients V(x,y,z) = a + bx +cy + dz
968  M.LUsolve( v0 );
969  M.LUsolve( v1 );
970 
971  // now we try to intesect the two hyperplanes with isosurface planes
972  // spanned by the faces of the tet, i.e. we assume a face is an isosurface hyperplane
973  int intersect = 0, NFaces = 4;
974  for(int i=0;i<NFaces;i++) {
975  // assign threshold values to nodes which span isosurface
976  for(int j=0;j<4;j++) vf[j] = th+1;
977  for(int j=0;j<3;j++) vf[TetFaces[i][j]] = th;
978 
979  // get base coeffs for this hyperplane
980  M.LUsolve( vf );
981 
982  // fill in rhs which is vth-a
983  double r[3];
984  r[0] = th - v0[0];
985  r[1] = th - v1[0];
986  r[2] = th - vf[0];
987 
988  for(int j=0;j<3;j++) {
989  Id.Ent[0][j] = v0[j+1];
990  Id.Ent[1][j] = v1[j+1];
991  Id.Ent[2][j] = vf[j+1];
992  }
993 
994  Id.LUD( );
995  if(Id.decomposed) {
996  Id.LUsolve( r );
997 
998  // this is primitive and not exactly correct,
999  // a proper test of whether the intersection is within the tet or not
1000  // should go here instead
1001  float xmn,xmx,ymn,ymx,zmn,zmx;
1002  xmn = xmx = p[0].x;
1003  ymn = ymx = p[0].y;
1004  zmn = zmx = p[0].z;
1005 
1006  for(int j=1;j<4;j++) {
1007  if(p[j].x<xmn) xmn = p[j].x;
1008  if(p[j].x>xmx) xmx = p[j].x;
1009  if(p[j].y<ymn) ymn = p[j].y;
1010  if(p[j].y>ymx) ymx = p[j].y;
1011  if(p[j].z<zmn) zmn = p[j].z;
1012  if(p[j].z>zmx) zmx = p[j].z;
1013  }
1014 
1015  if((r[0]>=xmn) && (r[0]<=xmx) &&
1016  (r[1]>=ymn) && (r[1]<=ymx) &&
1017  (r[2]>=zmn) && (r[2]<=zmx) ) {
1018  intersect++;
1019  log_msg(NULL,0,0, "Intersection found at [x,y,z]=[%.2f,%.2f,%.2f]",
1020  r[0],r[1],r[2]);
1021  }
1022  }
1023 
1024  }
1025  if( ((e->type==Tri) && (intersect==1)) ||
1026  ((e->type==Tetra) && (intersect==2)) )
1027  isFilament = true;
1028 
1029  return isFilament;
1030 }
1031 
double Real
Definition: DataTypes.h:14
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:429
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:548
bool PtInTriangleBarycentricSP(Point pTest, Point p1, Point p2)
Definition: filament.cc:816
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:785
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:456
bool fl_triFindPS_ShpFnc(float *d0, float *d1, float th, Point *p, Point *PS)
Definition: filament.cc:634
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:946
const int MAX_ELEM_NODES
Definition: filament.cc:30
bool fl_IsoTagTriangle(float *d, float th, const int idx[])
Definition: filament.cc:523
void close_filament_IO(FILE *fh[])
Definition: filament.cc:414
bool PointInTriangle(Point pTest, Point p0, Point p1, Point p2)
Definition: filament.cc:804
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:912
void output_filaments(filament *f, FILE *fh[])
Definition: filament.cc:375
bool PointInTriangleBarycentric(Point pTest, Point p0, Point p1, Point p2)
Definition: filament.cc:857
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:652
bool fl_IsoTagTetFaces(float *d, float th, bool *faceTags)
Definition: filament.cc:483
Point fl_triNormalLocal(Point *pts, bool u)
Definition: filament.cc:108
bool fl_IsoTagTriFaces(float *d, float th, bool *faceTags)
Definition: filament.cc:504
bool fl_triFindPS(float *d0, float *d1, float th, Point *p, Point *PS, int meth)
Definition: filament.cc:607
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