Page 1 of 1

Train bounding boxes

Posted: Mon Aug 29, 2016 2:51 am
by mknejp
While working on electric-vehicles I noticed that the "bounding_box" property doesn't really seem to work the way I expected. That part is probably my own fault for making assumptions because the property has no description in the API reference.

Basically what I was trying to do is take the locomotive's "bounding_box", use it as the "area" filter in "find_entities_filtered" and hoping I would get the rail segments the train was standing on. This worked fine for a train that was standing vertically in the north-south direction. But when the train was oriented east/west the game didn't seem to incorporate this information into the "bounding_box" value returned to Lua. As an example I have a locomotive placed at {-7.8, -3} and its bounding box is {{-8.4, -5.5}, {-7.2, -0.4}} which is clearly a vertically stretched box. The "direction" property always returns 0 regardless how the train is oriented thus I couldn't rotate the BB myself. So what I'm doing right now is take a fixed 6x6 search area centered on the locomotive, search for my electric-energy-interface entities and then do the reverse: check if find_entity() at the position of each found entity returns the locomotive. This method seems to be quite accurate, I assume find_entity() is testing against the oriented collision boxes, but I wonder if isn't overkill. Not that I'm doing this every tick but stil...

So, my conclusion here is basically: is there a better way to achieve what I'm doing? is this behavior of "bounding_box" intended, and if so is there a chance of getting a "collision_box" added to LuaEntity? It wouldn't have to be an oriented BB as there ins't much use for one but the AABB could be useful in this situation.

Re: Train bounding boxes

Posted: Mon Aug 29, 2016 3:02 am
by Nexela
http://lua-api.factorio.com/latest/LuaTrain.html

using front rail and back rail you can get all the rails in between

Re: Train bounding boxes

Posted: Mon Aug 29, 2016 3:44 am
by mknejp
I looked at those but how would I know which direction to use in get_connected_rail if there is a track switch in the middle of the train?

Re: Train bounding boxes

Posted: Tue Aug 30, 2016 7:09 pm
by mknejp
Nexela wrote:http://lua-api.factorio.com/latest/LuaTrain.html

using front rail and back rail you can get all the rails in between
Please show me how you would do that. I have been pondering about this for a while now and can't figure it out. In a situation like this
train1.PNG
train1.PNG (465.33 KiB) Viewed 12454 times
it's obvious. Using LuaTrain.front_rail, LauTrain.rail_direction_from_front_rail and iterating with LuaEntity.get_connected_rail until I hit LuaTrain.back_rail it's easy. But if the train is standing like this
train2.PNG
train2.PNG (868.5 KiB) Viewed 12454 times
then how do I know which rail_connection_direction to use at the separation without testing every combination for X amount of track? Is there a call I am missing or misunderstanding?

Re: Train bounding boxes

Posted: Tue Aug 30, 2016 10:09 pm
by Nexela
mknejp wrote:
Nexela wrote:http://lua-api.factorio.com/latest/LuaTrain.html

then how do I know which rail_connection_direction to use at the separation without testing every combination for X amount of track? Is there a call I am missing or misunderstanding?

You will have to do exactly what you don't want to do and test x pieces of track in all three directions. To make the check go quicker you might be able to check rail.minable. It is possible that if there is a train on it this will return false.

Re: Train bounding boxes

Posted: Wed Aug 31, 2016 12:06 am
by mknejp
Nexela wrote:You will have to do exactly what you don't want to do and test x pieces of track in all three directions. To make the check go quicker you might be able to check rail.minable. It is possible that if there is a train on it this will return false.
Sigh. This seems really redundant to me. The game clearly already has this information available. Guess I'll stick to my existing solution for now. It's not only simpler but also seems a lot less computationally expensive.

Re: Train bounding boxes

Posted: Wed Aug 31, 2016 12:31 am
by aubergine18
Can't you get the x,y,rotation of cargo carriages and use that to determine where rails are likely to be (when you encounter a rail junction)?

Re: Train bounding boxes

Posted: Wed Aug 31, 2016 12:52 am
by mknejp
aubergine18 wrote:Can't you get the x,y,rotation of cargo carriages and use that to determine where rails are likely to be (when you encounter a rail junction)?
There is no rotation. Only direction but that always returns 0 for rolling stock.

Re: Train bounding boxes

Posted: Wed Aug 31, 2016 1:04 am
by DedlySpyder
mknejp wrote:There is no rotation. Only direction but that always returns 0 for rolling stock.
I think trains use orientation instead of direction

Re: Train bounding boxes

Posted: Wed Aug 31, 2016 10:15 am
by Nexela
All rails underneath the train.

Code: Select all

function Position.expand_to_area(pos, radius) --liberated from Factorio STDLIB
    if #pos == 2 then
        return { left_top = { x = pos[1] - radius, y = pos[2] - radius }, right_bottom = { x = pos[1] + radius, y = pos[2] + radius } }
    end
    return { left_top = { x = pos.x - radius, y = pos.y - radius}, right_bottom = { x = pos.x + radius, y = pos.y + radius } }
end

local debug_picker = {}
debug_picker.name = "debug_picker"


local function valid(entity)
    if entity and entity.valid then return true else return false end
end

function debug_picker.do_script(event)
    local player = game.players[event.player_index]
    local entity = player.selected
    local rails = {}

    for _, text in pairs(player.surface.find_entities_filtered({type="flying-text"})) do
        if text and text.valid then text.destroy() end
    end
    if not entity then return end

    if valid(player) and valid(entity) and (entity.type == "cargo-wagon" or entity.type == "locomotive") then
        local train = entity.train
        if valid(train) then
            local carriages=train.carriages
            for _, carriage in pairs(carriages) do
                for _, rail in pairs(carriage.surface.find_entities_filtered({area=Position.expand_to_area(carriage.position, 4), type="straight-rail"})) do
                    if rail.minable==false then rails[rail.unit_number]=rail end --index by unique unit num to avoid dupes
                end
                --repeat above block using type=curved-rail if you want curved rail.
            end
            for _, rail in pairs(rails) do
                local text = rail.surface.create_entity({name="flying-text", position=rail.position, force=rail.force, text="RAIL", color=colors.yellow})
                text.active=false
            end
        end
    end
end
Pics or it didnt happen

Re: Train bounding boxes

Posted: Wed Aug 31, 2016 6:34 pm
by mknejp
Well yes this is obviously what I'm already doing as I described in my initial post and I find it inefficient, so I'm not sure that your point is. You suggested to use the LuaTrain API instead for more reliable results but I suggest that it's insufficient.

Re: Train bounding boxes

Posted: Wed Aug 31, 2016 6:35 pm
by mknejp
DedlySpyder wrote:
mknejp wrote:There is no rotation. Only direction but that always returns 0 for rolling stock.
I think trains use orientation instead of direction
You're right I totally missed that.