-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FILTER: Add WriteNodesAndElementsFiles filter (#1168)
Signed-off-by: Joey Kleingers <[email protected]>
- Loading branch information
1 parent
1135e27
commit a70dd76
Showing
8 changed files
with
799 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
src/Plugins/SimplnxCore/docs/WriteNodesAndElementsFilesFilter.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Write Nodes and Elements File(s) | ||
|
||
## Group (Subgroup) | ||
|
||
IO (Output) | ||
|
||
## Description | ||
|
||
This **Filter** exports geometric data into structured text files. It allows users to save the following: | ||
|
||
1. Node Data (Vertices): Export the coordinates of points that define the geometry. | ||
2. Element Data (Connectivity): Export the node indices that make up the edges, faces, or volumes of the geometry. | ||
|
||
The filter gives the user the option to export a node file, element file, or both. It also allows the user to decide whether or not to number the nodes and elements and whether or not to include headers for the node and element files. | ||
|
||
% Auto generated parameter table will be inserted here | ||
|
||
## License & Copyright | ||
|
||
Please see the description file distributed with this **Plugin** | ||
|
||
## DREAM3D-NX Help | ||
|
||
If you need help, need to file a bug report or want to request a new feature, please head over to the [DREAM3DNX-Issues](https://github.com/BlueQuartzSoftware/DREAM3DNX-Issues/discussions) GitHub site where the community of DREAM3D-NX users can help answer your questions. |
196 changes: 196 additions & 0 deletions
196
src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteNodesAndElementsFiles.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
#include "WriteNodesAndElementsFiles.hpp" | ||
|
||
#include "simplnx/DataStructure/DataArray.hpp" | ||
#include "simplnx/DataStructure/Geometry/EdgeGeom.hpp" | ||
#include "simplnx/DataStructure/Geometry/HexahedralGeom.hpp" | ||
#include "simplnx/DataStructure/Geometry/QuadGeom.hpp" | ||
#include "simplnx/DataStructure/Geometry/TetrahedralGeom.hpp" | ||
#include "simplnx/DataStructure/Geometry/TriangleGeom.hpp" | ||
#include "simplnx/DataStructure/Geometry/VertexGeom.hpp" | ||
#include "simplnx/SIMPLNXVersion.hpp" | ||
#include "simplnx/Utilities/StringUtilities.hpp" | ||
|
||
#include <algorithm> | ||
#include <filesystem> | ||
|
||
namespace fs = std::filesystem; | ||
|
||
using namespace nx::core; | ||
|
||
namespace | ||
{ | ||
template <typename T> | ||
void WriteValue(std::ofstream& file, const T& value) | ||
{ | ||
if constexpr(std::is_floating_point<T>::value) | ||
{ | ||
// For floating-point numbers, use up to 4 decimal places | ||
file << std::fixed << std::setprecision(4) << value; | ||
} | ||
else | ||
{ | ||
// For non-floating-point types, reset to default format with no precision | ||
file << std::defaultfloat << std::setprecision(0) << value; | ||
} | ||
} | ||
|
||
template <typename T> | ||
Result<> WriteFile(const fs::path& outputFilePath, const DataArray<T>& array, bool includeArrayHeaders, std::vector<std::string_view> arrayHeaders, bool numberRows, bool includeComponentCount) | ||
{ | ||
std::ofstream file(outputFilePath.string()); | ||
if(!file.is_open()) | ||
{ | ||
return MakeErrorResult(to_underlying(WriteNodesAndElementsFiles::ErrorCodes::FailedToOpenOutputFile), fmt::format("Failed to open output file \"{}\".", outputFilePath.string())); | ||
} | ||
|
||
file << fmt::format("# This file was created by simplnx v{}", Version::Complete()) << std::endl; | ||
|
||
if(includeArrayHeaders) | ||
{ | ||
WriteValue(file, StringUtilities::join(arrayHeaders, " ")); | ||
file << std::endl; | ||
} | ||
usize numComps = array.getNumberOfComponents(); | ||
for(usize i = 0; i < array.getNumberOfTuples(); i++) | ||
{ | ||
if(numberRows) | ||
{ | ||
WriteValue(file, i); | ||
file << " "; | ||
} | ||
|
||
if(includeComponentCount) | ||
{ | ||
WriteValue(file, numComps); | ||
file << " "; | ||
} | ||
|
||
for(usize j = 0; j < numComps; j++) | ||
{ | ||
WriteValue(file, array[i * numComps + j]); | ||
if(j != numComps - 1) | ||
{ | ||
file << " "; | ||
} | ||
} | ||
file << std::endl; | ||
} | ||
|
||
return {}; | ||
} | ||
} // namespace | ||
|
||
// ----------------------------------------------------------------------------- | ||
WriteNodesAndElementsFiles::WriteNodesAndElementsFiles(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, | ||
WriteNodesAndElementsFilesInputValues* inputValues) | ||
: m_DataStructure(dataStructure) | ||
, m_InputValues(inputValues) | ||
, m_ShouldCancel(shouldCancel) | ||
, m_MessageHandler(mesgHandler) | ||
{ | ||
} | ||
|
||
// ----------------------------------------------------------------------------- | ||
WriteNodesAndElementsFiles::~WriteNodesAndElementsFiles() noexcept = default; | ||
|
||
// ----------------------------------------------------------------------------- | ||
const std::atomic_bool& WriteNodesAndElementsFiles::getCancel() | ||
{ | ||
return m_ShouldCancel; | ||
} | ||
|
||
// ----------------------------------------------------------------------------- | ||
void WriteNodesAndElementsFiles::sendMessage(const std::string& message) | ||
{ | ||
m_MessageHandler(IFilter::Message::Type::Info, message); | ||
} | ||
|
||
// ----------------------------------------------------------------------------- | ||
Result<> WriteNodesAndElementsFiles::operator()() | ||
{ | ||
auto& iNodeGeometry = m_DataStructure.getDataRefAs<INodeGeometry0D>(m_InputValues->SelectedGeometryPath); | ||
auto geomType = iNodeGeometry.getGeomType(); | ||
UInt64Array* cellsArray = nullptr; | ||
|
||
switch(geomType) | ||
{ | ||
case IGeometry::Type::Edge: { | ||
auto& geom = m_DataStructure.getDataRefAs<EdgeGeom>(m_InputValues->SelectedGeometryPath); | ||
cellsArray = geom.getEdges(); | ||
break; | ||
} | ||
case IGeometry::Type::Triangle: { | ||
auto& geom = m_DataStructure.getDataRefAs<TriangleGeom>(m_InputValues->SelectedGeometryPath); | ||
cellsArray = geom.getFaces(); | ||
break; | ||
} | ||
case IGeometry::Type::Quad: { | ||
auto& geom = m_DataStructure.getDataRefAs<QuadGeom>(m_InputValues->SelectedGeometryPath); | ||
cellsArray = geom.getFaces(); | ||
break; | ||
} | ||
case IGeometry::Type::Tetrahedral: { | ||
auto& geom = m_DataStructure.getDataRefAs<TetrahedralGeom>(m_InputValues->SelectedGeometryPath); | ||
cellsArray = geom.getPolyhedra(); | ||
break; | ||
} | ||
case IGeometry::Type::Hexahedral: { | ||
auto& geom = m_DataStructure.getDataRefAs<HexahedralGeom>(m_InputValues->SelectedGeometryPath); | ||
cellsArray = geom.getPolyhedra(); | ||
break; | ||
} | ||
case IGeometry::Type::Vertex: { | ||
break; | ||
} | ||
case IGeometry::Type::Image: | ||
return MakeErrorResult(to_underlying(ErrorCodes::UnsupportedGeometryType), fmt::format("The Image geometry type is not supported by this filter. Please choose another geometry.")); | ||
case IGeometry::Type::RectGrid: { | ||
return MakeErrorResult(to_underlying(ErrorCodes::UnsupportedGeometryType), fmt::format("The Rectilinear Grid geometry type is not supported by this filter. Please choose another geometry.")); | ||
} | ||
} | ||
|
||
const Float32Array& vertices = iNodeGeometry.getVerticesRef(); | ||
|
||
if(m_InputValues->WriteNodeFile) | ||
{ | ||
std::vector<std::string> arrayHeaders; | ||
if(m_InputValues->NumberNodes) | ||
{ | ||
arrayHeaders.push_back("NODE_NUM"); | ||
} | ||
arrayHeaders.insert(arrayHeaders.end(), {"X", "Y", "Z"}); | ||
|
||
std::vector<std::string_view> arrayHeadersViews(arrayHeaders.size()); | ||
std::transform(arrayHeaders.begin(), arrayHeaders.end(), arrayHeadersViews.begin(), [](const std::string& s) { return std::string_view(s); }); | ||
auto result = WriteFile(m_InputValues->NodeFilePath, vertices, m_InputValues->IncludeNodeFileHeader, arrayHeadersViews, m_InputValues->NumberNodes, false); | ||
if(result.invalid()) | ||
{ | ||
return result; | ||
} | ||
} | ||
|
||
if(m_InputValues->WriteElementFile && geomType != IGeometry::Type::Vertex) | ||
{ | ||
std::vector<std::string> arrayHeaders; | ||
if(m_InputValues->NumberElements) | ||
{ | ||
arrayHeaders.push_back("ELEMENT_NUM"); | ||
} | ||
arrayHeaders.push_back("NUM_VERTS_IN_ELEMENT"); | ||
for(usize i = 0; i < cellsArray->getNumberOfComponents(); i++) | ||
{ | ||
std::string vertexHeader = fmt::format("V{}_Index", i); | ||
arrayHeaders.push_back(vertexHeader); | ||
} | ||
|
||
std::vector<std::string_view> arrayHeadersViews(arrayHeaders.size()); | ||
std::transform(arrayHeaders.begin(), arrayHeaders.end(), arrayHeadersViews.begin(), [](const std::string& s) { return std::string_view(s); }); | ||
auto result = WriteFile(m_InputValues->ElementFilePath, *cellsArray, m_InputValues->IncludeElementFileHeader, arrayHeadersViews, m_InputValues->NumberElements, true); | ||
if(result.invalid()) | ||
{ | ||
return result; | ||
} | ||
} | ||
|
||
return {}; | ||
} |
66 changes: 66 additions & 0 deletions
66
src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/WriteNodesAndElementsFiles.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
#pragma once | ||
|
||
#include "SimplnxCore/SimplnxCore_export.hpp" | ||
|
||
#include "simplnx/DataStructure/DataPath.hpp" | ||
#include "simplnx/DataStructure/DataStructure.hpp" | ||
#include "simplnx/Filter/IFilter.hpp" | ||
#include "simplnx/Parameters/ArraySelectionParameter.hpp" | ||
#include "simplnx/Parameters/FileSystemPathParameter.hpp" | ||
#include "simplnx/Parameters/NumberParameter.hpp" | ||
#include "simplnx/Parameters/StringParameter.hpp" | ||
|
||
namespace fs = std::filesystem; | ||
|
||
namespace nx::core | ||
{ | ||
|
||
struct SIMPLNXCORE_EXPORT WriteNodesAndElementsFilesInputValues | ||
{ | ||
DataPath SelectedGeometryPath; | ||
bool WriteNodeFile; | ||
bool NumberNodes; | ||
bool IncludeNodeFileHeader; | ||
fs::path NodeFilePath; | ||
bool WriteElementFile; | ||
bool NumberElements; | ||
bool IncludeElementFileHeader; | ||
fs::path ElementFilePath; | ||
}; | ||
|
||
/** | ||
* @class | ||
*/ | ||
class SIMPLNXCORE_EXPORT WriteNodesAndElementsFiles | ||
{ | ||
public: | ||
WriteNodesAndElementsFiles(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, WriteNodesAndElementsFilesInputValues* inputValues); | ||
~WriteNodesAndElementsFiles() noexcept; | ||
|
||
WriteNodesAndElementsFiles(const WriteNodesAndElementsFiles&) = delete; | ||
WriteNodesAndElementsFiles(WriteNodesAndElementsFiles&&) noexcept = delete; | ||
WriteNodesAndElementsFiles& operator=(const WriteNodesAndElementsFiles&) = delete; | ||
WriteNodesAndElementsFiles& operator=(WriteNodesAndElementsFiles&&) noexcept = delete; | ||
|
||
enum class ErrorCodes : int64 | ||
{ | ||
NoFileWriterChosen = -134, | ||
FailedToOpenOutputFile = -135, | ||
VertexGeomHasNoElements = -136, | ||
UnsupportedGeometryType = -137 | ||
}; | ||
|
||
Result<> operator()(); | ||
|
||
const std::atomic_bool& getCancel(); | ||
|
||
void sendMessage(const std::string& message); | ||
|
||
private: | ||
DataStructure& m_DataStructure; | ||
const WriteNodesAndElementsFilesInputValues* m_InputValues = nullptr; | ||
const std::atomic_bool& m_ShouldCancel; | ||
const IFilter::MessageHandler& m_MessageHandler; | ||
}; | ||
|
||
} // namespace nx::core |
Oops, something went wrong.