ViennaLS
Loading...
Searching...
No Matches
lsToDiskMesh.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <hrleSparseIterator.hpp>
6
8#include <lsDomain.hpp>
9#include <lsExpand.hpp>
10#include <lsMaterialMap.hpp>
11#include <lsMesh.hpp>
12#include <unordered_map>
13
14namespace viennals {
15
16using namespace viennacore;
17
24template <class T, int D, class N = T> class ToDiskMesh {
25 typedef typename Domain<T, D>::DomainType hrleDomainType;
26
27public:
28 using TranslatorType = std::unordered_map<unsigned long, unsigned long>;
29
30private:
31 std::vector<SmartPointer<Domain<T, D>>> levelSets;
32 SmartPointer<Mesh<N>> mesh = nullptr;
33 SmartPointer<TranslatorType> translator = nullptr;
34 SmartPointer<MaterialMap> materialMap = nullptr;
35 T maxValue = 0.5;
36 bool buildTranslator = false;
37 static constexpr double wrappingLayerEpsilon = 1e-4;
38
39public:
41
42 ToDiskMesh(SmartPointer<Mesh<N>> passedMesh, T passedMaxValue = 0.5)
43 : mesh(passedMesh), maxValue(passedMaxValue) {}
44
45 ToDiskMesh(SmartPointer<Domain<T, D>> passedLevelSet,
46 SmartPointer<Mesh<N>> passedMesh, T passedMaxValue = 0.5)
47 : mesh(passedMesh), maxValue(passedMaxValue) {
48 levelSets.push_back(passedLevelSet);
49 }
50
51 ToDiskMesh(SmartPointer<Domain<T, D>> passedLevelSet,
52 SmartPointer<Mesh<N>> passedMesh,
53 SmartPointer<TranslatorType> passedTranslator,
54 T passedMaxValue = 0.5)
55 : mesh(passedMesh), translator(passedTranslator),
56 maxValue(passedMaxValue) {
57 levelSets.push_back(passedLevelSet);
58 buildTranslator = true;
59 }
60
61 void setLevelSet(SmartPointer<Domain<T, D>> passedLevelSet) {
62 levelSets.push_back(passedLevelSet);
63 }
64
66 void insertNextLevelSet(SmartPointer<Domain<T, D>> passedLevelSet) {
67 levelSets.push_back(passedLevelSet);
68 }
69
70 void setMesh(SmartPointer<Mesh<N>> passedMesh) { mesh = passedMesh; }
71
72 void setTranslator(SmartPointer<TranslatorType> passedTranslator) {
73 translator = passedTranslator;
74 buildTranslator = true;
75 }
76
77 void setMaterialMap(SmartPointer<MaterialMap> passedMaterialMap) {
78 materialMap = passedMaterialMap;
79 }
80
81 void setMaxValue(const T passedMaxValue) { maxValue = passedMaxValue; }
82
83 void apply() {
84 if (levelSets.size() < 1) {
85 Logger::getInstance()
86 .addWarning("No level sets passed to ToDiskMesh.")
87 .print();
88 return;
89 }
90 if (mesh == nullptr) {
91 Logger::getInstance()
92 .addWarning("No mesh was passed to ToDiskMesh.")
93 .print();
94 return;
95 }
96 if (buildTranslator && translator == nullptr) {
97 Logger::getInstance()
98 .addWarning("No translator was passed to ToDiskMesh.")
99 .print();
100 }
101
102 mesh->clear();
103
104 // expand top levelset
105 Expand<T, D>(levelSets.back(), (maxValue * 4) + 1).apply();
106 CalculateNormalVectors<T, D>(levelSets.back(), maxValue).apply();
107
108 const T gridDelta = levelSets.back()->getGrid().getGridDelta();
109 const auto &normalVectors =
110 *(levelSets.back()->getPointData().getVectorData(
112
113 // set up data arrays
114 std::vector<N> values;
115 std::vector<std::array<N, 3>> normals;
116 std::vector<N> materialIds;
117
118 // save the extent of the resulting mesh
119 std::array<N, 3> minimumExtent = {};
120 std::array<N, 3> maximumExtent = {};
121 for (unsigned i = 0; i < D; ++i) {
122 minimumExtent[i] = std::numeric_limits<T>::max();
123 maximumExtent[i] = std::numeric_limits<T>::lowest();
124 }
125
126 values.reserve(normalVectors.size());
127 normals.reserve(normalVectors.size());
128 materialIds.reserve(normalVectors.size());
129
130 const bool useMaterialMap = materialMap != nullptr;
131 const bool buildTranslatorFlag = buildTranslator;
132 unsigned long counter = 0;
133 if (buildTranslatorFlag) {
134 translator->clear();
135 translator->reserve(normalVectors.size());
136 }
137
138 // an iterator for each levelset
139 std::vector<hrleConstSparseIterator<hrleDomainType>> iterators;
140 for (const auto levelSet : levelSets) {
141 iterators.push_back(
142 hrleConstSparseIterator<hrleDomainType>(levelSet->getDomain()));
143 }
144
145 // iterate over top levelset
146 for (auto &topIt = iterators.back(); !topIt.isFinished(); ++topIt) {
147 if (!topIt.isDefined() || std::abs(topIt.getValue()) > maxValue) {
148 continue;
149 }
150
151 unsigned pointId = topIt.getPointId();
152
153 // insert pointId-counter pair in translator
154 if (buildTranslatorFlag) {
155 translator->insert({pointId, counter++});
156 }
157
158 // insert material ID
159 const T value = topIt.getValue();
160 int matId = levelSets.size() - 1;
161 for (int lowerLevelSetId = 0; lowerLevelSetId < levelSets.size() - 1;
162 ++lowerLevelSetId) {
163 // check if there is any other levelset at the same point:
164 // put iterator to same position as the top levelset
165 iterators[lowerLevelSetId].goToIndicesSequential(
166 topIt.getStartIndices());
167 if (iterators[lowerLevelSetId].getValue() <=
168 value + wrappingLayerEpsilon) {
169 matId = lowerLevelSetId;
170 break;
171 }
172 }
173 if (useMaterialMap)
174 matId = materialMap->getMaterialId(matId);
175
176 materialIds.push_back(matId);
177
178 // insert vertex
179 std::array<unsigned, 1> vertex;
180 vertex[0] = mesh->nodes.size();
181 mesh->insertNextVertex(vertex);
182
183 // insert corresponding node shifted by ls value in direction of the
184 // normal vector
185 std::array<N, 3> node;
186 node[2] = 0.;
187 double max = 0.;
188 for (unsigned i = 0; i < D; ++i) {
189 // original position
190 node[i] = double(topIt.getStartIndices(i)) * gridDelta;
191
192 // save extent
193 if (node[i] < minimumExtent[i]) {
194 minimumExtent[i] = node[i];
195 } else if (node[i] > maximumExtent[i]) {
196 maximumExtent[i] = node[i];
197 }
198
199 if (std::abs(normalVectors[pointId][i]) > max) {
200 max = std::abs(normalVectors[pointId][i]);
201 }
202 }
203
204 // now normalize vector to scale position correctly to manhatten distance
205 double scaling = value * gridDelta * max;
206 for (unsigned i = 0; i < D; ++i) {
207 node[i] -= scaling * normalVectors[pointId][i];
208 }
209
210 mesh->insertNextNode(node);
211
212 // add data into mesh
213 // copy normal
214 std::array<N, 3> normal;
215 if (D == 2)
216 normal[2] = 0.;
217 for (unsigned i = 0; i < D; ++i) {
218 normal[i] = normalVectors[pointId][i];
219 }
220
221 normals.push_back(normal);
222 values.push_back(value);
223 }
224
225 // delete normal vectors point data again as it is not needed anymore
226 {
227 auto &pointData = levelSets.back()->getPointData();
228 auto index = pointData.getVectorDataIndex(
230 if (index < 0) {
231 Logger::getInstance()
232 .addWarning("ToDiskMesh: Internal error: Could not find normal "
233 "vector data.")
234 .print();
235 } else {
236 pointData.eraseVectorData(index);
237 }
238 }
239
240 mesh->cellData.insertNextScalarData(values, "LSValues");
241 mesh->cellData.insertNextVectorData(normals, "Normals");
242 mesh->cellData.insertNextScalarData(materialIds, "MaterialIds");
243 mesh->minimumExtent = minimumExtent;
244 mesh->maximumExtent = maximumExtent;
245 }
246};
247
248} // namespace viennals
This algorithm is used to compute the normal vectors for all points with level set values <= 0....
Definition lsCalculateNormalVectors.hpp:26
void apply()
Definition lsCalculateNormalVectors.hpp:45
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
Expands the leveleSet to the specified number of layers. The largest value in the levelset is thus wi...
Definition lsExpand.hpp:16
void apply()
Apply the expansion to the specified width.
Definition lsExpand.hpp:44
This class holds an explicit mesh, which is always given in 3 dimensions. If it describes a 2D mesh,...
Definition lsMesh.hpp:21
This class creates a mesh from the level set with all grid points with a level set value <= 0....
Definition lsToDiskMesh.hpp:24
ToDiskMesh(SmartPointer< Domain< T, D > > passedLevelSet, SmartPointer< Mesh< N > > passedMesh, T passedMaxValue=0.5)
Definition lsToDiskMesh.hpp:45
void setMesh(SmartPointer< Mesh< N > > passedMesh)
Definition lsToDiskMesh.hpp:70
void setMaterialMap(SmartPointer< MaterialMap > passedMaterialMap)
Definition lsToDiskMesh.hpp:77
void apply()
Definition lsToDiskMesh.hpp:83
ToDiskMesh(SmartPointer< Domain< T, D > > passedLevelSet, SmartPointer< Mesh< N > > passedMesh, SmartPointer< TranslatorType > passedTranslator, T passedMaxValue=0.5)
Definition lsToDiskMesh.hpp:51
void setTranslator(SmartPointer< TranslatorType > passedTranslator)
Definition lsToDiskMesh.hpp:72
std::unordered_map< unsigned long, unsigned long > TranslatorType
Definition lsToDiskMesh.hpp:28
void insertNextLevelSet(SmartPointer< Domain< T, D > > passedLevelSet)
Pushes the passed level set to the back of the list of level sets.
Definition lsToDiskMesh.hpp:66
ToDiskMesh()
Definition lsToDiskMesh.hpp:40
void setMaxValue(const T passedMaxValue)
Definition lsToDiskMesh.hpp:81
void setLevelSet(SmartPointer< Domain< T, D > > passedLevelSet)
Definition lsToDiskMesh.hpp:61
ToDiskMesh(SmartPointer< Mesh< N > > passedMesh, T passedMaxValue=0.5)
Definition lsToDiskMesh.hpp:42
Definition lsAdvect.hpp:46
constexpr int D
Definition pyWrap.cpp:65
double T
Definition pyWrap.cpp:63