504_NRosyDesign.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import igl
  2. from math import atan2,pi,cos,sin
  3. # Mesh
  4. V = igl.eigen.MatrixXd()
  5. F = igl.eigen.MatrixXi()
  6. # Constrained faces id
  7. b = igl.eigen.MatrixXi()
  8. # Constrained faces representative vector
  9. bc = igl.eigen.MatrixXd()
  10. # Degree of the N-RoSy field
  11. N = 4;
  12. # Converts a representative vector per face in the full set of vectors that describe
  13. # an N-RoSy field
  14. def representative_to_nrosy(V, F, R, N, Y):
  15. B1 = igl.eigen.MatrixXd()
  16. B2 = igl.eigen.MatrixXd()
  17. B3 = igl.eigen.MatrixXd()
  18. igl.local_basis(V,F,B1,B2,B3)
  19. Y.resize(F.rows()*N, 3)
  20. for i in range (0,F.rows()):
  21. x = R.row(i) * B1.row(i).transpose()
  22. y = R.row(i) * B2.row(i).transpose()
  23. angle = atan2(y[0],x[0])
  24. for j in range(0,N):
  25. anglej = angle + 2*pi*j/float(N)
  26. xj = cos(anglej)
  27. yj = sin(anglej)
  28. Y.setRow(i*N+j, xj * B1.row(i) + yj * B2.row(i))
  29. # Plots the mesh with an N-RoSy field and its singularities on top
  30. # The constrained faces (b) are colored in red.
  31. def plot_mesh_nrosy(viewer, V, F, N, PD1, S, b):
  32. # Clear the mesh
  33. viewer.data.clear()
  34. viewer.data.set_mesh(V,F)
  35. # Expand the representative vectors in the full vector set and plot them as lines
  36. avg = igl.avg_edge_length(V, F)
  37. Y = igl.eigen.MatrixXd()
  38. representative_to_nrosy(V, F, PD1, N, Y)
  39. B = igl.eigen.MatrixXd()
  40. igl.barycenter(V,F,B)
  41. Be = igl.eigen.MatrixXd(B.rows()*N,3)
  42. for i in range(0,B.rows()):
  43. for j in range(0,N):
  44. Be.setRow(i*N+j,B.row(i))
  45. viewer.data.add_edges(Be,Be+Y*(avg/2),igl.eigen.MatrixXd([[0,0,1]]))
  46. # Plot the singularities as colored dots (red for negative, blue for positive)
  47. for i in range(0,S.size()):
  48. if S[i] < -0.001:
  49. viewer.data.add_points(V.row(i),igl.eigen.MatrixXd([[1,0,0]]))
  50. elif S[i] > 0.001:
  51. viewer.data.add_points(V.row(i),igl.eigen.MatrixXd([[0,1,0]]));
  52. # Highlight in red the constrained faces
  53. C = igl.eigen.MatrixXd.Constant(F.rows(),3,1)
  54. for i in range(0,b.size()):
  55. C.setRow(b[i], igl.eigen.MatrixXd([[1, 0, 0]]))
  56. viewer.data.set_colors(C)
  57. # It allows to change the degree of the field when a number is pressed
  58. def key_down(viewer, key, modifier):
  59. global N
  60. if key >= ord('1') and key <= ord('9'):
  61. N = key - '0'
  62. R = igl.eigen.MatrixXd()
  63. S = igl.eigen.MatrixXd()
  64. igl.comiso.nrosy(V,F,b,bc,igl.eigen.MatrixXi(),igl.eigen.MatrixXd(),igl.eigen.MatrixXd(),N,0.5,R,S)
  65. plot_mesh_nrosy(viewer,V,F,N,R,S,b)
  66. return False
  67. # Load a mesh in OFF format
  68. igl.readOFF("../tutorial/shared/bumpy.off", V, F);
  69. # Threshold faces with high anisotropy
  70. b = igl.eigen.MatrixXi([[0]])
  71. bc = igl.eigen.MatrixXd([[1,1,1]])
  72. viewer = igl.viewer.Viewer()
  73. # Interpolate the field and plot
  74. key_down(viewer, '4', 0)
  75. # Plot the mesh
  76. viewer.data.set_mesh(V, F)
  77. viewer.callback_key_down = key_down
  78. # Disable wireframe
  79. viewer.core.show_lines = False
  80. # Launch the viewer
  81. viewer.launch()