NEMoSys  0.63.0
A modular, extensible resource with robust automated mesh generation, mesh quality analysis, adaptive mesh refinement, and data transfer between arbitrary meshes.
meshSrch.C
Go to the documentation of this file.
1 /*******************************************************************************
2 * Promesh *
3 * Copyright (C) 2022, IllinoisRocstar LLC. All rights reserved. *
4 * *
5 * Promesh is the property of IllinoisRocstar LLC. *
6 * *
7 * IllinoisRocstar LLC *
8 * Champaign, IL *
9 * www.illinoisrocstar.com *
10 * promesh@illinoisrocstar.com *
11 *******************************************************************************/
12 /*******************************************************************************
13 * This file is part of Promesh *
14 * *
15 * This version of Promesh is free software: you can redistribute it and/or *
16 * modify it under the terms of the GNU Lesser General Public License as *
17 * published by the Free Software Foundation, either version 3 of the License, *
18 * or (at your option) any later version. *
19 * *
20 * Promesh is distributed in the hope that it will be useful, but WITHOUT ANY *
21 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more *
23 * details. *
24 * *
25 * You should have received a copy of the GNU Lesser General Public License *
26 * along with this program. If not, see <https://www.gnu.org/licenses/>. *
27 * *
28 *******************************************************************************/
29 #include "MeshOperation/meshSrch.H"
30 
31 #include <vtkCell.h>
32 #include <vtkCellArray.h>
33 #include <vtkCellCenters.h>
34 #include <vtkPoints.h>
35 #include <vtkPolyData.h>
36 #include <vtkSelectEnclosedPoints.h>
37 #include <vtkSphereSource.h>
38 
39 // DEBUG:
40 //#include <vtkSTLWriter.h>
41 
42 #include "AuxiliaryFunctions.H"
43 
44 using nemAux::operator*; // for vector multiplication.
45 using nemAux::operator+; // for vector addition.
46 
47 // get point with id
48 std::vector<double> meshSrch::getPoint(nemId_t id) const {
49  double coords[3];
50  dataSet->GetPoint(id, coords);
51  std::vector<double> result(coords, coords + 3);
52  return result;
53 }
54 
55 // returns coordinates of the cell vertices in a vector
56 std::vector<std::vector<double>> meshSrch::getCellVec(nemId_t id) const {
57  if (id < numCells) {
58  std::vector<std::vector<double>> cell;
59  vtkSmartPointer<vtkIdList> point_ids = vtkSmartPointer<vtkIdList>::New();
60  point_ids = dataSet->GetCell(id)->GetPointIds();
61  vtkIdType num_ids = point_ids->GetNumberOfIds();
62  cell.resize(num_ids);
63  for (vtkIdType i = 0; i < num_ids; ++i) {
64  nemId_t pntId = point_ids->GetId(i);
65  cell[i] = getPoint(pntId);
66  }
67  return cell;
68  } else {
69  std::cerr << "Cell ID is out of range!" << std::endl;
70  exit(1);
71  }
72 }
73 
74 // get center of a cell
75 std::vector<double> meshSrch::getCellCenter(nemId_t cellID) const {
76  std::vector<double> center(3);
77  std::vector<std::vector<double>> cell = getCellVec(cellID);
78 
79  for (const auto &i : cell) center = center + i;
80  return (1.0 / static_cast<double>(cell.size())) * center;
81 }
82 
84  if (upd_vcl) {
85  // Create the tree
87  vcl->SetDataSet(dataSet);
88  vcl->BuildLocator();
89  upd_vcl = false;
90  }
91 }
92 
93 void meshSrch::FindCellsWithinBounds(std::vector<double> &bb,
94  std::vector<nemId_t> &ids, bool fulImrsd) {
95  // finding all intersecting cells
97  vtkSmartPointer<vtkIdList> idl = vtkSmartPointer<vtkIdList>::New();
98  vcl->FindCellsWithinBounds(bb.data(), idl);
99  std::cout << "Found " << idl->GetNumberOfIds() << " cells." << std::endl;
100  std::vector<nemId_t> aids;
101  for (vtkIdType idx = 0; idx < idl->GetNumberOfIds(); idx++)
102  aids.push_back(idl->GetId(idx));
103  // removing cells centered out of the bounding box
104  int nr = 0;
105  if (fulImrsd) {
106  for (const auto &aid : aids)
107  if (!nemAux::isInBBox(getCellCenter(aid), bb)) {
108  nr++;
109  continue;
110  } else {
111  ids.push_back(aid);
112  }
113  std::cout << "Remove " << nr << " cells from the list." << std::endl;
114  } else {
115  ids = aids;
116  }
117 }
118 
119 void meshSrch::FindPntsOnTriSrf(const std::vector<double> &crds,
120  const std::vector<nemId_t> &conn,
121  std::set<nemId_t> &ids, double tol) const {
122  // create polyData
123  vtkSmartPointer<vtkPoints> pnts = vtkSmartPointer<vtkPoints>::New();
124  for (std::size_t iPnt = 0; iPnt < crds.size() / 3; iPnt++)
125  pnts->InsertNextPoint(crds[iPnt * 3], crds[iPnt * 3 + 1],
126  crds[iPnt * 3 + 2]);
127  vtkSmartPointer<vtkCellArray> polys = vtkSmartPointer<vtkCellArray>::New();
128  for (std::size_t iCel = 0; iCel < conn.size() / 3; iCel++) {
129  polys->InsertNextCell(3);
130  polys->InsertCellPoint(conn[iCel * 3]);
131  polys->InsertCellPoint(conn[iCel * 3 + 1]);
132  polys->InsertCellPoint(conn[iCel * 3 + 2]);
133  }
134  vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
135  polyData->SetPoints(pnts);
136  polyData->SetPolys(polys);
137 
138  // Write the file
139  // vtkSmartPointer<vtkXMLPolyDataWriter> writer
140  // = vtkSmartPointer<vtkXMLPolyDataWriter>::New();
141  // writer->SetFileName("test.vtp");
142  // writer->SetInputData(polyData);
143  // Optional - set the mode. The default is binary.
144  ////writer->SetDataModeToBinary();
145  // writer->SetDataModeToAscii();
146  // writer->Write();
147 
148  // find nodes residing on the trisurf
149  // create cell locator
150  vtkSmartPointer<vtkCellLocator> cellLocator =
152  cellLocator->SetDataSet(polyData);
153  cellLocator->BuildLocator();
154 
155  double closestPoint[3];
156  double closestPointDist2;
157  vtkIdType cellId;
158  int subId;
159  for (nemId_t iPt = 0; iPt < getNumberOfPoints(); iPt++) {
160  std::vector<double> pnt = getPoint(iPt);
161  cellLocator->FindClosestPoint(pnt.data(), closestPoint, cellId, subId,
162  closestPointDist2);
163  if (closestPointDist2 < tol) ids.insert(iPt + 1);
164  }
165 }
166 
167 void meshSrch::FindPntsOnEdge(std::vector<double> &crds, std::set<nemId_t> &ids,
168  double tol) const {
169  // create polyData
170  vtkSmartPointer<vtkPoints> pnts = vtkSmartPointer<vtkPoints>::New();
171  for (std::size_t iPnt = 0; iPnt < crds.size() / 3; iPnt++)
172  pnts->InsertNextPoint(crds[iPnt * 3], crds[iPnt * 3 + 1],
173  crds[iPnt * 3 + 2]);
174  vtkSmartPointer<vtkCellArray> polys = vtkSmartPointer<vtkCellArray>::New();
175  polys->InsertNextCell(2);
176  polys->InsertCellPoint(0);
177  polys->InsertCellPoint(1);
178  vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
179  polyData->SetPoints(pnts);
180  polyData->SetPolys(polys);
181 
182  // Write the file
183  // vtkSmartPointer<vtkXMLPolyDataWriter> writer
184  // = vtkSmartPointer<vtkXMLPolyDataWriter>::New();
185  // writer->SetFileName("edge.vtp");
186  // writer->SetInputData(polyData);
187  // Optional - set the mode. The default is binary.
188  ////writer->SetDataModeToBinary();
189  // writer->SetDataModeToAscii();
190  // writer->Write();
191 
192  // find nodes residing on the edge
193  // create cell locator
194  vtkSmartPointer<vtkCellLocator> cellLocator =
196  cellLocator->SetDataSet(polyData);
197  cellLocator->BuildLocator();
198 
199  double closestPoint[3];
200  double closestPointDist2;
201  vtkIdType cellId;
202  int subId;
203  for (nemId_t iPt = 0; iPt < getNumberOfPoints(); iPt++) {
204  std::vector<double> pnt = getPoint(iPt);
205  cellLocator->FindClosestPoint(pnt.data(), closestPoint, cellId, subId,
206  closestPointDist2);
207  if (closestPointDist2 < tol) ids.insert(iPt + 1);
208  }
209 }
210 
211 // checks for duplicate elements
212 bool meshSrch::chkDuplElm() const {
213  std::set<std::vector<nemId_t>> ids;
214  for (nemId_t ic = 0; ic < getNumberOfCells(); ic++) {
215  std::vector<nemId_t> cid;
216  vtkSmartPointer<vtkIdList> idl = vtkSmartPointer<vtkIdList>::New();
217  idl = dataSet->GetCell(ic)->GetPointIds();
218  for (vtkIdType id = 0; id < idl->GetNumberOfIds(); id++)
219  cid.push_back(idl->GetId(id));
220  std::pair<std::set<std::vector<nemId_t>>::iterator, bool> ret;
221  ret = ids.insert(cid);
222  if (!ret.second) return true;
223  }
224  return false;
225 }
226 
227 void meshSrch::FindCellsInPolyData(vtkPolyData *polyData,
228  std::vector<nemId_t> &ids, bool query3Donly,
229  double tol) const {
230  // pass dataSet through vtkCellCenters filter
231  vtkSmartPointer<vtkCellCenters> cc = vtkSmartPointer<vtkCellCenters>::New();
232 
233  cc->SetInputData(dataSet);
234 
235  // create vtkSelectEnclosedPoints
236  vtkSmartPointer<vtkSelectEnclosedPoints> sep =
238 
239  sep->SetInputConnection(cc->GetOutputPort());
240 
241  sep->SetSurfaceData(polyData);
242  // sep->CheckSurfaceOn();
243 
244  sep->SetTolerance(tol);
245 
246  sep->Update();
247 
248  for (nemId_t id = 0; id < getNumberOfCells(); ++id)
249  if (sep->IsInside(id)) {
250  if (query3Donly && dataSet->GetCell(id)->GetCellDimension() != 3)
251  continue;
252  ids.emplace_back(id);
253  }
254 }
255 
257  const std::vector<std::vector<double>> &crds,
258  const std::vector<std::vector<vtkIdType>> &conns, std::vector<nemId_t> &ids,
259  bool query3Donly, double tol) const {
260  // create vtkPolyData using crds and conns
261  vtkSmartPointer<vtkPoints> pnts = vtkSmartPointer<vtkPoints>::New();
262  vtkSmartPointer<vtkCellArray> polys = vtkSmartPointer<vtkCellArray>::New();
263  vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
264 
265  for (const auto &crd : crds) pnts->InsertNextPoint(crd.data());
266  for (const auto &conn : conns)
267  polys->InsertNextCell(conn.size(), conn.data());
268  polyData->SetPoints(pnts);
269  polyData->SetPolys(polys);
270 
271  // DEBUG: Write polyData to STL
272  // vtkSmartPointer<vtkSTLWriter> stlw = vtkSmartPointer<vtkSTLWriter>::New();
273  // stlw->SetInputData(polyData);
274  // stlw->SetFileName("polydata.stl");
275  // stlw->Write();
276 
277  FindCellsInPolyData(polyData, ids, query3Donly, tol);
278 }
279 
280 void meshSrch::FindCellsInSphere(const std::vector<double> &center,
281  double radius, std::vector<nemId_t> &ids,
282  bool query3Donly, double tol) const {
283  // create vtkSphere using center and radius
284  vtkSmartPointer<vtkSphereSource> ss = vtkSmartPointer<vtkSphereSource>::New();
285  ss->SetRadius(radius);
286  ss->SetCenter(center[0], center[1], center[2]);
287 
288  ss->Update();
289 
290  FindCellsInPolyData(ss->GetOutput(), ids, query3Donly, tol);
291 }
std::vector< std::vector< double > > getCellVec(nemId_t id) const override
get vector of coords of cell with id
Definition: meshSrch.C:56
vtkSmartPointer< vtkDataSet > dataSet
mesh points, topology and data
Definition: meshBase.H:722
std::size_t nemId_t
Definition: meshBase.H:51
bool upd_vcl
Definition: meshSrch.H:138
geoMeshBase * New(MeshType meshType)
Create a new mesh object.
bool chkDuplElm() const
Definition: meshSrch.C:212
nemId_t numCells
number of cells in mesh
Definition: meshBase.H:718
void FindCellsInTriSrf(const std::vector< std::vector< double >> &crds, const std::vector< std::vector< vtkIdType >> &conns, std::vector< nemId_t > &ids, bool query3Donly=true, double tol=0.1e-15) const
Definition: meshSrch.C:256
nemId_t getNumberOfPoints() const
return the number of points
Definition: meshBase.H:545
vtkIdType id
id in .inp file
Definition: inpGeoMesh.C:128
void FindPntsOnTriSrf(const std::vector< double > &crds, const std::vector< nemId_t > &conn, std::set< nemId_t > &ids, double tol=0.1e-15) const
Definition: meshSrch.C:119
void buildCellLocator()
Definition: meshSrch.C:83
void FindCellsInPolyData(vtkPolyData *polyData, std::vector< nemId_t > &ids, bool query3Donly=true, double tol=0.1e-15) const
Definition: meshSrch.C:227
void FindCellsWithinBounds(std::vector< double > &bb, std::vector< nemId_t > &ids, bool fulImrsd=true)
Definition: meshSrch.C:93
vtkSmartPointer< vtkCellLocator > vcl
Definition: meshSrch.H:139
std::vector< double > getCellCenter(nemId_t cellID) const override
get center of a cell
Definition: meshSrch.C:75
bool isInBBox(const std::vector< T > &crd, const std::vector< T > &bb)
void FindCellsInSphere(const std::vector< double > &center, double radius, std::vector< nemId_t > &ids, bool query3Donly=true, double tol=0.1e-15) const
Definition: meshSrch.C:280
void FindPntsOnEdge(std::vector< double > &crds, std::set< nemId_t > &ids, double tol=0.1e-15) const
Definition: meshSrch.C:167
nemId_t getNumberOfCells() const
return the number of cells
Definition: meshBase.H:550
std::vector< double > getPoint(nemId_t id) const override
get point with id
Definition: meshSrch.C:48