504_NRosyDesign.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #!/usr/bin/env python
  2. #
  3. # This file is part of libigl, a simple c++ geometry processing library.
  4. #
  5. # Copyright (C) 2017 Sebastian Koch <s.koch@tu-berlin.de> and Daniele Panozzo <daniele.panozzo@gmail.com>
  6. #
  7. # This Source Code Form is subject to the terms of the Mozilla Public License
  8. # v. 2.0. If a copy of the MPL was not distributed with this file, You can
  9. # obtain one at http://mozilla.org/MPL/2.0/.
  10. import sys, os
  11. from math import atan2, pi, cos, sin
  12. # Add the igl library to the modules search path
  13. sys.path.insert(0, os.getcwd() + "/../")
  14. import pyigl as igl
  15. from shared import TUTORIAL_SHARED_PATH, check_dependencies
  16. dependencies = ["comiso", "glfw"]
  17. check_dependencies(dependencies)
  18. # Mesh
  19. V = igl.eigen.MatrixXd()
  20. F = igl.eigen.MatrixXi()
  21. # Constrained faces id
  22. b = igl.eigen.MatrixXi()
  23. # Constrained faces representative vector
  24. bc = igl.eigen.MatrixXd()
  25. # Degree of the N-RoSy field
  26. N = 4
  27. # Converts a representative vector per face in the full set of vectors that describe
  28. # an N-RoSy field
  29. def representative_to_nrosy(V, F, R, N, Y):
  30. B1 = igl.eigen.MatrixXd()
  31. B2 = igl.eigen.MatrixXd()
  32. B3 = igl.eigen.MatrixXd()
  33. igl.local_basis(V, F, B1, B2, B3)
  34. Y.resize(F.rows() * N, 3)
  35. for i in range(0, F.rows()):
  36. x = R.row(i) * B1.row(i).transpose()
  37. y = R.row(i) * B2.row(i).transpose()
  38. angle = atan2(y[0], x[0])
  39. for j in range(0, N):
  40. anglej = angle + 2 * pi * j / float(N)
  41. xj = cos(anglej)
  42. yj = sin(anglej)
  43. Y.setRow(i * N + j, xj * B1.row(i) + yj * B2.row(i))
  44. # Plots the mesh with an N-RoSy field and its singularities on top
  45. # The constrained faces (b) are colored in red.
  46. def plot_mesh_nrosy(viewer, V, F, N, PD1, S, b):
  47. # Clear the mesh
  48. viewer.data().clear()
  49. viewer.data().set_mesh(V, F)
  50. # Expand the representative vectors in the full vector set and plot them as lines
  51. avg = igl.avg_edge_length(V, F)
  52. Y = igl.eigen.MatrixXd()
  53. representative_to_nrosy(V, F, PD1, N, Y)
  54. B = igl.eigen.MatrixXd()
  55. igl.barycenter(V, F, B)
  56. Be = igl.eigen.MatrixXd(B.rows() * N, 3)
  57. for i in range(0, B.rows()):
  58. for j in range(0, N):
  59. Be.setRow(i * N + j, B.row(i))
  60. viewer.data().add_edges(Be, Be + Y * (avg / 2), igl.eigen.MatrixXd([[0, 0, 1]]))
  61. # Plot the singularities as colored dots (red for negative, blue for positive)
  62. for i in range(0, S.size()):
  63. if S[i] < -0.001:
  64. viewer.data().add_points(V.row(i), igl.eigen.MatrixXd([[1, 0, 0]]))
  65. elif S[i] > 0.001:
  66. viewer.data().add_points(V.row(i), igl.eigen.MatrixXd([[0, 1, 0]]));
  67. # Highlight in red the constrained faces
  68. C = igl.eigen.MatrixXd.Constant(F.rows(), 3, 1)
  69. for i in range(0, b.size()):
  70. C.setRow(b[i], igl.eigen.MatrixXd([[1, 0, 0]]))
  71. viewer.data().set_colors(C)
  72. # It allows to change the degree of the field when a number is pressed
  73. def key_down(viewer, key, modifier):
  74. global N
  75. if ord('1') <= key <= ord('9'):
  76. N = key - ord('0')
  77. R = igl.eigen.MatrixXd()
  78. S = igl.eigen.MatrixXd()
  79. igl.comiso.nrosy(V, F, b, bc, igl.eigen.MatrixXi(), igl.eigen.MatrixXd(), igl.eigen.MatrixXd(), N, 0.5, R, S)
  80. plot_mesh_nrosy(viewer, V, F, N, R, S, b)
  81. return False
  82. # Load a mesh in OFF format
  83. igl.readOFF(TUTORIAL_SHARED_PATH + "bumpy.off", V, F)
  84. # Threshold faces with high anisotropy
  85. b = igl.eigen.MatrixXd([[0]]).castint()
  86. bc = igl.eigen.MatrixXd([[1, 1, 1]])
  87. viewer = igl.glfw.Viewer()
  88. # Interpolate the field and plot
  89. key_down(viewer, ord('4'), 0)
  90. # Plot the mesh
  91. viewer.data().set_mesh(V, F)
  92. viewer.callback_key_down = key_down
  93. # Disable wireframe
  94. viewer.data().show_lines = False
  95. # Launch the viewer
  96. viewer.launch()