@@ -74,6 +74,7 @@ class Cartesian(Widget):
74
74
:param int nudge_y: movement in pixels in the y direction to move the origin.
75
75
Defaults to 0
76
76
77
+ :param bool verbose: print debugging information in some internal functions. Default to False
77
78
78
79
**Quickstart: Importing and using Cartesian**
79
80
@@ -181,11 +182,14 @@ def __init__(
181
182
subticks : bool = False ,
182
183
nudge_x : int = 0 ,
183
184
nudge_y : int = 0 ,
185
+ verbose : bool = False ,
184
186
** kwargs ,
185
187
) -> None :
186
188
187
189
super ().__init__ (** kwargs )
188
190
191
+ self ._verbose = verbose
192
+
189
193
self ._background_color = background_color
190
194
191
195
self ._axes_line_color = axes_color
@@ -250,8 +254,8 @@ def __init__(
250
254
self ._axesy_bitmap = displayio .Bitmap (self ._axesy_width , self .height , 4 )
251
255
self ._axesy_bitmap .fill (0 )
252
256
253
- self ._screen_bitmap = displayio .Bitmap (self .width , self .height , 5 )
254
- self ._screen_bitmap . fill ( 5 )
257
+ self ._plot_bitmap = displayio .Bitmap (self .width , self .height , 5 )
258
+ self .clear_plot_lines ( )
255
259
self ._screen_palette = displayio .Palette (6 )
256
260
self ._screen_palette .make_transparent (0 )
257
261
self ._screen_palette [1 ] = self ._tick_color
@@ -293,7 +297,7 @@ def __init__(
293
297
)
294
298
295
299
self ._screen_tilegrid = displayio .TileGrid (
296
- self ._screen_bitmap ,
300
+ self ._plot_bitmap ,
297
301
pixel_shader = self ._screen_palette ,
298
302
x = 0 ,
299
303
y = 0 ,
@@ -310,8 +314,6 @@ def __init__(
310
314
self .append (self ._screen_tilegrid )
311
315
self .append (self ._corner_tilegrid )
312
316
313
- self ._update_line = True
314
-
315
317
self ._pointer = None
316
318
self ._circle_palette = None
317
319
self .plot_line_point = None
@@ -389,10 +391,12 @@ def _draw_ticks(self) -> None:
389
391
390
392
if self ._subticks :
391
393
if i in subticks :
394
+ # calc subtick_line_height; force min lineheigt to 1.
395
+ subtick_line_height = max (1 , self ._tick_line_height // 2 )
392
396
rectangle_helper (
393
397
text_dist ,
394
398
self ._axes_line_thickness ,
395
- self . _tick_line_height // 2 ,
399
+ subtick_line_height ,
396
400
1 ,
397
401
self ._axesx_bitmap ,
398
402
1 ,
@@ -457,6 +461,130 @@ def _draw_pointers(self, x: int, y: int) -> None:
457
461
458
462
self .append (self ._pointer )
459
463
464
+ def _calc_local_xy (self , x : int , y : int ) -> (int , int ):
465
+ local_x = (
466
+ int ((x - self ._xrange [0 ]) * self ._factorx * self ._valuex ) + self ._nudge_x
467
+ )
468
+ # details on `+ (self.height - 1)` :
469
+ # the bitmap is set to self.width & self.height
470
+ # but we are only allowed to draw to pixels 0..height-1 and 0..width-1
471
+ local_y = (
472
+ int ((self ._yrange [0 ] - y ) * self ._factory * self ._valuey )
473
+ + (self .height - 1 )
474
+ + self ._nudge_y
475
+ )
476
+ return (local_x , local_y )
477
+
478
+ def _check_local_x_in_range (self , local_x ):
479
+ return 0 <= local_x < self .width
480
+
481
+ def _check_local_y_in_range (self , local_y ):
482
+ return 0 <= local_y < self .height
483
+
484
+ def _check_local_xy_in_range (self , local_x , local_y ):
485
+ return self ._check_local_x_in_range (local_x ) and self ._check_local_y_in_range (
486
+ local_y
487
+ )
488
+
489
+ def _check_x_in_range (self , x ):
490
+ return self ._xrange [0 ] <= x <= self ._xrange [1 ]
491
+
492
+ def _check_y_in_range (self , y ):
493
+ return self ._yrange [0 ] <= y <= self ._yrange [1 ]
494
+
495
+ def _check_xy_in_range (self , x , y ):
496
+ return self ._check_x_in_range (x ) and self ._check_y_in_range (y )
497
+
498
+ def _add_point (self , x : int , y : int ) -> None :
499
+ """_add_point function
500
+ helper function to add a point to the graph in the plane
501
+ :param int x: ``x`` coordinate in the local plane
502
+ :param int y: ``y`` coordinate in the local plane
503
+ :return: None
504
+ rtype: None
505
+ """
506
+ local_x , local_y = self ._calc_local_xy (x , y )
507
+ if self ._verbose :
508
+ print ("" )
509
+ print (
510
+ "xy: ({: >4}, {: >4}) "
511
+ "_xrange: ({: >4}, {: >4}) "
512
+ "_yrange: ({: >4}, {: >4}) "
513
+ "" .format (
514
+ x ,
515
+ y ,
516
+ self ._xrange [0 ],
517
+ self ._xrange [1 ],
518
+ self ._yrange [0 ],
519
+ self ._yrange [1 ],
520
+ )
521
+ )
522
+ print (
523
+ "local_*: ({: >4}, {: >4}) "
524
+ " width: ({: >4}, {: >4}) "
525
+ " height: ({: >4}, {: >4}) "
526
+ "" .format (
527
+ local_x ,
528
+ local_y ,
529
+ 0 ,
530
+ self .width ,
531
+ 0 ,
532
+ self .height ,
533
+ )
534
+ )
535
+ if self ._check_xy_in_range (x , y ):
536
+ if self ._check_local_xy_in_range (local_x , local_y ):
537
+ if self .plot_line_point is None :
538
+ self .plot_line_point = []
539
+ self .plot_line_point .append ((local_x , local_y ))
540
+ else :
541
+ # for better error messages we check in detail what failed...
542
+ # this should never happen:
543
+ # we already checked the range of the input values.
544
+ # but in case our calculation is wrong we handle this case to..
545
+ if not self ._check_local_x_in_range (local_x ):
546
+ raise ValueError (
547
+ "local_x out of range: "
548
+ "local_x:{: >4}; _xrange({: >4}, {: >4})"
549
+ "" .format (
550
+ local_x ,
551
+ 0 ,
552
+ self .width ,
553
+ )
554
+ )
555
+ if not self ._check_local_y_in_range (local_y ):
556
+ raise ValueError (
557
+ "local_y out of range: "
558
+ "local_y:{: >4}; _yrange({: >4}, {: >4})"
559
+ "" .format (
560
+ local_y ,
561
+ 0 ,
562
+ self .height ,
563
+ )
564
+ )
565
+ else :
566
+ # for better error messages we check in detail what failed...
567
+ if not self ._check_x_in_range (x ):
568
+ raise ValueError (
569
+ "x out of range: "
570
+ "x:{: >4}; xrange({: >4}, {: >4})"
571
+ "" .format (
572
+ x ,
573
+ self ._xrange [0 ],
574
+ self ._xrange [1 ],
575
+ )
576
+ )
577
+ if not self ._check_y_in_range (y ):
578
+ raise ValueError (
579
+ "y out of range: "
580
+ "y:{: >4}; yrange({: >4}, {: >4})"
581
+ "" .format (
582
+ y ,
583
+ self ._yrange [0 ],
584
+ self ._yrange [1 ],
585
+ )
586
+ )
587
+
460
588
def update_pointer (self , x : int , y : int ) -> None :
461
589
"""updater_pointer function
462
590
helper function to update pointer in the plane
@@ -465,46 +593,49 @@ def update_pointer(self, x: int, y: int) -> None:
465
593
:return: None
466
594
rtype: None
467
595
"""
468
- local_x = int ((x - self ._xrange [0 ]) * self ._factorx ) + self ._nudge_x
469
- local_y = (
470
- int ((self ._yrange [0 ] - y ) * self ._factory ) + self .height + self ._nudge_y
471
- )
596
+ self ._add_point (x , y )
597
+ if not self ._pointer :
598
+ self ._draw_pointers (
599
+ self .plot_line_point [- 1 ][0 ],
600
+ self .plot_line_point [- 1 ][1 ],
601
+ )
602
+ else :
603
+ self ._pointer .x = self .plot_line_point [- 1 ][0 ]
604
+ self ._pointer .y = self .plot_line_point [- 1 ][1 ]
472
605
473
- if local_x >= 0 or local_y <= 100 :
474
- if self ._update_line :
475
- self ._draw_pointers (local_x , local_y )
476
- self ._update_line = False
477
- else :
478
- self ._pointer .x = local_x
479
- self ._pointer .y = local_y
606
+ def add_plot_line (self , x : int , y : int ) -> None :
607
+ """add_plot_line function.
480
608
481
- def _set_plotter_line ( self ) -> None :
482
- self . plot_line_point = []
609
+ add line to the plane.
610
+ multiple calls create a line-plot graph.
483
611
484
- def update_line (self , x : int , y : int ) -> None :
485
- """updater_line function
486
- helper function to update pointer in the plane
487
612
:param int x: ``x`` coordinate in the local plane
488
613
:param int y: ``y`` coordinate in the local plane
489
614
:return: None
615
+
490
616
rtype: None
491
617
"""
492
- local_x = int ((x - self ._xrange [0 ]) * self ._factorx ) + self ._nudge_x
493
- local_y = (
494
- int ((self ._yrange [0 ] - y ) * self ._factory ) + self .height + self ._nudge_y
495
- )
496
- if x < self ._xrange [1 ] and y < self ._yrange [1 ]:
497
- if local_x > 0 or local_y < 100 :
498
- if self ._update_line :
499
- self ._set_plotter_line ()
500
- self .plot_line_point .append ((local_x , local_y ))
501
- self ._update_line = False
502
- else :
503
- bitmaptools .draw_line (
504
- self ._screen_bitmap ,
505
- self .plot_line_point [- 1 ][0 ],
506
- self .plot_line_point [- 1 ][1 ],
507
- local_x ,
508
- local_y ,
509
- 1 ,
510
- )
618
+ self ._add_point (x , y )
619
+ if len (self .plot_line_point ) > 1 :
620
+ bitmaptools .draw_line (
621
+ self ._plot_bitmap ,
622
+ self .plot_line_point [- 2 ][0 ],
623
+ self .plot_line_point [- 2 ][1 ],
624
+ self .plot_line_point [- 1 ][0 ],
625
+ self .plot_line_point [- 1 ][1 ],
626
+ 1 ,
627
+ )
628
+
629
+ def clear_plot_lines (self , palette_index = 5 ):
630
+ """clear_plot_lines function.
631
+
632
+ clear all added lines
633
+ (clear line-plot graph)
634
+
635
+ :param int palette_index: color palett index. Defaults to 5
636
+ :return: None
637
+
638
+ rtype: None
639
+ """
640
+ self .plot_line_point = None
641
+ self ._plot_bitmap .fill (palette_index )
0 commit comments