Author Topic: graphs with QB64 and how to scroll the screen.  (Read 7676 times)

0 Members and 1 Guest are viewing this topic.

Offline bartok

  • Newbie
  • Posts: 80
    • View Profile
Re: graphs with QB64 and how to scroll the screen.
« Reply #30 on: January 27, 2021, 11:33:18 am »
This is the last release of my elementary code. Now there is only one screen, instead the previous screens put one each other with _PUTIMAGE. I avoid the use of _PUTIMAGE and I have used WINDOW, VIEW, VIEW PRINT instead. I have also implemented the possibility to scroll the screen.

I accept advice and tips.

By flair, I feel something inelegant in:

1-a main code that is merely the call of a subroutine (line 22);
2-a subutine that calls itself (line 96);
3-a subroutine that never get out of itself: see p. 2, and the fact that the program terminates in line 93, in the subroutine, and not in the main program.

but I don't know if these are my far-fetched ideas and I didn't find better ways.

Code: QB64: [Select]
  1.  
  2. CONST A% = 1 'per prendere un punto ogni A% pixel.
  3. CONST k! = 2 ' coefficiente della x.
  4. CONST m% = 3 'esponente della x.
  5. CONST s! = 10 * k! 'amplificazione di scala delle ascisse.
  6.  
  7. _TITLE "RAPPRESENTAZIONE DELLA FUNZIONE y = kx^m (k =" + STR$(k!) + " ; m =" + STR$(m%) + ")"
  8.  
  9. CONST L% = 1024
  10. CONST H% = 768
  11. CONST rosso = _RGB32(255, 0, 0)
  12. CONST bianco = _RGB32(255, 255, 255)
  13.  
  14. TYPE funzione
  15.     x AS INTEGER
  16.     y AS SINGLE
  17.  
  18. SCREEN _NEWIMAGE(L%, H%, 32)
  19.  
  20. disegno
  21.  
  22. SUB disegno ()
  23.     CONST Z% = 43 - 8
  24.  
  25.     DIM titolo1$, titolo2$, punti$, istruzioni$, keypress$
  26.     DIM punti%, i%, n% 'valori di x considerati da -punti% a +punti%, i% e n% sono contatori.
  27.     REDIM _PRESERVE funzione(i%) AS funzione
  28.  
  29.     i% = 1
  30.     n% = 0
  31.     DO 'disegna cartiglio, assi, scrive istruzioni e chiede il n. di punti. non accetta come valore "0".
  32.         CLS
  33.         titolo1$ = "RAPPRESENTAZIONE DELLA FUNZIONE y = kx^m (k =" + STR$(k!) + " ; m =" + STR$(m%) + ")"
  34.         LOCATE 2, ((L% / 8 - LEN(titolo1$)) \ 2): PRINT titolo1$
  35.         titolo2$ = "(Fattore di amplificazione delle ascisse: s = " + STR$(s!) + ")"
  36.         LOCATE 3, ((L% / 8 - LEN(titolo2$)) \ 2): PRINT titolo2$
  37.         VIEW ((L% - 800) \ 2, (H% - 600) \ 2)-((L% - 800) \ 2 + 800, (H% - 600) \ 2 + 600), , rosso 'area grafico 800x600 e pone le coordinate come locali a quest'area.
  38.         CLS
  39.         LINE (799 \ 2, 31)-(799 \ 2, 568), bianco
  40.         LINE (31, 599 \ 2 + 2)-(768, 599 \ 2 + 2), bianco
  41.         PSET (799 \ 2, 31), bianco: DRAW "F20": PSET (799 \ 2, 31), bianco: DRAW "G20": LOCATE 7, 65: PRINT "y"
  42.         PSET (768, 599 \ 2), bianco: DRAW "G20": PSET (768, 599 \ 2), bianco: DRAW "H20": LOCATE 25, 112: PRINT "x"
  43.         LOCATE 25, 63: PRINT "0"
  44.         punti$ = "Inserire il n. di punti in ascissa: "
  45.         LOCATE 5, ((L% / 8 - LEN(punti$) - 1) \ 2)
  46.         PRINT punti$;
  47.         INPUT "", punti%
  48.     LOOP WHILE LTRIM$(STR$(punti%)) = "0"
  49.     n% = -punti%
  50.     DO UNTIL n% = punti% + 1 ' crea il vettore con i valori di x e y i cui elementi vanno da -punti% a +punti%. disegna un cerchio colorato per ogni punto, traslando il grafico in modo che l'orgine non sia in alto a sinistra, ma su "0".
  51.         REDIM _PRESERVE funzione(i%) AS funzione
  52.         funzione(i%).x = n%
  53.         funzione(i%).y = k! * (funzione(i%).x) ^ m
  54.         WINDOW (0, 0)-(799, 599) 'pone il punto (0,0) in basso a sinistra e non scala gli assi x e y.
  55.         CIRCLE (s! * A% * funzione(i%).x + 399, A% * funzione(i%).y + 299), 2, rosso
  56.         PAINT (s! * A% * funzione(i%).x + 399 + 0.5, A% * funzione(i%).y + 299 + 0.5), rosso
  57.         i% = i% + 1
  58.         n% = n% + 1
  59.     LOOP
  60.     FOR i% = 1 TO UBOUND(funzione) - 1 ' congiunge i punti.
  61.         LINE (s! * A% * funzione(i%).x + 399, A% * funzione(i%).y + 299)-(s! * A% * funzione(i% + 1).x + 399, A% * funzione(i% + 1).y + 299), rosso
  62.     NEXT i%
  63.     WINDOW
  64.     VIEW 'elimina l'area del grafico 800x600 e ripristina le coordinate assolute.
  65.     istruzioni$ = "Premere INVIO per un nuovo calcolo, ESC per terminare."
  66.     LOCATE 45, ((L% / 8 - LEN(istruzioni$)) \ 2): PRINT istruzioni$
  67.     LOCATE 7, 16: COLOR rosso: PRINT "Premere " + CHR$(24) + " oppure " + CHR$(25) + "."
  68.     COLOR bianco
  69.     n% = 0
  70.     DO ' stampa le coppie di valori.
  71.         VIEW PRINT 8 TO 43
  72.         FOR i% = (1 + Z% * n%) TO Z% * (n% + 1)
  73.             SELECT CASE i%
  74.                 CASE UBOUND(funzione) + 1 AND UBOUND(funzione) MOD Z% > 0
  75.                     FOR i% = UBOUND(funzione) + 1 TO (UBOUND(funzione) + Z% - UBOUND(funzione) MOD Z%)
  76.                         LOCATE , 16: PRINT "                           "
  77.                     NEXT i%
  78.                 CASE ELSE
  79.                     LOCATE , 16: PRINT _TRIM$(STR$(i%)) + ")x=" + _TRIM$(STR$(funzione(i%).x)) + ";y=" + _TRIM$(STR$(funzione(i%).y)) + "        "
  80.             END SELECT
  81.         NEXT i%
  82.         DO
  83.             keypress$ = INKEY$
  84.         LOOP UNTIL keypress$ <> ""
  85.         SELECT CASE keypress$
  86.             CASE CHR$(0) + "H"
  87.                 IF n% > 0 THEN n% = n% - 1
  88.             CASE CHR$(0) + "P"
  89.                 IF i% < UBOUND(funzione) THEN n% = n% + 1
  90.             CASE CHR$(27)
  91.                 SYSTEM
  92.             CASE CHR$(13)
  93.                 VIEW PRINT 'elimina l'area view print.
  94.                 disegno
  95.         END SELECT
  96.     LOOP
  97.  

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: graphs with QB64 and how to scroll the screen.
« Reply #31 on: January 27, 2021, 12:01:56 pm »
I'd be worried about causing a memory leak by recalling a sub within a sub. It's a bit similar to not exiting a GOSUB RETURN properly, which messes with the order of the stack space. So to not overload the system memory, I just flag and double loop these types of routines, double loop and exit all conditions, except the ones I want to rerun the sub, or flag the condition I want to rerun, pass it out of the sub upon exit (meaning the flag variable hase to be in the parameter list of DIM SHARED) and then DO LOOP the SUB call, like...

