├── MeshLP ├── offobj.mexw64 ├── geodesics │ ├── geodesic_matlab_api.mexw64 │ ├── readme.txt │ ├── geodesic_cpp_03_02_2008.zip │ ├── geodesic_matlab_api.h │ ├── geodesic_constants_and_simple_functions.h │ ├── example0.cpp │ ├── example1.cpp │ ├── geodesic_algorithm_dijkstra.h │ ├── geodesic_memory.h~ │ ├── geodesic_memory.h │ ├── geodesic_algorithm_base.h │ ├── flat_triangular_mesh.txt │ ├── geodesic_matlab_api.cpp │ ├── geodesic_algorithm_subdivision.h │ ├── geodesic_algorithm_graph_base.h │ ├── geodesic_algorithm_dijkstra_alternative.h │ ├── geodesic_mesh_elements.h │ ├── geodesic_algorithm_exact_elements.h │ └── geodesic_mesh.h ├── tmesh.cpp ├── cotlpmatrix.mexa64 ├── cotlpmatrix.mexglx ├── cotlpmatrix.mexw64 ├── meshlpmatrix.cpp ├── symmshlpmatrix.mexa64 ├── symmshlpmatrix.mexglx ├── symmshlpmatrix.mexw64 ├── mex.txt ├── eigens_cot.m ├── eigens_cot.m~ ├── cotlp_matrix.m ├── cotlp_matrix.m~ ├── mshlp_eigens.m ├── eigens_msh.m~ ├── eigens_msh.m ├── point.h ├── comp_meshlpmatrix.h ├── meshlpmatrix.h ├── symmshlp_matrix.m ├── offobj.h ├── cotlpmatrix.cpp ├── makefile ├── makefile_32 ├── makefile_64 ├── makefile~ ├── point.cpp ├── README ├── README~ ├── tmesh.h ├── symmshlpmatrix.cpp ├── datastructure.h ├── matrix.cpp └── matrix.h ├── HKS_release ├── offobj.mexw64 ├── OFF2HKS.m ├── color.bmp ├── cotlpmatrix.mexa64 ├── cotlpmatrix.mexglx ├── cotlpmatrix.mexw64 ├── symmshlpmatrix.mexa64 ├── symmshlpmatrix.mexglx ├── symmshlpmatrix.mexw64 ├── main.asv ├── main.m ├── cotlp_matrix.m ├── saveResult.m ├── README.txt ├── read_vertices_and_faces_from_obj_file.m ├── HKS_t.m ├── HKS.m ├── read_vertices_and_faces_from_obj_file.asv ├── symmshlp_matrix.m ├── bunnyvf.off └── bunnyvf.obj └── README.md /MeshLP/offobj.mexw64: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /HKS_release/offobj.mexw64: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /MeshLP/geodesics/geodesic_matlab_api.mexw64: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /MeshLP/tmesh.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/MeshLP/tmesh.cpp -------------------------------------------------------------------------------- /HKS_release/OFF2HKS.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/HKS_release/OFF2HKS.m -------------------------------------------------------------------------------- /HKS_release/color.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/HKS_release/color.bmp -------------------------------------------------------------------------------- /MeshLP/cotlpmatrix.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/MeshLP/cotlpmatrix.mexa64 -------------------------------------------------------------------------------- /MeshLP/cotlpmatrix.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/MeshLP/cotlpmatrix.mexglx -------------------------------------------------------------------------------- /MeshLP/cotlpmatrix.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/MeshLP/cotlpmatrix.mexw64 -------------------------------------------------------------------------------- /MeshLP/meshlpmatrix.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/MeshLP/meshlpmatrix.cpp -------------------------------------------------------------------------------- /MeshLP/geodesics/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/MeshLP/geodesics/readme.txt -------------------------------------------------------------------------------- /HKS_release/cotlpmatrix.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/HKS_release/cotlpmatrix.mexa64 -------------------------------------------------------------------------------- /HKS_release/cotlpmatrix.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/HKS_release/cotlpmatrix.mexglx -------------------------------------------------------------------------------- /HKS_release/cotlpmatrix.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/HKS_release/cotlpmatrix.mexw64 -------------------------------------------------------------------------------- /MeshLP/symmshlpmatrix.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/MeshLP/symmshlpmatrix.mexa64 -------------------------------------------------------------------------------- /MeshLP/symmshlpmatrix.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/MeshLP/symmshlpmatrix.mexglx -------------------------------------------------------------------------------- /MeshLP/symmshlpmatrix.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/MeshLP/symmshlpmatrix.mexw64 -------------------------------------------------------------------------------- /HKS_release/symmshlpmatrix.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/HKS_release/symmshlpmatrix.mexa64 -------------------------------------------------------------------------------- /HKS_release/symmshlpmatrix.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/HKS_release/symmshlpmatrix.mexglx -------------------------------------------------------------------------------- /HKS_release/symmshlpmatrix.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/HKS_release/symmshlpmatrix.mexw64 -------------------------------------------------------------------------------- /MeshLP/geodesics/geodesic_cpp_03_02_2008.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shicoder/HKS/HEAD/MeshLP/geodesics/geodesic_cpp_03_02_2008.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HKS-heat-kernel-signature 2 | the Matlab implement of heat kernel signature 3 | the detail of HKS introduced in my blog "http://blog.csdn.net/sxf1061926959/article/details/53538105" 4 | -------------------------------------------------------------------------------- /MeshLP/mex.txt: -------------------------------------------------------------------------------- 1 | mex cotlpmatrix.cpp meshlpmatrix.cpp comp_meshlpmatrix.cpp tmesh.cpp offobj.cpp matrix.cpp point.cpp; 2 | mex symmshlpmatrix.cpp meshlpmatrix.cpp comp_meshlpmatrix.cpp tmesh.cpp offobj.cpp matrix.cpp point.cpp; 3 | -------------------------------------------------------------------------------- /HKS_release/main.asv: -------------------------------------------------------------------------------- 1 | res=OFF2HKS('bunnyvf1.off',true); 2 | nu=(res(:,50)-min(res(:,50)))./(max(res(:,50))-min(res(:,50))); 3 | [v,f]=read_vertices_and_faces_from_obj_file('bunnyvf1.off'); 4 | f=f+1; 5 | saveResult('bunny.obj',v,f,nu); 6 | -------------------------------------------------------------------------------- /HKS_release/main.m: -------------------------------------------------------------------------------- 1 | res=OFF2HKS('bunnyvf1.off',true); 2 | nu=(res(:,50)-min(res(:,50)))./(max(res(:,50))-min(res(:,50))); 3 | [v,f]=read_vertices_and_faces_from_obj_file('bunnyvf1.off'); 4 | f=f+1; 5 | saveResult('bunnyvf1.obj',v,f,nu); 6 | -------------------------------------------------------------------------------- /MeshLP/eigens_cot.m: -------------------------------------------------------------------------------- 1 | nev = 300; 2 | prefix='bighand'; 3 | 4 | filename=sprintf('./%s.off', prefix); 5 | 6 | [W A]=cotlp_matrix(filename); 7 | 8 | Am = sparse([1:length(A)], [1:length(A)], A); 9 | 10 | [evecs evals] = eigs(W, Am, nev, -1e-5); 11 | evals = diag(evals); 12 | 13 | filename=sprintf('./%s_cot', prefix); 14 | save(filename, 'W', 'A', 'evecs', 'evals'); 15 | -------------------------------------------------------------------------------- /MeshLP/eigens_cot.m~: -------------------------------------------------------------------------------- 1 | nev = 300; 2 | prefix='bighand'; 3 | 4 | filename=sprintf('./%s.off', prefix); 5 | 6 | [W A]=cotlp_matrix(filename); 7 | 8 | Am = sparse([1:length(A)], [1:length(A)], A); 9 | 10 | [evecs evals] = eigs(W, Am, nev, -1e-5); 11 | evals = diag(evals); 12 | 13 | filename=sprintf('./egnmat/%s_cot', prefix); 14 | save(filename, 'W', 'A', 'evecs', 'evals'); 15 | -------------------------------------------------------------------------------- /MeshLP/cotlp_matrix.m: -------------------------------------------------------------------------------- 1 | function [W A] = cotlp_matrix(filename) 2 | % 3 | % Compute the Laplace-Beltrami matrix from mesh by cot scheme 4 | % 5 | % INPUTS 6 | % filename: off file of triangle mesh. 7 | % 8 | % OUTPUTS 9 | % W: weight matrix 10 | % A: area weight per vertex, the Laplace-Beltrami matrix = diag(1./ A) * W 11 | 12 | 13 | if nargin < 1 14 | error('Too few input arguments'); 15 | end; 16 | 17 | [II JJ SS AA] = cotlpmatrix(filename); 18 | W=sparse(II, JJ, SS); 19 | A=AA; 20 | 21 | -------------------------------------------------------------------------------- /MeshLP/cotlp_matrix.m~: -------------------------------------------------------------------------------- 1 | function [W A] = cotlp_matrix(filename) 2 | % 3 | % Compute the Laplace-Beltrami matrix from mesh by cot scheme 4 | % 5 | % INPUTS 6 | % filename: off file of triangle mesh. 7 | % 8 | % OUTPUTS 9 | % W: weight matrix 10 | % A: area weight per vertex, the Laplace-Beltrami matrix = diag(1./ D) * W 11 | 12 | 13 | if nargin < 1 14 | error('Too few input arguments'); 15 | end; 16 | 17 | [II JJ SS AA] = cotlpmatrix(filename); 18 | W=sparse(II, JJ, SS); 19 | A=AA; 20 | 21 | -------------------------------------------------------------------------------- /HKS_release/cotlp_matrix.m: -------------------------------------------------------------------------------- 1 | function [W A] = cotlp_matrix(filename) 2 | % 3 | % Compute the Laplace-Beltrami matrix from mesh by cot scheme 4 | % 5 | % INPUTS 6 | % filename: off file of triangle mesh. 7 | % 8 | % OUTPUTS 9 | % W: weight matrix 10 | % A: area weight per vertex, the Laplace-Beltrami matrix = diag(1./ D) * W 11 | 12 | 13 | if nargin < 1 14 | error('Too few input arguments'); 15 | end; 16 | 17 | [II JJ SS AA] = cotlpmatrix(filename); 18 | W=sparse(II, JJ, SS); 19 | A=AA; 20 | 21 | -------------------------------------------------------------------------------- /MeshLP/mshlp_eigens.m: -------------------------------------------------------------------------------- 1 | opt.dtype='geodesic'; 2 | opt.htype='ddr'; 3 | opt.hs = 2; 4 | opt.rho = 3; 5 | nev = 300; 6 | 7 | prefix='bighand'; 8 | filename=sprintf('%s.off', prefix); 9 | 10 | [W A] = mshlp_matrix(filename, opt); 11 | Am = sparse([1:length(A)], [1:length(A)], A); 12 | 13 | [evecs evals] = eigs(W, Am, nev, -1e-5); 14 | evals = diag(evals); 15 | 16 | filename=sprintf('%s_dt_%s_ht_%s_hs%d_rho%d', prefix, opt.dtype, opt.htype, opt.hs, opt.rho); 17 | save(filename, 'W', 'A', 'evecs', 'evals'); 18 | -------------------------------------------------------------------------------- /MeshLP/eigens_msh.m~: -------------------------------------------------------------------------------- 1 | opt.dtype='geodesic'; 2 | %opt.dtype='euclidean'; 3 | opt.htype='ddr'; 4 | opt.hs = 2; 5 | opt.rho = 3; 6 | nev = 300; 7 | 8 | 9 | prefix = 'bighand'; 10 | filename=sprintf('./%s.off', prefix); 11 | [W A h] = symmshlp_matrix(filename, opt); 12 | Am = sparse([1:length(A)], [1:length(A)], A); 13 | [evecs evals] = eigs(W, Am, nev, -1e-5); 14 | evals = diag(evals); 15 | 16 | filename=sprintf('./%s_sym_dt_%s_ht_%s_hs%d_rho%d', prefix, opt.dtype, opt.htype, opt.hs, opt.rho); 17 | save(filename, 'W', 'A', 'evecs', 'evals', 'h'); 18 | -------------------------------------------------------------------------------- /MeshLP/eigens_msh.m: -------------------------------------------------------------------------------- 1 | %opt.dtype='geodesic'; 2 | opt.dtype='euclidean'; 3 | opt.htype='ddr'; 4 | opt.hs = 2; 5 | opt.rho = 3; 6 | nev = 300; 7 | 8 | 9 | prefix = 'bighand'; 10 | prefix = 'object' 11 | filename=sprintf('./%s.off', prefix); 12 | [W A h] = symmshlp_matrix(filename, opt); 13 | Am = sparse([1:length(A)], [1:length(A)], A); 14 | [evecs evals] = eigs(W, Am, nev, -1e-5); 15 | evals = diag(evals); 16 | 17 | filename=sprintf('./%s_sym_dt_%s_ht_%s_hs%d_rho%d', prefix, opt.dtype, opt.htype, opt.hs, opt.rho); 18 | save(filename, 'W', 'A', 'evecs', 'evals', 'h'); 19 | -------------------------------------------------------------------------------- /HKS_release/saveResult.m: -------------------------------------------------------------------------------- 1 | function [V,F] = saveResult(filename,vertices,faces,vt) 2 | fprintf('save resutl\n'); 3 | num_vertices = size(vertices,1); 4 | num_faces = size(faces,1); 5 | delete(filename); 6 | fid = fopen(filename,'w'); 7 | for i=1:num_vertices 8 | fprintf(fid,'v %.6f %.6f %.6f\n',vertices(i,1),vertices(i,2),vertices(i,3)); 9 | end 10 | for i=1:num_vertices 11 | fprintf(fid,'vt %.6f 0\n',vt(i)); 12 | end 13 | for i=1:num_faces 14 | fprintf(fid,'f %d/%d %d/%d %d/%d\n',faces(i,1),faces(i,1),faces(i,2),faces(i,2),faces(i,3),faces(i,3)); 15 | end 16 | 17 | fclose(fid); 18 | fprintf('done\n'); -------------------------------------------------------------------------------- /HKS_release/README.txt: -------------------------------------------------------------------------------- 1 | OFF2HKS.m: Compute the heat kernel signatures given an mesh in off format. It 2 | uses MeshLP package (www.cs.princeton.edu/~jiansun/software/meshlp.html) to 3 | compute the eigenvalues and the eigenvectors of the Laplace operator. The time 4 | axis is sampled logarithmically. example: OFF2HKS('trimstar.off', true) 5 | 6 | HKS.m: Compute the heat kernel signature for each point in the mesh given the 7 | eigenvalues and the eigenvectors of the Laplace operator. The time axis is 8 | sampled logarithmically. 9 | 10 | HKS_t.m: Compute the heat kernel signature restricted to a given time scale 11 | given the eigenvalues and the eigenvectors of the Laplace operator. 12 | 13 | 14 | -------------------------------------------------------------------------------- /HKS_release/read_vertices_and_faces_from_obj_file.m: -------------------------------------------------------------------------------- 1 | function [vertex,faces] = read_vertices_and_faces_from_obj_file(filename) 2 | % Reads a .obj mesh file and outputs the vertex and face list 3 | % assumes a 3D triangle mesh and ignores everything but: 4 | % v x y z and f i j k lines 5 | % Input: 6 | % filename string of obj file's path 7 | % 8 | % Output: 9 | % V number of vertices x 3 array of vertex positions 10 | % F number of faces x 3 array of face indices 11 | % 12 | V = zeros(0,3); 13 | F = zeros(0,3); 14 | vertex_index = 1; 15 | face_index = 1; 16 | fid = fopen(filename,'rt'); 17 | line = fgets(fid); 18 | line = fgets(fid); 19 | [nums]=sscanf(line,'%d %d %d'); 20 | vertex=zeros(nums(1),3); 21 | faces=zeros(nums(2),3); 22 | for i=1:nums(1) 23 | line = fgets(fid); 24 | vertex(i,:) = sscanf(line,'%f %f %f'); 25 | end 26 | for i=1:nums(2) 27 | line = fgets(fid); 28 | faces(i,:)=sscanf(line,'3 %d %d %d'); 29 | end 30 | 31 | 32 | fclose(fid); 33 | end -------------------------------------------------------------------------------- /MeshLP/point.h: -------------------------------------------------------------------------------- 1 | #ifndef POINT_H 2 | #define POINT_H 3 | 4 | //points 5 | 6 | #include 7 | 8 | using namespace std; 9 | 10 | 11 | class Point { 12 | friend Point cross_product(Point a, Point b, Point c); 13 | friend double dot_product(Point a, Point b); 14 | friend Point centroid(vector verts); 15 | 16 | public: 17 | double x,y,z; 18 | 19 | Point(double x, double y, double z); 20 | 21 | Point(const Point& o); 22 | Point& operator=(const Point& rhs); 23 | 24 | void normalize_point(); 25 | 26 | bool operator==(Point &p) { 27 | return ((x <= p.x + epsilon) && (x >= p.x - epsilon) && 28 | (y <= p.y + epsilon) && (y >= p.y - epsilon) && 29 | (z <= p.z + epsilon) && (z >= p.z - epsilon) 30 | ); 31 | } 32 | 33 | bool operator<(const Point& p) const { 34 | return ((x < p.x) || (x == p.x && y < p.y)); 35 | } 36 | 37 | private: 38 | static double epsilon; 39 | }; 40 | 41 | double triangleArea(const Point& a, const Point& b, const Point& c); 42 | Point barycentricCoords(const Point& a, const Point& b, const Point& c, 43 | const Point& p); 44 | 45 | #endif 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /HKS_release/HKS_t.m: -------------------------------------------------------------------------------- 1 | function [hks_t] = HKS(evecs, evals, A, t, scale) 2 | 3 | % INPUTS 4 | % evecs: ith each column in this matrix is the ith eigenfunction of the Laplace-Beltrami operator 5 | % evals: ith element in this vector is the ith eigenvalue of the Laplace-Beltrami operator 6 | % A: ith element in this vector is the area associated with the ith vertex 7 | % t: the time scale 8 | % scale: if scale = true, output the scaled hks 9 | % o.w. ouput the not scaled hks 10 | 11 | % OUTPUTS 12 | % hks_t: heat kernel signature restricted to the time scale t 13 | 14 | 15 | %area = sum(A); 16 | %A = (1/area) * A; 17 | %evals = area * evals; 18 | %evecs = sqrt(area) * evecs; 19 | 20 | if scale == true, 21 | hks_t = abs( evecs(:, 2:end) ).^2 * exp( ( abs(evals(2)) - abs(evals(2:end)) ) * t); 22 | Am = sparse([1:length(A)], [1:length(A)], A); 23 | colsum = sum(Am*hks_t); 24 | scale = 1.0 / colsum; 25 | scalem = sparse([1:length(scale)], [1:length(scale)], scale); 26 | hks_t = hks_t * scalem; 27 | else 28 | hks_t = abs( evecs(:, 2:end) ).^2 * exp( - abs(evals(2:end)) * t); 29 | 30 | end 31 | 32 | 33 | -------------------------------------------------------------------------------- /HKS_release/HKS.m: -------------------------------------------------------------------------------- 1 | function [hks] = HKS(evecs, evals, A, scale) 2 | 3 | % INPUTS 4 | % evecs: ith each column in this matrix is the ith eigenfunction of the Laplace-Beltrami operator 5 | % evals: ith element in this vector is the ith eigenvalue of the Laplace-Beltrami operator 6 | % A: ith element in this vector is the area associated with the ith vertex 7 | % scale: if scale = true, output the scaled hks 8 | % o.w. ouput the hks that is not scaled 9 | 10 | % OUTPUTS 11 | % hks: ith row in this matrix is the heat kernel signature of the ith vertex 12 | 13 | 14 | %area = sum(A); 15 | %A = (1/area) * A; 16 | %evals = area * evals; 17 | %evecs = sqrt(area) * evecs; 18 | 19 | tmin = abs(4*log(10) / evals(end)); 20 | tmax = abs(4*log(10) / evals(2)); 21 | nstep = 100; 22 | 23 | stepsize = (log(tmax) - log(tmin)) / nstep; 24 | logts = log(tmin):stepsize:log(tmax); 25 | ts = exp(logts); 26 | 27 | if scale == true, 28 | hks = abs( evecs(:, 2:end) ).^2 * exp( ( abs(evals(2)) - abs(evals(2:end)) ) * ts); 29 | Am = sparse([1:length(A)], [1:length(A)], A); 30 | colsum = sum(Am*hks); 31 | scale = 1.0./ colsum; 32 | scalem = sparse([1:length(scale)], [1:length(scale)], scale); 33 | hks = hks * scalem; 34 | else 35 | hks = abs( evecs(:, 2:end) ).^2 * exp( - abs(evals(2:end)) * ts); 36 | 37 | end 38 | 39 | 40 | -------------------------------------------------------------------------------- /MeshLP/comp_meshlpmatrix.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMP_MESHLPMATRIX_H__ 2 | #define __COMP_MESHLPMATRIX_H__ 3 | 4 | #include "tmesh.h" 5 | void generate_sym_meshlp_matrix(TMesh& mesh, double h, double rho, vector& IIV, vector& JJV, vector& SSV, vector& AAV); 6 | void generate_sym_meshlp_matrix_geod(TMesh& mesh, double h, double rho, vector& IIV, vector& JJV, vector& SSV, vector& AAV); 7 | 8 | void generate_meshlp_matrix(TMesh& mesh, double h, double rho, vector& IIV, vector& JJV, vector& SSV); 9 | void generate_meshlp_matrix_geod(TMesh& mesh, double h, double rho, vector& IIV, vector& JJV, vector& SSV); 10 | 11 | void generate_meshlp_matrix_adp(TMesh& mesh, double hs, double rho, vector& IIV, vector& JJV, vector& SSV); 12 | void generate_meshlp_matrix_adp_geod(TMesh& mesh, double hs, double rho, vector& IIV, vector& JJV, vector& SSV); 13 | 14 | 15 | void generate_Xu_Meyer_laplace_matrix(TMesh& mesh, vector& IIV, vector& JJV, vector& SSV, vector& DDV); 16 | 17 | 18 | //void compute_one2part_Euclidean_vdist(unsigned int vid_start, TMesh& mesh, vector >& vgdists, double maxdist); 19 | 20 | #endif //__COMP_MESHLPMATRIX_H__ 21 | -------------------------------------------------------------------------------- /MeshLP/meshlpmatrix.h: -------------------------------------------------------------------------------- 1 | #ifndef __MESHLPMATRIX_H__ 2 | #define __MESHLPMATRIX_H__ 3 | 4 | #include 5 | using namespace std; 6 | bool generate_sym_meshlp_matrix_matlab(char* filename, unsigned int htype, double hs, double rho, double &h, vector& IIV, vector& JJV, vector& SSV, vector& AAV); 7 | 8 | bool generate_sym_meshlp_matrix_geod_matlab(char* filename, unsigned int htype, double hs, double rho, double &h, vector& IIV, vector& JJV, vector& SSV, vector& AAV); 9 | 10 | //bool generate_sym_meshlp_matrix_geod_matlab_fastmarching(char* filename, unsigned int htype, double hs, double rho, vector& IIV, vector& JJV, vector& SSV, vector& AAV); 11 | 12 | bool generate_meshlp_matrix_matlab(char* filename, unsigned int htype, double hs, double rho, vector& IIV, vector& JJV, vector& SSV); 13 | 14 | bool generate_meshlp_matrix_geod_matlab(char* filename, unsigned int htype, double hs, double rho, vector& IIV, vector& JJV, vector& SSV); 15 | 16 | bool generate_meshlp_matrix_adp_matlab(char* filename, double hs, double rho, vector& IIV, vector& JJV, vector& SSV); 17 | 18 | bool generate_meshlp_matrix_adp_geod_matlab(char* filename, double hs, double rho, vector& IIV, vector& JJV, vector& SSV); 19 | 20 | 21 | 22 | void generate_Xu_Meyer_laplace_matrix_matlab(char* filename, vector& IIV, vector& JJV, vector& SSV, vector& DDV); 23 | 24 | #endif //__MESHLPMATRIX_H__ 25 | -------------------------------------------------------------------------------- /HKS_release/read_vertices_and_faces_from_obj_file.asv: -------------------------------------------------------------------------------- 1 | function [V,F] = read_vertices_and_faces_from_obj_file(filename) 2 | % Reads a .obj mesh file and outputs the vertex and face list 3 | % assumes a 3D triangle mesh and ignores everything but: 4 | % v x y z and f i j k lines 5 | % Input: 6 | % filename string of obj file's path 7 | % 8 | % Output: 9 | % V number of vertices x 3 array of vertex positions 10 | % F number of faces x 3 array of face indices 11 | % 12 | V = zeros(0,3); 13 | F = zeros(0,3); 14 | vertex_index = 1; 15 | face_index = 1; 16 | fid = fopen(filename,'rt'); 17 | line = fgets(fid); 18 | line = fgets(fid); 19 | [numV,numF,zero]=sscanf(line,'%d %d %d'); 20 | vertex 21 | for i=1:numV 22 | vertex = sscanf(line,'%f %f %f'); 23 | end 24 | 25 | 26 | while ischar(line) 27 | % vertex = sscanf(line,'v %f %f %f'); 28 | vertex = sscanf(line,'%f %f %f'); 29 | %face = sscanf(line,'f %d %d %d'); 30 | face = sscanf(line,'3 %d %d %d'); 31 | %face_long = sscanf(line,'f %d/%d/%d %d/%d/%d %d/%d/%d'); 32 | 33 | % see if line is vertex command if so add to vertices 34 | %{ 35 | if(size(vertex)>0) 36 | V(vertex_index,:) = vertex; 37 | vertex_index = vertex_index+1; 38 | % see if line is simple face command if so add to faces 39 | elseif(size(face)>0) 40 | F(face_index,:) = face; 41 | face_index = face_index+1; 42 | % see if line is a long face command if so add to faces 43 | elseif(size(face_long)>0) 44 | % remove normal and texture indices 45 | face_long = face_long(1:3:end) 46 | F(face_index,:) = face_long; 47 | face_index = face_index+1; 48 | else 49 | fprintf('Ignored: %s',line); 50 | end 51 | %} 52 | line = fgets(fid); 53 | end 54 | fclose(fid); 55 | end -------------------------------------------------------------------------------- /MeshLP/symmshlp_matrix.m: -------------------------------------------------------------------------------- 1 | function [W A h] = symmshlp_matrix(filename, opt) 2 | % 3 | % Compute the symmetric Laplace-Beltrami matrix from mesh 4 | % 5 | % INPUTS 6 | % filename: off file of triangle mesh. 7 | % opt.htype: the way to compute the parameter h. h = hs * neighborhoodsize 8 | % if htype = 'ddr' (data driven); h = hs if hytpe = 'psp' (pre-specify) 9 | % Default : 'ddr' 10 | % opt.hs: the scaling factor that scales the neighborhood size to the 11 | % parameter h where h^2 = 4t. 12 | % Default: 2, must > 0 13 | % opt.rho: The cut-off for Gaussion function evaluation. 14 | % Default: 3, must > 0 15 | % opt.dtype: the way to compute the distance 16 | % dtype = 'euclidean' or 'geodesic'; 17 | % Default : 'euclidean' 18 | 19 | % 20 | % OUTPUTS 21 | % W: symmetric weight matrix 22 | % A: area weight per vertex, the Laplace matrix = diag(1./ A) * W 23 | % h: Gaussian width: h^2 = 4t 24 | 25 | 26 | if nargin < 1 27 | error('Too few input arguments'); 28 | elseif nargin < 2 29 | opt.hs = 2; 30 | opt.rho = 3; 31 | opt.htype = 'ddr'; 32 | opt.dtype = 'euclidean' 33 | end 34 | opt=parse_opt(opt) 35 | 36 | if opt.hs <= 0 | opt.rho <= 0 37 | error('Invalid values in opt'); 38 | end 39 | 40 | 41 | [II JJ SS AA h] = symmshlpmatrix(filename, opt); 42 | W=sparse(II, JJ, SS); 43 | A=AA; 44 | 45 | % Parsing Option. 46 | function option = parse_opt(opt) 47 | option = opt; 48 | option_names = {'hs', 'rho', 'htype', 'dtype'}; 49 | if ~isfield(option,'hs'), 50 | option = setfield(option,'hs',2); 51 | end 52 | if ~isfield(option,'rho'), 53 | option = setfield(option,'rho', 3); 54 | end 55 | 56 | if ~isfield(option,'htype'), 57 | option = setfield(option,'htype', 'ddr'); 58 | end 59 | 60 | if ~isfield(option,'dtype'), 61 | option = setfield(option,'dtype', 'euclidean'); 62 | end 63 | 64 | -------------------------------------------------------------------------------- /HKS_release/symmshlp_matrix.m: -------------------------------------------------------------------------------- 1 | function [W A h] = symmshlp_matrix(filename, opt) 2 | % 3 | % Compute the symmetric Laplace-Beltrami matrix from mesh 4 | % 5 | % INPUTS 6 | % filename: off file of triangle mesh. 7 | % opt.htype: the way to compute the parameter h. h = hs * neighborhoodsize 8 | % if htype = 'ddr' (data driven); h = hs if hytpe = 'psp' (pre-specify) 9 | % Default : 'ddr' 10 | % opt.hs: the scaling factor that scales the neighborhood size to the 11 | % parameter h where h^2 = 4t. 12 | % Default: 2, must > 0 13 | % opt.rho: The cut-off for Gaussion function evaluation. 14 | % Default: 3, must > 0 15 | % opt.dtype: the way to compute the distance 16 | % dtype = 'euclidean' or 'geodesic'; 17 | % Default : 'euclidean' 18 | 19 | % 20 | % OUTPUTS 21 | % W: symmetric weight matrix 22 | % A: area weight per vertex, the Laplace matrix = diag(1./ A) * W 23 | % h: Gaussian width: h^2 = 4t 24 | 25 | 26 | if nargin < 1 27 | error('Too few input arguments'); 28 | elseif nargin < 2 29 | opt.hs = 2; 30 | opt.rho = 3; 31 | opt.htype = 'ddr'; 32 | opt.dtype = 'euclidean' 33 | end 34 | opt=parse_opt(opt) 35 | 36 | if opt.hs <= 0 | opt.rho <= 0 37 | error('Invalid values in opt'); 38 | end 39 | 40 | 41 | [II JJ SS AA h] = symmshlpmatrix(filename, opt); 42 | W=sparse(II, JJ, SS); 43 | A=AA; 44 | 45 | % Parsing Option. 46 | function option = parse_opt(opt) 47 | option = opt; 48 | option_names = {'hs', 'rho', 'htype', 'dtype'}; 49 | if ~isfield(option,'hs'), 50 | option = setfield(option,'hs',2); 51 | end 52 | if ~isfield(option,'rho'), 53 | option = setfield(option,'rho', 3); 54 | end 55 | 56 | if ~isfield(option,'htype'), 57 | option = setfield(option,'htype', 'ddr'); 58 | end 59 | 60 | if ~isfield(option,'dtype'), 61 | option = setfield(option,'dtype', 'euclidean'); 62 | end 63 | 64 | -------------------------------------------------------------------------------- /MeshLP/offobj.h: -------------------------------------------------------------------------------- 1 | #ifndef OFFOBJ_H 2 | #define OFFOBJ_H 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "point.h" 11 | 12 | using namespace std; 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | //class for colors 22 | class RGBA { 23 | public: 24 | RGBA() { 25 | } 26 | 27 | RGBA(const RGBA& o) { 28 | r = o.r; g = o.g; b = o.b; a = o.a; 29 | } 30 | 31 | RGBA& operator=(const RGBA& o) { 32 | r = o.r; g = o.g; b = o.b; a = o.a; 33 | return *this; 34 | } 35 | 36 | bool operator==(RGBA& o) { 37 | return (r == o.r) && (g == o.g) && (b == o.b) && (a == o.a); 38 | } 39 | 40 | double r,g,b,a; 41 | }; 42 | 43 | 44 | 45 | class OffObj { 46 | public: 47 | OffObj(); 48 | OffObj(const OffObj& o); 49 | 50 | OffObj& operator=(const OffObj& o); 51 | bool operator==(OffObj& o); 52 | 53 | void writeOff(ofstream & theFile); 54 | void updateBBox(double x, double y, double z); 55 | void orient_facets(); 56 | void calculate_facet_normals(); 57 | void calculate_vert_normals(); 58 | 59 | vector vertices; 60 | vector > facets; 61 | vector vert_colors; 62 | vector facet_colors; 63 | vector > topo_verts; 64 | vector > topo_facets; 65 | vector facet_normals; 66 | vector vert_normals; 67 | 68 | bool is_coff; 69 | 70 | Point bbmin, bbmax; 71 | }; 72 | 73 | 74 | 75 | 76 | class OffFileReader { 77 | public: 78 | OffFileReader(string& filename); 79 | ~OffFileReader(); 80 | 81 | string trim(string& in); 82 | void split(string& in, const string& delims, vector& tokens); 83 | bool get_next_line(vector& tokens); 84 | bool get_next_off_object(OffObj& o); 85 | 86 | bool bad; 87 | 88 | private: 89 | ifstream input; 90 | }; 91 | 92 | 93 | 94 | #endif 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /MeshLP/geodesics/geodesic_matlab_api.h: -------------------------------------------------------------------------------- 1 | #ifndef GEODESIC_DLL_HEADER_HPP_234232 2 | #define GEODESIC_DLL_HEADER_HPP_234232 3 | 4 | #ifndef GEODESIC_DLL_IMPORT 5 | #define GEODESIC_DLL_IMPORT 6 | #endif 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | GEODESIC_DLL_IMPORT long new_mesh(long num_points, //creates new mesh 13 | double* points, 14 | long num_triangles, 15 | long* triangles, 16 | long* num_edges, 17 | double** edges); 18 | 19 | GEODESIC_DLL_IMPORT long new_algorithm(long mesh_id, //creates a geodesic algorithm for a given mesh 20 | long type, 21 | long subdivision); 22 | 23 | GEODESIC_DLL_IMPORT void delete_algorithm(long id); 24 | 25 | GEODESIC_DLL_IMPORT void delete_mesh(long id); //delete mesh and all associated algorithms 26 | 27 | GEODESIC_DLL_IMPORT void propagate(long algorithm_id, //compute distance field for given source points 28 | double* source_points, 29 | long num_sources, 30 | double* stop_points, //limitations on distance field propagation 31 | long num_stop_points, 32 | double max_propagation_distance); 33 | 34 | GEODESIC_DLL_IMPORT long trace_back(long algorithm_id, //using procomputed distance field, compute a shortest path from destination to the closest source 35 | double* destination, 36 | double** path); 37 | 38 | GEODESIC_DLL_IMPORT long distance_and_source(long algorithm_id, //quickly find what source this point belongs to and what is the distance to this source 39 | double* destination, 40 | double* best_source_distance); 41 | 42 | GEODESIC_DLL_IMPORT long distance_and_source_for_all_vertices(long algorithm_id, //same idea as in the previous function 43 | double** distances, //list distance/source info for all vertices of the mesh 44 | long** sources); 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /MeshLP/cotlpmatrix.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "meshlpmatrix.h" 11 | 12 | 13 | using namespace std; 14 | 15 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 16 | { 17 | 18 | /* check for proper number of arguments */ 19 | /* NOTE: You do not need an else statement when using mexErrMsgTxt 20 | * within an if statement, because it will never get to the else 21 | * statement if mexErrMsgTxt is executed. (mexErrMsgTxt breaks you out of 22 | * the MEX-file) 23 | */ 24 | if(nrhs != 1){ 25 | mexErrMsgTxt("One inputs required."); 26 | } 27 | if(nlhs != 4){ 28 | mexErrMsgTxt("Four output required."); 29 | } 30 | 31 | /* check to make sure the first input argument is a string */ 32 | if( mxGetClassID(prhs[0]) != mxCHAR_CLASS){ 33 | mexErrMsgTxt("Input x must be a string."); 34 | } 35 | char* filename; 36 | filename = mxArrayToString(prhs[0]); 37 | //mexPrintf("%s!!!!", filename); 38 | 39 | //cout<<"nn: "< SSV, DDV; 43 | vector IIV, JJV; 44 | 45 | generate_Xu_Meyer_laplace_matrix_matlab(filename, IIV, JJV, SSV, DDV); 46 | 47 | unsigned int dim = DDV.size(); 48 | unsigned int nelem = IIV.size(); 49 | if( nelem != JJV.size() || nelem != SSV.size() ){ 50 | mexErrMsgTxt("Dimension of II, JJ, SS has to be the same"); 51 | } 52 | plhs[0] = mxCreateDoubleMatrix(nelem, 1, mxREAL); 53 | plhs[1] = mxCreateDoubleMatrix(nelem, 1, mxREAL); 54 | plhs[2] = mxCreateDoubleMatrix(nelem, 1, mxREAL); 55 | plhs[3] = mxCreateDoubleMatrix(dim, 1, mxREAL); 56 | II = mxGetPr(plhs[0]); 57 | JJ = mxGetPr(plhs[1]); 58 | SS = mxGetPr(plhs[2]); 59 | DD = mxGetPr(plhs[3]); 60 | 61 | for(mwSize i = 0; i < nelem; i ++){ 62 | II[i] = IIV[i]; 63 | JJ[i] = JJV[i]; 64 | SS[i] = SSV[i]; 65 | } 66 | for(mwSize i = 0; i < dim; i ++){ 67 | DD[i] = DDV[i]; 68 | } 69 | 70 | mxFree(filename); 71 | } 72 | 73 | 74 | -------------------------------------------------------------------------------- /MeshLP/geodesics/geodesic_constants_and_simple_functions.h: -------------------------------------------------------------------------------- 1 | //Copyright (C) 2008 Danil Kirsanov, MIT License 2 | #ifndef GEODESIC_CONSTANTS_20071231 3 | #define GEODESIC_CONSTANTS_20071231 4 | 5 | // some constants and simple math functions 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace geodesic{ 13 | 14 | #ifndef M_PI 15 | #define M_PI 3.14159265358979323846 16 | #endif 17 | 18 | //double const GEODESIC_INF = std::numeric_limits::max(); 19 | double const GEODESIC_INF = 1e100; 20 | 21 | //in order to avoid numerical problems with "infinitely small" intervals, 22 | //we drop all the intervals smaller than SMALLEST_INTERVAL_RATIO*edge_length 23 | double const SMALLEST_INTERVAL_RATIO = 1e-6; 24 | //double const SMALL_EPSILON = 1e-10; 25 | 26 | 27 | inline double cos_from_edges(double const a, //compute the cosine of the angle given the lengths of the edges 28 | double const b, 29 | double const c) 30 | { 31 | assert(a>1e-50); 32 | assert(b>1e-50); 33 | assert(c>1e-50); 34 | 35 | double result = (b*b + c*c - a*a)/(2.0*b*c); 36 | result = std::max(result, -1.0); 37 | return std::min(result, 1.0); 38 | } 39 | 40 | inline double angle_from_edges(double const a, //compute the cosine of the angle given the lengths of the edges 41 | double const b, 42 | double const c) 43 | { 44 | return acos(cos_from_edges(a,b,c)); 45 | } 46 | 47 | template 48 | inline bool read_mesh_from_file(char* filename, 49 | Points& points, 50 | Faces& faces) 51 | { 52 | std::ifstream file(filename); 53 | assert(file.is_open()); 54 | if(!file.is_open()) return false; 55 | 56 | unsigned num_points; 57 | file >> num_points; 58 | assert(num_points>=3); 59 | 60 | unsigned num_faces; 61 | file >> num_faces; 62 | 63 | points.resize(num_points*3); 64 | for(typename Points::iterator i=points.begin(); i!=points.end(); ++i) 65 | { 66 | file >> *i; 67 | } 68 | 69 | faces.resize(num_faces*3); 70 | for(typename Faces::iterator i=faces.begin(); i!=faces.end(); ++i) 71 | { 72 | file >> *i; 73 | } 74 | file.close(); 75 | 76 | return true; 77 | } 78 | 79 | } //geodesic 80 | 81 | #endif //GEODESIC_CONSTANTS_20071231 82 | -------------------------------------------------------------------------------- /MeshLP/makefile: -------------------------------------------------------------------------------- 1 | MATLAB_INC_DIR = /usr/local/matlab-R2009b/extern/include 2 | MATLAB_LIB_DIR1 = /usr/local/matlab-R2009b/bin/glnxa64 3 | MATLAB_LIB_DIR2 = /usr/local/matlab-R2009b/sys/os/glnxa64 4 | 5 | 6 | CXX = g++ 7 | OBJ_EXT = .o 8 | SOBJ_EXT = .so 9 | OBJ_OPT = -c 10 | 11 | MEX = mex 12 | MEXSUFFIX = .mexa64 13 | MEXFLAGS = -cxx CC='$(CXX)' CXX='$(CXX)' LD='$(CXX)' 14 | 15 | #---------------------------------------------------------------------# 16 | # compiler flags 17 | #---------------------------------------------------------------------# 18 | MATLAB_CXXFLAGS = \ 19 | -I$(MATLAB_INC_DIR) 20 | 21 | CXXFLAGS = \ 22 | -fPIC \ 23 | $(MATLAB_CXXFLAGS) \ 24 | -O2 25 | 26 | #---------------------------------------------------------------------# 27 | # linker flags 28 | #---------------------------------------------------------------------# 29 | LDFLAGS_SO = \ 30 | 31 | LDFLAGS_MAT = \ 32 | -L$(MATLAB_LIB_DIR1) -lmat -leng -lut -lmx -licuuc -licudata -licui18n -licuio -lhdf5 \ 33 | -lpthread 34 | 35 | # -L./ -lmeshlpmatrix \ 36 | 37 | #--------------------------------------------------------------------# 38 | # target entries 39 | #---------------------------------------------------------------------# 40 | 41 | 42 | all: \ 43 | symmshlpmatrix$(MEXSUFFIX) \ 44 | cotlpmatrix$(MEXSUFFIX) 45 | 46 | OBJ = \ 47 | tmesh$(OBJ_EXT) \ 48 | comp_meshlpmatrix$(OBJ_EXT) \ 49 | meshlpmatrix$(OBJ_EXT) \ 50 | offobj$(OBJ_EXT) \ 51 | point$(OBJ_EXT) \ 52 | matrix$(OBJ_EXT) 53 | 54 | symmshlpOBJ = \ 55 | symmshlpmatrix$(OBJ_EXT) 56 | 57 | symmshlpmatrix$(MEXSUFFIX): $(symmshlpOBJ) $(OBJ) 58 | mex $(LDFLAGS_MAT) $(MEXFLAGS) $(symmshlpOBJ) $(OBJ) 59 | 60 | cotlpOBJ = \ 61 | cotlpmatrix$(OBJ_EXT) 62 | 63 | cotlpmatrix$(MEXSUFFIX): $(cotlpOBJ) $(OBJ) 64 | mex $(LDFLAGS_MAT) $(MEXFLAGS) $(cotlpOBJ) $(OBJ) 65 | 66 | clean: 67 | rm -f $(OBJ) $(mshlpOBJ) $(cotlpOBJ) $(symmshlpOBJ) 68 | 69 | #---------------------------------------------------------------------# 70 | # suffix rules 71 | #---------------------------------------------------------------------# 72 | 73 | 74 | .C$(OBJ_EXT): 75 | $(CXX) $(CXXFLAGS) $(OBJ_OPT) $< 76 | 77 | -------------------------------------------------------------------------------- /MeshLP/makefile_32: -------------------------------------------------------------------------------- 1 | MATLAB_INC_DIR = /usr/local/matlab-R2009a/extern/include 2 | MATLAB_LIB_DIR1 = /usr/local/matlab-R2009a/bin/glnxa64 3 | MATLAB_LIB_DIR2 = /usr/local/matlab-R2009a/sys/os/glnxa64 4 | 5 | 6 | CXX = g++ 7 | OBJ_EXT = .o 8 | SOBJ_EXT = .so 9 | OBJ_OPT = -c 10 | 11 | MEX = mex 12 | MEXSUFFIX = .mexglx 13 | MEXFLAGS = -cxx CC='$(CXX)' CXX='$(CXX)' LD='$(CXX)' 14 | 15 | #---------------------------------------------------------------------# 16 | # compiler flags 17 | #---------------------------------------------------------------------# 18 | MATLAB_CXXFLAGS = \ 19 | -I$(MATLAB_INC_DIR) 20 | 21 | CXXFLAGS = \ 22 | -fPIC \ 23 | $(MATLAB_CXXFLAGS) \ 24 | -O2 25 | 26 | #---------------------------------------------------------------------# 27 | # linker flags 28 | #---------------------------------------------------------------------# 29 | LDFLAGS_SO = \ 30 | 31 | LDFLAGS_MAT = \ 32 | -L$(MATLAB_LIB_DIR1) -lmat -leng -lut -lmx -licuuc -licudata -licui18n -licuio -lhdf5 \ 33 | -lpthread 34 | 35 | # -L./ -lmeshlpmatrix \ 36 | 37 | #--------------------------------------------------------------------# 38 | # target entries 39 | #---------------------------------------------------------------------# 40 | 41 | 42 | all: \ 43 | symmshlpmatrix$(MEXSUFFIX) \ 44 | cotlpmatrix$(MEXSUFFIX) 45 | 46 | OBJ = \ 47 | tmesh$(OBJ_EXT) \ 48 | comp_meshlpmatrix$(OBJ_EXT) \ 49 | meshlpmatrix$(OBJ_EXT) \ 50 | offobj$(OBJ_EXT) \ 51 | point$(OBJ_EXT) \ 52 | matrix$(OBJ_EXT) 53 | 54 | symmshlpOBJ = \ 55 | symmshlpmatrix$(OBJ_EXT) 56 | 57 | symmshlpmatrix$(MEXSUFFIX): $(symmshlpOBJ) $(OBJ) 58 | mex $(LDFLAGS_MAT) $(MEXFLAGS) $(symmshlpOBJ) $(OBJ) 59 | 60 | cotlpOBJ = \ 61 | cotlpmatrix$(OBJ_EXT) 62 | 63 | cotlpmatrix$(MEXSUFFIX): $(cotlpOBJ) $(OBJ) 64 | mex $(LDFLAGS_MAT) $(MEXFLAGS) $(cotlpOBJ) $(OBJ) 65 | 66 | clean: 67 | rm -f $(OBJ) $(mshlpOBJ) $(cotlpOBJ) $(symmshlpOBJ) 68 | 69 | #---------------------------------------------------------------------# 70 | # suffix rules 71 | #---------------------------------------------------------------------# 72 | 73 | 74 | .C$(OBJ_EXT): 75 | $(CXX) $(CXXFLAGS) $(OBJ_OPT) $< 76 | 77 | -------------------------------------------------------------------------------- /MeshLP/makefile_64: -------------------------------------------------------------------------------- 1 | MATLAB_INC_DIR = /usr/local/matlab-R2009b/extern/include 2 | MATLAB_LIB_DIR1 = /usr/local/matlab-R2009b/bin/glnxa64 3 | MATLAB_LIB_DIR2 = /usr/local/matlab-R2009b/sys/os/glnxa64 4 | 5 | 6 | CXX = g++-4.1 7 | OBJ_EXT = .o 8 | SOBJ_EXT = .so 9 | OBJ_OPT = -c 10 | 11 | MEX = mex 12 | MEXSUFFIX = .mexa64 13 | MEXFLAGS = -cxx CC='$(CXX)' CXX='$(CXX)' LD='$(CXX)' 14 | 15 | #---------------------------------------------------------------------# 16 | # compiler flags 17 | #---------------------------------------------------------------------# 18 | MATLAB_CXXFLAGS = \ 19 | -I$(MATLAB_INC_DIR) 20 | 21 | CXXFLAGS = \ 22 | -fPIC \ 23 | $(MATLAB_CXXFLAGS) \ 24 | -O2 25 | 26 | #---------------------------------------------------------------------# 27 | # linker flags 28 | #---------------------------------------------------------------------# 29 | LDFLAGS_SO = \ 30 | 31 | LDFLAGS_MAT = \ 32 | -L$(MATLAB_LIB_DIR1) -lmat -leng -lut -lmx -licuuc -licudata -licui18n -licuio -lhdf5 \ 33 | -lpthread 34 | 35 | # -L./ -lmeshlpmatrix \ 36 | 37 | #--------------------------------------------------------------------# 38 | # target entries 39 | #---------------------------------------------------------------------# 40 | 41 | 42 | all: \ 43 | symmshlpmatrix$(MEXSUFFIX) \ 44 | cotlpmatrix$(MEXSUFFIX) 45 | 46 | OBJ = \ 47 | tmesh$(OBJ_EXT) \ 48 | comp_meshlpmatrix$(OBJ_EXT) \ 49 | meshlpmatrix$(OBJ_EXT) \ 50 | offobj$(OBJ_EXT) \ 51 | point$(OBJ_EXT) \ 52 | matrix$(OBJ_EXT) 53 | 54 | symmshlpOBJ = \ 55 | symmshlpmatrix$(OBJ_EXT) 56 | 57 | symmshlpmatrix$(MEXSUFFIX): $(symmshlpOBJ) $(OBJ) 58 | mex $(LDFLAGS_MAT) $(MEXFLAGS) $(symmshlpOBJ) $(OBJ) 59 | 60 | cotlpOBJ = \ 61 | cotlpmatrix$(OBJ_EXT) 62 | 63 | cotlpmatrix$(MEXSUFFIX): $(cotlpOBJ) $(OBJ) 64 | mex $(LDFLAGS_MAT) $(MEXFLAGS) $(cotlpOBJ) $(OBJ) 65 | 66 | clean: 67 | rm -f $(OBJ) $(mshlpOBJ) $(cotlpOBJ) $(symmshlpOBJ) 68 | 69 | #---------------------------------------------------------------------# 70 | # suffix rules 71 | #---------------------------------------------------------------------# 72 | 73 | 74 | .C$(OBJ_EXT): 75 | $(CXX) $(CXXFLAGS) $(OBJ_OPT) $< 76 | 77 | -------------------------------------------------------------------------------- /MeshLP/makefile~: -------------------------------------------------------------------------------- 1 | MATLAB_INC_DIR = /usr/local/matlab-R2009b/extern/include 2 | MATLAB_LIB_DIR1 = /usr/local/matlab-R2009b/bin/glnxa64 3 | MATLAB_LIB_DIR2 = /usr/local/matlab-R2009b/sys/os/glnxa64 4 | 5 | 6 | CXX = g++-4.1 7 | OBJ_EXT = .o 8 | SOBJ_EXT = .so 9 | OBJ_OPT = -c 10 | 11 | MEX = mex 12 | MEXSUFFIX = .mexa64 13 | MEXFLAGS = -cxx CC='$(CXX)' CXX='$(CXX)' LD='$(CXX)' 14 | 15 | #---------------------------------------------------------------------# 16 | # compiler flags 17 | #---------------------------------------------------------------------# 18 | MATLAB_CXXFLAGS = \ 19 | -I$(MATLAB_INC_DIR) 20 | 21 | CXXFLAGS = \ 22 | -fPIC \ 23 | $(MATLAB_CXXFLAGS) \ 24 | -O2 25 | 26 | #---------------------------------------------------------------------# 27 | # linker flags 28 | #---------------------------------------------------------------------# 29 | LDFLAGS_SO = \ 30 | 31 | LDFLAGS_MAT = \ 32 | -L$(MATLAB_LIB_DIR1) -lmat -leng -lut -lmx -licuuc -licudata -licui18n -licuio -lhdf5 \ 33 | -lpthread 34 | 35 | # -L./ -lmeshlpmatrix \ 36 | 37 | #--------------------------------------------------------------------# 38 | # target entries 39 | #---------------------------------------------------------------------# 40 | 41 | 42 | all: \ 43 | symmshlpmatrix$(MEXSUFFIX) \ 44 | cotlpmatrix$(MEXSUFFIX) 45 | 46 | OBJ = \ 47 | tmesh$(OBJ_EXT) \ 48 | comp_meshlpmatrix$(OBJ_EXT) \ 49 | meshlpmatrix$(OBJ_EXT) \ 50 | offobj$(OBJ_EXT) \ 51 | point$(OBJ_EXT) \ 52 | matrix$(OBJ_EXT) 53 | 54 | symmshlpOBJ = \ 55 | symmshlpmatrix$(OBJ_EXT) 56 | 57 | symmshlpmatrix$(MEXSUFFIX): $(symmshlpOBJ) $(OBJ) 58 | mex $(LDFLAGS_MAT) $(MEXFLAGS) $(symmshlpOBJ) $(OBJ) 59 | 60 | cotlpOBJ = \ 61 | cotlpmatrix$(OBJ_EXT) 62 | 63 | cotlpmatrix$(MEXSUFFIX): $(cotlpOBJ) $(OBJ) 64 | mex $(LDFLAGS_MAT) $(MEXFLAGS) $(cotlpOBJ) $(OBJ) 65 | 66 | clean: 67 | rm -f $(OBJ) $(mshlpOBJ) $(cotlpOBJ) $(symmshlpOBJ) 68 | 69 | #---------------------------------------------------------------------# 70 | # suffix rules 71 | #---------------------------------------------------------------------# 72 | 73 | 74 | .C$(OBJ_EXT): 75 | $(CXX) $(CXXFLAGS) $(OBJ_OPT) $< 76 | 77 | -------------------------------------------------------------------------------- /MeshLP/point.cpp: -------------------------------------------------------------------------------- 1 | #include "point.h" 2 | 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | double Point::epsilon = 0.00001; 9 | 10 | Point::Point(double x, double y, double z) : 11 | x(x), y(y), z(z) 12 | { 13 | 14 | } 15 | 16 | Point::Point(const Point& o) { 17 | x = o.x; 18 | y = o.y; 19 | z = o.z; 20 | } 21 | 22 | 23 | 24 | Point& Point::operator=(const Point& rhs) { 25 | x = rhs.x; 26 | y = rhs.y; 27 | z = rhs.z; 28 | 29 | return *this; 30 | } 31 | 32 | 33 | void Point::normalize_point() { 34 | double norm = sqrt(x*x + y*y + z*z); 35 | 36 | if (norm != 0.0) { 37 | x /= norm; 38 | y /= norm; 39 | z /= norm; 40 | } else { 41 | x = y = z = 0.0; 42 | } 43 | } 44 | 45 | 46 | Point cross_product(Point a, Point b, Point c) { 47 | double u[3], v[3]; 48 | 49 | u[0] = b.x - a.x; 50 | u[1] = b.y - a.y; 51 | u[2] = b.z - a.z; 52 | 53 | v[0] = c.x - a.x; 54 | v[1] = c.y - a.y; 55 | v[2] = c.z - a.z; 56 | 57 | double x,y,z; 58 | 59 | x = u[1]*v[2] - u[2]*v[1]; 60 | y = u[2]*v[0] - u[0]*v[2]; 61 | z = u[0]*v[1] - u[1]*v[0]; 62 | 63 | return Point(x, y, z); 64 | } 65 | 66 | double dot_product(Point a, Point b) { 67 | return a.x*b.x + a.y*b.y + a.z*b.z; 68 | } 69 | 70 | 71 | Point centroid(vector verts) { 72 | int size = verts.size(); 73 | int i; 74 | 75 | double x = 0, y = 0, z = 0; 76 | for(i=0; i 8 | #include 9 | 10 | #include "geodesic_algorithm_exact.h" 11 | 12 | 13 | int main(int argc, char **argv) 14 | { 15 | if(argc < 2) 16 | { 17 | std::cout << "usage: mesh_file_name [first_vertex] [second_vertex]" << std::endl; //try: "hedgehog_mesh.txt 3 14" or "flat_triangular_mesh.txt 1" 18 | return 0; 19 | } 20 | 21 | std::vector points; 22 | std::vector faces; 23 | 24 | bool success = geodesic::read_mesh_from_file(argv[1],points,faces); 25 | if(!success) 26 | { 27 | std::cout << "something is wrong with the input file" << std::endl; 28 | return 0; 29 | } 30 | 31 | geodesic::Mesh mesh; 32 | mesh.initialize_mesh_data(points, faces); //create internal mesh data structure including edges 33 | 34 | geodesic::GeodesicAlgorithmExact algorithm(&mesh); //create exact algorithm for the mesh 35 | 36 | unsigned source_vertex_index = (argc == 2) ? 0 : atol(argv[2]); 37 | 38 | geodesic::SurfacePoint source(&mesh.vertices()[source_vertex_index]); //create source 39 | std::vector all_sources(1,source); //in general, there could be multiple sources, but now we have only one 40 | 41 | if(argc > 3) //target vertex specified, compute single path 42 | { 43 | unsigned target_vertex_index = atol(argv[3]); 44 | geodesic::SurfacePoint target(&mesh.vertices()[target_vertex_index]); //create source 45 | 46 | std::vector path; //geodesic path is a sequence of SurfacePoints 47 | 48 | bool const lazy_people_flag = false; //there are two ways to do exactly the same 49 | if(lazy_people_flag) 50 | { 51 | algorithm.geodesic(source, target, path); //find a single source-target path 52 | } 53 | else //doing the same thing explicitly for educational reasons 54 | { 55 | double const distance_limit = geodesic::GEODESIC_INF; // no limit for propagation 56 | std::vector stop_points(1, target); //stop propagation when the target is covered 57 | algorithm.propagate(all_sources, distance_limit, &stop_points); //"propagate(all_sources)" is also fine, but take more time because covers the whole mesh 58 | 59 | algorithm.trace_back(target, path); //trace back a single path 60 | } 61 | 62 | print_info_about_path(path); 63 | for(unsigned i = 0; i 5 | #include 6 | #include 7 | 8 | #include "geodesic_algorithm_dijkstra.h" 9 | #include "geodesic_algorithm_subdivision.h" 10 | #include "geodesic_algorithm_exact.h" 11 | 12 | int main(int argc, char **argv) 13 | { 14 | std::vector points; 15 | std::vector faces; 16 | geodesic::read_mesh_from_file("hedgehog_mesh.txt",points,faces); 17 | 18 | geodesic::Mesh mesh; 19 | mesh.initialize_mesh_data(points, faces); //create internal mesh data structure including edges 20 | 21 | geodesic::GeodesicAlgorithmExact exact_algorithm(&mesh); //exact algorithm 22 | geodesic::GeodesicAlgorithmDijkstra dijkstra_algorithm(&mesh); //simplest approximate algorithm: path only allowed on the edges of the mesh 23 | unsigned const subdivision_level = 3; //three additional vertices per every edge in subdivision algorithm 24 | geodesic::GeodesicAlgorithmSubdivision subdivision_algorithm(&mesh,2); //with subdivision_level=0 this algorithm becomes Dijkstra, with subdivision_level->infinity it becomes exact 25 | 26 | std::vector all_algorithms; //for simplicity, store all possible geodesic algorithms here 27 | all_algorithms.push_back(&dijkstra_algorithm); 28 | all_algorithms.push_back(&subdivision_algorithm); 29 | all_algorithms.push_back(&exact_algorithm); 30 | 31 | std::vector sources; 32 | sources.push_back(geodesic::SurfacePoint(&mesh.vertices()[0])); //one source is located at vertex zero 33 | sources.push_back(geodesic::SurfacePoint(&mesh.edges()[12])); //second source is located in the middle of edge 12 34 | sources.push_back(geodesic::SurfacePoint(&mesh.faces()[20])); //third source is located in the middle of face 20 35 | 36 | std::vector targets; //same thing with targets 37 | targets.push_back(geodesic::SurfacePoint(&mesh.vertices().back())); 38 | targets.push_back(geodesic::SurfacePoint(&mesh.edges()[10])); 39 | targets.push_back(geodesic::SurfacePoint(&mesh.faces()[3])); 40 | 41 | for(unsigned index=0; indexname() << std::endl; 45 | 46 | algorithm->propagate(sources); //cover the whole mesh 47 | algorithm->print_statistics(); 48 | 49 | //------------------first task: compute the pathes to the targets---- 50 | std::vector path; 51 | for(int i=0; itrace_back(targets[i], path); 54 | print_info_about_path(path); 55 | } 56 | 57 | //------------------second task: for each source, find the furthest vertex that it covers ---- 58 | std::vector max_distance(sources.size(), 0.0); //distance to the furthest vertex that is covered by the given source 59 | for(int i=0; ibest_source(p,distance); 64 | 65 | max_distance[best_source] = std::max(max_distance[best_source], distance); 66 | } 67 | 68 | std::cout << std::endl; 69 | for(int i=0; i 8 | #include 9 | #include 10 | 11 | namespace geodesic{ 12 | 13 | class DijkstraNode 14 | { 15 | typedef DijkstraNode* node_pointer; 16 | public: 17 | DijkstraNode(){}; 18 | ~DijkstraNode(){}; 19 | 20 | double& distance_from_source(){return m_distance;}; 21 | node_pointer& previous(){return m_previous;}; 22 | unsigned& source_index(){return m_source_index;}; 23 | vertex_pointer& vertex(){return m_vertex;}; 24 | 25 | void clear() 26 | { 27 | m_distance = GEODESIC_INF; 28 | m_previous = NULL; 29 | } 30 | 31 | bool operator()(node_pointer const s1, node_pointer const s2) const 32 | { 33 | return s1->distance_from_source() != s2->distance_from_source() ? 34 | s1->distance_from_source() < s2->distance_from_source() : 35 | s1->vertex()->id() < s2->vertex()->id(); 36 | }; 37 | 38 | double distance(SurfacePoint* p) 39 | { 40 | return m_vertex->distance(p); 41 | } 42 | 43 | SurfacePoint surface_point() 44 | { 45 | return SurfacePoint(m_vertex); 46 | } 47 | 48 | private: 49 | double m_distance; //distance to the closest source 50 | unsigned m_source_index; //closest source index 51 | node_pointer m_previous; //previous node in the geodesic path 52 | vertex_pointer m_vertex; //correspoding vertex 53 | }; 54 | 55 | class GeodesicAlgorithmDijkstra: public GeodesicAlgorithmGraphBase 56 | { 57 | public: 58 | typedef DijkstraNode Node; 59 | typedef Node* node_pointer; 60 | 61 | GeodesicAlgorithmDijkstra(geodesic::Mesh* mesh): 62 | GeodesicAlgorithmGraphBase(mesh) 63 | { 64 | m_type = DIJKSTRA; 65 | 66 | m_nodes.resize(mesh->vertices().size()); 67 | for(unsigned i=0; ivertices()[i]; 70 | } 71 | }; 72 | 73 | ~GeodesicAlgorithmDijkstra(){}; 74 | 75 | protected: 76 | 77 | void list_nodes_visible_from_source(MeshElementBase* p, 78 | std::vector& storage); //list all nodes that belong to this mesh element 79 | 80 | void list_nodes_visible_from_node(node_pointer node, //list all nodes that belong to this mesh element 81 | std::vector& storage, 82 | std::vector& distances, 83 | double threshold_distance); //list only the nodes whose current distance is larger than the threshold 84 | }; 85 | 86 | void GeodesicAlgorithmDijkstra::list_nodes_visible_from_source(MeshElementBase* p, 87 | std::vector& storage) 88 | { 89 | assert(p->type() != UNDEFINED_POINT); 90 | 91 | if(p->type() == FACE) 92 | { 93 | face_pointer f = static_cast(p); 94 | for(unsigned i=0; i<3; ++i) 95 | { 96 | vertex_pointer v = f->adjacent_vertices()[i]; 97 | storage.push_back(&m_nodes[node_index(v)]); 98 | } 99 | } 100 | else if(p->type() == EDGE) 101 | { 102 | edge_pointer e = static_cast(p); 103 | for(unsigned i=0; i<2; ++i) 104 | { 105 | vertex_pointer v = e->adjacent_vertices()[i]; 106 | storage.push_back(&m_nodes[node_index(v)]); 107 | } 108 | } 109 | else //VERTEX 110 | { 111 | vertex_pointer v = static_cast(p); 112 | storage.push_back(&m_nodes[node_index(v)]); 113 | } 114 | } 115 | 116 | inline void GeodesicAlgorithmDijkstra::list_nodes_visible_from_node(node_pointer node, //list all nodes that belong to this mesh element 117 | std::vector& storage, 118 | std::vector& distances, 119 | double threshold_distance) 120 | { 121 | vertex_pointer v = node->vertex(); 122 | assert(storage.size() == distances.size()); 123 | 124 | for(unsigned i=0; iadjacent_edges().size(); ++i) 125 | { 126 | edge_pointer e = v->adjacent_edges()[i]; 127 | vertex_pointer new_v = e->opposite_vertex(v); 128 | node_pointer new_node = &m_nodes[node_index(new_v)]; 129 | 130 | if(new_node->distance_from_source() > threshold_distance + e->length()) 131 | { 132 | storage.push_back(new_node); 133 | distances.push_back(e->length()); 134 | } 135 | } 136 | } 137 | 138 | } //geodesic 139 | 140 | #endif //GEODESIC_ALGORITHM_DIJKSTRA_010506 141 | -------------------------------------------------------------------------------- /MeshLP/geodesics/geodesic_memory.h~: -------------------------------------------------------------------------------- 1 | //Copyright (C) 2008 Danil Kirsanov, MIT License 2 | #ifndef _GEODESIC_MEMORY_20071231 3 | #define _GEODESIC_MEMORY_20071231 4 | 5 | //two fast and simple memory allocators 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace geodesic{ 12 | 13 | template //quickly allocates multiple elements of a given type; no deallocation 14 | class SimlpeMemoryAllocator 15 | { 16 | public: 17 | typedef T* pointer; 18 | 19 | SimlpeMemoryAllocator(unsigned block_size = 0, 20 | unsigned max_number_of_blocks = 0) 21 | { 22 | reset(block_size, 23 | max_number_of_blocks); 24 | }; 25 | 26 | ~SimlpeMemoryAllocator(){}; 27 | 28 | void reset(unsigned block_size, 29 | unsigned max_number_of_blocks) 30 | { 31 | m_block_size = block_size; 32 | m_max_number_of_blocks = max_number_of_blocks; 33 | 34 | 35 | m_current_position = 0; 36 | 37 | m_storage.reserve(max_number_of_blocks); 38 | m_storage.resize(1); 39 | m_storage[0].resize(block_size); 40 | }; 41 | 42 | pointer allocate(unsigned const n) //allocate n units 43 | { 44 | assert(n < m_block_size); 45 | 46 | if(m_current_position + n >= m_block_size) 47 | { 48 | m_storage.push_back( std::vector() ); 49 | m_storage.back().resize(m_block_size); 50 | m_current_position = 0; 51 | } 52 | pointer result = & m_storage.back()[m_current_position]; 53 | m_current_position += n; 54 | 55 | return result; 56 | }; 57 | private: 58 | std::vector > m_storage; 59 | unsigned m_block_size; //size of a single block 60 | unsigned m_max_number_of_blocks; //maximum allowed number of blocks 61 | unsigned m_current_position; //first unused element inside the current block 62 | }; 63 | 64 | 65 | template //quickly allocates and deallocates single elements of a given type 66 | class MemoryAllocator 67 | { 68 | public: 69 | typedef T* pointer; 70 | 71 | MemoryAllocator(unsigned block_size = 1024, 72 | unsigned max_number_of_blocks = 1024) 73 | { 74 | reset(block_size, 75 | max_number_of_blocks); 76 | }; 77 | 78 | ~MemoryAllocator(){}; 79 | 80 | void clear() 81 | { 82 | reset(m_block_size, 83 | m_max_number_of_blocks); 84 | } 85 | 86 | void reset(unsigned block_size, 87 | unsigned max_number_of_blocks) 88 | { 89 | m_block_size = block_size; 90 | m_max_number_of_blocks = max_number_of_blocks; 91 | 92 | assert(m_block_size > 0); 93 | assert(m_max_number_of_blocks > 0); 94 | 95 | m_current_position = 0; 96 | 97 | m_storage.reserve(max_number_of_blocks); 98 | m_storage.resize(1); 99 | m_storage[0].resize(block_size); 100 | 101 | m_deleted.clear(); 102 | m_deleted.reserve(2*block_size); 103 | }; 104 | 105 | pointer allocate() //allocates single unit of memory 106 | { 107 | pointer result; 108 | if(m_deleted.empty()) 109 | { 110 | if(m_current_position + 1 >= m_block_size) 111 | { 112 | m_storage.push_back( std::vector() ); 113 | m_storage.back().resize(m_block_size); 114 | m_current_position = 0; 115 | } 116 | result = & m_storage.back()[m_current_position]; 117 | ++m_current_position; 118 | } 119 | else 120 | { 121 | result = m_deleted.back(); 122 | m_deleted.pop_back(); 123 | } 124 | 125 | return result; 126 | }; 127 | 128 | void deallocate(pointer p) //allocate n units 129 | { 130 | if(m_deleted.size() < m_deleted.capacity()) 131 | { 132 | m_deleted.push_back(p); 133 | } 134 | }; 135 | 136 | private: 137 | std::vector > m_storage; 138 | unsigned m_block_size; //size of a single block 139 | unsigned m_max_number_of_blocks; //maximum allowed number of blocks 140 | unsigned m_current_position; //first unused element inside the current block 141 | 142 | std::vector m_deleted; //pointers to deleted elemets 143 | }; 144 | 145 | 146 | class OutputBuffer 147 | { 148 | public: 149 | OutputBuffer(): 150 | m_num_bytes(0) 151 | {} 152 | 153 | void clear() 154 | { 155 | m_num_bytes = 0; 156 | m_buffer = std::auto_ptr(); 157 | } 158 | 159 | template 160 | T* allocate(unsigned n) 161 | { 162 | double wanted = n*sizeof(T); 163 | if(wanted > m_num_bytes) 164 | { 165 | unsigned new_size = (unsigned) ceil(wanted / (double)sizeof(double)); 166 | m_buffer = std::auto_ptr(new double[new_size]); 167 | m_num_bytes = new_size*sizeof(double); 168 | } 169 | 170 | return (T*)m_buffer.get(); 171 | } 172 | 173 | template 174 | T* get() 175 | { 176 | return (T*)m_buffer.get(); 177 | } 178 | 179 | template 180 | unsigned capacity() 181 | { 182 | return (unsigned)floor((double)m_num_bytes/(double)sizeof(T)); 183 | }; 184 | 185 | private: 186 | 187 | std::auto_ptr m_buffer; 188 | unsigned m_num_bytes; 189 | }; 190 | 191 | 192 | } //geodesic 193 | 194 | #endif //_GEODESIC_MEMORY_20071231 195 | -------------------------------------------------------------------------------- /MeshLP/geodesics/geodesic_memory.h: -------------------------------------------------------------------------------- 1 | //Copyright (C) 2008 Danil Kirsanov, MIT License 2 | #ifndef _GEODESIC_MEMORY_20071231 3 | #define _GEODESIC_MEMORY_20071231 4 | 5 | //two fast and simple memory allocators 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace geodesic{ 13 | 14 | template //quickly allocates multiple elements of a given type; no deallocation 15 | class SimlpeMemoryAllocator 16 | { 17 | public: 18 | typedef T* pointer; 19 | 20 | SimlpeMemoryAllocator(unsigned block_size = 0, 21 | unsigned max_number_of_blocks = 0) 22 | { 23 | reset(block_size, 24 | max_number_of_blocks); 25 | }; 26 | 27 | ~SimlpeMemoryAllocator(){}; 28 | 29 | void reset(unsigned block_size, 30 | unsigned max_number_of_blocks) 31 | { 32 | m_block_size = block_size; 33 | m_max_number_of_blocks = max_number_of_blocks; 34 | 35 | 36 | m_current_position = 0; 37 | 38 | m_storage.reserve(max_number_of_blocks); 39 | m_storage.resize(1); 40 | m_storage[0].resize(block_size); 41 | }; 42 | 43 | pointer allocate(unsigned const n) //allocate n units 44 | { 45 | assert(n < m_block_size); 46 | 47 | if(m_current_position + n >= m_block_size) 48 | { 49 | m_storage.push_back( std::vector() ); 50 | m_storage.back().resize(m_block_size); 51 | m_current_position = 0; 52 | } 53 | pointer result = & m_storage.back()[m_current_position]; 54 | m_current_position += n; 55 | 56 | return result; 57 | }; 58 | private: 59 | std::vector > m_storage; 60 | unsigned m_block_size; //size of a single block 61 | unsigned m_max_number_of_blocks; //maximum allowed number of blocks 62 | unsigned m_current_position; //first unused element inside the current block 63 | }; 64 | 65 | 66 | template //quickly allocates and deallocates single elements of a given type 67 | class MemoryAllocator 68 | { 69 | public: 70 | typedef T* pointer; 71 | 72 | MemoryAllocator(unsigned block_size = 1024, 73 | unsigned max_number_of_blocks = 1024) 74 | { 75 | reset(block_size, 76 | max_number_of_blocks); 77 | }; 78 | 79 | ~MemoryAllocator(){}; 80 | 81 | void clear() 82 | { 83 | reset(m_block_size, 84 | m_max_number_of_blocks); 85 | } 86 | 87 | void reset(unsigned block_size, 88 | unsigned max_number_of_blocks) 89 | { 90 | m_block_size = block_size; 91 | m_max_number_of_blocks = max_number_of_blocks; 92 | 93 | assert(m_block_size > 0); 94 | assert(m_max_number_of_blocks > 0); 95 | 96 | m_current_position = 0; 97 | 98 | m_storage.reserve(max_number_of_blocks); 99 | m_storage.resize(1); 100 | m_storage[0].resize(block_size); 101 | 102 | m_deleted.clear(); 103 | m_deleted.reserve(2*block_size); 104 | }; 105 | 106 | pointer allocate() //allocates single unit of memory 107 | { 108 | pointer result; 109 | if(m_deleted.empty()) 110 | { 111 | if(m_current_position + 1 >= m_block_size) 112 | { 113 | m_storage.push_back( std::vector() ); 114 | m_storage.back().resize(m_block_size); 115 | m_current_position = 0; 116 | } 117 | result = & m_storage.back()[m_current_position]; 118 | ++m_current_position; 119 | } 120 | else 121 | { 122 | result = m_deleted.back(); 123 | m_deleted.pop_back(); 124 | } 125 | 126 | return result; 127 | }; 128 | 129 | void deallocate(pointer p) //allocate n units 130 | { 131 | if(m_deleted.size() < m_deleted.capacity()) 132 | { 133 | m_deleted.push_back(p); 134 | } 135 | }; 136 | 137 | private: 138 | std::vector > m_storage; 139 | unsigned m_block_size; //size of a single block 140 | unsigned m_max_number_of_blocks; //maximum allowed number of blocks 141 | unsigned m_current_position; //first unused element inside the current block 142 | 143 | std::vector m_deleted; //pointers to deleted elemets 144 | }; 145 | 146 | 147 | class OutputBuffer 148 | { 149 | public: 150 | OutputBuffer(): 151 | m_num_bytes(0) 152 | {} 153 | 154 | void clear() 155 | { 156 | m_num_bytes = 0; 157 | m_buffer = std::auto_ptr(); 158 | } 159 | 160 | template 161 | T* allocate(unsigned n) 162 | { 163 | double wanted = n*sizeof(T); 164 | if(wanted > m_num_bytes) 165 | { 166 | unsigned new_size = (unsigned) ceil(wanted / (double)sizeof(double)); 167 | m_buffer = std::auto_ptr(new double[new_size]); 168 | m_num_bytes = new_size*sizeof(double); 169 | } 170 | 171 | return (T*)m_buffer.get(); 172 | } 173 | 174 | template 175 | T* get() 176 | { 177 | return (T*)m_buffer.get(); 178 | } 179 | 180 | template 181 | unsigned capacity() 182 | { 183 | return (unsigned)floor((double)m_num_bytes/(double)sizeof(T)); 184 | }; 185 | 186 | private: 187 | 188 | std::auto_ptr m_buffer; 189 | unsigned m_num_bytes; 190 | }; 191 | 192 | 193 | } //geodesic 194 | 195 | #endif //_GEODESIC_MEMORY_20071231 196 | -------------------------------------------------------------------------------- /MeshLP/tmesh.h: -------------------------------------------------------------------------------- 1 | #ifndef __TMESH_H__ 2 | #define __TMESH_H__ 3 | 4 | #include "datastructure.h" 5 | 6 | //------------------------------------------------------------------- 7 | //VTMesh: vertex class for triangle mesh 8 | //------------------- 9 | #define VTMESH_FLAG_BOUNDARY 0x1 10 | #define VTMESH_FLAG_NMANIFOLD 0x2 11 | #define VTMESH_FLAG_SELECTED 0x4 12 | 13 | class VTMesh : public VertexBase{ 14 | public: 15 | //Constructor 16 | VTMesh():VertexBase(){} 17 | VTMesh(double x, double y, double z):VertexBase(x, y, z){} 18 | VTMesh(VECTOR3 co):VertexBase(co){} 19 | VTMesh(const VTMesh& v):VertexBase(v){ 20 | for(unsigned int i = 0; i < v.n_verts(); i ++) 21 | add_vert( v.vert(i) ); 22 | for(unsigned int i = 0; i < v.n_facets(); i ++) 23 | add_facet( v.facet(i) ); 24 | } 25 | 26 | //Assignment operator 27 | VTMesh& operator = (const VTMesh& v){ 28 | if (this != &v){ 29 | this->VTMesh::~VTMesh(); 30 | new (this) VTMesh(v); 31 | } 32 | return *this; 33 | } 34 | 35 | //Functions for accessing data 36 | unsigned int n_verts() const { return _verts.size(); } 37 | unsigned int vert(unsigned int i) const { return _verts[i]; } 38 | unsigned int add_vert(unsigned int vid){ _verts.push_back(vid); return _verts.size() - 1; } 39 | void remove_vert(unsigned int vid){ 40 | for(unsigned int i = 0; i < _verts.size(); i ++){ 41 | if(vid == _verts[i]){ 42 | _verts[i] = _verts[_verts.size() - 1]; 43 | _verts.pop_back(); 44 | break; 45 | } 46 | }//for i 47 | } 48 | unsigned int add_unique_vert(unsigned int vid){ 49 | for(unsigned int i = 0; i < _verts.size(); i ++) 50 | if(vid == _verts[i]) return i; 51 | _verts.push_back(vid); 52 | return _verts.size() - 1; 53 | } 54 | unsigned int n_facets() const { return _facets.size(); } 55 | unsigned int facet(unsigned int i) const { return _facets[i]; } 56 | unsigned int add_facet(unsigned int fid){ _facets.push_back(fid); return _facets.size() - 1; } 57 | void remove_facet(unsigned int fid){ 58 | for(unsigned int i = 0; i < _facets.size(); i ++){ 59 | if( fid == _facets[i] ){ 60 | _facets[i] = _facets[_facets.size() - 1]; 61 | _facets.pop_back(); 62 | break; 63 | } 64 | }//for i 65 | } 66 | unsigned int add_unique_facet(unsigned int fid){ 67 | for(unsigned int i = 0; i < _facets.size(); i ++) 68 | if(fid == _facets[i]) return i;; 69 | _facets.push_back(fid); 70 | return _facets.size() - 1; 71 | } 72 | 73 | //Functions for some simple operations 74 | int index(unsigned int vid){ 75 | for(unsigned int i = 0; i < _verts.size(); i ++) 76 | if(vid == _verts[i]) return i; 77 | return -1; 78 | } 79 | 80 | private: 81 | vector _facets; 82 | vector _verts; 83 | 84 | }; 85 | //------------------------------------------------------------------- 86 | 87 | //------------------------------------------------------------------- 88 | //FTMesh: facet class for triangle mesh 89 | //------------------- 90 | #define FTMESH_FLAG_NMANIFOLD 0x01 91 | #define FTMESH_FLAG_REVERSE 0x02 92 | #define FTMESH_FLAG_ORIENTATE 0x10 93 | 94 | #define FTMESH_FLAG_BOUNDARY 0x20 95 | 96 | #define FTMESH_FLAG_VISITED 0x04 97 | #define FTMESH_FLAG_IN 0x08 98 | #define FTMESH_FLAG_SELECT 0x40 99 | class FTMesh : public TFacetBase{ 100 | public: 101 | //Constructor 102 | FTMesh():TFacetBase(){} 103 | FTMesh(unsigned int v0, unsigned int v1, unsigned int v2):TFacetBase(v0, v1, v2){} 104 | FTMesh(const FTMesh& f):TFacetBase(f){} 105 | //Assignment operator 106 | FTMesh& operator = (const FTMesh& f){ 107 | if(this != &f){ 108 | this->FTMesh::~FTMesh(); 109 | new (this) FTMesh(f); 110 | } 111 | return *this; 112 | } 113 | private: 114 | }; 115 | //------------------------------------------------------------------- 116 | 117 | class TMesh{ 118 | public: 119 | //Constructor 120 | TMesh(){}; 121 | //Destructor 122 | virtual ~TMesh(){}; 123 | 124 | //Functions for Creation 125 | bool ReadOffFile(char *filename, bool wcolor); 126 | bool ReadOffFile(char *filename); 127 | bool ReadObjFile(char *filename); 128 | void GenerateMeshTopo(); 129 | 130 | bool CheckMeshTopo(); 131 | void PrintMeshTopo(); 132 | void OrientateFacets(); 133 | void MarkNonManifoldness(); 134 | 135 | //Functions for output 136 | void OutMeshOffFile(char *filename); 137 | void OutMeshOffFile(FILE *fp, double r = 0, double g = 1, double b = 0, double a = 0.2); 138 | 139 | 140 | //Function for accessing data 141 | unsigned int v_count() const { return _vertices.size(); } 142 | unsigned int f_count() const { return _facets.size(); } 143 | 144 | unsigned int add_vertex(const VTMesh& v){ _vertices.push_back(v); return (_vertices.size() - 1);} 145 | VTMesh& vertex(unsigned int i ) { return _vertices[i]; } 146 | unsigned int add_facet(const FTMesh& f){ _facets.push_back(f); return (_facets.size() - 1);} 147 | FTMesh& facet(unsigned int i) { return _facets[i]; } 148 | 149 | void copy_name(char* name) { sprintf(name, "%s", _name); } 150 | void set_name(char* name){ sprintf(_name, "%s", name );} 151 | 152 | //Functions for bounding box 153 | void GetBBox(); 154 | bool IsOutBBox(VECTOR3 pt); 155 | void MeshSize(double& maxs, double& mins, double& aves); 156 | VECTOR3 pmin(){ return _pmin; } 157 | VECTOR3 pmax(){ return _pmax; } 158 | 159 | 160 | //Clear 161 | void clear(){ _vertices.clear(); _facets.clear(); } 162 | 163 | private: 164 | char _name[256]; 165 | vector _vertices; 166 | vector _facets; 167 | VECTOR3 _pmin; 168 | VECTOR3 _pmax; 169 | }; 170 | 171 | #endif //_TMESH_H__ 172 | 173 | -------------------------------------------------------------------------------- /MeshLP/symmshlpmatrix.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "meshlpmatrix.h" 11 | 12 | 13 | using namespace std; 14 | 15 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 16 | { 17 | 18 | /* check for proper number of arguments */ 19 | /* NOTE: You do not need an else statement when using mexErrMsgTxt 20 | * within an if statement, because it will never get to the else 21 | * statement if mexErrMsgTxt is executed. (mexErrMsgTxt breaks you out of 22 | * the MEX-file) 23 | */ 24 | if(nrhs < 1){ 25 | mexErrMsgTxt("At least one inputs required."); 26 | } 27 | if(nrhs > 2){ 28 | mexErrMsgTxt("At most two inputs required."); 29 | } 30 | if(nlhs != 5){ 31 | mexErrMsgTxt("Five output required."); 32 | } 33 | 34 | /* check to make sure the first input argument is a string */ 35 | if( mxGetClassID(prhs[0]) != mxCHAR_CLASS){ 36 | mexErrMsgTxt("Input x must be a string."); 37 | } 38 | char* filename; 39 | filename = mxArrayToString(prhs[0]); 40 | //mexPrintf("%s!!!!", filename); 41 | 42 | unsigned int htype = 0, dtype = 0; 43 | double hs = 2, rho = 3; 44 | 45 | if(nrhs == 2){ 46 | const mxArray *opt = prhs[1]; 47 | mxClassID category = mxGetClassID(opt); 48 | if(category != mxSTRUCT_CLASS){ 49 | mexErrMsgTxt("Third input must be a structure"); 50 | } 51 | mwSize total_num_of_elements; 52 | mwIndex index; 53 | int number_of_fields, field_index; 54 | const char *field_name; 55 | const mxArray *field_array_ptr; 56 | total_num_of_elements = mxGetNumberOfElements(opt); 57 | number_of_fields = mxGetNumberOfFields(opt); 58 | 59 | /* Walk through each structure element. */ 60 | for (index=0; index 256){ 93 | buflen = 256; 94 | } 95 | 96 | /* Copy the string data from string_array_ptr and place it into buf. */ 97 | if (mxGetString(field_array_ptr, buf, buflen) == 0){ 98 | if( strcmp(buf, "ddr") == 0 ){ 99 | htype = 0; 100 | } 101 | else if( strcmp(buf, "psp") == 0 ){ 102 | htype = 1; 103 | } 104 | } 105 | } 106 | } 107 | else if(strcmp(field_name, "dtype") == 0){ 108 | mxClassID cat = mxGetClassID(field_array_ptr); 109 | if(cat == mxCHAR_CLASS){ 110 | char buf[256]; 111 | mwSize buflen; 112 | 113 | /* Allocate enough memory to hold the converted string. */ 114 | buflen = mxGetNumberOfElements(field_array_ptr) + 1; 115 | if(buflen > 256){ 116 | buflen = 256; 117 | } 118 | 119 | /* Copy the string data from string_array_ptr and place it into buf. */ 120 | if (mxGetString(field_array_ptr, buf, buflen) == 0){ 121 | if( strcmp(buf, "euclidean") == 0 ){ 122 | dtype = 0; 123 | } 124 | else if( strcmp(buf, "geodesic") == 0 ){ 125 | dtype = 1; 126 | } 127 | //else if( strcmp(buf, "fastmarching") == 0 ){ 128 | // dtype = 2; 129 | //} 130 | 131 | } 132 | } 133 | } 134 | }// for field_index 135 | }//for index 136 | }//if(nrhs == 3) 137 | mexPrintf("dtype: %d, htype: %d, hs: %.2f, rho: %.2f\n", dtype, htype, hs, rho); 138 | 139 | //cout<<"nn: "< SSV, AAV; 143 | vector IIV, JJV; 144 | //unsigned int htype = 0, dtype = 0; 145 | //double hs = 2, rho = 3; 146 | if(dtype == 0){ 147 | generate_sym_meshlp_matrix_matlab(filename, htype, hs, rho, h, IIV, JJV, SSV, AAV); 148 | } 149 | else{ // if (dtype == 1 ) 150 | generate_sym_meshlp_matrix_geod_matlab(filename, htype, hs, rho, h, IIV, JJV, SSV, AAV); 151 | } 152 | //else{ 153 | // generate_sym_meshlp_matrix_geod_matlab_fastmarching(filename, htype, hs, rho, IIV, JJV, SSV, AAV); 154 | //} 155 | 156 | 157 | unsigned int dim = AAV.size(); 158 | unsigned int nelem = IIV.size(); 159 | if( nelem != JJV.size() || nelem != SSV.size() ){ 160 | mexErrMsgTxt("Dimension of II, JJ, SS has to be the same"); 161 | } 162 | plhs[0] = mxCreateDoubleMatrix(nelem, 1, mxREAL); 163 | plhs[1] = mxCreateDoubleMatrix(nelem, 1, mxREAL); 164 | plhs[2] = mxCreateDoubleMatrix(nelem, 1, mxREAL); 165 | plhs[3] = mxCreateDoubleMatrix(dim, 1, mxREAL); 166 | plhs[4] = mxCreateDoubleMatrix(1, 1, mxREAL); 167 | 168 | 169 | II = mxGetPr(plhs[0]); 170 | JJ = mxGetPr(plhs[1]); 171 | SS = mxGetPr(plhs[2]); 172 | AA = mxGetPr(plhs[3]); 173 | pt_h = mxGetPr(plhs[4]); 174 | 175 | cout<<"h: "< 9 | #include 10 | 11 | namespace geodesic{ 12 | 13 | class GeodesicAlgorithmBase 14 | { 15 | public: 16 | enum AlgorithmType 17 | { 18 | EXACT, 19 | DIJKSTRA, 20 | SUBDIVISION, 21 | UNDEFINED_ALGORITHM 22 | }; 23 | 24 | GeodesicAlgorithmBase(geodesic::Mesh* mesh): 25 | m_type(UNDEFINED_ALGORITHM), 26 | m_max_propagation_distance(1e100), 27 | m_mesh(mesh) 28 | {}; 29 | 30 | virtual ~GeodesicAlgorithmBase(){}; 31 | 32 | virtual void propagate(std::vector& sources, 33 | double max_propagation_distance = GEODESIC_INF, //propagation algorithm stops after reaching the certain distance from the source 34 | std::vector* stop_points = NULL) = 0; //or after ensuring that all the stop_points are covered 35 | 36 | virtual void trace_back(SurfacePoint& destination, //trace back piecewise-linear path 37 | std::vector& path) = 0; 38 | 39 | void geodesic(SurfacePoint& source, 40 | SurfacePoint& destination, 41 | std::vector& path); //lazy people can find geodesic path with one function call 42 | 43 | void geodesic(std::vector& sources, 44 | std::vector& destinations, 45 | std::vector >& paths); //lazy people can find geodesic paths with one function call 46 | 47 | virtual unsigned best_source(SurfacePoint& point, //after propagation step is done, quickly find what source this point belongs to and what is the distance to this source 48 | double& best_source_distance) = 0; 49 | 50 | virtual void print_statistics() //print info about timing and memory usage in the propagation step of the algorithm 51 | { 52 | std::cout << "propagation step took " << m_time_consumed << " seconds " << std::endl; 53 | }; 54 | 55 | AlgorithmType type(){return m_type;}; 56 | 57 | virtual std::string name(); 58 | 59 | geodesic::Mesh* mesh(){return m_mesh;}; 60 | protected: 61 | 62 | void set_stop_conditions(std::vector* stop_points, 63 | double stop_distance); 64 | double stop_distance() 65 | { 66 | return m_max_propagation_distance; 67 | } 68 | 69 | AlgorithmType m_type; // type of the algorithm 70 | 71 | typedef std::pair stop_vertex_with_distace_type; 72 | std::vector m_stop_vertices; // algorithm stops propagation after covering certain vertices 73 | double m_max_propagation_distance; // or reaching the certain distance 74 | 75 | geodesic::Mesh* m_mesh; 76 | 77 | double m_time_consumed; //how much time does the propagation step takes 78 | double m_propagation_distance_stopped; //at what distance (if any) the propagation algorithm stopped 79 | }; 80 | 81 | inline double length(std::vector& path) 82 | { 83 | double length = 0; 84 | if(!path.empty()) 85 | { 86 | for(unsigned i=0; i& path) 95 | { 96 | std::cout << "number of the points in the path = " << path.size() 97 | << ", length of the path = " << length(path) 98 | << std::endl; 99 | } 100 | 101 | inline std::string GeodesicAlgorithmBase::name() 102 | { 103 | switch(m_type) 104 | { 105 | case EXACT: 106 | return "exact"; 107 | case DIJKSTRA: 108 | return "dijkstra"; 109 | case SUBDIVISION: 110 | return "subdivision"; 111 | default: 112 | case UNDEFINED_ALGORITHM: 113 | return "undefined"; 114 | } 115 | } 116 | 117 | inline void GeodesicAlgorithmBase::geodesic(SurfacePoint& source, 118 | SurfacePoint& destination, 119 | std::vector& path) //lazy people can find geodesic path with one function call 120 | { 121 | std::vector sources(1, source); 122 | std::vector stop_points(1, destination); 123 | double const max_propagation_distance = GEODESIC_INF; 124 | 125 | propagate(sources, 126 | max_propagation_distance, 127 | &stop_points); 128 | 129 | trace_back(destination, path); 130 | } 131 | 132 | inline void GeodesicAlgorithmBase::geodesic(std::vector& sources, 133 | std::vector& destinations, 134 | std::vector >& paths) //lazy people can find geodesic paths with one function call 135 | { 136 | double const max_propagation_distance = GEODESIC_INF; 137 | 138 | propagate(sources, 139 | max_propagation_distance, 140 | &destinations); //we use desinations as stop points 141 | 142 | paths.resize(destinations.size()); 143 | 144 | for(unsigned i=0; i* stop_points, 151 | double stop_distance) 152 | { 153 | m_max_propagation_distance = stop_distance; 154 | 155 | if(!stop_points) 156 | { 157 | m_stop_vertices.clear(); 158 | return; 159 | } 160 | 161 | m_stop_vertices.resize(stop_points->size()); 162 | 163 | std::vector possible_vertices; 164 | for(unsigned i = 0; i < stop_points->size(); ++i) 165 | { 166 | SurfacePoint* point = &(*stop_points)[i]; 167 | 168 | possible_vertices.clear(); 169 | m_mesh->closest_vertices(point, &possible_vertices); 170 | 171 | vertex_pointer closest_vertex = NULL; 172 | double min_distance = 1e100; 173 | for(unsigned j = 0; j < possible_vertices.size(); ++j) 174 | { 175 | double distance = point->distance(possible_vertices[j]); 176 | if(distance < min_distance) 177 | { 178 | min_distance = distance; 179 | closest_vertex = possible_vertices[j]; 180 | } 181 | } 182 | assert(closest_vertex); 183 | 184 | m_stop_vertices[i].first = closest_vertex; 185 | m_stop_vertices[i].second = min_distance; 186 | } 187 | } 188 | 189 | }//geodesic 190 | 191 | #endif //GEODESIC_ALGORITHM_BASE_122806 192 | -------------------------------------------------------------------------------- /HKS_release/bunnyvf.obj: -------------------------------------------------------------------------------- 1 | v -10.265800 33.899800 0.000000 2 | v -15.398700 32.066700 0.000000 3 | v -22.364800 17.401200 0.000000 4 | v -25.481200 14.651400 0.000000 5 | v -31.530700 14.284800 0.000000 6 | v -34.647100 9.335200 0.000000 7 | v -38.130200 -1.663900 0.000000 8 | v -36.480300 -6.980100 0.000000 9 | v -33.547200 -7.713400 0.000000 10 | v -31.897400 -16.512600 0.000000 11 | v -27.131100 -21.278900 0.000000 12 | v -20.715000 -25.495200 0.000000 13 | v -21.264900 -30.261500 0.000000 14 | v -25.664500 -29.894800 0.000000 15 | v -27.131100 -32.644600 0.000000 16 | v -27.314400 -36.677600 0.000000 17 | v -21.998200 -38.694100 0.000000 18 | v -17.048600 -39.610700 0.000000 19 | v -15.765400 -42.177100 0.000000 20 | v 3.116400 -45.293500 0.000000 21 | v 11.915600 -40.527300 0.000000 22 | v 21.448200 -39.610700 0.000000 23 | v 27.497700 -33.011200 0.000000 24 | v 25.847800 -27.695000 0.000000 25 | v 22.181500 -25.861800 0.000000 26 | v 23.464700 -16.879300 0.000000 27 | v 14.848700 -4.413600 0.000000 28 | v 8.799200 -0.563900 0.000000 29 | v -0.733300 0.352600 0.000000 30 | v -9.349200 2.919100 0.000000 31 | v -13.198900 5.485500 0.000000 32 | v -13.015600 9.151900 0.000000 33 | v 3.299700 14.651400 0.000000 34 | v 7.699300 19.051100 0.000000 35 | v 8.615900 24.184000 0.000000 36 | v 4.216300 26.017200 0.000000 37 | v -12.465600 19.417700 0.000000 38 | v -6.966100 28.033700 0.000000 39 | v -6.416200 31.700000 0.000000 40 | v -23.645600 -33.600600 3.525290 41 | v -19.431400 15.191400 3.597790 42 | v -10.640900 29.652000 3.874170 43 | v -23.274600 -34.022700 3.915100 44 | v 4.177820 21.761500 3.943110 45 | v -10.792700 29.467400 3.996940 46 | v -20.845200 -34.573200 4.261950 47 | v 3.677880 21.150100 4.327780 48 | v -17.348800 -35.041500 4.438180 49 | v -23.662400 10.248600 4.504770 50 | v -12.103600 28.422800 4.539850 51 | v -17.447800 12.506100 4.594180 52 | v 0.544595 19.092500 5.088450 53 | v 21.239500 -31.608400 5.561180 54 | v -31.471600 -1.683050 6.353710 55 | v -28.871000 5.885850 6.547960 56 | v -28.575000 6.518760 6.639030 57 | v -27.725200 7.859300 6.643930 58 | v 17.778500 -32.247500 7.680640 59 | v 12.033300 -31.178900 9.294220 60 | v -24.145300 -0.025780 10.657600 61 | v -24.219800 1.073590 10.786900 62 | v -24.869200 2.154930 11.489400 63 | v -24.899000 1.989650 11.510900 64 | v -8.925980 -28.817200 12.092100 65 | v 7.668890 -26.608700 14.261100 66 | v -18.068800 -9.218610 14.935900 67 | v -15.787200 -10.800500 14.986600 68 | v -17.614100 -9.591340 14.993900 69 | v -5.464750 -28.207400 15.460600 70 | v 3.375550 -16.331800 16.214600 71 | v -3.980900 -16.293200 16.880200 72 | v -2.297770 -16.885900 17.309100 73 | v -0.395834 -24.384500 20.058000 74 | v 0.800616 -20.717100 20.826200 75 | v 1.222400 -22.121000 21.277500 76 | v 1.147060 -22.103000 21.329200 77 | vt 1.000000 0 78 | vt 0.439466 0 79 | vt 0.093472 0 80 | vt 0.082036 0 81 | vt 0.099515 0 82 | vt 0.083728 0 83 | vt 0.056510 0 84 | vt 0.037573 0 85 | vt 0.023925 0 86 | vt 0.011699 0 87 | vt 0.006839 0 88 | vt 0.007614 0 89 | vt 0.015236 0 90 | vt 0.018365 0 91 | vt 0.039651 0 92 | vt 0.082980 0 93 | vt 0.052413 0 94 | vt 0.043907 0 95 | vt 0.056530 0 96 | vt 0.108038 0 97 | vt 0.112806 0 98 | vt 0.213632 0 99 | vt 0.308171 0 100 | vt 0.191015 0 101 | vt 0.103065 0 102 | vt 0.081070 0 103 | vt 0.008579 0 104 | vt 0.003103 0 105 | vt 0.007873 0 106 | vt 0.020900 0 107 | vt 0.031875 0 108 | vt 0.045115 0 109 | vt 0.072950 0 110 | vt 0.180559 0 111 | vt 0.720167 0 112 | vt 0.341631 0 113 | vt 0.101141 0 114 | vt 0.251490 0 115 | vt 0.668445 0 116 | vt 0.023986 0 117 | vt 0.072638 0 118 | vt 0.313865 0 119 | vt 0.023713 0 120 | vt 0.231903 0 121 | vt 0.322875 0 122 | vt 0.022659 0 123 | vt 0.162618 0 124 | vt 0.022976 0 125 | vt 0.053500 0 126 | vt 0.214925 0 127 | vt 0.057302 0 128 | vt 0.103375 0 129 | vt 0.105139 0 130 | vt 0.027840 0 131 | vt 0.043768 0 132 | vt 0.045326 0 133 | vt 0.048550 0 134 | vt 0.079866 0 135 | vt 0.051732 0 136 | vt 0.019964 0 137 | vt 0.022442 0 138 | vt 0.025487 0 139 | vt 0.025114 0 140 | vt 0.013923 0 141 | vt 0.028734 0 142 | vt 0.001464 0 143 | vt 0.000000 0 144 | vt 0.001068 0 145 | vt 0.015553 0 146 | vt 0.008253 0 147 | vt 0.003425 0 148 | vt 0.004955 0 149 | vt 0.015246 0 150 | vt 0.012077 0 151 | vt 0.014216 0 152 | vt 0.014139 0 153 | f 1/1 42/42 39/39 154 | f 2/2 50/50 45/45 155 | f 2/2 45/45 42/42 156 | f 2/2 42/42 1/1 157 | f 3/3 41/41 50/50 158 | f 3/3 50/50 2/2 159 | f 4/4 49/49 41/41 160 | f 4/4 41/41 3/3 161 | f 5/5 57/57 49/49 162 | f 5/5 49/49 4/4 163 | f 6/6 56/56 57/57 164 | f 6/6 57/57 5/5 165 | f 7/7 54/54 63/63 166 | f 7/7 63/63 62/62 167 | f 7/7 62/62 55/55 168 | f 7/7 55/55 56/56 169 | f 7/7 56/56 6/6 170 | f 8/8 54/54 7/7 171 | f 9/9 61/61 63/63 172 | f 9/9 63/63 54/54 173 | f 9/9 54/54 8/8 174 | f 10/10 66/66 60/60 175 | f 10/10 60/60 61/61 176 | f 10/10 61/61 9/9 177 | f 11/11 68/68 66/66 178 | f 11/11 66/66 10/10 179 | f 12/12 72/72 71/71 180 | f 12/12 71/71 67/67 181 | f 12/12 67/67 68/68 182 | f 12/12 68/68 11/11 183 | f 13/13 48/48 64/64 184 | f 13/13 64/64 69/69 185 | f 13/13 69/69 73/73 186 | f 13/13 73/73 76/76 187 | f 13/13 76/76 74/74 188 | f 13/13 74/74 72/72 189 | f 13/13 72/72 12/12 190 | f 14/14 40/40 43/43 191 | f 14/14 43/43 46/46 192 | f 14/14 46/46 48/48 193 | f 14/14 48/48 13/13 194 | f 15/15 40/40 14/14 195 | f 16/16 43/43 40/40 196 | f 16/16 40/40 15/15 197 | f 17/17 46/46 43/43 198 | f 17/17 43/43 16/16 199 | f 18/18 64/64 48/48 200 | f 18/18 48/48 46/46 201 | f 18/18 46/46 17/17 202 | f 19/19 69/69 64/64 203 | f 19/19 64/64 18/18 204 | f 20/20 73/73 69/69 205 | f 20/20 69/69 19/19 206 | f 21/21 65/65 75/75 207 | f 21/21 75/75 76/76 208 | f 21/21 76/76 73/73 209 | f 21/21 73/73 20/20 210 | f 59/59 65/65 21/21 211 | f 59/59 21/21 22/22 212 | f 59/59 22/22 58/58 213 | f 23/23 53/53 58/58 214 | f 23/23 58/58 22/22 215 | f 24/24 53/53 23/23 216 | f 25/25 59/59 58/58 217 | f 25/25 58/58 53/53 218 | f 25/25 53/53 24/24 219 | f 26/26 75/75 65/65 220 | f 26/26 65/65 59/59 221 | f 26/26 59/59 25/25 222 | f 27/27 70/70 74/74 223 | f 27/27 74/74 76/76 224 | f 27/27 76/76 75/75 225 | f 27/27 75/75 26/26 226 | f 28/28 70/70 27/27 227 | f 29/29 71/71 72/72 228 | f 29/29 72/72 74/74 229 | f 29/29 74/74 70/70 230 | f 29/29 70/70 28/28 231 | f 30/30 67/67 71/71 232 | f 30/30 71/71 29/29 233 | f 31/31 60/60 66/66 234 | f 31/31 66/66 68/68 235 | f 31/31 68/68 67/67 236 | f 31/31 67/67 30/30 237 | f 32/32 51/51 62/62 238 | f 32/32 62/62 63/63 239 | f 32/32 63/63 61/61 240 | f 32/32 61/61 60/60 241 | f 32/32 60/60 31/31 242 | f 33/33 52/52 51/51 243 | f 33/33 51/51 32/32 244 | f 34/34 47/47 52/52 245 | f 34/34 52/52 33/33 246 | f 35/35 44/44 47/47 247 | f 35/35 47/47 34/34 248 | f 36/36 44/44 35/35 249 | f 55/55 51/51 37/37 250 | f 37/37 51/51 52/52 251 | f 37/37 52/52 36/36 252 | f 36/36 52/52 47/47 253 | f 36/36 47/47 44/44 254 | f 51/51 55/55 62/62 255 | f 50/50 41/41 37/37 256 | f 50/50 37/37 38/38 257 | f 50/50 38/38 45/45 258 | f 49/49 57/57 56/56 259 | f 49/49 56/56 55/55 260 | f 49/49 55/55 37/37 261 | f 49/49 37/37 41/41 262 | f 39/39 42/42 45/45 263 | f 39/39 45/45 38/38 264 | -------------------------------------------------------------------------------- /MeshLP/geodesics/flat_triangular_mesh.txt: -------------------------------------------------------------------------------- 1 | 121 200 2 | 1.500000 -1.000000 0.000000 3 | 1.500000 -0.800000 0.000000 4 | 1.500000 -0.600000 0.000000 5 | 1.500000 -0.400000 0.000000 6 | 1.500000 -0.200000 0.000000 7 | 1.500000 0.000000 0.000000 8 | 1.500000 0.200000 0.000000 9 | 1.500000 0.400000 0.000000 10 | 1.500000 0.600000 0.000000 11 | 1.500000 0.800000 0.000000 12 | 1.500000 1.000000 0.000000 13 | 1.700000 -1.000000 0.000000 14 | 1.700000 -0.800000 0.000000 15 | 1.700000 -0.600000 0.000000 16 | 1.700000 -0.400000 0.000000 17 | 1.700000 -0.200000 0.000000 18 | 1.700000 0.000000 0.000000 19 | 1.700000 0.200000 0.000000 20 | 1.700000 0.400000 0.000000 21 | 1.700000 0.600000 0.000000 22 | 1.700000 0.800000 0.000000 23 | 1.700000 1.000000 0.000000 24 | 1.900000 -1.000000 0.000000 25 | 1.900000 -0.800000 0.000000 26 | 1.900000 -0.600000 0.000000 27 | 1.900000 -0.400000 0.000000 28 | 1.900000 -0.200000 0.000000 29 | 1.900000 0.000000 0.000000 30 | 1.900000 0.200000 0.000000 31 | 1.900000 0.400000 0.000000 32 | 1.900000 0.600000 0.000000 33 | 1.900000 0.800000 0.000000 34 | 1.900000 1.000000 0.000000 35 | 2.100000 -1.000000 0.000000 36 | 2.100000 -0.800000 0.000000 37 | 2.100000 -0.600000 0.000000 38 | 2.100000 -0.400000 0.000000 39 | 2.100000 -0.200000 0.000000 40 | 2.100000 0.000000 0.000000 41 | 2.100000 0.200000 0.000000 42 | 2.100000 0.400000 0.000000 43 | 2.100000 0.600000 0.000000 44 | 2.100000 0.800000 0.000000 45 | 2.100000 1.000000 0.000000 46 | 2.300000 -1.000000 0.000000 47 | 2.300000 -0.800000 0.000000 48 | 2.300000 -0.600000 0.000000 49 | 2.300000 -0.400000 0.000000 50 | 2.300000 -0.200000 0.000000 51 | 2.300000 0.000000 0.000000 52 | 2.300000 0.200000 0.000000 53 | 2.300000 0.400000 0.000000 54 | 2.300000 0.600000 0.000000 55 | 2.300000 0.800000 0.000000 56 | 2.300000 1.000000 0.000000 57 | 2.500000 -1.000000 0.000000 58 | 2.500000 -0.800000 0.000000 59 | 2.500000 -0.600000 0.000000 60 | 2.500000 -0.400000 0.000000 61 | 2.500000 -0.200000 0.000000 62 | 2.500000 0.000000 0.000000 63 | 2.500000 0.200000 0.000000 64 | 2.500000 0.400000 0.000000 65 | 2.500000 0.600000 0.000000 66 | 2.500000 0.800000 0.000000 67 | 2.500000 1.000000 0.000000 68 | 2.700000 -1.000000 0.000000 69 | 2.700000 -0.800000 0.000000 70 | 2.700000 -0.600000 0.000000 71 | 2.700000 -0.400000 0.000000 72 | 2.700000 -0.200000 0.000000 73 | 2.700000 0.000000 0.000000 74 | 2.700000 0.200000 0.000000 75 | 2.700000 0.400000 0.000000 76 | 2.700000 0.600000 0.000000 77 | 2.700000 0.800000 0.000000 78 | 2.700000 1.000000 0.000000 79 | 2.900000 -1.000000 0.000000 80 | 2.900000 -0.800000 0.000000 81 | 2.900000 -0.600000 0.000000 82 | 2.900000 -0.400000 0.000000 83 | 2.900000 -0.200000 0.000000 84 | 2.900000 0.000000 0.000000 85 | 2.900000 0.200000 0.000000 86 | 2.900000 0.400000 0.000000 87 | 2.900000 0.600000 0.000000 88 | 2.900000 0.800000 0.000000 89 | 2.900000 1.000000 0.000000 90 | 3.100000 -1.000000 0.000000 91 | 3.100000 -0.800000 0.000000 92 | 3.100000 -0.600000 0.000000 93 | 3.100000 -0.400000 0.000000 94 | 3.100000 -0.200000 0.000000 95 | 3.100000 0.000000 0.000000 96 | 3.100000 0.200000 0.000000 97 | 3.100000 0.400000 0.000000 98 | 3.100000 0.600000 0.000000 99 | 3.100000 0.800000 0.000000 100 | 3.100000 1.000000 0.000000 101 | 3.300000 -1.000000 0.000000 102 | 3.300000 -0.800000 0.000000 103 | 3.300000 -0.600000 0.000000 104 | 3.300000 -0.400000 0.000000 105 | 3.300000 -0.200000 0.000000 106 | 3.300000 0.000000 0.000000 107 | 3.300000 0.200000 0.000000 108 | 3.300000 0.400000 0.000000 109 | 3.300000 0.600000 0.000000 110 | 3.300000 0.800000 0.000000 111 | 3.300000 1.000000 0.000000 112 | 3.500000 -1.000000 0.000000 113 | 3.500000 -0.800000 0.000000 114 | 3.500000 -0.600000 0.000000 115 | 3.500000 -0.400000 0.000000 116 | 3.500000 -0.200000 0.000000 117 | 3.500000 0.000000 0.000000 118 | 3.500000 0.200000 0.000000 119 | 3.500000 0.400000 0.000000 120 | 3.500000 0.600000 0.000000 121 | 3.500000 0.800000 0.000000 122 | 3.500000 1.000000 0.000000 123 | 0 1 11 124 | 1 11 12 125 | 1 2 12 126 | 2 12 13 127 | 2 3 13 128 | 3 13 14 129 | 3 4 14 130 | 4 14 15 131 | 4 5 15 132 | 5 15 16 133 | 5 6 16 134 | 6 16 17 135 | 6 7 17 136 | 7 17 18 137 | 7 8 18 138 | 8 18 19 139 | 8 9 19 140 | 9 19 20 141 | 9 10 20 142 | 10 20 21 143 | 11 12 22 144 | 12 22 23 145 | 12 13 23 146 | 13 23 24 147 | 13 14 24 148 | 14 24 25 149 | 14 15 25 150 | 15 25 26 151 | 15 16 26 152 | 16 26 27 153 | 16 17 27 154 | 17 27 28 155 | 17 18 28 156 | 18 28 29 157 | 18 19 29 158 | 19 29 30 159 | 19 20 30 160 | 20 30 31 161 | 20 21 31 162 | 21 31 32 163 | 22 23 33 164 | 23 33 34 165 | 23 24 34 166 | 24 34 35 167 | 24 25 35 168 | 25 35 36 169 | 25 26 36 170 | 26 36 37 171 | 26 27 37 172 | 27 37 38 173 | 27 28 38 174 | 28 38 39 175 | 28 29 39 176 | 29 39 40 177 | 29 30 40 178 | 30 40 41 179 | 30 31 41 180 | 31 41 42 181 | 31 32 42 182 | 32 42 43 183 | 33 34 44 184 | 34 44 45 185 | 34 35 45 186 | 35 45 46 187 | 35 36 46 188 | 36 46 47 189 | 36 37 47 190 | 37 47 48 191 | 37 38 48 192 | 38 48 49 193 | 38 39 49 194 | 39 49 50 195 | 39 40 50 196 | 40 50 51 197 | 40 41 51 198 | 41 51 52 199 | 41 42 52 200 | 42 52 53 201 | 42 43 53 202 | 43 53 54 203 | 44 45 55 204 | 45 55 56 205 | 45 46 56 206 | 46 56 57 207 | 46 47 57 208 | 47 57 58 209 | 47 48 58 210 | 48 58 59 211 | 48 49 59 212 | 49 59 60 213 | 49 50 60 214 | 50 60 61 215 | 50 51 61 216 | 51 61 62 217 | 51 52 62 218 | 52 62 63 219 | 52 53 63 220 | 53 63 64 221 | 53 54 64 222 | 54 64 65 223 | 55 56 66 224 | 56 66 67 225 | 56 57 67 226 | 57 67 68 227 | 57 58 68 228 | 58 68 69 229 | 58 59 69 230 | 59 69 70 231 | 59 60 70 232 | 60 70 71 233 | 60 61 71 234 | 61 71 72 235 | 61 62 72 236 | 62 72 73 237 | 62 63 73 238 | 63 73 74 239 | 63 64 74 240 | 64 74 75 241 | 64 65 75 242 | 65 75 76 243 | 66 67 77 244 | 67 77 78 245 | 67 68 78 246 | 68 78 79 247 | 68 69 79 248 | 69 79 80 249 | 69 70 80 250 | 70 80 81 251 | 70 71 81 252 | 71 81 82 253 | 71 72 82 254 | 72 82 83 255 | 72 73 83 256 | 73 83 84 257 | 73 74 84 258 | 74 84 85 259 | 74 75 85 260 | 75 85 86 261 | 75 76 86 262 | 76 86 87 263 | 77 78 88 264 | 78 88 89 265 | 78 79 89 266 | 79 89 90 267 | 79 80 90 268 | 80 90 91 269 | 80 81 91 270 | 81 91 92 271 | 81 82 92 272 | 82 92 93 273 | 82 83 93 274 | 83 93 94 275 | 83 84 94 276 | 84 94 95 277 | 84 85 95 278 | 85 95 96 279 | 85 86 96 280 | 86 96 97 281 | 86 87 97 282 | 87 97 98 283 | 88 89 99 284 | 89 99 100 285 | 89 90 100 286 | 90 100 101 287 | 90 91 101 288 | 91 101 102 289 | 91 92 102 290 | 92 102 103 291 | 92 93 103 292 | 93 103 104 293 | 93 94 104 294 | 94 104 105 295 | 94 95 105 296 | 95 105 106 297 | 95 96 106 298 | 96 106 107 299 | 96 97 107 300 | 97 107 108 301 | 97 98 108 302 | 98 108 109 303 | 99 100 110 304 | 100 110 111 305 | 100 101 111 306 | 101 111 112 307 | 101 102 112 308 | 102 112 113 309 | 102 103 113 310 | 103 113 114 311 | 103 104 114 312 | 104 114 115 313 | 104 105 115 314 | 105 115 116 315 | 105 106 116 316 | 106 116 117 317 | 106 107 117 318 | 107 117 118 319 | 107 108 118 320 | 108 118 119 321 | 108 109 119 322 | 109 119 120 323 | -------------------------------------------------------------------------------- /MeshLP/geodesics/geodesic_matlab_api.cpp: -------------------------------------------------------------------------------- 1 | #define GEODESIC_DLL_IMPORT __declspec(dllexport) 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "geodesic_mesh.h" 10 | #include "geodesic_algorithm_dijkstra_alternative.h" 11 | #include "geodesic_algorithm_dijkstra.h" 12 | #include "geodesic_algorithm_subdivision.h" 13 | #include "geodesic_algorithm_exact.h" 14 | #include "geodesic_matlab_api.h" 15 | 16 | typedef boost::shared_ptr mesh_shared_pointer; 17 | std::vector meshes; 18 | 19 | typedef boost::shared_ptr algorithm_shared_pointer; 20 | std::vector algorithms; 21 | 22 | std::vector output_path; 23 | geodesic::OutputBuffer output_buffer, output_buffer1; 24 | 25 | 26 | std::size_t find_mesh_id(geodesic::Mesh* mesh) 27 | { 28 | for(std::size_t i=0; imesh()); 44 | geodesic::fill_surface_point_structure(&point, 45 | destination, 46 | algorithm->mesh()); 47 | 48 | std::size_t best_source = algorithm->best_source(point, 49 | *best_source_distance); 50 | return best_source; 51 | } 52 | 53 | GEODESIC_DLL_IMPORT long distance_and_source_for_all_vertices(long algorithm_id, //same idea as in the previous function 54 | double** distances, //list distance/source info for all vertices of the mesh 55 | long** sources) 56 | { 57 | 58 | geodesic::GeodesicAlgorithmBase* algorithm = algorithms[algorithm_id].get(); 59 | geodesic::Mesh* mesh = algorithm->mesh(); 60 | 61 | output_buffer.allocate(mesh->vertices().size()); //allocate space for distances 62 | *distances = output_buffer.get(); 63 | 64 | output_buffer1.allocate(mesh->vertices().size()); //allocate space for sources 65 | *sources = output_buffer1.get(); 66 | 67 | 68 | for(std::size_t i = 0; i < mesh->vertices().size(); ++i) 69 | { 70 | geodesic::SurfacePoint point(&mesh->vertices()[i]); 71 | double* distace_location = *distances + i; 72 | (*sources)[i] = algorithm->best_source(point, *distace_location); 73 | } 74 | 75 | return mesh->vertices().size(); 76 | } 77 | 78 | 79 | GEODESIC_DLL_IMPORT long trace_back(long algorithm_id, 80 | double* destination, 81 | double** path) 82 | { 83 | geodesic::SurfacePoint point; 84 | geodesic::GeodesicAlgorithmBase* algorithm = algorithms[algorithm_id].get(); 85 | geodesic::fill_surface_point_structure(&point, 86 | destination, 87 | algorithm->mesh()); 88 | 89 | algorithm->trace_back(point, 90 | output_path); 91 | 92 | std::size_t mesh_id = find_mesh_id(algorithm->mesh()); 93 | output_buffer.allocate(output_path.size()*5); 94 | for(std::size_t i=0; i() + 5*i, 98 | mesh_id); 99 | } 100 | 101 | *path = output_buffer.get(); 102 | 103 | return output_path.size(); 104 | } 105 | 106 | GEODESIC_DLL_IMPORT void propagate(long algorithm_id, 107 | double* source_points, 108 | long num_sources, 109 | double* stop_points, 110 | long num_stop_points, 111 | double max_propagation_distance) 112 | { 113 | std::vector sources(num_sources); 114 | 115 | geodesic::Mesh* mesh = algorithms[algorithm_id]->mesh(); 116 | for(std::size_t i=0; i stop(num_stop_points); 124 | for(std::size_t i=0; ipropagate(sources, 132 | max_propagation_distance, 133 | &stop); 134 | } 135 | 136 | 137 | GEODESIC_DLL_IMPORT long new_mesh(long num_points, 138 | double* points, 139 | long num_triangles, 140 | long* triangles, 141 | long* num_edges, 142 | double** edges) 143 | { 144 | mesh_shared_pointer new_mesh = mesh_shared_pointer(new geodesic::Mesh); 145 | meshes.push_back(new_mesh); 146 | 147 | new_mesh->initialize_mesh_data(num_points, 148 | points, 149 | num_triangles, 150 | triangles); 151 | 152 | *num_edges = new_mesh->edges().size(); 153 | 154 | output_buffer.allocate(*num_edges * 4); 155 | *edges = output_buffer.get(); 156 | 157 | for(std::size_t i=0; i<*num_edges; ++i) 158 | { 159 | geodesic::Edge& edge = new_mesh->edges()[i]; 160 | double* buffer = *edges + 4*i; 161 | 162 | buffer[0] = edge.adjacent_vertices()[0]->id(); 163 | buffer[1] = edge.adjacent_vertices()[1]->id(); 164 | buffer[2] = edge.adjacent_faces()[0]->id(); 165 | buffer[3] = edge.adjacent_faces().size() == 2 ? 166 | edge.adjacent_faces()[1]->id() : 167 | -1; 168 | } 169 | 170 | return meshes.size() - 1; 171 | } 172 | 173 | GEODESIC_DLL_IMPORT long new_algorithm(long mesh_id, 174 | long type, 175 | long subdivision) 176 | { 177 | if(subdivision == 0 && type == 1)//SUBDIVISION) 178 | { 179 | type = 2; //DIJKSTRA; 180 | } 181 | 182 | geodesic::Mesh* mesh = meshes[mesh_id].get(); 183 | geodesic::GeodesicAlgorithmBase* algorithm; 184 | switch(type) 185 | { 186 | case 2: //DIJKSTRA 187 | { 188 | algorithm = new geodesic::GeodesicAlgorithmDijkstra(mesh); 189 | break; 190 | } 191 | case 1: //SUBDIVISION: 192 | { 193 | algorithm = new geodesic::GeodesicAlgorithmSubdivision(mesh, subdivision); 194 | break; 195 | } 196 | case 0://EXACT: 197 | default: 198 | { 199 | algorithm = new geodesic::GeodesicAlgorithmExact(mesh); 200 | break; 201 | } 202 | } 203 | 204 | algorithms.push_back(algorithm_shared_pointer(algorithm)); 205 | 206 | return algorithms.size() - 1; 207 | } 208 | 209 | GEODESIC_DLL_IMPORT void delete_mesh(long id) //delete mesh and all related algorithms 210 | { 211 | assert(id < meshes.size()); 212 | 213 | geodesic::Mesh* mesh = meshes[id].get(); 214 | for(std::size_t i=0; imesh() == mesh) 218 | { 219 | algorithms[i] = algorithm_shared_pointer(); 220 | } 221 | } 222 | 223 | meshes[id] = mesh_shared_pointer(); 224 | } 225 | 226 | GEODESIC_DLL_IMPORT void delete_algorithm(long id) 227 | { 228 | if(id < algorithms.size()) 229 | { 230 | algorithms[id] = algorithm_shared_pointer(); 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /MeshLP/geodesics/geodesic_algorithm_subdivision.h: -------------------------------------------------------------------------------- 1 | //Copyright (C) 2008 Danil Kirsanov, MIT License 2 | #ifndef GEODESIC_ALGORITHM_SUBDIVISION_122806 3 | #define GEODESIC_ALGORITHM_SUBDIVISION_122806 4 | 5 | #include "geodesic_algorithm_graph_base.h" 6 | #include "geodesic_mesh_elements.h" 7 | #include 8 | #include 9 | #include 10 | 11 | namespace geodesic{ 12 | 13 | class SubdivisionNode: public SurfacePoint 14 | { 15 | typedef SubdivisionNode* node_pointer; 16 | public: 17 | SubdivisionNode(){}; 18 | 19 | template 20 | SubdivisionNode(Pointer p): 21 | SurfacePoint(p), 22 | m_previous(NULL), 23 | m_distance(0.0) 24 | {}; 25 | 26 | template 27 | SubdivisionNode(Pointer p, Parameter param): 28 | SurfacePoint(p, param), 29 | m_previous(NULL), 30 | m_distance(0.0) 31 | {}; 32 | 33 | ~SubdivisionNode(){}; 34 | 35 | double& distance_from_source(){return m_distance;}; 36 | node_pointer& previous(){return m_previous;}; 37 | unsigned& source_index(){return m_source_index;}; 38 | 39 | void clear() 40 | { 41 | m_distance = GEODESIC_INF; 42 | m_previous = NULL; 43 | } 44 | 45 | bool operator()(node_pointer const s1, node_pointer const s2) const 46 | { 47 | if(s1 == s2) 48 | { 49 | return false; 50 | } 51 | if(s1->distance_from_source() != s2->distance_from_source()) 52 | { 53 | return s1->distance_from_source() < s2->distance_from_source(); 54 | } 55 | /* if(s1->type() != s2->type()) 56 | { 57 | return s1->type() < s2->type(); 58 | } 59 | if(s1->base_element()->id() != s2->base_element()->id()) 60 | { 61 | return s1->base_element()->id() < s2->base_element()->id(); 62 | } */ 63 | if(s1->x() != s2->x()) //two nodes cannot be located in the same space 64 | { 65 | return s1->x() < s2->x(); 66 | } 67 | if(s1->y() != s2->y()) 68 | { 69 | return s1->y() < s2->y(); 70 | } 71 | if(s1->z() != s2->z()) 72 | { 73 | return s1->z() < s2->z(); 74 | } 75 | 76 | assert(0); 77 | return true; 78 | }; 79 | 80 | SurfacePoint& surface_point(){return static_cast(*this);}; 81 | 82 | private: 83 | double m_distance; //distance to the closest source 84 | unsigned m_source_index; //closest source index 85 | node_pointer m_previous; //previous node in the geodesic path 86 | }; 87 | 88 | class GeodesicAlgorithmSubdivision: public GeodesicAlgorithmGraphBase 89 | { 90 | typedef SubdivisionNode Node; 91 | public: 92 | GeodesicAlgorithmSubdivision(geodesic::Mesh* mesh = NULL, 93 | unsigned subdivision_level = 0): 94 | GeodesicAlgorithmGraphBase(mesh) 95 | { 96 | m_type = SUBDIVISION; 97 | 98 | m_nodes.reserve(mesh->vertices().size()); 99 | for(unsigned i=0; ivertices().size(); ++i) 100 | { 101 | vertex_pointer v = &mesh->vertices()[i]; 102 | m_nodes.push_back(Node(v)); //!! 103 | } 104 | 105 | set_subdivision_level(subdivision_level); 106 | }; 107 | 108 | ~GeodesicAlgorithmSubdivision(){}; 109 | 110 | unsigned subdivision_level(){return m_subdivision_level;}; 111 | 112 | void set_subdivision_level(unsigned subdivision_level) 113 | { 114 | m_subdivision_level = subdivision_level; 115 | 116 | m_nodes.resize(m_mesh->vertices().size()); 117 | m_nodes.reserve(m_mesh->vertices().size() + 118 | m_mesh->edges().size()*subdivision_level); 119 | 120 | for(unsigned i=0; iedges().size(); ++i) 121 | { 122 | edge_pointer e = &m_mesh->edges()[i]; 123 | for(unsigned i=0; i& storage); //list all nodes that belong to this mesh element 134 | 135 | void list_nodes_visible_from_node(node_pointer node, //list all nodes that belong to this mesh element 136 | std::vector& storage, 137 | std::vector& distances, 138 | double threshold_distance); //list only the nodes whose current distance is larger than the threshold 139 | 140 | unsigned node_indexx(edge_pointer e) 141 | { 142 | return e->id()*m_subdivision_level + m_mesh->vertices().size(); 143 | }; 144 | 145 | private: 146 | void list_nodes(MeshElementBase* p, //list nodes that belong to this mesh element 147 | std::vector& storage, 148 | double threshold_distance = -1.0); //list only the nodes whose current distance is larger than the threshold 149 | 150 | unsigned m_subdivision_level; //when level is equal to 1, this algorithm corresponds to the Dijkstra algorithm 151 | }; 152 | 153 | inline void GeodesicAlgorithmSubdivision::list_nodes(MeshElementBase* p, 154 | std::vector& storage, 155 | double threshold_distance) 156 | { 157 | assert(p->type() != UNDEFINED_POINT); 158 | 159 | if(p->type() == VERTEX) 160 | { 161 | vertex_pointer v = static_cast(p); 162 | node_pointer node = &m_nodes[node_index(v)]; 163 | if(node->distance_from_source() > threshold_distance) 164 | { 165 | storage.push_back(node); 166 | } 167 | } 168 | else if(p->type() == EDGE) 169 | { 170 | edge_pointer e = static_cast(p); 171 | unsigned node_index = node_indexx(e); 172 | for(unsigned i=0; idistance_from_source() > threshold_distance) 176 | { 177 | storage.push_back(node); 178 | } 179 | } 180 | } 181 | //FACE has no nodes 182 | } 183 | 184 | void GeodesicAlgorithmSubdivision::list_nodes_visible_from_source(MeshElementBase* p, 185 | std::vector& storage) 186 | { 187 | assert(p->type() != UNDEFINED_POINT); 188 | 189 | if(p->type() == FACE) 190 | { 191 | face_pointer f = static_cast(p); 192 | for(unsigned i=0; i<3; ++i) 193 | { 194 | list_nodes(f->adjacent_vertices()[i],storage); 195 | list_nodes(f->adjacent_edges()[i],storage); 196 | } 197 | } 198 | else if(p->type() == EDGE) 199 | { 200 | list_nodes(p,storage); 201 | list_nodes(p->adjacent_vertices()[0],storage); 202 | list_nodes(p->adjacent_vertices()[1],storage); 203 | } 204 | else //VERTEX 205 | { 206 | list_nodes(p,storage); 207 | } 208 | } 209 | 210 | void GeodesicAlgorithmSubdivision::list_nodes_visible_from_node(node_pointer node, //list all nodes that belong to this mesh element 211 | std::vector& storage, 212 | std::vector& distances, 213 | double threshold_distance) 214 | { 215 | MeshElementBase* p = node->base_element(); 216 | assert(p->type() != UNDEFINED_POINT); 217 | assert(storage.size() == distances.size()); 218 | 219 | if(p->type() == VERTEX) 220 | { 221 | vertex_pointer v = static_cast(p); 222 | 223 | for(unsigned i=0; iadjacent_edges().size(); ++i) 224 | { 225 | edge_pointer e = v->adjacent_edges()[i]; 226 | vertex_pointer v_opposite = e->opposite_vertex(v); 227 | list_nodes(e, storage, threshold_distance); 228 | list_nodes(v_opposite, storage, threshold_distance); 229 | } 230 | for(unsigned i=0; iadjacent_faces().size(); ++i) 231 | { 232 | face_pointer f = v->adjacent_faces()[i]; 233 | edge_pointer e = f->opposite_edge(v); 234 | list_nodes(e, storage, threshold_distance); 235 | } 236 | } 237 | else if(p->type() == EDGE) 238 | { 239 | edge_pointer e = static_cast(p); 240 | 241 | vertex_pointer v0 = e->adjacent_vertices()[0]; 242 | vertex_pointer v1 = e->adjacent_vertices()[1]; 243 | list_nodes(v0, storage, threshold_distance); 244 | list_nodes(v1, storage, threshold_distance); 245 | 246 | for(unsigned i=0; iadjacent_faces().size(); ++i) 247 | { 248 | face_pointer f = e->adjacent_faces()[i]; 249 | 250 | list_nodes(f->next_edge(e,v0), storage, threshold_distance); 251 | list_nodes(f->next_edge(e,v1), storage, threshold_distance); 252 | list_nodes(f->opposite_vertex(e), storage, threshold_distance); 253 | } 254 | } 255 | else 256 | { 257 | assert(0); 258 | } 259 | 260 | unsigned index = distances.size(); 261 | distances.resize(storage.size()); 262 | for(; indexdistance(&storage[index]->surface_point()); 265 | } 266 | } 267 | 268 | } //geodesic 269 | 270 | #endif //GEODESIC_ALGORITHM_SUBDIVISION_122806 271 | -------------------------------------------------------------------------------- /MeshLP/geodesics/geodesic_algorithm_graph_base.h: -------------------------------------------------------------------------------- 1 | #ifndef GEODESIC_ALGORITHM_GRAPH_BASE_010907 2 | #define GEODESIC_ALGORITHM_GRAPH_BASE_010907 3 | 4 | #include "geodesic_algorithm_base.h" 5 | #include "geodesic_mesh_elements.h" 6 | #include 7 | #include 8 | #include 9 | 10 | namespace geodesic{ 11 | 12 | template 13 | class GeodesicAlgorithmGraphBase: public GeodesicAlgorithmBase 14 | { 15 | public: 16 | typedef Node* node_pointer; 17 | 18 | GeodesicAlgorithmGraphBase(geodesic::Mesh* mesh): 19 | GeodesicAlgorithmBase(mesh) 20 | {}; 21 | 22 | ~GeodesicAlgorithmGraphBase(){}; 23 | 24 | void propagate(std::vector& sources, 25 | double max_propagation_distance = GEODESIC_INF, //propagation algorithm stops after reaching the certain distance from the source 26 | std::vector* stop_points = NULL); //or after ensuring that all the stop_points are covered 27 | 28 | void trace_back(SurfacePoint& destination, //trace back piecewise-linear path 29 | std::vector& path); 30 | 31 | unsigned best_source(SurfacePoint& point, //quickly find what source this point belongs to and what is the distance to this source 32 | double& best_source_distance); 33 | 34 | void print_statistics() 35 | { 36 | GeodesicAlgorithmBase::print_statistics(); 37 | 38 | double memory = m_nodes.size()*sizeof(Node); 39 | std::cout << "uses about " << memory/1e6 << "Mb of memory" <id(); 46 | }; 47 | 48 | void set_sources(std::vector& sources) 49 | { 50 | m_sources = sources; 51 | } 52 | 53 | node_pointer best_first_node(SurfacePoint& point, double& best_total_distance) 54 | { 55 | node_pointer best_node = NULL; 56 | if(point.type() == VERTEX) 57 | { 58 | vertex_pointer v = (vertex_pointer)point.base_element(); 59 | best_node = &m_nodes[node_index(v)]; 60 | best_total_distance = best_node->distance_from_source(); 61 | } 62 | else 63 | { 64 | std::vector possible_nodes; 65 | list_nodes_visible_from_source(point.base_element(), possible_nodes); 66 | 67 | best_total_distance = GEODESIC_INF; 68 | for(unsigned i=0; idistance(&point); 73 | if(node->distance_from_source() + distance_from_dest < best_total_distance) 74 | { 75 | best_total_distance = node->distance_from_source() + distance_from_dest; 76 | best_node = node; 77 | } 78 | } 79 | } 80 | 81 | //assert(best_node); 82 | //assert(best_total_distance m_propagation_distance_stopped) //result is unreliable 84 | { 85 | best_total_distance = GEODESIC_INF; 86 | return NULL; 87 | } 88 | else 89 | { 90 | return best_node; 91 | } 92 | }; //quickly find what node will be the next one in geodesic path 93 | 94 | bool check_stop_conditions(unsigned& index); //check when propagation should stop 95 | 96 | virtual void list_nodes_visible_from_source(MeshElementBase* p, 97 | std::vector& storage) = 0; //list all nodes that belong to this mesh element 98 | 99 | virtual void list_nodes_visible_from_node(node_pointer node, //list all nodes that belong to this mesh element 100 | std::vector& storage, 101 | std::vector& distances, 102 | double threshold_distance) = 0; //list only the nodes whose current distance is larger than the threshold 103 | 104 | std::vector m_nodes; //nodes of the graph 105 | 106 | typedef std::set queue_type; 107 | queue_type m_queue; 108 | 109 | std::vector m_sources; //for simplicity, we keep sources as they are 110 | }; 111 | 112 | template 113 | void GeodesicAlgorithmGraphBase::propagate(std::vector& sources, 114 | double max_propagation_distance, //propagation algorithm stops after reaching the certain distance from the source 115 | std::vector* stop_points) //or after ensuring that all the stop_points are covered 116 | { 117 | set_stop_conditions(stop_points, max_propagation_distance); 118 | set_sources(sources); 119 | 120 | m_queue.clear(); 121 | m_propagation_distance_stopped = GEODESIC_INF; 122 | for(unsigned i=0; i visible_nodes; //initialize vertices directly visible from sources 130 | for(unsigned i=0; ibase_element(), 134 | visible_nodes); 135 | 136 | for(unsigned j=0; jdistance(source); 140 | if(distance < node->distance_from_source()) 141 | { 142 | node->distance_from_source() = distance; 143 | node->source_index() = i; 144 | node->previous() = NULL; 145 | } 146 | } 147 | visible_nodes.clear(); 148 | } 149 | 150 | for(unsigned i=0; i distances_between_nodes; 162 | while(!m_queue.empty()) //main cycle 163 | { 164 | if(counter++ % 10 == 0) //check if we covered all required vertices 165 | { 166 | if (check_stop_conditions(satisfied_index)) 167 | { 168 | break; 169 | } 170 | } 171 | 172 | node_pointer min_node = *m_queue.begin(); 173 | m_queue.erase(m_queue.begin()); 174 | assert(min_node->distance_from_source() < GEODESIC_INF); 175 | 176 | visible_nodes.clear(); 177 | distances_between_nodes.clear(); 178 | list_nodes_visible_from_node(min_node, 179 | visible_nodes, 180 | distances_between_nodes, 181 | min_node->distance_from_source()); 182 | 183 | for(unsigned i=0; idistance_from_source() > min_node->distance_from_source() + 188 | distances_between_nodes[i]) 189 | { 190 | if(next_node->distance_from_source() < GEODESIC_INF) //remove it from the queue 191 | { 192 | typename queue_type::iterator iter = m_queue.find(next_node); 193 | assert(iter != m_queue.end()); 194 | m_queue.erase(iter); 195 | } 196 | next_node->distance_from_source() = min_node->distance_from_source() + 197 | distances_between_nodes[i]; 198 | next_node->source_index() = min_node->source_index(); 199 | next_node->previous() = min_node; 200 | m_queue.insert(next_node); 201 | } 202 | } 203 | } 204 | 205 | m_propagation_distance_stopped = m_queue.empty() ? GEODESIC_INF : (*m_queue.begin())->distance_from_source(); 206 | clock_t finish = clock(); 207 | m_time_consumed = (static_cast(finish)-static_cast(start))/CLOCKS_PER_SEC; 208 | //std::cout << std::endl; 209 | } 210 | 211 | template 212 | inline bool GeodesicAlgorithmGraphBase::check_stop_conditions(unsigned& index) 213 | { 214 | double queue_min_distance = (*m_queue.begin())->distance_from_source(); 215 | 216 | if(queue_min_distance < m_max_propagation_distance) 217 | { 218 | return false; 219 | } 220 | 221 | while(index < m_stop_vertices.size()) 222 | { 223 | vertex_pointer v = m_stop_vertices[index].first; 224 | Node& node = m_nodes[node_index(v)]; 225 | if(queue_min_distance < node.distance_from_source() + m_stop_vertices[index].second) 226 | { 227 | return false; 228 | } 229 | ++index; 230 | } 231 | return true; 232 | } 233 | 234 | template 235 | inline void GeodesicAlgorithmGraphBase::trace_back(SurfacePoint& destination, //trace back piecewise-linear path 236 | std::vector& path) 237 | { 238 | path.clear(); 239 | 240 | double total_path_length; 241 | node_pointer node = best_first_node(destination, total_path_length); 242 | 243 | if(total_path_length>GEODESIC_INF/2.0) //unable to find the path 244 | { 245 | return; 246 | } 247 | 248 | path.push_back(destination); 249 | 250 | if(node->distance(&destination) > 1e-50) 251 | { 252 | path.push_back(node->surface_point()); 253 | } 254 | 255 | while(node->previous()) //follow the path 256 | { 257 | node = node->previous(); 258 | path.push_back(node->surface_point()); 259 | } 260 | 261 | SurfacePoint& source = m_sources[node->source_index()]; //add source to the path if it is not already there 262 | if(node->distance(&source) > 1e-50) 263 | { 264 | path.push_back(source); 265 | } 266 | } 267 | 268 | 269 | template 270 | inline unsigned GeodesicAlgorithmGraphBase::best_source(SurfacePoint& point, //quickly find what source this point belongs to and what is the distance to this source 271 | double& best_source_distance) 272 | { 273 | node_pointer node = best_first_node(point, best_source_distance); 274 | return node ? node->source_index() : 0; 275 | }; 276 | 277 | } //geodesic 278 | 279 | #endif //GEODESIC_ALGORITHM_GRAPH_BASE_010907 280 | -------------------------------------------------------------------------------- /MeshLP/geodesics/geodesic_algorithm_dijkstra_alternative.h: -------------------------------------------------------------------------------- 1 | //Copyright (C) 2008 Danil Kirsanov, MIT License 2 | #ifndef GEODESIC_ALGORITHM_DIJKSTRA_ALTERNATIVE_010506 3 | #define GEODESIC_ALGORITHM_DIJKSTRA_ALTERNATIVE_010506 4 | 5 | #include "geodesic_algorithm_base.h" 6 | #include "geodesic_mesh_elements.h" 7 | #include 8 | #include 9 | #include 10 | 11 | namespace geodesic{ 12 | 13 | class DijkstraNode1 14 | { 15 | typedef DijkstraNode1* node_pointer; 16 | public: 17 | DijkstraNode1(){}; 18 | ~DijkstraNode1(){}; 19 | 20 | double& distance_from_source(){return m_distance;}; 21 | node_pointer& previous(){return m_previous;}; 22 | unsigned& source_index(){return m_source_index;}; 23 | vertex_pointer& vertex(){return m_vertex;}; 24 | 25 | void clear() 26 | { 27 | m_distance = GEODESIC_INF; 28 | m_previous = NULL; 29 | } 30 | 31 | bool operator()(node_pointer const s1, node_pointer const s2) const 32 | { 33 | return s1->distance_from_source() != s2->distance_from_source() ? 34 | s1->distance_from_source() < s2->distance_from_source() : 35 | s1->vertex()->id() < s2->vertex()->id(); 36 | }; 37 | 38 | private: 39 | double m_distance; //distance to the closest source 40 | unsigned m_source_index; //closest source index 41 | node_pointer m_previous; //previous node in the geodesic path 42 | vertex_pointer m_vertex; //correspoding vertex 43 | }; 44 | 45 | class GeodesicAlgorithmDijkstraAlternative: public GeodesicAlgorithmBase 46 | { 47 | public: 48 | typedef DijkstraNode1 Node; 49 | typedef Node* node_pointer; 50 | 51 | GeodesicAlgorithmDijkstraAlternative(geodesic::Mesh* mesh = NULL): 52 | GeodesicAlgorithmBase(mesh), 53 | m_nodes(mesh->vertices().size()) 54 | { 55 | m_type = DIJKSTRA; 56 | for(unsigned i=0; ivertices()[i]; 59 | } 60 | }; 61 | 62 | ~GeodesicAlgorithmDijkstraAlternative(){}; 63 | 64 | virtual void propagate(std::vector& sources, 65 | double max_propagation_distance = GEODESIC_INF, //propagation algorithm stops after reaching the certain distance from the source 66 | std::vector* stop_points = NULL); //or after ensuring that all the stop_points are covered 67 | 68 | virtual void trace_back(SurfacePoint& destination, //trace back piecewise-linear path 69 | std::vector& path); 70 | 71 | virtual unsigned best_source(SurfacePoint& point, //quickly find what source this point belongs to and what is the distance to this source 72 | double& best_source_distance); 73 | private: 74 | 75 | void set_sources(std::vector& sources) 76 | { 77 | m_sources = sources; 78 | } 79 | 80 | bool check_stop_conditions(unsigned& index); 81 | 82 | std::vector m_nodes; //nodes of the subdivision graph located on the vertices 83 | 84 | std::vector m_sources; //for simplicity, we keep sources as they are 85 | 86 | typedef std::set queue_type; 87 | queue_type m_queue; 88 | }; 89 | 90 | inline unsigned GeodesicAlgorithmDijkstraAlternative::best_source(SurfacePoint& point, //quickly find what source this point belongs to and what is the distance to this source 91 | double& best_source_distance) 92 | { 93 | if(point.type() == VERTEX) 94 | { 95 | vertex_pointer v = (vertex_pointer)point.base_element(); 96 | node_pointer node = &m_nodes[v->id()]; 97 | best_source_distance = node->distance_from_source(); 98 | return node->source_index(); 99 | } 100 | else 101 | { 102 | std::vector possible_vertices; //initialize vertices directly visible from sources 103 | m_mesh->closest_vertices(&point, &possible_vertices); 104 | 105 | best_source_distance = GEODESIC_INF; 106 | vertex_pointer min_vertex = NULL; 107 | for(unsigned i=0; iid()].distance_from_source(); 112 | double distance_from_dest = v->distance(&point); 113 | if(distance_from_source + distance_from_dest < best_source_distance) 114 | { 115 | best_source_distance = distance_from_source + distance_from_dest; 116 | min_vertex = v; 117 | } 118 | } 119 | assert(min_vertex); 120 | node_pointer node = &m_nodes[min_vertex->id()]; 121 | return node->source_index(); 122 | } 123 | } 124 | 125 | inline void GeodesicAlgorithmDijkstraAlternative::trace_back(SurfacePoint& destination, //trace back piecewise-linear path 126 | std::vector& path) 127 | { 128 | path.clear(); 129 | path.push_back(destination); 130 | 131 | if(destination.type() != VERTEX) //snap to the closest vertex 132 | { 133 | std::vector possible_vertices; //initialize vertices directly visible from sources 134 | m_mesh->closest_vertices(&destination, &possible_vertices); 135 | 136 | double min_distance = GEODESIC_INF; 137 | vertex_pointer min_vertex = NULL; 138 | for(unsigned i=0; iid()].distance_from_source(); 143 | double distance_from_dest = v->distance(&destination); 144 | if(distance_from_source + distance_from_dest < min_distance) 145 | { 146 | min_distance = distance_from_source + distance_from_dest; 147 | min_vertex = v; 148 | } 149 | } 150 | assert(min_vertex); 151 | path.push_back(SurfacePoint(min_vertex)); 152 | } 153 | 154 | node_pointer node = &m_nodes[path.back().base_element()->id()]; 155 | while(node->previous()) //follow the path 156 | { 157 | node = node->previous(); 158 | path.push_back(SurfacePoint(node->vertex())); 159 | } 160 | 161 | SurfacePoint& source = m_sources[node->source_index()]; //add source to the path if it is not already there 162 | if(source.type() != VERTEX || 163 | source.base_element()->id() != node->vertex()->id()) 164 | { 165 | path.push_back(source); 166 | } 167 | } 168 | 169 | inline void GeodesicAlgorithmDijkstraAlternative::propagate(std::vector& sources, 170 | double max_propagation_distance, //propagation algorithm stops after reaching the certain distance from the source 171 | std::vector* stop_points) //or after ensuring that all the stop_points are covered 172 | { 173 | set_stop_conditions(stop_points, max_propagation_distance); 174 | set_sources(sources); 175 | 176 | m_queue.clear(); //clear everything 177 | for(unsigned i=0; i visible_vertices; //initialize vertices directly visible from sources 185 | for(unsigned i=0; iclosest_vertices(s, &visible_vertices); 189 | for(unsigned j=0; jdistance(v); 193 | 194 | node_pointer node = &m_nodes[v->id()]; 195 | if(distance < node->distance_from_source()) 196 | { 197 | node->distance_from_source() = distance; 198 | node->source_index() = i; 199 | node->previous() = NULL; 200 | } 201 | } 202 | visible_vertices.clear(); 203 | } 204 | 205 | for(unsigned i=0; idistance_from_source()<< std::endl; 225 | } 226 | 227 | node_pointer min_node = *m_queue.begin(); 228 | m_queue.erase(m_queue.begin()); 229 | 230 | vertex_pointer v = min_node->vertex(); 231 | 232 | for(unsigned i=0; iadjacent_edges().size(); ++i) //update all the adgecent vertices 233 | { 234 | edge_pointer e = v->adjacent_edges()[i]; 235 | vertex_pointer next_v = e->opposite_vertex(v); 236 | node_pointer next_node = &m_nodes[next_v->id()]; 237 | //double current_distance = 238 | if(next_node->distance_from_source() > min_node->distance_from_source() + e->length()) 239 | { 240 | if(next_node->distance_from_source() < GEODESIC_INF) //remove it from the queue 241 | { 242 | queue_type::iterator iter = m_queue.find(next_node); 243 | assert(iter != m_queue.end()); 244 | m_queue.erase(iter); 245 | } 246 | next_node->distance_from_source() = min_node->distance_from_source() + e->length(); 247 | next_node->source_index() = min_node->source_index(); 248 | next_node->previous() = min_node; 249 | m_queue.insert(next_node); 250 | } 251 | } 252 | } 253 | //std::cout << std::endl; 254 | 255 | clock_t finish = clock(); 256 | m_time_consumed = (static_cast(finish)-static_cast(start))/CLOCKS_PER_SEC; 257 | } 258 | 259 | inline bool GeodesicAlgorithmDijkstraAlternative::check_stop_conditions(unsigned& index) 260 | { 261 | double queue_min_distance = (*m_queue.begin())->distance_from_source(); 262 | 263 | if(queue_min_distance < m_max_propagation_distance) 264 | { 265 | return false; 266 | } 267 | 268 | while(index < m_stop_vertices.size()) 269 | { 270 | vertex_pointer v = m_stop_vertices[index].first; 271 | Node& node = m_nodes[v->id()]; 272 | if(queue_min_distance < node.distance_from_source() + m_stop_vertices[index].second) 273 | { 274 | return false; 275 | } 276 | ++index; 277 | } 278 | return true; 279 | } 280 | 281 | } //geodesic 282 | 283 | #endif //GEODESIC_ALGORITHM_DIJKSTRA_ALTERNATIVE_010506 284 | -------------------------------------------------------------------------------- /MeshLP/geodesics/geodesic_mesh_elements.h: -------------------------------------------------------------------------------- 1 | //Copyright (C) 2008 Danil Kirsanov, MIT License 2 | #ifndef GEODESIC_MESH_ELEMENTS_20071231 3 | #define GEODESIC_MESH_ELEMENTS_20071231 4 | 5 | // here we define the building elements of the mesh: 6 | // 3D-points, vertices, edges, faces, and surface points 7 | 8 | #include 9 | #include 10 | 11 | namespace geodesic{ 12 | 13 | class Vertex; 14 | class Edge; 15 | class Face; 16 | class Mesh; 17 | class MeshElementBase; 18 | 19 | typedef Vertex* vertex_pointer; 20 | typedef Edge* edge_pointer; 21 | typedef Face* face_pointer; 22 | typedef Mesh* mesh_pointer; 23 | typedef MeshElementBase* base_pointer; 24 | 25 | template //simple vector that stores info about mesh references 26 | class SimpleVector //for efficiency, it uses an outside memory allocator 27 | { 28 | public: 29 | SimpleVector(): 30 | m_size(0), 31 | m_begin(NULL) 32 | {}; 33 | 34 | typedef Data* iterator; 35 | 36 | unsigned size(){return m_size;}; 37 | iterator begin(){return m_begin;}; 38 | iterator end(){return m_begin + m_size;}; 39 | 40 | template 41 | void set_allocation(DataPointer begin, unsigned size) 42 | { 43 | assert(begin != NULL || size == 0); 44 | m_size = size; 45 | m_begin = (iterator)begin; 46 | } 47 | 48 | Data& operator[](unsigned i) 49 | { 50 | assert(i < m_size); 51 | return *(m_begin + i); 52 | } 53 | 54 | void clear() 55 | { 56 | m_size = 0; 57 | m_begin = NULL; 58 | } 59 | 60 | private: 61 | unsigned m_size; 62 | Data* m_begin; 63 | }; 64 | 65 | enum PointType 66 | { 67 | VERTEX, 68 | EDGE, 69 | FACE, 70 | UNDEFINED_POINT 71 | }; 72 | 73 | class MeshElementBase //prototype of vertices, edges and faces 74 | { 75 | public: 76 | typedef SimpleVector vertex_pointer_vector; 77 | typedef SimpleVector edge_pointer_vector; 78 | typedef SimpleVector face_pointer_vector; 79 | 80 | MeshElementBase(): 81 | m_id(0), 82 | m_type(UNDEFINED_POINT) 83 | {}; 84 | 85 | vertex_pointer_vector& adjacent_vertices(){return m_adjacent_vertices;}; 86 | edge_pointer_vector& adjacent_edges(){return m_adjacent_edges;}; 87 | face_pointer_vector& adjacent_faces(){return m_adjacent_faces;}; 88 | 89 | unsigned& id(){return m_id;}; 90 | PointType type(){return m_type;}; 91 | 92 | protected: 93 | vertex_pointer_vector m_adjacent_vertices; //list of the adjacent vertices 94 | edge_pointer_vector m_adjacent_edges; //list of the adjacent edges 95 | face_pointer_vector m_adjacent_faces; //list of the adjacent faces 96 | 97 | unsigned m_id; //unique id 98 | PointType m_type; //vertex, edge or face 99 | }; 100 | 101 | class Point3D //point in 3D and corresponding operations 102 | { 103 | public: 104 | Point3D(){}; 105 | Point3D(Point3D* p) 106 | { 107 | x() = p->x(); 108 | y() = p->y(); 109 | z() = p->z(); 110 | }; 111 | 112 | double* xyz(){return m_coordinates;}; 113 | double& x(){return *m_coordinates;}; 114 | double& y(){return *(m_coordinates+1);}; 115 | double& z(){return *(m_coordinates+2);}; 116 | 117 | void set(double new_x, double new_y, double new_z) 118 | { 119 | x() = new_x; 120 | y() = new_y; 121 | z() = new_z; 122 | } 123 | 124 | void set(double* data) 125 | { 126 | x() = *data; 127 | y() = *(data+1); 128 | z() = *(data+2); 129 | } 130 | 131 | double distance(double* v) 132 | { 133 | double dx = m_coordinates[0] - v[0]; 134 | double dy = m_coordinates[1] - v[1]; 135 | double dz = m_coordinates[2] - v[2]; 136 | 137 | return sqrt(dx*dx + dy*dy + dz*dz); 138 | }; 139 | 140 | double distance(Point3D* v) 141 | { 142 | return distance(v->xyz()); 143 | }; 144 | 145 | void add(Point3D* v) 146 | { 147 | x() += v->x(); 148 | y() += v->y(); 149 | z() += v->z(); 150 | }; 151 | 152 | void multiply(double v) 153 | { 154 | x() *= v; 155 | y() *= v; 156 | z() *= v; 157 | }; 158 | 159 | private: 160 | double m_coordinates[3]; //xyz 161 | }; 162 | 163 | class Vertex: public MeshElementBase, public Point3D 164 | { 165 | public: 166 | Vertex() 167 | { 168 | m_type = VERTEX; 169 | }; 170 | 171 | ~Vertex(){}; 172 | 173 | bool& saddle_or_boundary(){return m_saddle_or_boundary;}; 174 | private: 175 | //this flag speeds up exact geodesic algorithm 176 | bool m_saddle_or_boundary; //it is true if total adjacent angle is larger than 2*PI or this vertex belongs to the mesh boundary 177 | }; 178 | 179 | 180 | class Face: public MeshElementBase 181 | { 182 | public: 183 | Face() 184 | { 185 | m_type = FACE; 186 | }; 187 | 188 | ~Face(){}; 189 | 190 | edge_pointer opposite_edge(vertex_pointer v); 191 | vertex_pointer opposite_vertex(edge_pointer e); 192 | edge_pointer next_edge(edge_pointer e, vertex_pointer v); 193 | 194 | double vertex_angle(vertex_pointer v) 195 | { 196 | for(unsigned i=0; i<3; ++i) 197 | { 198 | if(adjacent_vertices()[i]->id() == v->id()) 199 | { 200 | return m_corner_angles[i]; 201 | } 202 | } 203 | assert(0); 204 | return 0; 205 | } 206 | 207 | double* corner_angles(){return m_corner_angles;}; 208 | 209 | private: 210 | double m_corner_angles[3]; //triangle angles in radians; angles correspond to vertices in m_adjacent_vertices 211 | }; 212 | 213 | class Edge: public MeshElementBase 214 | { 215 | public: 216 | Edge() 217 | { 218 | m_type = EDGE; 219 | }; 220 | 221 | ~Edge(){}; 222 | 223 | double& length(){return m_length;}; 224 | 225 | face_pointer opposite_face(face_pointer f) 226 | { 227 | if(adjacent_faces().size() == 1) 228 | { 229 | assert(adjacent_faces()[0]->id() == f->id()); 230 | return NULL; 231 | } 232 | 233 | assert(adjacent_faces()[0]->id() == f->id() || 234 | adjacent_faces()[1]->id() == f->id()); 235 | 236 | return adjacent_faces()[0]->id() == f->id() ? 237 | adjacent_faces()[1] : adjacent_faces()[0]; 238 | }; 239 | 240 | vertex_pointer opposite_vertex(vertex_pointer v) 241 | { 242 | assert(belongs(v)); 243 | 244 | return adjacent_vertices()[0]->id() == v->id() ? 245 | adjacent_vertices()[1] : adjacent_vertices()[0]; 246 | }; 247 | 248 | bool belongs(vertex_pointer v) 249 | { 250 | return adjacent_vertices()[0]->id() == v->id() || 251 | adjacent_vertices()[1]->id() == v->id(); 252 | } 253 | 254 | bool is_boundary(){return adjacent_faces().size() == 1;}; 255 | 256 | vertex_pointer v0(){return adjacent_vertices()[0];}; 257 | vertex_pointer v1(){return adjacent_vertices()[1];}; 258 | 259 | void local_coordinates(Point3D* point, 260 | double& x, 261 | double& y) 262 | { 263 | double d0 = point->distance(v0()); 264 | if(d0 < 1e-50) 265 | { 266 | x = 0.0; 267 | y = 0.0; 268 | return; 269 | } 270 | 271 | double d1 = point->distance(v1()); 272 | if(d1 < 1e-50) 273 | { 274 | x = m_length; 275 | y = 0.0; 276 | return; 277 | } 278 | 279 | x = m_length/2.0 + (d0*d0 - d1*d1)/(2.0*m_length); 280 | y = sqrt(std::max(0.0, d0*d0 - x*x)); 281 | return; 282 | } 283 | 284 | private: 285 | double m_length; //length of the edge 286 | }; 287 | 288 | class SurfacePoint:public Point3D //point on the surface of the mesh 289 | { 290 | public: 291 | SurfacePoint(): 292 | m_p(NULL) 293 | {}; 294 | 295 | SurfacePoint(vertex_pointer v): //set the surface point in the vertex 296 | SurfacePoint::Point3D(v), 297 | m_p(v) 298 | {}; 299 | 300 | SurfacePoint(face_pointer f): //set the surface point in the center of the face 301 | m_p(f) 302 | { 303 | set(0,0,0); 304 | add(f->adjacent_vertices()[0]); 305 | add(f->adjacent_vertices()[1]); 306 | add(f->adjacent_vertices()[2]); 307 | multiply(1./3.); 308 | }; 309 | 310 | SurfacePoint(edge_pointer e, //set the surface point in the middle of the edge 311 | double a = 0.5): 312 | m_p(e) 313 | { 314 | double b = 1 - a; 315 | 316 | vertex_pointer v0 = e->adjacent_vertices()[0]; 317 | vertex_pointer v1 = e->adjacent_vertices()[1]; 318 | 319 | x() = b*v0->x() + a*v1->x(); 320 | y() = b*v0->y() + a*v1->y(); 321 | z() = b*v0->z() + a*v1->z(); 322 | }; 323 | 324 | SurfacePoint(base_pointer g, 325 | double x, 326 | double y, 327 | double z, 328 | PointType t = UNDEFINED_POINT): 329 | m_p(g) 330 | { 331 | set(x,y,z); 332 | }; 333 | 334 | void initialize(SurfacePoint const& p) 335 | { 336 | *this = p; 337 | } 338 | 339 | ~SurfacePoint(){}; 340 | 341 | PointType type(){return m_p ? m_p->type() : UNDEFINED_POINT;}; 342 | base_pointer& base_element(){return m_p;}; 343 | protected: 344 | base_pointer m_p; //could be face, vertex or edge pointer 345 | }; 346 | 347 | inline edge_pointer Face::opposite_edge(vertex_pointer v) 348 | { 349 | for(unsigned i=0; i<3; ++i) 350 | { 351 | edge_pointer e = adjacent_edges()[i]; 352 | if(!e->belongs(v)) 353 | { 354 | return e; 355 | } 356 | } 357 | assert(0); 358 | return NULL; 359 | } 360 | 361 | inline vertex_pointer Face::opposite_vertex(edge_pointer e) 362 | { 363 | for(unsigned i=0; i<3; ++i) 364 | { 365 | vertex_pointer v = adjacent_vertices()[i]; 366 | if(!e->belongs(v)) 367 | { 368 | return v; 369 | } 370 | } 371 | assert(0); 372 | return NULL; 373 | } 374 | 375 | inline edge_pointer Face::next_edge(edge_pointer e, vertex_pointer v) 376 | { 377 | assert(e->belongs(v)); 378 | 379 | for(unsigned i=0; i<3; ++i) 380 | { 381 | edge_pointer next = adjacent_edges()[i]; 382 | if(e->id() != next->id() && next->belongs(v)) 383 | { 384 | return next; 385 | } 386 | } 387 | assert(0); 388 | return NULL; 389 | } 390 | 391 | struct HalfEdge //prototype of the edge; used for mesh construction 392 | { 393 | unsigned face_id; 394 | unsigned vertex_0; //adjacent vertices sorted by id value 395 | unsigned vertex_1; //they are sorted, vertex_0 < vertex_1 396 | }; 397 | 398 | inline bool operator < (const HalfEdge &x, const HalfEdge &y) 399 | { 400 | if(x.vertex_0 == y.vertex_0) 401 | { 402 | return x.vertex_1 < y.vertex_1; 403 | } 404 | else 405 | { 406 | return x.vertex_0 < y.vertex_0; 407 | } 408 | } 409 | 410 | inline bool operator != (const HalfEdge &x, const HalfEdge &y) 411 | { 412 | return x.vertex_0 != y.vertex_0 || x.vertex_1 != y.vertex_1; 413 | } 414 | 415 | inline bool operator == (const HalfEdge &x, const HalfEdge &y) 416 | { 417 | return x.vertex_0 == y.vertex_0 && x.vertex_1 == y.vertex_1; 418 | } 419 | 420 | } //geodesic 421 | 422 | #endif 423 | -------------------------------------------------------------------------------- /MeshLP/geodesics/geodesic_algorithm_exact_elements.h: -------------------------------------------------------------------------------- 1 | //Copyright (C) 2008 Danil Kirsanov, MIT License 2 | #ifndef GEODESIC_ALGORITHM_EXACT_ELEMENTS_20071231 3 | #define GEODESIC_ALGORITHM_EXACT_ELEMENTS_20071231 4 | 5 | #include "geodesic_memory.h" 6 | #include "geodesic_mesh_elements.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace geodesic{ 13 | 14 | class Interval; 15 | class IntervalList; 16 | typedef Interval* interval_pointer; 17 | typedef IntervalList* list_pointer; 18 | 19 | class Interval //interval of the edge 20 | { 21 | public: 22 | 23 | Interval(){}; 24 | ~Interval(){}; 25 | 26 | enum DirectionType 27 | { 28 | FROM_FACE_0, 29 | FROM_FACE_1, 30 | FROM_SOURCE, 31 | UNDEFINED_DIRECTION 32 | }; 33 | 34 | double signal(double x) //geodesic distance function at point x 35 | { 36 | assert(x>=0.0 && x <= m_edge->length()); 37 | 38 | if(m_d == GEODESIC_INF) 39 | { 40 | return GEODESIC_INF; 41 | } 42 | else 43 | { 44 | double dx = x - m_pseudo_x; 45 | if(m_pseudo_y == 0.0) 46 | { 47 | return m_d + std::abs(dx); 48 | } 49 | else 50 | { 51 | return m_d + sqrt(dx*dx + m_pseudo_y*m_pseudo_y); 52 | } 53 | } 54 | } 55 | 56 | double max_distance(double end) 57 | { 58 | if(m_d == GEODESIC_INF) 59 | { 60 | return GEODESIC_INF; 61 | } 62 | else 63 | { 64 | double a = std::abs(m_start - m_pseudo_x); 65 | double b = std::abs(end - m_pseudo_x); 66 | 67 | return a > b ? m_d + sqrt(a*a + m_pseudo_y*m_pseudo_y): 68 | m_d + sqrt(b*b + m_pseudo_y*m_pseudo_y); 69 | } 70 | } 71 | 72 | void compute_min_distance(double stop) //compute min, given c,d theta, start, end. 73 | { 74 | assert(stop > m_start); 75 | 76 | if(m_d == GEODESIC_INF) 77 | { 78 | m_min = GEODESIC_INF; 79 | } 80 | else if(m_start > m_pseudo_x) 81 | { 82 | m_min = signal(m_start); 83 | } 84 | else if(stop < m_pseudo_x) 85 | { 86 | m_min = signal(stop); 87 | } 88 | else 89 | { 90 | assert(m_pseudo_y<=0); 91 | m_min = m_d - m_pseudo_y; 92 | } 93 | } 94 | //compare two intervals in the queue 95 | bool operator()(interval_pointer const x, interval_pointer const y) const 96 | { 97 | if(x->min() != y->min()) 98 | { 99 | return x->min() < y->min(); 100 | } 101 | else if(x->start() != y->start()) 102 | { 103 | return x->start() < y->start(); 104 | } 105 | else 106 | { 107 | return x->edge()->id() < y->edge()->id(); 108 | } 109 | } 110 | 111 | double stop() //return the endpoint of the interval 112 | { 113 | return m_next ? m_next->start() : m_edge->length(); 114 | } 115 | 116 | double hypotenuse(double a, double b) 117 | { 118 | return sqrt(a*a + b*b); 119 | } 120 | 121 | void find_closest_point(double const x, 122 | double const y, 123 | double& offset, 124 | double& distance); //find the point on the interval that is closest to the point (alpha, s) 125 | 126 | double& start(){return m_start;}; 127 | double& d(){return m_d;}; 128 | double& pseudo_x(){return m_pseudo_x;}; 129 | double& pseudo_y(){return m_pseudo_y;}; 130 | double& min(){return m_min;}; 131 | interval_pointer& next(){return m_next;}; 132 | edge_pointer& edge(){return m_edge;}; 133 | DirectionType& direction(){return m_direction;}; 134 | bool visible_from_source(){return m_direction == FROM_SOURCE;}; 135 | unsigned& source_index(){return m_source_index;}; 136 | 137 | void initialize(edge_pointer edge, 138 | SurfacePoint* point = NULL, 139 | unsigned source_index = 0); 140 | 141 | protected: 142 | double m_start; //initial point of the interval on the edge 143 | double m_d; //distance from the source to the pseudo-source 144 | double m_pseudo_x; //coordinates of the pseudo-source in the local coordinate system 145 | double m_pseudo_y; //y-coordinate should be always negative 146 | double m_min; //minimum distance on the interval 147 | 148 | interval_pointer m_next; //pointer to the next interval in the list 149 | edge_pointer m_edge; //edge that the interval belongs to 150 | unsigned m_source_index; //the source it belongs to 151 | DirectionType m_direction; //where the interval is coming from 152 | }; 153 | 154 | struct IntervalWithStop : public Interval 155 | { 156 | public: 157 | double& stop(){return m_stop;}; 158 | protected: 159 | double m_stop; 160 | }; 161 | 162 | class IntervalList //list of the of intervals of the given edge 163 | { 164 | public: 165 | IntervalList(){m_first = NULL;}; 166 | ~IntervalList(){}; 167 | 168 | void clear() 169 | { 170 | m_first = NULL; 171 | }; 172 | 173 | void initialize(edge_pointer e) 174 | { 175 | m_edge = e; 176 | m_first = NULL; 177 | }; 178 | 179 | interval_pointer covering_interval(double offset) //returns the interval that covers the offset 180 | { 181 | assert(offset >= 0.0 && offset <= m_edge->length()); 182 | 183 | interval_pointer p = m_first; 184 | while(p && p->stop() < offset) 185 | { 186 | p = p->next(); 187 | } 188 | 189 | return p;// && p->start() <= offset ? p : NULL; 190 | }; 191 | 192 | void find_closest_point(SurfacePoint* point, 193 | double& offset, 194 | double& distance, 195 | interval_pointer& interval) 196 | { 197 | interval_pointer p = m_first; 198 | distance = GEODESIC_INF; 199 | interval = NULL; 200 | 201 | double x,y; 202 | m_edge->local_coordinates(point, x, y); 203 | 204 | while(p) 205 | { 206 | if(p->min()find_closest_point(x, y, o, d); 210 | if(d < distance) 211 | { 212 | distance = d; 213 | offset = o; 214 | interval = p; 215 | } 216 | } 217 | p = p->next(); 218 | } 219 | }; 220 | 221 | unsigned number_of_intervals() 222 | { 223 | interval_pointer p = m_first; 224 | unsigned count = 0; 225 | while(p) 226 | { 227 | ++count; 228 | p = p->next(); 229 | } 230 | return count; 231 | } 232 | 233 | interval_pointer last() 234 | { 235 | interval_pointer p = m_first; 236 | if(p) 237 | { 238 | while(p->next()) 239 | { 240 | p = p->next(); 241 | } 242 | } 243 | return p; 244 | } 245 | 246 | double signal(double x) 247 | { 248 | interval_pointer interval = covering_interval(x); 249 | 250 | return interval ? interval->signal(x) : GEODESIC_INF; 251 | } 252 | 253 | interval_pointer& first(){return m_first;}; 254 | edge_pointer& edge(){return m_edge;}; 255 | private: 256 | interval_pointer m_first; //pointer to the first member of the list 257 | edge_pointer m_edge; //edge that owns this list 258 | }; 259 | 260 | class SurfacePointWithIndex : public SurfacePoint 261 | { 262 | public: 263 | unsigned index(){return m_index;}; 264 | 265 | void initialize(SurfacePoint& p, unsigned index) 266 | { 267 | SurfacePoint::initialize(p); 268 | m_index = index; 269 | } 270 | 271 | bool operator()(SurfacePointWithIndex* x, SurfacePointWithIndex* y) const //used for sorting 272 | { 273 | assert(x->type() != UNDEFINED_POINT && y->type() !=UNDEFINED_POINT); 274 | 275 | if(x->type() != y->type()) 276 | { 277 | return x->type() < y->type(); 278 | } 279 | else 280 | { 281 | return x->base_element()->id() < y->base_element()->id(); 282 | } 283 | } 284 | 285 | private: 286 | unsigned m_index; 287 | }; 288 | 289 | class SortedSources : public std::vector 290 | { 291 | private: 292 | typedef std::vector sorted_vector_type; 293 | public: 294 | typedef sorted_vector_type::iterator sorted_iterator; 295 | typedef std::pair sorted_iterator_pair; 296 | 297 | sorted_iterator_pair sources(base_pointer mesh_element) 298 | { 299 | m_search_dummy.base_element() = mesh_element; 300 | 301 | return equal_range(m_sorted.begin(), 302 | m_sorted.end(), 303 | &m_search_dummy, 304 | m_compare_less); 305 | } 306 | 307 | void initialize(std::vector& sources) //we initialize the sources by copie 308 | { 309 | resize(sources.size()); 310 | m_sorted.resize(sources.size()); 311 | for(unsigned i=0; ilength(); 352 | if(std::abs(hs+hc) < local_epsilon) 353 | { 354 | if(rs<=m_start) 355 | { 356 | r = m_start; 357 | d_out = signal(m_start) + std::abs(rs - m_start); 358 | } 359 | else if(rs>=end) 360 | { 361 | r = end; 362 | d_out = signal(end) + fabs(end - rs); 363 | } 364 | else 365 | { 366 | r = rs; 367 | d_out = signal(rs); 368 | } 369 | } 370 | else 371 | { 372 | double ri = (rs*hc + hs*rc)/(hs+hc); 373 | 374 | if(riend) 380 | { 381 | r = end; 382 | d_out = signal(end) + hypotenuse(end - rs, hs); 383 | } 384 | else 385 | { 386 | r = ri; 387 | d_out = m_d + hypotenuse(rc - rs, hc + hs); 388 | } 389 | } 390 | } 391 | 392 | 393 | inline void Interval::initialize(edge_pointer edge, 394 | SurfacePoint* source, 395 | unsigned source_index) 396 | { 397 | m_next = NULL; 398 | //m_geodesic_previous = NULL; 399 | m_direction = UNDEFINED_DIRECTION; 400 | m_edge = edge; 401 | m_source_index = source_index; 402 | 403 | m_start = 0.0; 404 | //m_stop = edge->length(); 405 | if(!source) 406 | { 407 | m_d = GEODESIC_INF; 408 | m_min = GEODESIC_INF; 409 | return; 410 | } 411 | m_d = 0; 412 | 413 | if(source->base_element()->type() == VERTEX) 414 | { 415 | if(source->base_element()->id() == edge->v0()->id()) 416 | { 417 | m_pseudo_x = 0.0; 418 | m_pseudo_y = 0.0; 419 | m_min = 0.0; 420 | return; 421 | } 422 | else if(source->base_element()->id() == edge->v1()->id()) 423 | { 424 | m_pseudo_x = stop(); 425 | m_pseudo_y = 0.0; 426 | m_min = 0.0; 427 | return; 428 | } 429 | } 430 | 431 | edge->local_coordinates(source, m_pseudo_x, m_pseudo_y); 432 | m_pseudo_y = -m_pseudo_y; 433 | 434 | compute_min_distance(stop()); 435 | } 436 | 437 | } //geodesic 438 | 439 | #endif //GEODESIC_ALGORITHM_EXACT_ELEMENTS_20071231 440 | -------------------------------------------------------------------------------- /MeshLP/datastructure.h: -------------------------------------------------------------------------------- 1 | #ifndef __DATASTRUCTURE_H__ 2 | #define __DATASTRUCTURE_H__ 3 | #define uint unsigned int 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "matrix.h" 12 | 13 | #define MYNZERO 1e-10 14 | 15 | 16 | //==================================================================== 17 | //Begin: Base elements for curve and mesh (manifold and non-manifold) 18 | //==================================================================== 19 | 20 | //------------------------------------------------------------------- 21 | //VertexBase 22 | //------------------- 23 | class VertexBase{ 24 | public: 25 | //Constructor 26 | VertexBase(): _flag(0){} 27 | VertexBase(double x, double y, double z): _flag(0) 28 | { _co[0] = x; _co[1] = y; _co[2] = z; } 29 | VertexBase(VECTOR3 co): _flag(0) 30 | { _co = co; } 31 | 32 | VertexBase(const VertexBase& vb){ 33 | _co = vb.coord(); 34 | _flag = vb.flag(); 35 | } 36 | //Overloaded operator 37 | VertexBase& operator = (const VertexBase& vb){ 38 | _co = vb.coord(); 39 | _flag = vb.flag(); 40 | return *this; 41 | } 42 | //Function for accessing data 43 | VECTOR3 coord() const { return _co; } 44 | void set_coord(VECTOR3 co) { _co = co; } 45 | 46 | bool check_flag(unsigned char f) { return _flag&f; } 47 | void set_flag(unsigned char f) { _flag |= f; } 48 | void un_set_flag(unsigned char f) { _flag &= (~f); } 49 | unsigned char flag() const { return _flag; } 50 | void copy_flag(unsigned char f) { _flag = f; } 51 | 52 | private: 53 | VECTOR3 _co; 54 | unsigned char _flag; 55 | }; 56 | //------------------------------------------------------------------- 57 | 58 | //------------------------------------------------------------------- 59 | //EdgeBase 60 | //------------------- 61 | class EdgeBase{ 62 | public: 63 | //Constructor 64 | EdgeBase(): _flag(0) {} 65 | EdgeBase(unsigned int vs, unsigned int ve): _flag(0) { set_vs_ve(vs, ve); } 66 | EdgeBase(const EdgeBase& eb){ 67 | _vs = eb.vs(); _ve = eb.ve(); 68 | _flag = eb.flag(); 69 | } 70 | //Overloaded operator 71 | EdgeBase& operator = (const EdgeBase& eb){ 72 | _vs = eb.vs(); _ve = eb.ve(); 73 | _flag = eb.flag(); 74 | return *this; 75 | } 76 | 77 | //Functions for accessing data 78 | unsigned int vs() const { return _vs; } 79 | unsigned int ve() const { return _ve; } 80 | void set_vs_ve(unsigned int vs, unsigned int ve) { 81 | if(vs < ve) { _vs = vs; _ve = ve; } 82 | else { _vs = ve; _ve = vs; } 83 | } 84 | 85 | 86 | bool check_flag(unsigned char f) { return _flag&f; } 87 | void set_flag(unsigned char f) { _flag |= f; } 88 | void un_set_flag(unsigned char f) { _flag &= (~f); } 89 | unsigned char flag() const { return _flag; } 90 | void copy_flag(unsigned char f) { _flag = f; } 91 | 92 | //Functions for some simple operations 93 | inline int index(unsigned int vid){ 94 | if(_vs == vid) return 0; 95 | else if(_ve == vid) return 1; 96 | else return -1; 97 | } 98 | unsigned int opposite_vertex(unsigned int vid) { 99 | if( vid == _vs ) return _ve; 100 | else { 101 | assert(vid == _ve); 102 | return _vs; 103 | } 104 | } 105 | 106 | private: 107 | unsigned int _vs, _ve; 108 | unsigned char _flag; 109 | }; 110 | //------------------------------------------------------------------- 111 | 112 | //------------------------------------------------------------------- 113 | //TFacetBase 114 | //------------------- 115 | //Base of triangle facet 116 | //------------------------------------------------------------------- 117 | class TFacetBase{ 118 | public: 119 | //Constructors 120 | TFacetBase():_flag(0){ 121 | _facets[0] = -1; _facets[1] = -1; _facets[2] = -1; 122 | } 123 | TFacetBase(unsigned int v0, unsigned int v1, unsigned int v2):_flag(0){ 124 | _verts[0] = v0; _verts[1] = v1; _verts[2] = v2; 125 | _facets[0] = -1; _facets[1] = -1; _facets[2] = -1; 126 | } 127 | TFacetBase(const TFacetBase& fb){ 128 | _facets[0] = fb.facet(0); _facets[1] = fb.facet(1); _facets[2] = fb.facet(2); 129 | _verts[0] = fb.vert(0); _verts[1] = fb.vert(1); _verts[2] = fb.vert(2); 130 | _flag = fb.flag(); 131 | } 132 | //Assignment operators 133 | TFacetBase& operator = (const TFacetBase& fb){ 134 | _facets[0] = fb.facet(0); _facets[1] = fb.facet(1); _facets[2] = fb.facet(2); 135 | _verts[0] = fb.vert(0); _verts[1] = fb.vert(1); _verts[2] = fb.vert(2); 136 | _flag = fb.flag(); 137 | return *this; 138 | } 139 | 140 | //Functions for accessing data 141 | int facet(int i) const {return _facets[i];} 142 | void set_facet(int i, int f){ _facets[i] = f;} 143 | unsigned int vert(int i) const {return _verts[i];} 144 | void set_vert(int i, unsigned int v){ _verts[i] = v;} 145 | 146 | bool check_flag(unsigned short f) { return _flag&f; } 147 | void set_flag(unsigned short f) { _flag |= f; } 148 | void un_set_flag(unsigned short f) { _flag &= (~f); } 149 | unsigned short flag() const { return _flag; } 150 | void copy_flag(unsigned short f) { _flag = f; } 151 | 152 | //Functions for some simple operations 153 | int index(unsigned int v){ 154 | if(_verts[0] == v) return 0; 155 | else if(_verts[1] == v) return 1; 156 | else if(_verts[2] == v) return 2; 157 | else return -1; 158 | } 159 | 160 | int findex(int f){ 161 | if(_facets[0] == f) return 0; 162 | else if(_facets[1] == f) return 1; 163 | else if(_facets[2] == f) return 2; 164 | else return -1; 165 | } 166 | 167 | //using this function instead of the above for "bad"(such as non manifold) mesh. 168 | int findex(unsigned int vid0, unsigned int vid1){ 169 | if( index(vid0) < 0 || index(vid1) < 0 ) return -1; 170 | if(_verts[0] != vid0 && _verts[0] != vid1) return 0; 171 | if(_verts[1] != vid0 && _verts[1] != vid1) return 1; 172 | if(_verts[2] != vid0 && _verts[2] != vid1) return 2; 173 | 174 | cerr<<"Warning: invalid facet or parameter of function findex"< _verts; 245 | vector _facets; //_facets[i] contains the neighboring polygons about edge _verts[i]--_verts[i + 1] 246 | unsigned short _flag; 247 | }; 248 | 249 | //------------------------------------------------------------------- 250 | //NPFaceBase: 251 | //------------------- 252 | //Base of polygon facet for non-manifold 253 | class NPFacetBase{ 254 | public: 255 | //Constuctors 256 | NPFacetBase():_flag(0){} 257 | NPFacetBase(const NPFacetBase& fb){ 258 | copy_flag( fb.flag() ); 259 | for(unsigned int i = 0; i < fb.n_verts(); i ++) 260 | add_vert( fb.vert(i) ); 261 | _facetss.resize( fb.n_facetss() ); 262 | for(unsigned int i = 0; i < fb.n_facetss(); i ++){ 263 | for(unsigned int j = 0; j < fb.n_ith_facets(i); j ++){ 264 | add_facet( i, fb.facet(i, j) ); 265 | }//for j 266 | }//for i 267 | } 268 | //Overloaded operators 269 | NPFacetBase& operator = (const NPFacetBase& fb){ 270 | copy_flag( fb.flag() ); 271 | for(unsigned int i = 0; i < fb.n_verts(); i ++) 272 | add_vert( fb.vert(i) ); 273 | _facetss.resize( fb.n_facetss() ); 274 | for(unsigned int i = 0; i < fb.n_facetss(); i ++){ 275 | for(unsigned int j = 0; j < fb.n_ith_facets(i); j ++){ 276 | add_facet( i, fb.facet(i, j) ); 277 | }//for j 278 | }//for i 279 | return *this; 280 | } 281 | // 282 | void clear(){ _facetss.clear(); _verts.clear(); } 283 | 284 | //Functions for accessing data 285 | bool check_flag(unsigned short f) { return _flag&f; } 286 | void set_flag(unsigned short f) { _flag |= f; } 287 | void un_set_flag(unsigned short f) { _flag &= (~f); } 288 | unsigned short flag() const { return _flag; } 289 | void copy_flag(unsigned short f) { _flag = f; } 290 | 291 | 292 | unsigned int n_verts() const {return _verts.size();} 293 | unsigned int vert(unsigned int i) const {return _verts[i];} 294 | void set_vert(unsigned int i, unsigned int vid){ _verts[i] = vid; } 295 | unsigned int add_vert(unsigned int v){ _verts.push_back(v); return _verts.size() - 1;} 296 | 297 | unsigned int n_facetss() const {return _facetss.size();} 298 | unsigned int n_ith_facets(unsigned int i) const { return _facetss[i].size(); } 299 | void resize_facetss(unsigned int n) { _facetss.resize(n); } 300 | 301 | unsigned int facet(unsigned int eind, unsigned int find) const {return (_facetss[eind])[find];} 302 | void set_facet(unsigned int eind, unsigned int find, unsigned int fid) { (_facetss[eind])[find] = fid; } 303 | unsigned int add_facet(unsigned int eind, unsigned int fid){ _facetss[eind].push_back(fid); return _facetss[eind].size() - 1;} 304 | 305 | //Functions for some simple operations 306 | int index(unsigned int v){ 307 | for(unsigned int i = 0; i < _verts.size(); i ++) 308 | if( v == _verts[i]) return i; 309 | return -1; 310 | } 311 | 312 | int findex(unsigned int f){ 313 | for(unsigned int i = 0; i < n_facetss(); i ++){ 314 | for(unsigned int j = 0; j < n_ith_facets(i); j ++) 315 | if( f == facet(i, j) ) return i; 316 | } 317 | return -1; 318 | } 319 | bool findex(unsigned int f, unsigned int& eind, unsigned int& find){ 320 | for(unsigned int i = 0; i < n_facetss(); i ++){ 321 | for(unsigned int j = 0; j < n_ith_facets(i); j ++){ 322 | if( f == facet(i, j) ){ 323 | eind = i; find = j; return true; 324 | } 325 | }//for j 326 | }//for i 327 | return false; 328 | } 329 | 330 | void remove_facet(unsigned int eind, unsigned int fid){ 331 | for(unsigned int i = 0; i < n_ith_facets(eind); i ++){ 332 | if(fid == facet(eind, i)){ 333 | (_facetss[eind])[i] = facet(eind, n_ith_facets(eind) - 1); 334 | _facetss[eind].pop_back(); 335 | } 336 | }//for i 337 | } 338 | 339 | private: 340 | vector _verts; 341 | vector< vector > _facetss; //_facetss[i] contains the neighboring polygons about edge _verts[i]--_verts[i + 1] 342 | unsigned short _flag; 343 | }; 344 | //------------------------------------------------------------------- 345 | 346 | //==================================================================== 347 | //End: Base elements for curve and mesh (manifold and non-manifold) 348 | //==================================================================== 349 | 350 | enum pmode{ 351 | EIGEN, LLF, MEANC 352 | }; 353 | enum mmode{ 354 | MEYER, XU, OUR 355 | }; 356 | 357 | enum nmode{ 358 | DENSE, SPARSE 359 | }; 360 | 361 | enum stype{ 362 | PLANE, SPHERE, SKINSURF 363 | }; 364 | 365 | 366 | #endif //__DATASTRUCTURE_H__ 367 | -------------------------------------------------------------------------------- /MeshLP/matrix.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Purpose: vector and matrix class and operations 3 | // Created by: Matt Camuto 4 | // 5 | // Modification: 6 | // Time Programmer 7 | // 07-09-99 R. Wenger 8 | // 07-15-00 J. Gao 9 | // 08-09-03 J. Sun 10 | /////////////////////////////////////////////////////////////////// 11 | 12 | #include "matrix.h" 13 | 14 | #include 15 | #include 16 | using namespace std; 17 | int Shift[32]; 18 | 19 | void init_shift() { 20 | Shift[0] = 1; 21 | for (int i=1; i<32; i++) { 22 | Shift[i] = 1<32)) 28 | return 0; 29 | if (value & Shift[pos-1]) { 30 | return 1; 31 | } 32 | return 0; 33 | } 34 | 35 | void set_bit(INT_32 &value, int pos){ 36 | if ((pos<1)||(pos>32)) 37 | return; 38 | value =value|Shift[pos-1]; 39 | } 40 | 41 | //********************************************************* 42 | // 43 | // INT64 class definitions 44 | // 45 | //********************************************************* 46 | 47 | // Set the posth [1, 64] bit as 1 48 | void INT_64::set_bit(int pos){ 49 | if ((pos<1)||(pos>64)) 50 | return; 51 | int flag = (pos>32)?1:0; 52 | int move = (pos-1)%32; 53 | //vec[flag] |= Shift[move]; 54 | if (move==0) vec[flag] |=1; 55 | else vec[flag] |= 1<64)) 61 | return 0; 62 | int flag = (pos>32)?1:0; 63 | int move = (pos-1)%32; 64 | int temp = 0; 65 | if (move==0) temp |=1; 66 | else temp |= 1< maxval) maxval = vec[1]; 101 | if (vec[2] > maxval) maxval = vec[2]; 102 | return maxval; 103 | } 104 | 105 | // make sure all dimension <=1.0 106 | void VECTOR3::Clamp() 107 | { 108 | for (int i = 0; i < Dimension(); i++) 109 | if (vec[i]>1.0) vec[i] = 1.0; 110 | } 111 | 112 | //********************************************************* 113 | // 114 | // VECTOR4 class definitions 115 | // 116 | //********************************************************* 117 | 118 | // normalize vector 119 | // Assumes (pre-condition): vector != (0,0,0,0) 120 | void VECTOR4::Normalize() 121 | { 122 | double norm = sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 123 | 124 | if(norm < 1e-5) 125 | return; 126 | 127 | for (int i = 0; i < Dimension(); i++) 128 | vec[i] = vec[i]/norm; 129 | } 130 | 131 | 132 | //********************************************************* 133 | // 134 | // MATRIX3 class definitions 135 | // 136 | //********************************************************* 137 | 138 | // set matrix to identity matrix 139 | void MATRIX3::Identity() 140 | { 141 | for (int i = 0; i < Dimension(); i++) { 142 | mat[i].Zero(); 143 | mat[i][i] = 1.0; 144 | }; 145 | } 146 | 147 | void MATRIX3::Zero() 148 | { 149 | for (int i = 0; i < Dimension(); i++) { 150 | mat[i].Zero(); 151 | }; 152 | } 153 | 154 | //********************************************************* 155 | // 156 | // MATRIX4 class definitions 157 | // 158 | //********************************************************* 159 | 160 | // set matrix to identity matrix 161 | void MATRIX4::Identity() 162 | { 163 | for (int i = 0; i < Dimension(); i++) { 164 | mat[i].Zero(); 165 | mat[i][i] = 1.0; 166 | }; 167 | } 168 | 169 | //************************ 170 | // MATRIX3 operations 171 | //************************ 172 | 173 | // return m0 + m1 174 | MATRIX3 operator +(const MATRIX3 & m0, const MATRIX3 & m1) 175 | { 176 | MATRIX3 result; 177 | 178 | result[0] = m0(0) + m1(0); 179 | result[1] = m0(1) + m1(1); 180 | result[2] = m0(2) + m1(2); 181 | 182 | return(result); 183 | } 184 | 185 | // return m0 - m1 186 | MATRIX3 operator -(const MATRIX3 & m0, const MATRIX3 & m1) 187 | { 188 | MATRIX3 result; 189 | 190 | result[0] = m0(0) - m1(0); 191 | result[1] = m0(1) - m1(1); 192 | result[2] = m0(2) - m1(2); 193 | 194 | return(result); 195 | } 196 | 197 | // return m0 * m1 198 | MATRIX3 operator *(const MATRIX3 & m0, const MATRIX3 & m1) 199 | { 200 | MATRIX3 result; 201 | 202 | for (int i = 0; i < m0.Dimension(); i++) 203 | for (int j = 0; j < m0.Dimension(); j++) { 204 | result[i][j] = 0; 205 | for (int k = 0; k < m0.Dimension(); k++) 206 | result[i][j] += m0(i,k) * m1(k,j); 207 | }; 208 | 209 | return(result); 210 | } 211 | 212 | // return x0 * m0 213 | MATRIX3 operator *(const double x0, const MATRIX3 & m0) 214 | { 215 | MATRIX3 result; 216 | 217 | result[0] = x0*m0(0); 218 | result[1] = x0*m0(1); 219 | result[2] = x0*m0(2); 220 | 221 | return(result); 222 | } 223 | 224 | // return m0 * x0 225 | MATRIX3 operator *(const MATRIX3 & m0, const double x0) 226 | { return(x0*m0); }; 227 | 228 | // return m0 * v0 229 | VECTOR3 operator *(const MATRIX3 & m0, const VECTOR3 & v0) 230 | { 231 | VECTOR3 result; 232 | 233 | result[0] = dot(m0(0),v0); 234 | result[1] = dot(m0(1),v0); 235 | result[2] = dot(m0(2),v0); 236 | 237 | return(result); 238 | } 239 | 240 | // return v0 * m0 241 | VECTOR3 operator *(const VECTOR3 & v0, const MATRIX3 & m0) 242 | { 243 | VECTOR3 result; 244 | 245 | result[0] = v0(0)*m0(0,0) + v0(1)*m0(1,0) + v0(2)*m0(2,0); 246 | result[1] = v0(0)*m0(0,1) + v0(1)*m0(1,1) + v0(2)*m0(2,1); 247 | result[2] = v0(0)*m0(0,2) + v0(1)*m0(1,2) + v0(2)*m0(2,2); 248 | 249 | return(result); 250 | } 251 | 252 | //************************ 253 | // MATRIX4 operations 254 | //************************ 255 | 256 | // get the rotation matrix 257 | // type: 1:x, 2:y, 3:z 258 | MATRIX4 rotate_matrix(int type, double angle) { 259 | MATRIX4 rot_mat; 260 | switch(type) { 261 | case 1: // rotate by x 262 | { 263 | double anglex = (angle/180.0f)*3.14159f; 264 | double sinx = (double)sin((double)anglex); 265 | double cosx = (double)cos((double)anglex); 266 | rot_mat[1][1] = rot_mat[2][2] = cosx; 267 | rot_mat[1][2] = -sinx; 268 | rot_mat[2][1] = sinx; 269 | break; 270 | } 271 | case 2: // rotate by y 272 | { 273 | double angley = (angle/180.0f)*3.14159f; 274 | double siny = (double)sin((double)angley); 275 | double cosy = (double)cos((double)angley); 276 | rot_mat[0][0] = rot_mat[2][2] = cosy; 277 | rot_mat[0][2] = siny; 278 | rot_mat[2][0] = -siny; 279 | break; 280 | } 281 | case 3: // rotate by z 282 | { 283 | double anglez = (angle/180.0f)*3.14159f; 284 | double sinz = (double)sin((double)anglez); 285 | double cosz = (double)cos((double)anglez); 286 | rot_mat[0][0] = rot_mat[1][1] = cosz; 287 | rot_mat[0][1] = -sinz; 288 | rot_mat[1][0] = sinz; 289 | break; 290 | } 291 | } 292 | return rot_mat; 293 | } 294 | 295 | // get translation matrix 296 | MATRIX4 translate_matrix(double tx, double ty, double tz){ 297 | MATRIX4 translation_mat; 298 | translation_mat[0][3] = tx; 299 | translation_mat[1][3] = ty; 300 | translation_mat[2][3] = tz; 301 | return translation_mat; 302 | } 303 | 304 | // get scaling matrix 305 | MATRIX4 scale_matrix(double sx, double sy, double sz){ 306 | MATRIX4 scale_mat; 307 | scale_mat[0][0] = sx; 308 | scale_mat[1][1] = sy; 309 | scale_mat[2][2] = sz; 310 | return scale_mat; 311 | } 312 | 313 | // return m0 + m1 314 | MATRIX4 operator +(const MATRIX4 & m0, const MATRIX4 & m1) 315 | { 316 | MATRIX4 result; 317 | 318 | result[0] = m0(0) + m1(0); 319 | result[1] = m0(1) + m1(1); 320 | result[2] = m0(2) + m1(2); 321 | result[3] = m0(3) + m1(3); 322 | 323 | return(result); 324 | } 325 | 326 | // return m0 - m1 327 | MATRIX4 operator -(const MATRIX4 & m0, const MATRIX4 & m1) 328 | { 329 | MATRIX4 result; 330 | 331 | result[0] = m0(0) - m1(0); 332 | result[1] = m0(1) - m1(1); 333 | result[2] = m0(2) - m1(2); 334 | result[3] = m0(3) - m1(3); 335 | 336 | return(result); 337 | } 338 | 339 | // return m0 * m1 340 | MATRIX4 operator *(const MATRIX4 & m0, const MATRIX4 & m1) 341 | { 342 | MATRIX4 result; 343 | 344 | for (int i = 0; i < m0.Dimension(); i++) 345 | for (int j = 0; j < m0.Dimension(); j++) { 346 | result[i][j] = 0; 347 | for (int k = 0; k < m0.Dimension(); k++) 348 | result[i][j] += m0(i,k) * m1(k,j); 349 | }; 350 | 351 | return(result); 352 | } 353 | 354 | // return x0 * m0 355 | MATRIX4 operator *(const double x0, const MATRIX4 & m0) 356 | { 357 | MATRIX4 result; 358 | 359 | result[0] = x0*m0(0); 360 | result[1] = x0*m0(1); 361 | result[2] = x0*m0(2); 362 | result[3] = x0*m0(3); 363 | 364 | return(result); 365 | } 366 | 367 | // return m0 * x0 368 | MATRIX4 operator *(const MATRIX4 & m0, const double x0) 369 | { return(x0*m0); }; 370 | 371 | // return m0 * v0 372 | VECTOR4 operator *(const MATRIX4 & m0, const VECTOR4 & v0) 373 | { 374 | VECTOR4 result; 375 | 376 | result[0] = dot(m0(0),v0); 377 | result[1] = dot(m0(1),v0); 378 | result[2] = dot(m0(2),v0); 379 | result[3] = dot(m0(3),v0); 380 | 381 | return(result); 382 | } 383 | 384 | 385 | // return m0 * v0 386 | VECTOR3 operator *(const MATRIX4 & m0, const VECTOR3 & v0) 387 | { 388 | VECTOR4 v(v0); 389 | VECTOR3 result; 390 | 391 | double temp = dot(m0(3),v); 392 | result[0] = dot(m0(0),v)/temp; 393 | result[1] = dot(m0(1),v)/temp; 394 | result[2] = dot(m0(2),v)/temp; 395 | return(result); 396 | } 397 | 398 | 399 | VECTOR4 operator *(const VECTOR4 & v0, const MATRIX4 & m0) 400 | // return v0 * m0 401 | { 402 | VECTOR4 result; 403 | 404 | result[0] = v0(0)*m0(0,0) + v0(1)*m0(1,0) + v0(2)*m0(2,0) + v0(3)*m0(3,0); 405 | result[1] = v0(0)*m0(0,1) + v0(1)*m0(1,1) + v0(2)*m0(2,1) + v0(3)*m0(3,1); 406 | result[2] = v0(0)*m0(0,2) + v0(1)*m0(1,2) + v0(2)*m0(2,2) + v0(3)*m0(3,2); 407 | result[3] = v0(0)*m0(0,3) + v0(1)*m0(1,3) + v0(2)*m0(2,3) + v0(3)*m0(3,3); 408 | 409 | return(result); 410 | } 411 | 412 | VECTOR3 operator *(const VECTOR3 & v0, const MATRIX4 & m0) 413 | // return v0 * m0 414 | { 415 | VECTOR3 result; 416 | double temp = v0(0)*m0(0,3) + v0(1)*m0(1,3) + v0(2)*m0(2,3) + m0(3,3); 417 | 418 | result[0] = (v0(0)*m0(0,0) + v0(1)*m0(1,0) + v0(2)*m0(2,0) + m0(3,0))/temp; 419 | result[1] = (v0(0)*m0(0,1) + v0(1)*m0(1,1) + v0(2)*m0(2,1) + m0(3,1))/temp; 420 | result[2] = (v0(0)*m0(0,2) + v0(1)*m0(1,2) + v0(2)*m0(2,2) + m0(3,2))/temp; 421 | 422 | return(result); 423 | } 424 | 425 | //Code was taken from the original 'edge' library written by dave ebert. 426 | MATRIX4 inverse(const MATRIX4 & m) { 427 | register int lp,i,j,k; 428 | static double wrk[4][8]; 429 | static double a, b; 430 | MATRIX4 result; 431 | 432 | for( i=0; i<4; i++ ) /* Set up matrices */ 433 | { 434 | for( j=0; j<4; j++ ) 435 | { 436 | wrk[i][j]=(double)m(i,j); 437 | wrk[i][j+4]=0.0; 438 | result[i][j] = 0.0; 439 | } 440 | wrk[i][i+4]=1.0; 441 | } 442 | 443 | for( lp=0; lp<4; lp++ ) /* Loop over all rows */ 444 | { 445 | a=0.0; 446 | j=(-1); 447 | for( i=lp; i<4; i++ ) /* Find largest non-zero element */ 448 | { 449 | b=wrk[i][lp]; 450 | if( b< 0.0 ) 451 | b=(-b); 452 | if( b>a ) 453 | { 454 | a=b; 455 | j=i; 456 | } 457 | } 458 | if( j!=lp ) /* If not on diagonal, put it there */ 459 | { 460 | if( j<0 ) /* Singular if none found */ 461 | return(result); 462 | else /* Exchange rows from lp to end */ 463 | for( k=lp; k<8; k++ ) 464 | { 465 | a=wrk[j][k]; 466 | wrk[j][k]=wrk[lp][k]; 467 | wrk[lp][k]=a; 468 | } 469 | } 470 | a=wrk[lp][lp]; /* Normalize working row */ 471 | for( i=lp; i<8; i++ ) 472 | wrk[lp][i]/=a; 473 | 474 | for( i=lp+1; i<8; i++ ) /* Adjust rest of work space */ 475 | { 476 | b=wrk[lp][i]; 477 | for( j=0; j<4; j++ ) /* One column at a time */ 478 | if( j!=lp ) 479 | wrk[j][i]-=wrk[j][lp]*b; 480 | } 481 | } 482 | 483 | for( i=0; i<4; i++ ) /* Return result matrix */ 484 | for( j=0; j<4; j++ ) 485 | result[i][j]=(double)wrk[i][j+4]; 486 | return(result); 487 | } 488 | 489 | //******************************* 490 | // output procedures/operators 491 | //******************************* 492 | 493 | // output vector 494 | ostream & operator<<(ostream & os, const VECTOR3 & v) 495 | { 496 | os << "( " << v(0) << " " << v(1) << " " << v(2) << " )"; 497 | return(os); 498 | } 499 | 500 | // output vector 501 | ostream & operator<<(ostream & os, const VECTOR4 & v) 502 | { 503 | os << "( " << v(0) << " " << v(1) << " " << v(2) << " " << v(3) << " )"; 504 | return(os); 505 | } 506 | 507 | // routine to print out matrix. Useful for debugging. 508 | // call at the beginning of a new line for proper formatting 509 | // mat = matrix 510 | // indent = # of indented spaces 511 | // cout_width = output field width 512 | // precision = output precision 513 | void print_matrix(const MATRIX3 & mat, 514 | const int indent, const int cout_width, const int precision) 515 | { 516 | cout.precision(precision); 517 | cout.flags(ios::fixed); 518 | for (int i = 0; i < mat.Dimension(); i++) { 519 | int j; 520 | for (j = 0; j < indent; j++) 521 | cout << " "; 522 | cout << "( "; 523 | for (j = 0; j < mat.Dimension(); j++) 524 | cout << setw(cout_width) << mat(i,j) << " "; 525 | cout << ")" << endl; 526 | }; 527 | } 528 | 529 | // routine to print out matrix. Useful for debugging. 530 | // call at the beginning of a new line for proper formatting 531 | // mat = matrix 532 | // indent = # of indented spaces 533 | // cout_width = output field width 534 | // precision = output precision 535 | void print_matrix(const MATRIX4 & mat, 536 | const int indent, const int cout_width, const int precision) 537 | { 538 | cout.precision(precision); 539 | cout.flags(ios::fixed); 540 | for (int i = 0; i < mat.Dimension(); i++) { 541 | int j; 542 | for (j = 0; j < indent; j++) 543 | cout << " "; 544 | cout << "( "; 545 | for (j = 0; j < mat.Dimension(); j++) 546 | cout << setw(cout_width) << mat(i,j) << " "; 547 | cout << ")" << endl; 548 | } 549 | } 550 | 551 | -------------------------------------------------------------------------------- /MeshLP/geodesics/geodesic_mesh.h: -------------------------------------------------------------------------------- 1 | //Copyright (C) 2008 Danil Kirsanov, MIT License 2 | #ifndef GEODESIC_MESH_20071231 3 | #define GEODESIC_MESH_20071231 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "geodesic_mesh_elements.h" 13 | #include "geodesic_memory.h" 14 | #include "geodesic_constants_and_simple_functions.h" 15 | 16 | namespace geodesic{ 17 | 18 | struct edge_visible_from_source 19 | { 20 | unsigned source; 21 | edge_pointer edge; 22 | }; 23 | 24 | class Mesh 25 | { 26 | public: 27 | Mesh() 28 | {}; 29 | 30 | ~Mesh(){}; 31 | 32 | template 33 | void initialize_mesh_data(unsigned num_vertices, 34 | Points& p, 35 | unsigned num_faces, 36 | Faces& tri); //build mesh from regular point-triangle representation 37 | 38 | template 39 | void initialize_mesh_data(Points& p, Faces& tri); //build mesh from regular point-triangle representation 40 | 41 | std::vector& vertices(){return m_vertices;}; 42 | std::vector& edges(){return m_edges;}; 43 | std::vector& faces(){return m_faces;}; 44 | 45 | unsigned closest_vertices(SurfacePoint* p, 46 | std::vector* storage = NULL); //list vertices closest to the point 47 | 48 | private: 49 | 50 | void build_adjacencies(); //build internal structure of the mesh 51 | bool verify(); //verifies connectivity of the mesh and prints some debug info 52 | 53 | typedef void* void_pointer; 54 | void_pointer allocate_pointers(unsigned n) 55 | { 56 | return m_pointer_allocator.allocate(n); 57 | } 58 | 59 | std::vector m_vertices; 60 | std::vector m_edges; 61 | std::vector m_faces; 62 | 63 | SimlpeMemoryAllocator m_pointer_allocator; //fast memory allocating for Face/Vertex/Edge cross-references 64 | }; 65 | 66 | inline unsigned Mesh::closest_vertices(SurfacePoint* p, 67 | std::vector* storage) 68 | { 69 | assert(p->type() != UNDEFINED_POINT); 70 | 71 | if(p->type() == VERTEX) 72 | { 73 | if(storage) 74 | { 75 | storage->push_back(static_cast(p->base_element())); 76 | } 77 | return 1; 78 | } 79 | else if(p->type() == FACE) 80 | { 81 | if(storage) 82 | { 83 | vertex_pointer* vp= p->base_element()->adjacent_vertices().begin(); 84 | storage->push_back(*vp); 85 | storage->push_back(*(vp+1)); 86 | storage->push_back(*(vp+2)); 87 | } 88 | return 2; 89 | } 90 | else if(p->type() == EDGE) //for edge include all 4 adjacent vertices 91 | { 92 | edge_pointer edge = static_cast(p->base_element()); 93 | 94 | if(storage) 95 | { 96 | storage->push_back(edge->adjacent_vertices()[0]); 97 | storage->push_back(edge->adjacent_vertices()[1]); 98 | 99 | for(unsigned i = 0; i < edge->adjacent_faces().size(); ++i) 100 | { 101 | face_pointer face = edge->adjacent_faces()[i]; 102 | storage->push_back(face->opposite_vertex(edge)); 103 | } 104 | } 105 | return 2 + edge->adjacent_faces().size(); 106 | } 107 | 108 | assert(0); 109 | return 0; 110 | } 111 | 112 | template 113 | void Mesh::initialize_mesh_data(Points& p, Faces& tri) //build mesh from regular point-triangle representation 114 | { 115 | assert(p.size() % 3 == 0); 116 | unsigned const num_vertices = p.size() / 3; 117 | assert(tri.size() % 3 == 0); 118 | unsigned const num_faces = tri.size() / 3; 119 | 120 | initialize_mesh_data(num_vertices, p, num_faces, tri); 121 | } 122 | 123 | template 124 | void Mesh::initialize_mesh_data(unsigned num_vertices, 125 | Points& p, 126 | unsigned num_faces, 127 | Faces& tri) 128 | { 129 | unsigned const approximate_number_of_internal_pointers = (num_vertices + num_faces)*4; 130 | unsigned const max_number_of_pointer_blocks = 100; 131 | m_pointer_allocator.reset(approximate_number_of_internal_pointers, 132 | max_number_of_pointer_blocks); 133 | 134 | m_vertices.resize(num_vertices); 135 | for(unsigned i=0; iadjacent Faces 168 | std::vector count(m_vertices.size()); //count adjacent vertices 169 | for(unsigned i=0; iid(); 175 | assert(vertex_id < m_vertices.size()); 176 | count[vertex_id]++; 177 | } 178 | } 179 | 180 | for(unsigned i=0; iadjacent_faces()[count[v->id()]++] = &f; 197 | } 198 | } 199 | 200 | //find all edges 201 | //i.e. find all half-edges, sort and combine them into edges 202 | std::vector half_edges(m_faces.size()*3); 203 | unsigned k = 0; 204 | for(unsigned i=0; iid(); 211 | unsigned vertex_id_2 = f.adjacent_vertices()[(j+1) % 3]->id(); 212 | half_edges[k].vertex_0 = std::min(vertex_id_1, vertex_id_2); 213 | half_edges[k].vertex_1 = std::max(vertex_id_1, vertex_id_2); 214 | 215 | k++; 216 | } 217 | } 218 | std::sort(half_edges.begin(), half_edges.end()); 219 | 220 | unsigned number_of_edges = 1; 221 | for(unsigned i=1; iadjacent Vertices and Faces 237 | m_edges.resize(number_of_edges); 238 | unsigned edge_id = 0; 239 | for(unsigned i=0; idistance(e.adjacent_vertices()[1]); 250 | assert(e.length() > 1e-100); //algorithm works well with non-degenerate meshes only 251 | 252 | if(i != half_edges.size()-1 && half_edges[i] == half_edges[i+1]) //double edge 253 | { 254 | e.adjacent_faces().set_allocation(allocate_pointers(2),2); 255 | e.adjacent_faces()[0] = &m_faces[half_edges[i].face_id]; 256 | e.adjacent_faces()[1] = &m_faces[half_edges[i+1].face_id]; 257 | i += 2; 258 | } 259 | else //single edge 260 | { 261 | e.adjacent_faces().set_allocation(allocate_pointers(1),1); //one adjucent faces 262 | e.adjacent_faces()[0] = &m_faces[half_edges[i].face_id]; 263 | i += 1; 264 | } 265 | } 266 | 267 | // Vertices->adjacent Edges 268 | std::fill(count.begin(), count.end(), 0); 269 | for(unsigned i=0; iid()]++; 274 | count[e.adjacent_vertices()[1]->id()]++; 275 | } 276 | for(unsigned i=0; iadjacent_edges()[count[v->id()]++] = &e; 289 | } 290 | } 291 | 292 | // Faces->adjacent Edges 293 | for(unsigned i=0; iid()]<3); 307 | f->adjacent_edges()[count[f->id()]++] = &e; 308 | } 309 | } 310 | 311 | //compute angles for the faces 312 | for(unsigned i=0; ilength(); 323 | } 324 | 325 | double angle = angle_from_edges(abc[0], abc[1], abc[2]); 326 | assert(angle>1e-5); //algorithm works well with non-degenerate meshes only 327 | 328 | f.corner_angles()[j] = angle; 329 | sum += angle; 330 | } 331 | assert(std::abs(sum - M_PI) < 1e-5); //algorithm works well with non-degenerate meshes only 332 | } 333 | 334 | //define m_turn_around_flag for vertices 335 | std::vector total_vertex_angle(m_vertices.size()); 336 | for(unsigned i=0; iid()] += f.corner_angles()[j]; 343 | } 344 | } 345 | 346 | for(unsigned i=0; i 2.0*M_PI - 1e-5); 350 | } 351 | 352 | for(unsigned i=0; isaddle_or_boundary() = true; 358 | e.adjacent_vertices()[1]->saddle_or_boundary() = true; 359 | } 360 | } 361 | 362 | assert(verify()); 363 | } 364 | 365 | inline bool Mesh::verify() //verifies connectivity of the mesh and prints some debug info 366 | { 367 | std::cout << std::endl; 368 | // make sure that all vertices are mentioned at least once. 369 | // though the loose vertex is not a bug, it most likely indicates that something is wrong with the mesh 370 | std::vector map(m_vertices.size(), false); 371 | for(unsigned i=0; iadjacent_vertices()[0]->id()] = true; 375 | map[e->adjacent_vertices()[1]->id()] = true; 376 | } 377 | assert(std::find(map.begin(), map.end(), false) == map.end()); 378 | 379 | //make sure that the mesh is connected trough its edges 380 | //if mesh has more than one connected component, it is most likely a bug 381 | std::vector stack(1,&m_faces[0]); 382 | stack.reserve(m_faces.size()); 383 | 384 | map.resize(m_faces.size()); 385 | std::fill(map.begin(), map.end(), false); 386 | map[0] = true; 387 | 388 | while(!stack.empty()) 389 | { 390 | face_pointer f = stack.back(); 391 | stack.pop_back(); 392 | 393 | for(unsigned i=0; i<3; ++i) 394 | { 395 | edge_pointer e = f->adjacent_edges()[i]; 396 | face_pointer f_adjacent = e->opposite_face(f); 397 | if(f_adjacent && !map[f_adjacent->id()]) 398 | { 399 | map[f_adjacent->id()] = true; 400 | stack.push_back(f_adjacent); 401 | } 402 | } 403 | } 404 | assert(std::find(map.begin(), map.end(), false) == map.end()); 405 | 406 | //print some mesh statistics that can be useful in debugging 407 | std::cout << "mesh has " << m_vertices.size() 408 | << " vertices, " << m_faces.size() 409 | << " faces, " << m_edges.size() 410 | << " edges\n"; 411 | 412 | unsigned total_boundary_edges = 0; 413 | double longest_edge = 0; 414 | double shortest_edge = 1e100; 415 | for(unsigned i=0; iset(data); 484 | unsigned type = (unsigned) data[3]; 485 | unsigned id = (unsigned) data[4]; 486 | 487 | 488 | if(type == 0) //vertex 489 | { 490 | point->base_element() = &mesh->vertices()[id]; 491 | } 492 | else if(type == 1) //edge 493 | { 494 | point->base_element() = &mesh->edges()[id]; 495 | } 496 | else //face 497 | { 498 | point->base_element() = &mesh->faces()[id]; 499 | } 500 | } 501 | 502 | inline void fill_surface_point_double(geodesic::SurfacePoint* point, 503 | double* data, 504 | long mesh_id) 505 | { 506 | data[0] = point->x(); 507 | data[1] = point->y(); 508 | data[2] = point->z(); 509 | data[4] = point->base_element()->id(); 510 | 511 | if(point->type() == VERTEX) //vertex 512 | { 513 | data[3] = 0; 514 | } 515 | else if(point->type() == EDGE) //edge 516 | { 517 | data[3] = 1; 518 | } 519 | else //face 520 | { 521 | data[3] = 2; 522 | } 523 | } 524 | 525 | } //geodesic 526 | 527 | #endif 528 | -------------------------------------------------------------------------------- /MeshLP/matrix.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Purpose: vector and matrix class and operations 3 | // Paper: Hierarchical Polygon Tiling with Coverage Masks 4 | // Created by: Matt Camuto 5 | // 6 | // Modification: 7 | // Time Programmer 8 | // 07-09-99 R. Wenger 9 | // 08-20-99 K. Boner 10 | // 07-15-00 J. Gao 11 | // 08-09-03 J. Sun 12 | /////////////////////////////////////////////////////////////////// 13 | 14 | 15 | #ifndef MATRIX_H 16 | #define MATRIX_H 17 | 18 | /////////////////////////////////////////////////////////////////// 19 | // 2d, 3d and 4d vector and matrix classes. 20 | // Supports vector and matrix addition and subtraction, 21 | // matrix multiplication, vector dot products, cross products, 22 | // normalization, etc. 23 | /////////////////////////////////////////////////////////////////// 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | using namespace std; 30 | 31 | typedef unsigned int INT_32; 32 | 33 | extern void init_shift(); 34 | extern int is_bit_set(INT_32 value, int pos); 35 | extern void set_bit(INT_32 &value, int pos); 36 | 37 | 38 | // 16 bit structure used for bit mask 39 | class INT_64 { 40 | 41 | private : 42 | INT_32 vec[2]; 43 | 44 | public : 45 | INT_64() // constructor 46 | { Zero();}; 47 | INT_64(const INT_32 x0, const INT_32 x1) // constructor 48 | { vec[0] = x0; vec[1] = x1;}; 49 | ~INT_64() {}; 50 | int Dimension() const 51 | { return 2; }; 52 | INT_32 & operator [](const int i) // index i'th element 53 | { return(vec[i]); }; 54 | INT_32 operator ()(const int i) const // return i'th element 55 | { return(vec[i]); }; 56 | const INT_64 & operator =(const INT_64 & v0) // copy vector v0 57 | { vec[0] = v0(0); vec[1] = v0(1); 58 | return(*this); }; 59 | void Zero() // make zero vector 60 | { vec[0] = vec[1] = 0; }; 61 | void Fullset() { 62 | vec[0] = ~0; 63 | vec[1] = ~0; 64 | }; 65 | void combine(INT_64 &v0) 66 | { 67 | vec[0] = vec[0] | v0[0]; 68 | vec[1] = vec[1] | v0[1]; 69 | } 70 | void combine2(INT_32 &v0, INT_32 &v1) 71 | { 72 | vec[0] = vec[0] | v0; 73 | vec[1] = vec[1] | v1; 74 | } 75 | 76 | void set_bit(int pos); 77 | int is_set(int pos); 78 | int is_zero() { 79 | if (vec[0] || vec[1]) 80 | return 0; 81 | return 1; 82 | }; 83 | int is_full() { 84 | INT_32 full = ~0; 85 | if ((vec[0]==full)&&(vec[1]==full)) 86 | return 1; 87 | return 0; 88 | }; 89 | void print(FILE *fp) const {fprintf(fp, "%d, %d", vec[0], vec[1]); }; 90 | }; 91 | 92 | 93 | // 2d vector used for Point 94 | class VECTOR2 { 95 | 96 | private : 97 | double vec[2]; 98 | 99 | public : 100 | VECTOR2() // constructor 101 | { Zero(); }; 102 | VECTOR2(const double x0, const double x1) // constructor 103 | { vec[0] = x0; vec[1] = x1;}; 104 | int Dimension() const 105 | { return 2; }; 106 | double & operator [](const int i) // index i'th element 107 | { return(vec[i]); }; 108 | double operator ()(const int i) const // return i'th element 109 | { return(vec[i]); }; 110 | const VECTOR2 & operator =(const VECTOR2 & v0) // copy vector v0 111 | { vec[0] = v0(0); vec[1] = v0(1); 112 | return(*this); }; 113 | 114 | const VECTOR2 operator *(const double t) //number mulitple overload 115 | { return VECTOR2(vec[0] * t, vec[1] * t); } 116 | const double operator *(const VECTOR2 & v0) //dot product overload 117 | { return vec[0] * v0.vec[0] + vec[1] * v0.vec[1]; } 118 | const VECTOR2 operator +(const VECTOR2 & v0) //add overload 119 | { return VECTOR2(vec[0] + v0.vec[0], vec[1] + v0.vec[1]); } 120 | // { return VECTOR2(vec[0], vec[1]); } 121 | const VECTOR2 operator - (const VECTOR2 & v0) //sub overload 122 | { return VECTOR2(vec[0] - v0.vec[0], vec[1] - v0.vec[1]); } 123 | // { return VECTOR2(vec[0], vec[1]); } 124 | 125 | void Normalize(); 126 | 127 | void Zero() // make zero vector 128 | { vec[0] = vec[1] = 0.0; }; 129 | void Set(const double x0, const double x1) 130 | { vec[0] = x0; vec[1] = x1; }; 131 | }; 132 | 133 | // Line class 134 | typedef struct line_2d { 135 | VECTOR2 start; 136 | VECTOR2 end; 137 | }Line; 138 | 139 | // 3d vector class 140 | class VECTOR3 { 141 | 142 | private : 143 | public : 144 | double vec[3]; 145 | 146 | public : 147 | friend class VECTOR4; 148 | VECTOR3() // constructor 149 | { Zero(); }; 150 | VECTOR3(const double x0, const double x1, const double x2) // constructor 151 | { vec[0] = x0; vec[1] = x1; vec[2] = x2; }; 152 | void Set(const double x0, const double x1, const double x2) 153 | { vec[0] = x0; vec[1] = x1; vec[2] = x2; }; 154 | int Dimension() const 155 | { return 3; }; 156 | double & operator [](const int i) // index i'th element 157 | { return(vec[i]); }; 158 | double operator ()(const int i) const // return i'th element 159 | { return(vec[i]); }; 160 | const VECTOR3 & operator =(const VECTOR3 & v0) // copy vector v0 161 | { vec[0] = v0(0); vec[1] = v0(1); vec[2] = v0(2); 162 | return(*this); }; 163 | void Zero() // make zero vector 164 | { vec[0] = vec[1] = vec[2] = 0.0; }; 165 | double GetMax(); 166 | void Clamp(); 167 | const double Magnitude(){ 168 | return sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 169 | } 170 | 171 | void Normalize() 172 | { 173 | double norm = Magnitude(); 174 | if(norm != 0){ 175 | norm = 1.0 / norm; 176 | vec[0] = vec[0] * norm; vec[1] = vec[1] * norm; vec[2] = vec[2] * norm; 177 | } 178 | } 179 | 180 | const VECTOR3 Hat() 181 | { double norm = Magnitude(); 182 | if(norm != 0){ 183 | norm = 1.0 / norm; 184 | return VECTOR3(vec[0] * norm, vec[1] * norm, vec[2] * norm); 185 | } 186 | return VECTOR3(vec[0], vec[1], vec[2]); 187 | } 188 | /* 189 | const VECTOR3 operator *(const double t) //number multiply 190 | { return VECTOR3( vec[0] * t, vec[1] * t, vec[2] * t ); } 191 | const double operator *(const VECTOR3 & v0) //dot product (v' * v) 192 | { return vec[0] * v0(0) + vec[1] * v0(1) + vec[2] * v0(2); } 193 | const VECTOR3 operator ^(const VECTOR3 & v0) //cross product 194 | { return VECTOR3( vec[1] * v0(2) - vec[2] * v0(1), 195 | vec[2] * v0(0) - vec[0] * v0(2), 196 | vec[0] * v0(1) - vec[1] * v0(0) ); } 197 | const VECTOR3 operator +(const VECTOR3 & v0) //add overload 198 | { return VECTOR3( vec[0] + v0(0), vec[1] + v0(1), vec[2] + v0(2) ); } 199 | const VECTOR3 operator -(const VECTOR3 & v0) //sub overload 200 | { return VECTOR3( vec[0] - v0(0), vec[1] - v0(1), vec[2] - v0(2) ); } 201 | */ 202 | 203 | const VECTOR3& operator +=(const VECTOR3 & v0) //+= overload 204 | { vec[0] += v0(0); vec[1] += v0(1); vec[2] += v0(2); 205 | return (*this); } 206 | const VECTOR3& operator -=(const VECTOR3 & v0) //+= overload 207 | { vec[0] -= v0(0); vec[1] -= v0(1); vec[2] -= v0(2); 208 | return (*this); } 209 | 210 | }; 211 | 212 | // 4d vector class 213 | class VECTOR4 { 214 | 215 | private : 216 | double vec[4]; 217 | 218 | public : 219 | VECTOR4() // constructor 220 | { Zero(); }; 221 | VECTOR4(VECTOR3 v) // constructor 222 | { vec[0] = v[0]; vec[1] = v[1]; vec[2] = v[2]; vec[3] = 1.0; }; 223 | VECTOR4(VECTOR3 v, double x) 224 | { vec[0] = v[0]; vec[1] = v[1]; vec[2] = v[2]; vec[3] = x; }; 225 | VECTOR4(const double x0, const double x1, 226 | const double x2, const double x3) // constructor 227 | { vec[0] = x0; vec[1] = x1; vec[2] = x2; vec[3] = x3; }; 228 | 229 | int Dimension() const 230 | { return 4; }; 231 | double & operator [](const int i) // index i'th element 232 | { return(vec[i]); }; 233 | double operator ()(const int i) const // return i'th element 234 | { return(vec[i]); }; 235 | const VECTOR4 & operator =(const VECTOR4 & v0) // copy vector v0 236 | { vec[0] = v0(0); vec[1] = v0(1); vec[2] = v0(2); vec[3] = v0(3); 237 | return(*this); }; 238 | const VECTOR4 & operator =(const VECTOR3 & v0) // copy vector v0 239 | { vec[0] = v0(0); vec[1] = v0(1); vec[2] = v0(2); vec[3] = 1.0; 240 | return(*this); }; 241 | 242 | VECTOR3 get_vector3() 243 | { VECTOR3 temp(vec[0]/vec[3], vec[1]/vec[3], vec[2]/vec[3]); return temp;}; 244 | void Zero() // make zero vector 245 | { vec[0] = vec[1] = vec[2] = vec[3] = 0.0; }; 246 | void Normalize(); // normalize vector 247 | }; 248 | 249 | // 3d matrix 250 | class MATRIX3 { 251 | 252 | private : 253 | VECTOR3 mat[3]; // a vector represents each matrix row 254 | 255 | public : 256 | 257 | MATRIX3() // constructor 258 | { Identity(); }; 259 | MATRIX3(const VECTOR3 & v0, const VECTOR3 & v1, const VECTOR3 & v2) 260 | { mat[0] = v0; mat[1] = v1; mat[2] = v2; }; // constructor 261 | int Dimension() const 262 | { return 3; }; 263 | VECTOR3 & operator [](const int i) // index row i 264 | { return(mat[i]); }; 265 | // Note: reference row i, column j of MATRIX3 m0 as m0[i][j] (not m0[i,j]) 266 | VECTOR3 operator()(const int i) const // return row i 267 | { return(mat[i]); }; 268 | double operator ()(const int i, const int j) const 269 | { return(mat[i](j)); }; // return element (i,j) 270 | MATRIX3 & operator =(const MATRIX3 & m0) // copy matrix m0 271 | { mat[0] = m0(0); mat[1] = m0(1); mat[2] = m0(2); 272 | return(*this); }; 273 | void Identity(); // set to identity 274 | void Zero(); 275 | 276 | /* 277 | const MATRIX3 operator *(const double t) //number multiply 278 | { return MATRIX3( mat[0] * t, mat[1] * t, mat[2] * t ); } 279 | 280 | const MATRIX3 operator +(const MATRIX3 & m0) //add overload 281 | { return MATRIX3( mat[0] + m0(0), mat[1] + m0(1), mat[2] + m0(2) );} 282 | const MATRIX3 operator -(const MATRIX3 & m0) //sub overload 283 | { return MATRIX3( mat[0] - m0(0), mat[1] - m0(1), mat[2] - m0(2) );} 284 | */ 285 | const void operator +=(const MATRIX3 & m0) //+= overload 286 | { mat[0] += m0(0); mat[1] += m0(1); mat[2] += m0(2);} 287 | const void operator -=(const MATRIX3 & m0) //-= overload 288 | { mat[0] -= m0(0); mat[1] -= m0(1); mat[2] -= m0(2);} 289 | 290 | 291 | }; 292 | 293 | // 4d matrix 294 | class MATRIX4 { 295 | 296 | private : 297 | VECTOR4 mat[4]; // a vector represents each matrix row 298 | 299 | public : 300 | 301 | MATRIX4() // constructor 302 | { Identity(); }; 303 | MATRIX4(const VECTOR4 & v0, const VECTOR4 & v1, 304 | const VECTOR4 & v2, const VECTOR4 & v3) // constructor 305 | { mat[0] = v0; mat[1] = v1; mat[2] = v2; mat[3] = v3; }; 306 | int Dimension() const 307 | { return 4; }; 308 | VECTOR4 & operator [](int i) // index row i 309 | { return(mat[i]); }; 310 | // Note: reference row i, column j of MATRIX4 m0 as m0[i][j] (not m0[i,j]) 311 | VECTOR4 operator()(const int i) const // return row i 312 | { return(mat[i]); }; 313 | double operator ()(const int i, const int j) const 314 | { return(mat[i](j)); }; // return element (i,j) 315 | MATRIX4 & operator =(const MATRIX4 & m0) // copy matrix m0 316 | { mat[0] = m0(0); mat[1] = m0(1); mat[2] = m0(2); mat[3] = m0(3); 317 | return(*this); }; 318 | MATRIX4 & operator =(const MATRIX3 & m0) // copy matrix m0 319 | { mat[0] = m0(0); mat[1] = m0(1); mat[2] = m0(2); 320 | VECTOR4 temp(0.0,0.0,0.0,1.0); 321 | mat[3] = temp; 322 | return(*this); }; 323 | void Identity(); // set to identity 324 | }; 325 | 326 | 327 | //************************ 328 | // INT_64 operations 329 | //************************ 330 | 331 | inline INT_64 operator &(const INT_64 & v0, const INT_64 & v1) 332 | // return v0 & v1 333 | { return(INT_64(v0(0)&v1(0), v0(1)&v1(1))); }; 334 | 335 | inline INT_64 operator |(const INT_64 & v0, const INT_64 & v1) 336 | // return v0 | v1 337 | { return(INT_64(v0(0)|v1(0), v0(1)|v1(1))); }; 338 | 339 | inline INT_64 operator ~(const INT_64 & v0) 340 | // return ~v0 341 | { return(INT_64(~v0(0), ~v0(1))); }; 342 | 343 | 344 | //************************ 345 | // VECTOR2 operations 346 | //************************ 347 | inline double dot(const VECTOR2 & v0, const VECTOR2 & v1) 348 | // return dot product of v0 and v1 349 | { return(v0(0)*v1(0) + v0(1)*v1(1)); }; 350 | 351 | inline VECTOR2 operator +(const VECTOR2 & v0, const VECTOR2 & v1) 352 | // return v0 + v1 353 | { return(VECTOR2(v0(0) + v1(0), v0(1) + v1(1))); }; 354 | 355 | inline VECTOR2 operator -(const VECTOR2 & v0, const VECTOR2 & v1) 356 | // return v0 - v1 357 | { return(VECTOR2(v0(0) - v1(0), v0(1) - v1(1))); }; 358 | 359 | inline VECTOR2 operator *(double x0, const VECTOR2 & v0) 360 | // return x0*v0 361 | { return(VECTOR2(x0*v0(0), x0*v0(1))); }; 362 | 363 | inline VECTOR2 operator *(const VECTOR2 & v0, double x0) 364 | // return v0*x0 (= x0*v0) 365 | { return(x0*v0); }; 366 | inline double norm(const VECTOR2& v) 367 | { return sqrt(v(0)*v(0) + v(1)*v(1)); } 368 | 369 | inline double norm2(const VECTOR2& v) 370 | { return v(0)*v(0) + v(1)*v(1);} 371 | 372 | 373 | //************************ 374 | // VECTOR3 operations 375 | //************************ 376 | 377 | inline double dot(const VECTOR3 & v0, const VECTOR3 & v1) 378 | // return dot product of v0 and v1 379 | { return(v0(0)*v1(0) + v0(1)*v1(1) + v0(2)*v1(2)); }; 380 | 381 | inline VECTOR3 cross(const VECTOR3 & v0, const VECTOR3 & v1) 382 | // return cross product of v0 and v1 383 | { return(VECTOR3(v0(1)*v1(2) - v0(2)*v1(1), 384 | v0(2)*v1(0) - v0(0)*v1(2), 385 | v0(0)*v1(1) - v0(1)*v1(0))); }; 386 | 387 | inline VECTOR3 operator +(const VECTOR3 & v0, const VECTOR3 & v1) 388 | // return v0 + v1 389 | { return(VECTOR3(v0(0) + v1(0), v0(1) + v1(1), v0(2) + v1(2))); }; 390 | 391 | inline VECTOR3 operator -(const VECTOR3 & v0, const VECTOR3 & v1) 392 | // return v0 - v1 393 | { return(VECTOR3(v0(0) - v1(0), v0(1) - v1(1), v0(2) - v1(2))); }; 394 | 395 | inline VECTOR3 operator *(double x0, const VECTOR3 & v0) 396 | // return x0*v0 397 | { return(VECTOR3(x0*v0(0), x0*v0(1), x0*v0(2))); }; 398 | 399 | inline VECTOR3 operator *(const VECTOR3 & v0, double x0) 400 | // return v0*x0 (= x0*v0) 401 | { return(x0*v0); }; 402 | 403 | inline VECTOR3 operator /(const VECTOR3 & v0, double x0) 404 | // return v0*x0 (= x0*v0) 405 | { double x = 1.0 / x0; return VECTOR3( x * v0(0), x * v0(1), x * v0(2) ); }; 406 | 407 | 408 | inline double norm(const VECTOR3& v) 409 | { return sqrt(v(0)*v(0) + v(1)*v(1) + v(2)*v(2)); } 410 | 411 | inline double norm2(const VECTOR3& v) 412 | { return v(0)*v(0) + v(1)*v(1) + v(2)*v(2);} 413 | 414 | inline VECTOR4 get_vector4(VECTOR3 vec) 415 | { VECTOR4 temp(vec[0], vec[1], vec[2], 1.0); return temp;}; 416 | 417 | 418 | //************************ 419 | // VECTOR4 operations 420 | //************************ 421 | 422 | inline double dot(const VECTOR4 & v0, const VECTOR4 & v1) 423 | // return dot product of v0 and v1 424 | { return(v0(0)*v1(0) + v0(1)*v1(1) + v0(2)*v1(2) + v0(3)*v1(3)); }; 425 | 426 | inline VECTOR4 operator +(const VECTOR4 & v0, const VECTOR4 & v1) 427 | // return v0 + v1 428 | { return(VECTOR4(v0(0)+v1(0), v0(1)+v1(1), v0(2)+v1(2), v0(3)+v1(3))); }; 429 | 430 | inline VECTOR4 operator -(const VECTOR4 & v0, const VECTOR4 & v1) 431 | // return v0 - v1 432 | { return(VECTOR4(v0(0)-v1(0), v0(1)-v1(1), v0(2)-v1(2), v0(3)-v1(3))); }; 433 | 434 | inline VECTOR4 operator *(double x0, const VECTOR4 & v0) 435 | // return x0*v0 436 | { return(VECTOR4(x0*v0(0), x0*v0(1), x0*v0(2), x0*v0(3))); }; 437 | 438 | inline VECTOR4 operator *(const VECTOR4 & v0, double x0) 439 | // return v0*x0 (= x0*v0) 440 | { return(x0*v0); }; 441 | 442 | inline double norm(const VECTOR4& v) 443 | { return sqrt(v(0)*v(0) + v(1)*v(1) + v(2)*v(2) + v(3)*v(3)); } 444 | 445 | inline double norm2(const VECTOR4& v) 446 | { return v(0)*v(0) + v(1)*v(1) + v(2)*v(2) + v(3)*v(3);} 447 | 448 | //************************ 449 | // MATRIX3 operations 450 | //************************ 451 | 452 | MATRIX3 operator +(const MATRIX3 & m0, const MATRIX3 & m1); // return m0 + m1 453 | MATRIX3 operator -(const MATRIX3 & m0, const MATRIX3 & m1); // return m0 - m1 454 | MATRIX3 operator *(const MATRIX3 & m0, const MATRIX3 & m1); // return m0 * m1 455 | MATRIX3 operator *(const double x0, const MATRIX3 & m0); // return x0 * m0 456 | MATRIX3 operator *(const MATRIX3 & m0, const double x0); // return m0 * x0 457 | VECTOR3 operator *(const MATRIX3 & m0, const VECTOR3 & v0); // return m0 * v0 458 | VECTOR3 operator *(const VECTOR3 & v0, const MATRIX3 & m0); // return v0 * m0 459 | 460 | //************************ 461 | // MATRIX4 operations 462 | //************************ 463 | 464 | MATRIX4 operator +(const MATRIX4 & m0, const MATRIX4 & m1); // return m0 + m1 465 | MATRIX4 operator -(const MATRIX4 & m0, const MATRIX4 & m1); // return m0 - m1 466 | MATRIX4 operator *(const MATRIX4 & m0, const MATRIX4 & m1); // return m0 * m1 467 | MATRIX4 operator *(const double x0, const MATRIX4 & m0); // return x0 * m0 468 | MATRIX4 operator *(const MATRIX4 & m0, const double x0); // return m0 * x0 469 | VECTOR4 operator *(const MATRIX4 & m0, const VECTOR4 & v0); // return m0 * v0 470 | VECTOR4 operator *(const VECTOR4 & v0, const MATRIX4 & m0); // return v0 * m0 471 | VECTOR3 operator *(const MATRIX4 & m0, const VECTOR3 & v0); // return m0 * v0 472 | VECTOR3 operator *(const VECTOR3 & v0, const MATRIX4 & m0); // return v0 * m0 473 | 474 | 475 | MATRIX4 inverse(const MATRIX4 & m); // return inverse of m; return 0 matrix if 476 | // m is singular 477 | MATRIX4 rotate_matrix(int type, double angle); // type: 1:x, 2:y, 3:z 478 | MATRIX4 translate_matrix(double dx, double dy, double dz); 479 | MATRIX4 scale_matrix(double sx, double sy, double sz); 480 | 481 | //****************************** 482 | // output procedures, operators 483 | //****************************** 484 | 485 | ostream & operator<<(ostream & os, const VECTOR3 & v); // output vector 486 | ostream & operator<<(ostream & os, const VECTOR4 & v); // output vector 487 | void print_matrix(const MATRIX3 & mat, // print matrix 488 | const int indent = 0, 489 | const int cout_width = 6, const int precision = 1); 490 | void print_matrix(const MATRIX4 & mat, // print matrix 491 | const int indent = 0, 492 | const int cout_width = 6, const int precision = 1); 493 | 494 | #endif 495 | --------------------------------------------------------------------------------