Skip to content

Commit 3d27b63

Browse files
committed
Update unit tests.
1 parent 632229f commit 3d27b63

1 file changed

Lines changed: 140 additions & 0 deletions

File tree

tests/test_all.py

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from re import I
12
import pytest
23
import numpy as np
34
# scipy sparse matrices
@@ -12,6 +13,10 @@
1213
import igl.copyleft.cgal
1314
import igl.embree
1415

16+
@pytest.fixture
17+
def icosahedron():
18+
V,F = igl.icosahedron()
19+
return V,F
1520

1621
#def rand_sparse(n,density):
1722
# n_features = n
@@ -600,3 +605,138 @@ def udf_sphere(Q):
600605
unique_ijk, J, unique_corners = igl.unique_sparse_voxel_corners(origin,h0,max_depth,ijk)
601606
unique_S = sdf_sphere(unique_corners)
602607
V,F = igl.marching_cubes(unique_S,unique_corners,J,0.0)
608+
609+
def test_rotate_vectors(icosahedron):
610+
V,F = icosahedron
611+
612+
# Create rotation angles (rotate by pi/4)
613+
A = np.ones(F.shape[0],dtype=np.float64) * (np.pi / 4.0)
614+
615+
# Get local basis
616+
B1,B2,_ = igl.local_basis(V,F)
617+
618+
# B1 is orthogonal to B2
619+
r = np.sum(B1* B2, axis=1)
620+
assert np.allclose(np.abs(r), 0.0)
621+
622+
# Rotate the first basis vector
623+
B1_rotated = igl.rotate_vectors(B1, A, B1, B2)
624+
625+
# Check output shape
626+
assert B1_rotated.shape == B1.shape
627+
628+
# Rotate B1_rotated by pi/4 again
629+
B1_rotated2 = igl.rotate_vectors(B1_rotated, A, B1, B2)
630+
assert B1_rotated2.shape == B1_rotated.shape
631+
632+
# B1_rotated2 should be parallel to B2
633+
r = np.sum(B1_rotated2 * B2, axis=1)
634+
assert np.allclose(np.abs(r), 1.0)
635+
636+
def test_compute_frame_field_bisectors(icosahedron):
637+
V,F = icosahedron
638+
639+
# Get local basis
640+
B1,B2,_ = igl.local_basis(V,F)
641+
642+
# Compute bisectors with explicit basis
643+
BIS1,BIS2 = igl.compute_frame_field_bisectors(V,F,B1,B2,B1,B2)
644+
645+
# Check output shapes
646+
assert BIS1.shape == (F.shape[0], 3)
647+
assert BIS2.shape == (F.shape[0], 3)
648+
649+
# BIS1 should be orthogonal to BIS2
650+
r = np.sum(BIS1 * BIS2, axis=1)
651+
assert np.allclose(np.abs(r), 0.0)
652+
653+
def test_comb_cross_field(icosahedron):
654+
V,F = icosahedron
655+
656+
# Get principal curvature directions (cross field)
657+
PD1,PD2,_,_,_ = igl.principal_curvature(V,F)
658+
659+
# Comb the cross field
660+
PD1_combed,PD2_combed = igl.comb_cross_field(V,F,PD1,PD2)
661+
662+
# Check output shapes
663+
assert PD1_combed.shape == (F.shape[0], 3)
664+
assert PD2_combed.shape == (F.shape[0], 3)
665+
666+
def test_cross_field_mismatch(icosahedron):
667+
V,F = icosahedron
668+
669+
# Get principal curvature directions (cross field)
670+
PD1,PD2,_,_,_ = igl.principal_curvature(V,F)
671+
672+
# Comb the cross field first
673+
PD1_combed,PD2_combed = igl.comb_cross_field(V,F,PD1,PD2)
674+
675+
# Compute mismatch on combed field
676+
mismatch = igl.cross_field_mismatch(V,F,PD1_combed,PD2_combed,True)
677+
678+
# Check output shape (should be #F by 3 for triangular mesh)
679+
assert mismatch.shape == (F.shape[0], 3)
680+
681+
# Test with uncombed field (function will comb it first)
682+
mismatch_uncombed = igl.cross_field_mismatch(V,F,PD1,PD2,False)
683+
assert mismatch_uncombed.shape == (F.shape[0], 3)
684+
685+
def test_find_cross_field_singularities(icosahedron):
686+
V,F = icosahedron
687+
688+
# Get principal curvature directions (cross field)
689+
PD1,PD2,_,_,_ = igl.principal_curvature(V,F)
690+
691+
# Comb the cross field
692+
PD1_combed,PD2_combed = igl.comb_cross_field(V,F,PD1,PD2)
693+
694+
# Compute mismatch
695+
mismatch = igl.cross_field_mismatch(V,F,PD1_combed,PD2_combed,True)
696+
697+
# Find singularities from mismatch
698+
isSingularity,singularityIndex = igl.find_cross_field_singularities(V,F,mismatch)
699+
700+
# Check Poincaré-Hopf theorem
701+
assert np.sum(singularityIndex) == 2 * 4 # Euler characteristic * 4-rosy fields
702+
703+
# Check output shapes
704+
assert isSingularity.shape[0] == V.shape[0]
705+
assert singularityIndex.shape[0] == V.shape[0]
706+
707+
# Test overload that computes mismatch internally
708+
isSingularity2,singularityIndex2 = igl.find_cross_field_singularities(V,F,PD1_combed,PD2_combed,True)
709+
710+
# Check Poincaré-Hopf theorem
711+
assert np.sum(singularityIndex2) == 2 * 4 # Euler characteristic * 4-rosy fields
712+
713+
# Check output shapes
714+
assert isSingularity2.shape[0] == V.shape[0]
715+
assert singularityIndex2.shape[0] == V.shape[0]
716+
717+
# Test with uncombed field
718+
isSingularity3,singularityIndex3 = igl.find_cross_field_singularities(V,F,PD1,PD2,False)
719+
assert isSingularity3.shape[0] == V.shape[0]
720+
assert singularityIndex3.shape[0] == V.shape[0]
721+
722+
# Check Poincaré-Hopf theorem
723+
assert np.sum(singularityIndex3) == 2 * 4 # Euler characteristic * 4-rosy fields
724+
725+
def test_comb_frame_field(icosahedron):
726+
V,F = icosahedron
727+
728+
# Get principal curvature directions (frame field)
729+
PD1,PD2,_,_,_ = igl.principal_curvature(V,F)
730+
731+
# Compute bisectors
732+
BIS1,BIS2 = igl.compute_frame_field_bisectors(V,F,PD1,PD2)
733+
734+
# Comb the bisectors (which are a cross field)
735+
BIS1_combed,BIS2_combed = igl.comb_cross_field(V,F,BIS1,BIS2)
736+
737+
# Comb the frame field using combed bisectors
738+
PD1_combed,PD2_combed = igl.comb_frame_field(V,F,PD1,PD2,BIS1_combed,BIS2_combed)
739+
740+
# Check output shapes
741+
assert PD1_combed.shape == (F.shape[0], 3)
742+
assert PD2_combed.shape == (F.shape[0], 3)

0 commit comments

Comments
 (0)