Notifications
Clear all

[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!

 PEN

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.

Great stuff, Matan. This is really fun to play with

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?

Page 2 / 2