'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
' JPolygonHealer_11 (c)
' javier@internarte.com
'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'This script will find all holes on a polygon selection and:
'1. cap polygons collapsing them outputting the selection of new polygons .
'2. and or, clean up new polygons by dissolving them.
'3. &/o Select all polygon boundaries

'If your original holes have common points, the capping may not be perfect.
'to fix this, just call the command again and the Healer with answer your prayers.
'caveat1. script is a bit slow but it works.
'caveat2. this method could produce self intersecting polygons. 
'I have fixes in the works but.., not yet, not free.
'UI Control
'********************************************************************************

option Explicit
dim oSel, oPolySel,oThing, oSelList, oEdgeSel, oItem,oGeometry,i,j,k, index
dim oNb2D,o2DGeometry, o2DNeighborhood
dim oNb1D,o1DGeometry,o1DNeighborhood
dim oNb0D,o0DGeometry,o0DNeighborhood
dim oRoot, oInput, oNote1, oCAP, oESel, oCleanup
dim oPtSel, oNewPtSel,oEdgePtSel,oEdgesSel
dim HoleCounter


set oRoot = ActiveProject.ActiveScene.Root
HoleCounter = 0
SetValue "*.camvis.attrselboundaryflags", True 

'SetValue "Views.*.*.camvis.attrselboundaryflags", True 
'***comment ^this setvalue line if you do Not want ALL Views 
'to have boundary flag visibility on. I nearly always do.

DO

'//UI 
	Set oInput =oRoot.AddProperty("custom_parameter_list",,"POLYGON BOUNDARIES")
		Set oNote1 =oInput.AddParameter2( "THIS FINDS", siString,,,,,,,2) 	
		set oCAP = oInput.AddParameter2( "CAP HOLES", siBool,,,,,,,4)	
		set oESel = oInput.AddParameter2( "SELECT Boundaries", siBool,,,,,,,4)	
		set oCleanup = oInput.AddParameter2( "Dont Clean Caps", siBool,,,,,,,4)				
	
	'********************* UI DEFAULT VALUES >
			oNote1.value = "POLYGON Boundaries, SELECTS, EXTRACTS, or CAPS them"
			oCAP.value = 1
			oESel.value = 0
			oCleanup.value = 0			
	'<********************
										
	on Error Resume Next	'//Open UI up
		InspectObj oInput,,"POLYGON_BOUNDARIES",siModal
		if err.Number <> 0 then
			Deleteobj oInput
			EXIT DO
		end if
	Err.Clear
	on Error Goto 0

	ActivateObjectSelTool	

	set oSel = CreateObject("XSI.Collection")
	set oEdgePtSel = CreateObject("XSI.Collection")
	set oNewPtSel = CreateObject("XSI.Collection")
	set oEdgesSel = CreateObject("XSI.Collection")

'//convert to Branch Selection if Necessary

	oSel.additems selection
	FOR index = 0 to oSel.Count -1
		set oThing = oSel(index)
		if oThing.Branchflag = 1 then
			SelectChildNodes
		end if
	NEXT

	set oSelList = GetValue("SelectionList")  
'//Loop  through all selected objects
	FOR k = 0 to oSelList.count -1 
		set oEdgeSel = CreateObject("XSI.Collection")
		set oPtSel = CreateObject("XSI.Collection")
		set oItem = oSelList(k) 
		logmessage oItem.type
		IF oItem.type = "polymsh" then
			set oGeometry = oItem.obj 
		
			oNb0D = oGeometry.Nb0D	' number of points
			oNb1D = oGeometry.Nb1D	' " 		lines
			oNb2D = oGeometry.Nb2D 	' " 		polygons
	
			SetSelFilter "Edge"
				Deselectall

			set oPolySel = CreateObject("XSI.Collection")
' Geometry1D has been replaced by Segment, but it works better for me!
			set o2DGeometry = oGeometry.Geometry2D 
			set o1DGeometry = oGeometry.Geometry1D 
			set o0DGeometry = oGeometry.Geometry0D 
			
				oPolySel.add oItem&".poly[*]"
				oPtSel.add oItem&".pnt[*]"


'//Build EdgeCollection
'i could not find an attribute to select Boundaries in Polymeshes
'so I had to build it. edges have only 1 adjacent polygon.
			FOR i = 0 to oNb1D - 1  
				o2DNeighborhood = o1DGeometry.Neighborhood2D( i, 1 )  
				if UBound( o2DNeighborhood, 1 ) = 0 then 	''> 	THERE IS A HOLE!!
					oEdgeSel.add oItem&".edge["&i&"]"
					oEdgesSel.add oItem&".edge["&i&"]" 'pass to Global boundary collection

			end if
			NEXT			
		
			IF oEdgeSel.count > 0 THEN	
				HoleCounter = HoleCounter + 1			
				AddToSelection oEdgeSel , , True 
				
					IF oCAP.value = "True" then	'> CAP POLYGON
					DuplicateMeshComponent , siPersistentOperation			
					ApplyTopoOp "Collapse", , siUnspecified, siPersistentOperation	
						IF oCleanup.value = "False" then	'>CLEAN NEW CAP
							SelectGeometryComponents oPtSel
							ToggleSelection oItem&".pnt[*]", , True			
							ApplyTopoOp "DissolveComponent", , siUnspecified, siPersistentOperation
						END IF
					SetSelFilter "Polygon"
					Selectobj oPolySel
					ToggleSelection oItem&".poly[*]", , True		
				END IF		
			END IF
		ELSE 
			logmessage "Object "&oItem.name&" is not a polygon" 
		END IF
	NEXT

	IF HoleCounter > 0 THEN
		ActivateObjectSelTool
		Selectobj oSel
		SetSelFilter "Polygon"

		if oESel.value = "True" then
			SetSelFilter "Edge"
			Selectobj oEdgesSel	
		end if
	ELSE
		logmessage " THESE POLYGONS HAVE NO HOLES"
	END IF 
	Deleteobj oInput
EXIT DO
LOOP
'------------------------------------------

