1
1
"""
2
2
Visualization toolkit in pyomeca
3
3
"""
4
+ from dataclasses import dataclass
4
5
import os
5
6
import time
6
7
import sys
@@ -198,13 +199,25 @@ def record(self, finish=False, button_to_block=(), file_name=None):
198
199
self .setMaximumSize (self .maximum_size )
199
200
200
201
202
+ @dataclass
203
+ class _MarkerInternal :
204
+ data : Markers
205
+ size : float
206
+ color : tuple [float , float , float ]
207
+ opacity : float
208
+ actors : list [QVTKRenderWindowInteractor , ...]
209
+
210
+
201
211
class VtkModel (QtWidgets .QWidget ):
202
212
def __init__ (
203
213
self ,
204
214
parent ,
205
215
markers_size = 0.010 ,
206
216
markers_color = (1 , 1 , 1 ),
207
217
markers_opacity = 1.0 ,
218
+ experimental_markers_size = 0.010 ,
219
+ experimental_markers_color = (1 , 1 , 1 ),
220
+ experimental_markers_opacity = 1.0 ,
208
221
contacts_color = (0 , 1 , 0 ),
209
222
contacts_size = 0.01 ,
210
223
contacts_opacity = 1.0 ,
@@ -258,11 +271,19 @@ def __init__(
258
271
self .setAutoFillBackground (True )
259
272
self .setPalette (palette )
260
273
261
- self .markers = Markers ()
262
- self .markers_size = markers_size
263
- self .markers_color = markers_color
264
- self .markers_opacity = markers_opacity
265
- self .markers_actors = list ()
274
+ self .markers = {
275
+ "model" : _MarkerInternal (
276
+ data = Markers (), color = markers_color , size = markers_size , opacity = markers_opacity , actors = list ()
277
+ ),
278
+ "experimental" : _MarkerInternal (
279
+ data = Markers (),
280
+ color = experimental_markers_color ,
281
+ size = experimental_markers_size ,
282
+ opacity = experimental_markers_opacity ,
283
+ actors = list (),
284
+ ),
285
+ }
286
+ self .markers_link_actors : list [QVTKRenderWindowInteractor , ...] = list ()
266
287
267
288
self .contacts = Markers ()
268
289
self .contacts_size = contacts_size
@@ -343,21 +364,53 @@ def set_markers_color(self, markers_color):
343
364
markers_color : tuple(int)
344
365
Color the markers should be drawn (1 is max brightness)
345
366
"""
346
- self .markers_color = markers_color
347
- self .update_markers (self .markers )
367
+ self ._set_markers_color (markers_color , key = "model" )
368
+
369
+ def set_experimental_markers_color (self , markers_color ):
370
+ """
371
+ Dynamically change the color of the markers
372
+ Parameters
373
+ ----------
374
+ markers_color : tuple(int)
375
+ Color the markers should be drawn (1 is max brightness)
376
+ """
377
+ self ._set_markers_color (markers_color , key = "experimental" )
378
+
379
+ def _set_markers_color (self , markers_color , key ):
380
+ """
381
+ Dynamically change the color of the markers
382
+ Parameters
383
+ ----------
384
+ markers_color : tuple(int)
385
+ Color the markers should be drawn (1 is max brightness)
386
+ """
387
+ self .markers_color [key ] = markers_color
388
+ self ._update_markers (self .markers , key )
348
389
349
390
def set_markers_size (self , markers_size ):
391
+ self ._set_markers_size (markers_size , "model" )
392
+
393
+ def set_experimental_markers_size (self , markers_size ):
394
+ self ._set_markers_size (markers_size , "experimental" )
395
+
396
+ def _set_markers_size (self , markers_size , key ):
350
397
"""
351
398
Dynamically change the size of the markers
352
399
Parameters
353
400
----------
354
401
markers_size : float
355
402
Size the markers should be drawn
356
403
"""
357
- self .markers_size = markers_size
358
- self .update_markers (self .markers )
404
+ self .markers_size [ key ] = markers_size
405
+ self ._update_markers (self .markers , key )
359
406
360
407
def set_markers_opacity (self , markers_opacity ):
408
+ self ._set_markers_opacity (markers_opacity , "model" )
409
+
410
+ def set_experimental_markers_opacity (self , markers_opacity ):
411
+ self ._set_markers_opacity (markers_opacity , "experimental" )
412
+
413
+ def _set_markers_opacity (self , markers_opacity , key ):
361
414
"""
362
415
Dynamically change the opacity of the markers
363
416
Parameters
@@ -368,10 +421,10 @@ def set_markers_opacity(self, markers_opacity):
368
421
-------
369
422
370
423
"""
371
- self .markers_opacity = markers_opacity
372
- self .update_markers (self .markers )
424
+ self .markers_opacity [ key ] = markers_opacity
425
+ self ._update_markers (self .markers , key )
373
426
374
- def new_marker_set (self , markers ):
427
+ def _new_marker_set (self , markers , key ):
375
428
"""
376
429
Define a new marker set. This function must be called each time the number of markers change
377
430
Parameters
@@ -382,28 +435,52 @@ def new_marker_set(self, markers):
382
435
"""
383
436
if len (markers .shape ) > 2 and markers .shape [2 ] > 1 :
384
437
raise IndexError ("Markers should be from one frame only" )
385
- self .markers = markers
438
+ self .markers [ key ]. data = markers
386
439
387
440
# Remove previous actors from the scene
388
- for actor in self .markers_actors :
441
+ for actor in self .markers [ key ]. actors :
389
442
self .parent_window .ren .RemoveActor (actor )
390
- self .markers_actors = list ()
443
+ self .markers [ key ]. actors = list ()
391
444
392
445
# Create the geometry of a point (the coordinate) points = vtk.vtkPoints()
393
446
for i in range (markers .channel .size ):
394
447
# Create a mapper
395
448
mapper = vtkPolyDataMapper ()
396
449
397
450
# Create an actor
398
- self .markers_actors .append (vtkActor ())
399
- self .markers_actors [i ].SetMapper (mapper )
451
+ self .markers [ key ]. actors .append (vtkActor ())
452
+ self .markers [ key ]. actors [i ].SetMapper (mapper )
400
453
401
- self .parent_window .ren .AddActor (self .markers_actors [i ])
454
+ self .parent_window .ren .AddActor (self .markers [ key ]. actors [i ])
402
455
403
456
# Update marker position
404
- self .update_markers (self .markers )
457
+ self ._update_markers (self .markers [ key ]. data , key )
405
458
406
459
def update_markers (self , markers ):
460
+ self ._update_markers (markers , "model" )
461
+
462
+ def update_experimental_markers (
463
+ self , markers , with_link : bool = True , virtual_to_experimental_markers_indices : list [int , ...] = None
464
+ ):
465
+ """
466
+ Update position of the experimental markers on the screen (but do not repaint)
467
+ Parameters
468
+ ----------
469
+ markers : Markers3d
470
+ One frame of markers
471
+ with_link : bool
472
+ If links to the virtual markers should be added (implies that coll to update_markers was done prior
473
+ virtual_to_experimental_markers_indices : list[int, ...]
474
+ A list that links the virtual markers indices to the experimental marker indices. If left None,
475
+ it is assumed to be a one to one (0=>0, 1=>1, ..., n_virtual_markers=>n_experimental_markers)
476
+ """
477
+ self ._update_markers (markers , "experimental" )
478
+ if with_link :
479
+ if virtual_to_experimental_markers_indices is None :
480
+ virtual_to_experimental_markers_indices = tuple (range (self .markers ["model" ].data .channel .size ))
481
+ self ._update_experimental_marker_link (virtual_to_experimental_markers_indices )
482
+
483
+ def _update_markers (self , markers , key ):
407
484
"""
408
485
Update position of the markers on the screen (but do not repaint)
409
486
Parameters
@@ -415,22 +492,90 @@ def update_markers(self, markers):
415
492
416
493
if len (markers .shape ) > 2 and markers .shape [2 ] > 1 :
417
494
raise IndexError ("Markers should be from one frame only" )
418
- if markers .channel .size != self .markers .channel .size :
419
- self .new_marker_set (markers )
495
+ if markers .channel .size != self .markers [ key ]. data .channel .size :
496
+ self ._new_marker_set (markers , key )
420
497
return # Prevent calling update_markers recursively
421
- self .markers = markers
498
+ self .markers [ key ]. data = markers
422
499
markers = np .array (markers )
423
500
424
- for i , actor in enumerate (self .markers_actors ):
501
+ for i , actor in enumerate (self .markers [ key ]. actors ):
425
502
# mapper = actors.GetNextActor().GetMapper()
426
503
mapper = actor .GetMapper ()
427
- self .markers_actors [ i ].GetProperty ().SetColor (self .markers_color )
428
- self .markers_actors [ i ].GetProperty ().SetOpacity (self .markers_opacity )
504
+ self .markers [ key ]. actors [ i ].GetProperty ().SetColor (self .markers [ key ]. color )
505
+ self .markers [ key ]. actors [ i ].GetProperty ().SetOpacity (self .markers [ key ]. opacity )
429
506
source = vtkSphereSource ()
430
507
source .SetCenter (markers [0 :3 , i ])
431
- source .SetRadius (self .markers_size )
508
+ source .SetRadius (self .markers [ key ]. size )
432
509
mapper .SetInputConnection (source .GetOutputPort ())
433
510
511
+ def _new_experimental_marker_link (self , virtual_to_experimental_markers_indices ):
512
+ """
513
+ Define a new marker link. This function must be called each time the number of markers change
514
+ Parameters
515
+ """
516
+
517
+ # Remove previous actors from the scene
518
+ for actor in self .markers_link_actors :
519
+ self .parent_window .ren .RemoveActor (actor )
520
+ self .markers_link_actors = list ()
521
+
522
+ cells = vtkCellArray ()
523
+ for i , j in enumerate (virtual_to_experimental_markers_indices ):
524
+ if j is None :
525
+ continue
526
+ points = vtkPoints ()
527
+ points .InsertNextPoint (self .markers ["model" ].data [:3 , j , 0 ].data )
528
+ points .InsertNextPoint (self .markers ["experimental" ].data [:3 , i , 0 ].data )
529
+
530
+ # Create the polygons
531
+ poly = vtkPolyLine ()
532
+ poly .GetPointIds ().SetNumberOfIds (2 ) # make a line
533
+ poly .GetPointIds ().SetId (0 , 0 )
534
+ poly .GetPointIds ().SetId (1 , 1 )
535
+ cells .InsertNextCell (poly )
536
+
537
+ poly_data = vtkPolyData ()
538
+ poly_data .SetPoints (points )
539
+ poly_data .SetLines (cells )
540
+
541
+ # Create a mapper
542
+ mapper = vtkPolyDataMapper ()
543
+ mapper .SetInputData (poly_data )
544
+
545
+ # Create an actor
546
+ self .markers_link_actors .append (vtkActor ())
547
+ self .markers_link_actors [- 1 ].SetMapper (mapper )
548
+ self .markers_link_actors [- 1 ].GetProperty ().SetColor ((1 , 0 , 0 ))
549
+
550
+ self .parent_window .ren .AddActor (self .markers_link_actors [- 1 ])
551
+
552
+ # Update marker position
553
+ self ._update_experimental_marker_link (virtual_to_experimental_markers_indices )
554
+
555
+ def _update_experimental_marker_link (self , virtual_to_experimental_markers_indices ):
556
+ """
557
+ Update position of the line between experimental markers and virtual markers on the screen (but do not repaint)
558
+ Parameters
559
+ """
560
+
561
+ if len (self .markers_link_actors ) != len (
562
+ tuple (i for i in virtual_to_experimental_markers_indices if i is not None )
563
+ ):
564
+ self ._new_experimental_marker_link (virtual_to_experimental_markers_indices )
565
+ return # Prevent calling update_markers recursively
566
+
567
+ cmp = 0
568
+ for i , j in enumerate (virtual_to_experimental_markers_indices ):
569
+ if j is None :
570
+ continue
571
+ points = vtkPoints ()
572
+ points .InsertNextPoint (self .markers ["model" ].data [:3 , j , 0 ].data )
573
+ points .InsertNextPoint (self .markers ["experimental" ].data [:3 , i , 0 ].data )
574
+
575
+ poly_line = self .markers_link_actors [cmp ].GetMapper ().GetInput ()
576
+ poly_line .SetPoints (points )
577
+ cmp += 1
578
+
434
579
def set_contacts_color (self , contacts_color ):
435
580
"""
436
581
Dynamically change the color of the contacts
0 commit comments