Newsgroup: it.comp.lang.visual-basic
Titolo: VB sbaglia i calcoli se ScaleMode=vbUser?

Devo disegnare semplicemente degli assi cartesiani all'interno di una 
PictureBox. Ho provato a farlo utilizzando ScaleMode=vbUser e impostande delle 
unità di misura comode, ma sembra che sbagli. Per confronto, ho fatto gli stessi 
calcoli in ScaleMode=vbPixels e sono effettivamente diversi.
In un nuovo progetto VB, aggiungete una PictureBox nel Form e poi questo codice:
---
Option Explicit
Private Sub Form_Load()
     Picture1.AutoRedraw = True
End Sub
Private Sub Form_Resize()
     Picture1.Cls
     ' Ridimensione PictureBox
     Picture1.Left = 100
     Picture1.Top = 100
     Picture1.Width = Me.Width - 400
     Picture1.Height = Me.Height - 800
     ' Disegna gli assi in vbUser
     Picture1.ScaleMode = vbUser
     Picture1.ScaleLeft = -50
     Picture1.ScaleTop = 50
     Picture1.ScaleWidth = 100
     Picture1.ScaleHeight = -100
     Picture1.ForeColor = vbBlack
     Picture1.Line (0, 50)-(0, -50)
     Picture1.Line (-50, 0)-(50, 0)
     ' Disegna gli assi in vbPixels
     Picture1.ScaleMode = vbPixels
     Picture1.ForeColor = vbRed
     Picture1.Line (0, Picture1.ScaleHeight \ 2)-(Picture1.ScaleWidth, 
Picture1.ScaleHeight \ 2)
     Picture1.Line (Picture1.ScaleWidth \ 2, 0)-(Picture1.ScaleWidth \ 2, 
Picture1.ScaleHeight)
     Me.Caption = Picture1.ScaleWidth & "x" & Picture1.ScaleHeight
End Sub
---
Eseguite il programma e ridimensionate la finestra. Vedrete che, in alcuni casi, 
gli assi neri (calcolati in vbUser) non si sovrappongono agli assi rossi 
(calcolati in vbPixels).
Provando con dimensioni piccole a catturare la finestra con un programma di 
grafica, sembra che i calcoli fatti in vbUser siano errati.
Qualcuno mi sa dare una spiegazione di ciò?

 Qualcuno mi sa dare una spiegazione di ciò?
Forse per colpa dell'approssimazione? Nel senso: il passaggio fra una
scala e l'altra comporta un ricalcolo basato sul rapporto tra le due
unità di misura. Se as esempio il rapporto è un valore irrazionale, il
passaggio tra una unità e l'altra comporta una perdita di precisione.
Questo però può giustificare al massimo uno scarto di qualche pixel.
Io non ho provato il tuo esempio, quindi non so se la differenza che
tu noti è appunto dell'ordine di qualche pixel

 Forse per colpa dell'approssimazione?
Anche io ho pensato all'approssimazione, ma deve essere una
approssimazione corretta. Alla fine questa approssimazione fa
sbagliare di UN SOLO pixel, ma, credimi, in alcuni casi si vede
benissimo che c'è qualcosa che non va.
Devo disegnare un cerchio pieno con centro proprio nell'intersezione
degli assi. Se il raggio del cerchio è piccolo, si vede benissimo che
gli assi non sono nella giusta posizione, anche se l'errore è di un
solo pixel.


Purtroppo il problema dell'approssimazione è irrisolvibile, nel senso
che l'unica unità di misura realmente significativa è vbPixel, che ti
permette di fare effettivamente riferimento al singolo pixel dello
schermo. Qualsiasi altra scelta implica che, in fase di conversione
rispetto allo schermo, si debba "decidere" quale pixel accendere o
meno: se io ho due pixel adiacenti, e se il primo rappresenta il
valore 1 e il secondo il valore 2, quale dei due devo usare per il
valore 1,5? Anche se avessi il valore 1,9 (e quindi fosse chiaro che
il pixel da usare è quello relativo al valore 2), otterrei in ogni
caso una rappresentazione errata. Sinceramente, in questi termini, non
vedo soluzione.


Qui stai usando la divisione intera, che tronca il risultato
all'intero più vicino.
Se usi la divisione normale, ottieni l'arrotondamento all'intero più
vicino e gli assi disegnati vengono perfettamente sopra agli altri.

 vicino e gli assi disegnati vengono perfettamente sopra agli altri.
Ho provato, ma non è vero che i due assi calcolati nei due modi sono 
coincidenti. Prova a verificare di persona quando la finestra ha una dimensione 
di 533x533 pixel (vedi nella Caption del Form).

 
batta...@libero.it
 ha scritto:

Si ho visto.
Ho fatto la prova ha 117x117 (la più piccola dimensione in cui ho
notato il problema) e ho visto una cosa strana.
Con 117 pixel mi aspetterei di trovare 58 pixel grigi, 1 pixel
dell'asse e altri 58 pixel grigi, ovvero dovrebbe venire colorato il
pixel 59.
Il 59° pixel viene colorato usando lo scaleMode personalizzato, mentre
lavorando in pixel viene colorato il 60° !
Per controllare questa cosa strana ho provato un caso più semplice:
    Picture1.ScaleMode = vbPixels
    Picture1.Line (0, 58.5)-(Picture1.ScaleWidth, 58.5)
Mi aspetterei che venga colorato il pixel 59, o al massimo, se fa
troncamento anziché arrotondamento, il 58, invece viene colorato il
60 :(
Per fare i controlli ho fatto un printscreen è ho zoomato con un
programma di grafica, la larghezza dell'area di disegno è
correttamente di 117 pixel, ma il pixel dell'asse è quello sbagliato.