56 Foam::scalar Foam::isoSurfaceTopo::minTetQ
59 const label faceBasePtI
62 const scalar ownQuality =
74 const scalar neiQuality =
84 if (neiQuality < ownQuality)
94 void Foam::isoSurfaceTopo::fixTetBasePtIs()
98 const faceList& faces = mesh_.faces();
99 const labelList& faceOwn = mesh_.faceOwner();
100 const labelList& faceNei = mesh_.faceNeighbour();
104 tetBasePtIs_ = mesh_.tetBasePtIs();
108 bitSet problemCells(
cells.size());
110 forAll(tetBasePtIs_, facei)
112 if (tetBasePtIs_[facei] == -1)
114 problemCells.set(faceOwn[facei]);
116 if (mesh_.isInternalFace(facei))
118 problemCells.set(faceNei[facei]);
126 bitSet problemPoints(mesh_.points().size());
131 Map<label> pointCount;
134 for (
const label celli : problemCells)
138 for (
const label facei :
cells[celli])
140 for (
const label pointi : faces[facei])
142 ++pointCount(pointi);
151 <<
"point:" << iter.key()
152 <<
" at:" << mesh_.points()[iter.key()]
153 <<
" only used by one face" <<
nl
156 else if (iter.val() == 2)
158 problemPoints.set(iter.key());
169 forAll(tetBasePtIs_, facei)
173 problemCells.test(faceOwn[facei])
174 || (mesh_.isInternalFace(facei) && problemCells.test(faceNei[facei]))
177 const face&
f = faces[facei];
181 const label fp0 = tetBasePtIs_[facei] < 0 ? 0 : tetBasePtIs_[facei];
185 !problemPoints.test(
f.rcValue(fp0))
186 && !problemPoints.test(
f.fcValue(fp0))
194 scalar maxQ = -GREAT;
200 !problemPoints.test(
f.rcValue(fp))
201 && !problemPoints.test(
f.fcValue(fp))
204 const scalar q = minTetQ(facei, fp);
216 tetBasePtIs_[facei] = maxFp;
224 tetBasePtIs_[facei] = 0;
234 Pout<<
"isoSurface : adapted starting point of triangulation on "
235 << nAdapted <<
" faces." <<
endl;
242 Foam::label Foam::isoSurfaceTopo::generatePoint
245 const bool edgeIsDiag,
248 DynamicList<edge>& pointToVerts,
249 DynamicList<label>& pointToFace,
250 DynamicList<bool>& pointFromDiag,
251 EdgeMap<label>& vertsToPoint
256 label pointi = vertsToPoint.lookup(
vertices, -1);
259 pointi = pointToVerts.size();
262 pointToFace.append(facei);
263 pointFromDiag.append(edgeIsDiag);
264 vertsToPoint.insert(
vertices, pointi);
271 void Foam::isoSurfaceTopo::generateTriPoints
274 const int tetCutIndex,
275 const tetCell& tetLabels,
276 const FixedList<bool, 6>& edgeIsDiag,
278 DynamicList<edge>& pointToVerts,
279 DynamicList<label>& pointToFace,
280 DynamicList<bool>& pointFromDiag,
282 EdgeMap<label>& vertsToPoint,
283 DynamicList<label>& verts
303 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
313 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
323 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
327 if (tetCutIndex == 0x0E)
330 const label sz = verts.size();
331 Swap(verts[sz-2], verts[sz-1]);
345 tetLabels.reverseEdge(0),
346 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
355 tetLabels.reverseEdge(3),
356 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
366 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
370 if (tetCutIndex == 0x0D)
373 const label sz = verts.size();
374 Swap(verts[sz-2], verts[sz-1]);
389 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
398 tetLabels.reverseEdge(3),
399 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
410 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
423 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
428 if (tetCutIndex == 0x0C)
431 const label sz = verts.size();
432 Swap(verts[sz-5], verts[sz-4]);
433 Swap(verts[sz-2], verts[sz-1]);
447 tetLabels.reverseEdge(1),
448 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
457 tetLabels.reverseEdge(4),
458 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
467 tetLabels.reverseEdge(5),
468 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
472 if (tetCutIndex == 0x0B)
475 const label sz = verts.size();
476 Swap(verts[sz-2], verts[sz-1]);
491 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
500 tetLabels.reverseEdge(5),
501 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
514 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
525 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
530 if (tetCutIndex == 0x0A)
533 const label sz = verts.size();
534 Swap(verts[sz-5], verts[sz-4]);
535 Swap(verts[sz-2], verts[sz-1]);
550 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
559 tetLabels.reverseEdge(5),
560 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
571 tetLabels.reverseEdge(3),
572 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
585 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
589 if (tetCutIndex == 0x09)
592 const label sz = verts.size();
593 Swap(verts[sz-5], verts[sz-4]);
594 Swap(verts[sz-2], verts[sz-1]);
608 tetLabels.reverseEdge(2),
609 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
618 tetLabels.reverseEdge(5),
619 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
629 pointToVerts, pointToFace, pointFromDiag, vertsToPoint
632 if (tetCutIndex == 0x07)
635 const label sz = verts.size();
636 Swap(verts[sz-2], verts[sz-1]);
644 void Foam::isoSurfaceTopo::generateTriPoints
649 DynamicList<edge>& pointToVerts,
650 DynamicList<label>& pointToFace,
651 DynamicList<bool>& pointFromDiag,
653 EdgeMap<label>& vertsToPoint,
654 DynamicList<label>& verts,
655 DynamicList<label>& faceLabels
658 const faceList& faces = mesh_.faces();
659 const labelList& faceOwner = mesh_.faceOwner();
660 const cell& cFaces = mesh_.cells()[celli];
667 const label startTrii = verts.size();
669 const label facei = cFaces[0];
670 const face& f0 = faces[facei];
674 const face& f1 = faces[cFaces[1]];
675 label oppositeI = -1;
679 if (!f0.found(oppositeI))
689 if (faceOwner[facei] == celli)
705 tetCell(
p0, p1, p2, oppositeI),
706 FixedList<bool, 6>(
false),
715 for (label nTris = (verts.size()-startTrii)/3; nTris; --nTris)
717 faceLabels.append(facei);
722 for (
const label facei : cFaces)
726 !mesh_.isInternalFace(facei)
727 && ignoreBoundaryFaces_.test(facei-mesh_.nInternalFaces())
733 const label startTrii = verts.size();
735 const face&
f = faces[facei];
737 label fp0 = tetBasePtIs_[facei];
745 label fp =
f.fcIndex(fp0);
746 for (label i = 2; i <
f.size(); ++i)
748 const label nextFp =
f.fcIndex(fp);
750 FixedList<bool, 6> edgeIsDiag(
false);
754 label p2 =
f[nextFp];
755 if (faceOwner[facei] == celli)
758 if (i != 2) edgeIsDiag[1] =
true;
759 if (i !=
f.size()-1) edgeIsDiag[0] =
true;
763 if (i != 2) edgeIsDiag[0] =
true;
764 if (i !=
f.size()-1) edgeIsDiag[1] =
true;
778 tetCell(
p0, p1, p2, mesh_.nPoints()+celli),
791 for (label nTris = (verts.size()-startTrii)/3; nTris; --nTris)
793 faceLabels.append(facei);
802 void Foam::isoSurfaceTopo::triangulateOutside
804 const bool filterDiag,
811 DynamicList<face>& compactFaces,
812 DynamicList<label>& compactCellIDs
829 compactFaces.append(face(loop.size()));
830 face&
f = compactFaces.last();
835 const label pointi =
mp[loop[i]];
836 if (filterDiag && pointFromDiag[pointi])
838 const label prevPointi =
mp[loop[loop.fcIndex(i)]];
841 pointFromDiag[prevPointi]
842 && (pointToFace[pointi] != pointToFace[prevPointi])
867 const label pointi =
mp[loop[i]];
871 compactCellIDs.
append(cellID);
877 void Foam::isoSurfaceTopo::removeInsidePoints
880 const bool filterDiag,
888 DynamicList<label>& pointCompactMap,
889 DynamicList<label>& compactCellIDs
892 pointCompactMap.clear();
893 compactCellIDs.clear();
897 DynamicList<face> compactFaces(
s.size()/8);
899 for (label celli = 0; celli < start.size()-1; ++celli)
903 const label nTris = start[celli+1]-start[celli];
909 SubList<face>(
s, nTris, start[celli]),
931 pointCompactMap.
clear();
933 for (face&
f : compactFaces)
937 label pointi =
f[fp];
938 label compacti = oldToCompact[pointi];
941 compacti = pointCompactMap.size();
942 oldToCompact[pointi] = compacti;
943 pointCompactMap.
append(pointi);
951 UIndirectList<point>(
s.points(), pointCompactMap)
959 std::move(compactPoints),
960 std::move(compactFaces),
981 cellCutType_(
mesh.
nCells(), cutType::UNVISITED)
985 Pout<<
"isoSurfaceTopo:" <<
nl
986 <<
" cell min/max : " <<
minMax(cVals_) <<
nl
987 <<
" point min/max : " <<
minMax(pVals_) <<
nl
988 <<
" isoValue : " << iso <<
nl
992 <<
" ignoreCells : " << ignoreCells.
count()
993 <<
" / " << cVals_.size() <<
nl
997 this->ignoreCyclics();
999 label nBlockedCells = 0;
1002 nBlockedCells += blockCells(cellCutType_, ignoreCells);
1012 const label nCutCells = calcCellCuts(cellCutType_);
1016 Pout<<
"isoSurfaceTopo : candidate cells cut "
1018 <<
" blocked " << nBlockedCells
1019 <<
" total " << mesh_.nCells() <<
endl;
1024 const fvMesh& fvmesh = dynamicCast<const fvMesh&>(
mesh);
1030 "isoSurfaceTopo.cutType",
1043 forAll(cellCutType_, celli)
1045 debugFld[celli] = cellCutType_[celli];
1048 Pout<<
"Writing cut types:"
1049 << debugField.objectPath() <<
endl;
1075 for (label celli = 0; celli < mesh_.nCells(); ++celli)
1077 startTri[celli] = faceLabels.size();
1078 if ((cellCutType_[celli] & cutType::ANYCUT) != 0)
1085 bool(cellCutType_[celli] & cutType::TETCUT),
1096 for (label i = startTri[celli]; i < faceLabels.size(); ++i)
1098 cellLabels.
append(celli);
1102 startTri[mesh_.nCells()] = faceLabels.size();
1105 pointToVerts_.
transfer(pointToVerts);
1106 meshCells_.transfer(cellLabels);
1107 pointToFace_.transfer(pointToFace);
1111 this->interpolateTemplate
1113 mesh_.cellCentres(),
1120 faceList allTris(faceLabels.size());
1122 for (
face& allTri : allTris)
1125 allTri[0] = verts[verti++];
1126 allTri[1] = verts[verti++];
1127 allTri[2] = verts[verti++];
1140 Mesh::transfer(updated);
1153 Pout<<
"isoSurfaceTopo : generated "
1154 << Mesh::size() <<
" faces "
1159 if (params.
filter() != filterType::NONE)
1169 (params.
filter() == filterType::DIAGCELL ? true :
false),
1180 meshCells_.transfer(compactCellIDs);
1187 Pout<<
"isoSurfaceTopo :"
1188 " after removing cell centre and face-diag triangles "
1189 << Mesh::size() <<
" faces "
1199 if (params.
filter() == filterType::DIAGCELL)
1225 const labelList& faceOwn = mesh_.faceOwner();
1226 const labelList& faceNei = mesh_.faceNeighbour();
1263 const edgeList& surfEdges = erosion.edges();
1266 label nEdgeRemove = 0;
1270 const labelList& eFaces = edgeFaces[edgei];
1271 if (eFaces.size() == 1)
1275 const edge&
e = surfEdges[edgei];
1277 const edge& verts0 = pointToVerts_[
mp[
e.first()]];
1278 const edge& verts1 = pointToVerts_[
mp[
e.second()]];
1282 isBoundaryPoint.test(verts0.first())
1283 && isBoundaryPoint.test(verts0.
second())
1284 && isBoundaryPoint.test(verts1.first())
1285 && isBoundaryPoint.test(verts1.
second())
1301 Pout<<
"isoSurfaceTopo :"
1304 <<
" faces on " << nEdgeRemove <<
" open edges" <<
endl;
1320 if (surf.
size() != faceAddr.size())
1340 Mesh::subsetMesh(include, pointMap,
faceMap)
1342 Mesh::transfer(filtered);