[Closed] Math for skin transfer?
Hi,
I had some fun with your code and rearranged it in an interactive dialog.
press the left mouse button anywhere on the map to add a white point
and press then right mouse button to add a black point.
I added another variable named ‘thresh’ to the equation to help deal with the issue you had with everything becoming gray (averaged) when far away from any point.
I also added the ‘trunk’ variable to un contrast the interpolated points so that the original points will become visible.
I still need to think of a way to calculate the correct thresh value instead of inputing it by hand…
(
global roll_Test
try (destroyDialog roll_Test) catch ()
rollout roll_Test "Shepard's method test"
(
-- Local Structs
-----------------------------------------
struct s_Points (coord, val)
-- Local Variable Declerations
------------------------------------------
local w = 200
local h = 100
local testMap = bitmap w h hdr:true color:red
local Pts = #()
-- User Interface
------------------------------------------
imgTag imtTest bitmap:testMap align:#center transparent:blue
spinner spnTrunk "trunk:" range:[0, 1, 0.1] scale:0.1
spinner spnP "p:" range:[0.01, 100, 3] scale:1
spinner spnThresh "thresh:" range:[0, 100, 15] scale:1
-- Functions
------------------------------------------
fn getShortestDist Pts x =
(
local lastDist = distance Pts[1].coord x
for i = 2 to Pts.count do (
local newDist = distance Pts[i].coord x
if newDist < lastDist then
lastDist = newDist
)
lastDist
)
fn testPolate w h Pts p thresh trunk =
(
for y = 0 to h - 1 do (
local colors = #()
if Pts.count > 0 then (
for x = 0 to w - 1 do (
local setColor = color 255 0 0
local thisCoord = point2 x y
local val1 = color 0 0 0
local val2 = 0.0
local shortestDist = getShortestDist Pts thisCoord
for i = 1 to Pts.count do (
local newDist = distance thisCoord Pts[i].coord
newDist -= shortestDist - thresh
local wi = 1.0 / (pow newDist p)
val1 += Pts[i].val * wi
val2 += wi
)
setColor = val1 / val2
setColor = (1 - trunk) * setColor + 0.5 * trunk * white
append colors setColor
)
setPixels testMap [0,y] colors
)
)
for i = 1 to pts.count do
setPixels testMap Pts[i].coord #(Pts[i].val)
imtTest.bitmap = testMap
)
fn redrawMap =
(
testPolate w h Pts spnP.value spnThresh.value spnTrunk.value
)
fn openDialog =
(
createDialog roll_Test width:210
)
fn init =
(
redrawMap()
)
fn done =
(
-- cleanup code
gc light:true
)
-- Event Handlers
------------------------------------------
on imtTest lbuttonup pos flags do (
append Pts (s_Points coord:pos val:white)
redrawMap()
)
on imtTest rbuttonup pos flags do (
append Pts (s_Points coord:pos val:black)
redrawMap()
)
on spnP changed arg do redrawMap()
on spnThresh changed arg do redrawMap()
on spnTrunk changed arg do redrawMap()
on roll_Test open do init()
on roll_Test close do done()
)
roll_Test.openDialog()
)
Matan.
Fun stuff, Matan!!
I’ll see if I can put my new method into your script! It’s got a couple of parameters that I think would be very interesting to interact with!
Skin Utilities works great, you must just be doing something wrong with it.
Skin Wrap is a bit easier how ever but I have run into the very odd case where it does something strange.
I had some more fun with the ui, don’t know why…
anyhow here it is:
(
global roll_Test
try (destroyDialog roll_Test) catch ()
rollout roll_Test "Shepard's method test"
(
-- Local Structs
-----------------------------------------
struct s_Points (coord, val)
-- Local Variable Declerations
------------------------------------------
local w = 200
local h = 100
local rad = 3
local testMap = bitmap w h hdr:true color:red
local Pts = #()
-- User Interface
------------------------------------------
progressBar pbrProg width:w height:10 align:#center
imgTag imtTest bitmap:testMap align:#center transparent:blue
button btnClear "Clear" width:w align:#center
radioButtons rbnMode "" labels:#("Add", "Edit")
spinner spnTrunk "trunk:" range:[0, 1, 0.3] scale:0.1
spinner spnP "p:" range:[0.01, 100, 3] scale:1
spinner spnThresh "thresh:" range:[0, 100, 15] scale:1
-- Functions
------------------------------------------
fn getClosestPt x =
(
local lastPoint = Pts[1]
local lastDist = distance lastPoint.coord x
for i = 2 to Pts.count do (
local newDist = distance Pts[i].coord x
if newDist < lastDist then (
lastDist = newDist
lastPoint = Pts[i]
)
)
lastPoint
)
fn getShortestDist x =
(
distance x (getClosestPt x).coord
)
fn movePointTo x =
(
if Pts.count > 0 then
(getClosestPt x).coord = x
)
fn delPoint x =
(
if Pts.count > 0 then
deleteItem Pts (findItem Pts (getClosestPt x))
)
fn setPt Pt rad mark:green =
(
for y = amax 0 (Pt.coord.y - rad) to amin (h - 1) (Pt.coord.y + rad) do (
local colors = #()
local startPt = undefined
for x = amax 0 (Pt.coord.x - rad) to amin (w - 1) (Pt.coord.x + rad) do (
local dist = distance Pt.coord [x,y]
if dist <= rad then (
local val = Pt.val
if dist < rad * 0.4 then
val = mark
append colors val
if startPt == undefined then
startPt = [x,y]
)
)
if startPt != undefined then
setPixels testMap startPt colors
)
)
fn testPolate w h Pts p thresh trunk =
(
if Pts.count > 0 then (
pbrProg.value = 0
for y = 0 to h - 1 do (
local colors = #()
for x = 0 to w - 1 do (
local setColor = color 255 0 0
local thisCoord = point2 x y
local val1 = color 0 0 0
local val2 = 0.0
local shortestDist = getShortestDist thisCoord
for i = 1 to Pts.count do (
local newDist = distance thisCoord Pts[i].coord
newDist += thresh - shortestDist
local wi = 1.0 / (pow newDist p)
val1 += Pts[i].val * wi
val2 += wi
)
setColor = val1 / val2
setColor = (1 - trunk) * setColor + 0.5 * trunk * white
append colors setColor
)
setPixels testMap [0,y] colors
pbrProg.value = 100.0 * y / (h - 1)
)
)
for Pt in Pts do
setPt Pt rad
imtTest.bitmap = testMap
)
fn redrawMap =
(
testPolate w h Pts spnP.value spnThresh.value spnTrunk.value
)
fn openDialog =
(
createDialog roll_Test width:(w + 10)
)
fn init =
(
Pts = #()
testMap = bitmap w h hdr:true color:red
imtTest.bitmap = testMap
)
fn done =
(
-- cleanup code
gc light:true
)
-- Event Handlers
------------------------------------------
on imtTest lbuttondown pos flags do (
case rbnMode.state of (
1: (
local Pt = s_Points coord:pos val:white
setPt Pt rad mark:red
append Pts Pt
)
2: setPt (getClosestPt pos) rad mark:red
)
imtTest.bitmap = testMap
)
on imtTest rbuttondown pos flags do (
case rbnMode.state of (
1: (
local Pt = s_Points coord:pos val:black
setPt Pt rad mark:red
append Pts Pt
)
2: setPt (getClosestPt pos) rad mark:red
)
imtTest.bitmap = testMap
)
on imtTest lbuttonup pos flags do (
case rbnMode.state of (
1: ()
2: movePointTo pos
)
redrawMap()
)
on imtTest rbuttonup pos flags do (
case rbnMode.state of (
1: ()
2: delPoint pos
)
redrawMap()
)
on btnClear pressed do init()
on spnP changed arg do redrawMap()
on spnThresh changed arg do redrawMap()
on spnTrunk changed arg do redrawMap()
on roll_Test open do init()
on roll_Test close do done()
)
roll_Test.openDialog()
)
now you can edit the points by selecting edit modeand then
left click will mode the closest point to the clicked position
right click will delete the closest point.
I also made the points bigger
Matan.
I added a checkbox next to the thresh parameter so that it will be clear how it effects then result.
(
global roll_Test
try (destroyDialog roll_Test) catch ()
rollout roll_Test "Shepard's method test"
(
-- Local Structs
-----------------------------------------
struct s_Points (coord, val)
-- Local Variable Declerations
------------------------------------------
local w = 200
local h = 100
local rad = 3
local testMap = bitmap w h hdr:true color:red
local Pts = #()
-- User Interface
------------------------------------------
progressBar pbrProg width:w height:10 align:#center
imgTag imtTest bitmap:testMap align:#center transparent:blue
button btnClear "Clear" width:w align:#center
radioButtons rbnMode "" labels:#("Add", "Edit")
spinner spnTrunk "trunk:" range:[0, 1, 0.3] scale:0.1
spinner spnP "p:" range:[0.01, 100, 3] scale:1
spinner spnThresh "thresh:" range:[0, 100, 40] scale:1
checkBox cbxUseThresh "" align:#left offset:[0,-22] checked:true
-- Functions
------------------------------------------
fn getClosestPt x =
(
local lastPoint = Pts[1]
local lastDist = distance lastPoint.coord x
for i = 2 to Pts.count do (
local newDist = distance Pts[i].coord x
if newDist < lastDist then (
lastDist = newDist
lastPoint = Pts[i]
)
)
lastPoint
)
fn getShortestDist x =
(
distance x (getClosestPt x).coord
)
fn movePointTo x =
(
if Pts.count > 0 then
(getClosestPt x).coord = x
)
fn delPoint x =
(
if Pts.count > 0 then
deleteItem Pts (findItem Pts (getClosestPt x))
)
fn setPt Pt rad mark:green =
(
for y = amax 0 (Pt.coord.y - rad) to amin (h - 1) (Pt.coord.y + rad) do (
local colors = #()
local startPt = undefined
for x = amax 0 (Pt.coord.x - rad) to amin (w - 1) (Pt.coord.x + rad) do (
local dist = distance Pt.coord [x,y]
if dist <= rad then (
local val = Pt.val
if dist < rad * 0.4 then
val = mark
append colors val
if startPt == undefined then
startPt = [x,y]
)
)
if startPt != undefined then
setPixels testMap startPt colors
)
)
fn testPolate Pts p thresh trunk =
(
if Pts.count == 0 then
testMap = bitmap w h hdr:true color:red
else (
pbrProg.value = 0
for y = 0 to h - 1 do (
local colors = #()
for x = 0 to w - 1 do (
local setColor = color 255 0 0
local thisCoord = point2 x y
local val1 = color 0 0 0
local val2 = 0.0
local shortestDist = getShortestDist thisCoord
for i = 1 to Pts.count do (
local newDist = distance thisCoord Pts[i].coord
if cbxUseThresh.checked then
newDist += thresh - shortestDist
local wi = 1.0 / (pow newDist p)
val1 += Pts[i].val * wi
val2 += wi
)
setColor = val1 / val2
setColor = (1 - trunk) * setColor + 0.5 * trunk * white
append colors setColor
)
setPixels testMap [0,y] colors
pbrProg.value = 100.0 * y / (h - 1)
)
for Pt in Pts do
setPt Pt rad
)
imtTest.bitmap = testMap
)
fn redrawMap =
(
testPolate Pts spnP.value spnThresh.value spnTrunk.value
)
fn openDialog =
(
createDialog roll_Test width:(w + 10)
)
fn init =
(
Pts = #()
redrawMap()
)
fn done =
(
-- cleanup code
gc light:true
)
-- Event Handlers
------------------------------------------
on imtTest lbuttondown pos flags do (
case rbnMode.state of (
1: (
local Pt = s_Points coord:pos val:white
setPt Pt rad mark:red
append Pts Pt
)
2: (
if Pts.count > 0 then
setPt (getClosestPt pos) rad mark:red
)
)
imtTest.bitmap = testMap
)
on imtTest rbuttondown pos flags do (
case rbnMode.state of (
1: (
local Pt = s_Points coord:pos val:black
setPt Pt rad mark:red
append Pts Pt
)
2: (
if Pts.count > 0 then
setPt (getClosestPt pos) rad mark:red
)
)
imtTest.bitmap = testMap
)
on imtTest lbuttonup pos flags do (
case rbnMode.state of (
1: ()
2: movePointTo pos
)
redrawMap()
)
on imtTest rbuttonup pos flags do (
case rbnMode.state of (
1: ()
2: delPoint pos
)
redrawMap()
)
on btnClear pressed do init()
on spnP changed arg do redrawMap()
on spnThresh changed arg do redrawMap()
on spnTrunk changed arg do redrawMap()
on cbxUseThresh changed arg do redrawMap()
on roll_Test open do init()
on roll_Test close do done()
)
roll_Test.openDialog()
)
what the”Shepards method” is? can anyone give me a link to the method’s math explanation?