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:
40 ToDiskMesh() = default;
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 clearLevelSets() { levelSets.clear(); }
84
85 void apply() {
86 if (levelSets.empty()) {
87 Logger::getInstance()
88 .addError("No level sets passed to ToDiskMesh.")
89 .print();
90 return;
91 }
92 if (mesh == nullptr) {
93 Logger::getInstance()
94 .addError("No mesh was passed to ToDiskMesh.")
95 .print();
96 return;
97 }
98 if (buildTranslator && translator == nullptr) {
99 Logger::getInstance()
100 .addWarning("No translator was passed to ToDiskMesh.")
101 .print();
102 }
103
104 mesh->clear();
105
106 // expand top levelset
107 Expand<T, D>(levelSets.back(), (maxValue * 4) + 1).apply();
108 CalculateNormalVectors<T, D>(levelSets.back(), maxValue).apply();
109
110 const T gridDelta = levelSets.back()->getGrid().getGridDelta();
111 const auto &normalVectors =
112 *(levelSets.back()->getPointData().getVectorData(
114
115 // set up data arrays
116 std::vector<N> values;
117 std::vector<Vec3D<N>> normals;
118 std::vector<N> materialIds;
119
120 // save the extent of the resulting mesh
121 Vec3D<N> minimumExtent;
122 Vec3D<N> maximumExtent;
123 for (unsigned i = 0; i < D; ++i) {
124 minimumExtent[i] = std::numeric_limits<T>::max();
125 maximumExtent[i] = std::numeric_limits<T>::lowest();
126 }
127
128 values.reserve(normalVectors.size());
129 normals.reserve(normalVectors.size());
130 materialIds.reserve(normalVectors.size());
131
132 const bool useMaterialMap = materialMap != nullptr;
133 const bool buildTranslatorFlag = buildTranslator;
134 unsigned long counter = 0;
135 if (buildTranslatorFlag) {
136 translator->clear();
137 translator->reserve(normalVectors.size());
138 }
139
140 // an iterator for each levelset
141 std::vector<viennahrle::ConstSparseIterator<hrleDomainType>> iterators;
142 for (const auto levelSet : levelSets) {
143 iterators.emplace_back(levelSet->getDomain());
144 }
145
146 // iterate over top levelset
147 for (auto &topIt = iterators.back(); !topIt.isFinished(); ++topIt) {
148 if (!topIt.isDefined() || std::abs(topIt.getValue()) > maxValue) {
149 continue;
150 }
151
152 unsigned pointId = topIt.getPointId();
153
154 // insert pointId-counter pair in translator
155 if (buildTranslatorFlag) {
156 translator->insert({pointId, counter++});
157 }
158
159 // insert material ID
160 const T value = topIt.getValue();
161 int matId = levelSets.size() - 1;
162 for (int lowerLevelSetId = 0; lowerLevelSetId < levelSets.size() - 1;
163 ++lowerLevelSetId) {
164 // check if there is any other levelset at the same point:
165 // put iterator to same position as the top levelset
166 iterators[lowerLevelSetId].goToIndicesSequential(
167 topIt.getStartIndices());
168 if (iterators[lowerLevelSetId].getValue() <=
169 value + wrappingLayerEpsilon) {
170 matId = lowerLevelSetId;
171 break;
172 }
173 }
174 if (useMaterialMap)
175 matId = materialMap->getMaterialId(matId);
176
177 materialIds.push_back(matId);
178
179 // insert vertex
180 std::array<unsigned, 1> vertex{};
181 vertex[0] = mesh->nodes.size();
182 mesh->insertNextVertex(vertex);
183
184 // insert corresponding node shifted by ls value in direction of the
185 // normal vector
186 Vec3D<N> node;
187 node[2] = 0.;
188 double max = 0.;
189 for (unsigned i = 0; i < D; ++i) {
190 // original position
191 node[i] = double(topIt.getStartIndices(i)) * gridDelta;
192
193 // save extent
194 if (node[i] < minimumExtent[i]) {
195 minimumExtent[i] = node[i];
196 } else if (node[i] > maximumExtent[i]) {
197 maximumExtent[i] = node[i];
198 }
199
200 if (std::abs(normalVectors[pointId][i]) > max) {
201 max = std::abs(normalVectors[pointId][i]);
202 }
203 }
204
205 // now normalize vector to scale position correctly to manhatten distance
206 double scaling = value * gridDelta * max;
207 for (unsigned i = 0; i < D; ++i) {
208 node[i] -= scaling * normalVectors[pointId][i];
209 }
210
211 mesh->insertNextNode(node);
212
213 // add data into mesh
214 // copy normal
215 Vec3D<N> normal;
216 if (D == 2)
217 normal[2] = 0.;
218 for (unsigned i = 0; i < D; ++i) {
219 normal[i] = normalVectors[pointId][i];
220 }
221
222 normals.push_back(normal);
223 values.push_back(value);
224 }
225
226 // delete normal vectors point data again as it is not needed anymore
227 {
228 auto &pointData = levelSets.back()->getPointData();
229 auto index = pointData.getVectorDataIndex(
231 if (index < 0) {
232 Logger::getInstance()
233 .addWarning("ToDiskMesh: Could not find normal 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
249
250} // namespace viennals
constexpr int D
Definition Epitaxy.cpp:11
double T
Definition Epitaxy.cpp:12
This algorithm is used to compute the normal vectors for all points with level set values <= maxValue...
Definition lsCalculateNormalVectors.hpp:35
static constexpr char normalVectorsLabel[]
Definition lsCalculateNormalVectors.hpp:45
void apply()
Definition lsCalculateNormalVectors.hpp:82
Class containing all information about the level set, including the dimensions of the domain,...
Definition lsDomain.hpp:27
viennahrle::Domain< T, D > DomainType
Definition lsDomain.hpp:32
Expands the levelSet to the specified number of layers. The largest value in the levelset is thus wid...
Definition lsExpand.hpp:17
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:22
ToDiskMesh(SmartPointer< Domain< T, D > > passedLevelSet, SmartPointer< Mesh< N > > passedMesh, T passedMaxValue=0.5)
Definition lsToDiskMesh.hpp:45
void clearLevelSets()
Definition lsToDiskMesh.hpp:83
void setMesh(SmartPointer< Mesh< N > > passedMesh)
Definition lsToDiskMesh.hpp:70
void setMaterialMap(SmartPointer< MaterialMap > passedMaterialMap)
Definition lsToDiskMesh.hpp:77
void apply()
Definition lsToDiskMesh.hpp:85
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
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
#define PRECOMPILE_PRECISION_DIMENSION(className)
Definition lsPreCompileMacros.hpp:24
Definition lsAdvect.hpp:36