Skip to content

Commit cd28559

Browse files
committed
macOS & Linux done
1 parent 24aac65 commit cd28559

File tree

9 files changed

+386
-125
lines changed

9 files changed

+386
-125
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ __pycache__/
88

99
# Distribution / packaging
1010
dist/
11+
*.egg-info
12+
build/
1113

1214
# coverage file
1315
.coverage
@@ -26,7 +28,10 @@ env
2628
# Executables
2729
*.out
2830
*.exe
31+
*.o
2932

3033
# Shared object files
3134
*.so
3235
*.pyd
36+
*.dylib
37+
*.dll

.travis.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,21 @@ notifications:
22
email: false
33

44
install:
5-
- pip install .
5+
- pip3 install .
66
- python setup.py build_ext --inplace
77
script:
8-
- pip install pytest~=3.6.1
9-
- pytest
8+
- pip3 install pytest pytest-cov
9+
- pytest --cov=gdist
1010

1111
jobs:
1212
include:
1313
- name: "Python 3.8 on Xenial Linux"
1414
language: python
1515
python: 3.8
16+
- name: "Python 3.7.4 on macOS"
17+
os: osx
18+
osx_image: xcode11.2
19+
language: shell
1620
- name: "Python 3.8.0 on Windows"
1721
os: windows
1822
language: shell

gdist.py

Lines changed: 146 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,150 @@
11
import ctypes
2+
import glob
3+
import sys
24

35
import numpy as np
6+
import scipy.sparse
47

