128 lines
2.9 KiB
Lua
128 lines
2.9 KiB
Lua
|
|
-- matchStrategies.lua
|
||
|
|
-- This file is included from matchFaces.lua and
|
||
|
|
-- contains the actual strategy-implementations
|
||
|
|
|
||
|
|
function matchFacesNull (src,dst,depth)
|
||
|
|
-- Do not create any pairings
|
||
|
|
return {}
|
||
|
|
end
|
||
|
|
|
||
|
|
function matchFacesMW (src, dst, depth)
|
||
|
|
-- Create pairings on top-level faces, but
|
||
|
|
-- don't pair concavities then (McKenney&Webb)
|
||
|
|
if (depth == 0) then
|
||
|
|
return matchFacesDistance(src, dst, depth)
|
||
|
|
else
|
||
|
|
return matchFacesNull(src, dst, depth)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function matchFacesSpecial (src, dst, depth)
|
||
|
|
-- Use this function for temporary tests
|
||
|
|
local ret = {}
|
||
|
|
|
||
|
|
if (depth < 1) then
|
||
|
|
return matchFacesOverlap(src, dst, depth)
|
||
|
|
else
|
||
|
|
return {
|
||
|
|
{ src = src[1] , dst = dst[2] },
|
||
|
|
{ src = src[2] , dst = dst[1] }
|
||
|
|
}
|
||
|
|
end
|
||
|
|
|
||
|
|
return ret
|
||
|
|
end
|
||
|
|
|
||
|
|
function matchFacesRandom (src, dst, depth)
|
||
|
|
-- Assing faces randomly, for testing mainly
|
||
|
|
ret = {}
|
||
|
|
i = 1
|
||
|
|
while (#src > 0 and #dst > 0) do
|
||
|
|
i1 = math.random(#src)
|
||
|
|
i2 = math.random(#dst)
|
||
|
|
ret[i] = { src = src[i1], dst = dst[i2] }
|
||
|
|
src[i1] = nil
|
||
|
|
dst[i2] = nil
|
||
|
|
i = i + 1
|
||
|
|
end
|
||
|
|
|
||
|
|
return ret
|
||
|
|
end
|
||
|
|
|
||
|
|
function matchFacesDistance (src, dst, depth)
|
||
|
|
return matchFacesCriterion (src, dst, depth, distance)
|
||
|
|
end
|
||
|
|
|
||
|
|
function overlapx (src, dst)
|
||
|
|
local ia,sa,da = overlap(src,dst)
|
||
|
|
debug(3, "Overlap: ia: " .. ia .. " sa: " .. sa .. " da: " .. da)
|
||
|
|
|
||
|
|
return 100-((ia/sa*100+ia/da*100)/2)
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
function matchFacesOverlap (src, dst, depth, minoverlap)
|
||
|
|
minoverlap = minoverlap or 10 -- default is 10 percent
|
||
|
|
|
||
|
|
debug(2, "Using Overlap with " .. minoverlap .. "% minimum")
|
||
|
|
|
||
|
|
return matchFacesCriterion (src, dst, depth, overlapx, 100 - minoverlap)
|
||
|
|
end
|
||
|
|
|
||
|
|
function matchFacesWood (src, dst, depth)
|
||
|
|
-- Do not compensate translation and scaling on top-level
|
||
|
|
if (depth == 0) then
|
||
|
|
srcoff, dstoff, srcscale, dstscale = nil
|
||
|
|
end
|
||
|
|
|
||
|
|
-- otherwise, just behave like Overlap with 9% threshold
|
||
|
|
return matchFacesOverlap(src, dst, depth, 9)
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Try to find best pairings using a scoring-function
|
||
|
|
function matchFacesCriterion (src, dst, depth, func, thres)
|
||
|
|
ret = {}
|
||
|
|
|
||
|
|
nrsrc = #src
|
||
|
|
nrdst = #dst
|
||
|
|
|
||
|
|
-- Call the scoring function for each pairing and store the
|
||
|
|
-- result in a table
|
||
|
|
k = 1
|
||
|
|
dist = {}
|
||
|
|
for i=1,nrsrc do
|
||
|
|
for j=1,nrdst do
|
||
|
|
s = src[i]
|
||
|
|
d = dst[j]
|
||
|
|
val = func(s,d)
|
||
|
|
if (val ~= nil and ((thres == nil) or (val < thres))) then
|
||
|
|
dist[k] = {}
|
||
|
|
dist[k].criterion = val
|
||
|
|
dist[k].s = s
|
||
|
|
dist[k].d = d
|
||
|
|
k = k + 1
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Sort this table with ascending score
|
||
|
|
table.sort(dist, function (a,b) return a.criterion < b.criterion end);
|
||
|
|
|
||
|
|
used = {}
|
||
|
|
|
||
|
|
-- Try to get a low overall score by prefering pairs at the beginning
|
||
|
|
-- of the sorted table
|
||
|
|
i = 1
|
||
|
|
for x,y in pairs(dist) do
|
||
|
|
if (used[y.s] ~= 1 and used[y.d] ~= 1) then
|
||
|
|
ret[i] = { src=y.s, dst=y.d }
|
||
|
|
used[y.s] = 1
|
||
|
|
used[y.d] = 1
|
||
|
|
debug(4, x.." = "..y.criterion)
|
||
|
|
i = i + 1
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return ret
|
||
|
|
end
|