1 //Author : Gaetan Bricteux
2 
3 #ifndef RECURCUT_CC
4 #define RECURCUT_CC
5 
6 #include "recurCut.h"
7 
middle(const DI_Point * p1,const DI_Point * p2)8 inline DI_Point* middle (const DI_Point *p1, const DI_Point *p2) {
9   return new DI_Point ((p1->x() + p2->x()) / 2, (p1->y() + p2->y()) / 2, (p1->z() + p2->z()) / 2);
10 }
11 
12 // create sub-elements recursively (according to a pattern) until maxlevel
recurCut(RecurElement * re,int maxlevel,int level)13 void recurCut(RecurElement *re, int maxlevel, int level)
14 {
15   if(level++ >= maxlevel) return;
16 
17   if(re->type() == DI_LIN) {
18     // p1 p12 p2
19     DI_Point* p1 = re->el->pt(0);
20     DI_Point* p2 = re->el->pt(1);
21     DI_Point* p12 = middle(p1, p2);
22     DI_Line *l0 = new DI_Line(p1, p12);
23     RecurElement *re0 = new RecurElement(l0);
24     recurCut(re0, maxlevel, level);
25     re->sub[0] = re0; re0->super = re;
26     DI_Line *l1 = new DI_Line(p12, p2);
27     RecurElement *re1 = new RecurElement(l1);
28     recurCut(re1, maxlevel, level);
29     re->sub[1] = re1; re1->super = re;
30     delete p12;
31     delete l0; delete l1;
32   }
33   if(re->type() == DI_TRI) {
34     // p3
35     // p13   p23
36     // p1    p12    p2
37     DI_Point *p1 = re->el->pt(0);
38     DI_Point *p2 = re->el->pt(1);
39     DI_Point *p3 = re->el->pt(2);
40     DI_Point *p12 = middle(p1, p2);
41     DI_Point *p13 = middle(p1, p3);
42     DI_Point *p23 = middle(p2, p3);
43     DI_Triangle *t0 = new DI_Triangle(p1, p12, p13);
44     RecurElement *re0 = new RecurElement(t0);
45     recurCut(re0, maxlevel, level);
46     re->sub[0] = re0; re0->super = re;
47     DI_Triangle *t1 = new DI_Triangle(p2, p23, p12);
48     RecurElement *re1 = new RecurElement(t1);
49     recurCut(re1, maxlevel, level);
50     re->sub[1] = re1; re1->super = re;
51     DI_Triangle *t2 = new DI_Triangle(p3, p13, p23);
52     RecurElement *re2 = new RecurElement(t2);
53     recurCut(re2, maxlevel, level);
54     re->sub[2] = re2; re2->super = re;
55     DI_Triangle *t3 = new DI_Triangle(p12, p23, p13);
56     RecurElement *re3 = new RecurElement(t3);
57     recurCut(re3, maxlevel, level);
58     re->sub[3] = re3; re3->super = re;
59     delete p12; delete p13; delete p23;
60     delete t0; delete t1; delete t2; delete t3;
61   }
62   else if(re->type() == DI_QUA) {
63     // p4    p34    p3
64     // p14   p1234  p23
65     // p1    p12    p2
66     DI_Point *p1 = re->el->pt(0);
67     DI_Point *p2 = re->el->pt(1);
68     DI_Point *p3 = re->el->pt(2);
69     DI_Point *p4 = re->el->pt(3);
70     DI_Point *p12 = middle(p1, p2);
71     DI_Point *p23 = middle(p2, p3);
72     DI_Point *p34 = middle(p3, p4);
73     DI_Point *p14 = middle(p1, p4);
74     DI_Point *p1234 = middle(p12, p34);
75     DI_Quad *q0 = new DI_Quad(p1, p12, p1234, p14);
76     RecurElement *re0 = new RecurElement(q0);
77     recurCut(re0, maxlevel, level);
78     re->sub[0] = re0; re0->super = re;
79     DI_Quad *q1 = new DI_Quad(p12, p2, p23, p1234);
80     RecurElement *re1 = new RecurElement(q1);
81     recurCut(re1, maxlevel, level);
82     re->sub[1] = re1; re1->super = re;
83     DI_Quad *q2 = new DI_Quad(p1234, p23, p3, p34);
84     RecurElement *re2 = new RecurElement(q2);
85     recurCut(re2, maxlevel, level);
86     re->sub[2] = re2; re2->super = re;
87     DI_Quad *q3 = new DI_Quad(p14, p1234, p34, p4);
88     RecurElement *re3 = new RecurElement(q3);
89     recurCut(re3, maxlevel, level);
90     re->sub[3] = re3; re3->super = re;
91     delete p12; delete p23; delete p34;
92     delete p14; delete p1234;
93     delete q0; delete q1; delete q2; delete q3;
94   }
95   else if(re->type() == DI_TET) {
96     //       p4
97     //       p14   p34
98     //   p24 p1    p13    p3
99     //    p12   p23
100     // p2
101     DI_Point *p1 = re->el->pt(0);
102     DI_Point *p2 = re->el->pt(1);
103     DI_Point *p3 = re->el->pt(2);
104     DI_Point *p4 = re->el->pt(3);
105     DI_Point *p12 = middle(p1, p2);
106     DI_Point *p13 = middle(p1, p3);
107     DI_Point *p14 = middle(p1, p4);
108     DI_Point *p23 = middle(p2, p3);
109     DI_Point *p24 = middle(p2, p4);
110     DI_Point *p34 = middle(p3, p4);
111     DI_Tetra *t0 = new DI_Tetra(p1, p12, p13, p14);
112     RecurElement *re0 = new RecurElement(t0);
113     recurCut(re0, maxlevel, level);
114     re->sub[0] = re0; re0->super = re;
115     DI_Tetra *t1 = new DI_Tetra(p2, p23, p12, p24);
116     RecurElement *re1 = new RecurElement(t1);
117     recurCut(re1, maxlevel, level);
118     re->sub[1] = re1; re1->super = re;
119     DI_Tetra *t2 = new DI_Tetra(p3, p13, p23, p34);
120     RecurElement *re2 = new RecurElement(t2);
121     recurCut(re2, maxlevel, level);
122     re->sub[2] = re2; re2->super = re;
123     DI_Tetra *t3 = new DI_Tetra(p4, p14, p34, p24);
124     RecurElement *re3 = new RecurElement(t3);
125     recurCut(re3, maxlevel, level);
126     re->sub[3] = re3; re3->super = re;
127     DI_Tetra *t4 = new DI_Tetra(p12, p14, p24, p34);
128     RecurElement *re4 = new RecurElement(t4);
129     recurCut(re4, maxlevel, level);
130     re->sub[4] = re4; re4->super = re;
131     DI_Tetra *t5 = new DI_Tetra(p12, p23, p34, p24);
132     RecurElement *re5 = new RecurElement(t5);
133     recurCut(re5, maxlevel, level);
134     re->sub[5] = re5; re5->super = re;
135     DI_Tetra *t6 = new DI_Tetra(p12, p13, p34, p23);
136     RecurElement *re6 = new RecurElement(t6);
137     recurCut(re6, maxlevel, level);
138     re->sub[6] = re6; re6->super = re;
139     DI_Tetra *t7 = new DI_Tetra(p12, p13, p14, p34);
140     RecurElement *re7 = new RecurElement(t7);
141     recurCut(re7, maxlevel, level);
142     re->sub[7] = re7; re7->super = re;
143     delete p12; delete p13; delete p14;
144     delete p23; delete p24; delete p34;
145     delete t0; delete t1; delete t2; delete t3;
146     delete t4; delete t5; delete t6; delete t7;
147   }
148   else if(re->type() == DI_HEX) {
149     DI_Point *p1 = re->el->pt(0);
150     DI_Point *p2 = re->el->pt(1);
151     DI_Point *p3 = re->el->pt(2);
152     DI_Point *p4 = re->el->pt(3);
153     DI_Point *p5 = re->el->pt(4);
154     DI_Point *p6 = re->el->pt(5);
155     DI_Point *p7 = re->el->pt(6);
156     DI_Point *p8 = re->el->pt(7);
157     DI_Point *p12 = middle(p1, p2);
158     DI_Point *p14 = middle(p1, p4);
159     DI_Point *p15 = middle(p1, p5);
160     DI_Point *p23 = middle(p2, p3);
161     DI_Point *p26 = middle(p2, p6);
162     DI_Point *p34 = middle(p3, p4);
163     DI_Point *p37 = middle(p3, p7);
164     DI_Point *p48 = middle(p4, p8);
165     DI_Point *p56 = middle(p5, p6);
166     DI_Point *p58 = middle(p5, p8);
167     DI_Point *p67 = middle(p6, p7);
168     DI_Point *p78 = middle(p7, p8);
169     DI_Point *p1234 = middle(p12, p34);
170     DI_Point *p1256 = middle(p12, p56);
171     DI_Point *p1458 = middle(p14, p58);
172     DI_Point *p2367 = middle(p23, p67);
173     DI_Point *p3478 = middle(p34, p78);
174     DI_Point *p5678 = middle(p56, p78);
175     DI_Point *p12345678 = middle(p1234, p5678);
176     DI_Hexa *h0 = new DI_Hexa(p1, p12, p1234, p14, p15, p1256, p12345678, p1458);
177     RecurElement *re0 = new RecurElement(h0);
178     recurCut(re0, maxlevel, level);
179     re->sub[0] = re0; re0->super = re;
180     DI_Hexa *h1 = new DI_Hexa(p12, p2, p23, p1234, p1256, p26, p2367, p12345678);
181     RecurElement *re1 = new RecurElement(h1);
182     recurCut(re1, maxlevel, level);
183     re->sub[1] = re1; re1->super = re;
184     DI_Hexa *h2 = new DI_Hexa(p1234, p23, p3, p34, p12345678, p2367, p37, p3478);
185     RecurElement *re2 = new RecurElement(h2);
186     recurCut(re2, maxlevel, level);
187     re->sub[2] = re2; re2->super = re;
188     DI_Hexa *h3 = new DI_Hexa(p14, p1234, p34, p4, p1458, p12345678, p3478, p48);
189     RecurElement *re3 = new RecurElement(h3);
190     recurCut(re3, maxlevel, level);
191     re->sub[3] = re3; re3->super = re;
192     DI_Hexa *h4 = new DI_Hexa(p15, p1256, p12345678, p1458, p5, p56, p5678, p58);
193     RecurElement *re4 = new RecurElement(h4);
194     recurCut(re4, maxlevel, level);
195     re->sub[4] = re4; re4->super = re;
196     DI_Hexa *h5 = new DI_Hexa(p1256, p26, p2367, p12345678, p56, p6, p67, p5678);
197     RecurElement *re5 = new RecurElement(h5);
198     recurCut(re5, maxlevel, level);
199     re->sub[5] = re5; re5->super = re;
200     DI_Hexa *h6 = new DI_Hexa(p12345678, p2367, p37, p3478, p5678, p67, p7, p78);
201     RecurElement *re6 = new RecurElement(h6);
202     recurCut(re6, maxlevel, level);
203     re->sub[6] = re6; re6->super = re;
204     DI_Hexa *h7 = new DI_Hexa(p1458, p12345678, p3478, p48, p58, p5678, p78, p8);
205     RecurElement *re7 = new RecurElement(h7);
206     recurCut(re7, maxlevel, level);
207     re->sub[7] = re7; re7->super = re;
208     delete p12; delete p14; delete p15;
209     delete p23; delete p26; delete p34;
210     delete p37; delete p48; delete p56;
211     delete p58; delete p67; delete p78;
212     delete p1234; delete p1256;
213     delete p1458; delete p2367;
214     delete p3478; delete p5678;
215     delete p12345678;
216     delete h0; delete h1; delete h2; delete h3;
217     delete h4; delete h5; delete h6; delete h7;
218   }
219 }
220 
221 // return true if the element re->el is crossed or run along by a primitive levelset in RPN and by the final levelset
222 // (the levelset is computed with the values at the nodes of the element e)
signChange(RecurElement * re,const DI_Element * e,const std::vector<gLevelset * > & RPN,double ** nodeLs)223 bool signChange (RecurElement *re, const DI_Element *e, const std::vector<gLevelset *> &RPN,
224                  double **nodeLs) {
225   bool cS = false;
226   DI_Element* elem = re->root()->el;
227   std::vector<DI_CuttingPoint *> cp;
228   std::vector<gLevelset *> RPNi;
229   int iPrim = 0;
230   for(std::size_t l = 0; l < RPN.size(); l++) {
231     gLevelset *Lsi = RPN[l];
232     RPNi.push_back(Lsi);
233     if(Lsi->isPrimitive()) {
234       elem->addLs(e, Lsi, iPrim++, nodeLs);
235       for(std::size_t i = 0; i < cp.size(); i++)
236         cp[i]->addLs(elem);
237       if(re->super) re->el->addLs(elem);
238       re->el->getCuttingPoints(elem, RPNi, cp);
239     }
240     else {
241       for(std::size_t p = 0; p < cp.size(); p++)
242         cp[p]->chooseLs(Lsi);
243       if(re->super) re->el->chooseLs(Lsi);
244     }
245   }
246   re->root()->el->clearLs();
247   if(re->super) re->el->clearLs();
248 
249   if(cp.size() > 1 || (re->type() == DI_LIN && cp.size() > 0)) {
250     for(int i = 0; i < (int)cp.size(); i++)
251       if(cp[i]->ls() == 0) {cS = true; break;}
252   }
253   for(int i = 0; i < (int)cp.size(); i++)
254     delete cp[i];
255   return cS;
256 }
257 
258 // Set isCrossed to true if a sub RecurElement is crossed.
259 // If it has no sub RecurElement, set isCrossed to true if the element is crossed or run along by the levelset
260 //(the levelset is computed with the values at the nodes of the triangle e)
computeIsCrossed(RecurElement * re,const DI_Element * e,const std::vector<gLevelset * > & RPN,double ** nodeLs)261 bool computeIsCrossed (RecurElement *re, const DI_Element *e, const std::vector<gLevelset *> &RPN,
262                        double **nodeLs) {
263   if (!re->sub[0])
264     re->isCrossed = signChange(re, e, RPN, nodeLs);
265   else {
266     bool iC = computeIsCrossed(re->sub[0], e, RPN, nodeLs);
267     for(int i = 1; i < re->nbSub(); i++){
268       bool iCi = computeIsCrossed(re->sub[i], e, RPN, nodeLs);
269       iC = iC || iCi;
270     }
271     re->isCrossed = iC;
272   }
273   return re->isCrossed;
274 }
275 
276 // Recursively set the visibility to true if the RecurElement is crossed and has no sub RecurElement
277 // or if the RecurElement is not crossed and the super RecurElement is crossed.
recurChangeVisibility(RecurElement * re)278 void recurChangeVisibility(RecurElement *re){
279   bool superIC = (re->super) ? re->super->isCrossed : true;
280 
281   if((re->isCrossed && !re->sub[0]) || (!re->isCrossed && superIC)) {
282     re->visible = true;
283     return;
284   }
285   for(int i = 0; i < re->nbSub(); i++)
286     recurChangeVisibility(re->sub[i]);
287 }
288 
recurChangeVisibility(RecurElement * re,const std::vector<gLevelset * > & RPN,double TOL)289 void recurChangeVisibility(RecurElement *re, const std::vector<gLevelset *> &RPN, double TOL){
290   printf("rCV : "); re->el->printls();
291   if(!re->sub[0]){
292     re->visible = true;
293   }
294   else {
295     re->el->printls();
296     double v = re->ls();
297     double vm = 0.;
298     if(!re->sub[0]->sub[0]) {
299       for(int i = 0; i < re->nbSub(); i++){
300         vm += re->sub[i]->ls();
301       }
302       vm = vm / re->nbSub();
303     }
304     else {
305       for(int i = 0; i < re->nbSub(); i++){
306         for(int j = 0; j < re->sub[0]->nbSub(); j++){
307           vm += re->sub[i]->sub[j]->ls();
308         }
309       }
310       vm = vm / (re->nbSub()*re->sub[0]->nbSub());
311     }
312     if(fabs(v - vm) < TOL)
313       re->visible = true;
314     else {
315       for(int i = 0; i < re->nbSub(); i++)
316         recurChangeVisibility(re->sub[i], RPN, TOL);
317     }
318   }
319 }
320 
recurAddLs(RecurElement * re)321 void recurAddLs(RecurElement *re) {
322   if(re != re->root())
323     re->el->addLs(re->root()->el);
324   if(re->sub[0])
325     for(int i = 0; i < re->nbSub(); i++)
326       recurAddLs(re->sub[i]);
327 }
328 
recurClearLs(RecurElement * re)329 void recurClearLs(RecurElement *re) {
330   re->el->clearLs();
331   if(re->sub[0])
332     for(int i = 0; i < re->nbSub(); i++)
333       recurClearLs(re->sub[i]);
334 }
335 
RecurElement(const DI_Element * e)336 RecurElement::RecurElement(const DI_Element *e) : visible(false), isCrossed(false)
337 {
338   switch(e->type()) {
339     case DI_LIN :
340       el = new DI_Line(*((DI_Line*)e));
341       break;
342     case DI_TRI :
343       el = new DI_Triangle(*((DI_Triangle*)e));
344       break;
345     case DI_QUA :
346       el = new DI_Quad(*((DI_Quad*)e));
347       break;
348     case DI_TET :
349       el = new DI_Tetra(*((DI_Tetra*)e));
350       break;
351     case DI_HEX :
352       el = new DI_Hexa(*((DI_Hexa*)e));
353       break;
354     default :
355       el = NULL;
356   }
357   super = NULL;
358   sub = new RecurElement*[nbSub()];
359   for(int i = 0; i < nbSub(); i++)
360     sub[i] = NULL;
361 }
362 
~RecurElement()363 RecurElement::~RecurElement ()
364 {
365   for(int i = 0; i < nbSub(); i++)
366     if(sub[i]) delete sub[i];
367   delete [] sub;
368   if(el) delete el;
369 }
370 
nbSub() const371 int RecurElement::nbSub() const
372 {
373   switch(type()) {
374     case DI_LIN :
375       return 2;
376     case DI_TRI :
377       return 4;
378     case DI_QUA :
379       return 4;
380     case DI_TET :
381       return 8;
382     case DI_HEX :
383       return 8;
384     default :
385       return 0;
386   }
387 }
388 
root()389 RecurElement* RecurElement::root()
390 {
391   if(super) return super->root();
392   return this;
393 }
394 
ls() const395 double RecurElement::ls() const
396 {
397   double Tot = 0;
398   for(int i = 0; i < nbVert(); i++)
399     Tot += el->ls(i);
400   return Tot / nbVert();
401 }
402 
cut(int maxlevel,const DI_Element * e,std::vector<gLevelset * > & LsRPN,double TOL,double ** nodeLs)403 bool RecurElement::cut(int maxlevel, const DI_Element *e, std::vector<gLevelset *> &LsRPN,
404                        double TOL, double **nodeLs)
405 {
406   recurCut(this, maxlevel, 0);
407   bool iC = computeIsCrossed(root(), e, LsRPN, nodeLs);
408   if(TOL < 0.)
409     recurChangeVisibility(root());
410   else {
411     root()->el->addLs(e, LsRPN.back());
412     recurAddLs(root());
413     recurChangeVisibility(root(), LsRPN, TOL);
414     recurClearLs(root());
415   }
416   return iC;
417 }
418 
419 #endif
420