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.
miauu's picture

Because you shows me the

Because you shows me the right direction. :)
My son is fill better, but still have temperature(tonsillitis).

barigazy's picture

...

This can be done using get/set VDataValue polyop methods

bga

tofoaso's picture

Thanks Branko for the

Thanks Branko for the suggestion! :)

miauu's picture

The problem is that when Max

The problem is that when Max weld vertices the index of the new vert is changed. If you select only one vert and run the script then is easy to get the resulting vert index - it is always the smaller index(I hope) of the vertices that are welded. So this will works only when you weld 2 verts(one is selected, the script find other one)

(
	if selection.count == 1 and classof (curO = selection[1]) == Editable_poly then
	(
		newVertsBA = #{}
		selVertsBA = polyop.getVertSelection curO
		if selVertsBA.numberset != 0 then
		(
			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
				(
					if vertsToWeldArr[i][2] < vertsToWeldArr[i][1] then 
						append newVertsBA vertsToWeldArr[i][2]
					else
						append newVertsBA vertsToWeldArr[i][1]
					--
					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
			)
			polyop.setVertSelection curO newVertsBA
		)
		else
			messagebox "Select some vertices" title:"Invalid Selection"
	)
	else
		messagebox "Select only one editable poly object" title:"Invalid Selection"
)

The method above can't be used when you want to weld 2 or more verts. Welding the first pair of verts will change their indexes, so the next pair will have new indexes and the rule with the smaller index can't work. This is why the I not weld verts pair by pair - after the first weld process the cript will loose track of the next verts that have to be welded. So I use weld by threshold, which welds all verts at once and there is no problem with verts indexes. The code below will select the resulting vertices when you weld 1,2 or more pairs.

(
	if selection.count == 1 and classof (curO = selection[1]) == Editable_poly then
	(
		selVertsBA = polyop.getVertSelection curO
		selVertsFacesArr = #()
		if selVertsBA.numberset != 0 then
		(
			vertsToWeldArr = #()
			for v in selVertsBA do
			(
				vPos = polyop.getVert curO v
				append selVertsFacesArr #(vPos,(polyop.getFacesUsingVert 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.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 = #{}
				for idx in  selVertsFacesArr do
				(
					vertsBA = polyop.getVertsUsingFace curO idx[2]
					for v in vertsBA do
					(
						if distance idx[1] (polyop.getVert curO v) < 0.0001 do
							append vertsToSelBA v
					)
				)
				polyop.setVertSelection curO vertsToSelBA
			)			
		)
		else
			messagebox "Select some vertices" title:"Invalid Selection"
	)
	else
		messagebox "Select only one editable poly object" title:"Invalid Selection"
)
tofoaso's picture

Small addition if

Small addition if possible..
Script to keep the original vertices selected after the welding process?

At the end I have added:
(
Selection = SelVertsBA
)

It does work only in certain areas, and sometimes not at all.

I also tried the other way around with keeping the selection with the numbers of the vertices that were to be welded but it does not work as well.

I am very new to maxscript as you can guess :)

tofoaso's picture

Thanks for the quick

Thanks for the quick help!
The script does its job in no time :)

miauu's picture

It is easy to write a script

It is easy to write a script that do what you want.

(
	if selection.count == 1 and classof (curO = selection[1]) == Editable_poly then
	(
		selVertsBA = polyop.getVertSelection curO
		if selVertsBA.numberset != 0 then
		(
			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.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
			)
		)
		else
			messagebox "Select some vertices" title:"Invalid Selection"
	)
	else
		messagebox "Select only one editable poly object" title:"Invalid Selection"
)
tofoaso's picture

Another option..

If that's tricky another option that would also work is to convert that selection (one vertex, or few vertices placed in different places on the mesh) to edges, but only the shortest connected edge to each vertex. Then I could add collapse to the script :)

Comment viewing options

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