18 #include "transformable.h"
24 static const Rect H2D_UNITY = { 0, 0, ONE, ONE };
25 Traverse::Traverse(
bool master) : master(master)
29 static int get_split_and_sons(Element* e, Rect* cr, Rect* er, int4& sons)
31 uint64_t hmid = (er->l + er->r) >> 1;
32 uint64_t vmid = (er->t + er->b) >> 1;
36 if(cr->r <= hmid && cr->t <= vmid)
37 return (sons[0] = sons[1] = sons[2] = sons[3] = 0), 0;
38 else if(cr->l >= hmid && cr->t <= vmid)
39 return (sons[0] = sons[1] = sons[2] = sons[3] = 1), 0;
40 else if(cr->l >= hmid && cr->b >= vmid)
41 return (sons[0] = sons[1] = sons[2] = sons[3] = 2), 0;
42 else if(cr->r <= hmid && cr->b >= vmid)
43 return (sons[0] = sons[1] = sons[2] = sons[3] = 3), 0;
44 else if(cr->r <= hmid)
45 return (sons[0] = sons[1] = 0, sons[2] = sons[3] = 3), 1;
46 else if(cr->l >= hmid)
47 return (sons[0] = sons[1] = 1, sons[2] = sons[3] = 2), 1;
48 else if(cr->t <= vmid)
49 return (sons[0] = sons[3] = 0, sons[1] = sons[2] = 1), 2;
50 else if(cr->b >= vmid)
51 return (sons[0] = sons[3] = 3, sons[1] = sons[2] = 2), 2;
53 return (sons[0] = 0, sons[1] = 1, sons[2] = 2, sons[3] = 3), 3;
58 return (sons[0] = sons[1] = sons[2] = sons[3] = 4), 0;
59 else if(cr->b >= vmid)
60 return (sons[0] = sons[1] = sons[2] = sons[3] = 5), 0;
62 return (sons[0] = sons[1] = 4, sons[2] = sons[3] = 5), 1;
67 return (sons[0] = sons[1] = sons[2] = sons[3] = 6), 0;
68 else if(cr->l >= hmid)
69 return (sons[0] = sons[1] = sons[2] = sons[3] = 7), 0;
71 return (sons[0] = sons[3] = 6, sons[1] = sons[2] = 7), 2;
75 static void move_to_son(Rect* rnew, Rect* rold,
int son)
77 uint64_t hmid = (rold->l + rold->r) >> 1;
78 uint64_t vmid = (rold->t + rold->b) >> 1;
80 memcpy(rnew, rold,
sizeof(Rect));
84 case 0: rnew->r = hmid; rnew->t = vmid;
break;
85 case 1: rnew->l = hmid; rnew->t = vmid;
break;
86 case 2: rnew->l = hmid; rnew->b = vmid;
break;
87 case 3: rnew->r = hmid; rnew->b = vmid;
break;
88 case 4: rnew->t = vmid;
break;
89 case 5: rnew->b = vmid;
break;
90 case 6: rnew->r = hmid;
break;
91 case 7: rnew->l = hmid;
break;
95 void Traverse::init_transforms(Traverse::State* s,
int i)
98 memcpy(&r, s->er + i,
sizeof(Rect));
100 while (s->cr.l > r.l || s->cr.r < r.r || s->cr.b > r.b || s->cr.t < r.t)
102 uint64_t hmid = (r.l + r.r) >> 1;
103 uint64_t vmid = (r.t + r.b) >> 1;
106 if(s->cr.r <= hmid && s->cr.t <= vmid) son = 0;
107 else if(s->cr.l >= hmid && s->cr.t <= vmid) son = 1;
108 else if(s->cr.l >= hmid && s->cr.b >= vmid) son = 2;
109 else if(s->cr.r <= hmid && s->cr.b >= vmid) son = 3;
110 else if(s->cr.r <= hmid) son = 6;
111 else if(s->cr.l >= hmid) son = 7;
112 else if(s->cr.t <= vmid) son = 4;
113 else if(s->cr.b >= vmid) son = 5;
116 s->push_transform(son, i, s->rep->is_triangle());
117 move_to_son(&r, &r, son);
121 Traverse::State::State()
123 memset(
this, 0,
sizeof(Traverse::State));
124 for(
int i = 0; i < 4; i++)
127 for (
int i = 0; i < num; i++)
132 void Traverse::State::operator=(
const State * other)
140 this->num = other->num;
142 this->e =
new Element*[num];
143 this->sub_idx =
new uint64_t[num];
144 memcpy(this->e, other->e, num *
sizeof(Element*));
145 memcpy(this->sub_idx, other->sub_idx, num *
sizeof(uint64_t));
146 memcpy(this->bnd, other->bnd, 4 *
sizeof(
bool));
148 this->rep = other->rep;
149 this->visited = other->visited;
150 this->isurf = other->isurf;
151 this->isBnd = other->isBnd;
154 Traverse::State::~State()
162 void Traverse::State::push_transform(
int son,
int i,
bool is_triangle)
164 this->sub_idx[i] = (sub_idx[i] << 3) + son + 1;
172 case 0: bnd[1] =
false;
break;
173 case 1: bnd[2] =
false;
break;
174 case 2: bnd[0] =
false;
break;
179 memset(bnd, 0,
sizeof(bnd));
184 if(son != 0 && son != 1 && son != 4 && son != 6 && son != 7)
186 if(son != 1 && son != 2 && son != 7 && son != 4 && son != 5)
188 if(son != 2 && son != 3 && son != 5 && son != 6 && son != 7)
190 if(son != 3 && son != 0 && son != 6 && son != 4 && son != 5)
195 uint64_t Traverse::State::get_transform(
int i)
197 return this->sub_idx[i];
200 Traverse::State* Traverse::push_state(
int* top_by_ref)
202 int* top_f = (top_by_ref == NULL) ? &this->top : top_by_ref;
205 throw Hermes::Exceptions::Exception(
"Stack overflow. Increase stack size.");
207 if(stack[*top_f].e == NULL)
209 stack[*top_f].e =
new Element*[num];
210 stack[*top_f].er =
new Rect[num];
211 stack[*top_f].sub_idx =
new uint64_t[num];
214 stack[*top_f].visited =
false;
215 stack[*top_f].isurf = -1;
216 memset(stack[*top_f].sub_idx, 0, num *
sizeof(uint64_t));
217 for(
int i = 0; i < 4; i++)
218 stack[*top_f].bnd[i] =
true;
219 stack[*top_f].num = this->num;
221 return stack + (*top_f)++;
224 void Traverse::set_boundary_info(State* s)
227 for (
int i = 0; i < num; i++)
228 if((e = s->e[i]) != NULL)
break;
230 if(s->rep->is_triangle())
232 for (
int i = 0; i < 3; i++)
233 (s->bnd[i] = (s->bnd[i] && e->en[i]->bnd));
234 s->isBnd = s->bnd[0] || s->bnd[1] || s->bnd[2] || e->vn[0]->bnd || e->vn[1]->bnd || e->vn[2]->bnd;
238 s->bnd[0] = s->bnd[0] && (s->cr.b == 0) && e->en[0]->bnd;
239 s->bnd[1] = s->bnd[1] && (s->cr.r == ONE) && e->en[1]->bnd;
240 s->bnd[2] = s->bnd[2] && (s->cr.t == ONE) && e->en[2]->bnd;
241 s->bnd[3] = s->bnd[3] && (s->cr.l == 0) && e->en[3]->bnd;
242 s->isBnd = s->bnd[0] || s->bnd[1] || s->bnd[2] || s->bnd[3] || e->vn[0]->bnd || e->vn[1]->bnd || e->vn[2]->bnd || e->vn[3]->bnd;
246 int Traverse::get_num_states(Hermes::vector<const Mesh*> meshes)
251 this->num = meshes.size();
252 this->begin(num, &meshes.front());
262 while (top > 0 && (s = stack + top-1)->visited)
279 if(
id >= meshes[0]->get_num_base_elements())
287 for (i = 0; i < num; i++)
290 s->e[i] = meshes[i]->get_element(
id);
298 s->er[i] = H2D_UNITY;
310 if(s->rep->is_triangle())
311 for (i = 0; i < 3; i++)
317 for (i = 0; i < num; i++)
321 if(s->sub_idx[i] == 0 && s->e[i]->active)
322 if(!s->rep->is_triangle())
323 init_transforms(s, i);
328 for (i = 0; i < num; i++)
346 if(s->rep->is_triangle())
349 for (son = 0; son <= 3; son++)
351 State* ns = push_state();
353 for (i = 0; i < num; i++)
360 else if(s->e[i]->active)
364 ns->sub_idx[i] = s->sub_idx[i];
365 ns->push_transform(son, i,
true);
370 ns->e[i] = s->e[i]->sons[son];
382 memcpy(ns->bnd, s->bnd,
sizeof(ns->bnd));
386 case 0: ns->bnd[1] =
false;
break;
387 case 1: ns->bnd[2] =
false;
break;
388 case 2: ns->bnd[0] =
false;
break;
393 memset(ns->bnd, 0,
sizeof(ns->bnd));
401 int4* current_sons =
new int4[num];
403 for (i = 0; i < num; i++)
404 if(s->e[i] != NULL && !s->e[i]->active)
405 split |= get_split_and_sons(s->e[i], &s->cr, s->er + i, current_sons[i]);
410 for (son = 0; son <= 3; son++)
412 State* ns = push_state();
414 move_to_son(&ns->cr, &s->cr, son);
416 for (i = 0; i < num; i++)
427 ns->sub_idx[i] = s->sub_idx[i];
428 ns->push_transform(son, i);
432 ns->e[i] = s->e[i]->sons[current_sons[i][son] & 3];
434 move_to_son(ns->er + i, s->er + i, current_sons[i][son]);
447 int son0 = 4, son1 = 5;
448 if(split == 2) { son0 = 6; son1 = 7; }
450 for (son = son0; son <= son1; son++)
452 State* ns = push_state();
453 move_to_son(&ns->cr, &s->cr, son);
455 int j = (son == 4 || son == 6) ? 0 : 2;
456 for (i = 0; i < num; i++)
467 ns->sub_idx[i] = s->sub_idx[i];
468 ns->push_transform(son, i);
472 ns->e[i] = s->e[i]->sons[current_sons[i][j] & 3];
473 move_to_son(ns->er + i, s->er + i, current_sons[i][j]);
487 State* ns = push_state();
488 memcpy(&ns->cr, &s->cr,
sizeof(Rect));
490 for (i = 0; i < num; i++)
496 else if(s->e[i]->active)
499 memcpy(&ns->er[i], &ns->cr,
sizeof(Rect));
503 ns->e[i] = s->e[i]->sons[current_sons[i][0] & 3];
504 move_to_son(ns->er + i, s->er + i, current_sons[i][0]);
512 delete [] current_sons;
518 Traverse::State* Traverse::get_next_state(
int* top_by_ref,
int* id_by_ref)
521 int* top_f = (top_by_ref == NULL) ? &this->top : top_by_ref;
522 int* id_f = (id_by_ref == NULL) ? &this->
id : id_by_ref;
532 while (*top_f > 0 && (s = stack + (*top_f)-1)->visited)
543 s = push_state(top_f);
549 if(*id_f >= meshes[0]->get_num_base_elements())
553 for (i = 0; i < num; i++)
556 s->e[i] = meshes[i]->get_element(*id_f);
564 s->er[i] = H2D_UNITY;
576 if(s->rep->is_triangle())
577 for (i = 0; i < 3; i++)
583 for (i = 0; i < num; i++)
587 if(s->sub_idx[i] == 0 && s->e[i]->active)
588 if(!s->rep->is_triangle())
589 init_transforms(s, i);
594 for (i = 0; i < num; i++)
608 for (i = 0; i < num; i++)
614 set_boundary_info(s);
619 if(s->rep->is_triangle())
622 for (son = 0; son <= 3; son++)
624 State* ns = push_state(top_f);
626 for (i = 0; i < num; i++)
633 else if(s->e[i]->active)
637 ns->sub_idx[i] = s->sub_idx[i];
638 ns->push_transform(son, i,
true);
643 ns->e[i] = s->e[i]->sons[son];
655 memcpy(ns->bnd, s->bnd,
sizeof(ns->bnd));
659 case 0: ns->bnd[1] =
false;
break;
660 case 1: ns->bnd[2] =
false;
break;
661 case 2: ns->bnd[0] =
false;
break;
666 memset(ns->bnd, 0,
sizeof(ns->bnd));
675 int4* current_sons =
new int4[num];
676 for (i = 0; i < num; i++)
677 if(s->e[i] != NULL && !s->e[i]->active)
678 split |= get_split_and_sons(s->e[i], &s->cr, s->er + i, current_sons[i]);
683 for (son = 0; son <= 3; son++)
685 State* ns = push_state(top_f);
687 move_to_son(&ns->cr, &s->cr, son);
689 for (i = 0; i < num; i++)
695 else if(s->e[i]->active)
698 ns->sub_idx[i] = s->sub_idx[i];
699 ns->push_transform(son, i);
703 ns->e[i] = s->e[i]->sons[current_sons[i][son] & 3];
705 move_to_son(ns->er + i, s->er + i, current_sons[i][son]);
717 int son0 = 4, son1 = 5;
718 if(split == 2) { son0 = 6; son1 = 7; }
720 for (son = son0; son <= son1; son++)
722 State* ns = push_state(top_f);
723 move_to_son(&ns->cr, &s->cr, son);
725 int j = (son == 4 || son == 6) ? 0 : 2;
726 for (i = 0; i < num; i++)
737 ns->sub_idx[i] = s->sub_idx[i];
738 ns->push_transform(son, i);
742 ns->e[i] = s->e[i]->sons[current_sons[i][j] & 3];
743 move_to_son(ns->er + i, s->er + i, current_sons[i][j]);
757 State* ns = push_state(top_f);
758 memcpy(&ns->cr, &s->cr,
sizeof(Rect));
760 for (i = 0; i < num; i++)
766 else if(s->e[i]->active)
769 memcpy(&ns->er[i], &ns->cr,
sizeof(Rect));
773 ns->e[i] = s->e[i]->sons[current_sons[i][0] & 3];
774 move_to_son(ns->er + i, s->er + i, current_sons[i][0]);
782 delete [] current_sons;
787 void Traverse::begin(
int n,
const Mesh** meshes, Transformable** fn)
794 this->meshes = meshes;
800 stack =
new State[size];
801 memset(stack, 0, size *
sizeof(State));
803 sons =
new int4[num];
804 subs =
new uint64_t[num];
810 int base_elem_num = meshes[0]->get_num_base_elements();
811 for (
int i = 1; i < n; i++)
812 if(base_elem_num != meshes[i]->get_num_base_elements())
813 throw Hermes::Exceptions::Exception(
"Meshes not compatible in Traverse::begin().");
817 double *areas =
new double[base_elem_num];
818 memset(areas, 0, base_elem_num*
sizeof(
double));
823 double min_elem_area = 1e30;
824 for_all_base_elements_incl_inactive(e, meshes[0])
827 areas[counter] = 0.0;
830 areas[counter] = e->get_area();
831 if(areas[counter] < min_elem_area)
832 min_elem_area = areas[counter];
838 double tolerance = min_elem_area/100.;
840 if(min_elem_area < 0)
841 throw Exceptions::ValueException(
"min_elem_area", 0.0, 1e-10);
843 for (
int i = 1; i < n; i++)
846 for_all_base_elements_incl_inactive(e, meshes[i])
849 if(fabs(areas[counter] - e->get_area()) > tolerance && areas[counter] > 1e-15)
851 this->info(
"counter = %d, area_1 = %g, area_2 = %g.\n", counter, areas[counter], e->get_area());
852 throw Hermes::Exceptions::Exception(
"Meshes not compatible in Traverse::begin().");
861 void Traverse::free_state(Traverse::State* state)
865 delete [] state->sub_idx;
866 memset(state, 0,
sizeof(Traverse::State));
869 void Traverse::finish()
876 if(stack == NULL)
return;
878 for (
int i = 0; i < size; i++)
879 if(stack[i].e != NULL)
880 free_state(stack + i);
887 uint64_t Traverse::init_idx(Rect* cr, Rect* er)
890 memcpy(&r, er,
sizeof(Rect));
893 while (cr->l > r.l || cr->r < r.r || cr->b > r.b || cr->t < r.t)
895 uint64_t hmid = (r.l + r.r) >> 1;
896 uint64_t vmid = (r.t + r.b) >> 1;
899 if(cr->r <= hmid && cr->t <= vmid) { son = 0; r.r = hmid; r.t = vmid; }
900 else if(cr->l >= hmid && cr->t <= vmid) { son = 1; r.l = hmid; r.t = vmid; }
901 else if(cr->l >= hmid && cr->b >= vmid) { son = 2; r.l = hmid; r.b = vmid; }
902 else if(cr->r <= hmid && cr->b >= vmid) { son = 3; r.r = hmid; r.b = vmid; }
903 else if(cr->t <= vmid) { son = 4; r.t = vmid; }
904 else if(cr->b >= vmid) { son = 5; r.b = vmid; }
905 else if(cr->r <= hmid) { son = 6; r.r = hmid; }
906 else if(cr->l >= hmid) { son = 7; r.l = hmid; }
909 idx = (idx << 3) + son + 1;
914 void Traverse::union_recurrent(Rect* cr, Element** e, Rect* er, uint64_t* idx, Element* uni)
920 for (i = 0; i < num; i++)
930 if(udsize <= uni->
id)
932 if(!udsize) udsize = 1024;
933 while (udsize <= uni->
id) udsize *= 2;
934 for (i = 0; i < num; i++)
935 unidata[i] = (UniData*) realloc(unidata[i], udsize *
sizeof(UniData));
937 for (i = 0; i < num; i++)
939 unidata[i][uni->id].e = e[i];
940 unidata[i][uni->id].idx = idx[i];
946 Element** e_new =
new Element*[num];
947 Rect* er_new =
new Rect[num];
950 int4* sons =
new int4[num];
951 uint64_t* idx_new =
new uint64_t[num];
952 memcpy(idx_new, idx, num*
sizeof(uint64_t));
958 for (son = 0; son <= 3; son++)
960 for (i = 0; i < num; i++)
965 idx_new[i] = (idx[i] << 3) + son + 1;
967 e_new[i] = e[i]->sons[son];
969 union_recurrent(NULL, e_new, NULL, idx_new, uni->sons[son]);
976 for (i = 0; i < num; i++)
978 split |= get_split_and_sons(e[i], cr, er + i, sons[i]);
985 for (son = 0; son <= 3; son++)
987 move_to_son(&cr_new, cr, son);
988 for (i = 0; i < num; i++)
993 idx_new[i] = (idx[i] << 3) + son + 1;
996 e_new[i] = e[i]->sons[sons[i][son] & 3];
997 move_to_son(&(er_new[i]), er + i, sons[i][son]);
998 if(e_new[i]->active) idx_new[i] = init_idx(&cr_new, &(er_new[i]));
1001 union_recurrent(&cr_new, e_new, er_new, idx_new, uni->sons[son]);
1009 int son0 = 4, son1 = 5;
1010 if(split == 2) { son0 = 6; son1 = 7; }
1012 for (son = son0; son <= son1; son++)
1014 move_to_son(&cr_new, cr, son);
1015 j = (son == 4 || son == 6) ? 0 : 2;
1016 for (i = 0; i < num; i++)
1021 idx_new[i] = (idx[i] << 3) + son + 1;
1024 e_new[i] = e[i]->sons[sons[i][j] & 3];
1025 move_to_son(&(er_new[i]), er + i, sons[i][j]);
1026 if(e_new[i]->active) idx_new[i] = init_idx(&cr_new, &(er_new[i]));
1029 union_recurrent(&cr_new, e_new, er_new, idx_new, uni->sons[son & 3]);
1035 memcpy(&cr_new, cr,
sizeof(Rect));
1036 for (i = 0; i < num; i++)
1042 e_new[i] = e[i]->sons[sons[i][0] & 3];
1043 move_to_son(&(er_new[i]), er + i, sons[i][0]);
1044 if(e_new[i]->active) idx_new[i] = init_idx(&cr_new, &(er_new[i]));
1047 union_recurrent(&cr_new, e_new, er_new, idx_new, uni);
1057 UniData** Traverse::construct_union_mesh(Mesh* unimesh)
1060 Element** e =
new Element*[num];
1061 Rect* er =
new Rect[num];
1064 this->unimesh = unimesh;
1065 unimesh->copy_base(const_cast<Mesh*>(meshes[0]));
1068 unidata =
new UniData*[num];
1069 memset(unidata, 0,
sizeof(UniData*) * num);
1071 uint64_t* idx =
new uint64_t[num];
1072 memset(idx, 0, num*
sizeof(uint64_t));
1074 for (
id = 0;
id < meshes[0]->get_num_base_elements();
id++)
1076 for (i = 0; i < num; i++)
1078 e[i] = meshes[i]->get_element(
id);
1079 static const Rect H2D_UNITY = { 0, 0, ONE, ONE };
1080 cr = er[i] = H2D_UNITY;
1083 tri = base->is_triangle();
1084 union_recurrent(&cr, e, er, idx, unimesh->get_element(
id));