ViennaLS
Loading...
Searching...
No Matches
lsToMultiSurfaceMesh.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <lsMaterialMap.hpp>
4#include <lsToSurfaceMesh.hpp>
5
6namespace viennals {
7
8using namespace viennacore;
9
10template <class NumericType, int D>
11class ToMultiSurfaceMesh : public ToSurfaceMesh<NumericType, D> {
12 using lsDomainType = viennals::Domain<NumericType, D>;
13 using hrleDomainType = typename lsDomainType::DomainType;
14 using hrleIndex = viennahrle::Index<D>;
15
29
30 SmartPointer<MaterialMap> materialMap = nullptr;
31
32 // Structure to track sharp corner nodes from each material
33 struct SharpCornerNode {
34 unsigned nodeId;
35 Vec3D<NumericType> position;
36 };
37
38 // Find the closest sharp corner node from materials below l.
39 // Returns the node ID or -1 if none found within threshold.
40 static int findNearestLowerCorner(
41 unsigned l, const Vec3D<NumericType> &pos,
42 const std::unordered_map<unsigned, std::vector<SharpCornerNode>>
43 &sharpCornerNodes) {
44 int snapId = -1;
45 NumericType minDist2 = 0.1;
46 for (unsigned m = 0; m < l; ++m) {
47 auto it = sharpCornerNodes.find(m);
48 if (it == sharpCornerNodes.end())
49 continue;
50 for (const auto &scn : it->second) {
51 NumericType dist2 = 0;
52 for (int i = 0; i < D; ++i) {
53 NumericType d = scn.position[i] - pos[i];
54 dist2 += d * d;
55 }
56 if (dist2 < minDist2) {
57 minDist2 = dist2;
58 snapId = scn.nodeId;
59 }
60 }
61 }
62 return snapId;
63 }
64
65 // In 2D, check if cornerPos lies on any edge of a previous material's mesh.
66 // If so, split that edge to include cornerNodeId.
67 void splitPreviousMaterialEdge(unsigned l, unsigned cornerNodeId,
68 const Vec3D<NumericType> &cornerPos,
69 size_t meshSizeBefore) {
70 if constexpr (D != 2)
71 return;
72 if (l == 0)
73 return;
74
75 for (size_t lineIdx = 0; lineIdx < mesh->lines.size(); ++lineIdx) {
76 unsigned mat = currentMaterials[lineIdx];
77 if (mat >= l)
78 continue;
79
80 auto &line = mesh->lines[lineIdx];
81 unsigned node0 = line[0];
82 unsigned node1 = line[1];
83
84 auto const &pos0 = mesh->nodes[node0];
85 auto const &pos1 = mesh->nodes[node1];
86 auto lineVec = pos1 - pos0;
87
88 NumericType lineLen2 = 0;
89 NumericType dot = 0;
90 for (int i = 0; i < D; ++i) {
91 lineLen2 += lineVec[i] * lineVec[i];
92 dot += (cornerPos[i] - pos0[i]) * lineVec[i];
93 }
94
95 if (lineLen2 < epsilon)
96 continue;
97
98 NumericType t = dot / lineLen2;
99 if (t <= 0 || t >= 1)
100 continue;
101
102 // Distance from corner to closest point on line
103 NumericType dist2 = 0;
104 for (int i = 0; i < D; ++i) {
105 NumericType d = cornerPos[i] - (pos0[i] + t * lineVec[i]);
106 dist2 += d * d;
107 }
108 if (dist2 >= 0.01)
109 continue;
110
111 // Corner is on this edge - find which recent lines already cover
112 // the split segments
113 auto reassignSegment = [&](int idx, unsigned a, unsigned b) {
114 currentMaterials[idx] = mat;
115 mesh->lines[idx] = {a, b};
116 currentNormals[idx] = currentNormals[lineIdx];
117 };
118
119 int seg1Idx = -1;
120 int seg2Idx = -1;
121 for (size_t k = meshSizeBefore; k < mesh->lines.size(); ++k) {
122 const auto &rl = mesh->lines[k];
123 if ((rl[0] == node0 && rl[1] == cornerNodeId) ||
124 (rl[0] == cornerNodeId && rl[1] == node0))
125 seg1Idx = k;
126 if ((rl[0] == cornerNodeId && rl[1] == node1) ||
127 (rl[0] == node1 && rl[1] == cornerNodeId))
128 seg2Idx = k;
129 }
130
131 if (seg1Idx != -1 && seg2Idx != -1) {
132 reassignSegment(seg1Idx, node0, cornerNodeId);
133 reassignSegment(seg2Idx, cornerNodeId, node1);
134 mesh->lines.erase(mesh->lines.begin() + lineIdx);
135 currentMaterials.erase(currentMaterials.begin() + lineIdx);
136 currentNormals.erase(currentNormals.begin() + lineIdx);
137 } else if (seg1Idx != -1) {
138 reassignSegment(seg1Idx, node0, cornerNodeId);
139 line[0] = cornerNodeId;
140 line[1] = node1;
141 } else if (seg2Idx != -1) {
142 reassignSegment(seg2Idx, cornerNodeId, node1);
143 line[1] = cornerNodeId;
144 } else {
145 line[1] = cornerNodeId;
146 mesh->lines.push_back({cornerNodeId, node1});
147 currentMaterials.push_back(mat);
148 currentNormals.push_back(currentNormals[lineIdx]);
149 }
150
151 break; // Corner can only be on one edge
152 }
153 }
154
155 // Handle snapping/splitting of sharp corners between materials.
156 void
157 snapSharpCorners(unsigned l, size_t meshSizeBefore,
158 std::unordered_map<unsigned, std::vector<SharpCornerNode>>
159 &sharpCornerNodes) {
160 for (const auto &cornerPair : matSharpCornerNodes) {
161 unsigned cornerNodeId = cornerPair.first;
162 Vec3D<NumericType> cornerPos = cornerPair.second;
163
164 int snapToNodeId =
165 (l > 0) ? findNearestLowerCorner(l, cornerPos, sharpCornerNodes) : -1;
166
167 if (snapToNodeId >= 0) {
168 // Snap: replace cornerNodeId with snapToNodeId in recent elements
169 if constexpr (D == 2) {
170 using I3 = typename ToSurfaceMesh<NumericType, D>::I3;
171 for (size_t i = mesh->lines.size(); i-- > meshSizeBefore;) {
172 for (int j = 0; j < 2; ++j) {
173 if (mesh->lines[i][j] == cornerNodeId)
174 mesh->lines[i][j] = snapToNodeId;
175 }
176
177 unsigned n0 = mesh->lines[i][0];
178 unsigned n1 = mesh->lines[i][1];
179 bool isDuplicate = uniqueElements.count({(int)n0, (int)n1, 0}) ||
180 uniqueElements.count({(int)n1, (int)n0, 0});
181
182 if (n0 == n1 || isDuplicate) {
183 mesh->lines.erase(mesh->lines.begin() + i);
184 currentMaterials.erase(currentMaterials.begin() + i);
185 currentNormals.erase(currentNormals.begin() + i);
186 } else {
187 uniqueElements.insert({(int)n0, (int)n1, 0});
188 }
189 }
190 }
191 sharpCornerNodes[l].push_back(
192 {static_cast<unsigned>(snapToNodeId), cornerPos});
193 } else {
194 // No snap - keep new corner and split any overlapping edge
195 sharpCornerNodes[l].push_back({cornerNodeId, cornerPos});
196 splitPreviousMaterialEdge(l, cornerNodeId, cornerPos, meshSizeBefore);
197 }
198 }
199 }
200
201public:
202 ToMultiSurfaceMesh(double minNodeDistFactor = 0.05, double eps = 1e-12)
203 : ToSurfaceMesh<NumericType, D>(minNodeDistFactor, eps) {}
204
205 ToMultiSurfaceMesh(SmartPointer<lsDomainType> passedLevelSet,
206 SmartPointer<viennals::Mesh<NumericType>> passedMesh,
207 double minNodeDistFactor = 0.05, double eps = 1e-12)
208 : ToSurfaceMesh<NumericType, D>(passedLevelSet, passedMesh,
209 minNodeDistFactor, eps) {}
210
212 std::vector<SmartPointer<lsDomainType>> const &passedLevelSets,
213 SmartPointer<viennals::Mesh<NumericType>> passedMesh,
214 double minNodeDistFactor = 0.05, double eps = 1e-12)
215 : ToSurfaceMesh<NumericType, D>(minNodeDistFactor, eps) {
216 levelSets = passedLevelSets;
217 mesh = passedMesh;
218 }
219
221 double minNodeDistFactor = 0.05, double eps = 1e-12)
222 : ToSurfaceMesh<NumericType, D>(minNodeDistFactor, eps) {
223 mesh = passedMesh;
224 }
225
226 void insertNextLevelSet(SmartPointer<lsDomainType> passedLevelSet) {
227 levelSets.push_back(passedLevelSet);
228 }
229
230 void clearLevelSets() { levelSets.clear(); }
231
232 void setMaterialMap(SmartPointer<MaterialMap> passedMaterialMap) {
233 materialMap = passedMaterialMap;
234 }
235
236 void apply() override {
237 if (levelSets.empty()) {
238 Logger::getInstance()
239 .addError("No level set was passed to ToMultiSurfaceMesh.")
240 .print();
241 return;
242 }
243 if (mesh == nullptr) {
244 Logger::getInstance()
245 .addError("No mesh was passed to ToMultiSurfaceMesh.")
246 .print();
247 return;
248 }
249
250 mesh->clear();
251 currentGridDelta = levelSets.front()->getGrid().getGridDelta();
252 for (unsigned i = 0; i < D; ++i) {
253 mesh->minimumExtent[i] = std::numeric_limits<NumericType>::max();
254 mesh->maximumExtent[i] = std::numeric_limits<NumericType>::lowest();
255 }
256
257 using nodeContainerType = std::map<viennahrle::Index<D>, unsigned>;
258
259 nodeContainerType nodes[D];
260 nodeContainerType faceNodes[D];
261 nodeContainerType cornerNodes;
262
263 nodeIdByBin.clear();
264 uniqueElements.clear();
265 currentNormals.clear();
266 currentMaterials.clear();
267
268 const bool useMaterialMap = materialMap != nullptr;
269 const bool sharpCorners = generateSharpCorners;
270
271 if (sharpCorners && D == 3) {
272 Logger::getInstance()
273 .addWarning("Sharp corner generation in 3D is experimental and may "
274 "produce suboptimal meshes. Use with caution.")
275 .print();
276 }
277
278 // an iterator for each level set
279 std::vector<viennahrle::ConstSparseCellIterator<hrleDomainType>> cellIts;
280 for (const auto &ls : levelSets)
281 cellIts.emplace_back(ls->getDomain());
282
283 // Explicit storage for sharp corner nodes, keyed by material index
284 std::unordered_map<unsigned, std::vector<SharpCornerNode>> sharpCornerNodes;
285
286 for (unsigned l = 0; l < levelSets.size(); l++) {
288 if (useMaterialMap) {
289 currentMaterialId = materialMap->getMaterialId(l);
290 } else {
291 currentMaterialId = static_cast<unsigned>(l);
292 }
293
294 normalVectorData = nullptr;
295 if (sharpCorners) {
298 normalCalculator.setMethod(
300 normalCalculator.setMaxValue(std::numeric_limits<NumericType>::max());
301 normalCalculator.apply();
302 normalVectorData = currentLevelSet->getPointData().getVectorData(
304 }
305
306 viennahrle::ConstSparseIterator<hrleDomainType> valueIt(
307 currentLevelSet->getDomain());
308
309 // iterate over all active surface points
310 for (auto cellIt = cellIts[l]; !cellIt.isFinished(); cellIt.next()) {
311 for (int u = 0; u < D; u++) {
312 while (!nodes[u].empty() &&
313 nodes[u].begin()->first <
314 viennahrle::Index<D>(cellIt.getIndices()))
315 nodes[u].erase(nodes[u].begin());
316
317 if constexpr (D == 3) {
318 while (!faceNodes[u].empty() &&
319 faceNodes[u].begin()->first <
320 viennahrle::Index<D>(cellIt.getIndices()))
321 faceNodes[u].erase(faceNodes[u].begin());
322
323 if (u == 0) {
324 while (!cornerNodes.empty() &&
325 cornerNodes.begin()->first <
326 viennahrle::Index<D>(cellIt.getIndices()))
327 cornerNodes.erase(cornerNodes.begin());
328 }
329 }
330 }
331
332 unsigned signs = 0;
333 for (int i = 0; i < (1 << D); i++) {
334 if (cellIt.getCorner(i).getValue() >= NumericType(0))
335 signs |= (1 << i);
336 }
337
338 // all corners have the same sign, so no surface here
339 if (signs == 0)
340 continue;
341 if (signs == (1 << (1 << D)) - 1)
342 continue;
343
344 // Check if this cell is at a material boundary with the immediate
345 // material below
346 bool atMaterialBoundary = false;
347 unsigned touchingMaterial = 0; // Which material we're touching
348 if (sharpCorners && l > 0) {
349 touchingMaterial = l - 1;
350 viennahrle::ConstSparseIterator<hrleDomainType> prevIt(
351 levelSets[touchingMaterial]->getDomain());
352 for (int i = 0; i < (1 << D); ++i) {
353 hrleIndex cornerIdx =
354 cellIt.getIndices() + viennahrle::BitMaskToIndex<D>(i);
355 prevIt.goToIndices(cornerIdx);
356 if (prevIt.getValue() <= 0) { // Inside previous material
357 atMaterialBoundary = true;
358 break;
359 }
360 }
361 }
362
363 // Attempt to generate sharp features if enabled
364 bool perfectCornerFound = false;
365 if (sharpCorners) {
366 int countNeg = 0;
367 int countPos = 0;
368 int negMask = 0;
369 int posMask = 0;
370 for (int i = 0; i < (1 << D); ++i) {
371 NumericType val = cellIt.getCorner(i).getValue();
372 if (val < -epsilon) {
373 countNeg++;
374 negMask |= (1 << i);
375 } else if (val > epsilon) {
376 countPos++;
377 posMask |= (1 << i);
378 } else {
379 if (val >= 0) {
380 countPos++;
381 posMask |= (1 << i);
382 } else {
383 countNeg++;
384 negMask |= (1 << i);
385 }
386 }
387 }
388
389 // Clear the base class's recent corner nodes before generation
390 matSharpCornerNodes.clear();
391
392 // Track mesh size before generating sharp corners
393 size_t meshSizeBefore = 0;
394 if constexpr (D == 2) {
395 meshSizeBefore = mesh->lines.size();
396 perfectCornerFound =
397 this->generateSharpCorner2D(cellIt, countNeg, countPos, negMask,
398 posMask, nodes, nullptr, valueIt);
399 } else if constexpr (D == 3) {
400 if (countNeg == 2 || countPos == 2) {
401 perfectCornerFound = this->generateSharpEdge3D(
402 cellIt, countNeg, countPos, negMask, posMask, nodes,
403 faceNodes, nullptr, valueIt);
404 } else if (countNeg == 1 || countPos == 1) {
405 perfectCornerFound = this->generateSharpCorner3D(
406 cellIt, countNeg, countPos, negMask, posMask, nodes,
407 cornerNodes, faceNodes, nullptr, valueIt);
408 } else if (countNeg == 3 || countPos == 3) {
409 perfectCornerFound = this->generateSharpL3D(
410 cellIt, countNeg, countPos, negMask, posMask, nodes,
411 faceNodes, nullptr, valueIt);
412 }
413 }
414
415 // If sharp corners were generated, check if they should snap to
416 // existing corners or split edges of previous materials
417 if (D == 2 && perfectCornerFound && !matSharpCornerNodes.empty()) {
418 snapSharpCorners(l, meshSizeBefore, sharpCornerNodes);
419 }
420 }
421
422 if (perfectCornerFound)
423 continue;
424
425 if constexpr (D == 3) {
426 // Stitch to perfect corners/edges
427 for (int axis = 0; axis < 3; ++axis) {
428 for (int d = 0; d < 2; ++d) {
429 viennahrle::Index<D> faceKey(cellIt.getIndices());
430 if (d == 1)
431 faceKey[axis]++;
432
433 auto it = faceNodes[axis].find(faceKey);
434 if (it != faceNodes[axis].end()) {
435 const unsigned faceNodeId = it->second;
436 const int *Triangles =
438
439 for (; Triangles[0] != -1; Triangles += 3) {
440 std::vector<unsigned> face_edge_nodes;
441 for (int i = 0; i < 3; ++i) {
442 int edge = Triangles[i];
443 int c0 = this->corner0[edge];
444 int c1 = this->corner1[edge];
445 bool onFace =
446 (((c0 >> axis) & 1) == d) && (((c1 >> axis) & 1) == d);
447 if (onFace) {
448 face_edge_nodes.push_back(
449 this->getNode(cellIt, edge, nodes, nullptr));
450 }
451 }
452 if (face_edge_nodes.size() == 2) {
453 this->insertElement(std::array<unsigned, 3>{
454 face_edge_nodes[0], face_edge_nodes[1], faceNodeId});
455 }
456 }
457 }
458 }
459 }
460 }
461
462 // for each element
463 const int *Triangles;
464 if constexpr (D == 2) {
466 } else {
468 }
469
470 for (; Triangles[0] != -1; Triangles += D) {
471 std::array<unsigned, D> nodeNumbers;
472
473 // for each node
474 for (int n = 0; n < D; n++) {
475 const int edge = Triangles[n];
476
477 unsigned p0 = this->corner0[edge];
478
479 // determine direction of edge
480 unsigned dir = this->direction[edge];
481
482 // look for existing surface node
483 viennahrle::Index<D> d(cellIt.getIndices());
484 auto p0B = viennahrle::BitMaskToIndex<D>(p0);
485 d += p0B;
486
487 auto nodeIt = nodes[dir].find(d);
488 if (nodeIt != nodes[dir].end()) {
489 nodeNumbers[n] = nodeIt->second;
490
491 // Check if this cached node is a sharp corner that should be
492 // inherited
493 if (sharpCorners && l > 0 && atMaterialBoundary) {
494 unsigned cachedNodeId = nodeIt->second;
495 // Check if this is a corner from the material below
496 auto it = sharpCornerNodes.find(touchingMaterial);
497 if (it != sharpCornerNodes.end()) {
498 for (const auto &scn : it->second) {
499 if (scn.nodeId == cachedNodeId) {
500 // Only inherit if not already inherited
501 auto &lCorners = sharpCornerNodes[l];
502 bool alreadyInherited = false;
503 for (const auto &existing : lCorners) {
504 if (existing.nodeId == cachedNodeId) {
505 alreadyInherited = true;
506 break;
507 }
508 }
509 if (!alreadyInherited)
510 lCorners.push_back({cachedNodeId, scn.position});
511 break;
512 }
513 }
514 }
515 }
516 } else {
517 // Node does not exist yet - try snapping to a sharp corner
518 // from the touching material at material boundaries
519 int snapNodeId = -1;
520 Vec3D<NumericType> snapPos{};
521 if (sharpCorners && l > 0 && atMaterialBoundary) {
522 auto tmIt = sharpCornerNodes.find(touchingMaterial);
523 if (tmIt != sharpCornerNodes.end() && !tmIt->second.empty()) {
524 Vec3D<NumericType> nodePos =
525 this->computeNodePosition(cellIt, edge);
526
527 NumericType minDist2 = 0.1; // Threshold: 0.5 grid spacings
528 for (const auto &scn : tmIt->second) {
529 NumericType dist2 = 0;
530 for (int i = 0; i < D; ++i) {
531 NumericType dd = scn.position[i] - nodePos[i];
532 dist2 += dd * dd;
533 }
534 if (dist2 < minDist2) {
535 minDist2 = dist2;
536 snapNodeId = scn.nodeId;
537 snapPos = scn.position;
538 }
539 }
540 }
541 }
542
543 if (snapNodeId >= 0) {
544 nodeNumbers[n] = snapNodeId;
545 nodes[dir][d] = snapNodeId; // Cache it
546 // Inherit this corner so upper materials can find it
547 sharpCornerNodes[l].push_back(
548 {static_cast<unsigned>(snapNodeId), snapPos});
549 } else {
550 nodeNumbers[n] = this->getNode(cellIt, edge, nodes, nullptr);
551 }
552 }
553 }
554
555 // Check for duplicates before inserting (standard Marching Cubes)
556 bool isDuplicate = false;
557 if constexpr (D == 2) {
558 using I3 = typename ToSurfaceMesh<NumericType, D>::I3;
559 if (uniqueElements.find({(int)nodeNumbers[1], (int)nodeNumbers[0],
560 0}) != uniqueElements.end())
561 isDuplicate = true;
562 }
563
564 if (!isDuplicate) {
565 this->insertElement(nodeNumbers);
566 }
567 }
568 }
569 }
570
571 this->scaleMesh();
572
573 mesh->cellData.insertNextScalarData(currentMaterials, "MaterialIds");
574 mesh->cellData.insertNextVectorData(currentNormals, "Normals");
575 mesh->triangles.shrink_to_fit();
576 mesh->nodes.shrink_to_fit();
577 }
578};
579
580PRECOMPILE_PRECISION_DIMENSION(ToMultiSurfaceMesh)
581
582} // namespace viennals
float NumericType
Definition AirGapDeposition.cpp:24
constexpr int D
Definition Epitaxy.cpp:11
static const int * polygonize2d(unsigned int signs)
signs = signs of the corners in lexicographic order (1bit per corner)
Definition lsMarchingCubes.hpp:312
static const int * polygonize3d(unsigned int signs)
signs = signs of the corners in lexicographic order (1bit per corner)
Definition lsMarchingCubes.hpp:324
This algorithm is used to compute the normal vectors for all points with level set values <= maxValue...
Definition lsCalculateNormalVectors.hpp:40
static constexpr char normalVectorsLabel[]
Definition lsCalculateNormalVectors.hpp:52
void apply()
Definition lsCalculateNormalVectors.hpp:95
void setMethod(NormalCalculationMethodEnum passedMethod)
Definition lsCalculateNormalVectors.hpp:79
void setMaxValue(const T passedMaxValue)
Definition lsCalculateNormalVectors.hpp:67
Class containing all information about the level set, including the dimensions of the domain,...
Definition lsDomain.hpp:28
viennahrle::Domain< NumericType, D > DomainType
Definition lsDomain.hpp:33
This class holds an explicit mesh, which is always given in 3 dimensions. If it describes a 2D mesh,...
Definition lsMesh.hpp:22
ToMultiSurfaceMesh(SmartPointer< lsDomainType > passedLevelSet, SmartPointer< viennals::Mesh< NumericType > > passedMesh, double minNodeDistFactor=0.05, double eps=1e-12)
Definition lsToMultiSurfaceMesh.hpp:205
ToMultiSurfaceMesh(SmartPointer< viennals::Mesh< NumericType > > passedMesh, double minNodeDistFactor=0.05, double eps=1e-12)
Definition lsToMultiSurfaceMesh.hpp:220
ToMultiSurfaceMesh(double minNodeDistFactor=0.05, double eps=1e-12)
Definition lsToMultiSurfaceMesh.hpp:202
void apply() override
Definition lsToMultiSurfaceMesh.hpp:236
ToMultiSurfaceMesh(std::vector< SmartPointer< lsDomainType > > const &passedLevelSets, SmartPointer< viennals::Mesh< NumericType > > passedMesh, double minNodeDistFactor=0.05, double eps=1e-12)
Definition lsToMultiSurfaceMesh.hpp:211
void setMaterialMap(SmartPointer< MaterialMap > passedMaterialMap)
Definition lsToMultiSurfaceMesh.hpp:232
void clearLevelSets()
Definition lsToMultiSurfaceMesh.hpp:230
void insertNextLevelSet(SmartPointer< lsDomainType > passedLevelSet)
Definition lsToMultiSurfaceMesh.hpp:226
SmartPointer< Mesh< NumericType > > mesh
Definition lsToSurfaceMesh.hpp:33
static constexpr unsigned int direction[12]
Definition lsToSurfaceMesh.hpp:77
bool generateSharpEdge3D(viennahrle::ConstSparseCellIterator< hrleDomainType > &cellIt, int countNeg, int countPos, int negMask, int posMask, std::map< hrleIndex, unsigned > *nodes, std::map< hrleIndex, unsigned > *faceNodes, std::vector< unsigned > *newDataSourceIds, ConstSparseIterator &valueIt)
Definition lsToSurfaceMesh.hpp:1209
SmartPointer< lsDomainType > currentLevelSet
Definition lsToSurfaceMesh.hpp:67
bool generateSharpCorner2D(viennahrle::ConstSparseCellIterator< hrleDomainType > &cellIt, int countNeg, int countPos, int negMask, int posMask, std::map< hrleIndex, unsigned > *nodes, std::vector< unsigned > *newDataSourceIds, ConstSparseIterator &valueIt)
Definition lsToSurfaceMesh.hpp:552
bool generateSharpCorners
Definition lsToSurfaceMesh.hpp:38
std::vector< SmartPointer< lsDomainType > > levelSets
Definition lsToSurfaceMesh.hpp:32
std::unordered_map< I3, unsigned, I3Hash > nodeIdByBin
Definition lsToSurfaceMesh.hpp:61
const NumericType epsilon
Definition lsToSurfaceMesh.hpp:35
Vec3D< NumericType > computeNodePosition(viennahrle::ConstSparseCellIterator< hrleDomainType > &cellIt, int edge)
Definition lsToSurfaceMesh.hpp:356
bool generateSharpCorner3D(viennahrle::ConstSparseCellIterator< hrleDomainType > &cellIt, int countNeg, int countPos, int negMask, int posMask, std::map< hrleIndex, unsigned > *nodes, std::map< hrleIndex, unsigned > &cornerNodes, std::map< hrleIndex, unsigned > *faceNodes, std::vector< unsigned > *newDataSourceIds, ConstSparseIterator &valueIt)
Definition lsToSurfaceMesh.hpp:1374
std::unordered_set< I3, I3Hash > uniqueElements
Definition lsToSurfaceMesh.hpp:62
std::vector< std::pair< unsigned, Vec3D< NumericType > > > matSharpCornerNodes
Definition lsToSurfaceMesh.hpp:71
static constexpr unsigned int corner1[12]
Definition lsToSurfaceMesh.hpp:75
void insertElement(const std::array< unsigned, D > &nodeNumbers)
Definition lsToSurfaceMesh.hpp:1647
ToSurfaceMesh(double mnd=0.05, double eps=1e-12)
Definition lsToSurfaceMesh.hpp:81
double currentGridDelta
Definition lsToSurfaceMesh.hpp:65
bool generateSharpL3D(viennahrle::ConstSparseCellIterator< hrleDomainType > &cellIt, int countNeg, int countPos, int negMask, int posMask, std::map< hrleIndex, unsigned > *nodes, std::map< hrleIndex, unsigned > *faceNodes, std::vector< unsigned > *newDataSourceIds, ConstSparseIterator &valueIt)
Definition lsToSurfaceMesh.hpp:671
PointData< NumericType >::VectorDataType * normalVectorData
Definition lsToSurfaceMesh.hpp:68
std::vector< Vec3D< NumericType > > currentNormals
Definition lsToSurfaceMesh.hpp:63
void scaleMesh()
Definition lsToSurfaceMesh.hpp:342
std::vector< NumericType > currentMaterials
Definition lsToSurfaceMesh.hpp:64
NumericType currentMaterialId
Definition lsToSurfaceMesh.hpp:66
unsigned getNode(viennahrle::ConstSparseCellIterator< hrleDomainType > &cellIt, int edge, std::map< hrleIndex, unsigned > *nodes, std::vector< unsigned > *newDataSourceIds)
Definition lsToSurfaceMesh.hpp:386
static constexpr unsigned int corner0[12]
Definition lsToSurfaceMesh.hpp:73
#define PRECOMPILE_PRECISION_DIMENSION(className)
Definition lsPreCompileMacros.hpp:24
Definition lsAdvect.hpp:41
@ ONE_SIDED_MIN_MOD
Definition lsCalculateNormalVectors.hpp:22
Definition lsToSurfaceMesh.hpp:40