Extend Edit_Poly to have Select Face by Area


#1

I have always wanted a modifier like volSelect that selects polygons based on area. It would be important that it update the selection as the topology below it in the stack changes.

I’m doing something wrong with the function. This doesn’t do anything as written but if I create the function outside the plugin first, then the plugin at least prints the face selection… but I still haven’t gotten it to update the actual face selection.

plugin modifier pSelByArea 
 name:"SelByArea" 
 classID:#(0x45b71d21, 0x637cf590)
 extends:Edit_Poly replaceUI:false version:2
 (
    fn setFaceSelByArea obj areaVal =
    (
 	   local theSelection = #{}
 	   local num_faces = obj.getNumFaces()
 	   for f = 1 to num_faces do
 	   (
 		   local face_Area = obj.GetFaceArea f
 		   if face_Area >= areaVal do append theSelection f 
 	   )
 	   print theSelection
 	   return theSelection
    )
    
    parameters params_Area rollout:rol_SelByArea
    (
 	   spn_MinArea type:#float animateable:true ui:spn_MinArea default:10
 		   on spn_MinArea set val do
 		   (
 			   face_Selection = setFaceSelByArea delegate val
 			   delegate.SetSelection #Face face_selection
 			   delegate.SetEPolySelLevel #Face
 		   )
    )
 
    rollout rol_SelByArea "Select By Area"
    (
 	   spinner spn_MinArea "Min Area: " range:[0.01,1e9,20]
    )
 )

#2

I change only this
if face_Area <= areaVal do append theSelection f
and it works


#3

Thanks for testing.
It works for me either way. I think when I tested it before, the object was so small in system units that it the Min Area value was not accurate enough to get subtle selections.

Can (should) I put a callback in the modifier to update if the stack topology changes? My gut tells me it’s a bad idea.


#4

I think using Get handler is a good idea for that purpose

fn setFaceSelByArea obj areaVal =
(
	local theSelection = #{}
	local num_faces = obj.getNumFaces()
	for f = 1 to num_faces do
	(
		local face_Area = obj.GetFaceArea f
		if face_Area <= areaVal do append theSelection f 
	)
	obj.SetSelection #Face theSelection
	obj.SetEPolySelLevel #Face
)
...
on spn_MinArea set val do
(
	setFaceSelByArea delegate val
)
on spn_MinArea get val do
(
	setFaceSelByArea delegate val ; val
) 

#5

here is a possible solution but more spec here than me can tell is it fine

plugin modifier polySelByArea 
name:"Select By Area" 
classID:#(0x45b71d21, 0x637cf590)
extends:Edit_Poly replaceUI:false version:2
(
	 fn mainCbFn ev nd =
	 (
		 local ob = (GetAnimByHandle nd[1])
		 if isValidNode ob do
		 (
			 for m in ob.modifiers where
			 classOf m == polySelByArea and m.setUpdate do m.minArea
		 )
	 )
 
	 fn setFaceSelByArea obj areaVal =
	 (
		 local theSelection = #{}
		 local numFaces = obj.getNumFaces()
		 for f = 1 to numFaces do
		 (
			 local face_Area = obj.GetFaceArea f
			 if face_Area <= areaVal do append theSelection f 
		 )
			 obj.SetSelection #Face theSelection
			 obj.SetEPolySelLevel #Face
	 )
 
	 parameters params_Area rollout:rol_SelByArea
	 (
		 minArea type:#float animateable:true ui:spn_MinArea default:20
		 setUpdate type:#boolean ui:chb_SetUpdate default:false
 
		 on minArea set val do
		 (
			 setFaceSelByArea delegate val
		 )
		 on minArea get val do
		 (
			 setFaceSelByArea delegate val ; val
		 )
	 )
 
	 rollout rol_SelByArea "Select By Area"
	 (
		 spinner spn_MinArea "Min Area: " range:[0.01,1e9,20]
		 checkbox chb_SetUpdate "Auto Update"
	 )
 
	 on create do
	 (
		 NodeEventCallback geometryChanged:mainCbFn topologyChanged:mainCbFn
	 )
 
	 on postLoad do
	 (
		 NodeEventCallback geometryChanged:mainCbFn topologyChanged:mainCbFn
	 )
 
) 

EDIT* … woops, little correction needs for creating the callback only once in ‘on create’ and ‘on postLoad’:

if ::cbUpdateModSelByArea == undefined do
	cbUpdateModSelByArea = NodeEventCallback geometryChanged:mainCbFn topologyChanged:mainCbFn


#6

That’s better. It acts a little funny but it is decent. Thanks for the additions. :thumbsup:


#7

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.