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