Code
--[[
Rejoin Cuts V1.010 by Crashguard303
this script helps you to re-merge cut segments.
by default, it will band all segs:
-- with adjacent indices, spatially "too far" than normally
-- and freeze all other segments
it can also scaffold segs:
-- with certain distances (off by default)
doing this, you should be able to do some wiggle
getting the cut parts together again
without involving the rest of the puzzle.
note:
this script can't detect a cut directly.
it just checks the measured spatial segment distance
between two segments with index distance of 1
and checks if this distance is inside the threshold range.
the threshold range specifies a "normal" connection without cut,
so detection success depends on the "right" threshold values.
it can also false-detect
-- cuts, if connected segments are connected by a sharp (glycine) egde
-- connections, if cut segments are too close already
then, you need to change the threshold values.
abbreviations:
seg: segment
idx: index
dist: distance
len: length
str: strength
act: active
inv: invert
cur: current
thr: threshold
tgt: target
res: result
--]]
function rejoin_cut(cut_n_scaff)
local band_list= cut_get(cut_n_scaff.cut)
if cut_n_scaff.cut.act then
band.AddBetweenSegments2(band_list,cut_n_scaff.cut)
end -- if cut_n_scaff.cut.act then
if cut_n_scaff.cut.freeze_other then
freeze.FreezeAll()
-- print('freezing all')
local i
for i=1,#band_list do
freeze.Unfreeze(band_list[i][1],true,true)
print('unfreezing seg#'..i..'[1] idx:'..band_list[i][1])
freeze.Unfreeze(band_list[i][2],true,true)
print('unfreezing seg#'..i..'[2] idx:'..band_list[i][2])
end -- for i
end -- cut_n_scaff.cut.freeze_other
if cut_n_scaff.scaff.act then
local band_list= scaff_get(cut_n_scaff.scaff)
band.AddBetweenSegments2(band_list,cut_n_scaff.scaff)
end -- if cut_n_scaff.cut.act then
end -- function
function cut_get(cut)
local band_list={}
print('\nsearching for segs with adjacent idx but dist:')
print(cut.thr.min..'-'..cut.thr.max..' inv:'..tostring(cut.inv))
print('freeze other:'..tostring(cut.freeze_other))
local i
for i=1,(seg_count-1) do
if dist_get(i,
(i+1),
cut.thr.min,
cut.thr.max,
cut.inv) then
table.insert(band_list,{i;(i+1)})
end -- if dist_get
end -- for i
-- list_show(band_list)
return band_list
end -- function cut_get
function scaff_get(scaff)
local band_list={}
print('\nsearching for segs with dist:')
print(scaff.thr.min..'-'..scaff.thr.max..' inv:'..tostring(scaff.inv))
local i
for i=1,(seg_count-1) do
local j
for j=(i+1),seg_count do
if dist_get(i,
j,
scaff.thr.min,
scaff.thr.max,
scaff.inv) then
table.insert(band_list,{i;j})
end -- if dist_get
end -- for j
end -- for i
-- list_show(band_list)
return band_list
end -- function cut_get
function list_show(list)
print('detected segs:')
local i
for i=1,#list do
print('#'..i..' idx:'..list[i][1]..':'..list[i][2])
end -- for k
end -- function list_show
function dist_get(i,i2,min,max,inv)
local dist= structure.GetDistance(i,i2)
-- print('dist seg#'..i..':'..i2..' value:'..dist)
if dist_check(dist,min,max,inv) then
return true
else
return false
end -- if dist_check
end -- function dist_get
function dist_check(dist,min,max,inv)
local res= false
if dist>=min then
if dist<=max then
res= true
end -- if dist
end -- dist
if inv then
res= not(res)
end -- if inv
return res
end -- dist_check
function band.AddBetweenSegments2(band_list,cut_or_scaff)
local i
for i=1,#band_list do
local banded_flag= band.AddBetweenSegments3(band_list[i][1],band_list[i][2],cut_or_scaff.tgt.len,cut_or_scaff.tgt.str)
end -- for i
end -- function band.AddBetweenSegments2
function band.AddBetweenSegments3(i,i2,len,str)
local banded_flag= false
local band_count1= band.GetCount()
-- check current of bands before applying another band
band.AddBetweenSegments(i,i2)
-- try to add band
local band_count2= band.GetCount()
-- check number of bands after applying another band
if band_count1~=band_count2 then
-- band was added
-- change len of last band:
local len= len
if len==nil then
len= structure.GetDistance(i,i2)
end -- if len==nil
band.SetGoalLength(band_count2,len)
band.SetStrength(band_count2,str)
-- change str of last band
print('banded seg idx:'..i..':'..i2..' len:'..len..' str:'..str)
-- show what was banded
banded_flag= true
--[[
else
assert (band_count1~=band_count2, "Band was not added!")
--]]
end -- if band_count
return banded_flag
end -- function band.AddBetweenSegments3(i,i2)
seg_count= structure.GetCount()
-- get number of segments
rejoin_cut({
cut={act=true;
-- activate cut-fixing by banding
-- true: yes
-- false: no
freeze_other=true;
-- freeze rest of puzzle
-- true: yes
-- false: no
thr={min=2.7;max=3.81};
-- detect adjacent segs with these distances
-- consider these distance as not cut
inv=true;
-- true: invert detection result
-- to band segs outside detection
tgt={len=3.801;str=1}};
-- band using these values
scaff={act=false;
-- activate scaffolding puzzle structure by banding
-- true: yes
-- false: no
thr={min=3.801*7;max=3.801*7.25};
-- detect all segs with these distances
-- consider these distance as scaffold-worthy
inv=false;
-- false: don't invert detection
-- to band segs inside detection
tgt={len=nil;str=10}}
-- scaffold using these values
-- len=nil: use measured distance, not fixed value
})