Code: QB64: [Select]
  1. CALL Pete(flag%)
  2. IF flag% then flag% = 0 else EXIT DO

One of the other three methods is coded below. It flags the Enter key press, and keeps it in the second DO/LOOP. All non-flagged key presses simply exit that second loop...

Code: QB64: [Select]
  1. SUB disegno ()
  2.     CONST Z% = 43 - 8
  3.  
  4.     DIM titolo1$, titolo2$, punti$, istruzioni$, keypress$
  5.     DIM punti%, i%, n% 'valori di x considerati da -punti% a +punti%, i% e n% sono contatori.
  6.  
  7.  
  8.     DO ' Double DO/LOOP to allow CHR$(13) Enter press to loop back here. All other presses exit.
  9.         REDIM _PRESERVE funzione(i%) AS funzione
  10.  
  11.         i% = 1
  12.         n% = 0
  13.  
  14.         DO 'disegna cartiglio, assi, scrive istruzioni e chiede il n. di punti. non accetta come valore "0".
  15.             CLS
  16.             titolo1$ = "RAPPRESENTAZIONE DELLA FUNZIONE y = kx^m (k =" + STR$(k!) + " ; m =" + STR$(m%) + ")"
  17.             LOCATE 2, ((L% / 8 - LEN(titolo1$)) \ 2): PRINT titolo1$
  18.             titolo2$ = "(Fattore di amplificazione delle ascisse: s = " + STR$(s!) + ")"
  19.             LOCATE 3, ((L% / 8 - LEN(titolo2$)) \ 2): PRINT titolo2$
  20.             VIEW ((L% - 800) \ 2, (H% - 600) \ 2)-((L% - 800) \ 2 + 800, (H% - 600) \ 2 + 600), , rosso 'area grafico 800x600 e pone le coordinate come locali a quest'area.
  21.             CLS
  22.             LINE (799 \ 2, 31)-(799 \ 2, 568), bianco
  23.             LINE (31, 599 \ 2 + 2)-(768, 599 \ 2 + 2), bianco
  24.             PSET (799 \ 2, 31), bianco: DRAW "F20": PSET (799 \ 2, 31), bianco: DRAW "G20": LOCATE 7, 65: PRINT "y"
  25.             PSET (768, 599 \ 2), bianco: DRAW "G20": PSET (768, 599 \ 2), bianco: DRAW "H20": LOCATE 25, 112: PRINT "x"
  26.             LOCATE 25, 63: PRINT "0"
  27.             punti$ = "Inserire il n. di punti in ascissa: "
  28.             LOCATE 5, ((L% / 8 - LEN(punti$) - 1) \ 2)
  29.             PRINT punti$;
  30.             INPUT "", punti%
  31.         LOOP WHILE LTRIM$(STR$(punti%)) = "0"
  32.         n% = -punti%
  33.         DO UNTIL n% = punti% + 1 ' crea il vettore con i valori di x e y i cui elementi vanno da -punti% a +punti%. disegna un cerchio colorato per ogni punto, traslando il grafico in modo che l'orgine non sia in alto a sinistra, ma su "0".
  34.                 REDIM _PRESERVE funzione(i%) AS funzione
  35.              funzione(i%).x = n%
  36.           funzione(i%).y = k! * (funzione(i%).x) ^ m
  37.         WINDOW (0, 0)-(799, 599) 'pone il punto (0,0) in basso a sinistra e non scala gli assi x e y.
  38.          CIRCLE (s! * A% * funzione(i%).x + 399, A% * funzione(i%).y + 299), 2, rosso
  39.          PAINT (s! * A% * funzione(i%).x + 399 + 0.5, A% * funzione(i%).y + 299 + 0.5), rosso
  40.         i% = i% + 1
  41.         n% = n% + 1
  42.     LOOP
  43.     FOR i% = 1 TO UBOUND(funzione) - 1 ' congiunge i punti.
  44.           LINE (s! * A% * funzione(i%).x + 399, A% * funzione(i%).y + 299)-(s! * A% * funzione(i% + 1).x + 399, A% * funzione(i% + 1).y + 299), rosso
  45.     NEXT i%
  46.     WINDOW
  47.     VIEW 'elimina l'area del grafico 800x600 e ripristina le coordinate assolute.
  48.     istruzioni$ = "Premere INVIO per un nuovo calcolo, ESC per terminare."
  49.     LOCATE 45, ((L% / 8 - LEN(istruzioni$)) \ 2): PRINT istruzioni$
  50.     LOCATE 7, 16: COLOR rosso: PRINT "Premere " + CHR$(24) + " oppure " + CHR$(25) + "."
  51.     COLOR bianco
  52.     n% = 0
  53.     DO ' stampa le coppie di valori.
  54.         VIEW PRINT 8 TO 43
  55.         FOR i% = (1 + Z% * n%) TO Z% * (n% + 1)
  56.             SELECT CASE i%
  57.                 CASE UBOUND(funzione) + 1 AND UBOUND(funzione) MOD Z% > 0
  58.                     FOR i% = UBOUND(funzione) + 1 TO (UBOUND(funzione) + Z% - UBOUND(funzione) MOD Z%)
  59.                         LOCATE , 16: PRINT "                           "
  60.                     NEXT i%
  61.                 CASE ELSE
  62.                                LOCATE , 16: PRINT _TRIM$(STR$(i%)) + ")x=" + _TRIM$(STR$(funzione(i%).x)) + ";y=" + _TRIM$(STR$(funzione(i%).y)) + "        "
  63.             END SELECT
  64.         NEXT i%
  65.         DO
  66.             _LIMIT 30 ' Saves CPU so you don't have to install a smoke detector in your laptop.
  67.             keypress$ = INKEY$
  68.         LOOP UNTIL keypress$ <> ""
  69.         SELECT CASE keypress$
  70.             CASE CHR$(0) + "H"
  71.                 IF n% > 0 THEN n% = n% - 1
  72.             CASE CHR$(0) + "P"
  73.                 IF i% < UBOUND(funzione) THEN n% = n% + 1
  74.             CASE CHR$(27)
  75.                 SYSTEM
  76.             CASE CHR$(13)
  77.                 VIEW PRINT 'elimina l'area view print.
  78.                 flag% = -1 ' Prevents second DO/LOOP exit and redoes the sub from start.
  79.         END SELECT
  80.     LOOP
  81.     IF flag% THEN flag% = 0 ELSE EXIT DO

