gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
meshOctreeLibOL.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 // Author: Maxence Reberol
7 
8 #include "meshOctreeLibOL.h"
9 #include "GFace.h"
10 #include "discreteFace.h"
11 #include "MVertex.h"
12 #include "MTriangle.h"
13 #include "OS.h"
14 
15 extern "C" {
16 #include "libol1.h"
17 }
18 
19 #include "robin_hood.h"
20 
21 // Debug vizu
22 // #include "geolog.h"
23 
25  /* Copy useful functions from contrib/QuadMeshingTools/arrayGeometry.h
26  * because this functions should work without QUADMESHINGTOOLS module */
27  using vec2 = std::array<double, 2>;
28  using vec3 = std::array<double, 3>;
29  inline vec3 operator-(const vec3 &a, const vec3 &b)
30  {
31  return {{a[0] - b[0], a[1] - b[1], a[2] - b[2]}};
32  }
33  inline vec3 operator+(const vec3 &a, const vec3 &b)
34  {
35  return {{a[0] + b[0], a[1] + b[1], a[2] + b[2]}};
36  }
37  inline vec3 operator*(const double &a, const vec3 &b)
38  {
39  return {{a * b[0], a * b[1], a * b[2]}};
40  }
41  inline vec3 operator*(const vec3 &a, const double &b)
42  {
43  return {{a[0] * b, a[1] * b, a[2] * b}};
44  }
45  inline double dot(const vec3 &a, const vec3 &b)
46  {
47  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
48  }
49  inline double length2(const vec3 &a) { return dot(a, a); }
50  inline double maxAbs(double x, double y, double z)
51  {
52  return std::max(std::abs(x), std::max(std::abs(y), std::abs(z)));
53  }
54  inline double maxAbs(const vec3 &a) { return maxAbs(a[0], a[1], a[2]); }
55  inline void normalizeFast(vec3 &a)
56  {
57  a = 1. / std::sqrt(length2(a)) * a;
58  } /* no check, not safe, not accurate */
59  inline void normalize(vec3 &a)
60  {
61  double amp = maxAbs(a);
62  if(amp == 0.) { return; }
63  a = amp * a;
64  normalizeFast(a);
65  }
66 
67  inline double project_point_segment_l2(const vec3 &query, const vec3 &a,
68  const vec3 &b, vec3 &proj,
69  double &lambda)
70  {
71  double l2 = length2(a - b);
72  double t = dot(query - a, b - a);
73  if(t <= 0. || l2 == 0.) {
74  proj = a;
75  lambda = 1.;
76  return length2(query - a);
77  }
78  else if(t > l2) {
79  proj = b;
80  lambda = 0.;
81  return length2(query - b);
82  }
83  lambda = 1. - t / l2;
84  proj = lambda * a + (1. - lambda) * b;
85  return length2(query - proj);
86  }
87 
88  /* This function is adapted from a equivalent function in the Geogram library,
89  * which is based on https://www.geometrictools.com/Source/Distance3D.html */
90  inline double project_point_triangle_l2(const vec3 &query, const vec3 &p1,
91  const vec3 &p2, const vec3 &p3,
92  vec3 &proj, double lambda[3])
93  {
94  vec3 diff = p1 - query;
95  vec3 edge0 = p2 - p1;
96  vec3 edge1 = p3 - p1;
97  double a00 = length2(edge0);
98  double a01 = dot(edge0, edge1);
99  double a11 = length2(edge1);
100  double b0 = dot(diff, edge0);
101  double b1 = dot(diff, edge1);
102  double c = length2(diff);
103  double det = ::fabs(a00 * a11 - a01 * a01);
104  double s = a01 * b1 - a11 * b0;
105  double t = a01 * b0 - a00 * b1;
106  double sqrDistance;
107 
108  // If the triangle is degenerate
109  if(det < 1e-30) {
110  double cur_l1;
111  vec3 cur_closest;
112  double result;
113  double cur_dist =
114  project_point_segment_l2(query, p1, p2, cur_closest, cur_l1);
115  result = cur_dist;
116  proj = cur_closest;
117  lambda[0] = cur_l1;
118  lambda[1] = 1. - cur_l1;
119  lambda[2] = 0.0;
120  cur_dist = project_point_segment_l2(query, p1, p3, cur_closest, cur_l1);
121  if(cur_dist < result) {
122  result = cur_dist;
123  proj = cur_closest;
124  lambda[0] = cur_l1;
125  lambda[2] = 1. - cur_l1;
126  lambda[1] = 0.0;
127  }
128  cur_dist = project_point_segment_l2(query, p2, p3, cur_closest, cur_l1);
129  if(cur_dist < result) {
130  result = cur_dist;
131  proj = cur_closest;
132  lambda[1] = cur_l1;
133  lambda[2] = 1. - cur_l1;
134  lambda[0] = 0.0;
135  }
136  return result;
137  }
138 
139  if(s + t <= det) {
140  if(s < 0.0) {
141  if(t < 0.0) { // region 4
142  if(b0 < 0.0) {
143  t = 0.0;
144  if(-b0 >= a00) {
145  s = 1.0;
146  sqrDistance = a00 + 2.0 * b0 + c;
147  }
148  else {
149  s = -b0 / a00;
150  sqrDistance = b0 * s + c;
151  }
152  }
153  else {
154  s = 0.0;
155  if(b1 >= 0.0) {
156  t = 0.0;
157  sqrDistance = c;
158  }
159  else if(-b1 >= a11) {
160  t = 1.0;
161  sqrDistance = a11 + 2.0 * b1 + c;
162  }
163  else {
164  t = -b1 / a11;
165  sqrDistance = b1 * t + c;
166  }
167  }
168  }
169  else { // region 3
170  s = 0.0;
171  if(b1 >= 0.0) {
172  t = 0.0;
173  sqrDistance = c;
174  }
175  else if(-b1 >= a11) {
176  t = 1.0;
177  sqrDistance = a11 + 2.0 * b1 + c;
178  }
179  else {
180  t = -b1 / a11;
181  sqrDistance = b1 * t + c;
182  }
183  }
184  }
185  else if(t < 0.0) { // region 5
186  t = 0.0;
187  if(b0 >= 0.0) {
188  s = 0.0;
189  sqrDistance = c;
190  }
191  else if(-b0 >= a00) {
192  s = 1.0;
193  sqrDistance = a00 + 2.0 * b0 + c;
194  }
195  else {
196  s = -b0 / a00;
197  sqrDistance = b0 * s + c;
198  }
199  }
200  else { // region 0
201  // minimum at interior query
202  double invDet = double(1.0) / det;
203  s *= invDet;
204  t *= invDet;
205  sqrDistance = s * (a00 * s + a01 * t + 2.0 * b0) +
206  t * (a01 * s + a11 * t + 2.0 * b1) + c;
207  }
208  }
209  else {
210  double tmp0, tmp1, numer, denom;
211 
212  if(s < 0.0) { // region 2
213  tmp0 = a01 + b0;
214  tmp1 = a11 + b1;
215  if(tmp1 > tmp0) {
216  numer = tmp1 - tmp0;
217  denom = a00 - 2.0 * a01 + a11;
218  if(numer >= denom) {
219  s = 1.0;
220  t = 0.0;
221  sqrDistance = a00 + 2.0 * b0 + c;
222  }
223  else {
224  s = numer / denom;
225  t = 1.0 - s;
226  sqrDistance = s * (a00 * s + a01 * t + 2.0 * b0) +
227  t * (a01 * s + a11 * t + 2.0 * b1) + c;
228  }
229  }
230  else {
231  s = 0.0;
232  if(tmp1 <= 0.0) {
233  t = 1.0;
234  sqrDistance = a11 + 2.0 * b1 + c;
235  }
236  else if(b1 >= 0.0) {
237  t = 0.0;
238  sqrDistance = c;
239  }
240  else {
241  t = -b1 / a11;
242  sqrDistance = b1 * t + c;
243  }
244  }
245  }
246  else if(t < 0.0) { // region 6
247  tmp0 = a01 + b1;
248  tmp1 = a00 + b0;
249  if(tmp1 > tmp0) {
250  numer = tmp1 - tmp0;
251  denom = a00 - 2.0 * a01 + a11;
252  if(numer >= denom) {
253  t = 1.0;
254  s = 0.0;
255  sqrDistance = a11 + 2.0 * b1 + c;
256  }
257  else {
258  t = numer / denom;
259  s = 1.0 - t;
260  sqrDistance = s * (a00 * s + a01 * t + 2.0 * b0) +
261  t * (a01 * s + a11 * t + 2.0 * b1) + c;
262  }
263  }
264  else {
265  t = 0.0;
266  if(tmp1 <= 0.0) {
267  s = 1.0;
268  sqrDistance = a00 + 2.0 * b0 + c;
269  }
270  else if(b0 >= 0.0) {
271  s = 0.0;
272  sqrDistance = c;
273  }
274  else {
275  s = -b0 / a00;
276  sqrDistance = b0 * s + c;
277  }
278  }
279  }
280  else { // region 1
281  numer = a11 + b1 - a01 - b0;
282  if(numer <= 0.0) {
283  s = 0.0;
284  t = 1.0;
285  sqrDistance = a11 + 2.0 * b1 + c;
286  }
287  else {
288  denom = a00 - 2.0 * a01 + a11;
289  if(numer >= denom) {
290  s = 1.0;
291  t = 0.0;
292  sqrDistance = a00 + 2.0 * b0 + c;
293  }
294  else {
295  s = numer / denom;
296  t = 1.0 - s;
297  sqrDistance = s * (a00 * s + a01 * t + 2.0 * b0) +
298  t * (a01 * s + a11 * t + 2.0 * b1) + c;
299  }
300  }
301  }
302  }
303 
304  // Account for numerical round-off error.
305  if(sqrDistance < 0.0) { sqrDistance = 0.0; }
306 
307  proj = p1 + s * edge0 + t * edge1;
308  lambda[0] = 1.0 - s - t;
309  lambda[1] = s;
310  lambda[2] = t;
311  return sqrDistance;
312  }
313 } // namespace SurfaceProjectorUtils
314 
315 using namespace SurfaceProjectorUtils;
316 
317 SurfaceProjector::SurfaceProjector(GFace *gf_) : gf(NULL), OctIdx(0)
318 {
319  std::vector<MTriangle *> triangles = gf->triangles;
320  if(gf->quadrangles.size() > 0) {
321  Msg::Error("SurfaceProjector: quads not implemented yet, should create "
322  "fake MTriangle* just for initialize()");
323  abort();
324  }
325  bool ok = initialize(gf_, triangles);
326  if(!ok) { Msg::Error("failed to initialize SurfaceProjector"); }
327 }
328 
330 {
331  if(OctIdx != 0) {
332  Msg::Debug("free libOL octree (OctIdx: %li)", OctIdx);
334  OctIdx = 0;
335  }
336  points.clear();
337  triangles.clear();
338  triangle_uvs.clear();
339 }
340 
342 
344 {
345  if(gf->geomType() == GFace::GeomType::Sphere) {
346  double radius = 0.;
347  SPoint3 center;
348  if(gf->isSphere(radius, center)) {
349  analyticalShape = GFace::GeomType::Sphere;
350  useAnalyticalFormula = true;
351  analyticalParameters[0] = center.x();
352  analyticalParameters[1] = center.y();
353  analyticalParameters[2] = center.z();
354  analyticalParameters[3] = radius;
355  return true;
356  }
357  }
358 
359  Msg::Error(
360  "Surface projector: analytical formula for given shape not supported");
361  return false;
362 }
363 
365  const std::vector<MTriangle *> &gfTriangles,
366  bool useCADStl)
367 {
368  clear();
369  gf = gf_;
370  bool paramAvailable = gf->haveParametrization();
371  const int BasIdx = 1; /* indices start at one in libOL */
372 
373  if (useCADStl) {
374  if (gf->buildSTLTriangulation()) {
375  this->points.resize(gf->stl_vertices_xyz.size());
376  for (size_t i = 0; i < this->points.size(); ++i) {
377  this->points[i] = {
378  gf->stl_vertices_xyz[i].x(),
379  gf->stl_vertices_xyz[i].y(),
380  gf->stl_vertices_xyz[i].z()};
381  }
382 
383  this->triangles.resize(gf->stl_triangles.size()/3);
384  for (size_t i = 0; i < this->triangles.size(); ++i) {
385  this->triangles[i] = {gf->stl_triangles[3*i+0]+BasIdx,
386  gf->stl_triangles[3*i+1]+BasIdx, gf->stl_triangles[3*i+2]+BasIdx};
387  }
388 
389  if (paramAvailable && gf->stl_vertices_uv.size()) {
390  this->triangle_uvs.resize(gf->stl_triangles.size()/3);
391  for (size_t i = 0; i < this->triangle_uvs.size(); ++i) {
392  this->triangle_uvs[i][0] = {
393  gf->stl_vertices_uv[gf->stl_triangles[3*i+0]].x(),
394  gf->stl_vertices_uv[gf->stl_triangles[3*i+0]].y()};
395  this->triangle_uvs[i][1] = {
396  gf->stl_vertices_uv[gf->stl_triangles[3*i+1]].x(),
397  gf->stl_vertices_uv[gf->stl_triangles[3*i+1]].y()};
398  this->triangle_uvs[i][2] = {
399  gf->stl_vertices_uv[gf->stl_triangles[3*i+2]].x(),
400  gf->stl_vertices_uv[gf->stl_triangles[3*i+2]].y()};
401  }
402  }
403  } else {
404  Msg::Warning("SurfaceProjector initialize: failed to build STL triangulation");
405  return false;
406  }
407  } else {
408  /* If periodic parametrization, get periods */
409  bool disableParamPer = false;
410  if(paramAvailable && (gf->periodic(0) || gf->periodic(1))) {
411  disableParamPer = true;
412  }
413 
414  /* Collect coordinates and triangle-continuous uv param */
416  int32_t count = 0;
417  triangles.reserve(gfTriangles.size());
418  points.reserve(gfTriangles.size());
419  if(paramAvailable) {
420  triangle_uvs.reserve(gfTriangles.size());
421  if(disableParamPer) triangle_no_uv_eval.reserve(gfTriangles.size());
422  }
423  for(MTriangle *f : gfTriangles) {
424  std::array<int32_t, 3> tri_pts;
425  std::array<vec2, 3> tri_uvs;
426  bool check_periodicity = false;
427  bool no_eval = false;
428  for(size_t lv = 0; lv < f->getNumVertices(); ++lv) {
429  MVertex *v = f->getVertex(lv);
430  auto it = old2new.find(v);
431  if(it == old2new.end()) {
432  old2new[v] = count;
433  tri_pts[lv] = count + BasIdx;
434  points.push_back(v->point());
435  count += 1;
436  }
437  else {
438  tri_pts[lv] = it->second + BasIdx;
439  }
440 
441  if(paramAvailable) { /* Get the uv in GFace */
442  bool onGf = (dynamic_cast<GFace *>(v->onWhat()) == gf);
443  if(onGf) {
444  v->getParameter(0, tri_uvs[lv][0]);
445  v->getParameter(1, tri_uvs[lv][1]);
446  }
447  else {
448  check_periodicity = true;
449  }
450  }
451  }
452 
453  if(check_periodicity) {
454  bool found = false;
455  for(size_t lv = 0; lv < 3; ++lv) {
456  MVertex *v1 = f->getVertex(lv);
457  bool onGf = (dynamic_cast<GFace *>(v1->onWhat()) == gf);
458  if(onGf) { /* If neither of the 3 are on surface, takes random ... */
459  MVertex *v2 = f->getVertex((lv + 1) % 3);
460  MVertex *v3 = f->getVertex((lv + 2) % 3);
461  SPoint2 param1;
462  SPoint2 param2;
463  SPoint2 param3;
464  reparamMeshEdgeOnFace(v1, v2, gf, param1, param2);
465  reparamMeshEdgeOnFace(v1, v3, gf, param1, param3);
466  tri_uvs[(lv + 0) % 3] = {{param1.x(), param1.y()}};
467  tri_uvs[(lv + 1) % 3] = {{param2.x(), param2.y()}};
468  tri_uvs[(lv + 2) % 3] = {{param3.x(), param3.y()}};
469  found = true;
470  break;
471  }
472  }
473  if(!found) {
474  /* Triangle with no vertex inside the GFace, difficult to get
475  * good UV parametrization, we use center projection to get
476  * a initial guess */
477  SPoint3 center = f->barycenter();
478  double initialGuess[2] = {0., 0.};
479  GPoint proj = gf->closestPoint(center, initialGuess);
480  if(proj.succeeded()) {
481  MFaceVertex cv(proj.x(), proj.y(), proj.z(), gf, proj.u(), proj.v());
482  MVertex *v1 = f->getVertex(0);
483  MVertex *v2 = f->getVertex(1);
484  MVertex *v3 = f->getVertex(2);
485  SPoint2 paramc;
486  SPoint2 param1;
487  SPoint2 param2;
488  SPoint2 param3;
489  reparamMeshEdgeOnFace(&cv, v1, gf, paramc, param1);
490  reparamMeshEdgeOnFace(&cv, v2, gf, paramc, param2);
491  reparamMeshEdgeOnFace(&cv, v3, gf, paramc, param3);
492  tri_uvs[0] = {{param1.x(), param1.y()}};
493  tri_uvs[1] = {{param2.x(), param2.y()}};
494  tri_uvs[2] = {{param3.x(), param3.y()}};
495  }
496  else {
497  no_eval = true;
498  tri_uvs[0] = {{0., 0.}};
499  tri_uvs[1] = {{0., 0.}};
500  tri_uvs[2] = {{0., 0.}};
501  }
502  }
503  }
504 
505  triangles.push_back(tri_pts);
506  if(paramAvailable) triangle_uvs.push_back(tri_uvs);
507  if(paramAvailable && disableParamPer)
508  triangle_no_uv_eval.push_back(no_eval);
509  // Debug to visualize param
510  // {
511  // GeoLog::add({points[tri_pts[0]-1], points[tri_pts[1]-1],
512  // points[tri_pts[2]-1]},
513  // std::vector<double>{tri_uvs[0][0],tri_uvs[1][0],tri_uvs[2][0]},
514  // "sp_u");
515  // GeoLog::add({points[tri_pts[0]-1], points[tri_pts[1]-1],
516  // points[tri_pts[2]-1]},
517  // std::vector<double>{tri_uvs[0][1],tri_uvs[1][1],tri_uvs[2][1]},
518  // "sp_v");
519  // }
520  }
521  }
522 
523  points.shrink_to_fit();
524  triangles.shrink_to_fit();
525  triangle_uvs.shrink_to_fit();
526 
527  // Build an octree from a surface mesh
528  int32_t NmbVer = (int32_t)points.size();
529  double *VerTab1 = points[0].data();
530  double *VerTab2 = points[1].data();
531  // double* VerTab2 = VerTab1[3];
532  int32_t NmbTri = (int32_t)triangles.size();
533  int32_t *TriTab1 = triangles[0].data();
534  // int32_t* TriTab2 = TriTab1[3];
535  int32_t *TriTab2 = triangles[1].data();
536  Msg::Debug("create libOL octree (%i vertices and %i triangles)", NmbVer,
537  NmbTri);
538  OctIdx = LolNewOctree(NmbVer, VerTab1, VerTab2, 0, NULL, NULL, NmbTri,
539  TriTab1, TriTab2, 0, NULL, NULL, 0, NULL, NULL, 0, NULL,
540  NULL, 0, NULL, NULL, 0, NULL, NULL, BasIdx, 1);
541 
542  return true;
543 }
544 
546 {
547  GPoint fail(DBL_MAX, DBL_MAX, DBL_MAX, NULL);
548  fail.setNoSuccess();
549  return fail;
550 }
551 
552 GPoint sphereProjection(GFace *gf, const double query[3],
553  const std::array<double, 10> &analyticalParameters)
554 {
555  vec3 dir = {{query[0] - analyticalParameters[0],
556  query[1] - analyticalParameters[1],
557  query[2] - analyticalParameters[2]}};
558  if(length2(dir) == 0.) { return failedProjection(); }
559  normalize(dir);
560  const vec3 newPos = {{
561  analyticalParameters[0] + analyticalParameters[3] * dir[0],
562  analyticalParameters[1] + analyticalParameters[3] * dir[1],
563  analyticalParameters[2] + analyticalParameters[3] * dir[2]}};
564  return GPoint(newPos[0], newPos[1], newPos[2], gf);
565 }
566 
567 GPoint SurfaceProjector::closestPoint(const double query[3], bool evalOnCAD,
568  bool projectOnCAD) const
569 {
571  if(analyticalShape == GFace::GeomType::Sphere) {
572  return sphereProjection(gf, query, analyticalParameters);
573  }
574  else {
575  Msg::Error(
576  "SurfaceProjector::closestPoint(): no analytical formula for shape");
577  return failedProjection();
578  }
579  }
580 
581  if(OctIdx == 0) {
582  Msg::Error("SurfaceProjector::closestPoint(): no octree (face %i, %li "
583  "points, %li triangles)",
584  gf->tag(), points.size(), triangles.size());
585  return failedProjection();
586  }
587 
588  const int BasIdx = 1; /* indices start at one in libOL */
589 
590  /* Octree query */
591  double crd[3] = {query[0], query[1], query[2]};
592  double dis = DBL_MAX;
593  int idx = LolGetNearest(OctIdx, LolTypTri, crd, &dis, 0, NULL, NULL, 0);
594  if(idx <= 0) {
595  Msg::Warning("SurfaceProjector::closestPoint(): no closest triangle found "
596  "(face %i, %li triangles)",
597  gf->tag(), triangles.size());
598  return failedProjection();
599  }
600  size_t tri = idx - 1;
601 
602  /* Projection to get the barycentric coordinates */
603  const vec3 queryv3 = {{query[0], query[1], query[2]}};
604  const vec3 &p1 = points[triangles[tri][0] - BasIdx];
605  const vec3 &p2 = points[triangles[tri][1] - BasIdx];
606  const vec3 &p3 = points[triangles[tri][2] - BasIdx];
607 
608  // {
609  // int rdi = rand();
610  // GeoLog::add({p1,p2,p3},0.,"proj_"+std::to_string(rdi));
611  // GeoLog::add(queryv3,double(dis),"proj_"+std::to_string(rdi));
612  // }
613 
614  double lambda[3];
615  vec3 cproj;
616  project_point_triangle_l2(queryv3, p1, p2, p3, cproj, lambda);
617  GPoint proj;
618  if(triangle_uvs.size() > 0) {
619  double uv[2] = {0., 0.};
620  uv[0] = lambda[0] * triangle_uvs[tri][0][0] +
621  lambda[1] * triangle_uvs[tri][1][0] +
622  lambda[2] * triangle_uvs[tri][2][0];
623  uv[1] = lambda[0] * triangle_uvs[tri][0][1] +
624  lambda[1] * triangle_uvs[tri][1][1] +
625  lambda[2] * triangle_uvs[tri][2][1];
626  if(projectOnCAD) {
627  SPoint3 queryp3(query[0], query[1], query[2]);
628  GPoint cadProj = gf->closestPoint(queryp3, uv);
629  if(cadProj.succeeded()) { proj = cadProj; }
630  }
631  else if(evalOnCAD) {
632  if(triangle_no_uv_eval.size() > 0 && triangle_no_uv_eval[tri]) {
633  /* 3D projection */
634  SPoint3 queryp3(query[0], query[1], query[2]);
635  GPoint cadProj = gf->closestPoint(queryp3, uv);
636  if(cadProj.succeeded()) { proj = cadProj; }
637  }
638  else {
639  proj = gf->point(uv[0], uv[1]);
640  }
641  }
642  else {
643  proj = GPoint(cproj[0], cproj[1], cproj[2], gf, uv[0], uv[1]);
644  }
645  }
646  else {
647  proj = GPoint(cproj[0], cproj[1], cproj[2], gf);
648  }
649 
650  return proj;
651 }
652 
654  const std::vector<std::array<double,3> >& _points,
655  const std::vector<std::array<int32_t,2> >& _edges,
656  const std::vector<std::array<int32_t,3> >& _triangles,
657  const std::vector<std::array<int32_t,4> >& _quads,
658  const std::vector<std::array<int32_t,4> >& _tetrahedra,
659  const std::vector<std::array<int32_t,5> >& _pyramids,
660  const std::vector<std::array<int32_t,6> >& _prisms,
661  const std::vector<std::array<int32_t,8> >& _hexahedra):
662  points(_points), edges(_edges), triangles(_triangles), quads(_quads),
663  tetrahedra(_tetrahedra), pyramids(_pyramids), prisms(_prisms),
664  hexahedra(_hexahedra)
665 {
666  const int BasIdx = 1; /* indices start at one in libOL */
667  for (size_t i = 0; i < edges.size(); ++i) for (size_t j = 0; j < edges[0].size(); ++j) edges[i][j] += BasIdx;
668  for (size_t i = 0; i < triangles.size(); ++i) for (size_t j = 0; j < triangles[0].size(); ++j) triangles[i][j] += BasIdx;
669  for (size_t i = 0; i < quads.size(); ++i) for (size_t j = 0; j < quads[0].size(); ++j) quads[i][j] += BasIdx;
670  for (size_t i = 0; i < tetrahedra.size(); ++i) for (size_t j = 0; j < tetrahedra[0].size(); ++j) tetrahedra[i][j] += BasIdx;
671  for (size_t i = 0; i < pyramids.size(); ++i) for (size_t j = 0; j < pyramids[0].size(); ++j) pyramids[i][j] += BasIdx;
672  for (size_t i = 0; i < prisms.size(); ++i) for (size_t j = 0; j < prisms[0].size(); ++j) prisms[i][j] += BasIdx;
673  for (size_t i = 0; i < hexahedra.size(); ++i) for (size_t j = 0; j < hexahedra[0].size(); ++j) hexahedra[i][j] += BasIdx;
674 
675  // Build an octree
676  double t0 = Cpu();
678  (int32_t)points.size(), points[0].data(), points[1].data(),
679  (int32_t)edges.size(), edges[0].data(), edges[1].data(),
680  (int32_t)triangles.size(), triangles[0].data(), triangles[1].data(),
681  (int32_t)quads.size(), quads[0].data(), quads[1].data(),
682  (int32_t)tetrahedra.size(), tetrahedra[0].data(), tetrahedra[1].data(),
683  (int32_t)pyramids.size(), pyramids[0].data(), pyramids[1].data(),
684  (int32_t)prisms.size(), prisms[0].data(), prisms[1].data(),
685  (int32_t)hexahedra.size(), hexahedra[0].data(), hexahedra[1].data(),
686  BasIdx, 1);
687 
688  Msg::Debug("libOL octree created (%li vertices, %.3f sec), OctIdx: %li", points.size(), Cpu()-t0, OctIdx);
689 }
690 
692  if(OctIdx != 0) {
693  Msg::Debug("libOL octree freed (OctIdx: %li)", OctIdx);
695  OctIdx = 0;
696  }
697 }
698 
700  double* bboxMin, double* bboxMax,
701  std::vector<int32_t>& elements) {
702 
703  const int BufSiz = 1e5;
704  int buf[BufSiz];
705 
706  int NmbItm = LolGetBoundingBox(OctIdx, (int)elementType, BufSiz, buf, bboxMin, bboxMax, 0);
707  elements.resize(NmbItm);
708  for (int i = 0; i < NmbItm; ++i) {
709  elements[i] = buf[i]-1;
710  }
711 
712  return NmbItm;
713 }
LolNewOctree
int64_t LolNewOctree(itg NmbVer, fpn *PtrCrd1, fpn *PtrCrd2, itg NmbEdg, itg *PtrEdg1, itg *PtrEdg2, itg NmbTri, itg *PtrTri1, itg *PtrTri2, itg NmbQad, itg *PtrQad1, itg *PtrQad2, itg NmbTet, itg *PtrTet1, itg *PtrTet2, itg NmbPyr, itg *PtrPyr1, itg *PtrPyr2, itg NmbPri, itg *PtrPri1, itg *PtrPri2, itg NmbHex, itg *PtrHex1, itg *PtrHex2, itg BasIdx, itg NmbThr)
Definition: libol1.c:343
GPoint::succeeded
bool succeeded() const
Definition: GPoint.h:63
SurfaceProjectorUtils::normalize
void normalize(vec3 &a)
Definition: meshOctreeLibOL.cpp:59
MTriangle.h
robin_hood.h
libOLwrapper::OctIdx
int64_t OctIdx
Definition: meshOctreeLibOL.h:124
SurfaceProjectorUtils::vec2
std::array< double, 2 > vec2
Definition: meshOctreeLibOL.cpp:27
SurfaceProjector::setAnalyticalProjection
bool setAnalyticalProjection(GFace *gf)
The SurfaceProjector can project with an analytical formula instead of a triangulation and a octree S...
Definition: meshOctreeLibOL.cpp:343
libol1.h
GPoint::y
double y() const
Definition: GPoint.h:22
GFace.h
SurfaceProjectorUtils::operator+
vec3 operator+(const vec3 &a, const vec3 &b)
Definition: meshOctreeLibOL.cpp:33
SurfaceProjector::OctIdx
int64_t OctIdx
Definition: meshOctreeLibOL.h:83
SurfaceProjector::~SurfaceProjector
~SurfaceProjector()
Definition: meshOctreeLibOL.cpp:341
GFace
Definition: GFace.h:33
GFace::triangles
std::vector< MTriangle * > triangles
Definition: GFace.h:428
SPoint2
Definition: SPoint2.h:12
OS.h
Msg::Debug
static void Debug(const char *fmt,...)
Definition: GmshMessage.cpp:752
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
libOLwrapper::prisms
std::vector< std::array< int32_t, 6 > > prisms
Definition: meshOctreeLibOL.h:122
MVertex
Definition: MVertex.h:24
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
libOLwrapper::points
std::vector< std::array< double, 3 > > points
Definition: meshOctreeLibOL.h:116
SPoint3
Definition: SPoint3.h:14
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
GFace::isSphere
virtual bool isSphere(double &radius, SPoint3 &center) const
Definition: GFace.h:333
libOLwrapper::elementsInsideBoundingBox
int elementsInsideBoundingBox(libOLTypTag elementType, double *bboxMin, double *bboxMax, std::vector< int32_t > &elements)
Definition: meshOctreeLibOL.cpp:699
GFace::point
virtual GPoint point(double par1, double par2) const =0
libOLwrapper::quads
std::vector< std::array< int32_t, 4 > > quads
Definition: meshOctreeLibOL.h:119
LolGetBoundingBox
itg LolGetBoundingBox(int64_t OctIdx, itg typ, itg MaxItm, itg *ItmTab, fpn MinCrd[3], fpn MaxCrd[3], itg ThrIdx)
Definition: libol1.c:639
MVertex::onWhat
GEntity * onWhat() const
Definition: MVertex.h:82
LolFreeOctree
size_t LolFreeOctree(int64_t OctIdx)
Definition: libol1.c:623
libOLwrapper::~libOLwrapper
~libOLwrapper()
Definition: meshOctreeLibOL.cpp:691
SurfaceProjector::initialize
bool initialize(GFace *gf, const std::vector< MTriangle * > &triangles, bool useCADStl=false)
Fill the triangles and uvs from the triangles, then build the octree. Overwrite existing triangulatio...
Definition: meshOctreeLibOL.cpp:364
MVertex::point
SPoint3 point() const
Definition: MVertex.h:67
edges
static int edges[6][2]
Definition: meshGRegionLocalMeshMod.cpp:23
GPoint
Definition: GPoint.h:13
GFace::closestPoint
virtual GPoint closestPoint(const SPoint3 &queryPoint, const double initialGuess[2]) const
Definition: GFace.cpp:1323
GFace::quadrangles
std::vector< MQuadrangle * > quadrangles
Definition: GFace.h:429
SurfaceProjector::SurfaceProjector
SurfaceProjector()
Definition: meshOctreeLibOL.h:26
SurfaceProjector::gf
GFace * gf
Definition: meshOctreeLibOL.h:76
libOLwrapper::tetrahedra
std::vector< std::array< int32_t, 4 > > tetrahedra
Definition: meshOctreeLibOL.h:120
libOLwrapper::edges
std::vector< std::array< int32_t, 2 > > edges
Definition: meshOctreeLibOL.h:117
SurfaceProjectorUtils
Definition: meshOctreeLibOL.cpp:24
GPoint::z
double z() const
Definition: GPoint.h:23
GFace::stl_vertices_xyz
std::vector< SPoint3 > stl_vertices_xyz
Definition: GFace.h:409
SPoint3::x
double x(void) const
Definition: SPoint3.h:125
GEntity::periodic
virtual bool periodic(int dim) const
Definition: GEntity.h:244
SurfaceProjector::triangles
std::vector< std::array< int32_t, 3 > > triangles
Definition: meshOctreeLibOL.h:80
libOLwrapper::triangles
std::vector< std::array< int32_t, 3 > > triangles
Definition: meshOctreeLibOL.h:118
SurfaceProjectorUtils::maxAbs
double maxAbs(double x, double y, double z)
Definition: meshOctreeLibOL.cpp:50
GPoint::u
double u() const
Definition: GPoint.h:27
SurfaceProjector::closestPoint
GPoint closestPoint(const double query[3], bool evalOnCAD=false, bool projectOnCAD=false) const
Get the query closest point on the triangulated surface.
Definition: meshOctreeLibOL.cpp:567
SurfaceProjector::triangle_uvs
std::vector< std::array< std::array< double, 2 >, 3 > > triangle_uvs
Definition: meshOctreeLibOL.h:81
MVertex.h
LolGetNearest
itg LolGetNearest(int64_t OctIdx, itg typ, fpn *VerCrd, fpn *MinDis, fpn MaxDis, itg(UsrPrc)(void *, itg), void *UsrDat, itg ThrIdx)
Definition: libol1.c:786
SurfaceProjector::clear
void clear()
Clear the triangulation and delete the octree.
Definition: meshOctreeLibOL.cpp:329
sphereProjection
GPoint sphereProjection(GFace *gf, const double query[3], const std::array< double, 10 > &analyticalParameters)
Definition: meshOctreeLibOL.cpp:552
SurfaceProjector::analyticalShape
GFace::GeomType analyticalShape
Definition: meshOctreeLibOL.h:87
Cpu
double Cpu()
Definition: OS.cpp:366
SurfaceProjectorUtils::operator*
vec3 operator*(const double &a, const vec3 &b)
Definition: meshOctreeLibOL.cpp:37
reparamMeshEdgeOnFace
bool reparamMeshEdgeOnFace(MVertex *v1, MVertex *v2, GFace *gf, SPoint2 &param1, SPoint2 &param2)
Definition: MVertex.cpp:474
GEntity::geomType
virtual GeomType geomType() const
Definition: GEntity.h:238
SPoint3::y
double y(void) const
Definition: SPoint3.h:127
libOLTypTag::LolTypTri
@ LolTypTri
GFace::stl_triangles
std::vector< int > stl_triangles
Definition: GFace.h:412
GEntity::tag
int tag() const
Definition: GEntity.h:280
MFaceVertex
Definition: MVertex.h:168
SurfaceProjector::points
std::vector< std::array< double, 3 > > points
Definition: meshOctreeLibOL.h:79
discreteFace.h
SurfaceProjectorUtils::project_point_segment_l2
double project_point_segment_l2(const vec3 &query, const vec3 &a, const vec3 &b, vec3 &proj, double &lambda)
Definition: meshOctreeLibOL.cpp:67
robin_hood::detail::Table::end
iterator end()
Definition: robin_hood.h:1996
SurfaceProjectorUtils::vec3
std::array< double, 3 > vec3
Definition: meshOctreeLibOL.cpp:28
SurfaceProjectorUtils::project_point_triangle_l2
double project_point_triangle_l2(const vec3 &query, const vec3 &p1, const vec3 &p2, const vec3 &p3, vec3 &proj, double lambda[3])
Definition: meshOctreeLibOL.cpp:90
SurfaceProjectorUtils::length2
double length2(const vec3 &a)
Definition: meshOctreeLibOL.cpp:49
MTriangle
Definition: MTriangle.h:26
b1
const double b1
Definition: GaussQuadratureHex.cpp:14
MVertex::getParameter
virtual bool getParameter(int i, double &par) const
Definition: MVertex.h:97
GPoint::setNoSuccess
bool setNoSuccess()
Definition: GPoint.h:64
SPoint2::x
double x(void) const
Definition: SPoint2.h:86
SurfaceProjectorUtils::operator-
vec3 operator-(const vec3 &a, const vec3 &b)
Definition: meshOctreeLibOL.cpp:29
SurfaceProjector::analyticalParameters
std::array< double, 10 > analyticalParameters
Definition: meshOctreeLibOL.h:88
SurfaceProjectorUtils::normalizeFast
void normalizeFast(vec3 &a)
Definition: meshOctreeLibOL.cpp:55
robin_hood::detail::Table::find
const_iterator find(const key_type &key) const
Definition: robin_hood.h:1935
failedProjection
GPoint failedProjection()
Definition: meshOctreeLibOL.cpp:545
libOLwrapper::pyramids
std::vector< std::array< int32_t, 5 > > pyramids
Definition: meshOctreeLibOL.h:121
z
const double z
Definition: GaussQuadratureQuad.cpp:56
dis
static fpn dis(fpn *, fpn *)
libOLTypTag
libOLTypTag
Definition: meshOctreeLibOL.h:93
SurfaceProjector::triangle_no_uv_eval
std::vector< bool > triangle_no_uv_eval
Definition: meshOctreeLibOL.h:82
GFace::stl_vertices_uv
std::vector< SPoint2 > stl_vertices_uv
Definition: GFace.h:408
SPoint3::z
double z(void) const
Definition: SPoint3.h:129
GFace::buildSTLTriangulation
virtual bool buildSTLTriangulation(bool force=false)
Definition: GFace.cpp:1585
GPoint::v
double v() const
Definition: GPoint.h:28
SurfaceProjectorUtils::dot
double dot(const vec3 &a, const vec3 &b)
Definition: meshOctreeLibOL.cpp:45
libOLwrapper::hexahedra
std::vector< std::array< int32_t, 8 > > hexahedra
Definition: meshOctreeLibOL.h:123
GPoint::x
double x() const
Definition: GPoint.h:21
robin_hood::detail::Table
Definition: robin_hood.h:916
meshOctreeLibOL.h
SurfaceProjector::useAnalyticalFormula
bool useAnalyticalFormula
Definition: meshOctreeLibOL.h:86
GEntity::haveParametrization
virtual bool haveParametrization()
Definition: GEntity.h:251
SPoint2::y
double y(void) const
Definition: SPoint2.h:88
libOLwrapper::libOLwrapper
libOLwrapper(const std::vector< std::array< double, 3 > > &points, const std::vector< std::array< int32_t, 2 > > &edges, const std::vector< std::array< int32_t, 3 > > &triangles, const std::vector< std::array< int32_t, 4 > > &quads, const std::vector< std::array< int32_t, 4 > > &tetrahedra, const std::vector< std::array< int32_t, 5 > > &pyramids, const std::vector< std::array< int32_t, 6 > > &prisms, const std::vector< std::array< int32_t, 8 > > &hexahedra)
Definition: meshOctreeLibOL.cpp:653