709_VectorFieldVisualizer.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import sys, os
  2. import numpy as np
  3. # Add the igl library to the modules search path
  4. sys.path.insert(0, os.getcwd() + "/../")
  5. import pyigl as igl
  6. from shared import TUTORIAL_SHARED_PATH, check_dependencies
  7. dependencies = ["viewer"]
  8. check_dependencies(dependencies)
  9. # Input mesh
  10. V = igl.eigen.MatrixXd()
  11. F = igl.eigen.MatrixXi()
  12. data = igl.StreamlineData()
  13. state = igl.StreamlineState()
  14. treat_as_symmetric = True
  15. # animation params
  16. anim_t = 0
  17. anim_t_dir = 1
  18. def representative_to_nrosy(V, F, R, N, Y):
  19. B1 = igl.eigen.MatrixXd()
  20. B2 = igl.eigen.MatrixXd()
  21. B3 = igl.eigen.MatrixXd()
  22. igl.local_basis(V, F, B1, B2, B3)
  23. Y.resize(F.rows(), 3 * N)
  24. for i in range(0, F.rows()):
  25. x = R.row(i) * B1.row(i).transpose()
  26. y = R.row(i) * B2.row(i).transpose()
  27. angle = np.arctan2(y, x)
  28. for j in range(0, N):
  29. anglej = angle + np.pi * float(j) / float(N)
  30. xj = float(np.cos(anglej))
  31. yj = float(np.sin(anglej))
  32. Y.setBlock(i, j * 3, 1, 3, xj * B1.row(i) + yj * B2.row(i))
  33. def pre_draw(viewer):
  34. if not viewer.core.is_animating:
  35. return False
  36. global anim_t
  37. global start_point
  38. global end_point
  39. igl.streamlines_next(V, F, data, state)
  40. value = (anim_t % 100) / 100.0
  41. if value > 0.5:
  42. value = 1 - value
  43. value /= 0.5
  44. r, g, b = igl.parula(value)
  45. viewer.data.add_edges(state.start_point, state.end_point, igl.eigen.MatrixXd([[r, g, b]]))
  46. anim_t += anim_t_dir
  47. return False
  48. def key_down(viewer, key, modifier):
  49. if key == ord(' '):
  50. viewer.core.is_animating = not viewer.core.is_animating
  51. return True
  52. return False
  53. def main():
  54. # Load a mesh in OFF format
  55. igl.readOFF(TUTORIAL_SHARED_PATH + "bumpy.off", V, F)
  56. # Create a Vector Field
  57. temp_field = igl.eigen.MatrixXd()
  58. b = igl.eigen.MatrixXi([[0]])
  59. bc = igl.eigen.MatrixXd([[1, 1, 1]])
  60. S = igl.eigen.MatrixXd() # unused
  61. degree = 3
  62. igl.comiso.nrosy(V, F, b, bc, igl.eigen.MatrixXi(), igl.eigen.MatrixXd(), igl.eigen.MatrixXd(), 1, 0.5, temp_field, S)
  63. temp_field2 = igl.eigen.MatrixXd()
  64. representative_to_nrosy(V, F, temp_field, degree, temp_field2)
  65. # Initialize tracer
  66. igl.streamlines_init(V, F, temp_field2, treat_as_symmetric, data, state)
  67. # Setup viewer
  68. viewer = igl.viewer.Viewer()
  69. viewer.data.set_mesh(V, F)
  70. viewer.callback_pre_draw = pre_draw
  71. viewer.callback_key_down = key_down
  72. viewer.core.show_lines = False
  73. viewer.core.is_animating = False
  74. viewer.core.animation_max_fps = 30.0
  75. # Paint mesh grayish
  76. C = igl.eigen.MatrixXd()
  77. C.setConstant(viewer.data.V.rows(), 3, .9)
  78. viewer.data.set_colors(C)
  79. # Draw vector field on sample points
  80. state0 = state.copy()
  81. igl.streamlines_next(V, F, data, state0)
  82. v = state0.end_point - state0.start_point
  83. v = v.rowwiseNormalized()
  84. viewer.data.add_edges(state0.start_point,
  85. state0.start_point + 0.059 * v,
  86. igl.eigen.MatrixXd([[1.0, 1.0, 1.0]]))
  87. print("Press [space] to toggle animation")
  88. viewer.launch()
  89. if __name__ == "__main__":
  90. main()