
'EDGE SELECTION V 1.1 by Reinhard Claus ray@giga4u.de
'The script selects edges along paths originating from an initial 
'selection of edges. A path ends when a point with an odd number of fan edges
'is encountered or the according initial edge is hit. Otherwise the path continues
'along the central edge of the fan. If you want the selecting to stop only at points 
'with 3 fan edges, edit the function findgoodedge in the following way:
' 	...........
'	...........
'  loop while UBound(edges) < UBound(star)-2 
'	subtract_array edges, star 
'	if UBound(star) = 0 or UBound(star) = 1 then
'		findgoodedge = star(0)
'	end if
'
'the next version will let you choose how many
'edges are selected in both directions (with sliders)

dim oSelection, SelectedEdge, oGeometry 'global variables
dim visited
visited = Array(-1)

select_edgeloop

sub select_edgeloop
	''''''single object must be selected
	if Application.Selection.Count <> 1 then
		LogMessage "INVALID SELECTION", siError
		exit sub	
	end if
	set oSelection = Application.Selection.Item(0)
	
	''''''one or more edges must be selected
	if oSelection.Type <> "edgeSubComponent" then
		LogMessage "INVALID SELECTION", siError
		exit sub
	end if
	set oGeometry = GetValue(oSelection.Name).obj
	SelectedEdges = oSelection.SubElements	
	for each SelectedEdge in SelectedEdges
		append SelectedEdge, visited
		adjacentPointsArray = oGeometry.Geometry1D.Neighborhood0D( SelectedEdge, 1 )
		continueatpoint adjacentPointsArray(0), SelectedEdge 'extend selection in direction one	
		continueatpoint adjacentPointsArray(1), SelectedEdge 'extend selection in direction two
	next
end sub

sub continueatpoint(point, fromedge)
	'''get edges shining from point
	star  = oGeometry.Geometry0D.Neighborhood1D( point, 1 ) 
	
	goodedge = findgoodedge(fromedge, star)
	if goodedge <> -1 then 
		AddToSelection oSelection.Name & ".edge[" & goodedge & "]"
		append goodedge, visited 
		
		'''choose the right direction to continue
		adjacentPointsArray = oGeometry.Geometry1D.Neighborhood0D( goodedge, 1 )
		if adjacentPointsArray(0)=point then
			continueatpoint adjacentPointsArray(1), goodedge 	
		else 
			continueatpoint adjacentPointsArray(0), goodedge 
		end if							
	end if
end sub

function findgoodedge(fromedge, star)
	findgoodedge = -1
	
	''''clear array of bad edges
	edges = Array(-1) 
	oldedges = Array(-1)
	
	''''fromedge is always bad
	append fromedge, edges 
	do
		'''''get adjacent polys of the bad edges
		o2DNeighborhood = oGeometry.Geometry1D.Neighbors2D(edges, 1)
			
		'''''now get adjacent edges thereof
		o1DNeighbors = oGeometry.Geometry2D.Neighbors1D( o2DNeighborhood , 1)
		
		'''''remove all edges from these but those inside the star, these are the new bad edges
		edges = o1DNeighbors									
		subtract_array star, o1DNeighbors
		subtract_array o1DNeighbors, edges 
		
		'''''emergency exit (workaround for a special case)
		if UBound(oldedges) = UBound(edges) then exit function end if
			
		oldedges = edges
		
	'''''stop if all but 1 edges are bad (the good edge)
	loop while UBound(edges) < UBound(star)-1		
						
	subtract_array edges, star
	
	'''''if there is one element in array return it if it's not already visited
	if UBound(star) = 0 then 			
		if get_ix(star(0), visited) = -1 then
			findgoodedge = star(0)
		end if
	end if
end function






'''''''little helpers library'''''''''

'''''remove i-th item from array
sub remove(i, ra) 
	if i = -1 then exit sub end if
	ra(i) = ra(UBound(ra))
	redim PRESERVE ra(UBound(ra)-1)
end sub

'''''remove array "ra" from array "ra_removefrom"
sub subtract_array(byval ra, ra_removefrom) 	
	for each r in ra
		remove get_ix(r, ra_removefrom), ra_removefrom
	next
end sub

''''' append item to array
sub append(byval v, ra) 
	if ra(0)<>-1 then redim PRESERVE ra(UBound(ra)+1) end if
	ra(UBound(ra))=v
end sub

'''''get index of first elem with value v or -1
function get_ix(byval v, ra) 
	get_ix = -1
	for i = LBound(ra) to UBound(ra)
		if ra(i) = v then get_ix = i end if
	next
end function	