Page 1 of 1

Railway Track

Posted: Sat Sep 18, 2021 8:59 pm
by darkfrei
Hi all!

There is my try to make railway track, where it's path is defined as love.graphics's line.

Used functions:
Get offset polyline - the right and left rails are just the same line as defined, but with offset :)
Get Points Along Line - every tie must be on the same distance, but the defined polyline can have long or short segments.

Code: Select all

 -- gives points on the line every gap; also returns tangents in this points
function get_points_along_line (line, gap)
	local points = {}
	local tangents = {}
	local rest = gap/2 -- rest is gap to start point on this section
	local x1, y1, x2, y2, dx, dy = line[1],line[2]
	for i=3, #line-1, 2 do
		x2, y2 = line[i],line[i+1]
		dx, dy = x2-x1, y2-y1
		local sector_length = (dx*dx+dy*dy)^0.5
		if sector_length > rest then
			-- rest is always shorter than gap; sector is shorter than rest (or gap)
			dx, dy = dx/sector_length, dy/sector_length
			while sector_length > rest do
				local x, y = x1+rest*dx, y1+rest*dy
				table.insert (points, x)
				table.insert (points, y)
				table.insert (tangents, dx)
				table.insert (tangents, dy)
				rest = rest + gap
			end
		else -- no point in this distance
		end
		-- the tail for the next 
		rest = rest-sector_length
		x1, y1 = x2, y2
	end
	return points, tangents
end

Code: Select all

-- Offsets the given polyline (line) by offset (offset)
function get_offset_polyline (line, offset, reversed)
	local offset_polyline = {}
	local loop = is_loop (line)
	if reversed then
		line = reverse_line (line)
	end
	if #line == 4 then
		local x1, y1 = line[1], line[2]
		local x2, y2 = line[3], line[4]
		local px1, py1, px2, py2 = get_parallel_segment (x1, y1, x2, y2, offset)
		offset_polyline = {px1, py1, px2, py2}
	elseif not loop then
		local x1, y1, x2, y2 = line[1], line[2], line[3], line[4]
		local px1, py1, px2, py2 = get_parallel_segment (x1, y1, x2, y2, offset)
		table.insert (offset_polyline, px1)
		table.insert (offset_polyline, py1)
		for i = 5, #line-1, 2 do
			local x3, y3 = line[i], line[i+1]
			local px3, py3, px4, py4 = get_parallel_segment (x2, y2, x3, y3, offset)
			local x, y = get_intersection (px1, py1, px2, py2, px3, py3, px4, py4, false, 4)
			table.insert (offset_polyline, x)
			table.insert (offset_polyline, y)
			x1, y1, x2, y2 = x2, y2, x3, y3
			px1, py1, px2, py2 = px3, py3, px4, py4
		end
		table.insert (offset_polyline, px2)
		table.insert (offset_polyline, py2)
	else -- loop
		local x1, y1, x2, y2 = line[#line-5], line[#line-4], line[#line-3], line[#line-2]
		local px1, py1, px2, py2 = get_parallel_segment (x1, y1, x2, y2, offset)
--		for i = 1, #line-1, 2 do
		for i = 1, #line-1, 2 do
			local x3, y3 = line[i], line[i+1]
			local px3, py3, px4, py4 = get_parallel_segment (x2, y2, x3, y3, offset)
			local x, y = get_intersection (px1, py1, px2, py2, px3, py3, px4, py4, false, 4)
			table.insert (offset_polyline, x)
			table.insert (offset_polyline, y)
			x1, y1, x2, y2 = x2, y2, x3, y3
			px1, py1, px2, py2 = px3, py3, px4, py4
		end
	end
	if #offset_polyline > 3 then
		return offset_polyline
	end
end

Re: Railway Track

Posted: Sat Sep 18, 2021 10:22 pm
by togFox
Nice. I'll not sure where I would start with such a problem!

Re: Railway Track

Posted: Sun Sep 19, 2021 3:21 am
by BrotSagtMist
Is it necessary to get this offset?
You could just draw two lines of different width on top of each other i would say.

For the ties it is also possible to draw them short and thick, may be faster.
This would have been a use case for stipple lines, but that setting was removed.

Re: Railway Track

Posted: Sun Sep 19, 2021 10:19 am
by darkfrei
BrotSagtMist wrote: Sun Sep 19, 2021 3:21 am Is it necessary to get this offset?
You could just draw two lines of different width on top of each other i would say.

For the ties it is also possible to draw them short and thick, may be faster.
This would have been a use case for stipple lines, but that setting was removed.
But rails must be above the ties and in the middle between rails must be transparent area, not black thick line.

Re: Railway Track

Posted: Sun Sep 19, 2021 3:15 pm
by BrotSagtMist
You can always add another canvas for order and instead of painting you can erase pixels too.
A quick hack in of my approach:
main.lua.zip
(1.85 KiB) Downloaded 239 times

Re: Railway Track

Posted: Sun Sep 19, 2021 4:05 pm
by darkfrei
BrotSagtMist wrote: Sun Sep 19, 2021 3:15 pm You can always add another canvas for order and instead of painting you can erase pixels too.
A quick hack in of my approach:
main.lua.zip
Nice! Didn't know that you can erase by writing with the color {0,0,0,0} with color replacing.

Code: Select all

-- new canvas
tmp = love.graphics.newCanvas()
	love.graphics.setCanvas(tmp)
	love.graphics.setColor({0.6,0.8,0.8}) -- rail color
	love.graphics.setLineWidth (rail_width+3) -- three pixels more
	love.graphics.line(line)
	love.graphics.setBlendMode("replace")
	love.graphics.setColor(0,0,0,0) -- black transparent color
	love.graphics.setLineWidth (rail_width-3) -- three pixels less
	love.graphics.line(line) -- each rail is 3 pixels wide now
-- disabling canvas
love.graphics.newCanvas()
love.graphics.setBlendMode("alpha")

Re: Railway Track

Posted: Wed Oct 06, 2021 2:45 pm
by darkfrei
BrotSagtMist wrote: Sun Sep 19, 2021 3:15 pm You can always add another canvas for order and instead of painting you can erase pixels too.
A quick hack in of my approach:
main.lua.zip
The problem:

Re: Railway Track

Posted: Wed Oct 06, 2021 7:19 pm
by BrotSagtMist
I dont think trains work like that dude.
Anyway, how do you even want it to look in the end? If you want to get rid of the rail gap you can simply add another canvas and render the rails step by step.