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

...#2 distance comparation method

(
	if selection.count == 1 and isKindOf (obj = selection[1]) Editable_poly then
	(
		selVertsBA = obj.selectedverts as bitarray
		if selVertsBA.isEmpty then (messagebox "Select some vertices" title:"Invalid Selection" beep:off) else
		(
			local vertsToWeldBA = #{}, vertsToSelBA = #{}, vertsPos = #()
			local getVuE = polyop.getVertsUsingEdge
			local getEuV = polyop.getEdgesUsingVert
			local weldThresh = obj.weldThreshold = 0.001
			local weldVerts = polyop.weldVertsByThreshold
			for v in selVertsBA do
			(
				vPos = obj.verts[v].pos
				neighborVertsBA = (getVuE obj (getEuV obj v)) - #{v}
				minDist = 1e9 ; nearestVert = undefined
				for nv in neighborVertsBA do (if (dist = distance (obj.verts[nv].pos) vPos) < minDist do (minDist = dist ; nearestVert = nv))
				join vertsToWeldBA  #{v, nearestVert}
				append vertsPos (obj.verts[nearestVert].pos = vPos)
			)
			weldVerts obj vertsToWeldBA
			for v in 1 to obj.numverts do
			(
				for p in vertsPos where distance obj.verts[v].pos p <= weldThresh do append vertsToSelBA v
			)
			obj.selectedverts = vertsToSelBA
		)
	) else (messagebox "Select only one editable poly object" title:"Invalid Selection" beep:off)
)

barigazy

barigazy's picture

...

So the point here is to reduce usage of polyOp struct to minimum.
Hope you agree with me Kostadin. I have not had time to to compare speed and memory.

barigazy

miauu's picture

I think that for object with

I think that for object with small amount of verts the speed using polyop and not using polyop will be too small. But when I have time I will compare both methods.
The most important I think is to stop the last for loop when all verts, that have to be selected, are found. So we have to use something like this:

cnt = 0
			for v in 1 to obj.numverts while cnt  < selVertsBA.numberset do
			(
				for p in vertsPos where distance obj.verts[v].pos p <= weldThresh do
				(
					append vertsToSelBA v
					cnt += 1
				)
			)
barigazy's picture

Nice one i like it. Maybe

Nice one i like it. Maybe there is a better finding method because what if we used few last verts that need to be selected after welding.

barigazy

miauu's picture
barigazy's picture

...#1 string comparation method

Sorry for double post and untested version.
I have a new aproch without using getset Vert Data.

(
	if selection.count == 1 and isKindOf (obj = selection[1]) Editable_poly then
	(
		selVertsBA = obj.selectedverts as bitarray
		if selVertsBA.isEmpty then (messagebox "Select some vertices" title:"Invalid Selection" beep:off) else
		(
			local vertsToWeldBA = #{}, vertsPos = #()
			local getVuE = polyop.getVertsUsingEdge
			local getEuV = polyop.getEdgesUsingVert
			local weldVerts = polyop.weldVertsByThreshold
			for v in selVertsBA do
			(
				vPos = obj.verts[v].pos
				neighborVertsBA = (getVuE obj (getEuV obj v)) - #{v}
				minDist = 1e9 ; nearestVert = undefined
				for nv in neighborVertsBA do (if (dist = distance (obj.verts[nv].pos) vPos) < minDist do (minDist = dist ; nearestVert = nv))
				join vertsToWeldBA  #{v, nearestVert}
				append vertsPos ((obj.verts[nearestVert].pos = vPos) as string)
			)
			weldVerts obj vertsToWeldBA
			obj.selectedverts = (for v in 1 to obj.numverts where findItem vertsPos (obj.verts[v].pos as string) != 0 collect v)
		)
	) else (messagebox "Select only one editable poly object" title:"Invalid Selection" beep:off)
)

barigazy

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"
)

Comment viewing options

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