3
votes

I try to make a function that calculate intersection points between to circles: one circle against a list of circles.

For each case there are 0,1 or 2 intersection points.

I want the function returns nil, nil for 0 points, z0, nil for 1 and z1, z2 for 2 points. I thought collecting gradually the pairs of results in a table through a loop, and unpack it at the end, but a table doesn't take a nil value.

I tried this for the moment. How can I achieve what I want ?

function InterSection_Cercles (Ca , ... )

    local C = table.pack( ... )
    local d, CosTheta, Theta, i
    local t = {}

    for i = 1, C.n do

        d = complex.abs ( Ca.Ct - C[i].Ct )

        CosTheta = round (((Ca.Ry * Ca.Ry + d * d - C[i].Ry * C[i].Ry) /( 2 * Ca.Ry * d )) , 10 )

        Theta = round ( math.acos( CosTheta ) , Prec)

        if not Theta then -- 0 solution
            -- table.insert( t , nil ) useless
            -- table.insert( t , nil )
        elseif Theta == 0 then -- 1 solution 
            table.insert( t , Ca.Ct + complex.polar (Ca.Ry , Theta + complex.arg (C[i].Ct -Ca.Ct)))
            -- table.insert( t , nil ) useless
        else -- 2 solitions
            table.insert( t , Ca.Ct + complex.polar (Ca.Ry , Theta + complex.arg (C[i].Ct -Ca.Ct)))
            table.insert( t , Ca.Ct + complex.polar (Ca.Ry , -Theta + complex.arg (C[i].Ct -Ca.Ct)))
        end -- if

    end -- for

    return table.unpack ( t )

end -- function
2

2 Answers

5
votes

There is no way to build an array in Lua that contains nil values. Arrays in Lua are defined as the sequence in a table from [1, n] which has no nil values in it.

You could either insert a placeholder value (false) or you will have to keep track of the table's size manually. So rather than calling table.insert, you have to make a new function that stores the length of the table in some value:

local function manualInsert(tbl, val)
  if(not tbl.n) then tbl.n = 0 end --all values are assumed to be inserted through this function.
  tbl[tbl.n + 1] = val
  tbl.n = tbl.n + 1
end

Normally, tbl cannot be used with standard Lua mechanisms for dealing with arrays. You can't call # on it to get the right length, so iterating over it is difficult unless you know it's special. Removing elements would need its own special function, and so forth.

However, you can use a metatable and metamethods to make using this kind of pseudo-array seem more functional. For example, in Lua 5.2+, you can override the __len metamethod to return n. This would allow you use for i = 1, #tbl do to iterate over the elements. It would also allow table.unpack to work without manually passing the length, since it's defined to use # to get the length if you don't provide it.

Note that while Lua 5.1 does allow the use of the __len metamethod, it does not permit a table to override the default length computation. Only userdata's __len metamethods are used.

In Lua 5.2, you can override the __ipairs metamethod in order to make ipairs work. In Lua 5.3, this is deprecated; ipairs relies on the standard metamethods instead. This could be workable, but the documentation says that ipairs will keep going "up to the first nil value." So it may not be possible in Lua 5.3.

So unless you're in Lua 5.2 or better, manualInsert will create a very dysfunctional table.

2
votes

If using nil inside tables is complicating life for your, use some other value like false.

Or return a table like { 0, 1, z1, 2, z1, z2 }.