December 04, 2020, 11:24:48 AM

Author Topic: [bmx] Draw evenly spaced dots along a line by Warpy [ 1+ years ago ]  (Read 382 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
Title : Draw evenly spaced dots along a line
Author : Warpy
Posted : 1+ years ago

Description : Suppose you've got a set of points you want to join up with dotted lines, spaced a certain distance apart.

Bresenham isn't the right algorithm for this - the gaps between the dots are bound to be a lot bigger than single pixels, so 'stupid' linear interpolation should do the job satisfactorily.

However, if you want to make sure you definitely draw the start and end points of a line, as well as dots in between, or if you want to draw a line made up of several segments, it gets a bit more complicated.

Here are two methods:

The first tries to draw each line segment so that its start and end points get a dot, and then it changes the size of the gaps slightly so that all the dots are evenly spaced right up to the end.

The second goes along between the points, drawing dots at the given distance apart from each other. It might not draw dots exactly on the given points, but the dots are always exactly the right distance apart.


Code :
Code: BlitzMax
  1. Strict
  2.  
  3. 'this method will draw each line segment individually
  4. 'it will change the gap slightly so that the dots are spread evenly along each segment
  5. 'it always draws a dot on each corner and endpoint
  6. Function drawdots1(points#[], gap#)
  7.         If Len(points)<4 Return 'need at least two pairs of co-ordinates
  8.        
  9.         Local sx#,sy#,ex#,ey#
  10.         Local dx#,dy#,d#,steps,tgap#
  11.         Local x#,y#
  12.        
  13.         DrawDot points[0],points[1]     'draw a dot at the start of the line
  14.        
  15.         For Local i=0 To Len(points)-3 Step 2           'draw each line segment
  16.        
  17.                 sx=points[i]                    'get start and end of this segment
  18.                 sy=points[i+1]
  19.                 ex=points[i+2]
  20.                 ey=points[i+3]
  21.                                
  22.                 dx# = ex-sx                     'calculate a vector in the direction of the line, so we can get the distance
  23.                 dy# = ey-sy
  24.                 d# = Sqr(dx*dx+dy*dy)
  25.                
  26.                 steps = round(d/gap)    'work out how many dots to draw (distance between the points, divide by the desired gap size). Round to nearest whole number
  27.                 tgap# = d/steps         'work out what the gap needs to be to space the calculated number of needed dots evenly
  28.                
  29.                 dx:*tgap/d                      'work out the vector between each dot
  30.                 dy:*tgap/d
  31.                
  32.                 For Local j=1 To steps
  33.                         x# = sx+j*dx    'calculate the dot's position by adding the gap vector to the position of the start of the line
  34.                         y# = sy+j*dy
  35.                         DrawDot x,y     'draw a dot
  36.                 Next
  37.         Next
  38. End Function
  39.  
  40. 'this method will draw dots evenly spaced along the whole set of lines
  41. 'it might not draw dots on the corners.
  42. Function drawdots2(points#[],gap#)
  43.         If Len(points)<4 Return 'need at least two pairs of co-ordinates
  44.  
  45.         Local sx#,sy#,ex#,ey#
  46.         Local dx#,dy#,d#,tstep#
  47.         Local x#,y#
  48.        
  49.         Local t#=0      't will keep track of how far along each line segment we are - 0 for at the start, 1 for at the end
  50.        
  51.         For Local i=0 To Len(points)-3 Step 2   'go through the line segments
  52.        
  53.                 sx=points[i]                    'get start and end of this segment
  54.                 sy=points[i+1]
  55.                 ex=points[i+2]
  56.                 ey=points[i+3]
  57.        
  58.                 dx = ex-sx                      'work out a vector in the direction of the line
  59.                 dy = ey-sy
  60.                 d = Sqr(dx*dx+dy*dy)    'work out the length of the line
  61.                
  62.                 tstep# = gap/d          'work out what fraction of the line each gap represents
  63.                
  64.                 While t<1               'draw dots until we reach the end of the line
  65.                
  66.                         x = sx+dx*t     'work out the position of the dot by multiplying the vector by t
  67.                         y = sy+dy*t
  68.                         DrawDot x,y     'draw the dot
  69.                         t:+tstep                'increase t by the amount corresponding to a gap
  70.                 Wend
  71.                
  72.                 t:-1                            'when we reach the end of the line, t might be more than 1, meaning we didn't manage to get a whole gap in at the end
  73.                                                 'subtract 1 from t, and carry over the remainder to the next line segment
  74.         Next
  75.        
  76.         DrawDot ex,ey                   'draw the end point of the line.
  77. End Function
  78.  
  79. Function DrawDot(x#,y#)
  80.         DrawOval x-2,y-2,4,4
  81. End Function
  82.  
  83. Function Round(f#)      'round a floating point number to the nearest whole number
  84.         Local i = Floor(f)
  85.         If f-i>=.5
  86.                 Return i+1
  87.         Else
  88.                 Return i
  89.         EndIf
  90. End Function
  91.  
  92.  
  93. Graphics 800,600,0
  94. Local points#[]
  95. Local mode=0
  96. Local gapsize#=20
  97.  
  98. While Not (KeyHit(KEY_ESCAPE) Or AppTerminate())
  99.         DrawText "Click the mouse!",0,0
  100.         DrawText "Right-click to change methods",0,15
  101.         DrawText "Press up/down to change gap size",0,30
  102.  
  103.         If MouseHit(1)
  104.                 points :+ [Float(MouseX()),Float(MouseY())]
  105.                 If Len(points)>16
  106.                         points=points[2..]
  107.                 EndIf
  108.         EndIf
  109.        
  110.         If MouseHit(2)
  111.                 mode=1-mode
  112.         EndIf
  113.        
  114.         gapsize :+ (KeyDown(KEY_UP)-KeyDown(KEY_DOWN))*.25
  115.         If gapsize<1 gapsize=1
  116.         DrawText "Gap Size: "+gapsize,400,15
  117.        
  118.         If mode=0
  119.                 drawdots1(points,gapsize)
  120.                 DrawText "Using Method 1",400,0
  121.         Else
  122.                 drawdots2(points,gapsize)
  123.                 DrawText "Using Method 2",400,0
  124.         EndIf
  125.         Flip
  126.         Cls
  127. Wend


Comments : none...

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal