* adding streamline code and tutorial
* adding python bindings for streamline and python tutorial
Former-commit-id: 9abb24e0bc
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
import sys, os
|
||||
import numpy as np
|
||||
|
||||
# Add the igl library to the modules search path
|
||||
sys.path.insert(0, os.getcwd() + "/../")
|
||||
import pyigl as igl
|
||||
from shared import TUTORIAL_SHARED_PATH, check_dependencies
|
||||
|
||||
dependencies = ["viewer"]
|
||||
check_dependencies(dependencies)
|
||||
|
||||
# Input mesh
|
||||
V = igl.eigen.MatrixXd()
|
||||
F = igl.eigen.MatrixXi()
|
||||
|
||||
data = igl.StreamlineData()
|
||||
state = igl.StreamlineState()
|
||||
|
||||
treat_as_symmetric = True
|
||||
|
||||
# animation params
|
||||
anim_t = 0
|
||||
anim_t_dir = 1
|
||||
|
||||
|
||||
def representative_to_nrosy(V, F, R, N, Y):
|
||||
B1 = igl.eigen.MatrixXd()
|
||||
B2 = igl.eigen.MatrixXd()
|
||||
B3 = igl.eigen.MatrixXd()
|
||||
|
||||
igl.local_basis(V, F, B1, B2, B3)
|
||||
|
||||
Y.resize(F.rows(), 3 * N)
|
||||
for i in range(0, F.rows()):
|
||||
x = R.row(i) * B1.row(i).transpose()
|
||||
y = R.row(i) * B2.row(i).transpose()
|
||||
angle = np.arctan2(y, x)
|
||||
|
||||
for j in range(0, N):
|
||||
anglej = angle + np.pi * float(j) / float(N)
|
||||
xj = float(np.cos(anglej))
|
||||
yj = float(np.sin(anglej))
|
||||
Y.setBlock(i, j * 3, 1, 3, xj * B1.row(i) + yj * B2.row(i))
|
||||
|
||||
|
||||
def pre_draw(viewer):
|
||||
if not viewer.core.is_animating:
|
||||
return False
|
||||
|
||||
global anim_t
|
||||
global start_point
|
||||
global end_point
|
||||
|
||||
igl.streamlines_next(V, F, data, state)
|
||||
|
||||
value = (anim_t % 100) / 100.0
|
||||
|
||||
if value > 0.5:
|
||||
value = 1 - value
|
||||
value /= 0.5
|
||||
r, g, b = igl.parula(value)
|
||||
viewer.data.add_edges(state.start_point, state.end_point, igl.eigen.MatrixXd([[r, g, b]]))
|
||||
|
||||
anim_t += anim_t_dir
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def key_down(viewer, key, modifier):
|
||||
if key == ord(' '):
|
||||
viewer.core.is_animating = not viewer.core.is_animating
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
# Load a mesh in OFF format
|
||||
igl.readOFF(TUTORIAL_SHARED_PATH + "bumpy.off", V, F)
|
||||
|
||||
# Create a Vector Field
|
||||
temp_field = igl.eigen.MatrixXd()
|
||||
b = igl.eigen.MatrixXi([[0]])
|
||||
bc = igl.eigen.MatrixXd([[1, 1, 1]])
|
||||
S = igl.eigen.MatrixXd() # unused
|
||||
|
||||
degree = 3
|
||||
igl.comiso.nrosy(V, F, b, bc, igl.eigen.MatrixXi(), igl.eigen.MatrixXd(), igl.eigen.MatrixXd(), 1, 0.5, temp_field, S)
|
||||
temp_field2 = igl.eigen.MatrixXd()
|
||||
representative_to_nrosy(V, F, temp_field, degree, temp_field2)
|
||||
|
||||
# Initialize tracer
|
||||
igl.streamlines_init(V, F, temp_field2, treat_as_symmetric, data, state)
|
||||
|
||||
# Setup viewer
|
||||
viewer = igl.viewer.Viewer()
|
||||
viewer.data.set_mesh(V, F)
|
||||
viewer.callback_pre_draw = pre_draw
|
||||
viewer.callback_key_down = key_down
|
||||
|
||||
viewer.core.show_lines = False
|
||||
|
||||
viewer.core.is_animating = False
|
||||
viewer.core.animation_max_fps = 30.0
|
||||
|
||||
# Paint mesh grayish
|
||||
C = igl.eigen.MatrixXd()
|
||||
C.setConstant(viewer.data.V.rows(), 3, .9)
|
||||
viewer.data.set_colors(C)
|
||||
|
||||
# Draw vector field on sample points
|
||||
state0 = state.copy()
|
||||
|
||||
igl.streamlines_next(V, F, data, state0)
|
||||
v = state0.end_point - state0.start_point
|
||||
v = v.rowwiseNormalized()
|
||||
|
||||
viewer.data.add_edges(state0.start_point,
|
||||
state0.start_point + 0.059 * v,
|
||||
igl.eigen.MatrixXd([[1.0, 1.0, 1.0]]))
|
||||
|
||||
print("Press [space] to toggle animation")
|
||||
viewer.launch()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user