84 if (levelSets.empty()) {
86 .addError(
"No level set was passed to ToMultiSurfaceMesh.")
90 if (mesh ==
nullptr) {
92 .addError(
"No mesh was passed to ToMultiSurfaceMesh.")
98 const auto gridDelta = levelSets.front()->getGrid().getGridDelta();
99 for (
unsigned i = 0; i <
D; ++i) {
100 mesh->minimumExtent[i] = std::numeric_limits<NumericType>::max();
101 mesh->maximumExtent[i] = std::numeric_limits<NumericType>::lowest();
104 constexpr unsigned int corner0[12] = {0, 1, 2, 0, 4, 5, 6, 4, 0, 1, 3, 2};
105 constexpr unsigned int corner1[12] = {1, 3, 3, 2, 5, 7, 7, 6, 4, 5, 7, 6};
106 constexpr unsigned int direction[12] = {0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2};
108 typedef std::map<viennahrle::Index<D>,
unsigned> nodeContainerType;
110 nodeContainerType nodes[
D];
111 const double minNodeDistance = gridDelta * minNodeDistanceFactor;
112 std::unordered_map<I3, unsigned, I3Hash> nodeIdByBin;
113 std::unordered_set<I3, I3Hash> uniqueElements;
115 typename nodeContainerType::iterator nodeIt;
117 std::vector<Vec3D<T>> normals;
118 std::vector<T> materials;
120 const bool checkNodeFlag = minNodeDistanceFactor > 0;
121 const bool useMaterialMap = materialMap !=
nullptr;
123 auto quantize = [&](
const Vec3D<T> &p) -> I3 {
124 const T inv =
T(1) / minNodeDistance;
125 return {(int)std::llround(p[0] * inv), (int)std::llround(p[1] * inv),
126 (int)std::llround(p[2] * inv)};
129 auto elementI3 = [&](
const std::array<unsigned, D> &element) -> I3 {
130 if constexpr (
D == 2)
131 return {(int)element[0], (
int)element[1], 0};
133 return {(int)element[0], (
int)element[1], (int)element[2]};
137 std::vector<viennahrle::ConstSparseCellIterator<hrleDomainType>> cellIts;
138 for (
const auto &
ls : levelSets)
139 cellIts.emplace_back(
ls->getDomain());
141 for (
unsigned l = 0; l < levelSets.size(); l++) {
143 for (
auto cellIt = cellIts[l]; !cellIt.isFinished(); cellIt.next()) {
144 for (
int u = 0; u <
D; u++) {
145 while (!nodes[u].empty() &&
146 nodes[u].begin()->first <
147 viennahrle::Index<D>(cellIt.getIndices()))
148 nodes[u].erase(nodes[u].begin());
152 for (
int i = 0; i < (1 <<
D); i++) {
153 if (cellIt.getCorner(i).getValue() >=
NumericType(0))
160 if (signs == (1 << (1 <<
D)) - 1)
164 const int *Triangles;
165 if constexpr (
D == 2) {
171 for (; Triangles[0] != -1; Triangles +=
D) {
172 std::array<unsigned, D> nod_numbers;
175 for (
int n = 0; n <
D; n++) {
176 const int edge = Triangles[n];
178 unsigned p0 = corner0[edge];
179 unsigned p1 = corner1[edge];
182 unsigned dir = direction[edge];
185 viennahrle::Index<D> d(cellIt.getIndices());
186 auto p0B = viennahrle::BitMaskToIndex<D>(p0);
189 nodeIt = nodes[dir].find(d);
190 if (nodeIt != nodes[dir].end()) {
191 nod_numbers[n] = nodeIt->second;
196 for (
int z = 0; z <
D; z++) {
200 cc[z] =
static_cast<T>(cellIt.getIndices(z) + p0B[z]);
202 auto d0 =
static_cast<T>(cellIt.getCorner(p0).getValue());
203 auto d1 =
static_cast<T>(cellIt.getCorner(p1).getValue());
207 cc[z] =
static_cast<T>(cellIt.getIndices(z)) + 0.5;
209 if (std::abs(d0) <= std::abs(d1)) {
210 cc[z] =
static_cast<T>(cellIt.getIndices(z)) +
213 cc[z] =
static_cast<T>(cellIt.getIndices(z) + 1) -
218 cc[z],
static_cast<T>(cellIt.getIndices(z) + epsilon));
221 static_cast<T>((cellIt.getIndices(z) + 1) - epsilon));
228 auto q = quantize(cc);
229 auto it = nodeIdByBin.find(q);
230 if (it != nodeIdByBin.end())
231 nodeIdx = it->second;
234 nod_numbers[n] = nodeIdx;
238 mesh->insertNextNode(cc);
239 nodes[dir][d] = nod_numbers[n];
241 nodeIdByBin.emplace(quantize(cc), nod_numbers[n]);
243 for (
int a = 0; a <
D; a++) {
244 if (cc[a] < mesh->minimumExtent[a])
245 mesh->minimumExtent[a] = cc[a];
246 if (cc[a] > mesh->maximumExtent[a])
247 mesh->maximumExtent[a] = cc[a];
254 if (!triangleMisformed(nod_numbers)) {
257 if (uniqueElements.insert(elementI3(nod_numbers)).second) {
259 if constexpr (
D == 2) {
260 normal = Vec3D<T>{-(mesh->nodes[nod_numbers[1]][1] -
261 mesh->nodes[nod_numbers[0]][1]),
262 mesh->nodes[nod_numbers[1]][0] -
263 mesh->nodes[nod_numbers[0]][0],
266 normal = calculateNormal(mesh->nodes[nod_numbers[0]],
267 mesh->nodes[nod_numbers[1]],
268 mesh->nodes[nod_numbers[2]]);
271 double n2 = normal[0] * normal[0] + normal[1] * normal[1] +
272 normal[2] * normal[2];
275 mesh->insertNextElement(nod_numbers);
278 T invn =
static_cast<T>(1.) / std::sqrt(
static_cast<T>(n2));
279 for (
int d = 0; d <
D; d++) {
282 normals.push_back(normal);
285 if (useMaterialMap) {
286 materials.push_back(materialMap->getMaterialId(l));
288 materials.push_back(
static_cast<T>(l));
297 mesh->cellData.insertNextScalarData(materials,
"MaterialIds");
298 mesh->cellData.insertNextVectorData(normals,
"Normals");
299 mesh->triangles.shrink_to_fit();
300 mesh->nodes.shrink_to_fit();