|
Post by Marco Kurvers on Jul 19, 2024 13:57:06 GMT
Pixels tekenen doen we niet vaak. We kiezen shapes om te tekenen omdat het sneller gaat. Het tekenen van alleen pixels kan ook handig zijn. Lijnen en cirkels zijn dan niet de uitkomst van wat je wilt.
Een pixeltechniek is bijvoorbeeld ditheren. Hoe hoger de brightness op bepaalde plaatsen, hoe meer pixels. Hoe lager de brightness, hoe minder pixels. De afstanden van de pixels zijn ook belangrijk.
Onderstaand programma tekent de pixels met willekeurige posities, dus de techniek doet even niet ter zake. Het gaat erom hoe we de pixels van boven naar beneden kunnen tekenen en hoe we het diagonaal kunnen tekenen, zonder dat de posities veranderen.
Het programma is nog niet 100% in orde, want het werkt tot nu toe alleen op een vierkante canvas. De code is ook te vinden in het Python board. Daar heb ik het voorbeeld met behulp van numpy.
WindowWidth = 600 WindowHeight = 600 UpperLeftX = 100 UpperLeftY = 100 dim pixels(WindowWidth - 1, WindowHeight - 1)
call GenereerPixels open "Pixels" for graphics_nf_nsb as #main #main "trapclose CloseMain" #main "down" #main "fill black" #main "color white" #main "size 3" #main "when characterInput Key" call TekenPixels #main "flush" wait
sub CloseMain handle$ #main "discard" close #handle$ end sub
sub Key handle$, char$ #main "cls" #main "fill black" #main "color white" call TekenDiagonaal end sub
sub GenereerPixels for y = 0 to WindowHeight - 1 for x = 0 to WindowWidth - 1 pixels(x, y) = 0 next x next p = 1 while p <= 800 x = int(rnd(1) * WindowWidth) y = int(rnd(1) * WindowHeight) if pixels(x, y) = 0 then pixels(x, y) = 1 p = p + 1 end if wend end sub
sub TekenPixels for y = 0 to WindowHeight - 1 for x = 0 to WindowWidth - 1 if pixels(x, y) = 1 then timer 3, [continue] wait [continue] #main "set "; x; " "; y timer 0 end if next next end sub
sub TekenDiagonaal 'teken diagonaal van linksboven naar schuine middenlijn endX = 0 for y = 0 to WindowHeight - 1 i = 0 j = y
for x = 0 to endX if pixels(i, j) = 1 then timer 3, [continueLB] wait [continueLB] #main "set "; i; " "; j timer 0 end if i = i + 1 j = j - 1 next x endX = endX + 1 next y
'teken diagonaal vanaf schuine middenlijn naar rechtsonder endY = 1 for x = 1 to WindowWidth - 1 i = x j = WindowHeight - 1 for y = WindowHeight - 1 to endY step -1 if pixels(i, j) = 1 then timer 3, [continueRO] wait [continueRO] #main "set "; i; " "; j timer 0 end if i = i + 1 j = j - 1 next endY = endY + 1 next end sub
|
|
|
Post by memophenon on Jul 22, 2024 21:18:15 GMT
Je probleem zit in de berekening van de pixelposities in de Sub TekenDiagonaal. Dat is beter in te zien door alle overbodigheden die niets met het eigenlijke probleem te maken hebben uit het programma te verwijderen en je te concentreren op de logica van de betrokken Sub. Het hele grafische gebeuren kan dus overboord. Beperk je tot een piepklein speelveld en laat de Sub alleen maar vertellen op welke x- en y-posities deze een pixel zou plaatsen, ervan uitgaande dat het hele veld uiteindelijk met pixels moet worden gevuld. Zo zie je tenminste precies wat er nu echt onder water gebeurt. Bij zo'n aanpak houd ik het volgende programma over (ik heb de variabele n toegevoegd om het aantal keren dat er een pixel wordt getekend te kunnen presenteren): H = 3 W = 3 Call TekenDiagonaal
W = 4 Call TekenDiagonaal
H = 4 Call TekenDiagonaal
W = 3 Call TekenDiagonaal
Sub TekenDiagonaal Shared H, W Print Print " H * W ="; H; "*"; W Print " -------------"
'---- Teken diagonaal van linkboven naar schuine middellijn ---' n = 0 endX = 0 For y = 0 To H - 1 i = 0 j = y Print " endX ="; endX For x = 0 To endX Print " Teken pixel("; i; ","; j; ")" i = i + 1 j = j - 1 n = n + 1 Next x endX = endX + 1 Next y Print " "; n; "pixels getekend"
'---- Teken diagonaal vanaf schuine middenlijn naar rechtsonder ----' n = 0 endY = 1 For x = 1 To W - 1 i = x j = H - 1 Print " endY ="; endY For y = H - 1 To endY Step -1 Print " Teken pixel("; i; ","; j; ")" i = i + 1 j = j - 1 n = n + 1 Next y endY = endY + 1 Next x Print " "; n; "pixels getekend" End Sub Het programma probeert dus vier speelveldjes uit, met resp. hoogte/breedte-verhoudingen 3/3, 3/4, 4/4 en 4/3. Dat lijken me voldoende testgevallen. En dit is dan het resultaat: H * W = 3 * 3 ------------- endX = 0 Teken pixel( 0 , 0 ) endX = 1 Teken pixel( 0 , 1 ) Teken pixel( 1 , 0 ) endX = 2 Teken pixel( 0 , 2 ) Teken pixel( 1 , 1 ) Teken pixel( 2 , 0 ) 6 pixels getekend endY = 1 Teken pixel( 1 , 2 ) Teken pixel( 2 , 1 ) endY = 2 Teken pixel( 2 , 2 ) 3 pixels getekend
H * W = 3 * 4 ------------- endX = 0 Teken pixel( 0 , 0 ) endX = 1 Teken pixel( 0 , 1 ) Teken pixel( 1 , 0 ) endX = 2 Teken pixel( 0 , 2 ) Teken pixel( 1 , 1 ) Teken pixel( 2 , 0 ) 6 pixels getekend endY = 1 Teken pixel( 1 , 2 ) Teken pixel( 2 , 1 ) endY = 2 Teken pixel( 2 , 2 ) endY = 3 3 pixels getekend
H * W = 4 * 4 ------------- endX = 0 Teken pixel( 0 , 0 ) endX = 1 Teken pixel( 0 , 1 ) Teken pixel( 1 , 0 ) endX = 2 Teken pixel( 0 , 2 ) Teken pixel( 1 , 1 ) Teken pixel( 2 , 0 ) endX = 3 Teken pixel( 0 , 3 ) Teken pixel( 1 , 2 ) Teken pixel( 2 , 1 ) Teken pixel( 3 , 0 ) 10 pixels getekend endY = 1 Teken pixel( 1 , 3 ) Teken pixel( 2 , 2 ) Teken pixel( 3 , 1 ) endY = 2 Teken pixel( 2 , 3 ) Teken pixel( 3 , 2 ) endY = 3 Teken pixel( 3 , 3 ) 6 pixels getekend
H * W = 4 * 3 ------------- endX = 0 Teken pixel( 0 , 0 ) endX = 1 Teken pixel( 0 , 1 ) Teken pixel( 1 , 0 ) endX = 2 Teken pixel( 0 , 2 ) Teken pixel( 1 , 1 ) Teken pixel( 2 , 0 ) endX = 3 Teken pixel( 0 , 3 ) Teken pixel( 1 , 2 ) Teken pixel( 2 , 1 ) Teken pixel( 3 , 0 ) 10 pixels getekend endY = 1 Teken pixel( 1 , 3 ) Teken pixel( 2 , 2 ) Teken pixel( 3 , 1 ) endY = 2 Teken pixel( 2 , 3 ) Teken pixel( 3 , 2 ) 5 pixels getekend
Bij de vierkante velden gaat het goed: er worden 9 resp. 16 pixels getekend. Bij de 3/4-rechthoek blijft de meest rechtse kolom leeg (wat in een plaatje van honderden bij honderden pixels misschien niet zou opvallen), en bij 4/3 worden er pixels rechts buiten de rechthoek getekend (wat je programma waarschijnlijk laat vastlopen). Het algoritme (zowel de eerste als de tweede helft van TekenDiagonaal) bevat dus nog wat onvolkomenheidjes. Ik vind de hele constructie eigenlijk ook wel behoorlijk complex, die foefjes met vier hulpvariabelen i, j, endX en endY. Het diagonaalsgewijs tekenen van pixels moet veel eenvoudiger kunnen.
Update 2024-07-23 16:27: De variabelen H en W in de printregel (direct boven de streep) waren verwisseld. Dat is nu verbeterd. Boven de tweede rechthoek staat nu dus correct de kop "H * W = 3 * 4". De conclusie is navenant aangepast.
|
|
keesb
New Member
Posts: 22
|
Post by keesb on Jul 22, 2024 21:49:54 GMT
Hieronder mijn (dankzij memophenon) verbeterde versie van het diagonaal tekenen, werkt ook met rechthoekige vensters :
sub TekenVanLBnaarRO
Tstart = time$("milliseconds")
x = 0 : y = 0 ' start linksboven, NB startwaarde y blijft 0 while x < WindowWidth - 1 ' zolang startwaarde x kleiner dan rechterkant window, m.a.w. laatste x-waarde = WindowWidth - 2 dx = 0 ' reset hulpvars voor schuine lijn dy = 0 while x + dx >= 0 and y + dy <= WindowHeight - 1 ' = zolang de linkerkant niet overschreden wordt EN de onderkant niet overschreden wordt ' = zolang de linkerkant OF de onderkant niet overschreden wordt if pixels(x + dx, y + dy) = 1 then #main "set "; x + dx; " "; y + dy ' als de waarde in het pixels-array 1 is dan een pixel plaatsen dx = dx - 1 ' ga 1 pixel verder naar links dy = dy + 1 ' ga 1 pixel verder naar beneden wend x = x + 1 ' volgende schuine lijn start 1 pixel verder naar rechts, startwaarde y = 0 wend
x = WindowWidth - 1 : y = 0 ' start rechtsboven, NB startwaarde x blijft WindowWidth - 1 while y <= WindowHeight - 1 ' zolang startwaarde y kleiner of gelijk aan onderkant window dx = 0 ' reset hulpvars voor schuine lijn dy = 0 while x + dx >= 0 and y + dy <= WindowHeight - 1 ' = zolang de linkerkant niet overschreden wordt EN de onderkant niet overschreden wordt ' = zolang de linkerkant OF de onderkant niet overschreden wordt if pixels(x + dx, y + dy) = 1 then #main "set "; x + dx; " "; y + dy ' als de waarde in het pixels-array 1 is dan een pixel plaatsen dx = dx - 1 ' ga 1 pixel verder naar links dy = dy + 1 ' ga 1 pixel verder naar beneden wend y = y + 1 ' volgende schuine lijn start 1 pixel verder naar beneden, startwaarde x = WindowWidth - 1 wend
Tstop = time$("milliseconds") call PrintTiming Tstart, Tstop, "tekenen pixels diagonaal van LB->RO" end sub
|
|
|
Post by Marco Kurvers on Jul 22, 2024 21:53:59 GMT
Ja, dat lijkt mij ook. Ik heb echter nog geen simpele manier kunnen vinden.
|
|
|
Post by memophenon on Jul 23, 2024 6:33:40 GMT
Zelfde procedé op die van keesb toegepast:
H = 3 W = 3 Call TekenVanLBnaarRO
W = 4 Call TekenVanLBnaarRO
H = 4 Call TekenVanLBnaarRO
W = 3 Call TekenVanLBnaarRO
Sub TekenVanLBnaarRO Shared H, W Print Print " H * W ="; H; "*"; W Print " -------------"
'---- Vanaf LB ----' n = 0 Print " Vanaf linksboven" x = 0: y = 0 While x < W - 1 dx = 0 dy = 0 While x + dx >= 0 And y + dy < H - 1 Print " Teken pixel("; x + dx; ","; y + dy; ")" dx = dx - 1 dy = dy + 1 n = n + 1 Wend x = x + 1 Wend Print " "; n; "pixels getekend"
'---- Vanaf RB ----' n = 0 Print " Vanaf rechtsboven" x = W - 1: y = 0 While y < H - 1 dx = 0 dy = 0 While x + dx >= 0 And y + dy < H - 1 Print " Teken pixel("; x + dx; ","; y + dy; ")" dx = dx - 1 dy = dy + 1 n = n + 1 Wend y = y + 1 Wend Print " "; n; "pixels getekend" End Sub
Resultaat:
H * W = 3 * 3 ------------- Vanaf linksboven Teken pixel( 0 , 0 ) Teken pixel( 1 , 0 ) Teken pixel( 0 , 1 ) 3 pixels getekend Vanaf rechtsboven Teken pixel( 2 , 0 ) Teken pixel( 1 , 1 ) Teken pixel( 2 , 1 ) 3 pixels getekend
H * W = 3 * 4 ------------- Vanaf linksboven Teken pixel( 0 , 0 ) Teken pixel( 1 , 0 ) Teken pixel( 0 , 1 ) Teken pixel( 2 , 0 ) Teken pixel( 1 , 1 ) 5 pixels getekend Vanaf rechtsboven Teken pixel( 3 , 0 ) Teken pixel( 2 , 1 ) Teken pixel( 3 , 1 ) 3 pixels getekend
H * W = 4 * 4 ------------- Vanaf linksboven Teken pixel( 0 , 0 ) Teken pixel( 1 , 0 ) Teken pixel( 0 , 1 ) Teken pixel( 2 , 0 ) Teken pixel( 1 , 1 ) Teken pixel( 0 , 2 ) 6 pixels getekend Vanaf rechtsboven Teken pixel( 3 , 0 ) Teken pixel( 2 , 1 ) Teken pixel( 1 , 2 ) Teken pixel( 3 , 1 ) Teken pixel( 2 , 2 ) Teken pixel( 3 , 2 ) 6 pixels getekend
H * W = 4 * 3 ------------- Vanaf linksboven Teken pixel( 0 , 0 ) Teken pixel( 1 , 0 ) Teken pixel( 0 , 1 ) 3 pixels getekend Vanaf rechtsboven Teken pixel( 2 , 0 ) Teken pixel( 1 , 1 ) Teken pixel( 0 , 2 ) Teken pixel( 2 , 1 ) Teken pixel( 1 , 2 ) Teken pixel( 2 , 2 ) 6 pixels getekend
Update om 16:29: De variabelen H en W in de printregel (direct boven de streep) waren verwisseld. Dat is nu verbeterd. Boven de tweede rechthoek staat nu dus correct de kop "H * W = 3 * 4".
|
|
keesb
New Member
Posts: 22
|
Post by keesb on Jul 23, 2024 12:09:24 GMT
Hallo memophenon,
Alle lof voor jouw plan van aanpak, je toont duidelijk aan dat mijn routine dus de onderste rij pixels mist (die met de hoogste y-waarde). Ik had een grafische controle ingebouwd d.m.v. een pixelraster met vaste afstanden maar die is de mist ingegaan om de volgende reden : Als je in LB een venster opent van bv 600 pixels breed en 600 pixels hoog, dan gaat daar de hoogte van de titelbalk vanaf. De onderste horizontale rijen pixels (ongeveer 30) verdwijnen daardoor uit beeld en daar had ik het nu juist aan moeten zien. Verder ben ik op het verkeerde spoor gezet door de voorwaarde x < W - 1, x loopt dus van 0 t.e.m. W - 2 bij het tekenen vanaf Linksboven. Die laatste pixel (en de hele kolom eronder) tekenen wordt ondervangen door in het tweede deel iedere schuine lijn te laten beginnen in de rechterbovenhoek met xcoordinaat W - 1. Datzelfde verhaal gaat natuurlijk niet meer op voor de y-richting, dus alle voorwaardes rond y met ... < H - 1 moeten nu ... <= H - 1 worden. Als ik jouw test met deze verandering run krijg ik de juiste aantallen pixels, ik zal hierboven in mijn code 3 maal een "=" toevoegen.
Ik moet alsnog constateren dat ik uit het oorspronkelijke commentaar bij de code de fout al had kunnen herkennen, het commentaar bij de code is nu na aanpassing weer correct.
|
|
|
Post by memophenon on Jul 23, 2024 13:42:19 GMT
Mijn aanpak was nogal anders en leidde zonder veel puzzelwerk naar het doel. Eigenlijk wel de moeite waard om hier uiteen te zetten. Zoals van mijn zelfportret valt af te lezen, ben ik een vrij simpel en rechtlijnig persoon. Ik ga niet meteen heldhaftig pogen allerlei wilde goocheltrucs met coördinaten uit te halen. Ik begin simpelweg bij het probleem zelf. Eerst maar eens domweg proberen de oplossing een afspiegeling van het probleem te laten zijn. Daarbij niet alle aspecten tegelijk willen behandelen (optimaliseren kan later altijd nog, als dat werkelijk nodig is). Wat was de opgave ook alweer? Bouw de weergave van een rechthoekig plaatje op het scherm geleidelijk op door telkens een onder 45° naar rechts hellende diagonaal van de met het plaatje corresponderende pixels te tekenen, te beginnen vanaf de linker bovenhoek en dan aansluitend tot aan de rechter onderhoek. Goed. Spelers in dit spel: rechthoekig plaatje, scherm, diagonalen, pixels. Reeds aanwezig wanneer het doek op gaat: het plaatje met z'n pixels, het scherm. Voor de hand liggende stappen: - Leg een geordende verzameling van de benodigde diagonalen aan, zodat alle spelers aanwezig zijn.
- Vul de diagonalen met de juiste pixels (of de coördinaten ervan) van het plaatje.
- Teken de diagonalen in de juiste volgorde op het scherm.
Hiermee heb ik de opgave opgesplitst in drie deelprobleempjes die elk voor zich eenvoudig zijn op te lossen. Het oorspronkelijke Python-programma dat ik op 11 juli tijdens een Programmeren-sessie had laten zien, heb ik voor deze gelegenheid vertaald naar BASIC en op dezelfde manier uitgekleed als ik bij de programma's van Marco Kurvers en keesb heb gedaan. In grote trekken zien de drie stappen er nu zo uit:
- Drie statements.
- Geneste iteraties over de y- en x-coördinaten van het plaatje. Het binnenblok bevat drie statements.
- Geneste iteraties over de diagonalen, d.w.z. over de diagonaalnummers en de offsets binnen elke diagonaal. Het binnenblok bevat twee statements.
Ik heb de statements t.b.v. debugginginformatie niet meegeteld. Behalve de "Teken pixel" berichten naar de console natuurlijk, want dat is in dit model nou precies de simulatie van het tekenen van een pixel. De test van mijn programma laat zien dat er keurig tot aan en binnen de lijntjes wordt gekleurd: H * W = 3 * 3 ------------- Diagonaal 0 Teken pixel( 0 , 0 ) Diagonaal 1 Teken pixel( 1 , 0 ) Teken pixel( 0 , 1 ) Diagonaal 2 Teken pixel( 2 , 0 ) Teken pixel( 1 , 1 ) Teken pixel( 0 , 2 ) Diagonaal 3 Teken pixel( 2 , 1 ) Teken pixel( 1 , 2 ) Diagonaal 4 Teken pixel( 2 , 2 ) 9 pixels getekend
H * W = 3 * 4 ------------- Diagonaal 0 Teken pixel( 0 , 0 ) Diagonaal 1 Teken pixel( 1 , 0 ) Teken pixel( 0 , 1 ) Diagonaal 2 Teken pixel( 2 , 0 ) Teken pixel( 1 , 1 ) Teken pixel( 0 , 2 ) Diagonaal 3 Teken pixel( 3 , 0 ) Teken pixel( 2 , 1 ) Teken pixel( 1 , 2 ) Diagonaal 4 Teken pixel( 3 , 1 ) Teken pixel( 2 , 2 ) Diagonaal 5 Teken pixel( 3 , 2 ) 12 pixels getekend
H * W = 4 * 4 ------------- Diagonaal 0 Teken pixel( 0 , 0 ) Diagonaal 1 Teken pixel( 1 , 0 ) Teken pixel( 0 , 1 ) Diagonaal 2 Teken pixel( 2 , 0 ) Teken pixel( 1 , 1 ) Teken pixel( 0 , 2 ) Diagonaal 3 Teken pixel( 3 , 0 ) Teken pixel( 2 , 1 ) Teken pixel( 1 , 2 ) Teken pixel( 0 , 3 ) Diagonaal 4 Teken pixel( 3 , 1 ) Teken pixel( 2 , 2 ) Teken pixel( 1 , 3 ) Diagonaal 5 Teken pixel( 3 , 2 ) Teken pixel( 2 , 3 ) Diagonaal 6 Teken pixel( 3 , 3 ) 16 pixels getekend
H * W = 4 * 3 ------------- Diagonaal 0 Teken pixel( 0 , 0 ) Diagonaal 1 Teken pixel( 1 , 0 ) Teken pixel( 0 , 1 ) Diagonaal 2 Teken pixel( 2 , 0 ) Teken pixel( 1 , 1 ) Teken pixel( 0 , 2 ) Diagonaal 3 Teken pixel( 2 , 1 ) Teken pixel( 1 , 2 ) Teken pixel( 0 , 3 ) Diagonaal 4 Teken pixel( 2 , 2 ) Teken pixel( 1 , 3 ) Diagonaal 5 Teken pixel( 2 , 3 ) 12 pixels getekend
Johoo en recht zo die gaat! ... Maar toch een kritische noot. Feitelijk heb ik een kopie van het oorspronkelijke plaatje gemaakt, maar dan met een schuin coördinatenstelsel. Dat schuine coördinatenstelsel wordt vervolgens 'recht' doorlopen om de pixels te tekenen. Keesb's algoritme loopt al pixels tekenend diagonaalgewijs door het origineel heen. Iets meer rekenwerk wellicht, maar beslist minder geheugengebruik. Aan de andere kant biedt mijn model wel meer flexibiliteit. Starten vanaf rechtsonder bijvoorbeeld is slechts een kwestie van achterwaarts itereren over de diagonalen.
|
|
|
Post by Marco Kurvers on Jul 23, 2024 15:50:48 GMT
Ik begrijp dat jullie diagonaal tekenen van boven naar beneden. Ik deed dat van beneden naar boven. Maakt dat met het schrijven van de code nog uit? Wat ik ook vreemd vind is het woord Shared. Nergens dit commando te vinden. Liberty BASIC kent het niet.
Ik moet een aantal keer de code goed bekijken voordat ik zonder spiekbriefje het kan begrijpen en zelf in mijn code kan wijzigen.
|
|
|
Post by memophenon on Jul 23, 2024 16:03:14 GMT
Shared zorgt ervoor dat de Sub of Function toegang krijgt tot de genoemde globale variabelen. Een eigenaardigheidje van QBasic en QuickBASIC, waar ik overigens wel enige waardering voor kan opbrengen. Kiest Liberty BASIC de omgekeerde weg, en moet je daar locale variabelen expliciet als Local declareren? Is ook wat voor te zeggen.
Verder zie ik, voor zover het niet om de grafische fratsen gaat, niet zo veel exotische code in deze thread.
|
|
|
Post by Marco Kurvers on Jul 23, 2024 17:36:34 GMT
Dat dacht ik al, dat het Q(uick)BASIC zou zijn. Als ik in Q(uick)BASIC Shared variabelen wil, dan dimensioneer ik ze altijd bovenaan. Je hoeft het dan niet in de SUB aan te geven.
DIM SHARED variabelenaam AS datatype
Normaal gesproken geef ik ze door als argumenten en parameters. Dat had je ook kunnen doen met de variabelen W en H.
In Liberty BASIC zijn de variabelen in subroutines en functies altijd lokaal. Er is geen LOCAL commando.
Je kunt de code nabootsen met de asterisk '*'. Met het commando LOCATE <y>, <x> kun je de pixels array zonder echte pixels printen.
|
|
|
Post by memophenon on Jul 24, 2024 12:08:07 GMT
Er staat nog een vraag van Marco Kurvers open (gisteren gesteld): Ja, dat maakt uit. Als je de code niet verandert, zal het gedrag evenmin veranderen. In mijn driestappenprogramma is het extreem eenvoudig om de pixels binnen de diagonaal van linksonder naar rechtsboven af te drukken. Het kan op twee manieren.
Manier A: Wissel in stap 2 de geneste iteraties met y en x om. Plaats de buitenste For-Next dus binnen de huidige binnenste For-Next. De drie binnengelegen statements blijven ongewijzigd.
Manier B: Itereer in stap 3 de binnenste lus achterstevoren. Dat wil zeggen, hoog de offset binnen de diagonjaal niet op van laag naar hoog, maar laat deze afnemen van hoog naar laag. Ook hier blijven de twee binnengelegen statements ongewijzigd.
Je kunt beide recepten natuurlijk combineren, maar dan krijg je weer de volgorde die je bij keesb en mij aantrof. Het illustreert wel dat verandering van de code toch tot hetzelfde gedrag kan leiden.
|
|
gaslouk
New Member
Hi from beautiful Greece .
Posts: 16
|
Post by gaslouk on Jul 26, 2024 4:32:52 GMT
Ik begrijp dat jullie diagonaal tekenen van boven naar beneden. Ik deed dat van beneden naar boven. Maakt dat met het schrijven van de code nog uit? Wat ik ook vreemd vind is het woord Shared. Nergens dit commando te vinden. Liberty BASIC kent het niet. Ik moet een aantal keer de code goed bekijken voordat ik zonder spiekbriefje het kan begrijpen en zelf in mijn code kan wijzigen. Hi from beautiful Greece. In Liberty Basic there isn't "Shared". In the first line of your program put "Global H, W".
regard.
|
|
keesb
New Member
Posts: 22
|
Post by keesb on Jul 26, 2024 9:26:57 GMT
Na alle theorie nu een extra flexibel gemaakt voorbeeldprogramma.
|
|
|
Post by Marco Kurvers on Jul 26, 2024 17:04:45 GMT
Hi gaslouk,
Yes, that's what we should do when we come across a Q(uick)BASIC word Shared. I had also thought: might it be better to use the global variables as the first line in your program instead of in a Sub?
|
|
|
Post by memophenon on Jul 27, 2024 12:42:10 GMT
Het programma pixels diagonaal tekenen versie KB.lbf is een mooie illustratie van de zorg die flexibiliteit met zich meebrengt. Het bevat vier versies van de Sub TekenVan??naar??, en als je ook de volgorde waarin de pixels binnen een diagonaal op het scherm worden afgebeeld wilt variëren, kom je uit op acht Subs, samen goed voor 280 regels code. Dat maakt het niet erg aantrekkelijk om deze code te moeten onderhouden. Een leuke uitdaging om daar iets aan te doen. Ik heb hiertoe mijn driestappenprogramma van een paar dagen geleden aangepast door de Sub TekenDiagonaal verregaand te parametriseren, zodat deze op de volgende acht verschillende manieren kan worden aangeroepen voor een plaatje van drie pixels hoog en vier pixels breed: TekenDiagonaal 3, 4, "LB", "neer" TekenDiagonaal 3, 4, "LB", "op" TekenDiagonaal 3, 4, "RO", "neer" TekenDiagonaal 3, 4, "RO", "op" TekenDiagonaal 3, 4, "RB", "neer" TekenDiagonaal 3, 4, "RB", "op" TekenDiagonaal 3, 4, "LO", "neer" TekenDiagonaal 3, 4, "LO", "op" De logica van de drie stappen wordt hiermee: Stap1: N = H + W - 1 If H < W Then L = H Else L = W Dim Diagonalen(N, L)
Stap2: For y = 0 To H - 1 For x = 0 To W - 1 diagNr = y + retro * (H - 1 - 2 * y) + x Diagonalen(diagNr, 0) = Diagonalen(diagNr, 0) + 1 Diagonalen(diagNr, Diagonalen(diagNr, 0)) = y * W + x Next x Next y
Stap3: For diagNr = D0 To D1 Step D2 Print " Diagonaal"; diagNr extra = Diagonalen(diagNr, 0) - 1 For offset = 1 + O0 * extra To 1 + O1 * extra Step O2 element = Diagonalen(diagNr, offset) Print " Teken pixel("; element Mod W; ","; element \ W; ")" Next offset Next diagNr
De waarden voor de variabelen retro, D0, D1 en D2 zijn voordat het itereren begint afgeleid uit de voorlaatste Sub-parameter ( Hoek$), terwijl die voor O0, O1 en O2 voortkomen uit de laatste parameter ( Richting$). De gehele Sub TekenDiagonaal beslaat 73 regels. Scheelt dus bijna een factor 4 met de 280 die ik hierboven noemde. Zo'n ombouwoperatie kan op het algoritme van keesb en Marco Kurvers waarschijnlijk ook wel worden toegepast. Ik laat dat over aan de betrokken auteurs. Nog wel een opmerking over het bijgesloten 8in1.bas. Dat begint met de regels: $ScreenHide $Console _Dest _Console Die had ik nodig om QB64 Phoenix Edition 3.13.1 naar de juiste console te laten schrijven. Wanneer je het programma in het originele QBasic of QuickBASIC wilt draaien, moet je ze weglaten.
|
|