5-
lib = ctypes.CDLL('./gdist_c_api.so')
6-
# build numpy arrays etc
7-
print(lib.computeGdist(1, 1, 1, 1))
8+
9+
if sys.platform == 'win32':
10+
libfile = glob.glob('build/*/gdist*.pyd')[0]
11+
lib = ctypes.windll.LoadLibrary(libfile)
12+
elif sys.platform == 'darwin':
13+
try:
14+
libfile = glob.glob('build/*/gdist*.so')[0]
15+
except IndexError:
16+
libfile = glob.glob('build/*/gdist*.dylib')[0]
17+
lib = ctypes.cdll.LoadLibrary(libfile)
18+
else:
19+
libfile = glob.glob('build/*/gdist*.so')[0]
20+
lib = ctypes.cdll.LoadLibrary(libfile)
21+
22+
lib.compute_gdist.argtypes = [
23+
ctypes.c_uint,
24+
ctypes.c_uint,
25+
np.ctypeslib.ndpointer(dtype=np.float64),
26+
np.ctypeslib.ndpointer(dtype=np.int32),
27+
ctypes.c_uint,
28+
ctypes.c_uint,
29+
np.ctypeslib.ndpointer(dtype=np.int32),
30+
np.ctypeslib.ndpointer(dtype=np.int32),
31+
np.ctypeslib.ndpointer(dtype=np.float64),
32+
ctypes.c_double,
33+
]
34+
35+
lib.compute_gdist.restype = None
36+
37+
lib.local_gdist_matrix.argtypes = [
38+
ctypes.c_uint,
39+
ctypes.c_uint,
40+
np.ctypeslib.ndpointer(dtype=np.float64),
41+
np.ctypeslib.ndpointer(dtype=np.int32),
42+
ctypes.POINTER(ctypes.c_uint),
43+
ctypes.c_double,
44+
]
45+
lib.local_gdist_matrix.restype = ctypes.POINTER(ctypes.c_double)
46+
47+
48+
class Gdist(object):
49+
def compute_gdist(
50+
self,
51+
number_of_vertices,
52+
number_of_triangles,
53+
vertices,
54+
triangles,
55+
number_of_source_indices,
56+
number_of_target_indices,
57+
source_indices_array,
58+
target_indices_array,
59+
distance_limit
60+
):
61+
target_indices_size = target_indices_array.size
62+
distance = np.empty(target_indices_size, dtype=np.float64)
63+
lib.compute_gdist(
64+
number_of_vertices,
65+
number_of_triangles,
66+
vertices,
67+
triangles,
68+
number_of_source_indices,
69+
number_of_target_indices,
70+
source_indices_array,
71+
target_indices_array,
72+
distance,
73+
distance_limit
74+
)
75+
return distance
76+
77+
def local_gdist_matrix(
78+
self,
79+
number_of_vertices,
80+
number_of_triangles,
81+
vertices,
82+
triangles,
83+
max_distance,
84+
):
85+
sparse_matrix_size = ctypes.c_uint(0)
86+
data = lib.local_gdist_matrix(
87+
number_of_vertices,
88+
number_of_triangles,
89+
vertices,
90+
triangles,
91+
ctypes.byref(sparse_matrix_size),
92+
max_distance
93+
)
94+
95+
data = np.fromiter(data, dtype=np.float64,
96+
count=3 * sparse_matrix_size.value)
97+
return data
98+
99+
100+
def compute_gdist(
101+
vertices,
102+
triangles,
103+
source_indices=None,
104+
target_indices=None,
105+
max_distance=1e100,
106+
):
107+
vertices = vertices.ravel()
108+
triangles = triangles.ravel()
109+
source_indices = source_indices.ravel()
110+
target_indices = target_indices.ravel()
111+
112+
g = Gdist()
113+
distance = g.compute_gdist(
114+
number_of_vertices=vertices.size,
115+
number_of_triangles=triangles.size,
116+
vertices=vertices,
117+
triangles=triangles,
118+
number_of_source_indices=source_indices.size,
119+
number_of_target_indices=target_indices.size,
120+
source_indices_array=source_indices,
121+
target_indices_array=target_indices,
122+
distance_limit=max_distance
123+
)
124+
return np.fromiter(distance, dtype=np.float64, count=target_indices.size)
125+
126+
127+
def local_gdist_matrix(
128+
vertices,
129+
triangles,
130+
max_distance=1e100
131+
):
132+
vertices = vertices.ravel()
133+
triangles = triangles.ravel()
134+
135+
g = Gdist()
136+
data = g.local_gdist_matrix(
137+
vertices.size,
138+
triangles.size,
139+
vertices,
140+
triangles,
141+
max_distance
142+
)
143+
sizes = data.size // 3
144+
rows = data[:sizes]
145+
columns = data[sizes: 2*sizes]
146+
data = data[2*sizes:]
147+
148+
return scipy.sparse.csc_matrix(
149+
(data, (rows, columns)), shape=(vertices.size // 3, vertices.size // 3)
150+
)

gdist_c_api.cpp

Lines changed: 154 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,154 @@
1-
#include <iostream>
2-
#include <fstream>
3-
4-
#include "geodesic_library/geodesic_algorithm_exact.h"
5-
6-
extern "C" {
7-
double computeGdist(int numberOfVertices, int numberOfTriangles, double *vertices, double *triangles);
8-
};
9-
10-
double computeGdist(int numberOfVertices, int numberOfTriangles, double *vertices, double *triangles) {
11-
return 1.0;
12-
}
1+
#include <iostream>
2+
#include <fstream>
3+
#include <inttypes.h>
4+
5+
#include "geodesic_library/geodesic_algorithm_exact.h"
6+
7+
8+
#if defined(_WIN32)
9+
# if defined(DLL_EXPORTS)
10+
# define DLL_EXPORT_API __declspec(dllexport)
11+
# else
12+
# define DLL_EXPORT_API __declspec(dllimport)
13+
# endif
14+
#else
15+
# define DLL_EXPORT_API
16+
#endif
17+
18+
19+
void compute_gdist_impl(
20+
unsigned number_of_vertices,
21+
unsigned number_of_triangles,
22+
double *vertices,
23+
int *triangles,
24+
unsigned number_of_source_indices,
25+
unsigned number_of_target_indices,
26+
unsigned *source_indices_array,
27+
unsigned *target_indices_array,
28+
double *distance,
29+
double distance_limit
30+
) {
31+
32+
std::vector<double> points (vertices, vertices + number_of_vertices);
33+
std::vector<unsigned> faces (triangles, triangles + number_of_triangles);
34+
std::vector<unsigned> source_indices (source_indices_array, source_indices_array + number_of_source_indices);
35+
std::vector<unsigned> target_indices (target_indices_array, target_indices_array + number_of_target_indices);
36+
37+
geodesic::Mesh mesh;
38+
mesh.initialize_mesh_data(points, faces); // create internal mesh data structure including edges
39+
40+
geodesic::GeodesicAlgorithmExact algorithm(&mesh); // create exact algorithm for the mesh
41+
42+
std::vector<geodesic::SurfacePoint> all_sources, stop_points;
43+
44+
for (unsigned i = 0; i < number_of_source_indices; ++i) {
45+
all_sources.push_back(geodesic::SurfacePoint(&mesh.vertices()[source_indices[i]]));
46+
}
47+
48+
for (unsigned i = 0; i < number_of_target_indices; ++i) {
49+
stop_points.push_back(geodesic::SurfacePoint(&mesh.vertices()[target_indices[i]]));
50+
}
51+
52+
algorithm.propagate(all_sources, distance_limit, &stop_points);
53+
54+
for (unsigned i = 0; i < stop_points.size(); ++i) {
55+
algorithm.best_source(stop_points[i], distance[i]);
56+
}
57+
}
58+
59+
double* local_gdist_matrix_impl(
60+
unsigned number_of_vertices,
61+
unsigned number_of_triangles,
62+
double *vertices,
63+
unsigned *triangles,
64+
unsigned *sparse_matrix_size,
65+
double max_distance
66+
) {
67+
std::vector<double> points (vertices, vertices + number_of_vertices);
68+
std::vector<unsigned> faces (triangles, triangles + number_of_triangles);
69+
70+
geodesic::Mesh mesh;
71+
mesh.initialize_mesh_data(points, faces); // create internal mesh data structure including edges
72+
geodesic::GeodesicAlgorithmExact algorithm(&mesh); // create exact algorithm for the mesh
73+
std::vector <unsigned> rows_vector, columns_vector;
74+
std::vector <double> data_vector;
75+
76+
double distance = 0;
77+
78+
std::vector<geodesic::SurfacePoint> targets(number_of_vertices), source;
79+
80+
for (unsigned i = 0; i < number_of_vertices; ++i) {
81+
targets[i] = geodesic::SurfacePoint(&mesh.vertices()[i]);
82+
}
83+
for (unsigned i = 0; i < number_of_vertices / 3; ++i) {
84+
source.push_back(geodesic::SurfacePoint(&mesh.vertices()[i]));
85+
algorithm.propagate(source, max_distance, NULL);
86+
source.pop_back();
87+
for (unsigned j = 0; j < number_of_vertices / 3; ++j) {
88+
algorithm.best_source(targets[j], distance);
89+
if (distance != geodesic::GEODESIC_INF && distance != 0 && distance <= max_distance) {
90+
rows_vector.push_back(i);
91+
columns_vector.push_back(j);
92+
data_vector.push_back(distance);
93+
}
94+
}
95+
}
96+
97+
double *data;
98+
data = new double[3 * rows_vector.size()];
99+
100+
*sparse_matrix_size = rows_vector.size();
101+
102+
std::copy(rows_vector.begin(), rows_vector.end(), data);
103+
std::copy(columns_vector.begin(), columns_vector.end(), data + data_vector.size());
104+
std::copy(data_vector.begin(), data_vector.end(), data + 2 * data_vector.size());
105+
106+
return data;
107+
}
108+
109+
110+
extern "C" {
111+
DLL_EXPORT_API void compute_gdist(
112+
unsigned number_of_vertices,
113+
unsigned number_of_triangles,
114+
double *vertices,
115+
int *triangles,
116+
unsigned number_of_source_indices,
117+
unsigned number_of_target_indices,
118+
unsigned *source_indices_array,
119+
unsigned *target_indices_array,
120+
double *distance,
121+
double distance_limit
122+
) {
123+
compute_gdist_impl(
124+
number_of_vertices,
125+
number_of_triangles,
126+
vertices,
127+
triangles,
128+
number_of_source_indices,
129+
number_of_target_indices,
130+
source_indices_array,
131+
target_indices_array,
132+
distance,
133+
distance_limit
134+
);
135+
}
136+
137+
DLL_EXPORT_API double* local_gdist_matrix(
138+
unsigned number_of_vertices,
139+
unsigned number_of_triangles,
140+
double *vertices,
141+
unsigned *triangles,
142+
unsigned *sparse_matrix_size,
143+
double max_distance
144+
) {
145+
return local_gdist_matrix_impl(
146+
number_of_vertices,
147+
number_of_triangles,
148+
vertices,
149+
triangles,
150+
sparse_matrix_size,
151+
max_distance
152+
);
153+
}
154+
};

geodesic_library/gdist.cpp

Lines changed: 0 additions & 21 deletions
This file was deleted.

pyproject.toml

Lines changed: 0 additions & 2 deletions
This file was deleted.

requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
cython
21
numpy
32
scipy

0 commit comments

Comments
 (0)