Selected vertex attracts it's nearest neighbor to weld into it.

Hello guys,

I am in need of a script:

Selected vertex attracts it's nearest neighbor to weld into it.

If more than one vertex is selected, each selected vertex should attract to it the nearest neighbor. Only one vertex to be welded to the original vertex.

Would appreciate if anybody could help on this :)

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
tofoaso's picture

Thanks, it works although

Thanks, it works although again not for all vertices.. would be nice if there is a way to tweak it so it works for all.
If not doable I am still happy with what it does now though. Thanks :)

miauu's picture

Can you send me a scene where

Can you send me a scene where the script not works for some of the verts? You can select the verts, so when I open the scene I can see which verts hav e to attract iss neighbors and then I will see whic verts are not selected.

tofoaso's picture

Here is a small test where

Here is a small test where you have 6 verts selected and after the script runs, there is one selected:

File is max 2010
http://www.sendspace.com/file/dv3a5l

miauu's picture

And here is the script.

Don't forget to thanks to Branko.

(
	if selection.count == 1 and classof (curO = selection[1]) == Editable_poly then
	(
		selVertsBA = polyop.getVertSelection curO
		if selVertsBA.numberset != 0 then
		(
			channelIdx = 12
			polyop.setVDataChannelSupport curO channelIdx true
			vertsToWeldArr = #()
			for v in selVertsBA do
			(
				vPos = polyop.getVert curO v
				neighborVertsBA = (polyop.getVertsUsingEdge curO (polyop.getEdgesUsingVert curO v)) - #{v}
				minDist = 1e9
				nearestVert = undefined
				for nv in neighborVertsBA do
				(
					dist = distance (polyop.getVert curO nv) vPos
					if dist < minDist do
					(
						minDist = dist
						nearestVert = nv						
					)
				)
				append vertsToWeldArr #(v, nearestVert)
			)
			if vertsToWeldArr.count != 0 do
			(
				vertsArr = #()
				for i = 1 to vertsToWeldArr.count do
				(
					polyop.setVDataValue curO channelIdx vertsToWeldArr[i] 0.12
					polyop.setVert curO vertsToWeldArr[i][2] (polyop.getVert curO vertsToWeldArr[i][1])
					append vertsArr vertsToWeldArr[i][1]
					append vertsArr vertsToWeldArr[i][2]
				)
				polyop.weldVertsByThreshold curO vertsArr
				--
				vertsToSelBA = #{}
				curOvertsBA = #{1..(polyop.getNumVerts curO)}
				for v in curOvertsBA where ((polyop.getVDataValue curO channelIdx v) == 0.12) do
				(
					append vertsToSelBA v
				)
				polyop.setVertSelection curO vertsToSelBA
				polyop.freeVData curO channelIdx
			)			
		)
		else
			messagebox "Select some vertices" title:"Invalid Selection"
	)
	else
		messagebox "Select only one editable poly object" title:"Invalid Selection"
)
tofoaso's picture

Works great! Thanks for the

Works great! Thanks for the script, its greatly appreciated! :)

miauu's picture

A slightly optimized version

(
	if selection.count == 1 and classof (curO = selection[1]) == Editable_poly then
	(
		selVertsBA = polyop.getVertSelection curO
		if selVertsBA.numberset != 0 then
		(
			channelIdx = 12
			polyop.setVDataChannelSupport curO channelIdx true
			vertsToWeldBA = #{}
			for v in selVertsBA do
			(
				vPos = polyop.getVert curO v
				neighborVertsBA = (polyop.getVertsUsingEdge curO (polyop.getEdgesUsingVert curO v)) - #{v}
				minDist = 1e9
				nearestVert = undefined
				for nv in neighborVertsBA do
				(
					dist = distance (polyop.getVert curO nv) vPos
					if dist < minDist do
					(
						minDist = dist
						nearestVert = nv						
					)
				)
				append vertsToWeldBA v
				append vertsToWeldBA nearestVert
				polyop.setVDataValue curO channelIdx v 0.12
				polyop.setVDataValue curO channelIdx nearestVert 0.12
				polyop.setVert curO nearestVert vPos
			)
			polyop.weldVertsByThreshold curO vertsToWeldBA
			vertsToSelBA = #{}
			curOvertsBA = #{1..(polyop.getNumVerts curO)}
			for v in curOvertsBA where ((polyop.getVDataValue curO channelIdx v) == 0.12) do
			(
				append vertsToSelBA v
			)
			polyop.setVertSelection curO vertsToSelBA
			polyop.freeVData curO channelIdx
		)
		else
			messagebox "Select some vertices" title:"Invalid Selection"
	)
	else
		messagebox "Select only one editable poly object" title:"Invalid Selection"
)
barigazy's picture

...more then sligthly optimized version :)

You know that the code will be optimized more if you use polyOp outside for-loop :)
Perhaps in this case there is no need for that. Can you try this:(not tested)

