Notifications
Clear all

[Closed] vertex distance part 2

 em3

In this new scenario, I have an object imported from CAD that has a group of verticies that sit far away from the object itself and have no relevance to it.

What I would like to do is find where those verts are and delete them. Here is how I was going to do it:


 z = $.verts
 c=0
 cont = false
 for i = 1 to z.count do
 (
 	cont = false
 	tolerance = 675
 	n = i+1
 	if n <= z.count then ( cont = true )
 	if cont then
 	(
 	v1 = $.verts[i].pos
 	v2 = $.verts[n].pos
 	a = distance v1 v2
 	if a > tolerance then (	print ("Vert1 position: %n" + v1 as string + "Vert2 position: %n" + v2 as string   ))
 	if a > tolerance then c+=1
 	if n == z.count do (print c)
 )
 )
 

In this script I am getting the distance between the verts and if they bust the tolerance, I flag them. This works for this scenario but not all others.

Another approach I was thinking of was to loop through the verts, align the pivot to center/min xyz and then center/max xyz, get the distance between the pivot and the vert, if it’s 0, delete it. This will work.

For simplicity sake, is there an easier way than the below method?

the pseudo code version


 get min/max of object
 collect verts
 for each vert
 align the pivot to min xyz/max xyz
 if distance of vert to pivot = 0 then delete it
 

Thanks!

8 Replies
 em3

Here is an example I should have posted. Turns out the verts are actually an element of the mesh.

Is it possible to get the elements position?

when I get the verticies distance from the pivot after aligning the pivot to the min I get this


1350.33
1350.33
1351.99
1355.31
1355.32
1355.96
7628.31
7628.31
7628.31
7628.31
7628.31
7628.32
7628.32
7628.32

I can see where the problem verts start (7628.31), I am just not sure how to handle it from there.

Thanks,

Dave

will your CAD imported mesh always be one mesh with one stray subelement, or could there be multiple meshes with multiple stray subelements? what scenarios / cases should the script cater to?

if your CAD mesh (that you want to keep) imports near the origin, you could: detach all subelements, center pivots, delete objects where object.pos is greater than tolerance.

if your CAD mesh has many subelements, but still has far away stray vertices, you could: detach all subelements, select object with greatest num of verts, delete objects where boudingBox does not overlap object with greatest num of verts.

if the stray verts are always predictably smaller than the mesh you want to keep, you could: detach all subelements, for node in geometry do collect boundingBox of node, delete node with boundingBox min/max less than tolerance min/max.

as i understood the idea is to delete all isolated pieces of geometry smaller than certain value.
well… we don’t need to detach these elements.
– find all elements
– value elements by:
#1: bounding box (you can find the code in this forum)
#2: maximum face area
#3: average face area

– delete small pieces

where is the problem?

 em3

Thanks for the replies! I like both methods. In this case, each object comes in as a few elements. It tuns out that each element I want to delete contains exactly 30 verts. I was looking for a meshop way to count the vertices each element and then delete the one with 30. I suppose I could take each face and multiply it by 3 to get the total face vertices but then how to derive the real vert count from there? Any hints there?

I know I can get the bounding box of the object, but how do I get the bounding box of each element?

Thanks guys!

ps proOptimizer fixed it but I won’t always want to use PO so I will still try to work this out. I will post my solution when I find it

Thanks!

Here is a script that will delete any subelement or node in the scene with 30 vertices.
Feel free to modify it to meet your needs:


fn detachSub myMesh =
(
myMesh.EditablePoly.SetSelection #Face #{1}; myMesh.SelectElement()
local theFaces = polyop.getFaceSelection myMesh
polyop.detachFaces myMesh theFaces delete:true asNode:true name:"Fragment"
local maxFaces = polyop.getNumFaces myMesh
format "maxFaces:%
" maxFaces
if maxFaces > 0 then detachSub myMesh else delete myMesh
)
for node in geometry do detachSub node
	
