304_LinearEqualityConstraints.py 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import sys, os
  2. # Add the igl library to the modules search path
  3. sys.path.insert(0, os.getcwd() + "/../")
  4. import pyigl as igl
  5. from shared import TUTORIAL_SHARED_PATH, check_dependencies
  6. dependencies = ["viewer"]
  7. check_dependencies(dependencies)
  8. V = igl.eigen.MatrixXd()
  9. F = igl.eigen.MatrixXi()
  10. igl.readOFF(TUTORIAL_SHARED_PATH + "cheburashka.off", V, F)
  11. # Two fixed points
  12. # Left hand, left foot
  13. b = igl.eigen.MatrixXi([[4331], [5957]])
  14. bc = igl.eigen.MatrixXd([[1], [-1]])
  15. # Construct Laplacian and mass matrix
  16. L = igl.eigen.SparseMatrixd()
  17. M = igl.eigen.SparseMatrixd()
  18. Minv = igl.eigen.SparseMatrixd()
  19. Q = igl.eigen.SparseMatrixd()
  20. igl.cotmatrix(V, F, L)
  21. igl.massmatrix(V, F, igl.MASSMATRIX_TYPE_VORONOI, M)
  22. igl.invert_diag(M, Minv)
  23. # Bi-Laplacian
  24. Q = L * (Minv * L)
  25. # Zero linear term
  26. B = igl.eigen.MatrixXd.Zero(V.rows(), 1)
  27. Z = igl.eigen.MatrixXd()
  28. Z_const = igl.eigen.MatrixXd()
  29. # Alternative, short hand
  30. mqwf = igl.min_quad_with_fixed_data()
  31. # Empty constraints
  32. Beq = igl.eigen.MatrixXd()
  33. Aeq = igl.eigen.SparseMatrixd()
  34. igl.min_quad_with_fixed_precompute(Q, b, Aeq, True, mqwf)
  35. igl.min_quad_with_fixed_solve(mqwf, B, bc, Beq, Z)
  36. # Constraint forcing difference of two points to be 0
  37. Aeq = igl.eigen.SparseMatrixd(1, V.rows())
  38. # Right hand, right foot
  39. Aeq.insert(0, 6074, 1)
  40. Aeq.insert(0, 6523, -1)
  41. Aeq.makeCompressed()
  42. Beq = igl.eigen.MatrixXd([[0]])
  43. igl.min_quad_with_fixed_precompute(Q, b, Aeq, True, mqwf)
  44. igl.min_quad_with_fixed_solve(mqwf, B, bc, Beq, Z_const)
  45. # Global definitions for viewer
  46. # Pseudo-color based on solution
  47. C = igl.eigen.MatrixXd()
  48. C_const = igl.eigen.MatrixXd()
  49. toggle = True
  50. # Use same color axes
  51. min_z = min(Z.minCoeff(), Z_const.minCoeff())
  52. max_z = max(Z.maxCoeff(), Z_const.maxCoeff())
  53. igl.jet(Z, min_z, max_z, C)
  54. igl.jet(Z_const, min_z, max_z, C_const)
  55. # Plot the mesh with pseudocolors
  56. viewer = igl.viewer.Viewer()
  57. viewer.data.set_mesh(V, F)
  58. viewer.core.show_lines = False
  59. viewer.data.set_colors(C)
  60. def key_down(viewer, key, mode):
  61. if key == ord(' '):
  62. global toggle, C, C_const
  63. if toggle:
  64. viewer.data.set_colors(C)
  65. else:
  66. viewer.data.set_colors(C_const)
  67. toggle = not toggle
  68. return True
  69. return False
  70. viewer.callback_key_down = key_down
  71. print("Press [space] to toggle between unconstrained and constrained.")
  72. viewer.launch()