304_LinearEqualityConstraints.py 2.7 KB

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