for node in geometry do
(
	local myVertCount = node.GetNumVertices ()
	if myVertCount = 30 then delete node
)

I detached the subelements to nodes because it exposed more properties. I’m not sure how to get the bounding box of a set of vertices, but you can get the bounding box of a node like this:


--create an object in max and select it
(
local myBoundingBox = $.max - $.min
print myBoundingBox[1] --width of bounding box
print myBoundingBox[2] --length
print myBoundingBox[3] --height
)

So from that, you could write something like:
for node in geometry do if node.boundingBox < tolerance then delete node
That psuedocode would delete the node if it was smaller than a certain tolerance.

I’m interested in seeing how to determine the boundingBox of a set of vertices, as that could come in very handy…

You may run into a problem where the nodes in your scene aren’t all editablePoly meshes. This will cause the script above to break, as it expects the node to be an editablePoly mesh (as it uses editablePoly commands). Here is an appended script that will work for all cases:

[left]


 fn detachSub myMesh = 
 ( 
 myMesh.EditablePoly.SetSelection #Face #{1}; myMesh.SelectElement() 
 local theFaces = polyop.getFaceSelection 
 myMesh polyop.detachFaces myMesh theFaces delete:true asNode:true name:"Fragment" 
 local maxFaces = polyop.getNumFaces myMesh 
 format "maxFaces:%
" maxFaces 
 if maxFaces > 0 then detachSub myMesh else delete myMesh 
 ) 
 
 for node in geometry do 
  (convertToPoly node; detachSub node)
  
for node in geometry do 
 (
 local myVertCount = node.GetNumVertices () 	
 if myVertCount = 30 then delete node 
 )

[/left]

 em3

Thanks, TheGrak! I will check it out and reply back here.

 em3

alrighty, so I ran out of time on the last project to look at this. Fortunately a new project came around and my OCD kicked in so I took another stab at it.

I got farther and have found the problem verts y position with this humongous over-worded code. I could have picked x,y,or z as all of the problem verts are on the same position if you round them up. Now that I write this out it seems I could have just said…

Pseudo:

for v in verts where WHEN V.X,Y,Z ARE ROUNDED UP ARE ALL IN THE SAME POSITION collect v

Anyway, here is what I have.

If you have tips on code optimization here I am all ears.



global iamx = false

fn wtf xyarr = --fn to collect and reduce the verticies y location array
(
	thexymin = amin xyarr
	thexymax = amax xyarr

	theOp = for c in xyarr where c == thexymin collect c
	if theOp.count > 0 then
	(
	reducearray theOp
	print theOp
		return theOp
	)
)


TheVv = #()
for o in selection where matchpattern o.name pattern:"*Level 1" do
(

bb=o.max-o.min --bounding box
if bb[1]>bb[2] then iamx=true --which direction should I be looking for isolated verts
cond1 = ceil (bb[1]*.01) --method to identify type of object
cond2 = ceil (bb[2]*.01)
if cond1==cond2 then
(
theRad = cond2
theHeight = bb[1]*2
if bb[3] > theHeight then
(
append theVv o
)
)

theVerts = for v in o.verts collect v -collect verts

i=0
theb = #()
thexyarr = #()
theyarr = #()
findIso = #()

	for v = 1 to theVerts.count do
(
	tv=theverts[v]
	if iamx == true then append thexyarr (ceil tv.pos[1]) else append thexyarr (ceil tv.pos[2]) --grab the vert x or y position depending on which direction the object is facing
)
if thexyarr.count > 0 then
(
	findIso = wtf thexyarr --process and reduce the array
)

)

-- 	 if findIso.count == 1 then  --if findIso (result of the processed array) = 1 then we have found the y position of all verts that need to be removed. Now I have to loop through the verts again and collect all verts that have that y position. Denis T could do this in one line.

-- 	(
-- 		theDverts = for v in o.verts where ceil v.pos[2] == findIso collect v -- <-- does not work
--        )