Notifications
Clear all

[Closed] Find similar vertex position in 2 objects

Hey everybody
As title say I like to find the similar vertices in 2 objects by their position, but in this example I can’t use the “distance” function, it just find one because of vertices order!
How to find the 2 similar vertices in these 2 objects:

wire1 = splineShape name:"wire1" wire1color:blue	 vertexTicks:on 
addnewSpline wire1	
addKnot wire1 1 #corner #line [30,30,0]
addKnot wire1 1 #corner #line [30,-30,0]
addKnot wire1 1 #corner #line [-30,-30,0]
addKnot wire1 1 #corner #line [-30,30,0]
close wire1 1
convertToPoly wire1
update wire1

wire2 = splineShape name:"wire2" wire1color:blue	 vertexTicks:on 
addnewSpline wire2	
addKnot wire2 1 #corner #line [60,0,0]
addKnot wire2 1 #corner #line [30,30,0]
addKnot wire2 1 #corner #line [30,-30,0]
close wire2 1
convertToPoly wire2
update wire2
11 Replies

Similar is a very broad term. But you could start from using GetHashValue of their knot positions

First time to hear ” GetHashValue” I’m on max 2016.
The objects are editable poly .
to show the vertex order i used spline then converted to edit poly.
If i try to find the distance between the vertcies of 2 objects, one of them has 3 vert and other has 4
and in this example I can just find one of them which is the vert numer “3”

Sorry for this Easy question
found it.

For anybody else with the same problem searching in the future you should post the answer you found.

1 Reply
(@scriptlover)
Joined: 10 months ago

Posts: 0

Frankly & honestly
When i think that denis & othres guru guys can see my crazy solution
I’m really shy to share the codes
But when you say that
Tha is OK.
Here is my approach for the scene above

fn ColectVerPos obj VertAr= 
	(
	nVerts = obj.numverts
	for i=1 to nVerts do  (append VertAr (polyop.getvert obj i )	)
	) 	
--test1
select wire1
selectmore wire2
--test2
select wire2
selectmore wire1	
--collect the vertices
		obj1 = selection[1]
		obj1VertAr=#()	
		ColectVerPos obj1 obj1VertAr	

		obj2 = selection[2]
		obj2VertAr=#()	
		ColectVerPos obj2 obj2VertAr	

here was my mistake

The2VertAr =#()
for i = 1 to obj1VertAr.count do	
	(
		for k in obj1VertAr do --(print k)
		(
			if (distance k obj2VertAr[i] < 0.01) do (append The2VertAr k)
		)
	)

above code if you select the bigger poly (wire1) in vertices first , you face a problem.
and if you select lesser ploy in vert (wire2) first, you can just find one same vert .
and this is the better one

	The2VertAr=#()
	for k in obj2VertAr do 
	(
	 for i=1 to obj1VertAr.count do	
	 (
		if (distance k obj1VertAr[i] < 0.01) do (append The2VertAr obj1VertAr[i])
	 )
	)	
	
point pos:The2VertAr[1] wirecolor:red
point pos:The2VertAr[2] wirecolor:Yellow	

First of all, when you talk about “similar” floats (or any few floats — point2, point3, point4, color, matrix3, etc.), you should indicate how close they should be.
therefore, two floats (or doubles) in real life can simply be “close enough”. in other words, the “distance” between them is less than the specified tolerance.

“hash value” can only be used to search for exactly the same values.

Thanks denis for your participation
Frankly I didn’t understand what you’ve said
Would you give an example that my will not work and needs “hash value” .

1 Reply
(@serejah)
Joined: 10 months ago

Posts: 0

Thanks. I should have mention that.
Here’s the example:


delete objects

shp1 = convertToSplineShape (Rectangle width:100 length:100)
shp2 = convertToSplineShape (Rectangle width:100 length:100 pos:[100,0,0])
move #( shp1, shp2 ) [ 1.654, 2.6465, 3.5641 ]

