ViennaLS
Loading...
Searching...
No Matches
lsToVoxelMesh.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <unordered_map>
4
6
7#include <hrleDenseCellIterator.hpp>
8#include <lsDomain.hpp>
9#include <lsMaterialMap.hpp>
10#include <lsMesh.hpp>
11
12namespace viennals {
13
14using namespace viennacore;
15
20template <class T, int D> class ToVoxelMesh {
21 typedef typename Domain<T, D>::DomainType hrleDomainType;
22
23 std::vector<SmartPointer<Domain<T, D>>> levelSets;
24 SmartPointer<Mesh<T>> mesh = nullptr;
25 SmartPointer<MaterialMap> materialMap = nullptr;
26 hrleVectorType<hrleIndexType, D> minIndex, maxIndex;
27
28 void calculateBounds() {
29 // set to zero
30 for (unsigned i = 0; i < D; ++i) {
31 minIndex[i] = std::numeric_limits<hrleIndexType>::max();
32 maxIndex[i] = std::numeric_limits<hrleIndexType>::lowest();
33 }
34 for (unsigned l = 0; l < levelSets.size(); ++l) {
35 auto &grid = levelSets[l]->getGrid();
36 auto &domain = levelSets[l]->getDomain();
37 for (unsigned i = 0; i < D; ++i) {
38 minIndex[i] = std::min(minIndex[i], (grid.isNegBoundaryInfinite(i))
39 ? domain.getMinRunBreak(i)
40 : grid.getMinBounds(i));
41
42 maxIndex[i] = std::max(maxIndex[i], (grid.isPosBoundaryInfinite(i))
43 ? domain.getMaxRunBreak(i)
44 : grid.getMaxBounds(i));
45 }
46 }
47 }
48
49public:
51
52 ToVoxelMesh(SmartPointer<Mesh<T>> passedMesh) : mesh(passedMesh) {}
53
54 ToVoxelMesh(SmartPointer<Domain<T, D>> passedLevelSet,
55 SmartPointer<Mesh<T>> passedMesh)
56 : mesh(passedMesh) {
57 levelSets.push_back(passedLevelSet);
58 }
59
60 ToVoxelMesh(const std::vector<SmartPointer<Domain<T, D>>> passedLevelSets,
61 SmartPointer<Mesh<T>> passedMesh)
62 : mesh(passedMesh) {
63 levelSets = passedLevelSets;
64 }
65
70 void insertNextLevelSet(SmartPointer<Domain<T, D>> passedLevelSet) {
71 levelSets.push_back(passedLevelSet);
72 }
73
74 void setMesh(SmartPointer<Mesh<T>> passedMesh) { mesh = passedMesh; }
75
76 void setMaterialMap(SmartPointer<MaterialMap> passedMaterialMap) {
77 materialMap = passedMaterialMap;
78 }
79
80 void apply() {
81 if (levelSets.size() < 1) {
82 Logger::getInstance()
83 .addWarning("No Level Sets supplied to ToVoxelMesh! Not converting.")
84 .print();
85 }
86 if (mesh == nullptr) {
87 Logger::getInstance()
88 .addWarning("No mesh was passed to ToVoxelMesh.")
89 .print();
90 return;
91 }
92
93 mesh->clear();
94 auto &levelSet = *(levelSets.back());
95 auto &grid = levelSet.getGrid();
96
97 calculateBounds();
98
99 // save the extent of the resulting mesh
100 for (unsigned i = 0; i < D; ++i) {
101 mesh->minimumExtent[i] = std::numeric_limits<T>::max();
102 mesh->maximumExtent[i] = std::numeric_limits<T>::lowest();
103 }
104
105 std::unordered_map<hrleVectorType<hrleIndexType, D>, size_t,
106 typename hrleVectorType<hrleIndexType, D>::hash>
107 pointIdMapping;
108 size_t currentPointId = 0;
109
110 // prepare mesh for material ids
111 mesh->cellData.insertNextScalarData(typename PointData<T>::ScalarDataType(),
112 "Material");
113 auto &materialIds = *(mesh->cellData.getScalarData(0));
114 const bool useMaterialMap = materialMap != nullptr;
115
116 // set up iterators for all materials
117 std::vector<hrleConstDenseCellIterator<typename Domain<T, D>::DomainType>>
118 iterators;
119 for (auto it = levelSets.begin(); it != levelSets.end(); ++it) {
120 iterators.push_back(
121 hrleConstDenseCellIterator<typename Domain<T, D>::DomainType>(
122 (*it)->getDomain(), minIndex));
123 }
124
125 // move iterator for lowest material id and then adjust others if they are
126 // needed
127 unsigned counter = 0;
128 for (; iterators.front().getIndices() < maxIndex;
129 iterators.front().next()) {
130 // go over all materials
131 for (unsigned materialId = 0; materialId < levelSets.size();
132 ++materialId) {
133
134 auto &cellIt = iterators[materialId];
135
136 cellIt.goToIndicesSequential(iterators.front().getIndices());
137
138 // find out whether the centre of the box is inside
139 T centerValue = 0.;
140 for (int i = 0; i < (1 << D); ++i) {
141 centerValue += cellIt.getCorner(i).getValue();
142 }
143
144 if (centerValue <= 0.) {
145 std::array<unsigned, 1 << D> voxel;
146 bool addVoxel;
147 // now insert all points of voxel into pointList
148 for (unsigned i = 0; i < (1 << D); ++i) {
149 hrleVectorType<hrleIndexType, D> index;
150 addVoxel = true;
151 for (unsigned j = 0; j < D; ++j) {
152 index[j] =
153 cellIt.getIndices(j) + cellIt.getCorner(i).getOffset()[j];
154 if (index[j] > maxIndex[j]) {
155 addVoxel = false;
156 break;
157 }
158 }
159 if (addVoxel) {
160 auto pointIdValue = std::make_pair(index, currentPointId);
161 auto pointIdPair = pointIdMapping.insert(pointIdValue);
162 voxel[i] = pointIdPair.first->second;
163 if (pointIdPair.second) {
164 ++currentPointId;
165 }
166 } else {
167 break;
168 }
169 }
170
171 // create element if inside domain bounds
172 if (addVoxel) {
173 int material = materialId;
174 if (useMaterialMap)
175 material = materialMap->getMaterialId(materialId);
176
177 if constexpr (D == 3) {
178 // reorder elements for hexas to be ordered correctly
179 std::array<unsigned, 8> hexa{voxel[0], voxel[1], voxel[3],
180 voxel[2], voxel[4], voxel[5],
181 voxel[7], voxel[6]};
182 mesh->hexas.push_back(hexa);
183 materialIds.push_back(material);
184 } else {
185 std::array<unsigned, 4> tetra{voxel[0], voxel[2], voxel[3],
186 voxel[1]};
187 mesh->tetras.push_back(tetra);
188 materialIds.push_back(material);
189 }
190 }
191 // jump out of material for loop
192 break;
193 }
194 }
195 }
196
197 // now insert points
198 double gridDelta = grid.getGridDelta();
199 mesh->nodes.resize(pointIdMapping.size());
200 for (auto it = pointIdMapping.begin(); it != pointIdMapping.end(); ++it) {
201 std::array<T, 3> coords{};
202 for (unsigned i = 0; i < D; ++i) {
203 coords[i] = gridDelta * it->first[i];
204
205 // save extent
206 if (coords[i] < mesh->minimumExtent[i]) {
207 mesh->minimumExtent[i] = coords[i];
208 } else if (coords[i] > mesh->maximumExtent[i]) {
209 mesh->maximumExtent[i] = coords[i];
210 }
211 }
212 mesh->nodes[it->second] = coords;
213 }
214 }
215};
216
217// add all template specializations for this class
219
220} // namespace viennals
Class containing all information about the level set, including the dimensions of the domain,...
Definition lsDomain.hpp:28
hrleDomain< T, 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:21
std::vector< T > ScalarDataType
Definition lsPointData.hpp:22
Creates a mesh, which consists only of quads/hexas for completely filled grid cells in the level set....
Definition lsToVoxelMesh.hpp:20
void setMesh(SmartPointer< Mesh< T > > passedMesh)
Definition lsToVoxelMesh.hpp:74
ToVoxelMesh(SmartPointer< Mesh< T > > passedMesh)
Definition lsToVoxelMesh.hpp:52
void setMaterialMap(SmartPointer< MaterialMap > passedMaterialMap)
Definition lsToVoxelMesh.hpp:76
ToVoxelMesh()
Definition lsToVoxelMesh.hpp:50
ToVoxelMesh(SmartPointer< Domain< T, D > > passedLevelSet, SmartPointer< Mesh< T > > passedMesh)
Definition lsToVoxelMesh.hpp:54
void insertNextLevelSet(SmartPointer< Domain< T, D > > passedLevelSet)
Push level set to the list of level sets used for output. If more than one are specified,...
Definition lsToVoxelMesh.hpp:70
ToVoxelMesh(const std::vector< SmartPointer< Domain< T, D > > > passedLevelSets, SmartPointer< Mesh< T > > passedMesh)
Definition lsToVoxelMesh.hpp:60
void apply()
Definition lsToVoxelMesh.hpp:80
#define PRECOMPILE_PRECISION_DIMENSION(className)
Definition lsPreCompileMacros.hpp:24
Definition lsAdvect.hpp:46
constexpr int D
Definition pyWrap.cpp:65
double T
Definition pyWrap.cpp:63