GetFEM  5.5
getfem_mesh_slicers.cc
1 /*===========================================================================
2 
3  Copyright (C) 2004-2026 Julien Pommier
4 
5  This file is a part of GetFEM
6 
7  GetFEM is free software; you can redistribute it and/or modify it
8  under the terms of the GNU Lesser General Public License as published
9  by the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version along with the GCC Runtime Library
11  Exception either version 3.1 or (at your option) any later version.
12  This program is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15  License and GCC Runtime Library Exception for more details.
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program. If not, see https://www.gnu.org/licenses/.
18 
19 ===========================================================================*/
20 
21 #include "getfem/dal_singleton.h"
26 
27 namespace getfem {
28  const float slicer_action::EPS = float(1e-13);
29 
30  /* ------------------------------ slicers ------------------------------- */
31 
32  slicer_none& slicer_none::static_instance() {
34  }
35 
36  /* boundary extraction */
37  slicer_boundary::slicer_boundary(const mesh& m, slicer_action &sA,
38  const mesh_region& cvflst) : A(&sA) {
39  build_from(m,cvflst);
40  }
41 
42  slicer_boundary::slicer_boundary(const mesh& m, slicer_action &sA) : A(&sA) {
43  mesh_region cvflist;
44  outer_faces_of_mesh(m, cvflist);
45  build_from(m,cvflist);
46  }
47 
48  void slicer_boundary::build_from(const mesh& m, const mesh_region& cvflst) {
49  if (m.convex_index().card()==0) return;
50  convex_faces.resize(m.convex_index().last()+1, slice_node::faces_ct(0L));
51  for (mr_visitor i(cvflst); !i.finished(); ++i)
52  if (i.is_face()) convex_faces[i.cv()][i.f()]=1;
53  else convex_faces[i.cv()].set();
54  /* set the mask to 1 for all other possible faces of the convexes, which may
55  appear after slicing the convex, hence they will be part of the "boundary" */
56  for (dal::bv_visitor cv(m.convex_index()); !cv.finished(); ++cv) {
57  for (short_type f=m.structure_of_convex(cv)->nb_faces(); f < convex_faces[cv].size(); ++f)
58  convex_faces[cv][f]=1;
59  }
60  }
61 
62  bool slicer_boundary::test_bound(const slice_simplex& s, slice_node::faces_ct& fmask, const mesh_slicer::cs_nodes_ct& nodes) const {
63  slice_node::faces_ct f; f.set();
64  for (size_type i=0; i < s.dim()+1; ++i) {
65  f &= nodes[s.inodes[i]].faces;
66  }
67  f &= fmask;
68  return (f.any());
69  }
70 
71  void slicer_boundary::exec(mesh_slicer& ms) {
72  if (A) A->exec(ms);
73  if (ms.splx_in.card() == 0) return;
74  slice_node::faces_ct fmask(ms.cv < convex_faces.size() ? convex_faces[ms.cv] : 0);
75  /* quickly check if the convex have any chance to be part of the boundary */
76  if (!convex_faces[ms.cv].any()) { ms.splx_in.clear(); return; }
77 
78  for (dal::bv_visitor_c cnt(ms.splx_in); !cnt.finished(); ++cnt) {
79  const slice_simplex& s = ms.simplexes[cnt];
80  if (s.dim() < ms.nodes[0].pt.size()) {
81  if (!test_bound(s, fmask, ms.nodes)) ms.splx_in.sup(cnt);
82  } else if (s.dim() == 2) {
83  ms.sup_simplex(cnt);
84  slice_simplex s2(2);
85  for (size_type j=0; j < 3; ++j) {
86  /* usage of s forbidden in this loop since push_back happens .. */
87  static unsigned ord[][2] = {{0,1},{1,2},{2,0}}; /* keep orientation of faces */
88  for (size_type k=0; k < 2; ++k) { s2.inodes[k] = ms.simplexes[cnt].inodes[ord[j][k]]; }
89  if (test_bound(s2, fmask, ms.nodes)) {
90  ms.add_simplex(s2, true);
91  }
92  }
93  } else if (s.dim() == 3) {
94  //ms.simplex_orientation(ms.simplexes[cnt]);
95  ms.sup_simplex(cnt);
96  slice_simplex s2(3);
97  for (size_type j=0; j < 4; ++j) {
98  /* usage of s forbidden in this loop since push_back happens .. */
99  static unsigned ord[][3] = {{0,2,1},{1,2,3},{1,3,0},{0,3,2}}; /* keep orientation of faces */
100  for (size_type k=0; k < 3; ++k) { s2.inodes[k] = ms.simplexes[cnt].inodes[ord[j][k]]; } //k + (k<j ? 0 : 1)]; }
101  /*cerr << " -> testing "; for (size_type iA=0; iA < s2.dim()+1; ++iA) cerr << s2.inodes[iA] << " ";
102  cerr << " : " << test_bound(s2, fmask, nodes) << endl;*/
103  if (test_bound(s2, fmask, ms.nodes)) {
104  ms.add_simplex(s2, true);
105  }
106  }
107  } /* simplexes of higher dimension are ignored... */
108  }
109  ms.update_nodes_index();
110  }
111 
112  /* apply deformation from a mesh_fem to the nodes */
113  void slicer_apply_deformation::exec(mesh_slicer& ms) {
114  base_vector coeff;
115  base_matrix G;
116  bool ref_pts_changed = false;
117  if (ms.cvr != ms.prev_cvr
118  || defdata->pmf->fem_of_element(ms.cv) != pf) {
119  pf = defdata->pmf->fem_of_element(ms.cv);
120  if (pf->need_G())
121  bgeot::vectors_to_base_matrix
122  (G, defdata->pmf->linked_mesh().points_of_convex(ms.cv));
123  }
124  /* check that the points are still the same
125  * -- or recompute the fem_precomp */
126  std::vector<base_node> ref_pts2; ref_pts2.reserve(ms.nodes_index.card());
127  for (dal::bv_visitor i(ms.nodes_index); !i.finished(); ++i) {
128  ref_pts2.push_back(ms.nodes[i].pt_ref);
129  if (ref_pts2.size() > ref_pts.size()
130  || gmm::vect_dist2_sqr(ref_pts2[i],ref_pts[i])>1e-20)
131  ref_pts_changed = true;
132  }
133  if (ref_pts2.size() != ref_pts.size()) ref_pts_changed = true;
134  if (ref_pts_changed) {
135  ref_pts.swap(ref_pts2);
136  fprecomp.clear();
137  }
138  bgeot::pstored_point_tab pspt = store_point_tab(ref_pts);
139  pfem_precomp pfp = fprecomp(pf, pspt);
140  defdata->copy(ms.cv, coeff);
141 
142  base_vector val(ms.m.dim());
143  size_type cnt = 0;
144  fem_interpolation_context ctx(ms.pgt, pfp, 0, G, ms.cv, short_type(-1));
145  for (dal::bv_visitor i(ms.nodes_index); !i.finished(); ++i, ++cnt) {
146  ms.nodes[i].pt.resize(defdata->pmf->get_qdim());
147  ctx.set_ii(cnt);
148  pf->interpolation(ctx, coeff, val, defdata->pmf->get_qdim());
149  gmm::add(val, ms.nodes[cnt].pt);
150  }
151  }
152 
153 
154  //static bool check_flat_simplex(mesh_slicer::cs_nodes_ct& /*nodes*/, const slice_simplex /*s*/) {
155  /*base_matrix M(s.dim(),s.dim());
156  for (size_type i=0; i < s.dim(); ++i) {
157  for (size_type j=0; j < s.dim(); ++j) {
158  M(i,j) = nodes[s.inodes[i+1]].pt_ref[j] - nodes[s.inodes[0]].pt_ref[j];
159  }
160  }
161  scalar_type d = gmm::lu_det(M);
162  if (gmm::abs(d) < pow(1e-6,s.dim())) {
163  cout.precision(10);
164  cout << "!!Flat (" << d << ") :";
165  for (size_type i=0; i < s.dim()+1; ++i) cout << " " << nodes[s.inodes[i]].pt;
166  cout << "\n";
167  return false;
168  }*/
169  // return true;
170  //}
171 
172  scalar_type slicer_volume::trinom(scalar_type a, scalar_type b, scalar_type c) {
173  scalar_type delta = b * b - 4 * a * c;
174  if (delta < 0.) return 1. / EPS;
175  delta = sqrt(delta);
176  scalar_type s1 = (-b - delta) / (2 * a);
177  scalar_type s2 = (-b + delta) / (2 * a);
178  if (gmm::abs(s1 - 0.5) < gmm::abs(s2 - 0.5))
179  return s1;
180  else
181  return s2;
182  }
183 
184  /*
185  intersects the simplex with the slice, and (recursively)
186  decomposes it into sub-simplices, which are added to the list
187  'splxs'. If orient == 0, then it is the faces of sub-simplices
188  which are added
189 
190  assertion: when called, it will always push *at least* one new
191  simplex on the stack.
192 
193  remark: s is not reference: on purpose.
194  */
195  void slicer_volume::split_simplex(mesh_slicer& ms,
196  slice_simplex s, size_type sstart,
197  std::bitset<32> spin, std::bitset<32> spbin) {
198  scalar_type alpha = 0; size_type iA=0, iB = 0;
199  bool intersection = false;
200  static int level = 0;
201 
202  level++;
203  /*
204  cerr << "split_simplex: level=" << level << " simplex: ";
205  for (iA=0; iA < s.dim()+1 && !intersection; ++iA)
206  cerr << "node#" << s.inodes[iA] << "=" << nodes[s.inodes[iA]].pt
207  << ", in=" << pt_in[s.inodes[iA]] << ", bin=" << pt_bin[s.inodes[iA]] << "; "; cerr << endl;
208  */
209  assert(level < 100);
210  for (iA=0; iA < s.dim(); ++iA) {
211  if (spbin[iA]) continue;
212  for (iB=iA+1; iB < s.dim()+1; ++iB) {
213  if (!spbin[iB] && spin[iA] != spin[iB]) {
214  alpha=edge_intersect(s.inodes[iA],s.inodes[iB],ms.nodes);
215  if (alpha >= 1e-8 && alpha <= 1-1e-8) { intersection = true; break; }
216  }
217  }
218  if (intersection) break;
219  }
220  if (intersection) {
221  /* will call split_simplex recursively */
222  const slice_node& A = ms.nodes[s.inodes[iA]];
223  const slice_node& B = ms.nodes[s.inodes[iB]];
224  slice_node n(A.pt + alpha*(B.pt-A.pt), A.pt_ref + alpha*(B.pt_ref-A.pt_ref));
225  n.faces = A.faces & B.faces;
226  size_type nn = ms.nodes.size();
227  ms.nodes.push_back(n); /* invalidate A and B.. */
228  pt_bin.add(nn); pt_in.add(nn);
229 
230  std::bitset<32> spin2(spin), spbin2(spbin);
231  std::swap(s.inodes[iA],nn);
232  spin2.set(iA); spbin2.set(iA);
233  split_simplex(ms, s, sstart, spin2, spbin2);
234 
235  std::swap(s.inodes[iA],nn); std::swap(s.inodes[iB],nn);
236  spin2 = spin; spbin2 = spbin; spin2.set(iB); spbin2.set(iB);
237  split_simplex(ms, s, sstart, spin2, spbin2);
238 
239  } else {
240  /* end of recursion .. */
241  bool all_in = true;
242  for (size_type i=0; i < s.dim()+1; ++i) if (!spin[i]) { all_in = false; break; }
243  //check_flat_simplex(ms.nodes,s);
244 
245  // even simplexes "outside" are pushed, in case of a slicer_complementary op
246  ms.add_simplex(s,(all_in && orient != VOLBOUND) || orient == VOLSPLIT);
247  if (orient==0) { /* reduce dimension */
248  slice_simplex face(s.dim());
249  for (size_type f=0; f < s.dim()+1; ++f) {
250  all_in = true;
251  for (size_type i=0; i < s.dim(); ++i) {
252  size_type p = i + (i<f?0:1);
253  if (!spbin[p]) { all_in = false; break; }
254  else face.inodes[i] = s.inodes[p];
255  }
256  if (all_in) {
257  /* prevent addition of a face twice */
258  std::sort(face.inodes.begin(), face.inodes.end());
259  if (std::find(ms.simplexes.begin()+sstart, ms.simplexes.end(), face) == ms.simplexes.end()) {
260  ms.add_simplex(face,true);
261  }
262  }
263  }
264  }
265  }
266  level--;
267  }
268 
269  /* nodes : list of nodes (new nodes may be added)
270  splxs : list of simplexes (new simplexes may be added)
271  splx_in : input: simplexes to take into account, output: list of simplexes inside the slice
272 
273  note that the simplexes in the list may have different dimensions
274  */
275  void slicer_volume::exec(mesh_slicer& ms) {
276  //cerr << "\n----\nslicer_volume::slice : entree, splx_in=" << splx_in << endl;
277  if (ms.splx_in.card() == 0) return;
278  prepare(ms.cv,ms.nodes,ms.nodes_index);
279  for (dal::bv_visitor_c cnt(ms.splx_in); !cnt.finished(); ++cnt) {
280  slice_simplex& s = ms.simplexes[cnt];
281  /*cerr << "\n--------slicer_volume::slice : slicing convex " << cnt << endl;
282  for (size_type i=0; i < s.dim()+1; ++i)
283  cerr << " * pt[" << i << "]=" << nodes[s.inodes[i]].pt << ", is_in=" <<
284  is_in(nodes[s.inodes[i]].pt) << ", is_bin=" << is_in(nodes[s.inodes[i]].pt,true) << endl;
285  */
286  size_type in_cnt = 0, in_bcnt = 0;
287  std::bitset<32> spin, spbin;
288  for (size_type i=0; i < s.dim()+1; ++i) {
289  if (pt_in.is_in(s.inodes[i])) { ++in_cnt; spin.set(i); }
290  if (pt_bin.is_in(s.inodes[i])) { ++in_bcnt; spbin.set(i); }
291  }
292 
293  if (in_cnt == 0) {
294  if (orient != VOLSPLIT) ms.splx_in.sup(cnt);
295  } else if (in_cnt != s.dim()+1 || orient==VOLBOUND) { /* the simplex crosses the slice boundary */
296  ms.sup_simplex(cnt);
297  split_simplex(ms, s, ms.simplexes.size(), spin, spbin);
298  }
299  }
300 
301  /* signalement des points qui se trouvent pile-poil sur la bordure */
302  if (pt_bin.card()) {
303  GMM_ASSERT1(ms.fcnt != dim_type(-1),
304  "too much {faces}/{slices faces} in the convex " << ms.cv
305  << " (nbfaces=" << ms.fcnt << ")");
306  for (dal::bv_visitor cnt(pt_bin); !cnt.finished(); ++cnt) {
307  ms.nodes[cnt].faces.set(ms.fcnt);
308  }
309  ms.fcnt++;
310  }
311  ms.update_nodes_index();
312  }
313 
314  slicer_mesh_with_mesh::slicer_mesh_with_mesh(const mesh& slm_) : slm(slm_) {
315  base_node min,max;
316  for (dal::bv_visitor cv(slm.convex_index()); !cv.finished(); ++cv) {
317  bgeot::bounding_box(min,max,slm.points_of_convex(cv),slm.trans_of_convex(cv));
318  tree.add_box(min, max, cv);
319  }
320  tree.build_tree();
321  }
322 
323  void slicer_mesh_with_mesh::exec(mesh_slicer &ms) {
324  /* identify potientially intersecting convexes of slm */
325  base_node min(ms.nodes[0].pt),max(ms.nodes[0].pt);
326  for (size_type i=1; i < ms.nodes.size(); ++i) {
327  for (size_type k=0; k < min.size(); ++k) {
328  min[k] = std::min(min[k], ms.nodes[i].pt[k]);
329  max[k] = std::max(max[k], ms.nodes[i].pt[k]);
330  }
331  }
332  std::vector<size_type> slmcvs;
333  tree.find_intersecting_boxes(min, max, slmcvs);
334  /* save context */
335  mesh_slicer::cs_simplexes_ct simplexes_final(ms.simplexes);
336  dal::bit_vector splx_in_save(ms.splx_in),
337  simplex_index_save(ms.simplex_index), nodes_index_save(ms.nodes_index);
338  size_type scnt0 = ms.simplexes.size();
339  /* loop over candidate convexes of slm */
340  //cout << "slicer_mesh_with_mesh: convex " << ms.cv << ", " << ms.splx_in.card() << " candidates\n";
341  for (size_type i=0; i < slmcvs.size(); ++i) {
342  size_type slmcv = slmcvs[i];
343  dim_type fcnt_save = dim_type(ms.fcnt);
344  ms.simplexes.resize(scnt0);
345  ms.splx_in = splx_in_save; ms.simplex_index = simplex_index_save; ms.nodes_index = nodes_index_save;
346  //cout << "test intersection of " << ms.cv << " and " << slmcv << "\n";
347  /* loop over the faces and apply slicer_half_space */
348  for (short_type f=0; f<slm.structure_of_convex(slmcv)->nb_faces(); ++f) {
349  base_node x0,n;
350  if (slm.structure_of_convex(slmcv)->dim() == 3 && slm.dim() == 3) {
351  x0 = slm.points_of_face_of_convex(slmcv,f)[0];
352  base_node A = slm.points_of_face_of_convex(slmcv,f)[1] - x0;
353  base_node B = slm.points_of_face_of_convex(slmcv,f)[2] - x0;
354  base_node G = gmm::mean_value(slm.points_of_convex(slmcv).begin(),slm.points_of_convex(slmcv).end());
355  n.resize(3);
356  n[0] = A[1]*B[2] - A[2]*B[1];
357  n[1] = A[2]*B[0] - A[0]*B[2];
358  n[2] = A[0]*B[1] - A[1]*B[0];
359  if (gmm::vect_sp(n,G-x0) > 0) n *= -1.;
360  } else {
361  size_type ip = slm.structure_of_convex(slmcv)->nb_points_of_face(f) / 2;
362  x0 = slm.points_of_face_of_convex(slmcv,f)[ip];
363  n = slm.normal_of_face_of_convex(slmcv,f, x0);
364  }
365  slicer_half_space slf(x0,n,slicer_volume::VOLIN);
366  slf.exec(ms);
367  if (ms.splx_in.card() == 0) break;
368  }
369  if (ms.splx_in.card()) intersection_callback(ms, slmcv);
370  for (dal::bv_visitor is(ms.splx_in); !is.finished(); ++is) {
371  simplexes_final.push_back(ms.simplexes[is]);
372  }
373  ms.fcnt=fcnt_save;
374  }
375  ms.splx_in.clear(); ms.splx_in.add(scnt0, simplexes_final.size()-scnt0);
376  ms.simplexes.swap(simplexes_final);
377  ms.simplex_index = ms.splx_in;
378  ms.update_nodes_index();
379  /*cout << "convex " << ms.cv << "was sliced into " << ms.splx_in.card()
380  << " simplexes, nodes.size=" << ms.nodes.size()
381  << ", used nodes=" << ms.nodes_index.card() << "\n";*/
382  }
383 
384  /* isosurface computations */
385  void slicer_isovalues::prepare(size_type cv,
386  const mesh_slicer::cs_nodes_ct& nodes,
387  const dal::bit_vector& nodes_index) {
388  pt_in.clear(); pt_bin.clear();
389  std::vector<base_node> refpts(nodes.size());
390  Uval.resize(nodes.size());
391  base_vector coeff;
392  base_matrix G;
393  pfem pf = mfU->pmf->fem_of_element(cv);
394  if (pf == 0) return;
395  fem_precomp_pool fprecomp;
396  if (pf->need_G())
397  bgeot::vectors_to_base_matrix
398  (G,mfU->pmf->linked_mesh().points_of_convex(cv));
399  for (size_type i=0; i < nodes.size(); ++i) refpts[i] = nodes[i].pt_ref;
400  pfem_precomp pfp = fprecomp(pf, store_point_tab(refpts));
401  mfU->copy(cv, coeff);
402  //cerr << "cv=" << cv << ", val=" << val << ", coeff=" << coeff << endl;
403  base_vector v(1);
404  fem_interpolation_context ctx(mfU->pmf->linked_mesh().trans_of_convex(cv),
405  pfp, 0, G, cv, short_type(-1));
406  for (dal::bv_visitor i(nodes_index); !i.finished(); ++i) {
407  v[0] = 0;
408  ctx.set_ii(i);
409  pf->interpolation(ctx, coeff, v, mfU->pmf->get_qdim());
410  Uval[i] = v[0];
411  // optimisable -- les bit_vectors sont lents..
412  pt_bin[i] = (gmm::abs(Uval[i] - val) < EPS * val_scaling);
413  pt_in[i] = (Uval[i] - val < 0); if (orient>0) pt_in[i] = !pt_in[i];
414  pt_in[i] = pt_in[i] || pt_bin[i];
415  // cerr << "cv=" << cv << ", node["<< i << "]=" << nodes[i].pt
416  // << ", Uval[i]=" << Uval[i] << ", pt_in[i]=" << pt_in[i]
417  // << ", pt_bin[i]=" << pt_bin[i] << endl;
418  }
419  }
420 
421  scalar_type
422  slicer_isovalues::edge_intersect(size_type iA, size_type iB,
423  const mesh_slicer::cs_nodes_ct&) const {
424  assert(iA < Uval.size() && iB < Uval.size());
425  if (((Uval[iA] < val) && (Uval[iB] > val)) ||
426  ((Uval[iA] > val) && (Uval[iB] < val)))
427  return (val-Uval[iA])/(Uval[iB]-Uval[iA]);
428  else
429  return 1./EPS;
430  }
431 
432 
433  void slicer_union::exec(mesh_slicer &ms) {
434  dal::bit_vector splx_in_base = ms.splx_in;
435  size_type c = ms.simplexes.size();
436  dim_type fcnt_0 = dim_type(ms.fcnt);
437  A->exec(ms);
438  dal::bit_vector splx_inA(ms.splx_in);
439  dim_type fcnt_1 = dim_type(ms.fcnt);
440 
441  dal::bit_vector splx_inB = splx_in_base;
442  splx_inB.add(c, ms.simplexes.size()-c);
443  splx_inB.setminus(splx_inA);
444  for (dal::bv_visitor_c i(splx_inB); !i.finished(); ++i) {
445  if (!ms.simplex_index[i]) splx_inB.sup(i);
446  }
447  //splx_inB &= ms.simplex_index;
448  ms.splx_in = splx_inB;
449  B->exec(ms); splx_inB = ms.splx_in;
450  ms.splx_in |= splx_inA;
451 
452  /*
453  the boring part : making sure that the "slice face" node markers
454  are correctly set
455  */
456  for (unsigned f=fcnt_0; f < fcnt_1; ++f) {
457  for (dal::bv_visitor i(splx_inB); !i.finished(); ++i) {
458  for (unsigned j=0; j < ms.simplexes[i].dim()+1; ++j) {
459  bool face_boundA = true;
460  for (unsigned k=0; k < ms.simplexes[i].dim()+1; ++k) {
461  if (j != k && !ms.nodes[ms.simplexes[i].inodes[k]].faces[f]) {
462  face_boundA = false; break;
463  }
464  }
465  if (face_boundA) {
466  /* now we know that the face was on slice A boundary, and
467  that the convex is inside slice B. The conclusion: the
468  face is not on a face of A union B.
469  */
470  for (unsigned k=0; k < ms.simplexes[i].dim()+1; ++k)
471  if (j != k) ms.nodes[ms.simplexes[i].inodes[k]].faces[f] = false;
472  }
473  }
474  }
475  }
476  ms.update_nodes_index();
477  }
478 
479  void slicer_intersect::exec(mesh_slicer& ms) {
480  A->exec(ms);
481  B->exec(ms);
482  }
483 
484  void slicer_complementary::exec(mesh_slicer& ms) {
485  dal::bit_vector splx_inA = ms.splx_in;
486  size_type sz = ms.simplexes.size();
487  A->exec(ms); splx_inA.swap(ms.splx_in);
488  ms.splx_in &= ms.simplex_index;
489  dal::bit_vector bv = ms.splx_in; bv.add(sz, ms.simplexes.size()-sz); bv &= ms.simplex_index;
490  for (dal::bv_visitor_c i(bv); !i.finished(); ++i) {
491  /*cerr << "convex " << cv << ",examining simplex #" << i << ": {";
492  for (size_type j=0; j < simplexes[i].inodes.size(); ++j) cerr << nodes[simplexes[i].inodes[j]].pt << " ";
493  cerr << "}, splx_in=" << splx_in[i] << "splx_inA=" << splx_inA[i] << endl;*/
494  ms.splx_in[i] = !splx_inA.is_in(i);
495  }
496  }
497 
498  void slicer_compute_area::exec(mesh_slicer &ms) {
499  for (dal::bv_visitor is(ms.splx_in); !is.finished(); ++is) {
500  const slice_simplex& s = ms.simplexes[is];
501  base_matrix M(s.dim(),s.dim());
502  for (size_type i=0; i < s.dim(); ++i)
503  for (size_type j=0; j < s.dim(); ++j)
504  M(i,j) = ms.nodes[s.inodes[i+1]].pt[j] - ms.nodes[s.inodes[0]].pt[j];
505  scalar_type v = bgeot::lu_det(&(*(M.begin())), s.dim());
506  for (size_type d=2; d <= s.dim(); ++d) v /= scalar_type(d);
507  a += v;
508  }
509  }
510 
511  void slicer_build_edges_mesh::exec(mesh_slicer &ms) {
512  for (dal::bv_visitor is(ms.splx_in); !is.finished(); ++is) {
513  const slice_simplex& s = ms.simplexes[is];
514  for (size_type i=0; i < s.dim(); ++i) {
515  for (size_type j=i+1; j <= s.dim(); ++j) {
516  const slice_node& A = ms.nodes[s.inodes[i]];
517  const slice_node& B = ms.nodes[s.inodes[j]];
518  /* duplicate with stored_mesh_slice which also
519  builds a list of edges */
520  if ((A.faces & B.faces).count() >= unsigned(ms.cv_dim-1)) {
521  slice_node::faces_ct fmask((1 << ms.cv_nbfaces)-1); fmask.flip();
522  size_type e = edges_m.add_segment_by_points(A.pt,B.pt);
523  if (pslice_edges && (((A.faces & B.faces) & fmask).any())) pslice_edges->add(e);
524  }
525  }
526  }
527  }
528  }
529 
530  void slicer_build_mesh::exec(mesh_slicer &ms) {
531  std::vector<size_type> pid(ms.nodes_index.last_true()+1);
532  for (dal::bv_visitor i(ms.nodes_index); !i.finished(); ++i)
533  pid[i] = m.add_point(ms.nodes[i].pt);
534  for (dal::bv_visitor i(ms.splx_in); !i.finished(); ++i) {
535  for (unsigned j=0; j < ms.simplexes.at(i).inodes.size(); ++j) {
536  assert(m.points_index().is_in(pid.at(ms.simplexes.at(i).inodes[j])));
537  }
538  m.add_convex(bgeot::simplex_geotrans(ms.simplexes[i].dim(),1),
539  gmm::index_ref_iterator(pid.begin(),
540  ms.simplexes[i].inodes.begin()));
541  }
542  }
543 
544  void slicer_explode::exec(mesh_slicer &ms) {
545  if (ms.nodes_index.card() == 0) return;
546 
547  base_node G;
548  if (ms.face < dim_type(-1))
549  G = gmm::mean_value(ms.m.points_of_face_of_convex(ms.cv, ms.face).begin(),
550  ms.m.points_of_face_of_convex(ms.cv, ms.face).end());
551  else
552  G = gmm::mean_value(ms.m.points_of_convex(ms.cv).begin(),
553  ms.m.points_of_convex(ms.cv).end());
554  for (dal::bv_visitor i(ms.nodes_index); !i.finished(); ++i)
555  ms.nodes[i].pt = G + coef*(ms.nodes[i].pt - G);
556 
557  for (dal::bv_visitor cnt(ms.splx_in); !cnt.finished(); ++cnt) {
558  const slice_simplex& s = ms.simplexes[cnt];
559  if (s.dim() == 3) { // keep only faces
560  ms.sup_simplex(cnt);
561  slice_simplex s2(3);
562  for (size_type j=0; j < 4; ++j) {
563  /* usage of s forbidden in this loop since push_back happens .. */
564  static unsigned ord[][3] = {{0,2,1},{1,2,3},{1,3,0},{0,3,2}}; /* keep orientation of faces */
565  for (size_type k=0; k < 3; ++k) { s2.inodes[k] = ms.simplexes[cnt].inodes[ord[j][k]]; } //k + (k<j ? 0 : 1)]; }
566 
567  slice_node::faces_ct f; f.set();
568  for (size_type i=0; i < s2.dim()+1; ++i) {
569  f &= ms.nodes[s2.inodes[i]].faces;
570  }
571  if (f.any()) {
572  ms.add_simplex(s2, true);
573  }
574  }
575  }
576  }
577  }
578 
579  /* -------------------- member functions of mesh_slicer -------------- */
580 
581  mesh_slicer::mesh_slicer(const mesh_level_set &mls_) :
582  m(mls_.linked_mesh()), mls(&mls_), pgt(0), cvr(0) {}
584  m(m_), mls(0), pgt(0), cvr(0) {}
585 
586  void mesh_slicer::using_mesh_level_set(const mesh_level_set &mls_) {
587  mls = &mls_;
588  GMM_ASSERT1(&m == &mls->linked_mesh(), "different meshes");
589  }
590 
591  void mesh_slicer::pack() {
592  std::vector<size_type> new_id(nodes.size());
593  size_type ncnt = 0;
594  for (dal::bv_visitor i(nodes_index); !i.finished(); ++i) {
595  if (i != ncnt) {
596  nodes[i].swap(nodes[ncnt]);
597  }
598  new_id[i] = ncnt++;
599  }
600  nodes.resize(ncnt);
601  size_type scnt = 0;
602  for (dal::bv_visitor j(simplex_index); !j.finished(); ++j) {
603  if (j != scnt) { simplexes[scnt] = simplexes[j]; }
604  for (std::vector<size_type>::iterator it = simplexes[scnt].inodes.begin();
605  it != simplexes[scnt].inodes.end(); ++it) {
606  *it = new_id[*it];
607  }
608  }
609  simplexes.resize(scnt);
610  }
611 
612  void mesh_slicer::update_nodes_index() {
613  nodes_index.clear();
614  for (dal::bv_visitor j(simplex_index); !j.finished(); ++j) {
615  assert(j < simplexes.size());
616  for (std::vector<size_type>::iterator it = simplexes[j].inodes.begin();
617  it != simplexes[j].inodes.end(); ++it) {
618  assert(*it < nodes.size());
619  nodes_index.add(*it);
620  }
621  }
622  }
623 
624  static void flag_points_on_faces(const bgeot::pconvex_ref& cvr,
625  const std::vector<base_node>& pts,
626  std::vector<slice_node::faces_ct>& faces) {
627  GMM_ASSERT1(cvr->structure()->nb_faces() <= 32,
628  "won't work for convexes with more than 32 faces "
629  "(hardcoded limit)");
630  faces.resize(pts.size());
631  for (size_type i=0; i < pts.size(); ++i) {
632  faces[i].reset();
633  for (short_type f=0; f < cvr->structure()->nb_faces(); ++f)
634  faces[i][f] = (gmm::abs(cvr->is_in_face(f, pts[i])) < 1e-10);
635  }
636  }
637 
638  void mesh_slicer::update_cv_data(size_type cv_, short_type f_) {
639  cv = cv_;
640  face = f_;
641  pgt = m.trans_of_convex(cv);
642  prev_cvr = cvr; cvr = pgt->convex_ref();
643  cv_dim = cvr->structure()->dim();
644  cv_nbfaces = cvr->structure()->nb_faces();
645  fcnt = cvr->structure()->nb_faces();
646  discont = (mls && mls->is_convex_cut(cv));
647  }
648 
649  void mesh_slicer::apply_slicers() {
650  simplex_index.clear(); simplex_index.add(0, simplexes.size());
651  splx_in = simplex_index;
652  nodes_index.clear(); nodes_index.add(0, nodes.size());
653  for (size_type i=0; i < action.size(); ++i) {
654  action[i]->exec(*this);
655  //cout << "simplex_index=" << simplex_index << "\n splx_in=" << splx_in << "\n";
656  assert(simplex_index.contains(splx_in));
657  }
658  }
659 
660  void mesh_slicer::simplex_orientation(slice_simplex& s) {
661  size_type N = m.dim();
662  if (s.dim() == N) {
663  base_matrix M(N,N);
664  for (size_type i=1; i < N+1; ++i) {
665  base_small_vector d = nodes[s.inodes[i]].pt - nodes[s.inodes[0]].pt;
666  gmm::copy_n(d.const_begin(), N, M.begin() + (i-1)*N);
667  }
668  scalar_type J = bgeot::lu_det(&(*(M.begin())), N);
669  //cout << " lu_det = " << J << "\n";
670  if (J < 0) {
671  std::swap(s.inodes[1],s.inodes[0]);
672  }
673  }
674  }
675 
676  void mesh_slicer::exec(size_type nrefine, const mesh_region& cvlst) {
677  short_type n = short_type(nrefine);
678  exec_(&n, 0, cvlst);
679  }
680 
681  void mesh_slicer::exec(const std::vector<short_type> &nrefine,
682  const mesh_region& cvlst) {
683  exec_(&nrefine[0], 1, cvlst);
684  }
685 
686  static bool check_orient(size_type cv, bgeot::pgeometric_trans pgt,
687  const mesh& m) {
688  if (pgt->dim() == m.dim() && m.dim()>=2) { /* no orient check for
689  convexes of lower dim */
690  base_matrix G; bgeot::vectors_to_base_matrix(G,m.points_of_convex(cv));
691  base_node g(pgt->dim()); g.fill(.5);
692  base_matrix pc; pgt->poly_vector_grad(g,pc);
693  base_matrix K(pgt->dim(),pgt->dim());
694  gmm::mult(G,pc,K);
695  scalar_type J = bgeot::lu_det(&(*(K.begin())), pgt->dim());
696  // bgeot::geotrans_interpolation_context ctx(pgp,0,G);
697  // scalar_type J = gmm::lu_det(ctx.B()); // pb car inverse K même
698  if (J < 0) return true;
699  //cout << "cv = " << cv << ", J = " << J << "\n";
700  }
701  return false;
702  }
703 
704 #if OLD_MESH_SLICER
705  void mesh_slicer::exec_(const short_type *pnrefine, int nref_stride,
706  const mesh_region& cvlst) {
707  std::vector<base_node> cvm_pts;
708  const bgeot::basic_mesh *cvm = 0;
709  const bgeot::mesh_structure *cvms = 0;
711  bgeot::pgeotrans_precomp pgp = 0;
712  std::vector<slice_node::faces_ct> points_on_faces;
713 
714  cvlst.from_mesh(m);
715  size_type prev_nrefine = 0;
716  for (mr_visitor it(cvlst); !it.finished(); ++it) {
717  size_type nrefine = pnrefine[it.cv()*nref_stride];
718  update_cv_data(it.cv(),it.f());
719  bool revert_orientation = check_orient(cv, pgt,m);
720 
721  /* update structure-dependent data */
722  if (prev_cvr != cvr || nrefine != prev_nrefine) {
723  cvm = bgeot::refined_simplex_mesh_for_convex(cvr, nrefine);
724  cvm_pts.resize(cvm->points().card());
725  std::copy(cvm->points().begin(), cvm->points().end(), cvm_pts.begin());
726  pgp = gppool(pgt, store_point_tab(cvm_pts));
727  flag_points_on_faces(cvr, cvm_pts, points_on_faces);
728  prev_nrefine = nrefine;
729  }
730  if (face < dim_type(-1))
731  cvms = bgeot::refined_simplex_mesh_for_convex_faces(cvr, nrefine)[face].get();
732  else
733  cvms = cvm;
734 
735  /* apply the initial geometric transformation */
736  std::vector<size_type> ptsid(cvm_pts.size()); std::fill(ptsid.begin(), ptsid.end(), size_type(-1));
737  simplexes.resize(cvms->nb_convex());
738  nodes.resize(0);
739  for (size_type snum = 0; snum < cvms->nb_convex(); ++snum) {
740  /* cvms should not contain holes in its convex index.. */
741  simplexes[snum].inodes.resize(cvms->nb_points_of_convex(snum));
742  std::copy(cvms->ind_points_of_convex(snum).begin(),
743  cvms->ind_points_of_convex(snum).end(), simplexes[snum].inodes.begin());
744  if (revert_orientation) std::swap(simplexes[snum].inodes[0],simplexes[snum].inodes[1]);
745  /* store indices of points which are really used , and renumbers them */
746  for (std::vector<size_type>::iterator itp = simplexes[snum].inodes.begin();
747  itp != simplexes[snum].inodes.end(); ++itp) {
748  if (ptsid[*itp] == size_type(-1)) {
749  ptsid[*itp] = nodes.size();
750  nodes.push_back(slice_node());
751  nodes.back().pt_ref = cvm_pts[*itp];
752  nodes.back().faces = points_on_faces[*itp];
753  nodes.back().pt.resize(m.dim()); nodes.back().pt.fill(0.);
754  pgp->transform(m.points_of_convex(cv), *itp, nodes.back().pt);
755  }
756  *itp = ptsid[*itp];
757  }
758  if (0) {
759  static int once = 0;
760  if (once++ < 3) {
761  cout << "check orient cv " << cv << ", snum=" << snum << "/" << cvms->nb_convex();
762  }
763  simplex_orientation(simplexes[snum]);
764  }
765  }
766  apply_slicers();
767  }
768  }
769 #endif // OLD_MESH_SLICER
770 
771  template <typename CONT>
772  static void add_degree1_convex(bgeot::pgeometric_trans pgt, const CONT &pts,
773  mesh &m) {
774  unsigned N = pgt->dim();
775  std::vector<base_node> v; v.reserve(N+1);
776  for (unsigned i=0; i < pgt->nb_points(); ++i) {
777  const base_node P = pgt->convex_ref()->points()[i];
778  scalar_type s = 0;
779  for (unsigned j=0; j < N; ++j) {
780  s += P[j]; if (P[j] == 1) { v.push_back(pts[i]); break; }
781  }
782  if (s == 0) v.push_back(pts[i]);
783  }
784  assert(v.size() == N+1);
785  base_node G = gmm::mean_value(v);
786  /*for (unsigned i=0; i < v.size();++i)
787  v[i] = v[i] + 0.1 * (G - v[i]);*/
788  m.add_convex_by_points(bgeot::simplex_geotrans(N,1), v.begin());
789  }
790 
791  const mesh& mesh_slicer::refined_simplex_mesh_for_convex_cut_by_level_set
792  (const mesh &cvm, unsigned nrefine) {
793  mesh mm; mm.copy_from(cvm);
794  while (nrefine > 1) {
795  mm.Bank_refine(mm.convex_index());
796  nrefine /= 2;
797  }
798 
799  std::vector<size_type> idx;
800  tmp_mesh.clear();
801  //cerr << "nb cv = " << tmp_mesh.convex_index().card() << "\n";
802  for (dal::bv_visitor_c ic(mm.convex_index()); !ic.finished(); ++ic) {
803  add_degree1_convex(mm.trans_of_convex(ic), mm.points_of_convex(ic), tmp_mesh);
804  }
805  /*tmp_mesh.write_to_file(std::cerr);
806  cerr << "\n";*/
807  return tmp_mesh;
808  }
809 
810  const bgeot::mesh_structure &
811  mesh_slicer::refined_simplex_mesh_for_convex_faces_cut_by_level_set
812  (short_type f) {
813  mesh &cvm = tmp_mesh;
814  tmp_mesh_struct.clear();
815  unsigned N = cvm.dim();
816 
817  dal::bit_vector pt_in_face; pt_in_face.sup(0, cvm.points().index().last_true()+1);
818  for (dal::bv_visitor ip(cvm.points().index()); !ip.finished(); ++ip)
819  if (gmm::abs(cvr->is_in_face(short_type(f), cvm.points()[ip]))) pt_in_face.add(ip);
820 
821  for (dal::bv_visitor_c ic(cvm.convex_index()); !ic.finished(); ++ic) {
822  for (short_type ff=0; ff < cvm.nb_faces_of_convex(ic); ++ff) {
823  bool face_ok = true;
824  for (unsigned i=0; i < N; ++i) {
825  if (!pt_in_face.is_in(cvm.ind_points_of_face_of_convex(ic,ff)[i])) {
826  face_ok = false; break;
827  }
828  }
829  if (face_ok) {
830  tmp_mesh_struct.add_convex(bgeot::simplex_structure(dim_type(N-1)),
831  cvm.ind_points_of_face_of_convex(ic, ff).begin());
832  }
833  }
834  }
835  return tmp_mesh_struct;
836  }
837 
838  void mesh_slicer::exec_(const short_type *pnrefine,
839  int nref_stride,
840  const mesh_region& cvlst) {
841  std::vector<base_node> cvm_pts;
842  const bgeot::basic_mesh *cvm = 0;
843  const bgeot::mesh_structure *cvms = 0;
845  bgeot::pgeotrans_precomp pgp = 0;
846  std::vector<slice_node::faces_ct> points_on_faces;
847  bool prev_discont = true;
848 
849  cvlst.from_mesh(m);
850  size_type prev_nrefine = 0;
851  // size_type prev_cv = size_type(-1);
852  for (mr_visitor it(cvlst); !it.finished(); ++it) {
853  size_type nrefine = pnrefine[it.cv()*nref_stride];
854  update_cv_data(it.cv(),it.f());
855  bool revert_orientation = check_orient(cv, pgt,m);
856 
857  /* update structure-dependent data */
858  /* TODO : fix levelset handling when slicing faces .. */
859  if (prev_cvr != cvr || nrefine != prev_nrefine
860  || discont || prev_discont) {
861  if (discont) {
862  cvm = &refined_simplex_mesh_for_convex_cut_by_level_set
863  (mls->mesh_of_convex(cv), unsigned(nrefine));
864  } else {
866  }
867  cvm_pts.resize(cvm->points().card());
868  std::copy(cvm->points().begin(), cvm->points().end(), cvm_pts.begin());
869  pgp = gppool(pgt, store_point_tab(cvm_pts));
870  flag_points_on_faces(cvr, cvm_pts, points_on_faces);
871  prev_nrefine = nrefine;
872  }
873  if (face < dim_type(-1)) {
874  if (!discont) {
876  (cvr, short_type(nrefine))[face].get();
877  } else {
878  cvms = &refined_simplex_mesh_for_convex_faces_cut_by_level_set(face);
879  }
880  } else {
881  cvms = cvm;
882  }
883 
884  /* apply the initial geometric transformation */
885  std::vector<size_type> ptsid(cvm_pts.size()); std::fill(ptsid.begin(), ptsid.end(), size_type(-1));
886  simplexes.resize(cvms->nb_convex());
887  nodes.resize(0);
888 
889  base_node G;
890  for (size_type snum = 0; snum < cvms->nb_convex(); ++snum) {
891  /* cvms should not contain holes in its convex index.. */
892  simplexes[snum].inodes.resize(cvms->nb_points_of_convex(snum));
893  std::copy(cvms->ind_points_of_convex(snum).begin(),
894  cvms->ind_points_of_convex(snum).end(), simplexes[snum].inodes.begin());
895  if (revert_orientation) std::swap(simplexes[snum].inodes[0],simplexes[snum].inodes[1]);
896  /* store indices of points which are really used , and renumbers them */
897  if (discont) {
898  G.resize(m.dim()); G.fill(0.);
899  for (std::vector<size_type>::iterator itp =
900  simplexes[snum].inodes.begin();
901  itp != simplexes[snum].inodes.end(); ++itp) {
902  G += cvm_pts[*itp];
903  }
904  G /= scalar_type(simplexes[snum].inodes.size());
905  }
906 
907  for (std::vector<size_type>::iterator itp =
908  simplexes[snum].inodes.begin();
909  itp != simplexes[snum].inodes.end(); ++itp) {
910  if (discont || ptsid[*itp] == size_type(-1)) {
911  ptsid[*itp] = nodes.size();
912  nodes.push_back(slice_node());
913  if (!discont) {
914  nodes.back().pt_ref = cvm_pts[*itp];
915  } else {
916  /* displace the ref point such that one will not interpolate
917  on the discontinuity (yes this is quite ugly and not
918  robust)
919  */
920  nodes.back().pt_ref = cvm_pts[*itp] + 0.01*(G - cvm_pts[*itp]);
921  }
922  nodes.back().faces = points_on_faces[*itp];
923  nodes.back().pt.resize(m.dim()); nodes.back().pt.fill(0.);
924  pgp->transform(m.points_of_convex(cv), *itp, nodes.back().pt);
925  //nodes.back().pt = pgt->transform(G, m.points_of_convex(cv));
926  //cerr << "G = " << G << " -> pt = " << nodes.back().pt << "\n";
927  }
928  *itp = ptsid[*itp];
929  }
930  }
931  //cerr << "cv = " << cv << ", cvm.nb_points_ = "<< cvm->points().size() << ", nbnodes = " << nodes.size() << ", nb_simpl=" << simplexes.size() << "\n";
932 
933  apply_slicers();
934  // prev_cv = it.cv();
935  prev_discont = discont;
936  }
937  }
938 
939 
940  void mesh_slicer::exec(size_type nrefine) {
941  exec(nrefine,mesh_region(m.convex_index()));
942  }
943 
944  /* apply slice ops to an already stored slice object */
946  GMM_ASSERT1(&sl.linked_mesh() == &m, "wrong mesh");
947  for (stored_mesh_slice::cvlst_ct::const_iterator it = sl.cvlst.begin(); it != sl.cvlst.end(); ++it) {
948  update_cv_data((*it).cv_num);
949  nodes = (*it).nodes;
950  simplexes = (*it).simplexes;
951  apply_slicers();
952  }
953  }
954 
955  /* apply slice ops to a set of nodes */
956  void mesh_slicer::exec(const std::vector<base_node>& pts) {
958  gti.add_points(pts);
961  for (dal::bv_visitor ic(m.convex_index()); !ic.finished(); ++ic) {
962  size_type nb = gti.points_in_convex(m.convex(ic), m.trans_of_convex(ic), ptab, itab);
963  if (!nb) continue;
964  update_cv_data(ic);
965  nodes.resize(0); simplexes.resize(0);
966  for (size_type i=0; i < nb; ++i) {
967  //cerr << "point " << itab[i] << "(" << pts[itab[i]]
968  //<< ") trouve dans le convex " << ic << " [pt_ref=" << ptab[i] << "]\n";
969  nodes.push_back(slice_node(pts[itab[i]],ptab[i])); nodes.back().faces=0;
970  slice_simplex s(1); s.inodes[0] = nodes.size()-1;
971  simplexes.push_back(s);
972  }
973  apply_slicers();
974  }
975  }
976 
977  void
978  slicer_half_space::test_point(const base_node& P, bool& in, bool& bound) const {
979  scalar_type s = gmm::vect_sp(P - x0, n);
980  in = (s <= 0); bound = (s * s <= EPS); // gmm::vect_norm2_sqr(P-x0)); No!
981  // do not try to be smart with the boundary check .. easily broken with
982  // slicer_mesh_with_mesh
983  }
984 
985  scalar_type
986  slicer_half_space::edge_intersect(size_type iA, size_type iB,
987  const mesh_slicer::cs_nodes_ct& nodes) const {
988  const base_node& A = nodes[iA].pt;
989  const base_node& B = nodes[iB].pt;
990  scalar_type s1 = 0., s2 = 0.;
991  for (unsigned i = 0; i < A.size(); ++i) {
992  s1 += (A[i] - B[i]) * n[i]; s2 += (A[i] - x0[i]) * n[i];
993  }
994  if (gmm::abs(s1) < EPS)
995  return 1. / EPS;
996  else
997  return s2 / s1;
998  }
999 
1000  void
1001  slicer_sphere::test_point(const base_node& P, bool& in, bool& bound) const {
1002  scalar_type R2 = gmm::vect_dist2_sqr(P,x0);
1003  bound = (R2 >= (1-EPS)*R*R && R2 <= (1+EPS)*R*R);
1004  in = R2 <= R*R;
1005  }
1006 
1007  scalar_type
1008  slicer_sphere::edge_intersect(size_type iA, size_type iB,
1009  const mesh_slicer::cs_nodes_ct& nodes) const {
1010  const base_node& A=nodes[iA].pt;
1011  const base_node& B=nodes[iB].pt;
1012  scalar_type a,b,c; // a*x^2 + b*x + c = 0
1013  a = gmm::vect_norm2_sqr(B-A);
1014  if (a < EPS)
1015  return pt_bin.is_in(iA) ? 0. : 1./EPS;
1016  b = 2*gmm::vect_sp(A-x0,B-A);
1017  c = gmm::vect_norm2_sqr(A-x0)-R*R;
1018  return slicer_volume::trinom(a,b,c);
1019  }
1020 
1021  void
1022  slicer_cylinder::test_point(const base_node& P, bool& in, bool& bound) const {
1023  base_node N = P;
1024  if (2 == N.size()) /* Add Z coorinate if mesh is 2D */
1025  N.push_back(0.0);
1026  N = N-x0;
1027  scalar_type axpos = gmm::vect_sp(d, N);
1028  scalar_type dist2 = gmm::vect_norm2_sqr(N) - gmm::sqr(axpos);
1029  bound = gmm::abs(dist2-R*R) < EPS;
1030  in = dist2 < R*R;
1031  }
1032 
1033  scalar_type
1034  slicer_cylinder::edge_intersect(size_type iA, size_type iB,
1035  const mesh_slicer::cs_nodes_ct& nodes) const {
1036  base_node F=nodes[iA].pt;
1037  base_node D=nodes[iB].pt-nodes[iA].pt;
1038  if (2 == F.size()) {
1039  F.push_back(0.0);
1040  D.push_back(0.0);
1041  }
1042  F = F - x0;
1043  scalar_type Fd = gmm::vect_sp(F,d);
1044  scalar_type Dd = gmm::vect_sp(D,d);
1045  scalar_type a = gmm::vect_norm2_sqr(D) - gmm::sqr(Dd);
1046  if (a < EPS)
1047  return pt_bin.is_in(iA) ? 0. : 1./EPS;
1048  assert(a> -EPS);
1049  scalar_type b = 2*(gmm::vect_sp(F,D) - Fd*Dd);
1050  scalar_type c = gmm::vect_norm2_sqr(F) - gmm::sqr(Fd) - gmm::sqr(R);
1051  return slicer_volume::trinom(a,b,c);
1052  }
1053 }
Inversion of geometric transformations.
handles the geometric inversion for a given (supposedly quite large) set of points
void add_points(const CONT &c)
Add the points contained in c to the list of points.
size_type points_in_convex(const convex< base_node, TAB > &cv, pgeometric_trans pgt, CONT1 &pftab, CONT2 &itab, bool bruteforce=false)
Search all the points in the convex cv, which is the transformation of the convex cref via the geomet...
The object geotrans_precomp_pool Allow to allocate a certain number of geotrans_precomp and automatic...
Mesh structure definition.
short_type nb_points_of_convex(size_type ic) const
Return the number of points of convex ic.
void clear()
erase the mesh
size_type nb_convex() const
The total number of convexes in the mesh.
size_type add_convex(pconvex_structure cs, ITER ipts, bool *present=0)
Insert a new convex in the mesh_structure.
pconvex_structure structure_of_convex(size_type ic) const
Return the pconvex_structure of the convex ic.
const ind_set & ind_points_of_convex(size_type ic) const
Return a container to the list of points attached to convex ic.
Dynamic Array.
Definition: dal_basic.h:195
static T & instance()
Instance from the current thread.
Keep informations about a mesh crossed by level-sets.
mesh & linked_mesh(void) const
Gives a reference to the linked mesh of type mesh.
structure used to hold a set of convexes and/or convex faces.
Apply a serie a slicing operations to a mesh.
void exec(size_type nrefine, const mesh_region &cvlst)
build a new mesh_slice.
mesh_slicer(const mesh &m_)
mesh_slicer constructor.
Describe a mesh (collection of convexes (elements) and points).
Definition: getfem_mesh.h:98
ref_mesh_face_pt_ct points_of_face_of_convex(size_type ic, short_type f) const
Return a (pseudo)container of points of face of a given convex.
Definition: getfem_mesh.h:181
base_small_vector normal_of_face_of_convex(size_type ic, short_type f, const base_node &pt) const
Return the normal of the given convex face, evaluated at the point pt.
Definition: getfem_mesh.cc:383
void clear()
Erase the mesh.
Definition: getfem_mesh.cc:272
size_type add_segment_by_points(const base_node &pt1, const base_node &pt2)
Add a segment to the mesh, given the coordinates of its vertices.
Definition: getfem_mesh.h:261
int orient
orient defines the kind of slicing : VOLIN -> keep the inside of the volume, VOLBOUND -> its boundary...
static scalar_type trinom(scalar_type a, scalar_type b, scalar_type c)
Utility function.
The output of a getfem::mesh_slicer which has been recorded.
const mesh & linked_mesh() const
return a pointer to the original mesh
A simple singleton implementation.
Keep informations about a mesh crossed by level-sets.
Define the class getfem::stored_mesh_slice.
Define various mesh slicers.
number_traits< typename linalg_traits< V1 >::value_type >::magnitude_type vect_dist2_sqr(const V1 &v1, const V2 &v2)
squared Euclidean distance between two vectors
Definition: gmm_blas.h:564
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2_sqr(const V &v)
squared Euclidean norm of a vector.
Definition: gmm_blas.h:543
strongest_value_type< V1, V2 >::value_type vect_sp(const V1 &v1, const V2 &v2)
*‍/
Definition: gmm_blas.h:263
void add(const L1 &l1, L2 &l2)
*‍/
Definition: gmm_blas.h:1275
void APIDECL outer_faces_of_mesh(const mesh &m, const dal::bit_vector &cvlst, convex_face_ct &flist)
returns a list of "exterior" faces of a mesh (i.e.
Definition: getfem_mesh.cc:821
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
Definition: getfem_fem.h:243
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:72
const basic_mesh * refined_simplex_mesh_for_convex(pconvex_ref cvr, short_type k)
simplexify a convex_ref.
const std::vector< std::unique_ptr< mesh_structure > > & refined_simplex_mesh_for_convex_faces(pconvex_ref cvr, short_type k)
simplexify the faces of a convex_ref
pconvex_structure simplex_structure(dim_type nc)
Give a pointer on the structures of a simplex of dimension d.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:48
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
GEneric Tool for Finite Element Methods.