gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
delaunay3d.cpp
Go to the documentation of this file.
1 // Gmsh - Copyright (C) 1997-2022 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 
6 #if defined(_OPENMP)
7 #include <omp.h>
8 #endif
9 
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <set>
13 #include <stack>
14 #include <map>
15 #include <vector>
16 #include <algorithm>
17 #include <cmath>
18 #include <queue>
19 #include "SPoint3.h"
20 #include "SBoundingBox3d.h"
21 #include "delaunay3d.h"
22 #include "MVertex.h"
23 #include "MTetrahedron.h"
25 #include "Context.h"
26 #include "robustPredicates.h"
27 #include "OS.h"
28 
29 #ifndef MAX_NUM_THREADS_
30 #define MAX_NUM_THREADS_ 8
31 #endif
32 
33 typedef unsigned char CHECKTYPE;
34 struct Tet;
35 
36 struct Vert {
37 private:
38  double _x[3];
39  double _lc;
40  std::size_t _num;
41  Tet *_t;
42 
43 public:
44  inline void setT(Tet *t) { _t = t; }
45  inline Tet *getT() const { return _t; }
46  inline std::size_t getNum() const { return _num; }
47  inline void setNum(std::size_t n) { _num = n; }
48  unsigned char _thread;
49  inline double x() const { return _x[0]; }
50  inline double y() const { return _x[1]; }
51  inline double z() const { return _x[2]; }
52  inline double lc() const { return _lc; }
53  inline double &x() { return _x[0]; }
54  inline double &y() { return _x[1]; }
55  inline double &z() { return _x[2]; }
56  inline double &lc() { return _lc; }
57  inline operator double *() { return _x; }
58  Vert(double X = 0, double Y = 0, double Z = 0, double lc = 0, int num = 0)
59  : _num(num), _t(nullptr), _thread(0)
60  {
61  _x[0] = X;
62  _x[1] = Y;
63  _x[2] = Z;
64  _lc = lc;
65  }
66  Vert operator+(const Vert &other)
67  {
68  return Vert(x() + other.x(), y() + other.y(), z() + other.z(),
69  other.lc() + _lc);
70  }
71  Vert operator*(const double &other)
72  {
73  return Vert(x() * other, y() * other, z() * other, _lc * other);
74  }
75  SPoint3 point() const { return SPoint3(x(), y(), z()); }
76 };
77 
78 static double orientationTestFast(double *pa, double *pb, double *pc,
79  double *pd)
80 {
81  const double adx = pa[0] - pd[0];
82  const double bdx = pb[0] - pd[0];
83  const double cdx = pc[0] - pd[0];
84  const double ady = pa[1] - pd[1];
85  const double bdy = pb[1] - pd[1];
86  const double cdy = pc[1] - pd[1];
87  const double adz = pa[2] - pd[2];
88  const double bdz = pb[2] - pd[2];
89  const double cdz = pc[2] - pd[2];
90 
91  return adx * (bdy * cdz - bdz * cdy) + bdx * (cdy * adz - cdz * ady) +
92  cdx * (ady * bdz - adz * bdy);
93 }
94 
95 static bool inSphereTest_s(Vert *va, Vert *vb, Vert *vc, Vert *vd, Vert *ve)
96 {
97  double val = robustPredicates::insphere(
98  (double *)va, (double *)vb, (double *)vc, (double *)vd, (double *)ve);
99  if(val == 0.0) {
100  Msg::Info("Symbolic perturbation needed vol %22.15E",
101  orientationTestFast((double *)va, (double *)vb, (double *)vc,
102  (double *)vd));
103  int count;
104  // symbolic perturbation
105  Vert *pt[5] = {va, vb, vc, vd, ve};
106  int swaps = 0;
107  int n = 5;
108  do {
109  count = 0;
110  n = n - 1;
111  for(int i = 0; i < n; i++) {
112  if(pt[i] > pt[i + 1]) {
113  Vert *swappt = pt[i];
114  pt[i] = pt[i + 1];
115  pt[i + 1] = swappt;
116  count++;
117  }
118  }
119  swaps += count;
120  } while(count > 0);
121  double oriA = robustPredicates::orient3d((double *)pt[1], (double *)pt[2],
122  (double *)pt[3], (double *)pt[4]);
123  if(oriA != 0.0) {
124  // Flip the sign if there are odd number of swaps.
125  if((swaps % 2) != 0) oriA = -oriA;
126  val = oriA;
127  }
128  else {
129  double oriB = -robustPredicates::orient3d(
130  (double *)pt[0], (double *)pt[2], (double *)pt[3], (double *)pt[4]);
131  if(oriB == 0.0) {
132  Msg::Error("Symbolic perturbation failed in icCircle Predicate");
133  }
134  // Flip the sign if there are odd number of swaps.
135  if((swaps % 2) != 0) oriB = -oriB;
136  val = oriB;
137  }
138  }
139  return val > 0;
140 }
141 
142 struct Face {
143  Vert *v[3];
144  Vert *V[3];
145  Face(Vert *v1, Vert *v2, Vert *v3)
146  {
147  V[0] = v[0] = v1;
148  V[1] = v[1] = v2;
149  V[2] = v[2] = v3;
150 #define cswap(a, b) \
151  do { \
152  if(a > b) { \
153  Vert *tmp = a; \
154  a = b; \
155  b = tmp; \
156  } \
157  } while(0)
158  cswap(v[0], v[1]);
159  cswap(v[1], v[2]);
160  cswap(v[0], v[1]);
161  }
162 
163  bool operator==(const Face &other) const
164  {
165  return v[0] == other.v[0] && v[1] == other.v[1] && v[2] == other.v[2];
166  }
167 
168  bool operator<(const Face &other) const
169  {
170  if(v[0] < other.v[0]) return true;
171  if(v[0] > other.v[0]) return false;
172  if(v[1] < other.v[1]) return true;
173  if(v[1] > other.v[1]) return false;
174  if(v[2] < other.v[2]) return true;
175  return false;
176  }
177 };
178 
179 struct Tet {
180  Tet *T[4];
181  Vert *V[4];
183  bool _modified;
184 
185  Tet() : _modified(true)
186  {
187  V[0] = V[1] = V[2] = V[3] = nullptr;
188  T[0] = T[1] = T[2] = T[3] = nullptr;
189  setAllDeleted();
190  }
191  int setVerticesNoTest(Vert *v0, Vert *v1, Vert *v2, Vert *v3)
192  {
193  _modified = true;
194  V[0] = v0;
195  V[1] = v1;
196  V[2] = v2;
197  V[3] = v3;
198  for(int i = 0; i < 4; i++)
199  if(V[i]) V[i]->setT(this);
200  return 1;
201  }
202  int setVertices(Vert *v0, Vert *v1, Vert *v2, Vert *v3)
203  {
204  _modified = true;
205  double val = robustPredicates::orient3d((double *)v0, (double *)v1,
206  (double *)v2, (double *)v3);
207  V[0] = v0;
208  V[1] = v1;
209  V[2] = v2;
210  V[3] = v3;
211  for(int i = 0; i < 4; i++)
212  if(V[i]) V[i]->setT(this);
213  if(val > 0) { return 1; }
214  else if(val < 0) {
215  V[0] = v1;
216  V[1] = v0;
217  V[2] = v2;
218  V[3] = v3;
219  return -1;
220  }
221  else {
222  return 0;
223  }
224  }
225  Tet(Vert *v0, Vert *v1, Vert *v2, Vert *v3)
226  {
227  setVertices(v0, v1, v2, v3);
228  T[0] = T[1] = T[2] = T[3] = nullptr;
229  setAllDeleted();
230  }
232  {
233  for(int i = 0; i < MAX_NUM_THREADS_; i++) _bitset[i] = 0x0;
234  }
235  void unset(int thread, int iPnt) { _bitset[thread] &= ~(1 << iPnt); }
236  void set(int thread, int iPnt) { _bitset[thread] |= (1 << iPnt); }
237  CHECKTYPE isSet(int thread, int iPnt) const
238  {
239  return _bitset[thread] & (1 << iPnt);
240  }
241  Face getFace(int k) const
242  {
243  const int fac[4][3] = {{0, 1, 2}, {1, 3, 2}, {2, 3, 0}, {1, 0, 3}};
244  return Face(V[fac[k][0]], V[fac[k][1]], V[fac[k][2]]);
245  }
246  Vert *getOppositeVertex(int k) const
247  {
248  const int o[4] = {3, 0, 1, 2};
249  return V[o[k]];
250  }
251  bool inSphere(Vert *vd, int thread)
252  {
253  return inSphereTest_s(V[0], V[1], V[2], V[3], vd);
254  }
255 };
256 
257 struct conn {
259  int i;
260  Tet *t;
261  conn() : f(nullptr, nullptr, nullptr), i(0), t(nullptr) {}
262  conn(Face _f, int _i, Tet *_t) : f(_f), i(_i), t(_t) {}
263  bool operator==(const conn &c) const { return f == c.f; }
264  bool operator<(const conn &c) const { return f < c.f; }
265 };
266 
267 // tetrahedra (one per thread)
268 template <class T> class aBunchOfStuff {
269 public:
270  std::vector<T *> _all;
271  std::size_t _current;
272  std::size_t _nbAlloc;
273  std::size_t size() { return _current + (_all.size() - 1) * _nbAlloc; }
274 
275 public:
276  T *operator()(std::size_t i)
277  {
278  const std::size_t _array = i / _nbAlloc;
279  const std::size_t _offset = i % _nbAlloc;
280  return _all[_array] + _offset;
281  }
282  aBunchOfStuff(std::size_t s) : _current(0), _nbAlloc(s)
283  {
284  if(!_nbAlloc) _nbAlloc = 1;
285  _all.push_back(new T[_nbAlloc]);
286  }
288  {
289  for(std::size_t i = 0; i < _all.size(); i++) { delete[] _all[i]; }
290  }
291  T *newStuff()
292  {
293  if(_current == _nbAlloc) {
294  _all.push_back(new T[_nbAlloc]);
295  _current = 0;
296  }
297  _current++;
298  return _all[_all.size() - 1] + (_current - 1);
299  }
300 };
301 
302 // tetAllocator owns the tets that have been allocated by itself
304  std::vector<aBunchOfStuff<Tet> *> _perThread;
305 
306 public:
307  std::size_t size(int thread) const
308  {
309  if((int)_perThread.size() <= thread) return 0;
310  return _perThread[thread]->size();
311  }
312  Tet *operator()(int thread, int j) const { return (*_perThread[thread])(j); }
313  tetContainer(int nbThreads, int preallocSizePerThread)
314  {
315  _perThread.resize(nbThreads);
316  for(std::size_t i = 0; i < _perThread.size(); i++) {
317  _perThread[i] = new aBunchOfStuff<Tet>(preallocSizePerThread);
318  }
319  }
320  Tet *newTet(int thread) { return _perThread[thread]->newStuff(); }
322  {
323  for(std::size_t i = 0; i < _perThread.size(); i++) delete _perThread[i];
324  }
325 };
326 
327 typedef std::vector<Tet *> cavityContainer;
328 typedef std::vector<conn> connContainer;
329 
330 struct HilbertSortB {
331  // The code for generating table transgc from:
332  // http://graphics.stanford.edu/~seander/bithacks.html.
333  int transgc[8][3][8];
334  int tsb1mod3[8];
335  int maxDepth;
336  int Limit;
338  void ComputeGrayCode(int n);
339  int Split(Vert **vertices, int arraysize, int GrayCode0, int GrayCode1,
340  double BoundingBoxXmin, double BoundingBoxXmax,
341  double BoundingBoxYmin, double BoundingBoxYmax,
342  double BoundingBoxZmin, double BoundingBoxZmax);
343  void Sort(Vert **vertices, int arraysize, int e, int d,
344  double BoundingBoxXmin, double BoundingBoxXmax,
345  double BoundingBoxYmin, double BoundingBoxYmax,
346  double BoundingBoxZmin, double BoundingBoxZmax, int depth);
347  HilbertSortB(int m = 0, int l = 2) : maxDepth(m), Limit(l)
348  {
349  ComputeGrayCode(3);
350  }
351  void MultiscaleSortHilbert(Vert **vertices, int arraysize, int threshold,
352  double ratio, int *depth,
353  std::vector<int> &indices)
354  {
355  int middle = 0;
356  if(arraysize >= threshold) {
357  (*depth)++;
358  middle = (int)(arraysize * ratio);
359  MultiscaleSortHilbert(vertices, middle, threshold, ratio, depth, indices);
360  }
361  indices.push_back(middle);
362  Sort(&(vertices[middle]), arraysize - middle, 0, 0, bbox.min().x(),
363  bbox.max().x(), bbox.min().y(), bbox.max().y(), bbox.min().z(),
364  bbox.max().z(), 0);
365  }
366  void Apply(std::vector<Vert *> &v, std::vector<int> &indices)
367  {
368  indices.clear();
369  if(v.empty()) return;
370  for(size_t i = 0; i < v.size(); i++) {
371  Vert *pv = v[i];
372  bbox += SPoint3(pv->x(), pv->y(), pv->z());
373  }
374  bbox *= 1.01;
375  Vert **pv = &v[0];
376  int depth;
377  indices.clear();
378  MultiscaleSortHilbert(pv, (int)v.size(), 64, .125, &depth, indices);
379  indices.push_back(v.size());
380  }
381 };
382 
384 {
385  int gc[8], N, mask, travel_bit;
386  int e, d, f, k, g;
387  int v, c;
388  int i;
389 
390  N = (n == 2) ? 4 : 8;
391  mask = (n == 2) ? 3 : 7;
392 
393  // Generate the Gray code sequence.
394  for(i = 0; i < N; i++) { gc[i] = i ^ (i >> 1); }
395 
396  for(e = 0; e < N; e++) {
397  for(d = 0; d < n; d++) {
398  // Calculate the end point (f).
399  f = e ^ (1 << d); // Toggle the d-th bit of 'e'.
400  // travel_bit = 2**p, the bit we want to travel.
401  travel_bit = e ^ f;
402  for(i = 0; i < N; i++) {
403  // // Rotate gc[i] left by (p + 1) % n bits.
404  k = gc[i] * (travel_bit * 2);
405  g = ((k | (k / N)) & mask);
406  // Calculate the permuted Gray code by xor with the start point (e).
407  transgc[e][d][i] = (g ^ e);
408  }
409  // assert(transgc[e][d][0] == e);
410  // assert(transgc[e][d][N - 1] == f);
411  } // d
412  } // e
413 
414  // Count the consecutive '1' bits (trailing) on the right.
415  tsb1mod3[0] = 0;
416  for(i = 1; i < N; i++) {
417  v = ~i; // Count the 0s.
418  v = (v ^ (v - 1)) >> 1; // Set v's trailing 0s to 1s and zero rest
419  for(c = 0; v; c++) { v >>= 1; }
420  tsb1mod3[i] = c % n;
421  }
422 }
423 
424 int HilbertSortB::Split(Vert **vertices, int arraysize, int GrayCode0,
425  int GrayCode1, double BoundingBoxXmin,
426  double BoundingBoxXmax, double BoundingBoxYmin,
427  double BoundingBoxYmax, double BoundingBoxZmin,
428  double BoundingBoxZmax)
429 {
430  Vert *swapvert;
431  int axis, d;
432  double split;
433 
434  // Find the current splitting axis. 'axis' is a value 0, or 1, or 2, which
435  // correspoding to x-, or y- or z-axis.
436  axis = (GrayCode0 ^ GrayCode1) >> 1;
437 
438  // Calulate the split position along the axis.
439  if(axis == 0) { split = 0.5 * (BoundingBoxXmin + BoundingBoxXmax); }
440  else if(axis == 1) {
441  split = 0.5 * (BoundingBoxYmin + BoundingBoxYmax);
442  }
443  else { // == 2
444  split = 0.5 * (BoundingBoxZmin + BoundingBoxZmax);
445  }
446 
447  // Find the direction (+1 or -1) of the axis. If 'd' is +1, the direction of
448  // the axis is to the positive of the axis, otherwise, it is -1.
449  d = ((GrayCode0 & (1 << axis)) == 0) ? 1 : -1;
450 
451  // Partition the vertices into left- and right-arrays such that left points
452  // have Hilbert indices lower than the right points.
453  int i = 0;
454  int j = arraysize - 1;
455 
456  // Partition the vertices into left- and right-arrays.
457  if(d > 0) {
458  do {
459  for(; i < arraysize; i++) {
460  if(vertices[i]->point()[axis] >= split) break;
461  }
462  for(; j >= 0; j--) {
463  if(vertices[j]->point()[axis] < split) break;
464  }
465  // Is the partition finished?
466  if(i >= (j + 1)) break;
467  // Swap i-th and j-th vertices.
468  swapvert = vertices[i];
469  vertices[i] = vertices[j];
470  vertices[j] = swapvert;
471  // Continue patitioning the array;
472  } while(true);
473  }
474  else {
475  do {
476  for(; i < arraysize; i++) {
477  if(vertices[i]->point()[axis] <= split) break;
478  }
479  for(; j >= 0; j--) {
480  if(vertices[j]->point()[axis] > split) break;
481  }
482  // Is the partition finished?
483  if(i >= (j + 1)) break;
484  // Swap i-th and j-th vertices.
485  swapvert = vertices[i];
486  vertices[i] = vertices[j];
487  vertices[j] = swapvert;
488  // Continue patitioning the array;
489  } while(true);
490  }
491 
492  return i;
493 }
494 
495 // The sorting code is inspired by Tetgen 1.5
496 void HilbertSortB::Sort(Vert **vertices, int arraysize, int e, int d,
497  double BoundingBoxXmin, double BoundingBoxXmax,
498  double BoundingBoxYmin, double BoundingBoxYmax,
499  double BoundingBoxZmin, double BoundingBoxZmax,
500  int depth)
501 {
502  double x1, x2, y1, y2, z1, z2;
503  int p[9], w, e_w, d_w, k, ei, di;
504  int n = 3, mask = 7;
505 
506  p[0] = 0;
507  p[8] = arraysize;
508 
509  p[4] = Split(vertices, p[8], transgc[e][d][3], transgc[e][d][4],
510  BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin,
511  BoundingBoxYmax, BoundingBoxZmin, BoundingBoxZmax);
512  p[2] = Split(vertices, p[4], transgc[e][d][1], transgc[e][d][2],
513  BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin,
514  BoundingBoxYmax, BoundingBoxZmin, BoundingBoxZmax);
515  p[1] = Split(vertices, p[2], transgc[e][d][0], transgc[e][d][1],
516  BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin,
517  BoundingBoxYmax, BoundingBoxZmin, BoundingBoxZmax);
518  p[3] =
519  Split(&(vertices[p[2]]), p[4] - p[2], transgc[e][d][2], transgc[e][d][3],
520  BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin, BoundingBoxYmax,
521  BoundingBoxZmin, BoundingBoxZmax) +
522  p[2];
523  p[6] =
524  Split(&(vertices[p[4]]), p[8] - p[4], transgc[e][d][5], transgc[e][d][6],
525  BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin, BoundingBoxYmax,
526  BoundingBoxZmin, BoundingBoxZmax) +
527  p[4];
528  p[5] =
529  Split(&(vertices[p[4]]), p[6] - p[4], transgc[e][d][4], transgc[e][d][5],
530  BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin, BoundingBoxYmax,
531  BoundingBoxZmin, BoundingBoxZmax) +
532  p[4];
533  p[7] =
534  Split(&(vertices[p[6]]), p[8] - p[6], transgc[e][d][6], transgc[e][d][7],
535  BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin, BoundingBoxYmax,
536  BoundingBoxZmin, BoundingBoxZmax) +
537  p[6];
538 
539  if(maxDepth > 0) {
540  if((depth + 1) == maxDepth) {
541  // printf("max depth attained\n");
542  return;
543  }
544  }
545 
546  // Recursively sort the points in sub-boxes.
547  for(w = 0; w < 8; w++) {
548  if((p[w + 1] - p[w]) > Limit) {
549  if(w == 0) { e_w = 0; }
550  else {
551  k = 2 * ((w - 1) / 2);
552  e_w = k ^ (k >> 1);
553  }
554  k = e_w;
555  e_w = ((k << (d + 1)) & mask) | ((k >> (n - d - 1)) & mask);
556  ei = e ^ e_w;
557  if(w == 0) { d_w = 0; }
558  else {
559  d_w = ((w % 2) == 0) ? tsb1mod3[w - 1] : tsb1mod3[w];
560  }
561  di = (d + d_w + 1) % n;
562  if(transgc[e][d][w] & 1) {
563  x1 = 0.5 * (BoundingBoxXmin + BoundingBoxXmax);
564  x2 = BoundingBoxXmax;
565  }
566  else {
567  x1 = BoundingBoxXmin;
568  x2 = 0.5 * (BoundingBoxXmin + BoundingBoxXmax);
569  }
570  if(transgc[e][d][w] & 2) { // y-axis
571  y1 = 0.5 * (BoundingBoxYmin + BoundingBoxYmax);
572  y2 = BoundingBoxYmax;
573  }
574  else {
575  y1 = BoundingBoxYmin;
576  y2 = 0.5 * (BoundingBoxYmin + BoundingBoxYmax);
577  }
578  if(transgc[e][d][w] & 4) { // z-axis
579  z1 = 0.5 * (BoundingBoxZmin + BoundingBoxZmax);
580  z2 = BoundingBoxZmax;
581  }
582  else {
583  z1 = BoundingBoxZmin;
584  z2 = 0.5 * (BoundingBoxZmin + BoundingBoxZmax);
585  }
586  Sort(&(vertices[p[w]]), p[w + 1] - p[w], ei, di, x1, x2, y1, y2, z1, z2,
587  depth + 1);
588  }
589  }
590 }
591 
592 static void SortHilbert(std::vector<Vert *> &v, std::vector<int> &indices)
593 {
594  HilbertSortB h(1000);
595  h.Apply(v, indices);
596 }
597 
598 static void computeAdjacencies(Tet *t, int iFace, connContainer &faceToTet)
599 {
600  conn c(t->getFace(iFace), iFace, t);
601  auto it = std::find(faceToTet.begin(), faceToTet.end(), c);
602  if(it == faceToTet.end()) { faceToTet.push_back(c); }
603  else {
604  t->T[iFace] = it->t;
605  it->t->T[it->i] = t;
606  faceToTet.erase(it);
607  }
608 }
609 
610 /*
611 static void printtet(const char *c, Tet *t)
612 {
613  printf("%s ", c);
614  if(t->V[0])
615  printf("%7d %7d %7d %7d\n", t->V[0]->getNum(), t->V[1]->getNum(),
616  t->V[2]->getNum(), t->V[3]->getNum());
617 }
618 */
619 
620 // Fixing a non star shaped cavity (non delaunay triangulations). See
621 // P.L. George's paper "Improvements on Delaunay-based three-dimensional
622 // automatic mesh generator", Finite Elements in Analysis and Design 25 (1997)
623 // 297-317
624 
625 static void starShapeness(Vert *v, connContainer &bndK,
626  std::vector<std::size_t> &_negatives)
627 {
628  _negatives.clear();
629  for(std::size_t i = 0; i < bndK.size(); i++) {
630  // no symbolic perturbation
631  const double val = robustPredicates::orient3d(
632  (double *)bndK[i].f.V[0], (double *)bndK[i].f.V[1],
633  (double *)bndK[i].f.V[2], (double *)v);
634  if(val <= 0.0) { _negatives.push_back(i); }
635  }
636 }
637 
638 static Tet *tetContainsV(Vert *v, cavityContainer &cavity)
639 {
640  for(std::size_t i = 0; i < cavity.size(); i++) {
641  std::size_t count = 0;
642  for(std::size_t j = 0; j < 4; j++) {
643  Face f = cavity[i]->getFace(j);
644  const double val = robustPredicates::orient3d(
645  (double *)f.V[0], (double *)f.V[1], (double *)f.V[2], (double *)v);
646  if(val >= 0) { count++; }
647  }
648  if(count == 4) return cavity[i];
649  }
650  return nullptr;
651 }
652 
653 static void buildDelaunayBall(cavityContainer &cavity, connContainer &faceToTet)
654 {
655  faceToTet.clear();
656  for(std::size_t i = 0; i < cavity.size(); i++) {
657  Tet *t = cavity[i];
658  for(std::size_t iFace = 0; iFace < 4; iFace++) {
659  Tet *neigh = t->T[iFace];
660  conn c(t->getFace(iFace), iFace, neigh);
661  auto it = std::find(faceToTet.begin(), faceToTet.end(), c);
662  if(it == faceToTet.end()) { faceToTet.push_back(c); }
663  else {
664  faceToTet.erase(it);
665  }
666  }
667  }
668 }
669 
670 static bool removeIsolatedTets(Tet *containsV, cavityContainer &cavity,
671  connContainer &bndK, int myThread, int K)
672 {
673  cavityContainer cc;
674  cc.push_back(containsV);
675  std::stack<Tet *> _stack;
676  _stack.push(containsV);
677 
678  while(!_stack.empty()) {
679  Tet *t = _stack.top();
680  _stack.pop();
681  for(int i = 0; i < 4; i++) {
682  Tet *neigh = t->T[i];
683  if(neigh && (std::find(cc.begin(), cc.end(), neigh) == cc.end()) &&
684  (std::find(cavity.begin(), cavity.end(), neigh) != cavity.end())) {
685  cc.push_back(neigh);
686  _stack.push(neigh);
687  }
688  }
689  }
690  if(cc.size() == cavity.size()) return false;
691  // Msg::Info(" cavity updated(%3ld elements) %3ld isolated tet removed",
692  // cavity.size(),cavity.size()-cc.size());
693  cavity = cc;
694  return true;
695 }
696 
698 {
699  // printf("size of cavity %ld\n",cavity.size());
700  for(std::size_t i = 0; i < cavity.size(); i++) {
701  Tet *t = cavity[i];
702  for(std::size_t iFace = 0; iFace < 4; iFace++) {
703  if(t->getFace(iFace) == f) { return t; }
704  }
705  }
706  return nullptr;
707 }
708 
709 static bool fixDelaunayCavity(Vert *v, cavityContainer &cavity,
710  connContainer &bndK, int myThread, int K,
711  std::vector<std::size_t> &_negatives)
712 {
713  starShapeness(v, bndK, _negatives);
714 
715  if(_negatives.empty()) return false;
716 
717  // unset all tets of the cavity
718  for(std::size_t i = 0; i < cavity.size(); i++) cavity[i]->unset(myThread, K);
719  for(std::size_t i = 0; i < bndK.size(); i++)
720  if(bndK[i].t) bndK[i].t->unset(myThread, K);
721 
722  // return true;
723 
724  Msg::Debug("Fixing cavity (%3ld,%3ld) : %ld negatives", cavity.size(),
725  bndK.size(), _negatives.size());
726 
727  Tet *containsV = tetContainsV(v, cavity);
728 
729  if(!containsV) return true;
730 
731  while(!_negatives.empty()) {
732  for(std::size_t i = 0; i < _negatives.size(); i++) {
733  conn &c = bndK[_negatives[i]];
734  Tet *toRemove = tetInsideCavityWithFAce(c.f, cavity);
735  if(toRemove) {
736  auto it = std::find(cavity.begin(), cavity.end(), toRemove);
737  if(it != cavity.end()) { cavity.erase(it); }
738  else {
739  Msg::Error("Datastructure Broken in %s line %5d", __FILE__, __LINE__);
740  break;
741  }
742  }
743  }
744  removeIsolatedTets(containsV, cavity, bndK, myThread, K);
745  buildDelaunayBall(cavity, bndK);
746  starShapeness(v, bndK, _negatives);
747  }
748  for(std::size_t i = 0; i < cavity.size(); i++) cavity[i]->set(myThread, K);
749  for(std::size_t i = 0; i < bndK.size(); i++)
750  if(bndK[i].t) bndK[i].t->set(myThread, K);
751  return false;
752 }
753 
754 static void delaunayCavity2(Tet *tet, Tet *prevTet, Vert *v,
755  cavityContainer &cavity, connContainer &bnd,
756  int thread, int iPnt)
757 {
758  std::stack<std::pair<std::pair<Tet *, Tet *>, std::pair<int, int> > > stack;
759  bool finished = false;
760  Tet *t = tet;
761  Tet *prev = prevTet;
762  int iNeighStart = 0;
763  const int maxNumberNeigh = 4;
764  int iNeighEnd = maxNumberNeigh;
765  while(!finished) {
766  if(iNeighStart == 0) {
767  t->set(thread, iPnt); // Mark the triangle
768  cavity.push_back(t);
769  }
770 
771  for(int iNeigh = iNeighStart; iNeigh < iNeighEnd; iNeigh++) {
772  Tet *neigh = t->T[iNeigh];
773  if(neigh == nullptr) {
774  bnd.push_back(conn(t->getFace(iNeigh), iNeigh, neigh));
775  }
776  else if(neigh == prev) {
777  }
778  else if(!neigh->inSphere(v, thread)) {
779  bnd.push_back(conn(t->getFace(iNeigh), iNeigh, neigh));
780  neigh->set(thread, iPnt);
781  }
782  else if(!(neigh->isSet(thread, iPnt))) {
783  // First, add rest of neighbours to stack
784  stack.push(std::make_pair(std::make_pair(prev, t),
785  std::make_pair(iNeigh + 1, maxNumberNeigh)));
786 
787  // Second, add neighbour itself to stack
788  stack.push(std::make_pair(std::make_pair(t, neigh),
789  std::make_pair(0, maxNumberNeigh)));
790 
791  // Break out loop
792  break;
793  }
794  }
795 
796  if(stack.empty()) { finished = true; }
797  else {
798  const std::pair<std::pair<Tet *, Tet *>, std::pair<int, int> > &next =
799  stack.top();
800  prev = next.first.first;
801  t = next.first.second;
802  iNeighStart = next.second.first;
803  iNeighEnd = next.second.second;
804  stack.pop();
805  }
806  }
807 }
808 
809 static Tet *walk(Tet *t, Vert *v, int maxx, double &totSearch, int thread)
810 {
811  std::set<Tet *> investigatedTets;
812  std::queue<Tet *> tets;
813  investigatedTets.insert(t);
814  while(1) {
815  totSearch++;
816  if(t == nullptr) {
817  return nullptr; // we should NEVER return here
818  }
819  // if(t->inSphere(v,thread)){return t;}
820  double _min = 0.0;
821  int NEIGH = -1;
822  int count = 0;
823  for(int iNeigh = 0; iNeigh < 4; iNeigh++) {
824  Face f = t->getFace(iNeigh);
825  double val = robustPredicates::orient3d(
826  (double *)f.V[0], (double *)f.V[1], (double *)f.V[2], (double *)v);
827  if(val >= 0.0) count++;
828  if(val < _min) {
829  if(!investigatedTets.count(t->T[iNeigh])) {
830  NEIGH = iNeigh;
831  _min = val;
832  }
833  else {
834  tets.push(t->T[iNeigh]);
835  }
836  }
837  }
838  if(count == 4 && t->inSphere(v, thread)) return t;
839  if(NEIGH >= 0) {
840  t = t->T[NEIGH];
841  investigatedTets.insert(t);
842  }
843  else if(tets.empty()) {
844  Msg::Error("Jump-and-walk failed (no neighbor)");
845  return nullptr;
846  }
847  else {
848  t = tets.front();
849  tets.pop();
850  }
851  }
852  Msg::Error("Jump-and-walk failed (no neighbor)");
853  return nullptr;
854 }
855 
856 /*
857 static void print(const char *name, connContainer &conn, Vert *v)
858 {
859  FILE *f = fopen(name, "w");
860  fprintf(f, "View \"\"{\n");
861 
862  if(v) fprintf(f, "SP(%g,%g,%g){%d};\n", v->x(), v->y(), v->z(), v->getNum());
863 
864  for(std::size_t i = 0; i < conn.size(); i++) {
865  fprintf(f, "ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g};\n",
866  conn[i].f.V[0]->x(), conn[i].f.V[0]->y(), conn[i].f.V[0]->z(),
867  conn[i].f.V[1]->x(), conn[i].f.V[1]->y(), conn[i].f.V[1]->z(),
868  conn[i].f.V[2]->x(), conn[i].f.V[2]->y(), conn[i].f.V[2]->z(), 1.,
869  1., 1.);
870  }
871  fprintf(f, "};\n");
872  fclose(f);
873 }
874 */
875 
876 /*
877 static void print(const char *name, int thread, tetContainer &T, Vert *v)
878 {
879  FILE *f = fopen(name, "w");
880  fprintf(f, "View \"\"{\n");
881  if(v) fprintf(f, "SP(%g,%g,%g){%d};\n", v->x(), v->y(), v->z(), v->getNum());
882 
883  for(std::size_t i = 0; i < T.size(thread); i++) {
884  Tet *tt = T(thread, i);
885  if(tt->V[0]) {
886  // double val = robustPredicates::orient3d
887  //
888 ((double*)tt->V[0],(double*)tt->V[1],(double*)tt->V[2],(double*)tt->V[3]);
889  if(!v) {
890  fprintf(f, "SS(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g,%g};\n",
891  tt->V[0]->x(), tt->V[0]->y(), tt->V[0]->z(), tt->V[1]->x(),
892  tt->V[1]->y(), tt->V[1]->z(), tt->V[2]->x(), tt->V[2]->y(),
893  tt->V[2]->z(), tt->V[3]->x(), tt->V[3]->y(), tt->V[3]->z(),
894  tt->V[0]->lc(), tt->V[1]->lc(), tt->V[2]->lc(), tt->V[3]->lc());
895  }
896  else {
897  fprintf(f, "SS(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g){%d,%d,%d,%d};\n",
898  tt->V[0]->x(), tt->V[0]->y(), tt->V[0]->z(), tt->V[1]->x(),
899  tt->V[1]->y(), tt->V[1]->z(), tt->V[2]->x(), tt->V[2]->y(),
900  tt->V[2]->z(), tt->V[3]->x(), tt->V[3]->y(), tt->V[3]->z(),
901  tt->V[0]->getNum(), tt->V[1]->getNum(), tt->V[2]->getNum(),
902  tt->V[3]->getNum());
903  }
904  }
905  }
906  fprintf(f, "};\n");
907  fclose(f);
908 }
909 */
910 
911 // xx10000 ok if all bits on my right are 0
912 
913 static bool canWeProcessCavity(cavityContainer &cavity, std::size_t myThread,
914  std::size_t iPt)
915 {
916  std::size_t cSize = cavity.size();
917  for(std::size_t j = 0; j < cSize; j++) {
918  Tet *f = cavity[j];
919  for(std::size_t index = 0; index < myThread; index++) {
920  if(f->_bitset[index]) return false;
921  }
922  if(iPt) {
923  if(f->_bitset[myThread] & ((1 << iPt) - 1)) return false;
924  }
925  }
926  return true;
927 }
928 
929 /*
930 static bool checkLocalDelaunayness(Tet *t)
931 {
932  if(t->V[0]) {
933  for(int i = 0; i < 4; i++) {
934  Tet *n = t->T[i];
935  if(n && n->inSphere(t->getOppositeVertex(i), 0)) return false;
936  }
937  }
938  return true;
939 }
940 */
941 
942 /*
943 static int checkLocalDelaunayness(tetContainer &c, int thread, char *msg)
944 {
945  int nLoc = 0;
946  for(std::size_t i = 0; i < c.size(thread); i++) {
947  if(!checkLocalDelaunayness(c(thread, i))) nLoc++;
948  }
949  if(nLoc != 0) Msg::Info("%s --> %d tets are not locally delaunay", msg, nLoc);
950  return nLoc;
951 }
952 */
953 
954 static Tet *randomTet(int thread, tetContainer &allocator)
955 {
956  std::size_t N = allocator.size(thread);
957  // printf("coucou random TET %d %d\n",thread,N);
958  while(1) {
959  Tet *t = allocator(thread, rand() % N);
960  if(t->V[0]) return t;
961  }
962 }
963 
964 //#define VERBOSE
965 
966 void delaunayTrgl(const std::size_t numThreads, const std::size_t NPTS_AT_ONCE,
967  std::size_t Npts, std::vector<Vert *> assignTo[],
968  tetContainer &allocator)
969 {
970 #if defined(VERBOSE)
971  double totSearchGlob = 0;
972  double totCavityGlob = 0;
973  printf("%d threads for inserting %d points\n", numThreads, Npts);
974 #endif
975 
976  // checkLocalDelaunayness(allocator, 0, "initial");
977 
978  std::vector<int> invalidCavities(numThreads);
979  std::vector<int> cacheMisses(numThreads, 0);
980 
981  std::size_t maxLocSizeK = 0;
982  for(std::size_t i = 0; i < numThreads * NPTS_AT_ONCE; i++) {
983  std::size_t s = assignTo[i].size();
984  maxLocSizeK = std::max(maxLocSizeK, s);
985  }
986 
987 #pragma omp parallel num_threads(numThreads)
988  {
989 #if defined(_OPENMP)
990  int myThread = omp_get_thread_num();
991 #else
992  int myThread = 0;
993 #endif
994 
995  double totSearch = 0;
996  std::vector<std::size_t> _negatives;
997  std::vector<cavityContainer> cavity(NPTS_AT_ONCE);
998  std::vector<connContainer> bnd(NPTS_AT_ONCE);
999  std::vector<bool> ok(NPTS_AT_ONCE);
1000  connContainer faceToTet;
1001  std::vector<Tet *> Choice(NPTS_AT_ONCE);
1002  for(std::size_t K = 0; K < NPTS_AT_ONCE; K++)
1003  Choice[K] = randomTet(0, allocator);
1004 
1005  invalidCavities[myThread] = 0;
1006  for(std::size_t K = 0; K < NPTS_AT_ONCE; K++) {
1007  for(std::size_t iP = 0; iP < assignTo[K + myThread * NPTS_AT_ONCE].size();
1008  iP++) {
1009  if(numThreads != 1)
1010  assignTo[K + myThread * NPTS_AT_ONCE][iP]->_thread = myThread;
1011  }
1012  }
1013 
1014  std::vector<Vert *> vToAdd(NPTS_AT_ONCE);
1015 
1016 #pragma omp barrier
1017 
1018  // Main loop
1019  for(std::size_t iPGlob = 0; iPGlob < maxLocSizeK; iPGlob++) {
1020 #pragma omp barrier
1021  std::vector<Tet *> t(NPTS_AT_ONCE);
1022 
1023  // FIND SEEDS
1024  for(std::size_t K = 0; K < NPTS_AT_ONCE; K++) {
1025  vToAdd[K] = (iPGlob < assignTo[K + myThread * NPTS_AT_ONCE].size()) ?
1026  assignTo[K + myThread * NPTS_AT_ONCE][iPGlob] :
1027  nullptr;
1028 
1029  if(vToAdd[K]) {
1030  // In 3D, insertion of a point may lead to deletion of tets !!
1031  if(!Choice[K]->V[0]) Choice[K] = randomTet(0, allocator);
1032  while(1) {
1033  t[K] = walk(Choice[K], vToAdd[K], Npts, totSearch, myThread);
1034  if(t[K]) break;
1035  // the domain may not be convex. we then start from a random tet and
1036  // walk from there
1037  Choice[K] = randomTet(0, allocator);
1038  }
1039  }
1040  }
1041 
1042  // BUILD CAVITIES
1043  for(std::size_t K = 0; K < NPTS_AT_ONCE; K++) {
1044  if(vToAdd[K]) {
1045  cavityContainer &cavityK = cavity[K];
1046  connContainer &bndK = bnd[K];
1047  for(std::size_t i = 0; i < cavityK.size(); i++)
1048  cavityK[i]->unset(myThread, K);
1049  for(std::size_t i = 0; i < bndK.size(); i++)
1050  if(bndK[i].t) bndK[i].t->unset(myThread, K);
1051  cavityK.clear();
1052  bndK.clear();
1053  delaunayCavity2(t[K], nullptr, vToAdd[K], cavityK, bndK, myThread, K);
1054  // verify the cavity
1055  if(fixDelaunayCavity(vToAdd[K], cavityK, bndK, myThread, K,
1056  _negatives)) {
1057  vToAdd[K] = nullptr;
1058  invalidCavities[myThread]++;
1059  }
1060  }
1061  }
1062 
1063 #pragma omp barrier
1064  for(std::size_t K = 0; K < NPTS_AT_ONCE; K++) {
1065  if(!vToAdd[K])
1066  ok[K] = false;
1067  else
1068  ok[K] = canWeProcessCavity(cavity[K], myThread, K);
1069  }
1070 
1071  for(std::size_t K = 0; K < NPTS_AT_ONCE; K++) {
1072  if(ok[K]) {
1073  cavityContainer &cavityK = cavity[K];
1074  connContainer &bndK = bnd[K];
1075  faceToTet.clear();
1076  const std::size_t cSize = cavityK.size();
1077  const std::size_t bSize = bndK.size();
1078  Choice[K] = cavityK[0];
1079  for(std::size_t i = 0; i < bSize; i++) {
1080  // reuse memory slots of invalid elements
1081  Tet *t = (i < cSize) ? cavityK[i] : allocator.newTet(myThread);
1082  if(i < cSize && t->V[0]->_thread != myThread)
1083  cacheMisses[myThread]++;
1084  t->setVerticesNoTest(bndK[i].f.V[0], bndK[i].f.V[1], bndK[i].f.V[2],
1085  vToAdd[K]);
1086  Tet *neigh = bndK[i].t;
1087  t->T[0] = neigh;
1088  t->T[1] = t->T[2] = t->T[3] = nullptr;
1089  if(neigh) {
1090  if(neigh->getFace(0) == bndK[i].f)
1091  neigh->T[0] = t;
1092  else if(neigh->getFace(1) == bndK[i].f)
1093  neigh->T[1] = t;
1094  else if(neigh->getFace(2) == bndK[i].f)
1095  neigh->T[2] = t;
1096  else if(neigh->getFace(3) == bndK[i].f)
1097  neigh->T[3] = t;
1098  else {
1099  Msg::Error("Datastructure broken in triangulation");
1100  break;
1101  }
1102  }
1103  computeAdjacencies(t, 1, faceToTet);
1104  computeAdjacencies(t, 2, faceToTet);
1105  computeAdjacencies(t, 3, faceToTet);
1106  }
1107  for(std::size_t i = bSize; i < cSize; i++) {
1108  cavityK[i]->V[0] = nullptr;
1109  }
1110  }
1111  }
1112  }
1113 #if defined(VERBOSE)
1114 #pragma omp critical
1115  {
1116  totCavityGlob += totCavity;
1117  totSearchGlob += totSearch;
1118  }
1119 #endif
1120 #pragma omp barrier
1121  // clear last cavity
1122  for(std::size_t K = 0; K < NPTS_AT_ONCE; K++) {
1123  for(std::size_t i = 0; i < cavity[K].size(); i++)
1124  cavity[K][i]->unset(myThread, K);
1125  for(std::size_t i = 0; i < bnd[K].size(); i++)
1126  if(bnd[K][i].t) bnd[K][i].t->unset(myThread, K);
1127  }
1128  }
1129 
1130  if(invalidCavities[0]) Msg::Error("%d invalid cavities", invalidCavities[0]);
1131 
1132 #if defined(VERBOSE)
1133  printf("average searches per point %12.5E\n", totSearchGlob / Npts);
1134  printf("average size for del cavity %12.5E\n", totCavityGlob / Npts);
1135  printf("cache misses: ");
1136  for(std::size_t i = 0; i < numThreads; i++) {
1137  printf("%4ud ", (int)cacheMisses[i]);
1138  }
1139  printf("\n");
1140 #endif
1141 
1142  for(std::size_t myThread = 0; myThread < numThreads; myThread++)
1143  for(std::size_t i = 0; i < allocator.size(myThread); i++)
1144  allocator(myThread, i)->setAllDeleted();
1145 }
1146 
1147 static void initialCube(std::vector<Vert *> &v, Vert *box[8],
1148  tetContainer &allocator)
1149 {
1150  SBoundingBox3d bbox;
1151  for(size_t i = 0; i < v.size(); i++) {
1152  Vert *pv = v[i];
1153  bbox += SPoint3(pv->x(), pv->y(), pv->z());
1154  }
1155  bbox *= 1.3;
1156  box[0] =
1157  new Vert(bbox.min().x(), bbox.min().y(), bbox.min().z(), bbox.diag());
1158  box[1] =
1159  new Vert(bbox.max().x(), bbox.min().y(), bbox.min().z(), bbox.diag());
1160  box[2] =
1161  new Vert(bbox.max().x(), bbox.max().y(), bbox.min().z(), bbox.diag());
1162  box[3] =
1163  new Vert(bbox.min().x(), bbox.max().y(), bbox.min().z(), bbox.diag());
1164  box[4] =
1165  new Vert(bbox.min().x(), bbox.min().y(), bbox.max().z(), bbox.diag());
1166  box[5] =
1167  new Vert(bbox.max().x(), bbox.min().y(), bbox.max().z(), bbox.diag());
1168  box[6] =
1169  new Vert(bbox.max().x(), bbox.max().y(), bbox.max().z(), bbox.diag());
1170  box[7] =
1171  new Vert(bbox.min().x(), bbox.max().y(), bbox.max().z(), bbox.diag());
1172 
1173  Tet *t0 = allocator.newTet(0);
1174  t0->setVertices(box[7], box[2], box[3], box[1]);
1175  Tet *t1 = allocator.newTet(0);
1176  t1->setVertices(box[7], box[0], box[1], box[3]);
1177  Tet *t2 = allocator.newTet(0);
1178  t2->setVertices(box[1], box[6], box[7], box[2]);
1179  Tet *t3 = allocator.newTet(0);
1180  t3->setVertices(box[1], box[0], box[7], box[4]);
1181  Tet *t4 = allocator.newTet(0);
1182  t4->setVertices(box[4], box[1], box[5], box[7]);
1183  Tet *t5 = allocator.newTet(0);
1184  t5->setVertices(box[7], box[1], box[5], box[6]);
1185 
1186  connContainer ctnr;
1187  for(int i = 0; i < 4; i++) {
1188  computeAdjacencies(t0, i, ctnr);
1189  computeAdjacencies(t1, i, ctnr);
1190  computeAdjacencies(t2, i, ctnr);
1191  computeAdjacencies(t3, i, ctnr);
1192  computeAdjacencies(t4, i, ctnr);
1193  computeAdjacencies(t5, i, ctnr);
1194  }
1195 }
1196 
1197 static void delaunayTriangulation(const int numThreads, const int nptsatonce,
1198  std::vector<Vert *> &S, Vert *box[8],
1199  tetContainer &allocator)
1200 {
1201  int N = S.size();
1202 
1203  std::vector<int> indices;
1204  SortHilbert(S, indices);
1205  if(!allocator.size(0)) { initialCube(S, box, allocator); }
1206 
1207  int nbBlocks = nptsatonce * numThreads;
1208 
1209  std::vector<std::vector<Vert *> > assignTo(nbBlocks);
1210 
1211  for(std::size_t i = 1; i < indices.size(); i++) {
1212  int start = indices[i - 1];
1213  int end = indices[i];
1214  int sizePerBlock = (nbBlocks * ((end - start) / nbBlocks)) / nbBlocks;
1215  int currentBlock = 0;
1216  int localCounter = 0;
1217  for(int jPt = start; jPt < end; jPt++) {
1218  if(localCounter++ >= sizePerBlock && currentBlock != nbBlocks - 1) {
1219  localCounter = 0;
1220  currentBlock++;
1221  }
1222  assignTo[currentBlock].push_back(S[jPt]);
1223  }
1224  }
1225 
1226  delaunayTrgl(numThreads, nptsatonce, N, &assignTo[0], allocator);
1227  // print("finalTetrahedrization.pos",0, allocator);
1228 }
1229 
1230 void delaunayTriangulation(const int numThreads, const int nptsatonce,
1231  std::vector<MVertex *> &S,
1232  std::vector<MTetrahedron *> &T, bool removeBox)
1233 {
1234  std::vector<MVertex *> _temp;
1235  std::vector<Vert *> _vertices;
1236  std::size_t N = S.size();
1237  _temp.resize(N + 1 + 8);
1238  double maxx = 0, maxy = 0, maxz = 0;
1239  for(std::size_t i = 0; i < N; i++) {
1240  MVertex *mv = S[i];
1241  maxx = std::max(maxx, fabs(mv->x()));
1242  maxy = std::max(maxy, fabs(mv->y()));
1243  maxz = std::max(maxz, fabs(mv->z()));
1244  }
1245  double d = 1 * sqrt(maxx * maxx + maxy * maxy + maxz * maxz);
1246 
1247  tetContainer allocator(numThreads, S.size() * 10);
1248 
1249  for(std::size_t i = 0; i < N; i++) {
1250  MVertex *mv = S[i];
1251  double dx =
1252  d * CTX::instance()->mesh.randFactor3d * (double)rand() / RAND_MAX;
1253  double dy =
1254  d * CTX::instance()->mesh.randFactor3d * (double)rand() / RAND_MAX;
1255  double dz =
1256  d * CTX::instance()->mesh.randFactor3d * (double)rand() / RAND_MAX;
1257  mv->x() += dx;
1258  mv->y() += dy;
1259  mv->z() += dz;
1260  Vert *v = new Vert(mv->x(), mv->y(), mv->z(), 1.e22, i + 1);
1261  _vertices.push_back(v);
1262  _temp[v->getNum()] = mv;
1263  }
1264 
1265  robustPredicates::exactinit(1, maxx, maxy, maxz);
1266 
1267  Vert *box[8];
1268  delaunayTriangulation(numThreads, nptsatonce, _vertices, box, allocator);
1269  // print("finalTetrahedrization.pos",0, allocator);
1270 
1271  for(int i = 0; i < 8; i++) {
1272  Vert *v = box[i];
1273  if(removeBox) { v->setNum(0); }
1274  else {
1275  v->setNum(N + i + 1);
1276  MVertex *mv = new MVertex(v->x(), v->y(), v->z(), nullptr, N + (i + 1));
1277  _temp[v->getNum()] = mv;
1278  S.push_back(mv);
1279  }
1280  }
1281 
1282  for(int myThread = 0; myThread < numThreads; myThread++) {
1283  for(std::size_t i = 0; i < allocator.size(myThread); i++) {
1284  Tet *t = allocator(myThread, i);
1285  if(t->V[0]) {
1286  if(t->V[0]->getNum() && t->V[1]->getNum() && t->V[2]->getNum() &&
1287  t->V[3]->getNum()) {
1288  MVertex *v1 = _temp[t->V[0]->getNum()];
1289  MVertex *v2 = _temp[t->V[1]->getNum()];
1290  MVertex *v3 = _temp[t->V[2]->getNum()];
1291  MVertex *v4 = _temp[t->V[3]->getNum()];
1292  MTetrahedron *tr = new MTetrahedron(v1, v2, v3, v4);
1293  T.push_back(tr);
1294  }
1295  else if(!removeBox) {
1296  Msg::Error("Error in triangulation");
1297  }
1298  }
1299  }
1300  }
1301 
1302  for(int i = 0; i < 8; i++) delete box[i];
1303  for(std::size_t i = 0; i < _vertices.size(); i++) delete _vertices[i];
1304 }
aBunchOfStuff::size
std::size_t size()
Definition: delaunay3d.cpp:273
conn::operator<
bool operator<(const conn &c) const
Definition: delaunay3d.cpp:264
contextMeshOptions::randFactor3d
double randFactor3d
Definition: Context.h:21
Tet::unset
void unset(int thread, int iPnt)
Definition: delaunay3d.cpp:235
SBoundingBox3d::diag
double diag() const
Definition: SBoundingBox3d.h:93
Tet::set
void set(int thread, int iPnt)
Definition: delaunay3d.cpp:236
Tet::T
Tet * T[4]
Definition: delaunay3d.cpp:180
conn::i
int i
Definition: delaunay3d.cpp:259
aBunchOfStuff
Definition: delaunay3d.cpp:268
Face::Face
Face(Vert *v1, Vert *v2, Vert *v3)
Definition: delaunay3d.cpp:145
SortHilbert
static void SortHilbert(std::vector< Vert * > &v, std::vector< int > &indices)
Definition: delaunay3d.cpp:592
conn::conn
conn()
Definition: delaunay3d.cpp:261
Vert::Vert
Vert(double X=0, double Y=0, double Z=0, double lc=0, int num=0)
Definition: delaunay3d.cpp:58
Tet::getOppositeVertex
Vert * getOppositeVertex(int k) const
Definition: delaunay3d.cpp:246
MTetrahedron
Definition: MTetrahedron.h:34
Tet::setAllDeleted
void setAllDeleted()
Definition: delaunay3d.cpp:231
Vert::setNum
void setNum(std::size_t n)
Definition: delaunay3d.cpp:47
HilbertSortB::bbox
SBoundingBox3d bbox
Definition: delaunay3d.cpp:337
meshGRegionLocalMeshMod.h
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
OS.h
Msg::Debug
static void Debug(const char *fmt,...)
Definition: GmshMessage.cpp:752
robustPredicates.h
c
static double c(int i, int j, fullMatrix< double > &CA, const std::vector< SPoint3 > &P, const std::vector< SPoint3 > &Q)
Definition: discreteFrechetDistance.cpp:15
Vert::_x
double _x[3]
Definition: delaunay3d.cpp:38
MVertex
Definition: MVertex.h:24
Vert::operator*
Vert operator*(const double &other)
Definition: delaunay3d.cpp:71
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
MVertex::z
double z() const
Definition: MVertex.h:62
box
Definition: gl2gif.cpp:311
Vert::lc
double & lc()
Definition: delaunay3d.cpp:56
SPoint3
Definition: SPoint3.h:14
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
aBunchOfStuff::~aBunchOfStuff
~aBunchOfStuff()
Definition: delaunay3d.cpp:287
SBoundingBox3d::min
SPoint3 min() const
Definition: SBoundingBox3d.h:90
connContainer
std::vector< conn > connContainer
Definition: delaunay3d.cpp:328
orientationTestFast
static double orientationTestFast(double *pa, double *pb, double *pc, double *pd)
Definition: delaunay3d.cpp:78
Vert
Definition: delaunay3d.cpp:36
randomTet
static Tet * randomTet(int thread, tetContainer &allocator)
Definition: delaunay3d.cpp:954
removeIsolatedTets
static bool removeIsolatedTets(Tet *containsV, cavityContainer &cavity, connContainer &bndK, int myThread, int K)
Definition: delaunay3d.cpp:670
MAX_NUM_THREADS_
#define MAX_NUM_THREADS_
Definition: delaunay3d.cpp:30
delaunay3d.h
conn::operator==
bool operator==(const conn &c) const
Definition: delaunay3d.cpp:263
CHECKTYPE
unsigned char CHECKTYPE
Definition: delaunay3d.cpp:33
HilbertSortB::ComputeGrayCode
void ComputeGrayCode(int n)
Definition: delaunay3d.cpp:383
Tet::getFace
Face getFace(int k) const
Definition: delaunay3d.cpp:241
buildDelaunayBall
static void buildDelaunayBall(cavityContainer &cavity, connContainer &faceToTet)
Definition: delaunay3d.cpp:653
Vert::lc
double lc() const
Definition: delaunay3d.cpp:52
tetContainer::tetContainer
tetContainer(int nbThreads, int preallocSizePerThread)
Definition: delaunay3d.cpp:313
CTX::instance
static CTX * instance()
Definition: Context.cpp:122
Tet::Tet
Tet(Vert *v0, Vert *v1, Vert *v2, Vert *v3)
Definition: delaunay3d.cpp:225
tetContainer::size
std::size_t size(int thread) const
Definition: delaunay3d.cpp:307
SPoint3::x
double x(void) const
Definition: SPoint3.h:125
conn::conn
conn(Face _f, int _i, Tet *_t)
Definition: delaunay3d.cpp:262
conn
Definition: delaunay3d.cpp:257
Vert::x
double x() const
Definition: delaunay3d.cpp:49
Vert::y
double y() const
Definition: delaunay3d.cpp:50
HilbertSortB::Split
int Split(Vert **vertices, int arraysize, int GrayCode0, int GrayCode1, double BoundingBoxXmin, double BoundingBoxXmax, double BoundingBoxYmin, double BoundingBoxYmax, double BoundingBoxZmin, double BoundingBoxZmax)
Definition: delaunay3d.cpp:424
HilbertSortB::maxDepth
int maxDepth
Definition: delaunay3d.cpp:335
tetContainer::operator()
Tet * operator()(int thread, int j) const
Definition: delaunay3d.cpp:312
Tet::V
Vert * V[4]
Definition: delaunay3d.cpp:181
SBoundingBox3d.h
MVertex.h
HilbertSortB
Definition: delaunay3d.cpp:330
conn::t
Tet * t
Definition: delaunay3d.cpp:260
aBunchOfStuff::operator()
T * operator()(std::size_t i)
Definition: delaunay3d.cpp:276
Vert::getNum
std::size_t getNum() const
Definition: delaunay3d.cpp:46
canWeProcessCavity
static bool canWeProcessCavity(cavityContainer &cavity, std::size_t myThread, std::size_t iPt)
Definition: delaunay3d.cpp:913
Tet::setVerticesNoTest
int setVerticesNoTest(Vert *v0, Vert *v1, Vert *v2, Vert *v3)
Definition: delaunay3d.cpp:191
Vert::_lc
double _lc
Definition: delaunay3d.cpp:39
tetContainer::newTet
Tet * newTet(int thread)
Definition: delaunay3d.cpp:320
Tet
Definition: delaunay3d.cpp:179
robustPredicates::insphere
REAL insphere(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe)
Definition: robustPredicates.cpp:4200
SPoint3::y
double y(void) const
Definition: SPoint3.h:127
walk
static Tet * walk(Tet *t, Vert *v, int maxx, double &totSearch, int thread)
Definition: delaunay3d.cpp:809
starShapeness
static void starShapeness(Vert *v, connContainer &bndK, std::vector< std::size_t > &_negatives)
Definition: delaunay3d.cpp:625
aBunchOfStuff::aBunchOfStuff
aBunchOfStuff(std::size_t s)
Definition: delaunay3d.cpp:282
cswap
#define cswap(a, b)
CTX::mesh
contextMeshOptions mesh
Definition: Context.h:313
Tet::_bitset
CHECKTYPE _bitset[MAX_NUM_THREADS_]
Definition: delaunay3d.cpp:182
Face::operator==
bool operator==(const Face &other) const
Definition: delaunay3d.cpp:163
aBunchOfStuff::newStuff
T * newStuff()
Definition: delaunay3d.cpp:291
Tet::setVertices
int setVertices(Vert *v0, Vert *v1, Vert *v2, Vert *v3)
Definition: delaunay3d.cpp:202
tetContainer::~tetContainer
~tetContainer()
Definition: delaunay3d.cpp:321
S
#define S
Definition: DefaultOptions.h:21
robustPredicates::exactinit
REAL exactinit(int filter, REAL maxx, REAL maxy, REAL maxz)
Definition: robustPredicates.cpp:676
HilbertSortB::Apply
void Apply(std::vector< Vert * > &v, std::vector< int > &indices)
Definition: delaunay3d.cpp:366
Tet::Tet
Tet()
Definition: delaunay3d.cpp:185
tetInsideCavityWithFAce
static Tet * tetInsideCavityWithFAce(Face &f, cavityContainer &cavity)
Definition: delaunay3d.cpp:697
tetContainer
Definition: delaunay3d.cpp:303
Tet::_modified
bool _modified
Definition: delaunay3d.cpp:183
delaunayTrgl
void delaunayTrgl(const std::size_t numThreads, const std::size_t NPTS_AT_ONCE, std::size_t Npts, std::vector< Vert * > assignTo[], tetContainer &allocator)
Definition: delaunay3d.cpp:966
Vert::operator+
Vert operator+(const Vert &other)
Definition: delaunay3d.cpp:66
Context.h
Vert::point
SPoint3 point() const
Definition: delaunay3d.cpp:75
MTetrahedron.h
cavityContainer
std::vector< Tet * > cavityContainer
Definition: delaunay3d.cpp:327
Vert::z
double z() const
Definition: delaunay3d.cpp:51
computeAdjacencies
static void computeAdjacencies(Tet *t, int iFace, connContainer &faceToTet)
Definition: delaunay3d.cpp:598
Vert::getT
Tet * getT() const
Definition: delaunay3d.cpp:45
HilbertSortB::Limit
int Limit
Definition: delaunay3d.cpp:336
aBunchOfStuff::_all
std::vector< T * > _all
Definition: delaunay3d.cpp:270
Tet::inSphere
bool inSphere(Vert *vd, int thread)
Definition: delaunay3d.cpp:251
HilbertSortB::Sort
void Sort(Vert **vertices, int arraysize, int e, int d, double BoundingBoxXmin, double BoundingBoxXmax, double BoundingBoxYmin, double BoundingBoxYmax, double BoundingBoxZmin, double BoundingBoxZmax, int depth)
Definition: delaunay3d.cpp:496
Face
Definition: delaunay3d.cpp:142
Vert::_thread
unsigned char _thread
Definition: delaunay3d.cpp:48
inSphereTest_s
static bool inSphereTest_s(Vert *va, Vert *vb, Vert *vc, Vert *vd, Vert *ve)
Definition: delaunay3d.cpp:95
aBunchOfStuff::_nbAlloc
std::size_t _nbAlloc
Definition: delaunay3d.cpp:272
Face::operator<
bool operator<(const Face &other) const
Definition: delaunay3d.cpp:168
SPoint3::z
double z(void) const
Definition: SPoint3.h:129
Vert::_num
std::size_t _num
Definition: delaunay3d.cpp:40
fixDelaunayCavity
static bool fixDelaunayCavity(Vert *v, cavityContainer &cavity, connContainer &bndK, int myThread, int K, std::vector< std::size_t > &_negatives)
Definition: delaunay3d.cpp:709
robustPredicates::orient3d
REAL orient3d(REAL *pa, REAL *pb, REAL *pc, REAL *pd)
Definition: robustPredicates.cpp:2321
delaunayCavity2
static void delaunayCavity2(Tet *tet, Tet *prevTet, Vert *v, cavityContainer &cavity, connContainer &bnd, int thread, int iPnt)
Definition: delaunay3d.cpp:754
aBunchOfStuff::_current
std::size_t _current
Definition: delaunay3d.cpp:271
MVertex::y
double y() const
Definition: MVertex.h:61
conn::f
Face f
Definition: delaunay3d.cpp:258
HilbertSortB::transgc
int transgc[8][3][8]
Definition: delaunay3d.cpp:333
HilbertSortB::tsb1mod3
int tsb1mod3[8]
Definition: delaunay3d.cpp:334
HilbertSortB::HilbertSortB
HilbertSortB(int m=0, int l=2)
Definition: delaunay3d.cpp:347
initialCube
static void initialCube(std::vector< Vert * > &v, Vert *box[8], tetContainer &allocator)
Definition: delaunay3d.cpp:1147
Face::v
Vert * v[3]
Definition: delaunay3d.cpp:143
Vert::z
double & z()
Definition: delaunay3d.cpp:55
SBoundingBox3d::max
SPoint3 max() const
Definition: SBoundingBox3d.h:91
Vert::x
double & x()
Definition: delaunay3d.cpp:53
SPoint3.h
tetContainsV
static Tet * tetContainsV(Vert *v, cavityContainer &cavity)
Definition: delaunay3d.cpp:638
HilbertSortB::MultiscaleSortHilbert
void MultiscaleSortHilbert(Vert **vertices, int arraysize, int threshold, double ratio, int *depth, std::vector< int > &indices)
Definition: delaunay3d.cpp:351
Vert::setT
void setT(Tet *t)
Definition: delaunay3d.cpp:44
Vert::_t
Tet * _t
Definition: delaunay3d.cpp:41
SBoundingBox3d
Definition: SBoundingBox3d.h:21
tetContainer::_perThread
std::vector< aBunchOfStuff< Tet > * > _perThread
Definition: delaunay3d.cpp:304
Vert::y
double & y()
Definition: delaunay3d.cpp:54
Tet::isSet
CHECKTYPE isSet(int thread, int iPnt) const
Definition: delaunay3d.cpp:237
delaunayTriangulation
static void delaunayTriangulation(const int numThreads, const int nptsatonce, std::vector< Vert * > &S, Vert *box[8], tetContainer &allocator)
Definition: delaunay3d.cpp:1197
MVertex::x
double x() const
Definition: MVertex.h:60
Face::V
Vert * V[3]
Definition: delaunay3d.cpp:144