Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] BUG: Sets Face Label for virtual boundary to -1 in SurfaceNetsFilter #1158

Draft
wants to merge 5 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/Plugins/SimplnxCore/docs/SurfaceNetsFilter.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,19 @@ Nodes that appear on the exterior of a volume have Node Type values starting at

![Exterior Node Types](Images/SurfaceNets_NodeType_Exterior.png)

### Exterior or Boundary Faces

Triangle faces that bound the virtual volume will have one of the Face Labels components
set to a value of -1. If you want to filter out those triangles, you can set any
triangle face where at least one of the Face Labels = -1 to be filtered out. You can also
run a Threshold Objects (Advanced) filter, those face labels as "TRUE" instead and
then run the "Remove Marked Triangles" filter to remove them from the surface mesh.

## Notes

This filter should be used in place of the "QuickMesh Surface Filter".
- This filter can be used in place of the "QuickMesh Surface Filter" and "Laplacian Smoothing Filter".
- This filter can use substantially more memory than the QuickMesh Filter



% Auto generated parameter table will be inserted here
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
#pragma once

#include "SimplnxCore/Filters/Algorithms/TupleTransfer.hpp"
#include "SimplnxCore/SimplnxCore_export.hpp"
#include "SimplnxCore/SurfaceNets/MMCellFlag.h"

#include "simplnx/DataStructure/DataPath.hpp"
#include "simplnx/DataStructure/DataStructure.hpp"
#include "simplnx/DataStructure/Geometry/ImageGeom.hpp"
#include "simplnx/DataStructure/Geometry/TriangleGeom.hpp"
#include "simplnx/Filter/IFilter.hpp"
#include "simplnx/Parameters/ArrayCreationParameter.hpp"
#include "simplnx/Parameters/ArraySelectionParameter.hpp"
#include "simplnx/Parameters/BoolParameter.hpp"
#include "simplnx/Parameters/DataGroupCreationParameter.hpp"
#include "simplnx/Parameters/MultiArraySelectionParameter.hpp"

class MMCellMap;

namespace nx::core
{

Expand Down Expand Up @@ -55,6 +61,9 @@ class SIMPLNXCORE_EXPORT SurfaceNets
const SurfaceNetsInputValues* m_InputValues = nullptr;
const std::atomic_bool& m_ShouldCancel;
const IFilter::MessageHandler& m_MessageHandler;

void GenerateTriangles(int idxVtx, MMCellFlag::Edge edgeType, MMCellMap* cellMapPtr, const ImageGeom& imageGeom, TriangleGeom& triangleGeom, usize& faceIndex, AbstractDataStore<int32_t>& featureIds,
AbstractDataStore<int32_t>& faceLabels, std::vector<std::shared_ptr<AbstractTupleTransfer>>& tupleTransferFunctions);
};

} // namespace nx::core
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class SIMPLNXCORE_EXPORT AbstractTupleTransfer
* @param secondcIndex
* @param forceSecondToZero
*/
virtual void transfer(size_t faceIndex, size_t firstcIndex, size_t secondcIndex, bool forceSecondToZero = false) = 0;
// virtual void transfer(size_t faceIndex, size_t firstcIndex, size_t secondcIndex, bool forceSecondToZero) = 0;

virtual void transfer(size_t faceIndex, size_t firstcIndex) = 0;

Expand Down Expand Up @@ -82,21 +82,21 @@ class TransferTuple : public AbstractTupleTransfer
* @param secondcIndex
* @param forceSecondToZero
*/
void transfer(size_t faceIndex, size_t firstcIndex, size_t secondcIndex, bool forceSecondToZero = false) override
{
for(size_t i = 0; i < m_NumComps; i++)
{
m_FaceRef[faceIndex * m_NumComps + i] = m_CellRef[firstcIndex * m_NumComps + i];
}

if(!forceSecondToZero)
{
for(size_t i = 0; i < m_NumComps; i++)
{
m_FaceRef[faceIndex + i + m_NumComps] = m_CellRef[secondcIndex + i];
}
}
}
// void transfer(size_t faceIndex, size_t cellIndex1, size_t cellIndex2, bool forceSecondToZero) override
// {
// for(size_t i = 0; i < m_NumComps; i++)
// {
// m_FaceRef[faceIndex * m_NumComps + i] = m_CellRef[cellIndex1 * m_NumComps + i];
// }
//
// if(!forceSecondToZero)
// {
// for(size_t i = 0; i < m_NumComps; i++)
// {
// m_FaceRef[faceIndex * m_NumComps + i] = m_CellRef[cellIndex2 * m_NumComps + i];
// }
// }
// }

