soft drawing: lijnen en ellipsen


download programma
bekijk de source code
download Delphi-7 project

Tekenen van "zachte" lijnen en ellipsen

Hierboven staat een afbeelding van het demo programma,
het rechterbeeld toont een tienvoudige vergroting van de linker bovenhoek.

Het "zachte" effect wordt verkregen door de pen pixels uit te smeren.
Het plaatje hieronder geeft het verschil duidelijk weer.
Bovenaan de zachte lijn, eronder de trappetjesvorm doordat per geheel pixel wordt getekend.


De theorie: rechte lijnen

Onderscheid wordt gemaakt tussen horizontaal- en vertikaal georiënteerde lijnen.
De horizontale hebben een hellingshoek van -45..45 graden,
de vertikale van -90..-45 of 45..90 graden.

Pixels worden verdeeld in 4*4 subpixels.
Onderstaand plaatje geeft de pen weer voor het tekenen van horizontaal georienteerde lijnen:
Afgebeeld zijn 2 rijen van elk 4 pixels.
De pen (zwart) is 0,25 pixel breed en 1 pixel hoog.
Bij het tekenen van een lijn gaat pen met stapjes van 0,25 pixel naar rechts.
De bijbehorende y waarde wordt berekend en afgerond op 0,25 pixel.

Bij vertikaal georiënteerde lijnen ziet het er zo uit:
De zwarte pen is 1 pixel breed en 0,25 pixel hoog.
Bij het tekenen van de lijn gaat de pen met stapjes van 0,25 pixel omlaag,
de bijbehorende y waarde wordt berekend en afgerond op 0,25 pixel.

Tekeningen worden zichtbaar op het canvas van bijvoorbeeld een paintbox.
Daarop rechtstreeks tekenen is niet handig omdat het heel traag verloopt.
Tekenen in een bitmap gaat veel sneller.
Die bitmap moet dan later naar de paintbox worden gekopieerd.

Het probleem is hier, dat we de pen moeten afbeelden door steeds 4 subpixels te kleuren.
Die subpixels hoeven niet binnen eenzelfde pixel te liggen.
Per pixel moeten we aangeven welke subpixels gekleurd zijn.
Daarvoor is een twee dimensionaal array[..,..] genaamd blender van het type word.
Is een subpixel gekleurd, dat wordt een bit in het blender word de waarde "1" gegeven.
Het blender array heeft dezelfde afmetingen als de bitmap waarin we kleuren.

Het tekenen gaat in drie stappen:
    1. bits in array blender worden op "1" gezet als de pen eroverheen gaat
    2. het blender array wordt gescand en de bitmap bijgewerkt
    3. de bitmap wordt naar een canvas gekopieerd
punt 2 :
Het aantal "1" bits per word / 16 bepaalt de invloed van de pen.
Bij waarde 16 krijgt het pixel de kleur van de pen, bij waarde 5 is dat 5/16 deel
van de pen en 11/16 deel van de originele waarde.
Hieronder staat de relatie tussen blender bits en subpixels:

Het programma

Centraal staan twee prodedures
    1. procedure Qpixel(x,y : single);
    2. procedure procblendRect;

1.
De parameters (x,y) zijn van het type single, om gedeeltelijk over pixels heen te kunnen schrijven.
Afhankelijk van de oriëntatie (horizontaal of vertikaal) wordt de pen gekozen.
Deze procedure verandert per pixel een word in array blender.

2.
Rechthoek blendRect omvat het gebied waarin werd getekend.
ProcBlendRect scant deze rechthoek van array blender en wijzigt de overeenkomstige
pixels in bitmap bm.

Zie de source code voor meer details.

Procedure Softline(x1,y1,x2,y2 : smallInt) tekent een soft lijn van (x1,y1) naar (x2,y2).
Hierbij wordt Qpixel aangeroepen en aan het einde procBlendRect.
De pen beweegt altijd van links naar rechts.
Als x1 > x2 dan worden de coördinaten vooraf verwisseld.

Ellipsen

Procedure SoftEllipse(x1,y1,x,y2 : smallInt) tekent een soft ellips binnen
de rechthoek (x1,y1) ---> (x2,y2).

Ook hier worden QPixel( ) en procBlendRect aangeroepen.

Een probleem is nog de keuze van de pen, die immers afhankelijk is van de orientatie.
De bogen van de ellips moeten worden opgedeeld in 2 horizontale- en twee vertikale gedeeltes.
De scheiding hiertussen is het punt waar de ellips een raaklijn heeft met helling -1.

De algemene formule van een ellips met lengte 2a en breedte 2b is
    (x/a)2 + (y/b)2 = 1
Denk daarbij aan een cirkel met straal 1, die heeft als vergelijking : x2+y2= 1
Rekken we de cirkel horizontaal met een factor a uit en vertikaal met b, dan ontstaat de ellips.
(sx,sy) is het omslagpunt tussen horizontale- en vertikale oriëntatie.

De ellips wordt getekend door vanuit (0,0) x met stapjes van 0,25 te verhogen tot sx en
te verlagen tot -sx.
Dan wordt de vertikale pen geselecteerd met stapjes van 0,25 van 0 tot sy en 0 tot -sy.
Steeds wordt daarbij de y of x waarde berekend en Qpixels(..,..) aangeroepen.

Zie de source listing voor details.