=begin
(c) 2013, Anar | Dan Rathbun | Pilou | Renderiza | TIG

Permission to use, copy, modify, and distribute this software for
any purpose and without fee is hereby granted, provided 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.

== Information
Author:: Anar | Dan Rathbun | Pilou | Renderiza | TIG
Name:: FaceSplit
Version:: 1.0.3
SU Version:: 2013
Date:: 11/4/2013
Description:: Split faces up a variety of ways.
=end

module RND_Extensions
	#
	module RND_FaceSplit
		#
		class FaceSplit
			@@model = Sketchup.active_model
			@@path = File.dirname(__FILE__)
			@@rnd_facesplit = "rnd_facesplit.html"
			@@facesplit_dlg = nil
			#
			def initialize()
				@facesplit_1_file = File.join(@@path, @@rnd_facesplit)
				if (!@facesplit_1_file) then
					UI.messagebox("Cannot find file '#{@@rnd_facesplit} in folder '#{@@path}'")
					return
				end
				#
				if @@facesplit_dlg == nil
					@@facesplit_dlg = UI::WebDialog.new("FaceSplit v1.0.3", false, "FaceSplit v1.0.3", 190, 320, 250, 250, true)
					@@facesplit_dlg.add_action_callback("push_frame") do |d,p|
						push_frame(d,p)
					end
				end
				#
				if @@facesplit_dlg.visible? == false
				@@facesplit_dlg.set_size(190, 320)
				end
				@@facesplit_dlg.set_file(@facesplit_1_file)
				@@facesplit_dlg.show()
				@setsize = true
				#
				Sketchup.send_action('selectSelectionTool:')
			end


			def push_frame(dialog,data)
				params = query_to_hash(data)
				model = Sketchup.active_model
				sel = model.selection
				#
				############
				# Minimize #
				############
				if params['min'].to_s == "true" && @setsize == true
					@@facesplit_dlg.set_size(190, 190)
					@setsize = false
				end
				if params['min'].to_s == "false" && @setsize == false
					@@facesplit_dlg.set_size(190, 320)
					@setsize = true
				end
				#########
				# start #
				#########
				if params['split_start'].to_s != ""
				@split_start = params['split_start'].to_f
				else
				@split_start = params['split_end'].to_f
				end
				#######
				# end #
				#######
				if params['split_end'].to_s != ""
				@split_end = params['split_end'].to_f
				else
				@split_end = params['split_start'].to_f
				end
				#
				if params['split'].to_s == "true" 
					split()
					running = 1
					script = "top.running = " + running.to_s + ";"
					dialog.execute_script(script)
				end
			end


			def split()
				model = Sketchup.active_model
				ents = model.active_entities
				sel = model.selection
				faces = sel.grep(Sketchup::Face)
				#
				caras = []
				edges = []
				avg = []
				dl = []
				remove = []
				#
				model.start_operation('csplit')
					#
					faces.each do |face|
						loops = face.loops
						#
						if loops.length == 2
							verts1 = loops[0].vertices
							verts2 = loops[1].vertices
							#
							verts1.each do |v1|
								p1 = v1.position
								test = true
								nearest = 0
								fp = v1
								#
								verts2.each do |v2|
									p2 = v2.position
									distance = p1.distance p2
									#
									if distance <= nearest || test == true
										test = false
										nearest = distance
										fp = v2
									end
									#
								end#verts2.each
								#
								##############
								## Add Line ##
								##############
								sss = ents.add_line( p1, fp )
								connected = sss.all_connected
								sel.add connected
							end#verts1.each
							#
						end#if loops.length > 1
						#
					end#faces.each
					#
					#
					faces = sel.grep(Sketchup::Face)
					#
					faces.each do |face|
						loops = face.loops
						#
						if loops.length == 1
						############
						# Centroid #
						############
						sum = Geom::Point3d.new(0,0,0)
						verts = face.vertices
						n = verts.size.to_f
						verts.each {|v| sum += ORIGIN.vector_to(v.position) }
						###########
						# Medians #
						###########
						lines = face.edges

						if @split_start != 0
							###########
							## Start ##
							lines.each {|e|
								e1 = e.start.position
								e2 = e.end.position
								d = e.length
								r = (d / @split_start) / d
								x = r * e2.x + (1 - r) * e1.x
								y = r * e2.y + (1 - r) * e1.y
								z = r * e2.z + (1 - r) * e1.z
								dl << Geom::Point3d.new( x, y, z )
							}
							#
							avg << Geom::Point3d.new( sum.x/n, sum.y/n, sum.z/n ) #/
							edges << face.edges
							caras << face
						end

						if @split_end != 0
							#########
							## END ##
							lines.each {|e|
								e1 = e.start.position
								e2 = e.end.position
								d = e.length
								r = (d / @split_end) / d
								x = r * e1.x + (1 - r) * e2.x
								y = r * e1.y + (1 - r) * e2.y
								z = r * e1.z + (1 - r) * e2.z
								dl << Geom::Point3d.new( x, y, z )
							}
							#
							avg << Geom::Point3d.new( sum.x/n, sum.y/n, sum.z/n ) #/
							edges << face.edges
							caras << face
						end
						end
					end # each face

					#########
					# Split #
					#########
					caras.each do |face|
						centroid = avg.shift
						edges.shift.each {|e|
							lc = dl.shift
							make = ents.add_line( centroid, lc )
							#
							if make.used_by? face
							else
								remove << make
							end
						}
					end
					#
					#
					sel.clear
					remove.each do |r|
						if r.faces.length == 0
							sel.add r
						end
					end
					sel.each do |e|
						e.erase!
					end
					#
					UI.beep

				model.commit_operation
				#
				rescue => e
				puts "Error <#{e.class.name}: #{e.message} >"
				puts e.backtrace if $VERBOSE
				#
				model.abort_operation
			else # when no errors:
				#sel.clear
			end # medians_to_centroid()


			def unescape(string)
				if string != nil
					string = string.gsub(/\+/, ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n) do
						[$1.delete('%')].pack('H*')
					end
				end
				return string
			end


			def query_to_hash(query)
				param_pairs = query.split('&')
				param_hash = {}
				for param in param_pairs
					name, value = param.split('=')
					name = unescape(name)
					value = unescape(value)
					param_hash[name] = value
				end
				return param_hash
			end
			#
		end #class
		#
	end #module
	#
end #module
#
file_loaded( File.basename(__FILE__) )