I put that extra DO statement after the DIM CONST and statements, as I don't believe those need updating. The REDIM _PRESERVE probably does, so I included that in the re-loop routine. Check it out first, and see if it works.

Pete




Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bartok

  • Newbie
  • Posts: 80
    • View Profile
Re: graphs with QB64 and how to scroll the screen.
« Reply #32 on: January 27, 2021, 04:38:38 pm »
Thanks Pete, very interesting.

your double DO is the solution. I solved as you can see below.

As you can see, I made some tries with the "flag" and I  admit that I haven't fully understood it. Finally, I put a simply EXIT DO in lines 109, 106 and 112. So, the program terminates in the main code. Without the double DO, the EXIT put in the main code where or the program finished, or, with a DO LOOP in the main code, was necessary to presso ENTER a second time.

_LIMIT 30 makes some 25% less of CPU use!

Code: QB64: [Select]
  1.  
  2. CONST A% = 1 'per prendere un punto ogni A% pixel.
  3. CONST k! = 2 ' coefficiente della x.
  4. CONST m% = 3 'esponente della x.
  5. CONST s! = 10 * k! 'amplificazione di scala delle ascisse.
  6.  
  7. _TITLE "RAPPRESENTAZIONE DELLA FUNZIONE y = kx^m (k =" + STR$(k!) + " ; m =" + STR$(m%) + ")"
  8.  
  9. CONST L% = 1024
  10. CONST H% = 768
  11. CONST rosso = _RGB32(255, 0, 0)
  12. CONST bianco = _RGB32(255, 255, 255)
  13.  
  14. TYPE funzione
  15.     x AS INTEGER
  16.     y AS SINGLE
  17.  
  18. 'DIM SHARED flag%
  19.  
  20. SCREEN _NEWIMAGE(L%, H%, 32)
  21.  
  22. 'DO
  23. disegno ' flag%
  24. '  IF flag% THEN flag% = 0 ELSE EXIT DO
  25. 'LOOP
  26.  
  27.  
  28. SUB disegno () ' (flag%)
  29.     CONST Z% = 43 - 8
  30.  
  31.     DIM titolo1$, titolo2$, punti$, istruzioni$, keypress$
  32.     DIM punti%, i%, n% 'valori di x considerati da -punti% a +punti%, i% e n% sono contatori.
  33.  
  34.     REDIM _PRESERVE funzione(i%) AS funzione
  35.  
  36.     DO ' Double DO/LOOP to allow CHR$(13) Enter press to loop back here. All other presses exit.
  37.         ' REDIM _PRESERVE funzione(i%) AS funzione
  38.  
  39.         i% = 1
  40.         n% = 0
  41.  
  42.         DO 'disegna cartiglio, assi, scrive istruzioni e chiede il n. di punti. non accetta come valore "0".
  43.             CLS
  44.             titolo1$ = "RAPPRESENTAZIONE DELLA FUNZIONE y = kx^m (k =" + STR$(k!) + " ; m =" + STR$(m%) + ")"
  45.             LOCATE 2, ((L% / 8 - LEN(titolo1$)) \ 2): PRINT titolo1$
  46.             titolo2$ = "(Fattore di amplificazione delle ascisse: s = " + STR$(s!) + ")"
  47.             LOCATE 3, ((L% / 8 - LEN(titolo2$)) \ 2): PRINT titolo2$
  48.             VIEW ((L% - 800) \ 2, (H% - 600) \ 2)-((L% - 800) \ 2 + 800, (H% - 600) \ 2 + 600), , rosso 'area grafico 800x600 e pone le coordinate come locali a quest'area.
  49.             CLS
  50.             LINE (799 \ 2, 31)-(799 \ 2, 568), bianco
  51.             LINE (31, 599 \ 2 + 2)-(768, 599 \ 2 + 2), bianco
  52.             PSET (799 \ 2, 31), bianco: DRAW "F20": PSET (799 \ 2, 31), bianco: DRAW "G20": LOCATE 7, 65: PRINT "y"
  53.             PSET (768, 599 \ 2), bianco: DRAW "G20": PSET (768, 599 \ 2), bianco: DRAW "H20": LOCATE 25, 112: PRINT "x"
  54.             LOCATE 25, 63: PRINT "0"
  55.             punti$ = "Inserire il n. di punti in ascissa: "
  56.             LOCATE 5, ((L% / 8 - LEN(punti$) - 1) \ 2)
  57.             PRINT punti$;
  58.             INPUT "", punti%
  59.         LOOP WHILE LTRIM$(STR$(punti%)) = "0"
  60.         n% = -punti%
  61.         DO UNTIL n% = punti% + 1 ' crea il vettore con i valori di x e y i cui elementi vanno da -punti% a +punti%. disegna un cerchio colorato per ogni punto, traslando il grafico in modo che l'orgine non sia in alto a sinistra, ma su "0".
  62.             REDIM _PRESERVE funzione(i%) AS funzione
  63.             funzione(i%).x = n%
  64.             funzione(i%).y = k! * (funzione(i%).x) ^ m
  65.             WINDOW (0, 0)-(799, 599) 'pone il punto (0,0) in basso a sinistra e non scala gli assi x e y.
  66.             CIRCLE (s! * A% * funzione(i%).x + 399, A% * funzione(i%).y + 299), 2, rosso
  67.             PAINT (s! * A% * funzione(i%).x + 399 + 0.5, A% * funzione(i%).y + 299 + 0.5), rosso
  68.             i% = i% + 1
  69.             n% = n% + 1
  70.         LOOP
  71.         FOR i% = 1 TO UBOUND(funzione) - 1 ' congiunge i punti.
  72.             LINE (s! * A% * funzione(i%).x + 399, A% * funzione(i%).y + 299)-(s! * A% * funzione(i% + 1).x + 399, A% * funzione(i% + 1).y + 299), rosso
  73.         NEXT i%
  74.         WINDOW
  75.         VIEW 'elimina l'area del grafico 800x600 e ripristina le coordinate assolute.
  76.         istruzioni$ = "Premere INVIO per un nuovo calcolo, ESC per terminare."
  77.         LOCATE 45, ((L% / 8 - LEN(istruzioni$)) \ 2): PRINT istruzioni$
  78.         LOCATE 7, 16: COLOR rosso: PRINT "Premere " + CHR$(24) + " oppure " + CHR$(25) + "."
  79.         COLOR bianco
  80.         n% = 0
  81.         DO ' stampa le coppie di valori.
  82.             VIEW PRINT 8 TO 43
  83.             FOR i% = (1 + Z% * n%) TO Z% * (n% + 1)
  84.                 SELECT CASE i%
  85.                     CASE UBOUND(funzione) + 1 '--------> not necessary: AND UBOUND(funzione) MOD Z% > 0
  86.                         FOR i% = UBOUND(funzione) + 1 TO (UBOUND(funzione) + Z% - UBOUND(funzione) MOD Z%)
  87.                             LOCATE , 16: PRINT STRING$(27, " ")
  88.                         NEXT i%
  89.                     CASE ELSE
  90.                         LOCATE , 16: PRINT _TRIM$(STR$(i%)) + ")x=" + _TRIM$(STR$(funzione(i%).x)) + ";y=" + _TRIM$(STR$(funzione(i%).y)) + STRING$(8, " ")
  91.                 END SELECT
  92.             NEXT i%
  93.             DO
  94.                 _LIMIT 30 ' Saves CPU so you don't have to install a smoke detector in your laptop.
  95.                 keypress$ = INKEY$
  96.             LOOP UNTIL keypress$ <> ""
  97.             SELECT CASE keypress$
  98.                 CASE CHR$(0) + "H"
  99.                     IF n% > 0 THEN n% = n% - 1
  100.                 CASE CHR$(0) + "P"
  101.                     IF i% < UBOUND(funzione) THEN n% = n% + 1
  102.                 CASE CHR$(27)
  103.                     EXIT DO
  104.                 CASE CHR$(13)
  105.                     VIEW PRINT 'elimina l'area view print.
  106.                     EXIT DO ' flag% = -1 ' Prevents second DO/LOOP exit and redoes the sub from start.
  107.             END SELECT
  108.         LOOP
  109.         IF keypress$ = CHR$(27) THEN EXIT DO '        IF flag% = -1 THEN flag% = 0 ELSE EXIT DO
  110.     LOOP
  111.  
« Last Edit: January 28, 2021, 02:11:21 am by bartok »