loop-cgal 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,54 @@
1
+ name: "🐍 Build and upload Conda packages"
2
+ on:
3
+ workflow_dispatch:
4
+ jobs:
5
+ conda-deploy:
6
+ name: Building conda package for python ${{ matrix.os }})
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ fail-fast: false
10
+ matrix:
11
+ python-version: ${{ fromJSON(vars.PYTHON_VERSIONS)}}
12
+ steps:
13
+ - uses: conda-incubator/setup-miniconda@v3
14
+ with:
15
+ auto-update-conda: true
16
+ python-version: ${{ matrix.python-version }}
17
+ - uses: actions/checkout@v4
18
+ - name: update submodules
19
+ run: |
20
+ git submodule update --init --recursive
21
+ - name: Conda build
22
+ env:
23
+ ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_TOKEN }}
24
+ shell: bash -l {0}
25
+ run: |
26
+ conda install -c conda-forge "conda-build<25" scikit-build numpy cython anaconda-client conda-libmamba-solver -y
27
+ conda build -c conda-forge -c loop3d --output-folder conda conda --python ${{matrix.python-version}}
28
+ conda convert -p all conda/linux-64/*.tar.bz2 -f -o conda
29
+ - name: upload artifacts
30
+ uses: actions/upload-artifact@v4
31
+ with:
32
+ name: conda-build-${{ matrix.python-version }}
33
+ path: conda
34
+ upload_to_conda:
35
+ runs-on: ubuntu-latest
36
+ needs: conda-deploy
37
+ strategy:
38
+ fail-fast: false
39
+ matrix:
40
+ python-version: ${{ fromJSON(vars.PYTHON_VERSIONS)}}
41
+ steps:
42
+ - uses: actions/download-artifact@v4
43
+ with:
44
+ name: conda-build-${{ matrix.python-version }}
45
+ path: conda
46
+ - uses: conda-incubator/setup-miniconda@v3
47
+ - name: upload all files to conda-forge
48
+ shell: bash -l {0}
49
+ env:
50
+ ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_TOKEN }}
51
+ run: |
52
+ conda install -c anaconda anaconda-client -y
53
+ anaconda upload --label main conda/*/*.tar.bz2
54
+
@@ -0,0 +1,40 @@
1
+ name: Deploy to PYPI
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ jobs:
6
+
7
+ sdist:
8
+ name: Build sdist
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - uses: actions/setup-python@v5
13
+ - name: Install dependencies
14
+ run: |
15
+ python -m pip install --upgrade pip
16
+ pip install build
17
+ - name: Build sdist
18
+ run: python -m build --sdist
19
+ - uses: actions/upload-artifact@v4
20
+ with:
21
+ name: dist
22
+ path: ./dist/*.tar.gz
23
+
24
+ publish:
25
+ name: Publish wheels to pypi
26
+ runs-on: ubuntu-latest
27
+ permissions:
28
+ # IMPORTANT: this permission is mandatory for trusted publishing
29
+ id-token: write
30
+ needs: sdist
31
+ steps:
32
+ - uses: actions/download-artifact@v4
33
+ with:
34
+ name: dist
35
+ path: dist
36
+ - uses: pypa/gh-action-pypi-publish@release/v1
37
+ with:
38
+ skip-existing: true
39
+ verbose: true
40
+ packages-dir: dist/
@@ -0,0 +1,42 @@
1
+ on:
2
+ push:
3
+ branches:
4
+ - master
5
+ env:
6
+ PACKAGE_NAME: loop_cgal
7
+ permissions:
8
+ contents: write
9
+ pull-requests: write
10
+ issues: write
11
+
12
+ name: release-please
13
+ jobs:
14
+ release-please:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: GoogleCloudPlatform/release-please-action@v4
18
+ id: release
19
+ with:
20
+ path: loop_cgal
21
+
22
+ outputs:
23
+ release_created: ${{ steps.release.outputs.releases_created }}
24
+ package:
25
+ needs: release-please
26
+ if: ${{ needs.release-please.outputs.release_created == 'true'}}
27
+ runs-on: ubuntu-latest
28
+ steps:
29
+ - name: Trigger build for pypi and upload
30
+ run: |
31
+ curl -X POST \
32
+ -H "Authorization: token ${{ secrets.GH_PAT }}" \
33
+ -H "Accept: application/vnd.github.v3+json" \
34
+ https://api.github.com/repos/Loop3d/${{env.PACKAGE_NAME}}/actions/workflows/pypi.yml/dispatches \
35
+ -d '{"ref":"master"}'
36
+ - name: Trigger build for conda and upload
37
+ run: |
38
+ curl -X POST \
39
+ -H "Authorization: token ${{ secrets.GH_PAT }}" \
40
+ -H "Accept: application/vnd.github.v3+json" \
41
+ https://api.github.com/repos/Loop3d/${{env.PACKAGE_NAME}}/actions/workflows/conda.yml/dispatches \
42
+ -d '{"ref":"master"}'
@@ -0,0 +1,42 @@
1
+ # C++ artifacts
2
+ *.o
3
+ *.so
4
+ *.a
5
+ *.lib
6
+ *.dll
7
+ *.dylib
8
+ *.exe
9
+ *.out
10
+
11
+ # Python
12
+ __pycache__/
13
+ *.py[cod]
14
+ *.egg
15
+ *.egg-info/
16
+ dist/
17
+ build/
18
+ _skbuild/
19
+ *.whl
20
+
21
+ # IDE and editors
22
+ .vscode/
23
+ .idea/
24
+ *.swp
25
+ *~
26
+
27
+ # CMake
28
+ CMakeFiles/
29
+ CMakeCache.txt
30
+ cmake_install.cmake
31
+ Makefile
32
+ *.cmake
33
+ !CMakeLists.txt
34
+
35
+ # Project specific
36
+ _deps/
37
+ external/
38
+ third_party/
39
+
40
+ # OS specific
41
+ .DS_Store
42
+ Thumbs.db
@@ -0,0 +1,40 @@
1
+ # Minimum CMake version
2
+ cmake_minimum_required(VERSION 3.15)
3
+
4
+ # Project name and version
5
+ project(loop-cgal VERSION 1.0 LANGUAGES CXX)
6
+
7
+ # Set C++ standard
8
+ set(CMAKE_CXX_STANDARD 17)
9
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
10
+
11
+ # Find CGAL package
12
+ find_package(CGAL REQUIRED)
13
+
14
+ # Add the include directory for your project
15
+ include_directories(${CMAKE_SOURCE_DIR}/src)
16
+
17
+ # Add the executable for standalone testing
18
+ # add_executable(loop-cgal-exe
19
+ # src/marching_cubes.cpp
20
+ # )
21
+
22
+ # Link CGAL to the executable
23
+ # target_link_libraries(loop-cgal-exe PRIVATE CGAL::CGAL)
24
+
25
+ # Find pybind11
26
+ find_package(pybind11 REQUIRED)
27
+
28
+ # Add the Python module
29
+ add_library(loop_cgal MODULE
30
+ loop_cgal/bindings.cpp
31
+ src/clip.cpp
32
+
33
+ )
34
+ target_link_libraries(loop_cgal PRIVATE pybind11::module CGAL::CGAL)
35
+ target_include_directories(loop_cgal PRIVATE ${CMAKE_SOURCE_DIR}/src)
36
+ set_target_properties(loop_cgal PROPERTIES PREFIX "" SUFFIX ".so")
37
+ # Install the Python module to the correct location
38
+ install(TARGETS loop_cgal
39
+ LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/loop_cgal
40
+ )
@@ -0,0 +1,56 @@
1
+ Metadata-Version: 2.2
2
+ Name: loop_cgal
3
+ Version: 0.0.1
4
+ Summary: python bindings for cgal for implicit model meshing
5
+ Author-Email: Lachlan Grose <lachlan.grose@monash.edu>
6
+ Classifier: Development Status :: 4 - Beta
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Programming Language :: Python :: 3 :: Only
9
+ Classifier: Programming Language :: Python :: 3.7
10
+ Classifier: Programming Language :: Python :: 3.8
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Python: >=3.7
16
+ Requires-Dist: pyvista
17
+ Description-Content-Type: text/markdown
18
+
19
+ # Loop-cgal
20
+
21
+ Loop-cgal is a Python package for mesh processing operations using the CGAL (Computational Geometry Algorithms Library). It is designed for efficient geometric computations using pyvista objects.
22
+
23
+ ## Features
24
+
25
+ - Python bindings for CGAL using `pybind11`.
26
+ - Current features:
27
+ - clipping of 3D triangular surfaces
28
+ - Future features:
29
+ - Marching cubes algorithm for isosurface extraction
30
+ - Boolean operations on marching cube meshes.
31
+
32
+ ## Installation
33
+
34
+ ### Prerequisites
35
+
36
+ - C++17 or later
37
+ - Python 3.11 or later
38
+ - CGAL library
39
+ - Boost library
40
+ - CMake 3.15 or later
41
+ - pybind11
42
+ - scikit-build
43
+ - pyvista
44
+
45
+ ### Build and Install
46
+
47
+ 1. Clone the repository:
48
+ ```bash
49
+ git clone https://github.com/Loop3D/loop-cgal.git
50
+ cd loop-cgal
51
+ pip install .
52
+ ```
53
+ 2. Alternatively, you can install it directly from PyPI:
54
+ ```bash
55
+ pip install loop-cgal
56
+ ```
@@ -0,0 +1,38 @@
1
+ # Loop-cgal
2
+
3
+ Loop-cgal is a Python package for mesh processing operations using the CGAL (Computational Geometry Algorithms Library). It is designed for efficient geometric computations using pyvista objects.
4
+
5
+ ## Features
6
+
7
+ - Python bindings for CGAL using `pybind11`.
8
+ - Current features:
9
+ - clipping of 3D triangular surfaces
10
+ - Future features:
11
+ - Marching cubes algorithm for isosurface extraction
12
+ - Boolean operations on marching cube meshes.
13
+
14
+ ## Installation
15
+
16
+ ### Prerequisites
17
+
18
+ - C++17 or later
19
+ - Python 3.11 or later
20
+ - CGAL library
21
+ - Boost library
22
+ - CMake 3.15 or later
23
+ - pybind11
24
+ - scikit-build
25
+ - pyvista
26
+
27
+ ### Build and Install
28
+
29
+ 1. Clone the repository:
30
+ ```bash
31
+ git clone https://github.com/Loop3D/loop-cgal.git
32
+ cd loop-cgal
33
+ pip install .
34
+ ```
35
+ 2. Alternatively, you can install it directly from PyPI:
36
+ ```bash
37
+ pip install loop-cgal
38
+ ```
@@ -0,0 +1,35 @@
1
+ import loop_cgal
2
+ import numpy as np
3
+ import pyvista as pv
4
+ from LoopStructural.datatypes import BoundingBox
5
+ def test():
6
+ bb = BoundingBox(np.zeros(3), np.ones(3))
7
+ grid = bb.structured_grid().vtk()
8
+ print(grid)
9
+ grid["scalars"] = grid.points[:,0]
10
+ surface = grid.contour([.5])
11
+ surface_1_tri = surface.faces.reshape(-1, 4)[:, 1:].copy()
12
+ surface_1_verts = surface.points.copy()
13
+ grid["scalars"] = grid.points[:,1]
14
+ surface_2 = grid.contour([.5])
15
+ surface_2_tri = surface_2.faces.reshape(-1, 4)[:, 1:].copy()
16
+ surface_2_verts = surface_2.points.copy()
17
+
18
+ surface_clipped = loop_cgal.clip_pyvista_polydata(
19
+ surface, surface_2
20
+ ) # surface_1_tri, surface_1_verts, surface_2_tri, surface_2_verts
21
+ # )
22
+ print(surface_clipped)
23
+ # print(mesh.vertices.shape)
24
+ # print(surface_1_verts.shape)
25
+ # print(mesh.triangles)
26
+ # print(mesh.triangles, mesh.vertices)
27
+ # surface_clipped = pv.PolyData.from_regular_faces(mesh.vertices, mesh.triangles)
28
+ p = pv.Plotter()
29
+ # p.add_mesh(surface)
30
+ p.add_mesh(surface_2, color="blue", show_edges=True)
31
+ p.add_mesh(surface_clipped, color="red", show_edges=True)
32
+ # p.add_points(mesh.vertices, render_points_as_spheres=True, point_size=5)
33
+ p.show()
34
+ if __name__ == "__main__":
35
+ test()
@@ -0,0 +1,15 @@
1
+ import loop_cgal
2
+ import numpy as np
3
+ def test():
4
+
5
+ X,Y,Z = np.meshgrid(np.linspace(0, 1, 10),
6
+ np.linspace(0, 1, 10),
7
+ np.linspace(0, 1, 10))
8
+
9
+ step_vector = np.array([.1, .1, .1])
10
+ nsteps = np.ones(3)*10
11
+ points, tri = loop_cgal.generate_mesh_from_numpy(Z,np.zeros(3),step_vector,nsteps,.6)
12
+ print("tri", tri)
13
+ print("points", points)
14
+ if __name__ == "__main__":
15
+ test()
@@ -0,0 +1,20 @@
1
+ import loop_cgal
2
+ import numpy as np
3
+
4
+
5
+ def test():
6
+
7
+ X, Y, Z = np.meshgrid(
8
+ np.linspace(0, 1, 10), np.linspace(0, 1, 10), np.linspace(0, 1, 10)
9
+ )
10
+
11
+ step_vector = np.array([0.1, 0.1, 0.1])
12
+ nsteps = np.ones(3) * 10
13
+ result = loop_cgal.compute_optimized_intersection(
14
+ Z,X,0.5,.5,0,0,0,0.1,0.1,0.1
15
+ )
16
+
17
+
18
+
19
+ if __name__ == "__main__":
20
+ test()
@@ -0,0 +1,35 @@
1
+ from .loop_cgal import clip_surface, NumpyMesh
2
+ import pyvista as pv
3
+ import numpy as np
4
+ def clip_pyvista_polydata(
5
+ surface_1: pv.PolyData,
6
+ surface_2: pv.PolyData,
7
+ ) -> pv.PolyData:
8
+ """
9
+ Clip two pyvista PolyData objects using the CGAL library.
10
+
11
+ Parameters
12
+ ----------
13
+ surface_1 : pyvista.PolyData
14
+ The first surface to be clipped.
15
+ surface_2 : pyvista.PolyData
16
+ The second surface to be used for clipping.
17
+
18
+ Returns
19
+ -------
20
+ pyvista.PolyData
21
+ The resulting clipped surface.
22
+ """
23
+ surface_1 = surface_1.triangulate()
24
+ surface_2 = surface_2.triangulate()
25
+ tm = NumpyMesh()
26
+ tm.vertices = np.array(surface_1.points).copy()
27
+ tm.triangles = surface_1.faces.reshape(-1, 4)[:, 1:].copy()
28
+ clipper = NumpyMesh()
29
+ clipper.vertices = np.array(surface_2.points).copy()
30
+ clipper.triangles = surface_2.faces.reshape(-1, 4)[:, 1:].copy()
31
+ mesh = clip_surface(
32
+ tm,
33
+ clipper,
34
+ )
35
+ return pv.PolyData.from_regular_faces(mesh.vertices, mesh.triangles)
@@ -0,0 +1,20 @@
1
+ #include <pybind11/pybind11.h>
2
+ #include <pybind11/stl.h>
3
+
4
+ #include "clip.h" // Include the API implementation
5
+
6
+ namespace py = pybind11;
7
+
8
+ PYBIND11_MODULE(loop_cgal, m)
9
+ {
10
+
11
+ m.def("clip_surface", &clip_surface,
12
+ py::arg("tm"),
13
+ py::arg("clipper"),
14
+ "Clip one surface with another.");
15
+ py::class_<NumpyMesh>(m, "NumpyMesh")
16
+ .def(py::init<>())
17
+ .def_readwrite("vertices", &NumpyMesh::vertices)
18
+ .def_readwrite("triangles", &NumpyMesh::triangles);
19
+
20
+ }
@@ -0,0 +1,85 @@
1
+ [build-system]
2
+ requires = [
3
+ "scikit-build-core>=0.3.3",
4
+ "pybind11>=2.10.0",
5
+ "oldest-supported-numpy",
6
+ ]
7
+ build-backend = "scikit_build_core.build"
8
+
9
+
10
+ [project]
11
+ authors = [{ name = "Lachlan Grose", email = "lachlan.grose@monash.edu" }]
12
+ name = "loop_cgal"
13
+ version = "0.0.1"
14
+ description = "python bindings for cgal for implicit model meshing"
15
+ readme = "README.md"
16
+ requires-python = ">=3.7"
17
+ classifiers = [
18
+ "Development Status :: 4 - Beta",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3 :: Only",
21
+ "Programming Language :: Python :: 3.7",
22
+ "Programming Language :: Python :: 3.8",
23
+ "Programming Language :: Python :: 3.9",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ ]
28
+
29
+ dependencies = ['pyvista']
30
+
31
+ [tool.scikit-build]
32
+ wheel.expand-macos-universal-tags = true
33
+
34
+
35
+
36
+ [tool.cibuildwheel.pyodide]
37
+ environment.CFLAGS = "-fexceptions"
38
+ environment.LDFLAGS = "-fexceptions"
39
+ build-frontend = { name = "build", args = ["--exports", "whole_archive"] }
40
+
41
+ [tool.ruff]
42
+ src = ["src"]
43
+
44
+ [tool.ruff.lint]
45
+ extend-select = [
46
+ "B", # flake8-bugbear
47
+ "I", # isort
48
+ "ARG", # flake8-unused-arguments
49
+ "C4", # flake8-comprehensions
50
+ "EM", # flake8-errmsg
51
+ "ICN", # flake8-import-conventions
52
+ "G", # flake8-logging-format
53
+ "PGH", # pygrep-hooks
54
+ "PIE", # flake8-pie
55
+ "PL", # pylint
56
+ "PT", # flake8-pytest-style
57
+ "PTH", # flake8-use-pathlib
58
+ "RET", # flake8-return
59
+ "RUF", # Ruff-specific
60
+ "SIM", # flake8-simplify
61
+ "T20", # flake8-print
62
+ "UP", # pyupgrade
63
+ "YTT", # flake8-2020
64
+ "EXE", # flake8-executable
65
+ "NPY", # NumPy specific rules
66
+ "PD", # pandas-vet
67
+ ]
68
+ ignore = [
69
+ "PLR09", # Too many X
70
+ "PLR2004", # Magic comparison
71
+ ]
72
+ isort.required-imports = ["from __future__ import annotations"]
73
+
74
+ [tool.ruff.lint.per-file-ignores]
75
+ "tests/**" = ["T20"]
76
+
77
+ [tool.cibuildwheel]
78
+ build = "cp39-* cp310-* cp311-* cp312-* cp313-*"
79
+ skip = "*-win32 *-manylinux_i686 *-musllinux_*"
80
+
81
+ [tool.cibuildwheel.linux]
82
+ before-all = "yum install python3-devel -y"
83
+
84
+ [tool.cibuildwheel.macos]
85
+ archs = ["x86_64", "arm64"]
@@ -0,0 +1,119 @@
1
+ #include "clip.h"
2
+ #include "numpymesh.h"
3
+ #include <CGAL/Simple_cartesian.h>
4
+ #include <CGAL/Polygon_mesh_processing/clip.h>
5
+ #include <CGAL/Surface_mesh.h>
6
+
7
+ NumpyMesh clip_surface(NumpyMesh tm, NumpyMesh clipper)
8
+ {
9
+ auto vertices1_buf = tm.vertices.unchecked<2>();
10
+ auto triangles1_buf = tm.triangles.unchecked<2>();
11
+ auto vertices2_buf = clipper.vertices.unchecked<2>();
12
+ auto triangles2_buf = clipper.triangles.unchecked<2>();
13
+
14
+ TriangleMesh _tm;
15
+ TriangleMesh _clipper;
16
+ std::vector<TriangleMesh::Vertex_index> vertex_indices;
17
+ // assemble cgal mesh objects from numpy/pybind11 arrays
18
+ for (ssize_t i = 0; i < vertices1_buf.shape(0); ++i)
19
+ {
20
+ vertex_indices.push_back(_tm.add_vertex(Point(vertices1_buf(i, 0), vertices1_buf(i, 1), vertices1_buf(i, 2))));
21
+ }
22
+ for (ssize_t i = 0; i < triangles1_buf.shape(0); ++i)
23
+ {
24
+ _tm.add_face(vertex_indices[triangles1_buf(i, 0)], vertex_indices[triangles1_buf(i, 1)], vertex_indices[triangles1_buf(i, 2)]);
25
+ }
26
+
27
+ vertex_indices.clear();
28
+ for (ssize_t i = 0; i < vertices2_buf.shape(0); ++i)
29
+ {
30
+ vertex_indices.push_back(_clipper.add_vertex(Point(vertices2_buf(i, 0), vertices2_buf(i, 1), vertices2_buf(i, 2))));
31
+ }
32
+ for (ssize_t i = 0; i < triangles2_buf.shape(0); ++i)
33
+ {
34
+ _clipper.add_face(vertex_indices[triangles2_buf(i, 0)], vertex_indices[triangles2_buf(i, 1)], vertex_indices[triangles2_buf(i, 2)]);
35
+ }
36
+ for (const auto &vertex : _tm.vertices())
37
+ {
38
+ const auto &point = _tm.point(vertex);
39
+ }
40
+ for (const auto &vertex : _clipper.vertices())
41
+ {
42
+ const auto &point = _clipper.point(vertex);
43
+ }
44
+ if (!CGAL::is_valid_polygon_mesh(_tm))
45
+ {
46
+ std::cerr << "tm is invalid!" << std::endl;
47
+ }
48
+ if (!CGAL::is_valid_polygon_mesh(_clipper))
49
+ {
50
+ std::cerr << "clipper is invalid!" << std::endl;
51
+ }
52
+ // make sure the meshes actually intersect. If they don't, just return mesh 1
53
+ bool intersection = CGAL::Polygon_mesh_processing::do_intersect(_tm, _clipper);
54
+ if (intersection)
55
+ {
56
+ // Clip tm with clipper
57
+ bool flag = CGAL::Polygon_mesh_processing::clip(_tm, _clipper);
58
+ if (!flag)
59
+ {
60
+ std::cerr << "Clipping failed." << std::endl;
61
+ return {};
62
+ }
63
+ }
64
+ else
65
+ {
66
+ std::cout << "Meshes do not intersect. Returning tm." << std::endl;
67
+ }
68
+ // store the result in a numpymesh object for sending back to Python
69
+ std::vector<std::array<double, 3>> vertices;
70
+ std::vector<std::array<int, 3>> triangles;
71
+ std::map<TriangleMesh::Vertex_index, int> vertex_index_map;
72
+ int index = 0;
73
+ for (const auto &vertex : _tm.vertices())
74
+
75
+ {
76
+ const auto &point = _tm.point(vertex);
77
+ vertices.push_back({point.x(), point.y(), point.z()});
78
+ vertex_index_map[vertex] = index++;
79
+ }
80
+ for (const auto &face : _tm.faces())
81
+ {
82
+ std::array<int, 3> triangle;
83
+ int i = 0;
84
+ for (auto halfedge : CGAL::halfedges_around_face(_tm.halfedge(face), _tm))
85
+ {
86
+ triangle[i++] = vertex_index_map[CGAL::target(halfedge, _tm)]; // Assuming `idx()` gives the vertex index
87
+ }
88
+ triangles.push_back(triangle);
89
+ }
90
+ // Convert vertices to a NumPy array
91
+ pybind11::array_t<double> vertices_array({static_cast<int>(vertices.size()), 3});
92
+ auto vertices_buf = vertices_array.mutable_unchecked<2>();
93
+ for (size_t i = 0; i < vertices.size(); ++i)
94
+ {
95
+ vertices_buf(i, 0) = vertices[i][0];
96
+ vertices_buf(i, 1) = vertices[i][1];
97
+ vertices_buf(i, 2) = vertices[i][2];
98
+ }
99
+ // Convert triangles to a NumPy array
100
+ pybind11::array_t<int> triangles_array({static_cast<int>(triangles.size()), 3});
101
+ auto triangles_buf = triangles_array.mutable_unchecked<2>();
102
+ for (size_t i = 0; i < triangles.size(); ++i)
103
+ {
104
+ triangles_buf(i, 0) = triangles[i][0];
105
+ triangles_buf(i, 1) = triangles[i][1];
106
+ triangles_buf(i, 2) = triangles[i][2];
107
+ }
108
+ // Create NumpyMesh object
109
+ NumpyMesh result;
110
+ result.vertices = vertices_array;
111
+ result.triangles = triangles_array;
112
+ // Return the NumpyMesh object
113
+ for (const auto &vertex : _tm.vertices())
114
+ {
115
+ const auto &point = _tm.point(vertex);
116
+ }
117
+ // Return the NumpyMesh object
118
+ return result;
119
+ }
@@ -0,0 +1,15 @@
1
+ #ifndef CLIP_H
2
+ #define CLIP_H
3
+ #include <pybind11/numpy.h>
4
+ #include "numpymesh.h"
5
+ #include <CGAL/Simple_cartesian.h>
6
+ #include <CGAL/Surface_mesh.h>
7
+
8
+ typedef CGAL::Simple_cartesian<double> Kernel;
9
+ typedef Kernel::Point_3 Point;
10
+ typedef CGAL::Surface_mesh<Point> TriangleMesh;
11
+ NumpyMesh clip_surface(
12
+ NumpyMesh tm,
13
+ NumpyMesh clipper
14
+ );
15
+ #endif
@@ -0,0 +1,9 @@
1
+ #ifndef NUMPYMESH_H
2
+ #define NUMPYMESH_H
3
+ #include <pybind11/numpy.h>
4
+ struct NumpyMesh
5
+ {
6
+ pybind11::array_t<double> vertices;
7
+ pybind11::array_t<int> triangles;
8
+ };
9
+ #endif // NUMPYMESH_H