Skip to content

Commit 1e274d7

Browse files
committed
feat(mesh-filters): geogram conversion test pipeline
1 parent f0bf6a8 commit 1e274d7

File tree

11 files changed

+499
-5
lines changed

11 files changed

+499
-5
lines changed

include/itkOutputMesh.h

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "itkPipeline.h"
2222
#include "itkMeshConvertPixelTraits.h"
2323
#include "itkMesh.h"
24+
#include "itkQuadEdgeMesh.h"
2425

2526
#ifndef ITK_WASM_NO_MEMORY_IO
2627
#include "itkWasmExports.h"
@@ -144,6 +145,107 @@ class ITK_TEMPLATE_EXPORT OutputMesh
144145
std::string m_Identifier;
145146
};
146147

148+
// write a template specialization for itk::QuadEdgeMesh that does not assume
149+
// that the points, etc. are stored in itk::VectorContainers
150+
template <typename TPixel, unsigned int VDimension>
151+
class OutputMesh<itk::QuadEdgeMesh<TPixel, VDimension>>
152+
{
153+
public:
154+
using MeshType = itk::QuadEdgeMesh<TPixel, VDimension>;
155+
156+
void Set(const MeshType * mesh) {
157+
this->m_Mesh = mesh;
158+
}
159+
160+
const MeshType * Get() const {
161+
return this->m_Mesh.GetPointer();
162+
}
163+
164+
/** FileName or output index. */
165+
void SetIdentifier(const std::string & identifier)
166+
{
167+
this->m_Identifier = identifier;
168+
}
169+
const std::string & GetIdentifier() const
170+
{
171+
return this->m_Identifier;
172+
}
173+
174+
OutputMesh() = default;
175+
~OutputMesh() {
176+
if(wasm::Pipeline::get_use_memory_io())
177+
{
178+
#ifndef ITK_WASM_NO_MEMORY_IO
179+
if (!this->m_Mesh.IsNull() && !this->m_Identifier.empty())
180+
{
181+
using MeshToWasmMeshFilterType = MeshToWasmMeshFilter<MeshType>;
182+
auto meshToWasmMeshFilter = MeshToWasmMeshFilterType::New();
183+
meshToWasmMeshFilter->SetInput(this->m_Mesh);
184+
meshToWasmMeshFilter->Update();
185+
auto wasmMesh = meshToWasmMeshFilter->GetOutput();
186+
const auto index = std::stoi(this->m_Identifier);
187+
setMemoryStoreOutputDataObject(0, index, wasmMesh);
188+
189+
if (this->m_Mesh->GetNumberOfPoints() > 0)
190+
{
191+
const auto pointsAddress = reinterpret_cast< size_t >( &(wasmMesh->GetPointsBufferContainer().at(0)) );
192+
const auto pointsSize = wasmMesh->GetPointsBufferContainer().size() * sizeof(typename MeshType::PointIdentifier);
193+
setMemoryStoreOutputArray(0, index, 0, pointsAddress, pointsSize);
194+
}
195+
196+
// if (this->m_Mesh->GetNumberOfCells() > 0)
197+
// {
198+
// const auto cellsAddress = reinterpret_cast< size_t >( &(wasmMesh->GetCellBuffer()->at(0)) );
199+
// const auto cellsSize = wasmMesh->GetCellBuffer()->Size() * sizeof(typename MeshType::CellIdentifier);
200+
// setMemoryStoreOutputArray(0, index, 1, cellsAddress, cellsSize);
201+
// }
202+
203+
// if (this->m_Mesh->GetPointData() != nullptr && this->m_Mesh->GetPointData()->Size() > 0)
204+
// {
205+
// using PointPixelType = typename MeshType::PixelType;
206+
// using ConvertPointPixelTraits = MeshConvertPixelTraits<PointPixelType>;
207+
// const auto pointDataAddress = reinterpret_cast< size_t >( &(wasmMesh->GetMesh()->GetPointData()->at(0)) );
208+
// const auto pointDataSize = wasmMesh->GetMesh()->GetPointData()->Size() * sizeof(typename ConvertPointPixelTraits::ComponentType) * ConvertPointPixelTraits::GetNumberOfComponents();
209+
// setMemoryStoreOutputArray(0, index, 2, pointDataAddress, pointDataSize);
210+
// }
211+
212+
// if (this->m_Mesh->GetCellData() != nullptr && this->m_Mesh->GetCellData()->Size() > 0)
213+
// {
214+
// using CellPixelType = typename MeshType::CellPixelType;
215+
// using ConvertCellPixelTraits = MeshConvertPixelTraits<CellPixelType>;
216+
// const auto cellDataAddress = reinterpret_cast< size_t >( &(wasmMesh->GetMesh()->GetCellData()->at(0)) );
217+
// const auto cellDataSize = wasmMesh->GetMesh()->GetCellData()->Size() * sizeof(typename ConvertCellPixelTraits::ComponentType) * ConvertCellPixelTraits::GetNumberOfComponents();
218+
// setMemoryStoreOutputArray(0, index, 3, cellDataAddress, cellDataSize);
219+
// }
220+
}
221+
#else
222+
std::cerr << "Memory IO not supported" << std::endl;
223+
abort();
224+
#endif
225+
}
226+
else
227+
{
228+
#ifndef ITK_WASM_NO_FILESYSTEM_IO
229+
if (!this->m_Mesh.IsNull() && !this->m_Identifier.empty())
230+
{
231+
using MeshWriterType = itk::MeshFileWriter<MeshType>;
232+
auto meshWriter = MeshWriterType::New();
233+
meshWriter->SetFileName(this->m_Identifier);
234+
meshWriter->SetInput(this->m_Mesh);
235+
meshWriter->Update();
236+
}
237+
#else
238+
std::cerr << "Filesystem IO not supported" << std::endl;
239+
abort();
240+
#endif
241+
}
242+
}
243+
protected:
244+
typename MeshType::ConstPointer m_Mesh;
245+
246+
std::string m_Identifier;
247+
};
248+
147249
template <typename TMesh>
148250
bool lexical_cast(const std::string &input, OutputMesh<TMesh> &outputMesh)
149251
{

include/itkWasmMesh.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "itkWasmDataObject.h"
2222
#include "itkVectorContainer.h"
23+
#include "itkQuadEdgeMesh.h"
2324

2425
namespace itk
2526
{
@@ -80,6 +81,54 @@ class ITK_TEMPLATE_EXPORT WasmMesh : public WasmDataObject
8081
typename CellBufferContainerType::Pointer m_CellBufferContainer;
8182
};
8283

84+
template <typename TPixel, unsigned int VDimension>
85+
class WasmMesh<QuadEdgeMesh<TPixel, VDimension>> : public WasmDataObject
86+
{
87+
public:
88+
ITK_DISALLOW_COPY_AND_MOVE(WasmMesh);
89+
90+
/** Standard class type aliases. */
91+
using Self = WasmMesh;
92+
using Superclass = WasmDataObject;
93+
using Pointer = SmartPointer<Self>;
94+
using ConstPointer = SmartPointer<const Self>;
95+
96+
itkNewMacro(Self);
97+
/** Run-time type information (and related methods). */
98+
itkTypeMacro(WasmMesh, WasmDataObject);
99+
100+
using MeshType = QuadEdgeMesh<TPixel, VDimension>;
101+
102+
using PointIdentifier = typename MeshType::PointIdentifier;
103+
using CellIdentifier = typename MeshType::CellIdentifier;
104+
105+
using PointsBufferContainerType = std::vector<PointIdentifier>;
106+
using CellBufferContainerType = std::vector<CellIdentifier>;
107+
using PointDataBufferContainerType = std::vector<typename MeshType::PointDataContainer::Element>;
108+
using CellDataBufferContainerType = std::vector<typename MeshType::CellDataContainer::Element>;
109+
110+
void SetMesh(const MeshType * mesh);
111+
112+
const MeshType * GetMesh() const {
113+
return static_cast< const MeshType * >(this->GetDataObject());
114+
}
115+
116+
const PointsBufferContainerType & GetPointsBufferContainer() const {
117+
return this->m_PointsBufferContainer;
118+
}
119+
120+
const CellBufferContainerType & GetCellBufferContainer() const {
121+
return this->m_CellBufferContainer;
122+
}
123+
124+
WasmMesh() = default;
125+
~WasmMesh() override = default;
126+
127+
PointsBufferContainerType m_PointsBufferContainer;
128+
CellBufferContainerType m_CellBufferContainer;
129+
};
130+
131+
83132
} // namespace itk
84133