void transfer(size_t faceIndex, size_t firstcIndex) override
{
Expand Down
15 changes: 15 additions & 0 deletions src/Plugins/SimplnxCore/src/SimplnxCore/SurfaceNets/MMCellFlag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,3 +345,18 @@ bool MMCellFlag::isEdgeCrossing(Edge edge) const
}
}
}

uint8_t MMCellFlag::numJunctions() const
{
return m_BitFlag >> k_NumJunctionsBitShift;
}

uint32_t MMCellFlag::getBitFlag() const
{
return m_BitFlag;
}

void MMCellFlag::clear()
{
m_BitFlag = 0;
}
18 changes: 6 additions & 12 deletions src/Plugins/SimplnxCore/src/SimplnxCore/SurfaceNets/MMCellFlag.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#pragma once

#include <cstddef>
#include <cstdint>

class MMCellFlag
Expand Down Expand Up @@ -57,24 +58,15 @@ class MMCellFlag
// edge or face crossings.
void set(const int32_t cellLabels[8]);

uint32_t getBitFlag() const
{
return m_BitFlag;
}
uint32_t getBitFlag() const;

void clear()
{
m_BitFlag = 0;
}
void clear();

// Get components of the cell flag
VertexType vertexType() const;
FaceCrossingType faceCrossingType(Face face) const;
bool isEdgeCrossing(Edge edge) const;
uint8_t numJunctions() const
{
return m_BitFlag >> k_NumJunctionsBitShift;
}
uint8_t numJunctions() const;

private:
static inline constexpr uint32_t k_NumJunctionsBitShift = 29;
Expand All @@ -83,6 +75,8 @@ class MMCellFlag
// The last 3 bits of the bitflag are the number of junctions
// numJunctions can at most be 6
uint32_t m_BitFlag = 0;

size_t m_CellIndex = 0;
};

// For iterating over cell faces
Expand Down
44 changes: 26 additions & 18 deletions src/Plugins/SimplnxCore/src/SimplnxCore/SurfaceNets/MMCellMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//
// Sarah Frisken, Brigham and Women's Hospital, Boston MA USA

