Draw a dashed Line

Share your advanced PureBasic knowledge/code with the community.
coco2
Enthusiast
Enthusiast
Posts: 368
Joined: Mon Nov 25, 2013 5:38 am
Location: Australia

Draw a dashed Line

Post by coco2 »

I got most of the code for the Bresenham's Line from Rosettacode. I needed it for an image editor to make the "selection" lines.

Code: Select all

Procedure DrawDashedLineXY(x1.i, y1.i, x2.i, y2.i, col1.i, col2.i, Dash_Length.i, Offset.i = 0)
  ; Dash_Length must be 1 or greater
  ; Offset can be 0 to (2 * Dash_Length) - 1
  Protected Steep.i, DeltaX.i, DeltaY.i, YStep.i, XStep.i, Error.i
  Protected x.i, y.i, cc.i, cs.i, c.i
  Protected Max_Offset.i
  If Abs(y2 - y1) > Abs(x2 - x1);
    steep =#True 
    Swap x1, y1
    Swap x2, y2
  EndIf    
  If x1 > x2 
    Swap x1, x2
    Swap y1, y2
  EndIf 
  DeltaX = x2 - x1
  DeltaY = Abs(y2 - y1)
  Error = DeltaX / 2
  y = y1
  If y1 < y2  
    YStep = 1
  Else
    YStep = -1 
  EndIf
  If Dash_Length < 1 : Dash_Length = 1 : EndIf
  Max_Offset = Dash_Length * 2 - 1
  If Offset > Max_Offset : Offset = Max_Offset: EndIf
  If Offset < 0 : Offset = 0 : EndIf
  cc = Offset ; colour counter
  If cc > Dash_Length - 1 : cs = 1 : Else : cs = 0 : EndIf
  For x = x1 To x2
    If cs = 0 : c = col1 : Else : c = col2 : EndIf
    If Steep 
      Plot(y, x, c)
    Else 
      Plot(x, y, c)
    EndIf
    Error = Error - DeltaY
    If Error < 0 
      y = y + YStep
      Error = Error + DeltaX
    EndIf
    cc = cc + 1
    If cc = Dash_Length
      cs = 1 - cs
    EndIf
    If cc = Dash_Length * 2
      cc = 0
      cs = 1 - cs
    EndIf
  Next 
  ProcedureReturn cc ; return the offset so drawing can continue
EndProcedure

