It looks like you're new here. If you want to get involved, click one of these buttons!
Hi all,
Below you can find my take on a function for drawing dashed lines. Now I'm just curious if any of you perhaps know a shorter, more efficient way of doing this?
function draw()
background(255)
xx,yy = CurrentTouch.x,CurrentTouch.y+50
noStroke()
fill(255, 0, 0, 255)
ellipse(xx, yy, 20)
stroke(0)
strokeWidth(4)
lineCapMode(SQUARE)
dashed(0,0,xx,yy, 20)
end
function dashed(x1, y1, x2, y2, seg)
local length = math.sqrt((x2-x1)^2 + (y2-y1)^2)
-- n, integer number of segements in length
local n = math.floor(length/seg)
local angle = math.atan((y2-y1)/(x2-x1))
-- dx, dy, leftover length shorter than segmentsize seg
local dx = (length-n*seg)*math.cos(angle)
local dy = (length-n*seg)*math.sin(angle)
local u1,v1,u2,v2
if length-n*seg>=seg/2 then
-- Draw extra segment if leftover is long enough
m = 1
else
-- Else, draw a shorter ending segment
m = 0
u1 = x1 + (x2-x1-dx)
v1 = y1 + (y2-y1-dy)
u2,v2 = x2,y2
line(u1,v1,u2,v2)
end
-- Draw all the line segments
for i = 0,n-1+m do
u1 = x1 + i/n*(x2-x1-dx)
v1 = y1 + i/n*(y2-y1-dy)
u2 = x1 + (i+.5)/n*(x2-x1-dx)
v2 = y1 + (i+.5)/n*(y2-y1-dy)
line(u1,v1,u2,v2)
end
end
Comments
If the lines have to all be the same size, I suggest a texture with a tile map on a mesh. Otherwise make a variable number called n and check if n is a multiple of 2 by doing
This will draw a line every other time creating a dashed line, sizes may vary a lot.
Not sure about the speed difference, but I made a much smaller function with the same result using some built-in functions to calculate things in less lines.
@Kjell Modulo is your friend here. Figure out how long a dash and a break are and modulo by that number. Then draw or not draw according to where in the pattern you are. E.g. if you want a 10-point dash and 5-point space, then do (pseudocode)
You can use a shader, leave it as an exercise to fix colors and width
Haha, it seems that my code doesn't even work right when
x2,y2 < x1,y1
, so I'm gonna take a good look at all of your options.Edit: I'm gonna go with @SkyTheCoder's way here, I didn't really think of just using the built-in vector functions. Looking back, it's amazing how I managed to write so much code to accomplish this.
@tnlogy Your code seems to work fine to, but I'm not that familiar with shaders yet, so I rather not use them. But in the end, are meshes a faster way of drawing lines? Or is the line function of Codea already a mesh at heart?
Also, thank you all for your input!
Yes, meshes are faster according to earlier tests, I think line is implemented in a shader, but I guess it is slower since it handles many special cases such as cap mode? Also, if you want to draw a line for several frames, you can store the mesh value m in my example and only call m:draw() in the draw function. Or add thousands of line to id with addRect. You can return to the code if you run into performance issues.
A fragment shader as above is called for every pixel on the rectangle I've defined with a vTexCoord going from x = 0 to x=1. Probably better to define a complementary color than to use discard, since it is a bit slower than to draw the pixel.
@tnlogy oh! You can draw negative colors to the screen with shaders? What happens if the result is <0 or >255?
@Jmv38 - shaders automatically restrict the result to be between 0 and 1 (as a fraction of 255)
@ignatz cool!
@Jmv38 - yes and no. This restriction can lead to false colours.
eg if you get an answer of (510, 100, 100), then restricting the color gives you (255, 100, 100), which dramatically reduces just the red.
Instead, you could scale all the numbers down to get (255, 50, 50)
But I'm not sure there is any perfect way of handling boundary conditions.