709_VectorFieldVisualizer.py 3.5 KB

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