64 #undef SNAP_END_ENCODE
65 #define SNAP_END_ENCODE(pos, val) (((val) << (4 + 2 * pos)))
66 #define SNAP_END_VALUE(pos, val) (((val) >> (4 + 2 * pos)) & 0x3)
94 if (doSnap && cutIndex && cutIndex != 0xF)
99 p0 -= val;
if (cutIndex & 1)
p0 *= -1;
100 p1 -= val;
if (cutIndex & 2) p1 *= -1;
101 p2 -= val;
if (cutIndex & 4) p2 *= -1;
102 p3 -= val;
if (cutIndex & 8) p3 *= -1;
107 #undef ADD_SNAP_INDEX
108 #define ADD_SNAP_INDEX(pos, d1, d2, idx1, idx2) \
109 switch (cutIndex & (idx1 | idx2)) \
113 cutIndex |= SNAP_END_ENCODE \
116 ((d1 * 100 < d2) ? 1 : (d2 * 100 < d1) ? 2 : 0) \
127 #undef ADD_SNAP_INDEX
145 if (a !=
b &&
b !=
c &&
c != a)
182 Foam::isoSurfaceTopo::tetCutAddressing::tetCutAddressing
184 const label nCutCells,
186 const bool useDebugCuts
189 vertsToPointLookup_(12*nCutCells),
192 pointToFace_(10*nCutCells),
193 pointFromDiag_(10*nCutCells),
195 pointToVerts_(10*nCutCells),
196 cutPoints_(12*nCutCells),
199 debugCutTetsOn_(useDebugCuts)
210 snapVertsLookup_.resize(4*nCutCells);
214 debugCutTets_.reserve(6*nCutCells);
221 void Foam::isoSurfaceTopo::tetCutAddressing::clearDebug()
223 debugCutTets_.clearStorage();
227 void Foam::isoSurfaceTopo::tetCutAddressing::clearDiagonal()
229 pointToFace_.clearStorage();
230 pointFromDiag_.clearStorage();
234 void Foam::isoSurfaceTopo::tetCutAddressing::clearHashes()
236 vertsToPointLookup_.clear();
237 snapVertsLookup_.clear();
241 Foam::label Foam::isoSurfaceTopo::tetCutAddressing::generatePoint
252 label pointi = vertsToPointLookup_.lookup(
vertices, -1);
255 bool addNewPoint(
true);
257 const label snapPointi =
260 : (snapEnd == 2) ?
vertices.second()
264 if (snapPointi == -1)
267 pointi = pointToVerts_.size();
274 edgeIsDiagonal =
false;
276 pointi = snapVertsLookup_.lookup(snapPointi, -1);
277 addNewPoint = (pointi == -1);
280 pointi = pointToVerts_.size();
281 snapVertsLookup_.insert(snapPointi, pointi);
282 pointToVerts_.append(edge(snapPointi, snapPointi));
288 pointToFace_.append(facei);
289 pointFromDiag_.append(edgeIsDiagonal);
292 vertsToPointLookup_.insert(
vertices, pointi);
299 bool Foam::isoSurfaceTopo::tetCutAddressing::generatePoints
302 const int tetCutIndex,
303 const tetCell& tetLabels,
306 const FixedList<bool, 6>& edgeIsDiagonal
310 const label nCutPointsOld(cutPoints_.size());
313 switch (tetCutIndex & 0x0F)
320 case 0x0E: flip =
true; [[fallthrough]];
359 case 0x0D: flip =
true; [[fallthrough]];
398 case 0x0C: flip =
true; [[fallthrough]];
448 case 0x0B: flip =
true; [[fallthrough]];
487 case 0x0A: flip =
true; [[fallthrough]];
537 case 0x09: flip =
true; [[fallthrough]];
587 case 0x07: flip =
true; [[fallthrough]];
626 const bool added(nCutPointsOld != cutPoints_.size());
628 if (added && debugCutTetsOn_)
630 debugCutTets_.append(tetLabels.shape());
640 void Foam::isoSurfaceTopo::generateTriPoints
645 tetCutAddressing& tetCutAddr
651 const bool doSnap = this->
snap();
658 const label facei = cFaces[0];
659 const face& f0 = faces[facei];
663 const face& f1 = faces[cFaces[1]];
668 if (!f0.found(apexi))
674 const label
p0 = f0[0];
678 if (faceOwner[facei] == celli)
683 const tetCell tetLabels(
p0, p1, p2, apexi);
684 const int tetCutIndex
697 tetCutAddr.generatePoints
702 FixedList<bool, 6>(
false)
707 for (
const label facei : cFaces)
718 const face&
f = faces[facei];
720 label fp0 = tetBasePtIs[facei];
728 const label
p0 =
f[fp0];
729 label fp =
f.fcIndex(fp0);
730 for (label i = 2; i <
f.size(); ++i)
736 FixedList<bool, 6> edgeIsDiagonal(
false);
737 if (faceOwner[facei] == celli)
740 if (i != 2) edgeIsDiagonal[1] =
true;
741 if (i !=
f.size()-1) edgeIsDiagonal[0] =
true;
745 if (i != 2) edgeIsDiagonal[0] =
true;
746 if (i !=
f.size()-1) edgeIsDiagonal[1] =
true;
750 const int tetCutIndex
763 tetCutAddr.generatePoints
778 void Foam::isoSurfaceTopo::triangulateOutside
780 const bool filterDiag,
787 DynamicList<face>& compactFaces,
788 DynamicList<label>& compactCellIDs
805 compactFaces.append(face(loop.size()));
806 face&
f = compactFaces.last();
811 const label pointi =
mp[loop[i]];
812 if (filterDiag && pointFromDiag[pointi])
814 const label prevPointi =
mp[loop[loop.fcIndex(i)]];
817 pointFromDiag[prevPointi]
818 && (pointToFace[pointi] != pointToFace[prevPointi])
843 const label pointi =
mp[loop[i]];
847 compactCellIDs.
append(cellID);
853 void Foam::isoSurfaceTopo::removeInsidePoints
856 const bool filterDiag,
864 DynamicList<label>& compactCellIDs
869 compactCellIDs.clear();
870 compactCellIDs.reserve(
s.size()/4);
872 DynamicList<face> compactFaces(
s.size()/4);
874 for (label celli = 0; celli < start.size()-1; ++celli)
878 const label nTris = start[celli+1]-start[celli];
884 SubList<face>(
s, nTris, start[celli]),
902 s.swapFaces(compactFaces);
928 Pout<<
"isoSurfaceTopo:" <<
nl
929 <<
" cell min/max : " <<
minMax(cVals_) <<
nl
930 <<
" point min/max : " <<
minMax(pVals_) <<
nl
931 <<
" isoValue : " << iso <<
nl
935 <<
" ignoreCells : " << ignoreCells.
count()
936 <<
" / " << cVals_.size() <<
nl
940 this->ignoreCyclics();
942 label nBlockedCells = 0;
945 nBlockedCells += blockCells(cellCutType_, ignoreCells);
959 const label nCutCells = calcCellCuts(cellCutType_);
963 Pout<<
"isoSurfaceTopo : candidate cells cut "
965 <<
" blocked " << nBlockedCells
966 <<
" total " << mesh_.nCells() <<
endl;
971 const auto& fvmesh = dynamicCast<const fvMesh>(
mesh);
977 "isoSurfaceTopo.cutType",
978 fvmesh.time().timeName(),
990 forAll(cellCutType_, celli)
992 debugFld[celli] = cellCutType_[celli];
995 Info<<
"Writing cut types: " << debugField.objectRelPath() <<
nl;
1004 constexpr uint8_t realCut(cutType::CUT | cutType::TETCUT);
1008 forAll(cellCutType_, celli)
1010 if ((cellCutType_[celli] & realCut) != 0)
1012 debugCutCells[nout] = celli;
1014 if (nout >= nCutCells)
break;
1020 vtuCells.
reset(mesh_, debugCutCells);
1028 mesh_.time().globalPath()
1029 / (
"isoSurfaceTopo." + timeDesc +
"-cutCells")
1038 writer.writeCellData(
"cutField", cVals_);
1042 writer.writePointData(
"cutField", pVals_);
1044 Info<<
"isoSurfaceTopo : (debug) wrote "
1052 tetCutAddressing tetCutAddr
1060 for (label celli = 0; celli < mesh_.nCells(); ++celli)
1062 startTri[celli] = tetCutAddr.nFaces();
1063 if ((cellCutType_[celli] & cutType::ANYCUT) != 0)
1069 bool(cellCutType_[celli] & cutType::TETCUT),
1076 startTri.last() = tetCutAddr.nFaces();
1079 tetBasePtIs.clear();
1080 tetCutAddr.clearHashes();
1084 faceList allTriFaces(startTri.last());
1086 auto& verts = tetCutAddr.cutPoints();
1089 for (
face&
f : allTriFaces)
1092 f[0] = verts[verti++];
1093 f[1] = verts[verti++];
1094 f[2] = verts[verti++];
1101 meshCells_.resize(startTri.last());
1102 for (label celli = 0; celli < startTri.size()-1; ++celli)
1108 (startTri[celli+1] - startTri[celli]),
1114 pointToVerts_.transfer(tetCutAddr.pointToVerts());
1118 this->interpolateTemplate
1120 mesh_.cellCentres(),
1129 std::move(allTriPoints),
1130 std::move(allTriFaces),
1136 Pout<<
"isoSurfaceTopo : generated "
1137 << Mesh::size() <<
" triangles "
1142 if ((
debug & 8) && (params.
filter() != filterType::NONE))
1144 const Mesh&
s = *
this;
1152 mesh_.time().globalPath()
1153 / (
"isoSurfaceTopo." + timeDesc +
"-triangles")
1174 const edge& verts = pointToVerts_[i];
1175 if (verts.first() == verts.
second())
1180 if (tetCutAddr.pointFromDiag().test(i))
1183 pointStatus[i] = -1;
1190 Info<<
"isoSurfaceTopo : (debug) wrote "
1205 if (params.
filter() == filterType::NONE)
1213 s.compactPoints(pointMap);
1232 params.
filter() == filterType::DIAGCELL
1233 || params.
filter() == filterType::NONMANIFOLD
1235 tetCutAddr.pointFromDiag(),
1236 tetCutAddr.pointToFace(),
1242 s.compactPoints(pointMap);
1245 meshCells_.transfer(compactCellIDs);
1249 Pout<<
"isoSurfaceTopo :"
1250 " after removing cell centre and face-diag triangles: "
1251 << Mesh::size() <<
" faces "
1258 tetCutAddr.clearDiagonal();
1267 (params.
filter() == filterType::NONMANIFOLD)
1268 || tetCutAddr.debugCutTetsOn()
1274 isProtectedPoint.
resize(mesh_.nPoints());
1278 label facei = mesh_.nInternalFaces();
1279 facei < mesh_.nFaces();
1283 isProtectedPoint.
set(mesh_.faces()[facei]);
1289 const labelList& faceOwn = mesh_.faceOwner();
1290 const labelList& faceNei = mesh_.faceNeighbour();
1302 isProtectedPoint.
set(mesh_.faces()[facei]);
1309 cellCutType_.clear();
1313 if (tetCutAddr.debugCutTetsOn())
1317 const auto& debugCuts = tetCutAddr.debugCutTets();
1333 mesh_.time().globalPath()
1334 / (
"isoSurfaceTopo." + timeDesc +
"-cutTets")
1347 forAll(cutTetQuality, teti)
1357 writer.writeCellData(
"tetQuality", cutTetQuality);
1367 for (
const edge& verts : pointToVerts_)
1369 if (verts.first() == verts.second())
1372 pointStatus[verts.first()] = 1;
1376 writer.writePointData(
"point-status", pointStatus);
1379 Info<<
"isoSurfaceTopo : (debug) wrote "
1390 const Mesh&
s = *
this;
1395 openEdgeIds.resize(2*
s.size());
1399 const labelList& eFaces = edgeFaces[edgei];
1400 if (eFaces.size() == 1)
1404 const edge&
e = surfEdges[edgei];
1405 const edge& verts0 = pointToVerts_[
mp[
e.first()]];
1406 const edge& verts1 = pointToVerts_[
mp[
e.second()]];
1410 isProtectedPoint.
test(verts0.first())
1412 && isProtectedPoint.
test(verts1.first())
1421 openEdgeIds.
insert(edgei);
1426 const label nOpenEdges
1436 openEdgeIds.sortedToc()
1445 mesh_.time().globalPath()
1446 / (
"isoSurfaceTopo." + timeDesc +
"-openEdges")
1456 Info<<
"isoSurfaceTopo : (debug) wrote "
1457 << nOpenEdges <<
" open edges: "
1462 Info<<
"isoSurfaceTopo : no open edges" <<
nl;
1469 const Mesh&
s = *
this;
1477 mesh_.time().globalPath()
1478 / (
"isoSurfaceTopo." + timeDesc +
"-surface")
1499 const edge& verts = pointToVerts_[i];
1500 if (verts.first() == verts.
second())
1510 Info<<
"isoSurfaceTopo : (debug) wrote "
1516 tetCutAddr.clearDebug();
1519 if (params.
filter() == filterType::NONMANIFOLD)
1548 const edgeList& surfEdges = erosion.edges();
1551 label nEdgeRemove = 0;
1555 const labelList& eFaces = edgeFaces[edgei];
1556 if (eFaces.size() == 1)
1560 const edge&
e = surfEdges[edgei];
1561 const edge& verts0 = pointToVerts_[
mp[
e.first()]];
1562 const edge& verts1 = pointToVerts_[
mp[
e.second()]];
1566 isProtectedPoint.
test(verts0.first())
1568 && isProtectedPoint.
test(verts1.first())
1585 Pout<<
"isoSurfaceTopo :"
1588 <<
" faces on " << nEdgeRemove <<
" open edges" <<
endl;
1604 if (surf.
size() != faceAddr.size())
1624 Mesh::subsetMesh(include, pointMap,
faceMap)
1626 Mesh::transfer(filtered);