File: instanced_mesh_picking.py

package info (click to toggle)
python-vispy 0.15.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 8,868 kB
  • sloc: python: 59,799; javascript: 6,800; makefile: 69; sh: 6
file content (96 lines) | stat: -rw-r--r-- 3,013 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# -*- coding: utf-8 -*-
# vispy: gallery 30
# -----------------------------------------------------------------------------
# Copyright (c) Vispy Development Team. All Rights Reserved.
# Distributed under the (new) BSD License. See LICENSE.txt for more info.
# -----------------------------------------------------------------------------
"""
Picking Instance of InstancedMeshes
===================================

Demonstrates how to identify (pick) individual instanced meshes.

"""

import numpy as np

from vispy import app, scene, use
from vispy.io import read_mesh, load_data_file
from vispy.scene.visuals import InstancedMesh
from vispy.scene import transforms
from scipy.spatial.transform import Rotation

#Necessary to use InstancedMesh
use(gl='gl+')

canvas = scene.SceneCanvas(keys='interactive', bgcolor='white')
view = canvas.central_widget.add_view()

view.camera = 'turntable'
view.camera.depth_value = 1e3

#Load an mesh file
mesh_path = load_data_file('spot/spot.obj.gz')

n_instances = 8
vertices, faces, normals, texcoords = read_mesh(mesh_path)
instance_colors = np.random.rand(n_instances, 3).astype(np.float32)
instance_positions = [[0,2,0], [2,0,0], [6,0,0], [3,4,1], [5,3,2], [6,2,1], [8,4,6], [1,2,6]]
instance_transforms = Rotation.identity(n_instances).as_matrix().astype(np.float32)

# Create a colored `MeshVisual`.
mesh = InstancedMesh(
    vertices,
    faces,
    instance_colors=instance_colors,
    instance_positions=instance_positions,
    instance_transforms=instance_transforms,
    parent=view.scene,
)

scene.visuals.XYZAxis(parent=view.scene)
mesh.interactive = True

@canvas.events.mouse_press.connect
def on_mouse_press(event):
    clicked_mesh = canvas.visual_at(event.pos)
    if isinstance(clicked_mesh, InstancedMesh):
        pos1, min, min_pos = get_view_axis_in_scene_coordinates(
            event.pos, clicked_mesh
        )
        instance_pos = clicked_mesh.instance_positions[min_pos]
        print(f"visual at : {clicked_mesh}")
        print(f"event.pos : {event.pos}")
        print(f"min distance : {min} and min_pos : {instance_pos}")
       


def get_view_axis_in_scene_coordinates(pos, mesh):
    event_pos = np.array([pos[0], pos[1], 0, 1])  
    instances_on_canvas = []
    # Translate each position to corresponding 2d canvas coordinates
    for instance in mesh.instance_positions:
        on_canvas = mesh.get_transform(map_from="visual", map_to="canvas").map(instance)
        on_canvas /= on_canvas[3:]
        instances_on_canvas.append(on_canvas)

    min = 10000
    min_pos = None
    # Find the closest position to the clicked position
    for i, instance_pos in enumerate(instances_on_canvas):
        # Not minding z axis
        temp_min = np.linalg.norm(
            np.array(event_pos[:2]) - np.array(instance_pos[:2])
        )
        if temp_min < min:
            min = temp_min
            min_pos = i

    return instances_on_canvas, min, min_pos

canvas.show()


if __name__ == "__main__":
    print(__doc__)
    app.run()