gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
MElementOctree.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 #include "GModel.h"
7 #include "MElement.h"
8 #include "MElementOctree.h"
9 #include "Octree.h"
10 #include "Context.h"
11 #include "fullMatrix.h"
12 #include "bezierBasis.h"
13 #include "BasisFactory.h"
14 #include "SBoundingBox3d.h"
15 #include "Context.h"
16 
17 void MElementBB(void *a, double *min, double *max)
18 {
19  MElement *e = static_cast<MElement *>(a);
20 
21  if(e->getPolynomialOrder() == 1) {
22  MVertex *v = e->getVertex(0);
23  min[0] = max[0] = v->x();
24  min[1] = max[1] = v->y();
25  min[2] = max[2] = v->z();
26  for(std::size_t i = 1; i < e->getNumVertices(); i++) {
27  v = e->getVertex(i);
28  min[0] = std::min(min[0], v->x());
29  max[0] = std::max(max[0], v->x());
30  min[1] = std::min(min[1], v->y());
31  max[1] = std::max(max[1], v->y());
32  min[2] = std::min(min[2], v->z());
33  max[2] = std::max(max[2], v->z());
34  }
35  }
36  else {
37  bezierCoeff &bezNodes = *e->getBezierVerticesCoord();
38 
39  min[0] = max[0] = bezNodes(0, 0);
40  min[1] = max[1] = bezNodes(0, 1);
41  min[2] = max[2] = bezNodes(0, 2);
42  for(int i = 1; i < bezNodes.getNumCoeff(); i++) {
43  min[0] = std::min(min[0], bezNodes(i, 0));
44  max[0] = std::max(max[0], bezNodes(i, 0));
45  min[1] = std::min(min[1], bezNodes(i, 1));
46  max[1] = std::max(max[1], bezNodes(i, 1));
47  min[2] = std::min(min[2], bezNodes(i, 2));
48  max[2] = std::max(max[2], bezNodes(i, 2));
49  }
50 
51  delete &bezNodes;
52  }
53 
54  SBoundingBox3d bb(min[0], min[1], min[2], max[0], max[1], max[2]);
55  bb.thicken(0.01); // make 1% thicker
56  max[0] = bb.max().x();
57  max[1] = bb.max().y();
58  max[2] = bb.max().z();
59  min[0] = bb.min().x();
60  min[1] = bb.min().y();
61  min[2] = bb.min().z();
62 }
63 
64 static void MElementCentroid(void *a, double *x)
65 {
66  MElement *e = (MElement *)a;
67  MVertex *v = e->getVertex(0);
68  int n = e->getNumVertices();
69  x[0] = v->x();
70  x[1] = v->y();
71  x[2] = v->z();
72  for(int i = 1; i < n; i++) {
73  v = e->getVertex(i);
74  x[0] += v->x();
75  x[1] += v->y();
76  x[2] += v->z();
77  }
78  double oc = 1. / (double)n;
79  x[0] *= oc;
80  x[1] *= oc;
81  x[2] *= oc;
82 }
83 
84 int MElementInEle(void *a, double *x)
85 {
86  MElement *e = (MElement *)a;
87  double uvw[3];
88  e->xyz2uvw(x, uvw);
89  return e->isInside(uvw[0], uvw[1], uvw[2]) ? 1 : 0;
90 }
91 
93 {
94  SBoundingBox3d bb = m->bounds();
95  bb.thicken(0.01); // make 1% thicker
96  SPoint3 bbmin = bb.min(), bbmax = bb.max();
97  double min[3] = {bbmin.x(), bbmin.y(), bbmin.z()};
98  double size[3] = {bbmax.x() - bbmin.x(), bbmax.y() - bbmin.y(),
99  bbmax.z() - bbmin.z()};
100  const int maxElePerBucket = 100; // memory vs. speed trade-off
101  _octree = Octree_Create(maxElePerBucket, min, size, MElementBB,
103  std::vector<GEntity *> entities;
104  m->getEntities(entities);
105  // do not add Gvertex non-associated to any GEdge
106  for(std::size_t i = 0; i < entities.size(); i++) {
107  for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++) {
108  if(entities[i]->dim() == 0) {
109  GVertex *gv = dynamic_cast<GVertex *>(entities[i]);
110  if(gv && gv->edges().size() > 0) {
111  Octree_Insert(entities[i]->getMeshElement(j), _octree);
112  }
113  }
114  else
115  Octree_Insert(entities[i]->getMeshElement(j), _octree);
116  }
117  }
119 }
120 
121 MElementOctree::MElementOctree(const std::vector<MElement *> &v)
122  : _gm(nullptr), _elems(v)
123 {
124  SBoundingBox3d bb;
125  for(std::size_t i = 0; i < v.size(); i++) {
126  for(std::size_t j = 0; j < v[i]->getNumVertices(); j++) {
127  bb += SPoint3(v[i]->getVertex(j)->x(), v[i]->getVertex(j)->y(),
128  v[i]->getVertex(j)->z());
129  }
130  }
131  bb.thicken(0.01); // make 1% thicker
132  SPoint3 bbmin = bb.min(), bbmax = bb.max();
133  double min[3] = {bbmin.x(), bbmin.y(), bbmin.z()};
134  double size[3] = {bbmax.x() - bbmin.x(), bbmax.y() - bbmin.y(),
135  bbmax.z() - bbmin.z()};
136  const int maxElePerBucket = 100; // memory vs. speed trade-off
137  _octree = Octree_Create(maxElePerBucket, min, size, MElementBB,
139  for(std::size_t i = 0; i < v.size(); i++) Octree_Insert(v[i], _octree);
141 }
142 
144 
145 std::vector<MElement *> MElementOctree::findAll(double x, double y, double z,
146  int dim, bool strict) const
147 {
148  double maxTol = 1.;
149  double tolIncr = 10.;
150 
151  double P[3] = {x, y, z};
152  std::vector<void *> v;
153  std::vector<MElement *> e;
154  Octree_SearchAll(P, _octree, &v);
155  for(auto it = v.begin(); it != v.end(); ++it) {
156  MElement *el = (MElement *)*it;
157  if(dim == -1 || el->getDim() == dim) e.push_back(el);
158  }
159  if(e.empty() && !strict && _gm) {
160  double initialTol = CTX::instance()->mesh.toleranceReferenceElement;
161  double tol = initialTol;
162  while(tol < maxTol) {
163  tol *= tolIncr;
165  std::vector<GEntity *> entities;
166  _gm->getEntities(entities);
167  for(std::size_t i = 0; i < entities.size(); i++) {
168  for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++) {
169  MElement *el = entities[i]->getMeshElement(j);
170  if(dim == -1 || el->getDim() == dim) {
171  if(MElementInEle(el, P)) { e.push_back(el); }
172  }
173  }
174  }
175  if(!e.empty()) {
177  return e;
178  }
179  }
181  }
182  else if(e.empty() && !strict && !_gm) {
183  double initialTol = CTX::instance()->mesh.toleranceReferenceElement;
184  double tol = initialTol;
185  while(tol < maxTol) {
186  tol *= tolIncr;
188  for(std::size_t i = 0; i < _elems.size(); i++) {
189  MElement *el = _elems[i];
190  if(dim == -1 || el->getDim() == dim) {
191  if(MElementInEle(el, P)) { e.push_back(el); }
192  }
193  }
194  if(!e.empty()) {
196  return e;
197  }
198  }
200  // Msg::Warning("Point %g %g %g not found",x,y,z);
201  }
202  return e;
203 }
204 
205 MElement *MElementOctree::find(double x, double y, double z, int dim,
206  bool strict) const
207 {
208  double P[3] = {x, y, z};
210  if(e && (dim == -1 || e->getDim() == dim)) return e;
211  std::vector<void *> l;
212  if(e && e->getDim() != dim) {
213  Octree_SearchAll(P, _octree, &l);
214  for(auto it = l.begin(); it != l.end(); it++) {
215  MElement *el = (MElement *)*it;
216  if(el->getDim() == dim) { return el; }
217  }
218  }
219  if(!strict && _gm) {
220  double initialTol = CTX::instance()->mesh.toleranceReferenceElement;
221  double tol = initialTol;
222  while(tol < 1.) {
223  tol *= 10;
225  std::vector<GEntity *> entities;
226  _gm->getEntities(entities);
227  for(std::size_t i = 0; i < entities.size(); i++) {
228  for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++) {
229  e = entities[i]->getMeshElement(j);
230  if(dim == -1 || e->getDim() == dim) {
231  if(MElementInEle(e, P)) {
233  return e;
234  }
235  }
236  }
237  }
238  }
240  // Msg::Warning("Point %g %g %g not found",x,y,z);
241  }
242  else if(!strict && !_gm) {
243  double initialTol = CTX::instance()->mesh.toleranceReferenceElement;
244  double tol = initialTol;
245  while(tol < 0.1) {
246  tol *= 10.0;
248  for(std::size_t i = 0; i < _elems.size(); i++) {
249  e = _elems[i];
250  if(dim == -1 || e->getDim() == dim) {
251  if(MElementInEle(e, P)) {
253  return e;
254  }
255  }
256  }
257  }
259  // Msg::Warning("Point %g %g %g not found",x,y,z);
260  }
261  return nullptr;
262 }
MElement::xyz2uvw
virtual void xyz2uvw(double xyz[3], double uvw[3]) const
Definition: MElement.cpp:1128
contextMeshOptions::toleranceReferenceElement
double toleranceReferenceElement
Definition: Context.h:47
SBoundingBox3d::thicken
void thicken(double factor)
Definition: SBoundingBox3d.h:103
Octree.h
MVertex
Definition: MVertex.h:24
MElement::getDim
virtual int getDim() const =0
MElementOctree::_elems
std::vector< MElement * > _elems
Definition: MElementOctree.h:19
MElementOctree.h
MVertex::z
double z() const
Definition: MVertex.h:62
SPoint3
Definition: SPoint3.h:14
SBoundingBox3d::min
SPoint3 min() const
Definition: SBoundingBox3d.h:90
Octree_Insert
void Octree_Insert(void *element, Octree *myOctree)
Definition: Octree.cpp:55
GVertex::edges
virtual std::vector< GEdge * > const & edges() const
Definition: GVertex.h:54
Octree_Delete
void Octree_Delete(Octree *myOctree)
Definition: Octree.cpp:46
Octree_SearchAll
void Octree_SearchAll(double *pt, Octree *myOctree, std::vector< void * > *output)
Definition: Octree.cpp:88
MElement::getNumVertices
virtual std::size_t getNumVertices() const =0
CTX::instance
static CTX * instance()
Definition: Context.cpp:122
MElement::getVertex
virtual const MVertex * getVertex(int num) const =0
SPoint3::x
double x(void) const
Definition: SPoint3.h:125
MElementInEle
int MElementInEle(void *a, double *x)
Definition: MElementOctree.cpp:84
Octree_Search
void * Octree_Search(double *pt, Octree *myOctree)
Definition: Octree.cpp:81
Octree_Arrange
void Octree_Arrange(Octree *myOctree)
Definition: Octree.cpp:67
GModel::bounds
SBoundingBox3d bounds(bool aroundVisible=false)
Definition: GModel.cpp:1043
bezierCoeff
Definition: bezierBasis.h:127
GVertex
Definition: GVertex.h:23
MElementCentroid
static void MElementCentroid(void *a, double *x)
Definition: MElementOctree.cpp:64
SBoundingBox3d.h
GModel
Definition: GModel.h:44
MElementOctree::_octree
Octree * _octree
Definition: MElementOctree.h:17
SPoint3::y
double y(void) const
Definition: SPoint3.h:127
bezierCoeff::getNumCoeff
int getNumCoeff() const
Definition: bezierBasis.h:169
Octree_Create
Octree * Octree_Create(int maxElements, double origin[3], double size[3], void(*BB)(void *, double *, double *), void(*Centroid)(void *, double *), int(*InEle)(void *, double *))
Definition: Octree.cpp:11
CTX::mesh
contextMeshOptions mesh
Definition: Context.h:313
MElement
Definition: MElement.h:30
MElementOctree::MElementOctree
MElementOctree(GModel *)
Definition: MElementOctree.cpp:92
MElementOctree::~MElementOctree
~MElementOctree()
Definition: MElementOctree.cpp:143
GModel::getEntities
void getEntities(std::vector< GEntity * > &entities, int dim=-1) const
Definition: GModel.cpp:651
MElementOctree::find
MElement * find(double x, double y, double z, int dim=-1, bool strict=false) const
Definition: MElementOctree.cpp:205
MElementBB
void MElementBB(void *a, double *min, double *max)
Definition: MElementOctree.cpp:17
MElement::getBezierVerticesCoord
bezierCoeff * getBezierVerticesCoord() const
Definition: MElement.cpp:998
Context.h
MElementOctree::_gm
GModel * _gm
Definition: MElementOctree.h:18
z
const double z
Definition: GaussQuadratureQuad.cpp:56
MElement.h
MElement::isInside
virtual bool isInside(double u, double v, double w) const =0
MElementOctree::findAll
std::vector< MElement * > findAll(double x, double y, double z, int dim, bool strict=false) const
Definition: MElementOctree.cpp:145
SPoint3::z
double z(void) const
Definition: SPoint3.h:129
GModel.h
MVertex::y
double y() const
Definition: MVertex.h:61
MElement::getPolynomialOrder
virtual int getPolynomialOrder() const
Definition: MElement.h:78
SBoundingBox3d::max
SPoint3 max() const
Definition: SBoundingBox3d.h:91
bezierBasis.h
SBoundingBox3d
Definition: SBoundingBox3d.h:21
fullMatrix.h
MVertex::x
double x() const
Definition: MVertex.h:60
BasisFactory.h