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