29 { is_adapted =
false; }
31 void mesh_im_level_set::clear_build_methods() {
32 for (
size_type i = 0; i < build_methods.size(); ++i)
33 del_stored_object(build_methods[i]);
34 build_methods.clear();
38 void mesh_im_level_set::clear(
void) {
40 clear_build_methods();
44 void mesh_im_level_set::init_with_mls(mesh_level_set &me,
46 pintegration_method reg,
47 pintegration_method sing) {
48 init_with_mesh(me.linked_mesh());
49 cut_im.init_with_mesh(me.linked_mesh());
51 integrate_where = integrate_where_;
53 this->add_dependency(*mls);
59 pintegration_method reg,
60 pintegration_method sing) {
62 init_with_mls(me, integrate_where_, reg, sing);
65 mesh_im_level_set::mesh_im_level_set(
void)
66 { mls = 0; is_adapted =
false; }
75 if (ignored_im.is_in(cv))
82 DAL_SIMPLE_KEY(special_imls_key, papprox_integration);
85 mesh_im_level_set::bool2 mesh_im_level_set::is_point_in_selected_area2
86 (
const std::vector<pmesher_signed_distance> &mesherls0,
87 const std::vector<pmesher_signed_distance> &mesherls1,
92 isin = isin && ((*(mesherls0[i]))(P) < 0);
93 if (gmm::abs((*(mesherls0[i]))(P)) < 1e-7)
95 if (mls->get_level_set(i)->has_secondary())
96 isin = isin && ((*(mesherls1[i]))(P) < 0);
99 b.in = ((integrate_where & INTEGRATE_OUTSIDE)) ? !isin : isin;
109 typedef mesh_im_level_set::bool2 bool2;
110 bool2 do_expr(
const char *&s) {
114 GMM_ASSERT1(*s++ ==
')',
115 "expecting ')' in csg expression at '" << s-1 <<
"'");
116 }
else if (*s ==
'!') {
117 r = do_expr(++s); r.in = !r.in;
118 }
else if (*s >=
'a' && *s <=
'z') {
119 unsigned idx = (*s) -
'a';
120 r.in = in.is_in(idx);
121 r.bin = bin.is_in(idx) ? idx+1 : 0;
124 GMM_ASSERT1(
false,
"parse error in csg expression at '" << s <<
"'");
127 bool2 a = r, b = do_expr(++s);
130 if (b.bin && !a.in) r.bin = b.bin;
131 else if (a.bin && !b.in) r.bin = a.bin;
133 }
else if (*s ==
'-') {
134 bool2 a = r, b = do_expr(++s);
135 r.in = a.in && !b.in;
136 if (a.bin && !b.in) r.bin = a.bin;
137 else if (a.in && b.bin) r.bin = b.bin;
139 }
else if (*s ==
'*') {
140 bool2 a = r, b = do_expr(++s);
142 if (a.bin && b.in) r.bin = a.bin;
143 else if (a.in && b.bin) r.bin = b.bin;
148 bool2 is_in(
const char*s) {
149 bool2 b = do_expr(s);
150 GMM_ASSERT1(!(*s),
"parse error in CSG expression at " << s);
154 const char *s[] = {
"a*b*c*d",
162 for (
const char **p = s; *p; ++p)
164 for (
unsigned c=0; c < 16; ++c) {
165 in[0] = (c&1); bin[0] = 1;
166 in[1] = (c&2); bin[1] = 1;
167 in[2] = (c&4); bin[2] = 1;
168 in[3] = (c&8); bin[3] = 1;
169 cerr << in[0] << in[1] << in[2] << in[3] <<
": ";
170 for (
const char **p = s; *p; ++p) {
172 cerr << b.in <<
"/" << b.bin <<
" ";
179 mesh_im_level_set::bool2
180 mesh_im_level_set::is_point_in_selected_area
181 (
const std::vector<pmesher_signed_distance> &mesherls0,
182 const std::vector<pmesher_signed_distance> &mesherls1,
183 const base_node& P) {
186 bool sec = mls->get_level_set(i)->has_secondary();
187 scalar_type d1 = (*(mesherls0[i]))(P);
188 scalar_type d2 = (sec ? (*(mesherls1[i]))(P) : -1);
189 if (d1 < 0 && d2 < 0) ev.in.add(i);
193 if (gmm::abs(d1) < 1e-7 && d2 < 1e-7)
199 if (ls_csg_description.size())
200 r = ev.is_in(ls_csg_description.c_str());
203 r.bin = (ev.bin.card() >= 1 && ev.in.card() >= mls->
nb_level_sets()-1);
206 if (integrate_where & INTEGRATE_OUTSIDE) r.in = !(r.in);
221 void mesh_im_level_set::build_method_of_convex(
size_type cv) {
222 const mesh &msh(mls->mesh_of_convex(cv));
223 GMM_ASSERT3(msh.convex_index().card() != 0,
"Internal error");
227 std::vector<pmesher_signed_distance> mesherls0(mls->
nb_level_sets());
228 std::vector<pmesher_signed_distance> mesherls1(mls->
nb_level_sets());
229 dal::bit_vector convexes_arein;
233 mesherls0[i] = mls->get_level_set(i)->mls_of_convex(cv, 0,
false);
234 if (mls->get_level_set(i)->has_secondary())
235 mesherls1[i] = mls->get_level_set(i)->mls_of_convex(cv, 1,
false);
238 if (integrate_where != (INTEGRATE_ALL)) {
239 for (dal::bv_visitor scv(msh.convex_index()); !scv.finished(); ++scv) {
240 B = gmm::mean_value(msh.points_of_convex(scv));
241 convexes_arein[scv] =
242 is_point_in_selected_area(mesherls0, mesherls1, B).in;
248 = msh.trans_of_convex(msh.convex_index().first_true());
249 dim_type n = pgt->dim();
251 if (base_singular_pim) GMM_ASSERT1
256 && (n >= 2) && (n <= 3),
257 "Base integration method for quasi polar integration not convenient");
259 auto new_approx = std::make_shared<approx_integration>(pgt->convex_ref());
260 new_approx->set_built_on_the_fly();
261 base_matrix KK(n,n), CS(n,n);
262 base_matrix pc(pgt2->nb_points(), n);
263 std::vector<size_type> ptsing;
267 for (dal::bv_visitor i(msh.convex_index()); !i.finished(); ++i) {
268 papprox_integration pai = regular_simplex_pim->approx_method();
270 GMM_ASSERT1(regular_simplex_pim->structure() ==
bgeot::simplex_structure(n),
"Base integration method should be defined on a simplex of same dimension than the mesh");
272 if ((integrate_where != INTEGRATE_ALL) &&
273 !convexes_arein[i])
continue;
275 if (base_singular_pim && mls->crack_tip_convexes().is_in(cv)) {
277 unsigned sing_ls = unsigned(-1);
280 if (mls->get_level_set(ils)->has_secondary()) {
281 for (
unsigned ipt = 0; ipt <= n; ++ipt) {
282 if (gmm::abs((*(mesherls0[ils]))(msh.points_of_convex(i)[ipt]))
284 && gmm::abs((*(mesherls1[ils]))(msh.points_of_convex(i)[ipt]))
286 if (sing_ls ==
unsigned(-1)) sing_ls = ils;
287 GMM_ASSERT1(sing_ls == ils,
"Two singular point in one "
288 "sub element : " << sing_ls <<
", " << ils <<
290 ptsing.push_back(ipt);
294 assert(ptsing.size() < n);
296 if (ptsing.size() > 0) {
297 std::stringstream sts;
299 <<
", " << ptsing[0];
300 if (ptsing.size() > 1) sts <<
", " << ptsing[1];
307 vectors_to_base_matrix(G2,
linked_mesh().points_of_convex(cv));
309 cc(
linked_mesh().trans_of_convex(cv), pai->point(0), G2);
311 if (integrate_where & (INTEGRATE_INSIDE | INTEGRATE_OUTSIDE)) {
313 vectors_to_base_matrix(G, msh.points_of_convex(i));
317 for (
size_type j = 0; j < pai->nb_points_on_convex(); ++j) {
318 c.set_xref(pai->point(j));
319 pgt2->poly_vector_grad(pai->point(j), pc);
321 scalar_type J = gmm::lu_det(KK);
322 new_approx->add_point(c.xreal(), pai->coeff(j) * gmm::abs(J));
334 for (
short_type f = 0; f < pgt2->structure()->nb_faces(); ++f) {
336 unsigned isin = unsigned(-1);
338 if (integrate_where == INTEGRATE_BOUNDARY) {
340 for (
unsigned ipt = 0; ipt <
341 pgt2->structure()->nb_points_of_face(f); ++ipt) {
342 const base_node &P = msh.points_of_face_of_convex(i, f)[ipt];
343 isin = is_point_in_selected_area(mesherls0, mesherls1, P).bin;
345 if (!isin) { lisin =
false;
break; }
347 if (!lisin)
continue;
350 B = gmm::mean_value(msh.points_of_face_of_convex(i, f));
351 if (pgt->convex_ref()->is_in(B) < -1E-7)
continue;
352 for (
short_type fi = 0; fi < pgt->structure()->nb_faces(); ++fi) {
353 if (gmm::abs(pgt->convex_ref()->is_in_face(fi, B)) < 2E-6) ff = fi;
357 cout <<
"Distance to the element : "
358 << pgt->convex_ref()->is_in(B) << endl;
359 for (
short_type fi = 0; fi < pgt->structure()->nb_faces(); ++fi) {
360 cout <<
"Distance to face " << fi <<
" : "
361 << gmm::abs(pgt->convex_ref()->is_in_face(fi, B)) << endl;
363 GMM_ASSERT3(
false,
"the point is neither in the interior nor "
364 "the boundary of the element");
368 vectors_to_base_matrix(G, msh.points_of_convex(i));
373 for (
size_type j = 0; j < pai->nb_points_on_face(f); ++j) {
374 if (gmm::abs(c.J()) > 1E-11) {
375 c.set_xref(pai->point_on_face(f, j));
376 base_small_vector un = pgt2->normals()[f], up(msh.dim());
377 gmm::mult(c.B(), un, up);
381 if (integrate_where == INTEGRATE_BOUNDARY) {
382 cc.set_xref(c.xreal());
383 mesherls0[isin]->grad(c.xreal(), un);
385 gmm::mult(cc.B(), un, up);
388 new_approx->add_point(c.xreal(), pai->coeff_on_face(f, j)
389 * gmm::abs(c.J()) * nup * nnup, ff);
395 if (new_approx->nb_points()) {
396 new_approx->valid_method();
398 pim = std::make_shared<integration_method>(new_approx);
399 dal::pstatic_stored_object_key
400 pk = std::make_shared<special_imls_key>(new_approx);
402 new_approx->pintegration_points());
403 build_methods.push_back(pim);
409 GMM_ASSERT1(linked_mesh_ != 0,
"mesh level set uninitialized");
411 clear_build_methods();
414 !cv.finished(); ++cv) {
415 if (mls->is_convex_cut(cv)) build_method_of_convex(cv);
421 if (integrate_where == INTEGRATE_BOUNDARY) {
423 }
else if (integrate_where != (INTEGRATE_OUTSIDE|INTEGRATE_INSIDE)) {
425 std::vector<pmesher_signed_distance> mesherls0(mls->
nb_level_sets());
426 std::vector<pmesher_signed_distance> mesherls1(mls->
nb_level_sets());
428 mesherls0[i] = mls->get_level_set(i)->mls_of_convex(cv, 0,
false);
429 if (mls->get_level_set(i)->has_secondary())
430 mesherls1[i] = mls->get_level_set(i)->mls_of_convex(cv,1,
false);
433 base_node B(gmm::mean_value(
linked_mesh().trans_of_convex(cv)
434 ->convex_ref()->points()));
435 if (!is_point_in_selected_area(mesherls0, mesherls1, B).in)
440 is_adapted =
true; touch();
444 void mesh_im_level_set::compute_normal_vector
447 std::vector<pmesher_signed_distance> mesherls0(nb_ls);
449 base_small_vector un(ctx.pgt()->dim());
452 gmm::clear(vec);
return;
453 }
else if (nb_ls == 1) {
455 = mls->get_level_set(0)->mls_of_convex(ctx.
convex_num(), 0,
false);
457 scalar_type d_min(0);
458 for (
unsigned i = 0; i < nb_ls; ++i) {
460 = mls->get_level_set(i)->mls_of_convex(ctx.
convex_num(), 0,
false);
461 scalar_type d = gmm::abs((*(mesherls0[i]))(ctx.
xref()));
462 if (i == 0 || d < d_min) { d_min = d; j = i; }
465 mesherls0[j]->grad(ctx.
xref(), un);
466 gmm::mult(ctx.B(), un, vec);
468 if (no != scalar_type(0))
469 gmm::scale(vec, scalar_type(1) / gmm::vect_norm2(vec));
475 { is_adapted =
false; }
477 void mesh_im_cross_level_set::clear_build_methods() {
478 for (
size_type i = 0; i < build_methods.size(); ++i)
479 if (build_methods[i].get()) del_stored_object(build_methods[i]);
480 build_methods.clear();
484 void mesh_im_cross_level_set::clear(
void)
485 { mesh_im::clear(); clear_build_methods(); is_adapted =
false; }
487 void mesh_im_cross_level_set::init_with_mls(mesh_level_set &me,
489 pintegration_method pim) {
490 init_with_mesh(me.linked_mesh());
491 cut_im.init_with_mesh(me.linked_mesh());
493 ind_ls1 = ind_ls1_; ind_ls2 = ind_ls2_;
495 this->add_dependency(*mls);
499 mesh_im_cross_level_set::mesh_im_cross_level_set(mesh_level_set &me,
501 pintegration_method pim)
502 { mls = 0; init_with_mls(me, ind_ls1_, ind_ls2_, pim); }
504 mesh_im_cross_level_set::mesh_im_cross_level_set(
void)
505 { mls = 0; is_adapted =
false; }
520 static bool is_point_in_intersection
521 (
const std::vector<pmesher_signed_distance> &mesherls0,
522 const std::vector<pmesher_signed_distance> &mesherls1,
523 const base_node& P) {
526 for (
unsigned i = 0; i < mesherls0.size(); ++i) {
527 bool sec = (
dynamic_cast<const mesher_level_set *
>(mesherls1[i].get()))->is_initialized();
528 scalar_type d1 = (*(mesherls0[i]))(P);
529 scalar_type d2 = (sec ? (*(mesherls1[i]))(P) : -1);
530 if (!(gmm::abs(d1) < 1e-7 && d2 < 1e-7)) r =
false;
535 static bool is_edges_intersect(
const base_node &PP1,
const base_node &PP2,
536 const base_node &PR1,
const base_node &PR2) {
537 size_type n = gmm::vect_size(PP1), k1 = 0;
538 scalar_type c1 = scalar_type(0);
539 base_node V = PR2 - PR1;
541 if (gmm::abs(V[k]) > gmm::abs(c1)) { c1 = V[k]; k1 = k; }
543 scalar_type alpha1 = (PP1[k1] - PR1[k1]) / c1;
544 scalar_type alpha2 = (PP2[k1] - PR1[k1]) / c1;
545 base_node W1 = PP1 - PR1 - alpha1 * V;
546 base_node W2 = PP2 - PR1 - alpha2 * V;
549 if (alpha1 > 1.-1e-7 && alpha2 > 1.-1e-7)
return false;
550 if (alpha1 < 1e-7 && alpha2 < 1e-7)
return false;
555 void mesh_im_cross_level_set::build_method_of_convex
557 const mesh &msh(mls->mesh_of_convex(cv));
558 GMM_ASSERT3(msh.convex_index().card() != 0,
"Internal error");
562 std::vector<pmesher_signed_distance> mesherls0(2);
563 std::vector<pmesher_signed_distance> mesherls1(2);
564 dal::bit_vector convexes_arein;
566 mesherls0[0] = mls->get_level_set(ind_ls1)->mls_of_convex(cv, 0,
false);
567 mesherls0[1] = mls->get_level_set(ind_ls2)->mls_of_convex(cv, 0,
false);
568 if (mls->get_level_set(ind_ls1)->has_secondary())
569 mesherls1[0] = mls->get_level_set(ind_ls1)->mls_of_convex(cv, 1,
false);
570 if (mls->get_level_set(ind_ls2)->has_secondary())
571 mesherls1[1] = mls->get_level_set(ind_ls2)->mls_of_convex(cv, 1,
false);
575 = msh.trans_of_convex(msh.convex_index().first_true());
576 dim_type n = pgt->dim();
578 auto new_approx = std::make_shared<approx_integration>(pgt->convex_ref());
579 new_approx->set_built_on_the_fly();
580 base_matrix KK(n,n), CS(n,n);
581 base_matrix pc(pgt2->nb_points(), n);
582 std::vector<size_type> ptsing;
584 for (dal::bv_visitor i(msh.convex_index()); !i.finished(); ++i) {
585 papprox_integration pai = segment_pim->approx_method();
586 GMM_ASSERT1(gmm::vect_size(pai->point(0)) == 1,
587 "A segment integration method is needed");
590 vectors_to_base_matrix(G2,
linked_mesh().points_of_convex(cv));
592 cc(
linked_mesh().trans_of_convex(cv), base_node(n), G2);
594 dal::bit_vector ptinter;
596 size_type ipt = msh.structure_of_convex(i)->ind_dir_points()[k];
597 const base_node &P = msh.points_of_convex(i)[ipt];
598 if (is_point_in_intersection(mesherls0, mesherls1, P))
605 size_type ipt = msh.structure_of_convex(i)->ind_dir_points()[k];
606 if (ptinter.is_in(ipt)) {
608 const base_node &P = msh.points_of_convex(i)[ipt];
611 if (global_intersection.search_point(cc.xreal())
613 global_intersection.add_point(cc.xreal());
614 new_approx->add_point(msh.points_of_convex(i)[ipt],
624 size_type ipt1 = msh.structure_of_convex(i)->ind_dir_points()[k1];
626 size_type ipt2=msh.structure_of_convex(i)->ind_dir_points()[k2];
627 if (ptinter.is_in(ipt1) && ptinter.is_in(ipt2)) {
629 const base_node &P1 = msh.points_of_convex(i)[ipt1];
630 const base_node &P2 = msh.points_of_convex(i)[ipt2];
632 base_node PR1 = cc.xreal();
634 base_node PR2 = cc.xreal();
636 size_type i1 = global_intersection.search_point(PR1);
637 size_type i2 = global_intersection.search_point(PR2);
640 !global_intersection.nb_convex_with_edge(i1, i2)) {
642 base_node min(n), max(n);
644 min[k] = std::min(PR1[k], PR2[k]);
645 max[k] = std::max(PR1[k], PR2[k]);
647 bgeot::rtree::pbox_set boxlst;
648 rtree_seg.find_intersecting_boxes(min, max, boxlst);
650 bool found_intersect =
false;
652 for (bgeot::rtree::pbox_set::const_iterator
653 it=boxlst.begin(); it != boxlst.end(); ++it) {
655 = global_intersection.points_of_convex((*it)->id)[0];
657 = global_intersection.points_of_convex((*it)->id)[1];
658 if (is_edges_intersect(PP1, PP2, PR1, PR2))
659 { found_intersect =
true;
break; }
662 if (!found_intersect) {
664 i1 = global_intersection.add_point(PR1);
665 i2 = global_intersection.add_point(PR2);
667 size_type is = global_intersection.add_segment(i1, i2);
669 rtree_seg.add_box(min, max, is);
670 rtree_seg.build_tree();
674 = msh.trans_of_convex(i)->convex_ref()->points()[ipt1];
676 = msh.trans_of_convex(i)->convex_ref()->points()[ipt1];
677 base_node V = PE2 - PE1, W1(n), W2(n);
680 vectors_to_base_matrix(G3, msh.points_of_convex(i));
682 ccc(msh.trans_of_convex(i), base_node(n), G3);
684 for (
size_type j=0; j < pai->nb_points_on_convex(); ++j) {
685 base_node PE = pai->point(j)[0] * PE2
686 + (scalar_type(1) - pai->point(j)[0]) * PE1;
688 cc.set_xref(ccc.xreal());
689 gmm::mult(ccc.K(), V, W1);
690 gmm::mult(cc.K(), W1, W2);
691 new_approx->add_point(ccc.xreal(),
692 pai->coeff(j) * gmm::vect_norm2(W2));
701 default: GMM_ASSERT1(
false,
"internal error");
706 if (new_approx->nb_points()) {
707 new_approx->valid_method();
709 pim = std::make_shared<integration_method>(new_approx);
710 dal::pstatic_stored_object_key
711 pk = std::make_shared<special_imls_key>(new_approx);
713 new_approx->pintegration_points());
714 build_methods.push_back(pim);
720 GMM_ASSERT1(linked_mesh_ != 0,
"mesh level set uninitialized");
721 GMM_ASSERT1(linked_mesh_->dim() > 1 && linked_mesh_->dim() <= 3,
722 "Sorry, works only in dimension 2 or 3");
725 clear_build_methods();
727 mesh global_intersection;
730 std::vector<size_type> icv;
731 std::vector<dal::bit_vector> ils;
732 mls->find_level_set_potential_intersections(icv, ils);
734 for (
size_type i = 0; i < icv.size(); ++i) {
735 if (ils[i].is_in(ind_ls1) && ils[i].is_in(ind_ls2)) {
736 build_method_of_convex(icv[i], global_intersection, rtree_seg);
741 !cv.finished(); ++cv)
742 if (!cut_im.
convex_index().is_in(cv)) ignored_im.add(cv);
744 is_adapted =
true; touch();