#include <array>
#include <cstdlib>
#include <exception>
#include <iostream>
Expand Down Expand Up @@ -39,7 +40,6 @@ MMCellMap::MMCellMap(int32_t* labels, int arraySize[3], float voxelSize[3])
// corner.
Cell* pCell = m_cellArray;
int32_t* pLabel = labels;
int32_t padLabel = (int32_t)MMSurfaceNet::ReservedLabel::Padding;
for(int k = 0; k < m_arraySize[2]; k++)
{
for(int j = 0; j < m_arraySize[1]; j++)
Expand All @@ -48,7 +48,7 @@ MMCellMap::MMCellMap(int32_t* labels, int arraySize[3], float voxelSize[3])
{
if(i == 0 || i == m_arraySize[0] - 1 || j == 0 || j == m_arraySize[1] - 1 || k == 0 || k == m_arraySize[2] - 1)
{
initCell(pCell++, padLabel);
initCell(pCell++, static_cast<int32_t>(MMSurfaceNet::ReservedLabel::Padding));
}
else
{
Expand Down Expand Up @@ -208,40 +208,38 @@ MMCellFlag::VertexType MMCellMap::vertexType(int vertexIndex)
// [x0, y0, z0, x1, y1 ...] in clockwise order and the quad face labels are inserted
// into quadLabels as [labelTopFaceOfQuad, labelBottomFaceOfQuad]. If there is no edge
// crossing, quadCorners and quadLabels will not be set.
bool MMCellMap::getEdgeQuad(int vertexIndex, MMCellFlag::Edge edge, float quadCorners[12], int32_t quadLabels[2])
bool MMCellMap::getEdgeQuad(int vertexIndex, MMCellFlag::Edge edge, float quadCorners[12], int32_t quadLabels[2], std::array<int32_t, 3>& cellIndex)
{
int cellIndex[3];
getVertexCellIndex(vertexIndex, cellIndex);
if(!isEdgeCrossing(cellArrayIndex(cellIndex), edge))
getVertexCellIndex(vertexIndex, cellIndex.data());
if(!isEdgeCrossing(cellArrayIndex(cellIndex.data()), edge))
{
return false;
}

// Because there is an edge crossing, cell map access in the following will be
// in-bounds by construction of the cell map.
getEdgeLabels(cellIndex, edge, quadLabels);
getEdgeQuadPositions(cellIndex, edge, quadCorners);
getEdgeLabels(cellIndex.data(), edge, quadLabels);
getEdgeQuadPositions(cellIndex.data(), edge, quadCorners);
return true;
}
// Returns true if there is an edge crossing and false otherwise. If there is an edge
// crossing, we defince a surface quad from vertices in the 4 cells touching the edge.
// crossing, we define a surface quad from vertices in the 4 cells touching the edge.
// The indices of these 4 vertices are inserted into quadVtxIndices in clockwise order
// and the quad face labels are inserted into quadLabels as [labelTopFaceOfQuad,
// labelBottomFaceOfQuad]. If there is no edge crossing, quadCorners and quadLabels
// will not be set.
bool MMCellMap::getEdgeQuad(int vertexIndex, MMCellFlag::Edge edge, int quadVtxIndices[4], int32_t quadLabels[2])
bool MMCellMap::getEdgeQuad(int vertexIndex, MMCellFlag::Edge edge, int quadVtxIndices[4], int32_t quadLabels[2], std::array<int32_t, 3>& cellIndex)
{
int cellIndex[3];
getVertexCellIndex(vertexIndex, cellIndex);
if(!isEdgeCrossing(cellArrayIndex(cellIndex), edge))
getVertexCellIndex(vertexIndex, cellIndex.data());
if(!isEdgeCrossing(cellArrayIndex(cellIndex.data()), edge))
{
return false;
}

// Because there is an edge crossing, cell map access in the following will be
// in-bounds by construction of the cell map.
getEdgeLabels(cellIndex, edge, quadLabels);
getEdgeQuadVtxIndices(cellIndex, edge, quadVtxIndices);
getEdgeLabels(cellIndex.data(), edge, quadLabels);
getEdgeQuadVtxIndices(cellIndex.data(), edge, quadVtxIndices);
return true;
}

Expand Down Expand Up @@ -321,9 +319,14 @@ void MMCellMap::setCellVertices()
// The caller is responsible for bounds checking to allow for optimal performance.
void MMCellMap::getEdgeLabels(int cellIndex[3], MMCellFlag::Edge edge, int32_t quadLabels[2])
{
std::array<int, 3> idx = {0, 0, 0};
Cell* zeroCell = getCell(idx.data());
idx = {52, 27, 52};
Cell* lastCell = getCell(idx.data());

Cell* pCell = getCell(cellIndex);
Cell* pCellFirstLabel;
Cell* pCellSecondLabel;
Cell* pCellFirstLabel = nullptr;
Cell* pCellSecondLabel = nullptr;
switch(edge)
{
case MMCellFlag::Edge::LeftBottomEdge:
Expand Down Expand Up @@ -379,12 +382,17 @@ void MMCellMap::getEdgeLabels(int cellIndex[3], MMCellFlag::Edge edge, int32_t q
pCellSecondLabel = pCell;
break;
}

ptrdiff_t diff_last_zero = lastCell - zeroCell;
ptrdiff_t diff_first_zero = pCellFirstLabel - zeroCell;
ptrdiff_t diff_first_second = pCellSecondLabel - zeroCell;

quadLabels[0] = pCellFirstLabel->label;
quadLabels[1] = pCellSecondLabel->label;
}

// The caller is responsible for bounds checking to allow for optimal performance.
// Vertices are ordered clockwise around each edge begining with the cell vertex, with
// Vertices are ordered clockwise around each edge beginning with the cell vertex, with
// edges oriented left-to-right, back-to-front and bottom-to-top.
void MMCellMap::getEdgeQuadPositions(int cellIndex[3], MMCellFlag::Edge edge, float quadCorners[12])
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include "MMCellFlag.h"
#include "MMSurfaceNet.h"

#include <array>

class MMCellMap
{
public:
Expand All @@ -27,8 +29,8 @@ class MMCellMap
int numVertices();
int numEdgeCrossings();
MMCellFlag::VertexType vertexType(int vertexIndex);
bool getEdgeQuad(int vertexIndex, MMCellFlag::Edge edge, float quadCorners[12], int32_t quadLabels[2]);
bool getEdgeQuad(int vertexIndex, MMCellFlag::Edge edge, int quadVtxIndices[4], int32_t quadLabels[2]);
bool getEdgeQuad(int vertexIndex, MMCellFlag::Edge edge, float quadCorners[12], int32_t quadLabels[2], std::array<int32_t, 3>& cellIndex);
bool getEdgeQuad(int vertexIndex, MMCellFlag::Edge edge, int quadVtxIndices[4], int32_t quadLabels[2], std::array<int32_t, 3>& cellIndex);
void getVertexPosition(int vertexIndex, float position[3]);

MMCellFlag::VertexType cellVertexType(int cellArrayIndex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,15 @@ MMGeometryGL::MMGeometryGL(MMSurfaceNet* surfaceNet)
m_numIndices = 0;
float* pVertices = m_vertices;
unsigned int* pIndices = m_indices;
std::array<int32_t, 3> cellIndices = {0, 0, 0};

for(int idxVtx = 0; idxVtx < cellMap->numVertices(); idxVtx++)
{
float vertexPositions[12];
int32_t labelsTmp[2];

// Back-bottom edge
if(cellMap->getEdgeQuad(idxVtx, MMCellFlag::Edge::BackBottomEdge, vertexPositions, labelsTmp) == true)
if(cellMap->getEdgeQuad(idxVtx, MMCellFlag::Edge::BackBottomEdge, vertexPositions, labelsTmp, cellIndices) == true)
{
MMGeometryGL::makeGLQuad(vertexPositions, labelsTmp, pVertices, pIndices, m_numVertices);
pVertices += 4 * 8;
Expand All @@ -87,7 +89,7 @@ MMGeometryGL::MMGeometryGL(MMSurfaceNet* surfaceNet)
}

// Left-bottom edge
if(cellMap->getEdgeQuad(idxVtx, MMCellFlag::Edge::LeftBottomEdge, vertexPositions, labelsTmp) == true)
if(cellMap->getEdgeQuad(idxVtx, MMCellFlag::Edge::LeftBottomEdge, vertexPositions, labelsTmp, cellIndices) == true)
{
MMGeometryGL::makeGLQuad(vertexPositions, labelsTmp, pVertices, pIndices, m_numVertices);
pVertices += 4 * 8;
Expand All @@ -97,7 +99,7 @@ MMGeometryGL::MMGeometryGL(MMSurfaceNet* surfaceNet)
}

// Left-back edge
if(cellMap->getEdgeQuad(idxVtx, MMCellFlag::Edge::LeftBackEdge, vertexPositions, labelsTmp) == true)
if(cellMap->getEdgeQuad(idxVtx, MMCellFlag::Edge::LeftBackEdge, vertexPositions, labelsTmp, cellIndices) == true)
{
MMGeometryGL::makeGLQuad(vertexPositions, labelsTmp, pVertices, pIndices, m_numVertices);
pVertices += 4 * 8;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,27 +70,29 @@ MMGeometryOBJ::MMGeometryOBJ(MMSurfaceNet* surfaceNet)
// Create temporary storage for cell quads which are constructed around edges
// crossed by the surface. Handle 3 edges per cell. The other 9 cell edges will
// be handled when neighboring cells that share edges with this cell are visited.
std::array<int32_t, 3> cellIndices = {0, 0, 0};

for(int idxVtx = 0; idxVtx < cellMap->numVertices(); idxVtx++)
{
int vertexIndices[4];
int32_t quadLabels[2];

// Back-bottom edge
if(cellMap->getEdgeQuad(idxVtx, MMCellFlag::Edge::BackBottomEdge, vertexIndices, quadLabels) == true)
if(cellMap->getEdgeQuad(idxVtx, MMCellFlag::Edge::BackBottomEdge, vertexIndices, quadLabels, cellIndices) == true)
{
MMQuad quad(vertexIndices, quadLabels);
m_quads.push_back(quad);
}

// Left-bottom edge
if(cellMap->getEdgeQuad(idxVtx, MMCellFlag::Edge::LeftBottomEdge, vertexIndices, quadLabels) == true)
if(cellMap->getEdgeQuad(idxVtx, MMCellFlag::Edge::LeftBottomEdge, vertexIndices, quadLabels, cellIndices) == true)
{
MMQuad quad(vertexIndices, quadLabels);
m_quads.push_back(quad);
}

// Left-back edge
if(cellMap->getEdgeQuad(idxVtx, MMCellFlag::Edge::LeftBackEdge, vertexIndices, quadLabels) == true)
if(cellMap->getEdgeQuad(idxVtx, MMCellFlag::Edge::LeftBackEdge, vertexIndices, quadLabels, cellIndices) == true)
{
MMQuad quad(vertexIndices, quadLabels);
m_quads.push_back(quad);
Expand Down
Loading
Loading