Drawing lines of variable thickness
Drawing lines of variable thickness
Hello all,
Have recently returned to programming after too many years in the wilderness and am new to PureBasic. What an excellent language.
Have made rapid gains in the space of a few weeks thanks to all the tips and snippets within these forums.
To the reason I am posting.
I am working upon what is becoming quite a nice little painting program which I am using as a learning platform.
Is it possible to draw / plot a line of variable thickness (rather than 1 pixel wide) ? I suspect that if it is possible then it might involve the Win API (which I am slowly coming to understand through these forums and PB itself.) Unfortunately, I don't know enough about hdc's, device contexts, brushes etc. to set about tackling this.
I am prepared to code such a procedure directly in PB but I can't help thinking that, with a little persuasion, Windows should be able to perform this task!
Thanks and keep up the excellent work.
Have recently returned to programming after too many years in the wilderness and am new to PureBasic. What an excellent language.
Have made rapid gains in the space of a few weeks thanks to all the tips and snippets within these forums.
To the reason I am posting.
I am working upon what is becoming quite a nice little painting program which I am using as a learning platform.
Is it possible to draw / plot a line of variable thickness (rather than 1 pixel wide) ? I suspect that if it is possible then it might involve the Win API (which I am slowly coming to understand through these forums and PB itself.) Unfortunately, I don't know enough about hdc's, device contexts, brushes etc. to set about tackling this.
I am prepared to code such a procedure directly in PB but I can't help thinking that, with a little persuasion, Windows should be able to perform this task!
Thanks and keep up the excellent work.
Don't know about WinAPI, but you can use a series of ovals or rects do draw thicker line.. :roll:
-Lars
-Lars
AMD Athlon XP2400, 512 MB RAM, Hercules 3D Prophet 9600 256MB RAM, WinXP
PIII 800MHz, 320 MB RAM, Nvidia Riva Tnt 2 Mach 64 (32MB), WinXP + Linux
17" iMac, 1.8 GHz G5, 512 MB DDR-RAM, 80 GB HD, 64 MB Geforce FX 5200, SuperDrive, OSX
Re: Drawing lines of variable thickness
Hi srod:
Maybe this helps.
Maybe this helps.
Is it possible to draw / plot a line of variable thickness
Code: Select all
Procedure Lin(x,y,x1,y1,Gros,Color)
hDC=GETDC_(WindowID())
pen=CreatePen_(#Ps_Solid,GROS,color)
hPenOld=SelectObject_(hDC,pen)
MoveToEx_(hDC,x,y,0):LineTo_(hDC,x1,y1)
DeleteObject_(pen)
DeleteObject_(hPenOld)
EndProcedure
;_____________________________________________
_X=GetSystemMetrics_(#SM_CXSCREEN)-8 : _Y=GetSystemMetrics_(#SM_CYSCREEN)-68
OpenWindow(0,0,0,_X,_Y,#WS_OVERLAPPEDWINDOW | #WS_MAXIMIZE,"")
lin(50,200,300,400,15,#red)
MessageRequester("","DONE",0)
Excellent. I was (with the aid of Petzold's book) almost there and experimenting with the very same function calls. You've just saved me a whole heap of trial and error!
Problem now is that I am drawing on an image. Will the same code work if I replace the window handle with that of an image ?
Thanks.
Problem now is that I am drawing on an image. Will the same code work if I replace the window handle with that of an image ?
Thanks.
Don't know why you're thanking me.. it's Einander who had the cool function..
-Lars

-Lars
AMD Athlon XP2400, 512 MB RAM, Hercules 3D Prophet 9600 256MB RAM, WinXP
PIII 800MHz, 320 MB RAM, Nvidia Riva Tnt 2 Mach 64 (32MB), WinXP + Linux
17" iMac, 1.8 GHz G5, 512 MB DDR-RAM, 80 GB HD, 64 MB Geforce FX 5200, SuperDrive, OSX
Re: Drawing lines of variable thickness
Has anyone found a solution which can be used to draw thick lines on images as well as to the printer? Maybe even OS independent?
All non-windows specific procedures for drawing lines in the forum which work also for printing have some disadvantages (very slow, not working for all angles or using the faulty circle command etc.)
All non-windows specific procedures for drawing lines in the forum which work also for printing have some disadvantages (very slow, not working for all angles or using the faulty circle command etc.)
Code: Select all
Procedure thickLineXY(start_x,start_y,end_x,end_y,thickness,whatcolor)
thickness>>1
err_x=0
err_y=0
inc_x=0
inc_y=0
delta_x=end_x - start_x;
delta_y=end_y - start_y;
If (delta_x>0)
inc_x=1
ElseIf (delta_x=0)
inc_x=0
Else
inc_x=-1
EndIf
If (delta_y>0)
inc_y=1
ElseIf (delta_y=0)
inc_y=0
Else
inc_y=-1
EndIf
delta_x=Abs(delta_x);
delta_y=Abs(delta_y);
If (delta_x>delta_y)
distance=delta_x;
Else
distance=delta_y;
EndIf
For xyz=0 To distance+1 Step 1
; modified to place a circle at the pixel location to get a thick line
;Plot(start_x,start_y,whatcolor)
Circle(start_x,start_y,thickness,whatcolor)
err_x=err_x + delta_x
err_y=err_y + delta_y
If (err_x>distance)
err_x=err_x - distance
start_x=start_x + inc_x
EndIf
If (err_y>distance)
err_y=err_y - distance
start_y=start_y +inc_y
EndIf
Next
EndProcedure
Procedure ClipLine(x1.w, y1.w, x2.w, y2.w, color,thickness.w)
; Draw line here with stupid PB Line command syntax
w=x2 - x1
h=y2 - y1
If wh
w=w+1
Else
h=h+1
If w=h
w=w+1
EndIf
EndIf
extra=0
For i.w=1 To thickness
If w>h
y1=y1+extra
Else
x1=x1+extra
EndIf
Line(x1, y1, w, h,color)
If extra<0
extra=extra-1
Else
extra=extra+1
EndIf
extra=-extra
Next
EndProcedure
ProcedureDLL.l ColorBlending(Color1.l, Color2.l, Blend.f)
Protected Red, Green, Blue, Red2, Green2, Blue2
Red=Color1 & $FF
Green=Color1 >> 8 & $FF
Blue=Color1 >> 16
Red2=Color2 & $FF
Green2=Color2 >> 8 & $FF
Blue2=Color2 >> 16
Red=Red * Blend + Red2 *(1-Blend)
Green=Green * Blend + Green2 *(1-Blend)
Blue=Blue * Blend + Blue2 *(1-Blend)
ProcedureReturn(Red | Green <<8 | Blue << 16)
EndProcedure
Procedure NormalL(X,Y, x3, y3, Color, Thickness=1)
Width=x3-X
Hight=y3-Y
Protected SignX, SignY, n, nn, Thick.f, x2.f, y2.f, Color_Found.l, Application.f, Hypo.f
If Width >= 0
SignX=1
Else
SignX=-1
Width=- Width
EndIf
If Hight >= 0
SignY=1
Else
SignY=-1
Hight=- Hight
EndIf
Thick.f=Thickness / 2
Hypo.f=Sqr(Width * Width + Hight * Hight)
CosPhi.f=Width / Hypo
SinPhi.f=-Sin(ACos(CosPhi))
For n=-Thickness To Width + Thickness
For nn=-Thickness To Hight + Thickness
x2=n * CosPhi - nn * SinPhi
y2=Abs(n * SinPhi + nn * CosPhi)
If y2 <= Thick + 0.5
Application= 0.5 + Thick - y2
If Application>1
Application=1
EndIf
If x2>-1 And x2<Hypo + 1
If x2<0
Application *(1 + x2)
ElseIf x2>Hypo
Application *(1 - x2 + Hypo)
EndIf
Else
Application=0
EndIf
If Application>0
If Application<1
Color_Found=Point(X + n * SignX, Y + nn * SignY)
Plot(X + n * SignX, Y + nn * SignY, ColorBlending(Color, Color_Found, Application))
Else
Plot(X + n * SignX, Y + nn * SignY, Color)
EndIf
EndIf
EndIf
Next
Next
EndProcedure
Procedure LineAA(X, Y, Width, Hight, Color, Thickness=1)
Protected SensX, SensY, n, nn, Epaisseur.f, x2.f, y2.f, Couleur_Fond.l, Application.f, Distance.f
; On mets la droite toujours dans le même sens pour l'analyse
; La sauvegarde du sens permettra de dessiner la droite ensuite dans le bon sens
If Width >= 0
SensX=1
Else
SensX=-1
Width=- Width
EndIf
If Hight >= 0
SensY=1
Else
SensY=-1
Hight=- Hight
EndIf
; Demi épaisseur de la ligne
Epaisseur.f=Thickness / 2
; calcul pour le changement de repère qui permet de connaitre l'épaisseur du trait et de gérer l'AA
Distance.f=Sqr(Width * Width + Hight * Hight)
CosAngle.f=Width / Distance
SinAngle.f=-Sin(ACos(CosAngle))
; Dessin de la ligne
For n=-Thickness To Width + Thickness
For nn=-Thickness To Hight + Thickness
; changement de base
; les y représentent l'épaisseur de la ligne
x2=n * CosAngle - nn * SinAngle
y2=Abs(n * SinAngle + nn * CosAngle)
If y2 <= Epaisseur + 0.5
Application= 0.5 + Epaisseur - y2
If Application>1
Application=1
EndIf
If x2>-1 And x2<Distance + 1
If x2<0
Application *(1 + x2)
ElseIf x2>Distance
Application *(1 - x2 + Distance)
EndIf
Else
Application=0
EndIf
If Application>0
If Application<1
Couleur_Fond=Point(X + n * SensX, Y + nn * SensY)
Plot(X + n * SensX, Y + nn * SensY, ColorBlending(Color, Couleur_Fond, Application))
Else
Plot(X + n * SensX, Y + nn * SensY, Color)
EndIf
EndIf
EndIf
Next
Next
EndProcedure
OpenWindow(0, 0, 0, 500, 500, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget)
CreateImage(0, 500, 500)
StartDrawing(ImageOutput(0))
#repeat=99
#angle=35
For i=0 To 3
t=ElapsedMilliseconds()
For m=0 To #repeat
p=0
For n=0 To #angle
If n&3=0 : p+1 : EndIf
Select i
Case 0
ClipLine(120,120,120+Sin(n*#PI/#angle*2)*100,120+Cos(n*#PI/#angle*2)*100,#Red,p); 1s
Case 1
thickLineXY(350,120,350+Sin(n*#PI/#angle*2)*100,120+Cos(n*#PI/#angle*2)*100,p,#Red); 15s
Case 2
NormalL(120,350,120+Sin(n*#PI/#angle*2)*100,350+Cos(n*#PI/#angle*2)*100,#Red,p); 15s
Case 3
LineAA(350,350,Sin(n*#PI/#angle*2)*100,Cos(n*#PI/#angle*2)*100,#Red,p); 15s
EndSelect
Next n
Next m
t-ElapsedMilliseconds()
Select i
Case 0
DrawText(200,30,Str(-t))
Case 1
DrawText(430,30,Str(-t))
Case 2
DrawText(200,240,Str(-t))
Case 3
DrawText(430,240,Str(-t))
EndSelect
Next i
StopDrawing()
ImageGadget(0, 0, 0, 300, 300, ImageID(0))
Repeat
Event=WaitWindowEvent()
Until Event=#PB_Event_CloseWindow
Re: Drawing lines of variable thickness
Wow, one of my first postings! 

I may look like a mule, but I'm not a complete ass.
Re: Drawing lines of variable thickness
Hi
PureBasic now has a range of functions and 3D animations very magical
but I think it's time to power with PB native 2DDrawing and CanvasGadget
draw a BOX with an angle
draw an Ellipse with an angle
draw an ARC with an angle would welcome
draw a LINE mode with Thickness and Styles
the thicknesses and styles also applied to ARC BOX ELLIPSE
Goodday
PureBasic now has a range of functions and 3D animations very magical
but I think it's time to power with PB native 2DDrawing and CanvasGadget
draw a BOX with an angle
draw an Ellipse with an angle
draw an ARC with an angle would welcome
draw a LINE mode with Thickness and Styles
the thicknesses and styles also applied to ARC BOX ELLIPSE
Goodday
Re: Drawing lines of variable thickness
I thought to use a workaround meanwhile, by drawing multiple standard lines (instead of the slow and ugly circles), but my quick try has holes like a cheese 

Code: Select all
Procedure MyLineXY(x1,y1,x2,y2,Color,Thickness=1)
#FineShift=10
#FineMore=1
#FineOne=1<<(#FineShift-#FineMore-1)
#FineTwo=2<<(#FineShift-#FineMore-1)
Protected n,h,w,sx,sy
Protected hypo.f,dx.f,dy.f
w=x2-x1
h=y2-y1
If w>=0
sx=1
Else
sx=-1
w=-w
EndIf
If h>= 0
sy=1
Else
sy=-1
h=-h
EndIf
hypo.f=Sqr(w*w+h*h)
dy=w/hypo
dx=-Sin(ACos(dy))*sx
dy=dy*sy
x1=x1<<#FineShift-(dx*Thickness)/#FineOne
y1=y1<<#FineShift-(dy*Thickness)/#FineOne
x2=x2<<#FineShift-(dx*Thickness)/#FineOne
y2=y2<<#FineShift-(dy*Thickness)/#FineOne
x0=dx*#FineTwo
y0=dy*#FineTwo
For n=0 To Thickness<<#FineMore
LineXY(x1>>#FineShift,y1>>#FineShift,x2>>#FineShift,y2>>#FineShift,#Blue)
x1+x0
y1+y0
x2+x0
y2+y0
Next n
EndProcedure