Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/netgen/libsrc/meshing/delaunay.cpp
3206 views
1
#include <mystdlib.h>
2
#include "meshing.hpp"
3
4
5
6
namespace netgen
7
{
8
9
10
static const int deltetfaces[][3] =
11
{ { 1, 2, 3 },
12
{ 2, 0, 3 },
13
{ 0, 1, 3 },
14
{ 1, 0, 2 } };
15
16
17
18
19
20
21
class DelaunayTet
22
{
23
PointIndex pnums[4];
24
int nb[4];
25
26
public:
27
DelaunayTet () { ; }
28
29
DelaunayTet (const DelaunayTet & el)
30
{
31
for (int i = 0; i < 4; i++)
32
pnums[i] = el[i];
33
}
34
35
DelaunayTet (const Element & el)
36
{
37
for (int i = 0; i < 4; i++)
38
pnums[i] = el[i];
39
}
40
41
PointIndex & operator[] (int i) { return pnums[i]; }
42
PointIndex operator[] (int i) const { return pnums[i]; }
43
44
int & NB1(int i) { return nb[i-1]; }
45
int NB1(int i) const { return nb[i-1]; }
46
47
int & NB(int i) { return nb[i]; }
48
int NB(int i) const { return nb[i]; }
49
50
51
int FaceNr (INDEX_3 & face) const // which face nr is it ?
52
{
53
for (int i = 0; i < 3; i++)
54
if (pnums[i] != face.I1() &&
55
pnums[i] != face.I2() &&
56
pnums[i] != face.I3())
57
return i;
58
return 3;
59
}
60
61
void GetFace1 (int i, INDEX_3 & face) const
62
{
63
face.I(1) = pnums[deltetfaces[i-1][0]];
64
face.I(2) = pnums[deltetfaces[i-1][1]];
65
face.I(3) = pnums[deltetfaces[i-1][2]];
66
}
67
68
void GetFace (int i, INDEX_3 & face) const
69
{
70
face.I(1) = pnums[deltetfaces[i][0]];
71
face.I(2) = pnums[deltetfaces[i][1]];
72
face.I(3) = pnums[deltetfaces[i][2]];
73
}
74
75
INDEX_3 GetFace1 (int i) const
76
{
77
return INDEX_3 (pnums[deltetfaces[i-1][0]],
78
pnums[deltetfaces[i-1][1]],
79
pnums[deltetfaces[i-1][2]]);
80
}
81
82
INDEX_3 GetFace (int i) const
83
{
84
return INDEX_3 (pnums[deltetfaces[i][0]],
85
pnums[deltetfaces[i][1]],
86
pnums[deltetfaces[i][2]]);
87
}
88
89
void GetFace1 (int i, Element2d & face) const
90
{
91
// face.SetType(TRIG);
92
face[0] = pnums[deltetfaces[i-1][0]];
93
face[1] = pnums[deltetfaces[i-1][1]];
94
face[2] = pnums[deltetfaces[i-1][2]];
95
}
96
};
97
98
99
100
101
102
103
104
105
106
/*
107
Table to maintain neighbour elements
108
*/
109
class MeshNB
110
{
111
// face nodes -> one element
112
INDEX_3_CLOSED_HASHTABLE<int> faces;
113
114
//
115
ARRAY<DelaunayTet> & tets;
116
117
public:
118
119
// estimated number of points
120
MeshNB (ARRAY<DelaunayTet> & atets, int np)
121
: faces(200), tets(atets)
122
{ ; }
123
124
// add element with 4 nodes
125
void Add (int elnr);
126
127
// delete element with 4 nodes
128
void Delete (int elnr)
129
{
130
DelaunayTet & el = tets.Elem(elnr);
131
for (int i = 0; i < 4; i++)
132
faces.Set (el.GetFace(i).Sort(), el.NB(i));
133
}
134
135
// get neighbour of element elnr in direction fnr
136
int GetNB (int elnr, int fnr)
137
{
138
return tets.Get(elnr).NB1(fnr);
139
}
140
141
//
142
void ResetFaceHT (int size)
143
{
144
faces.SetSize (size);
145
}
146
};
147
148
149
150
void MeshNB :: Add (int elnr)
151
{
152
DelaunayTet & el = tets.Elem(elnr);
153
154
for (int i = 0; i < 4; i++)
155
{
156
INDEX_3 i3 = INDEX_3::Sort (el.GetFace(i));
157
158
int posnr;
159
160
if (!faces.PositionCreate (i3, posnr))
161
{
162
// face already in use
163
int othertet = faces.GetData (posnr);
164
165
el.NB(i) = othertet;
166
if (othertet)
167
{
168
int fnr = tets.Get(othertet).FaceNr (i3);
169
tets.Elem(othertet).NB(fnr) = elnr;
170
}
171
}
172
else
173
{
174
faces.SetData (posnr, elnr);
175
el.NB(i) = 0;
176
}
177
}
178
}
179
180
181
182
183
184
185
/*
186
connected lists of cosphereical elements
187
*/
188
class SphereList
189
{
190
ARRAY<int> links;
191
public:
192
SphereList ()
193
{ ; }
194
195
void AddElement (int elnr)
196
{
197
if (elnr > links.Size())
198
links.Append (1);
199
links.Elem(elnr) = elnr;
200
}
201
202
void DeleteElement (int elnr)
203
{
204
links.Elem(elnr) = 0;
205
}
206
207
void ConnectElement (int eli, int toi)
208
{
209
links.Elem (eli) = links.Get (toi);
210
links.Elem (toi) = eli;
211
}
212
213
void GetList (int eli, ARRAY<int> & linked) const;
214
};
215
216
217
void SphereList :: GetList (int eli, ARRAY<int> & linked) const
218
{
219
linked.SetSize (0);
220
int pi = eli;
221
222
do
223
{
224
if (pi <= 0 || pi > links.Size())
225
{
226
cerr << "link, error " << endl;
227
cerr << "pi = " << pi << " linked.s = " << linked.Size() << endl;
228
exit(1);
229
}
230
if (linked.Size() > links.Size())
231
{
232
cerr << "links have loop" << endl;
233
exit(1);
234
}
235
236
linked.Append (pi);
237
pi = links.Get(pi);
238
}
239
while (pi != eli);
240
}
241
242
243
244
245
246
void AddDelaunayPoint (PointIndex newpi, const Point3d & newp,
247
ARRAY<DelaunayTet> & tempels,
248
Mesh & mesh,
249
Box3dTree & tettree,
250
MeshNB & meshnb,
251
ARRAY<Point<3> > & centers, ARRAY<double> & radi2,
252
ARRAY<int> & connected, ARRAY<int> & treesearch,
253
ARRAY<int> & freelist, SphereList & list,
254
IndexSet & insphere, IndexSet & closesphere)
255
{
256
/*
257
find any sphere, such that newp is contained in
258
*/
259
260
DelaunayTet el;
261
int cfelind = -1;
262
263
const Point<3> * pp[4];
264
Point<3> pc;
265
double r2;
266
Point3d tpmin, tpmax;
267
268
tettree.GetIntersecting (newp, newp, treesearch);
269
270
double quot,minquot(1e20);
271
272
for (int j = 0; j < treesearch.Size(); j++)
273
{
274
int jjj = treesearch[j];
275
quot = Dist2 (centers.Get(jjj), newp) / radi2.Get(jjj);
276
277
if((cfelind == -1 || quot < 0.99*minquot) && quot < 1)
278
{
279
minquot = quot;
280
el = tempels.Get(jjj);
281
cfelind = jjj;
282
if(minquot < 0.917632)
283
break;
284
}
285
}
286
287
288
/*
289
int i, j, k, l;
290
if (!felind)
291
{
292
cerr << "not in any sphere, 1" << endl;
293
// old, non tree search
294
295
double mindist = 1e10;
296
for (j = 1; j <= tempels.Size(); j++)
297
{
298
if (tempels.Get(j).PNum(1))
299
{
300
double toofar =
301
Dist2 (centers.Get(j), newp) - radi2.Get(j);
302
if (toofar < mindist || toofar < 1e-7)
303
{
304
mindist = toofar;
305
cout << " dist2 = " << Dist2 (centers.Get(j), newp)
306
<< " radi2 = " << radi2.Get(j) << endl;
307
}
308
if (toofar < 0)
309
{
310
el = tempels.Get(j);
311
felind = j;
312
cout << "sphere found !" << endl;
313
break;
314
}
315
}
316
}
317
cout << "point is too far from sheres: " << mindist << endl;
318
}
319
*/
320
321
if (cfelind == -1)
322
{
323
PrintWarning ("Delaunay, point not in any sphere");
324
return;
325
}
326
327
328
/*
329
insphere: point is in sphere -> delete element
330
closesphere: point is close to sphere -> considered for same center
331
*/
332
333
// save overestimate
334
insphere.SetMaxIndex (2 * tempels.Size() + 5 * mesh.GetNP());
335
closesphere.SetMaxIndex (2 * tempels.Size() + 5 * mesh.GetNP());
336
337
insphere.Clear();
338
closesphere.Clear();
339
340
341
insphere.Add (cfelind);
342
343
int changed = 1;
344
int nstarti = 1, starti;
345
346
347
while (changed)
348
{
349
changed = 0;
350
starti = nstarti;
351
nstarti = insphere.Array().Size()+1;
352
353
354
// if point in sphere, then it is also closesphere
355
for (int j = starti; j < nstarti; j++)
356
{
357
int helind = insphere.Array().Get(j);
358
if (!closesphere.IsIn (helind))
359
closesphere.Add (helind);
360
}
361
362
// add connected spheres to insphere - list
363
for (int j = starti; j < nstarti; j++)
364
{
365
list.GetList (insphere.Array().Get(j), connected);
366
for (int k = 0; k < connected.Size(); k++)
367
{
368
int celind = connected[k];
369
370
if (tempels.Get(celind)[0] != -1 &&
371
!insphere.IsIn (celind))
372
{
373
changed = 1;
374
insphere.Add (celind);
375
}
376
}
377
}
378
379
// check neighbour-tets
380
for (int j = starti; j < nstarti; j++)
381
for (int k = 1; k <= 4; k++)
382
{
383
int helind = insphere.Array().Get(j);
384
int nbind = meshnb.GetNB (helind, k);
385
386
if (nbind && !insphere.IsIn (nbind) )
387
{
388
//changed
389
//int prec = testout->precision();
390
//testout->precision(12);
391
//(*testout) << "val1 " << Dist2 (centers.Get(nbind), newp)
392
// << " val2 " << radi2.Get(nbind) * (1+1e-8)
393
// << " val3 " << radi2.Get(nbind)
394
// << " val1 / val3 " << Dist2 (centers.Get(nbind), newp)/radi2.Get(nbind) << endl;
395
//testout->precision(prec);
396
if (Dist2 (centers.Get(nbind), newp)
397
< radi2.Get(nbind) * (1+1e-8) )
398
closesphere.Add (nbind);
399
400
if (Dist2 (centers.Get(nbind), newp)
401
< radi2.Get(nbind) * (1 + 1e-12))
402
{
403
// point is in sphere -> remove tet
404
insphere.Add (nbind);
405
changed = 1;
406
}
407
else
408
{
409
/*
410
Element2d face;
411
tempels.Get(helind).GetFace (k, face);
412
413
const Point3d & p1 = mesh.Point (face.PNum(1));
414
const Point3d & p2 = mesh.Point (face[1]);
415
const Point3d & p3 = mesh.Point (face[2]);
416
*/
417
418
INDEX_3 i3 = tempels.Get(helind).GetFace (k-1);
419
420
const Point3d & p1 = mesh.Point ( PointIndex (i3.I1()));
421
const Point3d & p2 = mesh.Point ( PointIndex (i3.I2()));
422
const Point3d & p3 = mesh.Point ( PointIndex (i3.I3()));
423
424
425
Vec3d v1(p1, p2);
426
Vec3d v2(p1, p3);
427
Vec3d n = Cross (v1, v2);
428
n /= n.Length();
429
430
if (n * Vec3d (p1, mesh.Point (tempels.Get(helind)[k-1])) > 0)
431
n *= -1;
432
433
double dist = n * Vec3d (p1, newp);
434
435
436
if (dist > -1e-10) // 1e-10
437
{
438
insphere.Add (nbind);
439
changed = 1;
440
}
441
442
443
}
444
}
445
}
446
} // while (changed)
447
448
// (*testout) << "newels: " << endl;
449
ARRAY<Element> newels;
450
451
Element2d face(TRIG);
452
453
for (int j = 1; j <= insphere.Array().Size(); j++)
454
for (int k = 1; k <= 4; k++)
455
{
456
// int elind = insphere.Array().Get(j);
457
int celind = insphere.Array().Get(j);
458
int nbind = meshnb.GetNB (celind, k);
459
460
if (!nbind || !insphere.IsIn (nbind))
461
{
462
tempels.Get (celind).GetFace1 (k, face);
463
464
Element newel(TET);
465
for (int l = 0; l < 3; l++)
466
newel[l] = face[l];
467
newel[3] = newpi;
468
469
newels.Append (newel);
470
471
Vec<3> v1 = mesh[face[1]] - mesh[face[0]];
472
Vec<3> v2 = mesh[face[2]] - mesh[face[0]];
473
Vec<3> n = Cross (v1, v2);
474
475
n.Normalize();
476
if (n * Vec3d(mesh.Point (face[0]),
477
mesh.Point (tempels.Get(insphere.Array().Get(j))[k-1]))
478
> 0)
479
n *= -1;
480
481
double hval = n * ( newp - mesh[face[0]]);
482
483
if (hval > -1e-12)
484
{
485
cerr << "vec to outer" << endl;
486
(*testout) << "vec to outer, hval = " << hval << endl;
487
(*testout) << "v1 x v2 = " << Cross (v1, v2) << endl;
488
(*testout) << "facep: "
489
<< mesh.Point (face[0]) << " "
490
<< mesh.Point (face[1]) << " "
491
<< mesh.Point (face[2]) << endl;
492
}
493
}
494
}
495
496
meshnb.ResetFaceHT (10*insphere.Array().Size()+1);
497
498
for (int j = 1; j <= insphere.Array().Size(); j++)
499
{
500
// int elind =
501
int celind = insphere.Array().Get(j);
502
503
meshnb.Delete (celind);
504
list.DeleteElement (celind);
505
506
for (int k = 0; k < 4; k++)
507
tempels.Elem(celind)[k] = -1;
508
509
((ADTree6&)tettree.Tree()).DeleteElement (celind);
510
freelist.Append (celind);
511
}
512
513
514
int hasclose = 0;
515
for (int j = 1; j <= closesphere.Array().Size(); j++)
516
{
517
int ind = closesphere.Array().Get(j);
518
if (!insphere.IsIn(ind) &&
519
fabs (Dist2 (centers.Get (ind), newp) - radi2.Get(ind)) < 1e-8 )
520
hasclose = 1;
521
}
522
523
for (int j = 1; j <= newels.Size(); j++)
524
{
525
int nelind;
526
527
if (!freelist.Size())
528
{
529
tempels.Append (newels.Get(j));
530
nelind = tempels.Size();
531
}
532
else
533
{
534
nelind = freelist.Last();
535
freelist.DeleteLast();
536
537
tempels.Elem(nelind) = newels.Get(j);
538
}
539
540
meshnb.Add (nelind);
541
list.AddElement (nelind);
542
543
for (int k = 0; k < 4; k++)
544
pp[k] = &mesh.Point (newels.Get(j)[k]);
545
546
if (CalcSphereCenter (&pp[0], pc) )
547
{
548
PrintSysError ("Delaunay: New tet is flat");
549
550
(*testout) << "new tet is flat" << endl;
551
for (int k = 1; k <= 4; k++)
552
(*testout) << newels.Get(j).PNum(k) << " ";
553
(*testout) << endl;
554
for (int k = 1; k <= 4; k++)
555
(*testout) << *pp[k-1] << " ";
556
(*testout) << endl;
557
}
558
559
r2 = Dist2 (*pp[0], pc);
560
if (hasclose)
561
for (int k = 1; k <= closesphere.Array().Size(); k++)
562
{
563
int csameind = closesphere.Array().Get(k);
564
if (!insphere.IsIn(csameind) &&
565
fabs (r2 - radi2.Get(csameind)) < 1e-10 &&
566
Dist (pc, centers.Get(csameind)) < 1e-10)
567
{
568
pc = centers.Get(csameind);
569
r2 = radi2.Get(csameind);
570
list.ConnectElement (nelind, csameind);
571
break;
572
}
573
}
574
575
if (centers.Size() < nelind)
576
{
577
centers.Append (pc);
578
radi2.Append (r2);
579
}
580
else
581
{
582
centers.Elem(nelind) = pc;
583
radi2.Elem(nelind) = r2;
584
}
585
586
closesphere.Add (nelind);
587
588
tpmax = tpmin = *pp[0];
589
for (int k = 1; k <= 3; k++)
590
{
591
tpmin.SetToMin (*pp[k]);
592
tpmax.SetToMax (*pp[k]);
593
}
594
tpmax = tpmax + 0.01 * (tpmax - tpmin);
595
tettree.Insert (tpmin, tpmax, nelind);
596
}
597
}
598
599
600
601
602
603
604
void Delaunay1 (Mesh & mesh, const MeshingParameters & mp, AdFront3 * adfront,
605
ARRAY<DelaunayTet> & tempels,
606
int oldnp, DelaunayTet & startel, Point3d & pmin, Point3d & pmax)
607
{
608
int i, j, k;
609
const Point<3> * pp[4];
610
611
ARRAY<Point<3> > centers;
612
ARRAY<double> radi2;
613
614
Point3d tpmin, tpmax;
615
616
617
// new: local box
618
mesh.GetBox (pmax, pmin); // lower bound for pmax, upper for pmin
619
for (i = 1; i <= adfront->GetNF(); i++)
620
{
621
const MiniElement2d & face = adfront->GetFace(i);
622
for (j = 0; j < face.GetNP(); j++)
623
{
624
pmin.SetToMin (mesh.Point (face[j]));
625
pmax.SetToMax (mesh.Point (face[j]));
626
}
627
}
628
629
for (i = 0; i < mesh.LockedPoints().Size(); i++)
630
{
631
pmin.SetToMin (mesh.Point (mesh.LockedPoints()[i]));
632
pmax.SetToMax (mesh.Point (mesh.LockedPoints()[i]));
633
}
634
635
636
637
Vec3d vdiag(pmin, pmax);
638
// double r1 = vdiag.Length();
639
double r1 = sqrt (3.0) * max3(vdiag.X(), vdiag.Y(), vdiag.Z());
640
vdiag = Vec3d (r1, r1, r1);
641
//double r2;
642
643
Point3d pmin2 = pmin - 8 * vdiag;
644
Point3d pmax2 = pmax + 8 * vdiag;
645
646
Point3d cp1(pmin2), cp2(pmax2), cp3(pmax2), cp4(pmax2);
647
cp2.X() = pmin2.X();
648
cp3.Y() = pmin2.Y();
649
cp4.Z() = pmin2.Z();
650
651
652
653
654
int np = mesh.GetNP();
655
656
startel[0] = mesh.AddPoint (cp1);
657
startel[1] = mesh.AddPoint (cp2);
658
startel[2] = mesh.AddPoint (cp3);
659
startel[3] = mesh.AddPoint (cp4);
660
661
// flag points to use for Delaunay:
662
BitArrayChar<PointIndex::BASE> usep(np);
663
usep.Clear();
664
for (i = 1; i <= adfront->GetNF(); i++)
665
{
666
const MiniElement2d & face = adfront->GetFace(i);
667
for (j = 0; j < face.GetNP(); j++)
668
usep.Set (face[j]);
669
}
670
671
for (i = oldnp + PointIndex::BASE;
672
i < np + PointIndex::BASE; i++)
673
usep.Set (i);
674
675
for (i = 0; i < mesh.LockedPoints().Size(); i++)
676
usep.Set (mesh.LockedPoints()[i]);
677
678
679
ARRAY<int> freelist;
680
681
682
int cntp = 0;
683
684
MeshNB meshnb (tempels, mesh.GetNP() + 5);
685
SphereList list;
686
687
pmin2 = pmin2 + 0.1 * (pmin2 - pmax2);
688
pmax2 = pmax2 + 0.1 * (pmax2 - pmin2);
689
690
Box3dTree tettree(pmin2, pmax2);
691
692
693
tempels.Append (startel);
694
meshnb.Add (1);
695
list.AddElement (1);
696
ARRAY<int> connected, treesearch;
697
698
699
tpmin = tpmax = mesh.Point(startel[0]);
700
for (k = 1; k < 4; k++)
701
{
702
tpmin.SetToMin (mesh.Point (startel[k]));
703
tpmax.SetToMax (mesh.Point (startel[k]));
704
}
705
tpmax = tpmax + 0.01 * (tpmax - tpmin);
706
tettree.Insert (tpmin, tpmax, 1);
707
708
709
Point<3> pc;
710
711
for (k = 0; k < 4; k++)
712
{
713
pp[k] = &mesh.Point (startel[k]);
714
}
715
716
CalcSphereCenter (&pp[0], pc);
717
718
centers.Append (pc);
719
radi2.Append (Dist2 (*pp[0], pc));
720
721
722
IndexSet insphere(mesh.GetNP());
723
IndexSet closesphere(mesh.GetNP());
724
725
726
727
// "random" reordering of points (speeds a factor 3 - 5 !!!)
728
729
ARRAY<int> mixed(np);
730
int prims[] = { 11, 13, 17, 19, 23, 29, 31, 37 };
731
int prim;
732
733
i = 0;
734
while (np % prims[i] == 0) i++;
735
prim = prims[i];
736
737
for (i = 1; i <= np; i++)
738
mixed.Elem(i) = (prim * i) % np + PointIndex::BASE;
739
740
for (i = 1; i <= np; i++)
741
{
742
if (i % 1000 == 0)
743
{
744
if (i % 10000 == 0)
745
PrintDot ('+');
746
else
747
PrintDot ('.');
748
}
749
750
multithread.percent = 100.0 * i / np;
751
if (multithread.terminate)
752
break;
753
754
PointIndex newpi = mixed.Get(i);
755
756
if (!usep.Test(newpi))
757
continue;
758
759
cntp++;
760
761
const Point3d & newp = mesh.Point(newpi);
762
763
AddDelaunayPoint (newpi, newp, tempels, mesh,
764
tettree, meshnb, centers, radi2,
765
connected, treesearch, freelist, list, insphere, closesphere);
766
}
767
768
for (i = tempels.Size(); i >= 1; i--)
769
if (tempels.Get(i)[0] <= 0)
770
tempels.DeleteElement (i);
771
772
PrintDot ('\n');
773
774
PrintMessage (3, "Points: ", cntp);
775
PrintMessage (3, "Elements: ", tempels.Size());
776
// (*mycout) << cntp << " / " << tempels.Size() << " points/elements" << endl;
777
778
/*
779
cout << "tempels: ";
780
tempels.PrintMemInfo(cout);
781
cout << "Searchtree: ";
782
tettree.Tree().PrintMemInfo(cout);
783
cout << "MeshNB: ";
784
meshnb.PrintMemInfo(cout);
785
*/
786
}
787
788
789
790
791
792
793
void Meshing3 :: Delaunay (Mesh & mesh, int domainnr, const MeshingParameters & mp)
794
{
795
int np, ne;
796
797
PrintMessage (1, "Delaunay meshing");
798
PrintMessage (3, "number of points: ", mesh.GetNP());
799
PushStatus ("Delaunay meshing");
800
801
802
ARRAY<DelaunayTet> tempels;
803
Point3d pmin, pmax;
804
805
DelaunayTet startel;
806
807
int oldnp = mesh.GetNP();
808
if (mp.blockfill)
809
{
810
BlockFillLocalH (mesh, mp);
811
PrintMessage (3, "number of points: ", mesh.GetNP());
812
}
813
814
np = mesh.GetNP();
815
816
Delaunay1 (mesh, mp, adfront, tempels, oldnp, startel, pmin, pmax);
817
818
{
819
// improve delaunay - mesh by swapping !!!!
820
821
Mesh tempmesh;
822
for (PointIndex pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++)
823
tempmesh.AddPoint (mesh[pi]);
824
825
for (int i = 1; i <= tempels.Size(); i++)
826
{
827
Element el(4);
828
for (int j = 0; j < 4; j++)
829
el[j] = tempels.Elem(i)[j];
830
831
el.SetIndex (1);
832
833
const Point3d & lp1 = mesh.Point (el[0]);
834
const Point3d & lp2 = mesh.Point (el[1]);
835
const Point3d & lp3 = mesh.Point (el[2]);
836
const Point3d & lp4 = mesh.Point (el[3]);
837
Vec3d v1(lp1, lp2);
838
Vec3d v2(lp1, lp3);
839
Vec3d v3(lp1, lp4);
840
841
Vec3d n = Cross (v1, v2);
842
double vol = n * v3;
843
if (vol > 0) swap (el[2], el[3]);
844
845
tempmesh.AddVolumeElement (el);
846
}
847
848
849
MeshQuality3d (tempmesh);
850
851
tempmesh.AddFaceDescriptor (FaceDescriptor (1, 1, 0, 0));
852
tempmesh.AddFaceDescriptor (FaceDescriptor (2, 1, 0, 0));
853
854
855
856
for (int i = 1; i <= mesh.GetNOpenElements(); i++)
857
{
858
Element2d sel = mesh.OpenElement(i);
859
sel.SetIndex(1);
860
tempmesh.AddSurfaceElement (sel);
861
swap (sel[1], sel[2]);
862
tempmesh.AddSurfaceElement (sel);
863
}
864
865
866
for (int i = 1; i <= 4; i++)
867
{
868
Element2d self(TRIG);
869
self.SetIndex (1);
870
startel.GetFace1 (i, self);
871
tempmesh.AddSurfaceElement (self);
872
}
873
874
875
// for (i = mesh.GetNP() - 3; i <= mesh.GetNP(); i++)
876
// tempmesh.AddLockedPoint (i);
877
for (PointIndex pi = PointIndex::BASE;
878
pi < tempmesh.GetNP() + PointIndex::BASE; pi++)
879
tempmesh.AddLockedPoint (pi);
880
881
// tempmesh.PrintMemInfo(cout);
882
// tempmesh.Save ("tempmesh.vol");
883
884
for (int i = 1; i <= 2; i++)
885
{
886
tempmesh.FindOpenElements ();
887
888
PrintMessage (5, "Num open: ", tempmesh.GetNOpenElements());
889
tempmesh.CalcSurfacesOfNode ();
890
891
tempmesh.FreeOpenElementsEnvironment (1);
892
893
MeshOptimize3d meshopt;
894
// tempmesh.CalcSurfacesOfNode();
895
meshopt.SwapImprove(tempmesh, OPT_CONFORM);
896
}
897
898
MeshQuality3d (tempmesh);
899
900
tempels.SetSize(0);
901
for (int i = 1; i <= tempmesh.GetNE(); i++)
902
tempels.Append (tempmesh.VolumeElement(i));
903
}
904
905
906
907
// remove degenerated
908
909
BitArray badnode(mesh.GetNP());
910
badnode.Clear();
911
int ndeg = 0;
912
for (int i = 1; i <= tempels.Size(); i++)
913
{
914
Element el(4);
915
for (int j = 0; j < 4; j++)
916
el[j] = tempels.Elem(i)[j];
917
// Element & el = tempels.Elem(i);
918
const Point3d & lp1 = mesh.Point (el[0]);
919
const Point3d & lp2 = mesh.Point (el[1]);
920
const Point3d & lp3 = mesh.Point (el[2]);
921
const Point3d & lp4 = mesh.Point (el[3]);
922
Vec3d v1(lp1, lp2);
923
Vec3d v2(lp1, lp3);
924
Vec3d v3(lp1, lp4);
925
Vec3d n = Cross (v1, v2);
926
double vol = n * v3;
927
928
double h = v1.Length() + v2.Length() + v3.Length();
929
if (fabs (vol) < 1e-8 * (h * h * h) &&
930
(el[0] <= np && el[1] <= np &&
931
el[2] <= np && el[3] <= np) ) // old: 1e-12
932
{
933
badnode.Set(el[0]);
934
badnode.Set(el[1]);
935
badnode.Set(el[2]);
936
badnode.Set(el[3]);
937
ndeg++;
938
(*testout) << "vol = " << vol << " h = " << h << endl;
939
}
940
941
if (vol > 0)
942
Swap (el[2], el[3]);
943
}
944
945
ne = tempels.Size();
946
for (int i = ne; i >= 1; i--)
947
{
948
const DelaunayTet & el = tempels.Get(i);
949
if (badnode.Test(el[0]) ||
950
badnode.Test(el[1]) ||
951
badnode.Test(el[2]) ||
952
badnode.Test(el[3]) )
953
tempels.DeleteElement(i);
954
}
955
956
957
PrintMessage (3, ndeg, " degenerated elements removed");
958
959
// find surface triangles which are no face of any tet
960
961
INDEX_3_HASHTABLE<int> openeltab(mesh.GetNOpenElements()+3);
962
ARRAY<int> openels;
963
for (int i = 1; i <= mesh.GetNOpenElements(); i++)
964
{
965
const Element2d & tri = mesh.OpenElement(i);
966
INDEX_3 i3(tri[0], tri[1], tri[2]);
967
i3.Sort();
968
openeltab.Set (i3, i);
969
}
970
971
for (int i = 1; i <= tempels.Size(); i++)
972
{
973
for (int j = 0; j < 4; j++)
974
{
975
INDEX_3 i3 = tempels.Get(i).GetFace (j);
976
i3.Sort();
977
if (openeltab.Used(i3))
978
openeltab.Set (i3, 0);
979
}
980
}
981
982
// and store them in openels
983
for (int i = 1; i <= openeltab.GetNBags(); i++)
984
for (int j = 1; j <= openeltab.GetBagSize(i); j++)
985
{
986
INDEX_3 i3;
987
int fnr;
988
openeltab.GetData (i, j, i3, fnr);
989
if (fnr)
990
openels.Append (fnr);
991
}
992
993
994
995
996
997
// find open triangle with close edge (from halfening of surface squares)
998
999
INDEX_2_HASHTABLE<INDEX_2> twotrias(mesh.GetNOpenElements()+5);
1000
// for (i = 1; i <= mesh.GetNOpenElements(); i++)
1001
for (int ii = 1; ii <= openels.Size(); ii++)
1002
{
1003
int i = openels.Get(ii);
1004
const Element2d & el = mesh.OpenElement(i);
1005
for (int j = 1; j <= 3; j++)
1006
{
1007
INDEX_2 hi2 (el.PNumMod (j), el.PNumMod(j+1));
1008
hi2.Sort();
1009
if (twotrias.Used(hi2))
1010
{
1011
INDEX_2 hi3;
1012
hi3 = twotrias.Get (hi2);
1013
hi3.I2() = el.PNumMod (j+2);
1014
twotrias.Set (hi2, hi3);
1015
}
1016
else
1017
{
1018
INDEX_2 hi3(el.PNumMod (j+2), 0);
1019
twotrias.Set (hi2, hi3);
1020
}
1021
}
1022
}
1023
1024
INDEX_2_HASHTABLE<int> tetedges(tempels.Size() + 5);
1025
for (int i = 1; i <= tempels.Size(); i++)
1026
{
1027
const DelaunayTet & el = tempels.Get(i);
1028
INDEX_2 i2;
1029
for (int j = 1; j <= 6; j++)
1030
{
1031
switch (j)
1032
{
1033
case 1: i2.I1()=el[0]; i2.I2()=el[1]; break;
1034
case 2: i2.I1()=el[0]; i2.I2()=el[2]; break;
1035
case 3: i2.I1()=el[0]; i2.I2()=el[3]; break;
1036
case 4: i2.I1()=el[1]; i2.I2()=el[2]; break;
1037
case 5: i2.I1()=el[1]; i2.I2()=el[3]; break;
1038
case 6: i2.I1()=el[2]; i2.I2()=el[3]; break;
1039
default: i2.I1()=i2.I2()=0; break;
1040
}
1041
i2.Sort();
1042
tetedges.Set (i2, 1);
1043
}
1044
}
1045
// cout << "tetedges:";
1046
// tetedges.PrintMemInfo (cout);
1047
1048
1049
for (INDEX_2_HASHTABLE<INDEX_2>::Iterator it = twotrias.Begin();
1050
it != twotrias.End(); it++)
1051
{
1052
INDEX_2 hi2, hi3;
1053
twotrias.GetData (it, hi2, hi3);
1054
hi3.Sort();
1055
if (tetedges.Used (hi3))
1056
{
1057
const Point3d & p1 = mesh.Point ( PointIndex (hi2.I1()));
1058
const Point3d & p2 = mesh.Point ( PointIndex (hi2.I2()));
1059
const Point3d & p3 = mesh.Point ( PointIndex (hi3.I1()));
1060
const Point3d & p4 = mesh.Point ( PointIndex (hi3.I2()));
1061
Vec3d v1(p1, p2);
1062
Vec3d v2(p1, p3);
1063
Vec3d v3(p1, p4);
1064
Vec3d n = Cross (v1, v2);
1065
double vol = n * v3;
1066
1067
double h = v1.Length() + v2.Length() + v3.Length();
1068
if (fabs (vol) < 1e-4 * (h * h * h)) // old: 1e-12
1069
{
1070
badnode.Set(hi3.I1());
1071
badnode.Set(hi3.I2());
1072
}
1073
}
1074
}
1075
1076
/*
1077
for (i = 1; i <= twotrias.GetNBags(); i++)
1078
for (j = 1; j <= twotrias.GetBagSize (i); j++)
1079
{
1080
INDEX_2 hi2, hi3;
1081
twotrias.GetData (i, j, hi2, hi3);
1082
hi3.Sort();
1083
if (tetedges.Used (hi3))
1084
{
1085
const Point3d & p1 = mesh.Point (hi2.I1());
1086
const Point3d & p2 = mesh.Point (hi2.I2());
1087
const Point3d & p3 = mesh.Point (hi3.I1());
1088
const Point3d & p4 = mesh.Point (hi3.I2());
1089
Vec3d v1(p1, p2);
1090
Vec3d v2(p1, p3);
1091
Vec3d v3(p1, p4);
1092
Vec3d n = Cross (v1, v2);
1093
double vol = n * v3;
1094
1095
double h = v1.Length() + v2.Length() + v3.Length();
1096
if (fabs (vol) < 1e-4 * (h * h * h)) // old: 1e-12
1097
{
1098
badnode.Set(hi3.I1());
1099
badnode.Set(hi3.I2());
1100
}
1101
}
1102
}
1103
*/
1104
1105
ne = tempels.Size();
1106
for (int i = ne; i >= 1; i--)
1107
{
1108
const DelaunayTet & el = tempels.Get(i);
1109
if (badnode.Test(el[0]) ||
1110
badnode.Test(el[1]) ||
1111
badnode.Test(el[2]) ||
1112
badnode.Test(el[3]) )
1113
tempels.DeleteElement(i);
1114
}
1115
1116
1117
1118
1119
// find intersecting:
1120
PrintMessage (3, "Remove intersecting");
1121
if (openels.Size())
1122
{
1123
Box3dTree setree(pmin, pmax);
1124
1125
/*
1126
cout << "open elements in search tree: " << openels.Size() << endl;
1127
cout << "pmin, pmax = " << pmin << " - " << pmax << endl;
1128
*/
1129
1130
for (int i = 1; i <= openels.Size(); i++)
1131
{
1132
int fnr;
1133
fnr = openels.Get(i);
1134
if (fnr)
1135
{
1136
const Element2d & tri = mesh.OpenElement(fnr);
1137
1138
Point3d ltpmin (mesh.Point(tri[0]));
1139
Point3d ltpmax (ltpmin);
1140
1141
for (int k = 2; k <= 3; k++)
1142
{
1143
ltpmin.SetToMin (mesh.Point (tri.PNum(k)));
1144
ltpmax.SetToMax (mesh.Point (tri.PNum(k)));
1145
}
1146
setree.Insert (ltpmin, ltpmax, fnr);
1147
}
1148
}
1149
1150
ARRAY<int> neartrias;
1151
for (int i = 1; i <= tempels.Size(); i++)
1152
{
1153
const Point<3> *pp[4];
1154
int tetpi[4];
1155
DelaunayTet & el = tempels.Elem(i);
1156
1157
int intersect = 0;
1158
1159
for (int j = 0; j < 4; j++)
1160
{
1161
pp[j] = &mesh.Point(el[j]);
1162
tetpi[j] = el[j];
1163
}
1164
1165
Point3d tetpmin(*pp[0]);
1166
Point3d tetpmax(tetpmin);
1167
for (int j = 1; j < 4; j++)
1168
{
1169
tetpmin.SetToMin (*pp[j]);
1170
tetpmax.SetToMax (*pp[j]);
1171
}
1172
tetpmin = tetpmin + 0.01 * (tetpmin - tetpmax);
1173
tetpmax = tetpmax + 0.01 * (tetpmax - tetpmin);
1174
1175
setree.GetIntersecting (tetpmin, tetpmax, neartrias);
1176
1177
1178
// for (j = 1; j <= mesh.GetNSE(); j++)
1179
// {
1180
for (int jj = 1; jj <= neartrias.Size(); jj++)
1181
{
1182
int j = neartrias.Get(jj);
1183
1184
const Element2d & tri = mesh.OpenElement(j);
1185
const Point<3> *tripp[3];
1186
int tripi[3];
1187
1188
for (int k = 1; k <= 3; k++)
1189
{
1190
tripp[k-1] = &mesh.Point (tri.PNum(k));
1191
tripi[k-1] = tri.PNum(k);
1192
}
1193
1194
if (IntersectTetTriangle (&pp[0], &tripp[0], tetpi, tripi))
1195
{
1196
/*
1197
int il1, il2;
1198
(*testout) << "intersect !" << endl;
1199
(*testout) << "triind: ";
1200
for (il1 = 0; il1 < 3; il1++)
1201
(*testout) << " " << tripi[il1];
1202
(*testout) << endl;
1203
(*testout) << "tetind: ";
1204
for (il2 = 0; il2 < 4; il2++)
1205
(*testout) << " " << tetpi[il2];
1206
(*testout) << endl;
1207
1208
(*testout) << "trip: ";
1209
for (il1 = 0; il1 < 3; il1++)
1210
(*testout) << " " << *tripp[il1];
1211
(*testout) << endl;
1212
(*testout) << "tetp: ";
1213
for (il2 = 0; il2 < 4; il2++)
1214
(*testout) << " " << *pp[il2];
1215
(*testout) << endl;
1216
*/
1217
1218
1219
intersect = 1;
1220
break;
1221
}
1222
}
1223
1224
1225
if (intersect)
1226
{
1227
tempels.DeleteElement(i);
1228
i--;
1229
}
1230
}
1231
}
1232
1233
1234
1235
1236
PrintMessage (3, "Remove outer");
1237
1238
// find connected tets (with no face between, and no hole due
1239
// to removed intersecting tets.
1240
// INDEX_3_HASHTABLE<INDEX_2> innerfaces(np);
1241
1242
1243
INDEX_3_HASHTABLE<int> boundaryfaces(mesh.GetNOpenElements()/3+1);
1244
for (int i = 1; i <= mesh.GetNOpenElements(); i++)
1245
{
1246
const Element2d & tri = mesh.OpenElement(i);
1247
INDEX_3 i3 (tri[0], tri[1], tri[2]);
1248
i3.Sort();
1249
boundaryfaces.PrepareSet (i3);
1250
}
1251
boundaryfaces.AllocateElements();
1252
for (int i = 1; i <= mesh.GetNOpenElements(); i++)
1253
{
1254
const Element2d & tri = mesh.OpenElement(i);
1255
INDEX_3 i3 (tri[0], tri[1], tri[2]);
1256
i3.Sort();
1257
boundaryfaces.Set (i3, 1);
1258
}
1259
1260
for (int i = 0; i < tempels.Size(); i++)
1261
for (int j = 0; j < 4; j++)
1262
tempels[i].NB(j) = 0;
1263
1264
TABLE<int,PointIndex::BASE> elsonpoint(mesh.GetNP());
1265
for (int i = 0; i < tempels.Size(); i++)
1266
{
1267
const DelaunayTet & el = tempels[i];
1268
INDEX_4 i4(el[0], el[1], el[2], el[3]);
1269
i4.Sort();
1270
elsonpoint.IncSizePrepare (i4.I1());
1271
elsonpoint.IncSizePrepare (i4.I2());
1272
}
1273
1274
elsonpoint.AllocateElementsOneBlock();
1275
1276
for (int i = 0; i < tempels.Size(); i++)
1277
{
1278
const DelaunayTet & el = tempels[i];
1279
INDEX_4 i4(el[0], el[1], el[2], el[3]);
1280
i4.Sort();
1281
elsonpoint.Add (i4.I1(), i+1);
1282
elsonpoint.Add (i4.I2(), i+1);
1283
}
1284
1285
// cout << "elsonpoint mem: ";
1286
// elsonpoint.PrintMemInfo(cout);
1287
1288
INDEX_3_CLOSED_HASHTABLE<INDEX_2> faceht(100);
1289
1290
Element2d hel(TRIG);
1291
for (PointIndex pi = PointIndex::BASE;
1292
pi < mesh.GetNP()+PointIndex::BASE; pi++)
1293
{
1294
faceht.SetSize (4 * elsonpoint[pi].Size());
1295
for (int ii = 0; ii < elsonpoint[pi].Size(); ii++)
1296
{
1297
int i = elsonpoint[pi][ii];
1298
const DelaunayTet & el = tempels.Get(i);
1299
1300
for (int j = 1; j <= 4; j++)
1301
{
1302
el.GetFace1 (j, hel);
1303
hel.Invert();
1304
hel.NormalizeNumbering();
1305
1306
if (hel[0] == pi)
1307
{
1308
INDEX_3 i3(hel[0], hel[1], hel[2]);
1309
1310
if (!boundaryfaces.Used (i3))
1311
{
1312
if (faceht.Used (i3))
1313
{
1314
INDEX_2 i2 = faceht.Get(i3);
1315
1316
tempels.Elem(i).NB1(j) = i2.I1();
1317
tempels.Elem(i2.I1()).NB1(i2.I2()) = i;
1318
}
1319
else
1320
{
1321
hel.Invert();
1322
hel.NormalizeNumbering();
1323
INDEX_3 i3i(hel[0], hel[1], hel[2]);
1324
INDEX_2 i2(i, j);
1325
faceht.Set (i3i, i2);
1326
}
1327
}
1328
}
1329
}
1330
}
1331
}
1332
1333
/*
1334
for (i = 1; i <= tempels.Size(); i++)
1335
{
1336
const DelaunayTet & el = tempels.Get(i);
1337
for (j = 1; j <= 4; j++)
1338
{
1339
INDEX_3 i3;
1340
Element2d face;
1341
el.GetFace1 (j, face);
1342
for (int kk = 1; kk <= 3; kk++)
1343
i3.I(kk) = face.PNum(kk);
1344
1345
i3.Sort();
1346
if (!boundaryfaces.Used (i3))
1347
{
1348
if (innerfaces.Used(i3))
1349
{
1350
INDEX_2 i2;
1351
i2 = innerfaces.Get(i3);
1352
i2.I2() = i;
1353
innerfaces.Set (i3, i2);
1354
}
1355
else
1356
{
1357
INDEX_2 i2;
1358
i2.I1() = i;
1359
i2.I2() = 0;
1360
innerfaces.Set (i3, i2);
1361
}
1362
}
1363
}
1364
}
1365
*/
1366
1367
/*
1368
(*testout) << "nb elements:" << endl;
1369
for (i = 1; i <= tempels.Size(); i++)
1370
{
1371
(*testout) << i << " ";
1372
for (j = 1; j <= 4; j++)
1373
(*testout) << tempels.Get(i).NB1(j) << " ";
1374
(*testout) << endl;
1375
}
1376
1377
(*testout) << "pairs:" << endl;
1378
for (i = 1; i <= innerfaces.GetNBags(); i++)
1379
for (j = 1; j <= innerfaces.GetBagSize(i); j++)
1380
{
1381
INDEX_3 i3;
1382
INDEX_2 i2;
1383
innerfaces.GetData (i, j, i3, i2);
1384
(*testout) << i2 << endl;
1385
}
1386
*/
1387
1388
1389
1390
1391
1392
1393
1394
/*
1395
cout << "innerfaces: ";
1396
innerfaces.PrintMemInfo (cout);
1397
*/
1398
1399
// cout << "boundaryfaces: ";
1400
// boundaryfaces.PrintMemInfo (cout);
1401
1402
1403
PrintMessage (5, "tables filled");
1404
1405
1406
ne = tempels.Size();
1407
BitArray inner(ne), outer(ne);
1408
inner.Clear();
1409
outer.Clear();
1410
ARRAY<int> elstack;
1411
1412
/*
1413
int starti = 0;
1414
for (i = 1; i <= ne; i++)
1415
{
1416
const Element & el = tempels.Get(i);
1417
for (j = 1; j <= 4; j++)
1418
for (k = 1; k <= 4; k++)
1419
if (el.PNum(j) == startel.PNum(k))
1420
{
1421
outer.Set(i);
1422
starti = i;
1423
}
1424
}
1425
*/
1426
1427
while (1)
1428
{
1429
int inside;
1430
bool done = 1;
1431
1432
int i;
1433
for (i = 1; i <= ne; i++)
1434
if (!inner.Test(i) && !outer.Test(i))
1435
{
1436
done = 0;
1437
break;
1438
}
1439
1440
if (done) break;
1441
1442
const DelaunayTet & el = tempels.Get(i);
1443
const Point3d & p1 = mesh.Point (el[0]);
1444
const Point3d & p2 = mesh.Point (el[1]);
1445
const Point3d & p3 = mesh.Point (el[2]);
1446
const Point3d & p4 = mesh.Point (el[3]);
1447
1448
Point3d ci = Center (p1, p2, p3, p4);
1449
1450
inside = adfront->Inside (ci);
1451
1452
/*
1453
cout << "startel: " << i << endl;
1454
cout << "inside = " << inside << endl;
1455
cout << "ins2 = " << adfront->Inside (Center (ci, p1)) << endl;
1456
cout << "ins3 = " << adfront->Inside (Center (ci, p2)) << endl;
1457
*/
1458
1459
elstack.SetSize(0);
1460
elstack.Append (i);
1461
1462
while (elstack.Size())
1463
{
1464
int ei = elstack.Last();
1465
elstack.DeleteLast();
1466
1467
if (!inner.Test(ei) && !outer.Test(ei))
1468
{
1469
if (inside)
1470
inner.Set(ei);
1471
else
1472
outer.Set(ei);
1473
1474
1475
for (int j = 1; j <= 4; j++)
1476
{
1477
INDEX_3 i3 = tempels.Get(ei).GetFace1(j);
1478
/*
1479
Element2d face;
1480
tempels.Get(ei).GetFace(j, face);
1481
for (int kk = 1; kk <= 3; kk++)
1482
i3.I(kk) = face.PNum(kk);
1483
*/
1484
i3.Sort();
1485
1486
1487
if (tempels.Get(ei).NB1(j))
1488
elstack.Append (tempels.Get(ei).NB1(j));
1489
1490
/*
1491
if (innerfaces.Used(i3))
1492
{
1493
INDEX_2 i2 = innerfaces.Get(i3);
1494
int other = i2.I1() + i2.I2() - ei;
1495
1496
if (other != tempels.Get(ei).NB1(j))
1497
cerr << "different1 !!" << endl;
1498
1499
if (other)
1500
{
1501
elstack.Append (other);
1502
}
1503
}
1504
else
1505
if (tempels.Get(ei).NB1(j))
1506
cerr << "different2 !!" << endl;
1507
*/
1508
1509
}
1510
}
1511
}
1512
}
1513
1514
1515
1516
// check outer elements
1517
if (debugparam.slowchecks)
1518
{
1519
for (int i = 1; i <= ne; i++)
1520
{
1521
const DelaunayTet & el = tempels.Get(i);
1522
const Point3d & p1 = mesh.Point (el[0]);
1523
const Point3d & p2 = mesh.Point (el[1]);
1524
const Point3d & p3 = mesh.Point (el[2]);
1525
const Point3d & p4 = mesh.Point (el[3]);
1526
1527
Point3d ci = Center (p1, p2, p3, p4);
1528
1529
// if (adfront->Inside (ci) != adfront->Inside (Center (ci, p1)))
1530
// cout << "ERROR: outer test unclear !!!" << endl;
1531
1532
if (inner.Test(i) != adfront->Inside (ci))
1533
{
1534
/*
1535
cout << "ERROR: outer test wrong !!!"
1536
<< "inner = " << int(inner.Test(i))
1537
<< "outer = " << int(outer.Test(i))
1538
<< endl;
1539
1540
cout << "Vol = " << Determinant(Vec3d(p1, p2),
1541
Vec3d(p1, p3),
1542
Vec3d(p1, p4)) << endl;
1543
1544
*/
1545
for (int j = 1; j <= 4; j++)
1546
{
1547
Point3d hp;
1548
switch (j)
1549
{
1550
case 1: hp = Center (ci, p1); break;
1551
case 2: hp = Center (ci, p2); break;
1552
case 3: hp = Center (ci, p3); break;
1553
case 4: hp = Center (ci, p4); break;
1554
}
1555
// cout << "inside(" << hp << ") = " << adfront->Inside(hp) << endl;
1556
}
1557
1558
}
1559
1560
if (adfront->Inside(ci))
1561
outer.Clear(i);
1562
else
1563
outer.Set(i);
1564
}
1565
}
1566
1567
1568
/*
1569
1570
// find bug in innerfaces
1571
1572
tempmesh.DeleteVolumeElements();
1573
1574
for (i = 1; i <= innerfaces.GetNBags(); i++)
1575
for (j = 1; j <= innerfaces.GetBagSize(i); j++)
1576
{
1577
INDEX_3 i3;
1578
INDEX_2 i2;
1579
innerfaces.GetData (i, j, i3, i2);
1580
if (i2.I2())
1581
{
1582
if (outer.Test(i2.I1()) != outer.Test(i2.I2()))
1583
{
1584
tempmesh.AddVolumeElement (tempels.Get(i2.I1()));
1585
tempmesh.AddVolumeElement (tempels.Get(i2.I2()));
1586
cerr << "outer flag different for connected els" << endl;
1587
}
1588
}
1589
}
1590
1591
1592
cout << "Check intersectiong once more" << endl;
1593
1594
for (i = 1; i <= openels.Size(); i++)
1595
{
1596
tempmesh.SurfaceElement(2*openels.Get(i)).SetIndex(2);
1597
tempmesh.SurfaceElement(2*openels.Get(i)-1).SetIndex(2);
1598
}
1599
1600
// for (i = 1; i <= tempmesh.GetNE(); i++)
1601
// for (j = 1; j <= tempmesh.GetNSE(); j++)
1602
i = 6; j = 403;
1603
if (i <= tempmesh.GetNE() && j <= tempmesh.GetNSE())
1604
if (tempmesh.SurfaceElement(j).GetIndex()==2)
1605
{
1606
const Element & el = tempmesh.VolumeElement(i);
1607
const Element2d & sel = tempmesh.SurfaceElement(j);
1608
1609
const Point3d *tripp[3];
1610
const Point3d *pp[4];
1611
int tetpi[4], tripi[3];
1612
1613
for (k = 1; k <= 4; k++)
1614
{
1615
pp[k-1] = &tempmesh.Point(el.PNum(k));
1616
tetpi[k-1] = el.PNum(k);
1617
}
1618
1619
for (k = 1; k <= 3; k++)
1620
{
1621
tripp[k-1] = &tempmesh.Point (sel.PNum(k));
1622
tripi[k-1] = sel.PNum(k);
1623
}
1624
1625
(*testout) << "Check Triangle " << j << ":";
1626
for (k = 1; k <= 3; k++)
1627
(*testout) << " " << sel.PNum(k);
1628
for (k = 1; k <= 3; k++)
1629
(*testout) << " " << tempmesh.Point(sel.PNum(k));
1630
(*testout) << endl;
1631
1632
(*testout) << "Check Tet " << i << ":";
1633
for (k = 1; k <= 4; k++)
1634
(*testout) << " " << el.PNum(k);
1635
for (k = 1; k <= 4; k++)
1636
(*testout) << " " << tempmesh.Point(el.PNum(k));
1637
(*testout) << endl;
1638
1639
if (IntersectTetTriangle (&pp[0], &tripp[0], tetpi, tripi))
1640
{
1641
cout << "Intesection detected !!" << endl;
1642
}
1643
}
1644
1645
tempmesh.Save ("temp.vol");
1646
1647
// end bug search
1648
*/
1649
1650
1651
for (int i = ne; i >= 1; i--)
1652
{
1653
if (outer.Test(i))
1654
tempels.DeleteElement(i);
1655
}
1656
1657
1658
// mesh.points.SetSize(mesh.points.Size()-4);
1659
1660
for (int i = 0; i < tempels.Size(); i++)
1661
{
1662
Element el(4);
1663
for (int j = 0; j < 4; j++)
1664
el[j] = tempels[i][j];
1665
mesh.AddVolumeElement (el);
1666
}
1667
1668
PrintMessage (5, "outer removed");
1669
1670
mesh.FindOpenElements(domainnr);
1671
1672
mesh.Compress();
1673
1674
PopStatus ();
1675
}
1676
}
1677
1678