(
	if selection.count == 1 and isKindOf (curO = selection[1]) Editable_poly then
	(
		selVertsBA = curO.selectedverts as bitarray
		if selVertsBA.isEmpty then (messagebox "Select some vertices" title:"Invalid Selection" beep:off) else
		(
			local channelIdx = 12, vertsToWeldBA = #{}, vertsToSelBA = #{}
			local getVuE = polyop.getVertsUsingEdge
			local getEuV = polyop.getEdgesUsingVert
			local setVData = polyop.setVDataValue
			local getVData = polyop.getVDataValue
			local weldVerts = polyop.weldVerts  --polyop.weldVertsByThreshold
			polyop.setVDataChannelSupport curO channelIdx true
			for v in selVertsBA do
			(
				vPos = curO.verts[v].pos
				neighborVertsBA = (getVuE curO (getEuV curO v)) - #{v}
				minDist = 1e9 ; nearestVert = undefined
				for nv in neighborVertsBA do (if dist = (distance (curO.verts[nv].pos) vPos) < minDist do (minDist = dist ; nearestVert = nv))
				vertsToWeldBA + #{v,nearestVert}
				setVData curO channelIdx #{v,nearestVert} 0.12
				--curO.verts[nearestVert].pos = vPos
				weldVerts cur0 v nearestVert vPos
			)
			--weldVerts curO vertsToWeldBA
			for v in 1 to obj.numverts where ((getVData curO channelIdx v) == 0.12) do vertsToSelBA + #{v}
			curO.selectedverts = vertsToSelBA
			polyop.freeVData curO channelIdx
		)
	) else (messagebox "Select only one editable poly object" title:"Invalid Selection" beep:off)
)

barigazy

barigazy's picture

...more then sligthly optimized version :)

You know that the code will be optimized more if you use polyOp outside for-loop :)
Perhaps in this case there is no need for that. Can you try this:(not tested)

(
	if selection.count == 1 and isKindOf (curO = selection[1]) Editable_poly then
	(
		selVertsBA = curO.selectedverts as bitarray
		if selVertsBA.isEmpty then (messagebox "Select some vertices" title:"Invalid Selection" beep:off) else
		(
			local channelIdx = 12, vertsToWeldBA = #{}, vertsToSelBA = #{}
			local getVuE = polyop.getVertsUsingEdge
			local getEuV = polyop.getEdgesUsingVert
			local setVData = polyop.setVDataValue
			local getVData = polyop.getVDataValue
			local weldVerts = polyop.weldVerts  --polyop.weldVertsByThreshold
			polyop.setVDataChannelSupport curO channelIdx true
			for v in selVertsBA do
			(
				vPos = curO.verts[v].pos
				neighborVertsBA = (getVuE curO (getEuV curO v)) - #{v}
				minDist = 1e9 ; nearestVert = undefined
				for nv in neighborVertsBA do (if dist = (distance (curO.verts[nv].pos) vPos) < minDist do (minDist = dist ; nearestVert = nv))
				vertsToWeldBA + #{v}+#{nearestVert}
				setVData curO channelIdx #{v,nearestVert} 0.12
				--curO.verts[nearestVert].pos = vPos
				weldVerts cur0 v nearestVert vPos
			)
			--weldVerts curO vertsToWeldBA
			for v in 1 to obj.numverts where ((getVData curO channelIdx v) == 0.12) do vertsToSelBA + #{v}
			curO.selectedverts = vertsToSelBA
			polyop.freeVData curO channelIdx
		)
	) else (messagebox "Select only one editable poly object" title:"Invalid Selection" beep:off)
)

barigazy

barigazy's picture

...more then sligthly optimized version :)

You know that the code will be optimized more if you use polyOp outside for-loop :)
Perhaps in this case there is no need for that. Can you try this:(not tested)

(
	if selection.count == 1 and isKindOf (curO = selection[1]) Editable_poly then
	(
		selVertsBA = curO.selectedverts as bitarray
		if selVertsBA.isEmpty then (messagebox "Select some vertices" title:"Invalid Selection" beep:off) else
		(
			local channelIdx = 12, vertsToWeldBA = #{}, vertsToSelBA = #{}
			local getVuE = polyop.getVertsUsingEdge
			local getEuV = polyop.getEdgesUsingVert
			local setVData = polyop.setVDataValue
			local getVData = polyop.getVDataValue
			local weldVerts = polyop.weldVerts  --polyop.weldVertsByThreshold
			polyop.setVDataChannelSupport curO channelIdx true
			for v in selVertsBA do
			(
				vPos = curO.verts[v].pos
				neighborVertsBA = (getVuE curO (getEuV curO v)) - #{v}
				minDist = 1e9 ; nearestVert = undefined
				for nv in neighborVertsBA do (if dist = (distance (curO.verts[nv].pos) vPos) < minDist do (minDist = dist ; nearestVert = nv))
				vertsToWeldBA + #{v}+#{nearestVert}
				setVData curO channelIdx #{v,nearestVert} 0.12
				--curO.verts[nearestVert].pos = vPos
				weldVerts cur0 v nearestVert vPos
			)
			--weldVerts curO vertsToWeldBA
			for v in 1 to obj.numverts where ((getVData curO channelIdx v) == 0.12) do vertsToSelBA + #{v}
			curO.selectedverts = vertsToSelBA
			polyop.freeVData curO channelIdx
		)
	) else (messagebox "Select only one editable poly object" title:"Invalid Selection" beep:off)
)

barigazy

barigazy's picture

Hey Kostadin

Why me? I didn't do anything.
All credits goes to you. You did exelent job. :)
Anyway how is your son, do you feel better?

barigazy

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.