Skip to content

Commit 675f3b3

Browse files
committed
Add Python modules.
1 parent 87a8d5c commit 675f3b3

File tree

18 files changed

+352
-29
lines changed

18 files changed

+352
-29
lines changed

.gitignore

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,12 @@ build/*
1010

1111
test_config.h
1212

13+
*.a
14+
*.so
15+
*.lib
16+
*.dll
17+
*.pyd
18+
*.dylib
19+
1320
*.ply
14-
*.obj
21+
*.obj

CMakeLists.txt

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ include(Macros)
99
# ----------
1010
option(WITH_OPENMP "Use OpenMP or not" ON)
1111
option(BUILD_STATIC_LIB "Build static link library" OFF)
12+
option(BUILD_PYTHON_MODULE "Build Python module" OFF)
1213
option(BUILD_EXAMPLES "Build examples." OFF)
1314
option(BUILD_TESTS "Build unit tests." OFF)
1415

@@ -19,7 +20,7 @@ if (UNIX)
1920
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -g -O2")
2021
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0")
2122
if (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
22-
#set(CXX_FS_LIBRARY "stdc++fs")
23+
set(CXX_FS_LIBRARY "") # LLVM include filesystem in libc++
2324
else()
2425
set(CXX_FS_LIBRARY "stdc++fs")
2526
endif()
@@ -30,6 +31,7 @@ endif()
3031
# ----------
3132
set(TINYMESH_LIBRARY "tinymesh")
3233
set(TINYMESH_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/src")
34+
set(TINYMESH_PYTHON_MODULE "pytinymesh")
3335

3436
# ----------
3537
# Required packages
@@ -50,15 +52,25 @@ endif()
5052
# ----------
5153
# Output paths
5254
# ----------
53-
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
54-
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
55-
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
56-
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin)
57-
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin)
58-
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/lib)
59-
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin)
60-
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin)
61-
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/lib)
55+
56+
if (NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
57+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
58+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin)
59+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin)
60+
endif()
61+
62+
if (NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
63+
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
64+
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin)
65+
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin)
66+
endif()
67+
68+
if (NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
69+
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
70+
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/lib)
71+
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/lib)
72+
endif()
73+
6274
set(CMAKE_DEBUG_POSTFIX "-debug")
6375

6476
# ----------

examples/python/construct.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import os
2+
import sys
3+
from plyfile import PlyData, PlyElement
4+
import numpy as np
5+
from pytinymesh import Mesh
6+
7+
def main(filename):
8+
# Construct a simple tetrahedron
9+
a = np.asarray([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype='double')
10+
b = np.asarray([0, 1, 2, 0, 2, 3, 0, 3, 1, 3, 2, 1], dtype='uint32')
11+
mesh = Mesh(a, b)
12+
mesh.save('tetra.ply')
13+
14+
# Load .PLY with "plyfile" and construct a mesh by "tinymesh"
15+
plydata = PlyData.read(filename)
16+
vx = plydata['vertex']['x']
17+
vy = plydata['vertex']['y']
18+
vz = plydata['vertex']['z']
19+
verts = np.stack([vx, vy, vz], axis=1).astype('double')
20+
elems = np.concatenate(plydata['face']['vertex_indices']).astype('uint32')
21+
mesh = Mesh(verts, elems)
22+
mesh.save('output.ply')
23+
24+
25+
if __name__ == '__main__':
26+
if len(sys.argv) <= 1:
27+
print("[USAGE] python %s %s" % (os.path.basename(__file__), "INPUT_FILE"))
28+
else:
29+
main(sys.argv[1])

examples/python/fill_and_fair.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import os
2+
import sys
3+
from pytinymesh import Mesh, hole_fill, remesh_incremental
4+
5+
6+
def main(filename):
7+
mesh = Mesh(filename)
8+
9+
# Freeze faces
10+
for i in range(mesh.num_faces()):
11+
f = mesh.face(i)
12+
f.set_is_static(True)
13+
14+
# Fill holes
15+
hole_fill(mesh)
16+
17+
# Then, remesh
18+
remesh_incremental(mesh)
19+
20+
# Save
21+
base, ext = os.path.splitext(filename)
22+
outfile = base + "_remesh" + ext
23+
mesh.save(outfile)
24+
25+
26+
if __name__ == '__main__':
27+
if len(sys.argv) <= 1:
28+
print("[USAGE] python %s %s" % (os.path.basename(__file__), "INPUT_FILE"))
29+
else:
30+
main(sys.argv[1])

examples/read_write/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
#include "tinymesh/tinymesh.h"
55

6-
namespace fs = std::experimental::filesystem;
6+
namespace fs = std::filesystem;
77

88
int main(int argc, char **argv) {
99
if (argc <= 1) {

examples/remesh/main.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace mesh = tinymesh;
66

77
int main(int argc, char **argv) {
88
if (argc <= 1) {
9-
std::cout << "usage: read_write [input mesh]" << std::endl;
9+
std::cout << "usage: remesh [input mesh]" << std::endl;
1010
return 1;
1111
}
1212

@@ -17,7 +17,7 @@ int main(int argc, char **argv) {
1717
}
1818

1919
// Fill holes & remesh
20-
mesh::holeFill(mesh);
20+
mesh::hole_fill(mesh);
2121
mesh::remeshIncremental(mesh);
2222

2323
// Save

examples/simplify/main.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
#include "tinymesh/tinymesh.h"
55

6-
namespace fs = std::experimental::filesystem;
6+
namespace fs = std::filesystem;
77

88
int main(int argc, char **argv) {
99
if (argc <= 1) {
@@ -19,7 +19,7 @@ int main(int argc, char **argv) {
1919
// Simplify
2020
const int target = (int)(ratio * mesh.num_vertices());
2121
tinymesh::simplifyIncremental(mesh, target);
22-
tinymesh::holeFill(mesh);
22+
tinymesh::hole_fill(mesh);
2323
tinymesh::remeshIncremental(mesh);
2424

2525
// Save

examples/smooth/main.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ int main(int argc, char **argv) {
2121
// Smooth (Laplacian)
2222
{
2323
mesh::Mesh mesh(argv[1]);
24-
mesh::holeFill(mesh);
24+
mesh::hole_fill(mesh);
2525
mesh::laplace_smooth(mesh, 1.0, 20);
2626
const std::string outfile =
2727
(dirpath / fs::path((basename + "_laplace_smooth" + extension).c_str())).string();
@@ -32,7 +32,7 @@ int main(int argc, char **argv) {
3232
// Smooth (Taubin)
3333
{
3434
mesh::Mesh mesh(argv[1]);
35-
mesh::holeFill(mesh);
35+
mesh::hole_fill(mesh);
3636
mesh::taubin_smooth(mesh, 1.0, 1.0,20);
3737
const std::string outfile =
3838
(dirpath / fs::path((basename + "_taubin_smooth" + extension).c_str())).string();
@@ -43,7 +43,7 @@ int main(int argc, char **argv) {
4343
// Smooth (implicit fairing)
4444
{
4545
mesh::Mesh mesh(argv[1]);
46-
mesh::holeFill(mesh);
46+
mesh::hole_fill(mesh);
4747
mesh::implicit_fair(mesh, 1.0e-4, 1);
4848
const std::string outfile =
4949
(dirpath / fs::path((basename + "_implicit_fair" + extension).c_str())).string();

setup.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import os
2+
import re
3+
import sys
4+
import platform
5+
import subprocess
6+
7+
from setuptools import setup, Extension
8+
from setuptools.command.build_ext import build_ext
9+
from distutils.version import LooseVersion
10+
11+
12+
class CMakeExtension(Extension):
13+
def __init__(self, name, sourcedir=''):
14+
Extension.__init__(self, name, sources=[])
15+
self.sourcedir = os.path.abspath(sourcedir)
16+
17+
18+
class CMakeBuild(build_ext):
19+
def run(self):
20+
try:
21+
out = subprocess.check_output(['cmake', '--version'])
22+
except OSError:
23+
raise RuntimeError("CMake must be installed to build the following extensions: " +
24+
", ".join(e.name for e in self.extensions))
25+
26+
if platform.system() == "Windows":
27+
cmake_version = LooseVersion(re.search(r'version\s*([\d.]+)', out.decode()).group(1))
28+
if cmake_version < '3.1.0':
29+
raise RuntimeError("CMake >= 3.1.0 is required on Windows")
30+
31+
for ext in self.extensions:
32+
self.build_extension(ext)
33+
34+
def build_extension(self, ext):
35+
extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))
36+
37+
# required for auto-detection of auxiliary "native" libs
38+
if not extdir.endswith(os.path.sep):
39+
extdir += os.path.sep
40+
41+
cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir,
42+
'-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=' + extdir,
43+
'-DPYTHON_EXECUTABLE=' + sys.executable,
44+
'-DBUILD_PYTHON_MODULE=ON']
45+
46+
cfg = 'Debug' if self.debug else 'Release'
47+
build_args = ['--config', cfg]
48+
49+
if platform.system() == "Windows":
50+
cmake_args += ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir)]
51+
if sys.maxsize > 2**32:
52+
cmake_args += ['-A', 'x64']
53+
build_args += ['--config', 'Release']
54+
build_args += ['--parallel', '2']
55+
else:
56+
cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg]
57+
build_args += ['--parallel', '2']
58+
59+
env = os.environ.copy()
60+
env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(env.get('CXXFLAGS', ''),
61+
self.distribution.get_version())
62+
if not os.path.exists(self.build_temp):
63+
os.makedirs(self.build_temp)
64+
subprocess.check_call(['cmake', ext.sourcedir] + cmake_args, cwd=self.build_temp, env=env)
65+
subprocess.check_call(['cmake', '--build', '.'] + build_args, cwd=self.build_temp)
66+
67+
setup(
68+
name='pytinymesh',
69+
version='0.1.0',
70+
author='Tatsuya Yatagawa',
71+
author_email='[email protected]',
72+
description='TinyMesh is a light-weight mesh processing library',
73+
long_description='',
74+
ext_modules=[CMakeExtension('pytinymesh')],
75+
cmdclass=dict(build_ext=CMakeBuild)
76+
)

src/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,13 @@
11
add_subdirectory(tinymesh)
2+
3+
# ----------
4+
# Python module
5+
# ----------
6+
if (BUILD_PYTHON_MODULE)
7+
message(STATUS "Build Python module")
8+
include_directories(${CMAKE_CURRENT_LIST_DIR}/tinymesh)
9+
include_directories(${CMAKE_CURRENT_LIST_DIR}/tinymesh/ext/pybind11)
10+
add_subdirectory(tinymesh/ext/pybind11)
11+
pybind11_add_module(${TINYMESH_PYTHON_MODULE} pybind11.cpp)
12+
target_link_libraries(${TINYMESH_PYTHON_MODULE} PRIVATE ${TINYMESH_LIBRARY})
13+
endif()

0 commit comments

Comments
 (0)