85134
#ifndef ITK_MANUAL_INSTANTIATION

include/itkWasmMesh.hxx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,27 @@ WasmMesh<TMesh>
3232
this->SetDataObject(const_cast<MeshType *>(mesh));
3333
}
3434

35+
template <typename TPixel, unsigned int VDimension>
36+
void
37+
WasmMesh<itk::QuadEdgeMesh<TPixel, VDimension>>
38+
::SetMesh(const MeshType * mesh)
39+
{
40+
m_PointsBufferContainer.resize(mesh->GetNumberOfPoints() * VDimension);
41+
for (unsigned int i = 0; i < mesh->GetNumberOfPoints(); ++i)
42+
{
43+
const auto & point = mesh->GetPoint(i);
44+
for (unsigned int d = 0; d < VDimension; ++d)
45+
{
46+
m_PointsBufferContainer[i * VDimension + d] = point[d];
47+
}
48+
}
49+
// m_CellBufferContainer.reserve(mesh->GetNumberOfCells() * 5);
50+
auto cellsArray = const_cast<MeshType *>(mesh)->GetCellsArray();
51+
52+
this->SetDataObject(const_cast<MeshType *>(mesh));
53+
}
54+
55+
3556
} // end namespace itk
3657

3758
#endif

itk_wasm_env.bash

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ export ITK_WASM_DICOM_TEST_DATA_URLS=${ITK_WASM_DICOM_TEST_DATA_URLS:-$(cat pack
4040
export ITK_WASM_DOWNSAMPLE_TEST_DATA_HASH=${ITK_WASM_DOWNSAMPLE_TEST_DATA_HASH:-$(cat packages/downsample/package.json | jq -e -r '."itk-wasm"."test-data-hash"')}
4141
export ITK_WASM_DOWNSAMPLE_TEST_DATA_URLS=${ITK_WASM_DOWNSAMPLE_TEST_DATA_URLS:-$(cat packages/downsample/package.json | jq -e -r '."itk-wasm"."test-data-urls" | join(" ")')}
4242

43+
export ITK_WASM_MESH_FILTERS_TEST_DATA_HASH=${ITK_WASM_MESH_FILTERS_TEST_DATA_HASH:-$(cat packages/mesh-filters/package.json | jq -e -r '."itk-wasm"."test-data-hash"')}
44+
export ITK_WASM_MESH_FILTERS_TEST_DATA_URLS=${ITK_WASM_MESH_FILTERS_TEST_DATA_URLS:-$(cat packages/mesh-filters/package.json | jq -e -r '."itk-wasm"."test-data-urls" | join(" ")')}
45+
4346
export ITK_WASM_MESH_IO_TEST_DATA_HASH=${ITK_WASM_MESH_IO_TEST_DATA_HASH:-$(cat packages/mesh-io/package.json | jq -e -r '."itk-wasm"."test-data-hash"')}
4447
export ITK_WASM_MESH_IO_TEST_DATA_URLS=${ITK_WASM_MESH_IO_TEST_DATA_URLS:-$(cat packages/mesh-io/package.json | jq -e -r '."itk-wasm"."test-data-urls" | join(" ")')}
4548

packages/mesh-filters/.gitignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
emscripten-build/
2+
wasi-build/
3+
python/itkwasm-mesh-filters-wasi/itkwasm_mesh-filters_wasi/wasm_modules/
4+
typescript/dist/
5+
typescript/test/browser/demo-app/public/
6+
typescript/demo-app/
7+
typescript/src/version.ts
8+
test/pyodide-dispatch.tar.bz2
9+
test/pyodide-emscripten.tar.bz2
10+
test/data.tar.gz
11+
test/data/baseline/
12+
test/data/python/
13+
python/itkwasm-mesh-filters-emscripten/dist/
14+
python/itkwasm-mesh-filters-wasi/dist/
15+
python/itkwasm-mesh-filters/dist/
16+
pyodide/

packages/mesh-filters/.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
git-checks=false

packages/mesh-filters/CMakeLists.txt

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
cmake_minimum_required(VERSION 3.16)
2+
project(itkwasm-mesh-filters LANGUAGES CXX)
3+
4+
set(CMAKE_CXX_STANDARD 20)
5+
6+
if(EMSCRIPTEN)
7+
set(io_components
8+
)
9+
elseif(WASI)
10+
set(io_components
11+
ITKIOOFF
12+
)
13+
else()
14+
set(io_components
15+
ITKMeshIO
16+
)
17+
endif()
18+
19+
find_package(ITK REQUIRED
20+
COMPONENTS
21+
WebAssemblyInterface
22+
ITKQuadEdgeMeshFiltering
23+
${io_components}
24+
)
25+
include(${ITK_USE_FILE})
26+
27+
include(FetchContent)
28+
29+
set(PMP_BUILD_DOCS OFF)
30+
set(PMP_BUILD_EXAMPLES OFF)
31+
set(PMP_BUILD_REGRESSIONS OFF)
32+
set(PMP_BUILD_TESTS OFF)
33+
set(PMP_BUILD_VIS OFF)
34+
set(PMP_INSTALL OFF)
35+
36+
set(PMP_GIT_REPOSITORY "https://github.com/pmp-library/pmp-library.git")
37+
# v3.0.0
38+
set(PMP_GIT_TAG "f2fb04f4a4188a5c1ab137e83b96e62fa99c639f")
39+
set(BUILD_SHARED_LIBS OFF)
40+
FetchContent_Declare(
41+
pmp
42+
GIT_REPOSITORY ${PMP_GIT_REPOSITORY}
43+
GIT_TAG ${PMP_GIT_TAG}
44+
GIT_SHALLOW TRUE
45+
)
46+
47+
if (POLICY CMP0077)
48+
cmake_policy(SET CMP0077 NEW)
49+
endif()
50+
set(GEOGRAM_WITH_GARGATUA OFF CACHE BOOL "64-bit indices")
51+
set(GEOGRAM_WITH_GRAPHICS OFF CACHE BOOL "Viewers and geogram_gfx library")
52+
set(GEOGRAM_WITH_HLBFGS OFF CACHE BOOL "HLBFGS non-linear solver library")
53+
set(GEOGRAM_WITH_LUA OFF CACHE BOOL "Lua scripting")
54+
set(GEOGRAM_WITH_TBB OFF CACHE BOOL "Intel TBB")
55+
set(GEOGRAM_WITH_TETGEN OFF CACHE BOOL "Tetrahedral mesh generation (Hang Si's TetGen)")
56+
set(GEOGRAM_WITH_TRIANGLE OFF CACHE BOOL "Triangle mesher (Jonathan Shewchuk's Triangle)")
57+
58+
set(GEOGRAM_GIT_REPOSITORY "https://github.com/BrunoLevy/geogram.git")
59+
# v1.9.1
60+
set(GEOGRAM_GIT_TAG "fd3db7f141e570ebc68585e15d01a2f2c8ddb02e")
61+
set(BUILD_SHARED_LIBS OFF)
62+
FetchContent_Declare(
63+
geogram
64+
GIT_REPOSITORY ${GEOGRAM_GIT_REPOSITORY}
65+
GIT_TAG ${GEOGRAM_GIT_TAG}
66+
GIT_SHALLOW TRUE
67+
)
68+
69+
FetchContent_MakeAvailable(pmp geogram)
70+
include_directories(${pmp_SOURCE_DIR}/src)
71+
72+
foreach(pipeline geogram-conversion)
73+
# foreach(pipeline mesh-filters mesh-filters-sigma gaussian-kernel-radius mesh-filters-bin-shrink mesh-filters-label-image)
74+
add_executable(${pipeline} ${pipeline}.cxx)
75+
target_link_libraries(${pipeline} PUBLIC ${ITK_LIBRARIES} pmp)
76+
target_include_directories(${pipeline} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
77+
endforeach()
78+
79+
enable_testing()
80+
add_test(NAME geogram-conversion
81+
COMMAND geogram-conversion
82+
${CMAKE_CURRENT_SOURCE_DIR}/test/data/input/suzanne.off
83+
${CMAKE_CURRENT_BINARY_DIR}/suzanne-geogram.off
84+
)
85+
# # Interesting backtrace on exit
86+
# if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
87+
# add_test(NAME mesh-filters
88+
# COMMAND mesh-filters
89+
# ${CMAKE_CURRENT_SOURCE_DIR}/test/data/input/cthead1.png
90+
# ${CMAKE_CURRENT_BINARY_DIR}/cthead1_mesh-filtersd.png
91+
# --shrink-factors 2 2
92+
# )
93+
# endif()
94+
95+
# add_test(NAME mesh-filters-sigma
96+
# COMMAND mesh-filters-sigma
97+
# ${CMAKE_CURRENT_BINARY_DIR}/mesh-filters-sigma.json
98+
# --shrink-factors 2 4
99+
# )
100+
101+
# add_test(NAME gaussian-kernel-radius
102+
# COMMAND gaussian-kernel-radius
103+
# ${CMAKE_CURRENT_BINARY_DIR}/gaussian-kernel-radius.json
104+
# --size 64 64 32
105+
# --sigma 2.0 4.0 2.0
106+
# )
107+
108+
# add_test(NAME mesh-filters-bin-shrink
109+
# COMMAND mesh-filters-bin-shrink
110+
# ${CMAKE_CURRENT_SOURCE_DIR}/test/data/input/cthead1.png
111+
# ${CMAKE_CURRENT_BINARY_DIR}/cthead1_mesh-filtersd_bin_shrink.png
112+
# --shrink-factors 2 2
113+
# )
114+
115+
# add_test(NAME mesh-filters-label-image
116+
# COMMAND mesh-filters-label-image
117+
# ${CMAKE_CURRENT_SOURCE_DIR}/test/data/input/2th_cthead1.png
118+
# ${CMAKE_CURRENT_BINARY_DIR}/cthead1_mesh-filtersd_label_image.png
119+
# --shrink-factors 2 2
120+
# )

0 commit comments

Comments
 (0)