=begin
Copyright 2004-2005 by Rick Wilson [in parts], and 2012-2016 (c) TIG.

Permission to use, copy, modify, and distribute this software for 
any purpose and without fee is hereby granted, provided that the above
copyright notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
TIG-weld_code
#
Description:-
Joins selected edges into a 'curve' (~"polyline").
#
Author:-
TIG - based somewhat on RickW's 'weld.rb'...
[but it has no close/face options, and also made suitable to be called from 
other methods].
#
Usage:-
Make a selection which includes the edges to be joined.
Run the script from the menu:
Tools > TIG-weld
or type in the Ruby Console:
TIG.weld +<enter>
or [recommended] set up a shortcut-key, say J [==Join?]
#
Selected edges will then be 'welded' into a curve wherever possible.
Disconnected edges or branching edges might give unexpected results.
A curve will be split where any 'branching' edge intersects it.
The process is one step undoable.

To use the tool run within another method include:
  require('TIG-weld.rb')
*** >= v2.0 use:
  require('TIG-weld/TIG-weld_code.rb')
to load it even if its extension is deactivated;
and later in the code use:
  TIG.weld(true)***
use the 'true' to supress 'undo' complications. 
It returns an array of the welded edges or 'nil' if none.
The calling method must make a selection of potential edges to 
process, even if inside another context; perhaps iterated in turn, 
see scripts like "TIG-weldall.rb" for an example of this...
#
Version:-
1.0 20120305 First public issue.
2.0 20160130 Made into Extension. Signed for v2016 full compatibility.
***Note: with v2.0 the alternative to TIG.weld() can be TIG::Weld.new()***
=end
module TIG
	###
	def self.weld(rep=false) ### to NOT break earlier bound code
		TIG::Weld.new(rep)
	end
	###
	module Weld
		###
		unless file_loaded?(__FILE__)
			UI.menu("Tools").add_item(NAME){ self.new() }
			file_loaded(__FILE__)
		end
		###
		def self.new( rep = false )
			model=Sketchup.active_model
			sel=model.selection
			verts=[]
			newVerts=[]
			startEdge=startVert=nil
			#GET EDGES & VERTICES
			edges=sel.grep(Sketchup::Edge)
			return nil if edges.length < 2
			ents=edges[0].parent.entities
			edges.each{|e| verts << e.vertices }
			verts.flatten!
			#FIND AN END VERTEX
			vertsShort=[]
			vertsLong=[]
			verts.each{|v|
				if vertsLong.include?(v)
					vertsShort << v
				else
					vertsLong << v
				end
			}
			if (startVert=(vertsLong-vertsShort)[0])==nil
						startVert=vertsLong[0]
						closed=true
					startEdge=startVert.edges[0]
			else
					closed=false
					startEdge=(edges & startVert.edges)[0]
			end
			#SORT VERTICES, LIMITING TO THOSE IN THE SELECTION SET
			if startVert==startEdge.start
				newVerts=[startVert]
				counter=0
				while newVerts.length < verts.length
					edges.each{|edge|
						if edge.end==newVerts[-1]
							newVerts << edge.start
						elsif edge.start==newVerts[-1]
							newVerts << edge.end
						end
					}
					counter+=1
					if counter > verts.length
						newVerts.reverse!
						reversed=true
					end
				end
			else
				newVerts=[startVert]
				counter=0
				while newVerts.length < verts.length
					edges.each{|edge|
						if edge.end==newVerts[-1]
							newVerts << edge.start
						elsif edge.start==newVerts[-1]
							newVerts << edge.end
						end
					}
					counter+=1
					if counter > verts.length
						newVerts.reverse!
						reversed=true
					end
				end
			end
			newVerts.uniq!
			newnewVerts=[]
			newVerts.each_with_index{|v, i|
				break if i==newVerts.length-1
				newnewVerts << v
				edged=false
				edges.each{|e|
					if e.start.position==v.position && e.end.position==newVerts[1+i].position
						newnewVerts << newVerts[1+i]
						edged=true
						break
					elsif e.end.position==v.position && e.start.position==newVerts[1+i].position
						newnewVerts << newVerts[1+i]
						edged=true
						break
					end
				}
				break unless edged
			}
			return nil unless newnewVerts[1]
			newnewVerts.reverse! if reversed
			newnewVerts << newnewVerts[0] if closed
			#CREATE THE CURVE
				###
				model.start_operation(NAME, true) unless rep
				###
			###
			edges.each{|e| e.explode_curve if e.curve && newnewVerts.include?(e.start) }
			group = ents.add_group()
			gents = group.entities
			curve = gents.add_curve(newnewVerts)
			group.explode
				###
				model.commit_operation unless rep
				###
			sel.clear
			###
			return curve ### returns an array of the welded edges.
			###
		end#def
	end
end#module