Define Event.i, Quit.i, Offset.i
OpenWindow(0,300, 300, 640, 480, "Test", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget)
CreateImage(0, 640, 480, 32, RGB(150, 150, 150))
CreateImage(1, 640, 480, 32, RGB(150, 150, 150))
Offset = 0
Repeat
  StartDrawing(ImageOutput(0))
  DrawingMode(#PB_2DDrawing_AllChannels)
  DrawDashedLineXY(100, 100, 300, 100, RGBA(0,0,0,255), RGBA(0,0,0,0), 8, Offset)
  DrawDashedLineXY(100, 110, 300, 110, RGBA(0,0,0,255), RGBA(255,255,255,255), 8, 0)
  DrawDashedLineXY(100, 120, 300, 120, RGBA(0,0,0,255), RGBA(0,0,0,0), 8, 4)
  DrawDashedLineXY(100, 130, 300, 130, RGBA(0,0,0,255), RGBA(0,0,0,0), 8, 13)
  DrawDashedLineXY(100, 150, 300, 400, RGBA(0,0,0,255), RGBA(0,0,0,0), 4)
  DrawDashedLineXY(500, 100, 500, 400, RGBA(0,0,0,255), RGBA(0,0,0,0), 8, Offset)
  LineXY(100, 160, 300, 160, RGBA(0,0,0,0))
  StopDrawing()
  StartDrawing(WindowOutput(0))
  DrawingMode(#PB_2DDrawing_AllChannels)
  DrawImage(ImageID(1), 0, 0)
  DrawAlphaImage(ImageID(0), 0, 0)
  StopDrawing()
  Delay(100)
  Offset = Offset + 1
  If Offset = 16 : Offset = 0 : EndIf
  Repeat
  Event = WaitWindowEvent(10)
  Select Event
    Case #PB_Event_CloseWindow
      Quit = 1
  EndSelect
  Until Event = 0
Until Quit = 1
Last edited by coco2 on Sat Feb 03, 2018 2:33 am, edited 4 times in total.
User avatar
Demivec
Addict
Addict
Posts: 4085
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Draw a dashed Line

Post by Demivec »

You probably could also use the PureBasic's Vector library for this.
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Re: Draw a dashed Line

Post by walbus »

coco2
Enthusiast
Enthusiast
Posts: 368
Joined: Mon Nov 25, 2013 5:38 am
Location: Australia

Re: Draw a dashed Line

Post by coco2 »

Demivec, I had a look at the vector routine and it appears you can't disable anti-aliasing and also you can't specify a dash offset.

Walbus very nice, I couldn't find your post when I searched for "dashed line". How do you get the dashes to go "around corners"? In my code I return the remaining offset and this can be passed to the next call to the line procedure to continue on the line from where the dashes left off.

Also, I figured out how to show transparent dash colours so I updated the code.
mestnyi
Addict
Addict
Posts: 995
Joined: Mon Nov 25, 2013 6:41 am

Re: Draw a dashed Line

Post by mestnyi »

And I did so may it be useful to you :)

Code: Select all

Procedure DrawFilterCallback(X, Y, SourceColor, TargetColor)
  Protected Dot.b=4, line.b = 10, Color, Length.b = (Line+Dot*2+1)
  Static Len.b
  
  If ((Len%Length)<line Or (Len%Length)=(line+Dot))
    If (Len>(Line+Dot)) : Len=0 : EndIf
    Color = SourceColor
  Else
    Color = TargetColor
  EndIf
  
  Len+1
  ProcedureReturn Color
EndProcedure

Define Event.i, Quit.i, Offset.i
OpenWindow(0,300, 300, 640, 480, "Test", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget)
CreateImage(0, 640, 480, 32, RGB(150, 150, 150))
CreateImage(1, 640, 480, 32, RGB(150, 150, 150))
Offset = 0

Define StartX=50,StartY=50,LastX=150,LastY=150
; Repeat
  StartDrawing(ImageOutput(0))
    DrawingMode(#PB_2DDrawing_Outlined|#PB_2DDrawing_CustomFilter)
                  CustomFilterCallback(@DrawFilterCallback())
                  Box(StartX,StartY,LastX,LastY, $E23A2B)
                
; ; ;   DrawingMode(#PB_2DDrawing_AllChannels)
; ; ;   DrawDashedLineXY(100, 100, 300, 100, RGBA(0,0,0,255), RGBA(0,0,0,0), 8, Offset)
; ; ;   DrawDashedLineXY(100, 110, 300, 110, RGBA(0,0,0,255), RGBA(255,255,255,255), 8, 0)
; ; ;   DrawDashedLineXY(100, 120, 300, 120, RGBA(0,0,0,255), RGBA(0,0,0,0), 8, 4)
; ; ;   DrawDashedLineXY(100, 130, 300, 130, RGBA(0,0,0,255), RGBA(0,0,0,0), 8, 13)
; ; ;   DrawDashedLineXY(100, 150, 300, 400, RGBA(0,0,0,255), RGBA(0,0,0,0), 4)
; ; ;   DrawDashedLineXY(500, 100, 500, 400, RGBA(0,0,0,255), RGBA(0,0,0,0), 8, Offset)
; ; ;   LineXY(100, 160, 300, 160, RGBA(0,0,0,0))
  StopDrawing()
  StartDrawing(WindowOutput(0))
  DrawingMode(#PB_2DDrawing_AllChannels)
  DrawImage(ImageID(0), 0, 0)
  ;DrawAlphaImage(ImageID(0), 0, 0)
  StopDrawing()
;   Delay(100)
;   Offset = Offset + 1
;   If Offset = 16 : Offset = 0 : EndIf
;   
  Repeat
  Event = WaitWindowEvent(10)
  Select Event
    Case #PB_Event_CloseWindow
      Quit = 1
  EndSelect
;   Until Event = 0
Until Quit = 1
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Re: Draw a dashed Line

Post by walbus »

Hi coco2
Because of the internal bit rotation it looks as if they are going around the corners
You don't have to do anything about it.
Post Reply