/*
-- uncomment to see how hash value comparison fails when position of first vert changes even slightly
p1 = getKnotPoint shp1 1 1
setKnotPoint shp1 1 1 (p1 + [ 0.005, 0, 0 ] )
updateShape shp1
*/

for i=1 to numKnots shp1 do
(
	pt1 = getKnotPoint shp1 1 i	
	hash_value_1 = getHashValue pt1 0
	
	for j = 1 to numKnots shp2 do
	(
		pt2 = getKnotPoint shp2 1 j
		hash_value_2 = getHashValue pt2 0
		
		format "knot:% hash:%   knot:% hash:%\n" i hash_value_1 j hash_value_2
		
		if distance pt1 pt2 < 0.01 then
		(
			format "	Close verts: [ %, % ]   Hashes match: %\n" i j (hash_value_1 == hash_value_2)
		)
		
		format "\n" 
	)
	
)

your naive algorithm checks all verts of one mesh against all verts of another which is slow and inefficient
to make it faster you’ll have to use some accelerating structure
little interactive example:

struct Lookup2DGrid
(
	_minx =  1e6,
	_miny =  1e6,
	_maxx = -1e6,
	_maxy = -1e6,
	_min  = [0,0,0],
	_max  = [0,0,0],
	width, 
	height,
	step,
	size = [0,0],
	points,
	lookup2D,
			
	fn init pts gridsize =
	(		
		for p in pts where p != undefined do
		( 
			if p.x < _minx then _minx = p.x else (if p.x > _maxx do _maxx = p.x) 
			if p.y < _miny then _miny = p.y else (if p.y > _maxy do _maxy = p.y) 
		)
		
		_min = [ _minx, _miny, 0 ]
		_max = [ _maxx, _maxy, 0 ]
		
		points   = pts
		width    = _maxx - _minx
		height   = _maxy - _miny
		step     = gridsize
		size     = [ceil (width / step) , ceil (height / step)]
				
		lookup2D = for i=1 to size.x collect (for j=1 to size.y collect #())

			
		for i=1 to pts.count where pts[i] != undefined do
		(			
			index_x = 1 + int((pts[i].x - _minx)/step)
			index_y = 1 + int((pts[i].y - _miny)/step)
					
			append lookup2D[ index_x ][ index_y ] i			
		)
		
	),

	fn getNearestNeighbors pt offset:1 =
	(		
		index_x = 1 + (floor((pt.x - _minx)/step))
		index_y = 1 + (floor((pt.y - _miny)/step))
			
		indexes = #()
		for x = amax 1 (index_x-offset) to amin (index_x + offset) size.x do
		(
			for y = amax 1 (index_y-offset) to amin (index_y + offset) size.y do join indexes lookup2D[ x ][ y ]			
		)
		indexes	
		
	),
	
	fn getNearestIndex pt =
	(			
		mind = 1e6
		index = -1
		
		for i in getNearestNeighbors pt where (d = distance pt points[i]) < mind do (mind = d; index = i) 
		index		
	),
	
	fn getMinDistance pt =
	(			
		mind = 1e6
				
		indexes = getNearestNeighbors pt
		
		if indexes.count == 0 do return -1
		
		for i in indexes where (d = distance pt points[i]) < mind do mind = d
		
		mind		
	)
)



delete objects
gc light:true

actionMan.executeAction 0 "551"
p = plane widthsegments:12 lengthsegments:12 wirecolor:black
convertToPoly p
rotate p (EulerAngles 0 0 23.5)

lg = Lookup2DGrid()
lg.init (for i=1 to polyop.getNumVerts p collect polyop.getVert p i) 2.0


move_me = point centermarker:on cross:off wirecolor:yellow isSelected:true
h2 = point wirecolor:red

deleteAllChangeHandlers id:#xxx
when transform move_me change id:#xxx val do
(
	nearest_index = lg.getNearestIndex val.pos
	
	if nearest_index > 0 do
	(
		h2.pos = lg.points[ nearest_index ]
	)
	
)

btw. What’s the best way to find closest grid cell to arbitrary point in space?

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

kd-tree

Thank you for the example