Logo Passei Direto
Buscar
Material

Esta é uma pré-visualização de arquivo. Entre para ver o arquivo original

SDM_FloorGenerator.rb
#------------------------------------------------------------------------------------------------
# Permission to use, copy, modify, and distribute this software for 
# any purpose and without fee is hereby granted.
#------------------------------------------------------------------------------------------------
# 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.
#------------------------------------------------------------------------------------------------
# THIS PLUGIN IS ANOTHER FIGMENT OF MY IMAGENATION AND IS NOT BASED ON OR COMPLY WITH ANYTHING! 
#------------------------------------------------------------------------------------------------
# IT WAS CREATED AND ONLY TESTED IN A WINDOWS ENVIRONMENT AND MAY NOT FUNCTION ON A MAC.
#------------------------------------------------------------------------------------------------
# Name:	SDM_FloorGenerator
# By:	sdmitch
# Usage:	Plugins>SDM Tools>Face Tool>FloorGenerator
#		 Note:	The grid pattern will be placed on the side of the face picked starting at the
#						closest corner to the pick point if origin corner is selected. The grid pattern can 
#						be placed on faces of any orientation,ie vertical or horizontal. The grid pattern
#						will be painted with the current material, random color or material as selected.
#						The materials to be randomly applied may be in any folder. The Material Picker window
#						has multiple selection capability using the Ctrl or Shift Key. Ctrl+A does not work! 
#						The Clapboard pattern can only be placed on a VERTICAL face.
# Ceated:	Jun 2015
# Updated:	Mar 2017
#------------------------------------------------------------------------------------------------
require 'Sketchup'
# ------------------ MENU SETUP ---------------------- #
unless $sdm_tools_menu
	$sdm_tools_menu = UI.menu("Plugins").add_submenu("SDM Tools")
	$sdm_Edge_tools = $sdm_tools_menu.add_submenu("Edge Tool")
	$sdm_Face_tools = $sdm_tools_menu.add_submenu("Face Tool")
	$sdm_CorG_tools = $sdm_tools_menu.add_submenu("CorG Tool")
	$sdm_Misc_tools = $sdm_tools_menu.add_submenu("Misc Tool")
end
unless file_loaded?(__FILE__)
	$sdm_Face_tools.add_item('FloorGenerator') { Sketchup.active_model.select_tool SDM::SDM_FloorGenerator.new }
	tb=UI::Toolbar.new("FlrGen")
	cmd=UI::Command.new("FlrGen") { Sketchup.active_model.select_tool SDM::SDM_FloorGenerator.new }
	cmd.small_icon=cmd.large_icon=File.join(File.dirname(__FILE__).gsub('\\','/'),"FG_Icons/Brick.jpg")
	cmd.tooltip="Floor Generator";tb.add_item cmd;tb.show unless tb.get_last_state==0
	file_loaded(__FILE__)
end
# ------------------------------------------------------ #
module SDM
	extend self
	class SDM_FloorGenerator
		@@dlg_FG_Main=@@opt=nil
		
		def initialize
			@mod=Sketchup.active_model
			@ent=@mod.active_entities
			@sel=@mod.selection
			@vue=@mod.active_view
			@ip=Sketchup::InputPoint.new
			@colors=Sketchup::Color.names
			@separator = begin;'1.0'.to_l;'.';rescue;',';end
			@icons = File.join(File.dirname(__FILE__).gsub('\\','/'),"FG_Icons/"); #puts @icons
			RUBY_PLATFORM =~ /(darwin)/ ? @font="Helvetica" : @font="Arial"
			@current_units=Sketchup.active_model.options["UnitsOptions"]["LengthUnit"]
			@current_precision=Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"]
			@@opt ||= "Tile"; @@opt=Sketchup.read_default("FloorGenerator","",@@opt)
			self.dialog; self.source_of_textures if @app == "Rand_Tex"; 
		end
		
		def dialog
			@@dlg_FG_Main=UI::WebDialog.new("FloorGenerator", false,"BTW",220,600,10,10,true)
			@failed=false; update_wd
			@@dlg_FG_Main.add_action_callback("OptionChanged") {|d,p|
				var,val = p.split("="); update=false; puts p
				case var
					when "CBT" then @cbt = val.to_l
					when "CBW" then @cbw = val.to_l
					when "CBO" then @cbo = val.to_l
					when "BTL" then @GX = val.to_l
					when "BTW" then @GY = val.to_l
					when "BGW" then @GW = val.to_l;@HW = @GW/2.0
					when "BGD" then @GD = val.to_l
					when "BWB" then @bwb=val.to_i
					when "ORG" then @spt = val
					when "ROT" then @rot = val
					when "MAT" then @app = val; update=true; @app=='Rand_Tex' ? self.source_of_textures : @dlg_FG_Picker.close if @dlg_FG_Picker
					when "IPD" then @ipd = val.to_f; @ipd = [@ipd,0.1].max; @ipd = [@ipd,1.0].min
					when "FLW" then @flw=="Yes" ? @flw="No" : @flw="Yes";
					when "FWW" then @fww=="Yes" ? @fww="No" : @fww="Yes";
					when "FWT" then @fwt=="Yes" ? @fwt="No" : @fwt="Yes";
					when "RDS" then @rds=val.to_i
					when "TSZ" then @tsz=val
					when "WAG" then @rtr=val
					when "ATE" then @ate=="Yes" ? @ate="No" : @ate="Yes";
					when "WIG" then @rtt=="Yes" ? @rtt="No" : @rtt="Yes"; update=true
					when "RTI" then @rti=val.to_l; @rti>0 ? @rtt="Yes" : @rtt="No"
					when "WOB" then @rfr=="Yes" ? @rfr="No" : @rfr="Yes"; update=true
					when "BVL" then @bev=="Yes" ? @bev="No" : @bev="Yes"; update=true
					when "R2R" then @r2r=val.to_f;r2r=val
					when "TWA" then @twa=val.to_f
					when "RIn" then @rin=val.to_l;@rin=[@rin,0].max
					when "RIx" then @rix=val.to_l;@rix=[@rix,@GD].min
					when "BVS" then @bvs=val.to_l;
					when "CBF" then @cbf=="Yes" ? @cbf="No" : @cbf="Yes";
					when "CIG" then @cig=="Yes" ? @cig="No" : @cig="Yes";
				end
				tbx=@GX.to_s.gsub('"','\"'); tby=@GY.to_s.gsub('"','\"'); twa=@twa.to_s; @txs=0;rds=@rds.to_s; r2r=@r2r.to_s
				(txw,txh=@tsz.split(","); if txh then @txs=[txw.to_l,txh.to_l] else @txs=@tsz.to_l end) if @tsz && @tsz != "0"
				gw=@GW.to_s.gsub('"','\"'); gd=@GD.to_s.gsub('"','\"');txs=@tsz.gsub('"','\"') if @tsz;bwb=@bwb.to_s; txs=@txs.to_s
				rin=@rin.to_s.gsub('"','\"'); rix=@rix.to_s.gsub('"','\"'); bvs=@bvs.to_s.gsub('"','\"'); ipd = @ipd.to_s; 
				rti=@rti.to_s.gsub('"','\"'); cbt=@cbt.to_s.gsub('"','\"'); cbw=@cbw.to_s.gsub('"','\"'); cbo=@cbo.to_s.gsub('"','\"');
				if @separator == ','
					tbx.gsub!('.',','); tby.gsub!('.',','); gw.gsub!('.',','); gd.gsub!('.',','); txs.gsub!('.',','); cbo.gsub!('.',','); 
					rin.gsub!('.',','); rix.gsub!('.',','); bvs.gsub!('.',','); rti.gsub!('.',','); cbt.gsub!('.',','); cbw.gsub!('.',','); 
				end
				# @spt,@rot,@app,@flw,@fww,r2r,@rtt,@rtr,txs,@rfr,@bev,twa,tbx,tby,gw,gd,bwb,@ate,@fwt,rds,rin,rix,bvs,ipd,rti,@cbf,@cig,cbt,cbw,cbo
				@defaults=[@spt,@rot,@app,@flw,@fww,r2r,@rtt,@rtr,txs,@rfr,@bev,twa,tbx,tby,gw,gd,bwb,@ate,@fwt,rds,rin,rix,bvs,ipd,rti,@cbf,@cig,cbt,cbw,cbo]
				Sketchup.write_default("FloorGenerator",@@opt,@defaults); update_wd if update
			}
			
			@@dlg_FG_Main.add_action_callback("PatternChanged") {|d,p|
				@@opt=p;
				if @@opt=="Reset" then 
					["Brick","Tile","Wood","Tweed","Hbone","BsktWv","HpScth1","HpScth2","Rand_Tex"].each{|o| Sketchup.write_default("FloorGenerator",o,nil)};
					["HpScth3","HpScth4","IrPoly","Hexgon","Octgon","Wedge","I_Block","Diamonds","Clapbrd"].each{|o| Sketchup.write_default("FloorGenerator",o,nil)};
					@@opt="Tile";
				end
				Sketchup.write_default("FloorGenerator","",@@opt)
				@failed=false; update_wd
				self.source_of_textures if @app == "Rand_Tex"
			}
			@@dlg_FG_Main.add_action_callback("ChangeSource") {|d,p|
				self.source_of_textures
			}
		end
		
		def update_wd
				if Sketchup.active_model.options["UnitsOptions"]["LengthUnit"]>1
					Sketchup.active_model.options["UnitsOptions"]["LengthUnit"]=2; #millimeters
					Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"]=1
					# @spt,@rot, @app,@flw,@fww, r2r,@rtt,@rtr,txs,@rfr,@bev, twa, tbx, tby, gw, gd,bwb,@ate, @fwt,rds,rin,rix,bvs,ipd,rti,@cbf,@cig, cbt, cbw, cbo
					@defaults=["Corner","0","Current","No","No","50","No","No","0","No","No","30","150","50","6","6","3","No","Yes","0","0","3","6","1","1",'No','No','25','150','13'] if @@opt=="Brick" || @@opt=="Wedge";
@defaults=["Corner","0","Current","No","No","0","No","No","0","No","No","30","300","300","6","3","3","No","Yes","0","0","3","6","1","1",'No','No','25','150','13'] if @@opt=="Tile" || @@opt=="HpScth4"; 
					@defaults=["Corner","0","Current","Yes","Yes","0","No","No","0","No","No","30","2000","100","3","3","3","No","Yes","0","0","3","6","1","1",'No','No','25','150','13'] if @@opt=="Wood" || @@opt=="Clapbrd"; 
					@defaults=["Corner","0","Current","No","No","0","No","No","0","No","No","30","150","50","12","6","3","Yes","Yes","0","0","3","6","1","1",'No','No','25','150','13'] if @@opt=="Tweed"
					@defaults=["Corner","0","Current","No","No","0","No","No","0","No","No","30","200","100","12","6","3","Yes","Yes","0","0","3","6","1","1",'No','No','25','150','13'] if @@opt=="Hbone" || @@opt=="BsktWv" || @@opt=="I_Block" ; 
					@defaults=["Center","0","Current","No","No","0","No","No","0","No","No","30","300","300","12","6","3","Yes","Yes","0","0","3","6","1","1",'No','No','25','150','13'] if @@opt=="HpScth1" || @@opt=="HpScth2"; 
					@defaults=["Corner","0","Current","No","No","0","No","No","0","No","No","30","600","600","6","3","3","No","Yes","0","0","3","6","1","1",'No','No','25','150','13'] if @@opt=="HpScth3"; 
					@defaults=["Center","0","Current","No","No","0","No","No","0","No","No","30","300","0","12","6","3","No","Yes","0","0","3","6","1","1",'No','No','25','150','13'] if @@opt=="Hexgon" || @@opt=="Octgon" || @@opt=="IrPoly" || @@opt=="Diamonds"; 
				else
					Sketchup.active_model.options["UnitsOptions"]["LengthUnit"]=0; #inches
					Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"]=3
					# @spt,@rot, @app,@flw,@fww, r2r,@rtt,@rtr,txs,@rfr,@bev, twa, tbx, tby, gw, gd,bwb,@ate, @fwt,rds,rin,rix,bvs,ipd,rti,@cbf,@cig, cbt, cbw, cbo
					@defaults=["Corner","0","Current","No","No","50","No","No","0","No","No","30","6.0","2.0","0.25","0.25","3","No","Yes","0","0","0.125","0.25","1","1",'No','No','1.0','6.0','0.5'] if @@opt=="Brick" || @@opt=="Wedge"; 
					@defaults=["Corner","0","Current","No","No","0","No","No","0","No","No","30","12.0","12.0","0.25","0.125","3","No","Yes","0","0","0.125","0.25","1","1",'No','No','1.0','6.0','0.5'] if @@opt=="Tile" || @@opt=="HpScth4"; 
					@defaults=["Corner","0","Current","Yes","Yes","0","No","No","0","No","No","30","60.0","3.0","0.125","0.125","3","No","Yes","0","0","0.125","0.25","1","1",'No','No','1.0','6.0','0.5'] if @@opt=="Wood" || @@opt=="Clapbrd"
					@defaults=["Corner","0","Current","No","No","0","No","No","0","No","No","30","6.0","2.0","0.5","0.25","3","Yes","Yes","0","0","0.125","0.25","1","1",'No','No','1.0','6.0','0.5'] if @@opt=="Tweed"; 
					@defaults=["Corner","0","Current","No","No","0","No","No","0","No","No","30","8.0","4.0","0.5","0.25","3","Yes","Yes","0","0","0.125","0.25","1","1",'No','No','1.0','6.0','0.5'] if @@opt=="Hbone" || @@opt=="BsktWv" || @@opt=="I_Block" ; 
					@defaults=["Center","0","Current","No","No","0","No","No","0","No","No","30","12.0","12.0","0.5","0.25","3","Yes","Yes","0","0","0.125","0.25","1","1",'No','No','1.0','6.0','0.5'] if @@opt=="HpScth1" || @@opt=="HpScth2" || @@opt=='HpScth3'; 
					@defaults=["Corner","0","Current","No","No","0","No","No","0","No","No","30","24.0","24.0","0.25","0.125","3","No","Yes","0","0","0.125","0.25","1","1",'No','No','1.0','6.0','0.5'] if @@opt=="HpScth3"; 
					@defaults=["Center","0","Current","No","No","0","No","No","0","No","No","30","12.0","0.0","0.5","0.25","3","No","Yes","0","0","0.125","0.25","1","1",'No','No','1.0','6.0','0.5'] if @@opt=="Hexgon" || @@opt=="Octgon" || @@opt=="IrPoly" || @@opt=="Diamonds"; 
				end
				begin
					@spt,@rot,@app,@flw,@fww,r2r,@rtt,@rtr,txs,@rfr,@bev,twa,tbx,tby,gw,gd,bwb,@ate,@fwt,rds,rin,rix,bvs,ipd,rti,@cbf,@cig,cbt,cbw,cbo=Sketchup.read_default("FloorGenerator",@@opt,@defaults)
					@GX=tbx.to_l;@GY=tby.to_l;@GW=gw.to_l;@HW=@GW/2.0;@GD=gd.to_l;@bwb=bwb.to_i; @rds=rds.to_i; @rin = rin.to_l; @rix = rix.to_l; @bvs = bvs.to_l; @ipd = ipd.to_f
					txw,txh=txs.split(","); if txh then @txs=[txw.to_l,txh.to_l] else @txs=txs.to_l end; @cbt=cbo.to_l; @cbw=cbw.to_l; @cbo=cbo.to_l
					@twa=twa.to_f; @r2r=r2r.to_f; @rti=rti.to_l;
				rescue
					puts "read_default failed"
					if @failed
						["Brick","Tile","Wood","Tweed","Hbone","BsktWv","HpScth1","HpScth2","Rand_Tex"].each{|o| Sketchup.write_default("FloorGenerator",o,nil)};
						["HpScth3","HpScth4","IrPoly","Hexgon","Octgon","Wedge","I_Block","Diamonds","Clapbrd"].each{|o| Sketchup.write_default("FloorGenerator",o,nil)};
						@@opt="Tile"; Sketchup.write_default("FloorGenerator","",@@opt); @failed=false;update_wd
					else
						Sketchup.write_default("FloorGenerator","",@@opt)
						Sketchup.write_default("FloorGenerator",@@opt,@defaults)
						@failed=true; update_wd
					end
				end
			@@dlg_FG_Main.set_html(get_html)
			Sketchup.platform == :platform_win ? @@dlg_FG_Main.show : @@dlg_FG_Main.show_modal
		end
		
		def get_html
			html="<html><body style='background-color:powderblue' ><form style='font-family:#{@font};font-size:70%;color:black' >"
			html+=pattern_html
			case @@opt
				when 'Brick','Tile';html+=brick_tile_html
				when 'Wood';html+=wood_html
				when 'Tweed';	html+=tweed_html
				when 'Hbone';	html+=herringbone_html
				when 'BsktWv';html+=basketweave_html
				when 'HpScth1';html+=hopscotch_html
				when 'HpScth2';html+=hopscotch_html
				when 'HpScth3';html+=hopscotch_html
				when 'HpScth4';html+=hopscotch_html
				when 'IrPoly';html+=irpoly_html
				when 'Hexgon';html+=hexoctdia_html
				when 'Octgon';html+=hexoctdia_html
				when 'Wedge';html+=hopscotch_html
				when 'I_Block';html+=hopscotch_html
				when 'Diamonds';html+=hexoctdia_html
				when 'Clapbrd';html+=clapboard_html
				else;UI.messagebox "#{@@opt} not found"
			end
			html+="</body></html>"
			html+=script_html
		end
		
		def script_html
			html=<<-HTML
			<script type='text/javascript'>
				function patternchanged(value)
				{
					window.location='skp:PatternChanged@'+value;
				};
				function optionchanged(name,value)
				{
					window.location='skp:OptionChanged@'+name+'='+value;
				};
				function ChangeSource()
				{
					window.location='skp:ChangeSource@';
				};
			</script>
			HTML
		end
		
		def pattern_html
			html=<<-HTML
				<fieldset>
					<legend style='font-size:125%;color:red'><b> Pattern </b></legend>
					<select onChange='patternchanged(value)'>
						<option value='Brick' #{@@opt=='Brick' ? 'selected' : ''}>Brick</option>
						<option value='Tile' #{@@opt=='Tile' ? 'selected' : ''}>Tile</option>
						<option value='Wood' #{@@opt=='Wood' ? 'selected' : ''}>Wood</option>
						<option value='Tweed' #{@@opt=='Tweed' ? 'selected' : ''}>Tweed</option>
						<option value='Hbone' #{@@opt=='Hbone' ? 'selected' : ''}>Herringbone</option>
						<option value='BsktWv' #{@@opt=='BsktWv' ? 'selected' : ''}>Basket Weave</option>
						<option value='HpScth1' #{@@opt=='HpScth1' ? 'selected' : ''}>Hopscotch1</option>
						<option value='HpScth2' #{@@opt=='HpScth2' ? 'selected' : ''}>HopScotch2</option>
						<option value='HpScth3' #{@@opt=='HpScth3' ? 'selected' : ''}>HopScotch3</option>
						<option value='HpScth4' #{@@opt=='HpScth4' ? 'selected' : ''}>HopScotch4</option>
						<option value='IrPoly' #{@@opt=='IrPoly' ? 'selected' : ''}>Irregular Polygons</option>
						<option value='Hexgon' #{@@opt=='Hexgon' ? 'selected' : ''}>Hexagons</option>
						<option value='Octgon' #{@@opt=='Octgon' ? 'selected' : ''}>Octagons</option>
						<option value='Wedge' #{@@opt=='Wedge' ? 'selected' : ''}>Wedges</option>
						<option value='I_Block' #{@@opt=='I_Block' ? 'selected' : ''}>I_Block</option>
						<option value='Diamonds' #{@@opt=='Diamonds' ? 'selected' : ''}>Diamonds</option>
						<option value='Clapbrd' #{@@opt=='Clapbrd' ? 'selected' : ''}>Clapboard</option>
						<option value='Reset'>Reset</option>
					</select>
					<!-- Pattern
Icons -->
					#{@@opt=='Brick' ? "<img src='#{@icons}Brick.jpg' align='top'/>" : ''}
					#{@@opt=='Tile' ? "<img src='#{@icons}Tile.jpg' align='top'/>" : ''}
					#{@@opt=='Wood' ? "<img src='#{@icons}Wood.jpg' align='top'/>" : ''}
					#{@@opt=='Tweed' ? "<img src='#{@icons}Tweed.jpg' align='top'/>" : ''}
					#{@@opt=='Hbone' ? "<img src='#{@icons}Hbone.jpg' align='top'/>" : ''}
					#{@@opt=='BsktWv' ? "<img src='#{@icons}BsktWv.jpg' align='top'/>" : ''}
					#{@@opt=='HpScth1' ? "<img src='#{@icons}HpScth1.jpg' align='top'/>" : ''}
					#{@@opt=='HpScth2' ? "<img src='#{@icons}HpScth2.jpg' align='top'/>" : ''}
					#{@@opt=='HpScth3' ? "<img src='#{@icons}HpScth3.jpg' align='top'/>" : ''}
					#{@@opt=='HpScth4' ? "<img src='#{@icons}HpScth4.jpg' align='top'/>" : ''}
					#{@@opt=='IrPoly' ? "<img src='#{@icons}IrPoly.jpg' align='top'/>" : ''}
					#{@@opt=='Hexgon' ? "<img src='#{@icons}Hexgon.jpg' align='top'/>" : ''}
					#{@@opt=='Octgon' ? "<img src='#{@icons}Octgon.jpg' align='top'/>" : ''}
					#{@@opt=='Wedge' ? "<img src='#{@icons}Wedge.jpg' align='top'/>" : ''}
					#{@@opt=='I_Block' ? "<img src='#{@icons}I_Block.jpg' align='top'/>" : ''}
					#{@@opt=='Diamonds' ? "<img src='#{@icons}Diamonds.jpg' align='top'/>" : ''}
					#{@@opt=='Clapbrd' ? "<img src='#{@icons}Clapboard.jpg' align='top'/>" : ''}
				</fieldset>
			HTML
		end
		
		def brick_tile_html
			html=<<-HTML
			<fieldset>
				<legend style='font-size:125%;color:red'><b> Size </b></legend>
				<table style='font-size:100%'>
					<tr><td align='right' width=54>Length:</td>
					<td><input type='text' name='BTL' value='#{@GX}' size=4 onChange='optionchanged(name,value)' /></td>
					<tr><td align='right'>Width:</td>
					<td><input type='text' name='BTW' value='#{@GY}' size=4 onChange='optionchanged(name,value)' /></td>
					<tr><td align='right' width=54>Gap Width:</td><td>
					<input type='text' name='BGW' value='#{@GW}' size=4 onChange='optionchanged(name,value)' /></td></tr>
					<tr><td align='right' width=54>Gap Depth:</td><td>
					<input type='text' name='BGD' value='#{@GD}' size=4 onChange='optionchanged(name,value)' /></td><td>
					<input type='checkbox' name='FWT' value='Yes' #{@fwt=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Fixed
					</td></tr>
					<tr><td align='right' width=54>\% Offset:</td>
					<td><input type='text' name='R2R' value='#{@r2r}' size=4 onChange='optionchanged(name,value)' /></td></tr>
				</table>
			</fieldset>
			<fieldset>
				<legend style='font-size:125%;color:red'><b> Options </b></legend>
				<select name='ORG' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='Corner' #{@spt=='Corner' ? 'selected' : ''}>Corner</option>
					<option value='Center' #{@spt=='Center' ? 'selected' : ''}>Center</option>
				</select> : Grid Origin<br>#{@@opt=='IrPoly' ? '<!--' : ''}
				<select name='ROT' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='0' #{@rot=='0' ? 'selected' : ''}>0</option>
					<option value='45' #{@rot=='45' ? 'selected' : ''}>45</option>
					<option value='90' #{@rot=='90' ? 'selected' : ''}>90</option>
				</select> : Grid Rotation<br>
				<select name='MAT' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='Current' #{@app=='Current' ? 'selected' : ''}>Current</option>
					<option value='Rand_Clr' #{@app=='Rand_Clr' ? 'selected' : ''}>Rand_Clr</option>
					<option value='Rand_Tex' #{@app=='Rand_Tex' ? 'selected' : ''}>Rand_Tex</option><br>
				</select> : Material#{@app!='Rand_Tex' ? '<!--' : '<br>'}
				&nbsp&nbsp<button id='RTS' onclick='ChangeSource(id)'>Source</button>#{@app!='Rand_Tex' ? '-->' : ''}<br><hr>
				<input type='text' name='RDS' value='#{@rds}' size=2 onChange='optionchanged(name,value)'/> : Random Seed<br><hr>
				<input type='text' name='TSZ' value='#{@txs}' size=5 onChange='optionchanged(name,value)'/> : Texture Size (w,h)<br>
				<input type='checkbox' name='ATE' value='Yes' #{@ate=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Align Texture to Longest Edge<br> 
				<input type='checkbox' name='WIG' value='Yes' #{@rtt=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Random Position Texture </input>
				#{@rtt=='No' ? '<!--' : ''}
				Inc: <input type='text' name ='RTI' value='#{@rti}' size=3 onchange='optionchanged(name,value)'/>
				#{@rtt=='No' ? '-->' : ''}<br> 
				<select name='WAG' style='width:60px' onChange='optionchanged(name,value)'>
					<option value='No' #{@rtr=='No' ? 'selected' : ''}>No</option>
					<option value='30' #{@rtr=='30' ? 'selected' : ''}>30</option>
					<option value='45' #{@rtr=='45' ? 'selected' : ''}>45</option>
					<option value='90' #{@rtr=='90' ? 'selected' : ''}>90</option>
					<option value='180' #{@rtr=='180' ? 'selected' : ''}>180</option>
					<option value='Rand' #{@rtr=='Rand' ? 'selected' : ''}>Rand</option>
				</select> : Random Rotation<br>									
				<hr>
				<input type='checkbox' name='WOB' value='Yes' #{@rfr=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Random Imperfections<br> 
				#{@rfr=='No' ? '<!--' : ''}
				Min:<input type='text' name='RIn' value='#{@rin}' size=4 onChange='optionchanged(name,value)'/>
				Max:<input type='text' name='RIx' value='#{@rix}' size=4 onChange='optionchanged(name,value)'/> <br>
				#{@rfr=='No' ? '-->' : ''} 									
				<input type='checkbox' name='BVL' value='Yes' #{@bev=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Add Bevel to #{@@opt}<br>
				#{@bev=='No' ? '<!--' : ''}
				Size:<input type='text' name='BVS' value='#{@bvs}' size=4 onChange='optionchanged(name,value)'/><br>
				#{@bev=='No' ? '-->' : ''}
				<input type='checkbox' name='CBF' value='Yes' #{@cbf=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Create Behind Face<br>
				<input type='checkbox' name='CIG' value='Yes' #{@cig=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Create Individual Groups<br>
			</fieldset>
			</form>
			HTML
		end
		
		def wood_html
		html=<<-HTML
		<fieldset>
			<legend style='font-size:125%;color:red'><b> Size </b></legend>
			<table style='font-size:100%'>
				<tr><td align='right' width=54>Length:</td>
				<td><input type='text' name='BTL' value='#{@GX}' size=4 onChange='optionchanged(name,value)' /></td>
				<td><input type='checkbox' name='FLW' value='Yes' #{@flw=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Fixed</td></tr>
				<tr><td align='right'>Width:</td>
				<td><input type='text' name='BTW' value='#{@GY}' size=4 onChange='optionchanged(name,value)' /></td>
				<td><input type='checkbox' name='FWW' value='Yes' #{@fww=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Fixed</td></tr>
				<tr><td align='right' width=54>Gap Width:</td><td>
				<input type='text' name='BGW' value='#{@GW}' size=4 onChange='optionchanged(name,value)' /></td></tr>
				<tr><td align='right' width=54>Gap Depth:</td><td>
				<input type='text' name='BGD' value='#{@GD}' size=4 onChange='optionchanged(name,value)' /></td><td>
				<input type='checkbox' name='FWT' value='Yes' #{@fwt=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Fixed
				</td></tr>
			</table>
		</fieldset>
		<fieldset>
			<legend style='font-size:125%;color:red'><b> Options </b></legend>
			<select name='ORG' style='width:90px' onChange='optionchanged(name,value)'>
				<option value='Corner' #{@spt=='Corner' ? 'selected' : ''}>Corner</option>
				<option value='Center' #{@spt=='Center' ? 'selected' : ''}>Center</option>
			</select> : Grid Origin<br>#{@@opt=='IrPoly' ? '<!--' : ''}
			<select name='ROT' style='width:90px' onChange='optionchanged(name,value)'>
				<option value='0' #{@rot=='0' ? 'selected' : ''}>0</option>
				<option value='45' #{@rot=='45' ? 'selected' : ''}>45</option>
				<option value='90' #{@rot=='90' ? 'selected' : ''}>90</option>
			</select> : Grid Rotation<br>
<select name='MAT' style='width:90px' onChange='optionchanged(name,value)'>
				<option value='Current' #{@app=='Current' ? 'selected' : ''}>Current</option>
				<option value='Rand_Clr' #{@app=='Rand_Clr' ? 'selected' : ''}>Rand_Clr</option>
				<option value='Rand_Tex' #{@app=='Rand_Tex' ? 'selected' : ''}>Rand_Tex</option><br>
			</select> : Material#{@app!='Rand_Tex' ? '<!--' : '<br>'}
			&nbsp&nbsp<button id='RTS' onclick='ChangeSource(id)'>Source</button>#{@app!='Rand_Tex' ? '-->' : ''}<br><hr>
			<input type='text' name='RDS' value='#{@rds}' size=2 onChange='optionchanged(name,value)'/> : Random Seed<br><hr>
			<input type='text' name='TSZ' value='#{@txs}' size=5 onChange='optionchanged(name,value)'/> : Texture Size (w,h)<br>
			<input type='checkbox' name='ATE' value='Yes' #{@ate=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Align Texture to Longest Edge<br> 
			<input type='checkbox' name='WIG' value='Yes' #{@rtt=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Random Position Texture </input>
			#{@rtt=='No' ? '<!--' : ''}
			Inc: <input type='text' name ='RTI' value='#{@rti}' size=3 onchange='optionchanged(name,value)'/>
			#{@rtt=='No' ? '-->' : ''}<br> 
			<select name='WAG' style='width:60px' onChange='optionchanged(name,value)'>
				<option value='No' #{@rtr=='No' ? 'selected' : ''}>No</option>
				<option value='30' #{@rtr=='30' ? 'selected' : ''}>30</option>
				<option value='45' #{@rtr=='45' ? 'selected' : ''}>45</option>
				<option value='90' #{@rtr=='90' ? 'selected' : ''}>90</option>
				<option value='180' #{@rtr=='180' ? 'selected' : ''}>180</option>
				<option value='Rand' #{@rtr=='Rand' ? 'selected' : ''}>Rand</option>
			</select> : Random Rotation<br>									
			<hr>
			<input type='checkbox' name='BVL' value='Yes' #{@bev=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Add Bevel to #{@@opt}<br>
			#{@bev!='Yes' ? '<!--' : ''}
			Size:<input type='text' name='BVS' value='#{@bvs}' size=4 onChange='optionchanged(name,value)'/><br>
			#{@bev!='Yes' ? '-->' : ''}
			<input type='checkbox' name='CBF' value='Yes' #{@cbf=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Create Behind Face<br>
			<input type='checkbox' name='CIG' value='Yes' #{@cig=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Create Individual Groups<br>
		</fieldset>
		HTML
		end
		
		def tweed_html
			html=<<-HTML
			<fieldset>
				<legend style='font-size:125%;color:red'><b> Size </b></legend>
				<table style='font-size:100%'>
					<tr><td align='right' width=54>Length:</td>
					<td><input type='text' name='BTL' value='#{@GX}' size=4 onChange='optionchanged(name,value)' /></td>
					<td><input type='checkbox' name='FLW' value='Yes' #{@flw=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Fixed</td></tr>
					<tr><td align='right'>Width:</td>
					<td><input type='text' name='BTW' value='#{@GY}' size=4 onChange='optionchanged(name,value)' /></td>
					<td><input type='checkbox' name='FWW' value='Yes' #{@fww=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Fixed</td></tr>
					<tr><td align='right' width=54>Gap Width:</td><td>
					<input type='text' name='BGW' value='#{@GW}' size=4 onChange='optionchanged(name,value)' /></td></tr>
					<tr><td align='right' width=54>Gap Depth:</td><td>
					<input type='text' name='BGD' value='#{@GD}' size=4 onChange='optionchanged(name,value)' /></td><td>
					<input type='checkbox' name='FWT' value='Yes' #{@fwt=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Fixed</td></tr>
					<tr><td align='right' width=54>Angle:</td>
					<td><input type='text' name='TWA' value='#{@twa}' size=4 onChange='optionchanged(name,value)' /></td></tr>
				</table>
				</table>
			</fieldset>
			<fieldset>
				<legend style='font-size:125%;color:red'><b> Options </b></legend>
				<select name='ORG' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='Corner' #{@spt=='Corner' ? 'selected' : ''}>Corner</option>
					<option value='Center' #{@spt=='Center' ? 'selected' : ''}>Center</option>
				</select> : Grid Origin<br>#{@@opt=='IrPoly' ? '<!--' : ''}
				<select name='ROT' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='0' #{@rot=='0' ? 'selected' : ''}>0</option>
					<option value='45' #{@rot=='45' ? 'selected' : ''}>45</option>
					<option value='90' #{@rot=='90' ? 'selected' : ''}>90</option>
				</select> : Grid Rotation<br>
				<select name='MAT' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='Current' #{@app=='Current' ? 'selected' : ''}>Current</option>
					<option value='Rand_Clr' #{@app=='Rand_Clr' ? 'selected' : ''}>Rand_Clr</option>
					<option value='Rand_Tex' #{@app=='Rand_Tex' ? 'selected' : ''}>Rand_Tex</option><br>
				</select> : Material#{@app!='Rand_Tex' ? '<!--' : '<br>'}
				&nbsp&nbsp<button id='RTS' onclick='ChangeSource(id)'>Source</button>#{@app!='Rand_Tex' ? '-->' : ''}<br><hr>
				<input type='text' name='RDS' value='#{@rds}' size=2 onChange='optionchanged(name,value)'/> : Random Seed<br><hr>
				<input type='text' name='TSZ' value='#{@txs}' size=5 onChange='optionchanged(name,value)'/> : Texture Size (w,h)<br>
				<input type='checkbox' name='ATE' value='Yes' #{@ate=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Align Texture to Longest Edge<br> 
				<input type='checkbox' name='WIG' value='Yes' #{@rtt=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Random Position Texture </input>
				#{@rtt=='No' ? '<!--' : ''}
				Inc: <input type='text' name ='RTI' value='#{@rti}' size=3 onchange='optionchanged(name,value)'/>
				#{@rtt=='No' ? '-->' : ''}<br> 
				<select name='WAG' style='width:60px' onChange='optionchanged(name,value)'>
					<option value='No' #{@rtr=='No' ? 'selected' : ''}>No</option>
					<option value='30' #{@rtr=='30' ? 'selected' : ''}>30</option>
					<option value='45' #{@rtr=='45' ? 'selected' : ''}>45</option>
					<option value='90' #{@rtr=='90' ? 'selected' : ''}>90</option>
					<option value='180' #{@rtr=='180' ? 'selected' : ''}>180</option>
					<option value='Rand' #{@rtr=='Rand' ? 'selected' : ''}>Rand</option>
				</select> : Random Rotation<br>									
				<hr>
				<input type='checkbox' name='WOB' value='Yes' #{@rfr=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Random Imperfections<br> 
				#{@rfr!='Yes' ? '<!--' : ''}
				Min:<input type='text' name='RIn' value='#{@rin}' size=4 onChange='optionchanged(name,value)'/>
				Max:<input type='text' name='RIx' value='#{@rix}' size=4 onChange='optionchanged(name,value)'/> <br>
				#{@rfr!='Yes' ? '-->' : ''} 									
				<input type='checkbox' name='BVL' value='Yes' #{@bev=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Add Bevel to #{@@opt}<br>
				#{@bev!='Yes' ? '<!--' : ''}
				Size:<input type='text' name='BVS' value='#{@bvs}' size=4 onChange='optionchanged(name,value)'/><br>
				#{@bev!='Yes' ? '-->' : ''}
				<input type='checkbox' name='CBF' value='Yes' #{@cbf=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Create Behind Face<br>
				<input type='checkbox' name='CIG' value='Yes' #{@cig=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Create Individual Groups<br>
			</fieldset>
			HTML
		end
		
		def herringbone_html
			html=<<-HTML
			<fieldset>
				<legend style='font-size:125%;color:red'><b> Size </b></legend>
				<table style='font-size:100%'>
					<tr><td align='right' width=54>Length:</td>
					<td><input type='text' name='BTL' value='#{@GX}' size=4 onChange='optionchanged(name,value)' /></td>
					<td><input type='checkbox' name='FLW' value='Yes' #{@flw=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Fixed</td></tr>
					<tr><td align='right'>Width:</td>
					<td><input type='text' name='BTW' value='#{@GY}' size=4 onChange='optionchanged(name,value)' /></td>
					<td><input
type='checkbox' name='FWW' value='Yes' #{@fww=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Fixed</td></tr>
					<tr><td align='right' width=54>Gap Width:</td><td>
					<input type='text' name='BGW' value='#{@GW}' size=4 onChange='optionchanged(name,value)' /></td></tr>
					<tr><td align='right' width=54>Gap Depth:</td><td>
					<input type='text' name='BGD' value='#{@GD}' size=4 onChange='optionchanged(name,value)' /></td><td>
					<input type='checkbox' name='FWT' value='Yes' #{@fwt=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Fixed</td></tr>
				</table>
				</table>
			</fieldset>
			<fieldset>
				<legend style='font-size:125%;color:red'><b> Options </b></legend>
				<select name='ORG' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='Corner' #{@spt=='Corner' ? 'selected' : ''}>Corner</option>
					<option value='Center' #{@spt=='Center' ? 'selected' : ''}>Center</option>
				</select> : Grid Origin<br>
				<select name='ROT' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='0' #{@rot=='0' ? 'selected' : ''}>0</option>
					<option value='45' #{@rot=='45' ? 'selected' : ''}>45</option>
					<option value='90' #{@rot=='90' ? 'selected' : ''}>90</option>
				</select> : Grid Rotation<br>
				<select name='MAT' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='Current' #{@app=='Current' ? 'selected' : ''}>Current</option>
					<option value='Rand_Clr' #{@app=='Rand_Clr' ? 'selected' : ''}>Rand_Clr</option>
					<option value='Rand_Tex' #{@app=='Rand_Tex' ? 'selected' : ''}>Rand_Tex</option><br>
				</select> : Material#{@app!='Rand_Tex' ? '<!--' : '<br>'}
				&nbsp&nbsp<button id='RTS' onclick='ChangeSource(id)'>Source</button>#{@app!='Rand_Tex' ? '-->' : ''}<br><hr>
				<input type='text' name='RDS' value='#{@rds}' size=2 onChange='optionchanged(name,value)'/> : Random Seed<br><hr>
				<input type='text' name='TSZ' value='#{@txs}' size=5 onChange='optionchanged(name,value)'/> : Texture Size (w,h)<br>
				<input type='checkbox' name='ATE' value='Yes' #{@ate=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Align Texture to Longest Edge<br> 
				<input type='checkbox' name='WIG' value='Yes' #{@rtt=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Random Position Texture </input>
				#{@rtt=='No' ? '<!--' : ''}
				Inc: <input type='text' name ='RTI' value='#{@rti}' size=3 onchange='optionchanged(name,value)'/>
				#{@rtt=='No' ? '-->' : ''}<br> 
				<select name='WAG' style='width:60px' onChange='optionchanged(name,value)'>
					<option value='No' #{@rtr=='No' ? 'selected' : ''}>No</option>
					<option value='30' #{@rtr=='30' ? 'selected' : ''}>30</option>
					<option value='45' #{@rtr=='45' ? 'selected' : ''}>45</option>
					<option value='90' #{@rtr=='90' ? 'selected' : ''}>90</option>
					<option value='180' #{@rtr=='180' ? 'selected' : ''}>180</option>
					<option value='Rand' #{@rtr=='Rand' ? 'selected' : ''}>Rand</option>
				</select> : Random Rotation<br>									
				<hr>
				<input type='checkbox' name='WOB' value='Yes' #{@rfr=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Random Imperfections<br> 
				#{@rfr!='Yes' ? '<!--' : ''}
				Min:<input type='text' name='RIn' value='#{@rin}' size=4 onChange='optionchanged(name,value)'/>
				Max:<input type='text' name='RIx' value='#{@rix}' size=4 onChange='optionchanged(name,value)'/> <br>
				#{@rfr!='Yes' ? '-->' : ''} 									
				<input type='checkbox' name='BVL' value='Yes' #{@bev=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Add Bevel to #{@@opt}<br>
				#{@bev!='Yes' ? '<!--' : ''}
				Size:<input type='text' name='BVS' value='#{@bvs}' size=4 onChange='optionchanged(name,value)'/><br>
				#{@bev!='Yes' ? '-->' : ''}
				<input type='checkbox' name='CBF' value='Yes' #{@cbf=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Create Behind Face<br>
				<input type='checkbox' name='CIG' value='Yes' #{@cig=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Create Individual Groups<br>
			</fieldset>
			HTML
		end
		
		def basketweave_html
			html=<<-HTML
			<fieldset>
				<legend style='font-size:125%;color:red'><b> Size </b></legend>
				<table style='font-size:100%'>
					<tr><td align='right' width=54>Length:</td>
					<td><input type='text' name='BTL' value='#{@GX}' size=4 onChange='optionchanged(name,value)' /></td>
					<tr><td align='right'>Width:</td>
					<td><input type='text' name='BTW' value='#{@GY}' size=4 onChange='optionchanged(name,value)' /></td>
					<tr><td align='right' width=54>Gap Width:</td><td>
					<input type='text' name='BGW' value='#{@GW}' size=4 onChange='optionchanged(name,value)' /></td></tr>
					<tr><td align='right' width=54>Gap Depth:</td><td>
					<input type='text' name='BGD' value='#{@GD}' size=4 onChange='optionchanged(name,value)' /></td><td>
					<input type='checkbox' name='FWT' value='Yes' #{@fwt=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Fixed
					</td></tr>
					<tr><td align='right' width=54>Weave Count:</td>
					<td><input type='text' name='BWB' value='#{@bwb}' size=4 onChange='optionchanged(name,value)' /></td></tr>
				</table>
			</fieldset>
			<fieldset>
				<legend style='font-size:125%;color:red'><b> Options </b></legend>
				<select name='ORG' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='Corner' #{@spt=='Corner' ? 'selected' : ''}>Corner</option>
					<option value='Center' #{@spt=='Center' ? 'selected' : ''}>Center</option>
				</select> : Grid Origin<br>#{@@opt=='IrPoly' ? '<!--' : ''}
				<select name='ROT' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='0' #{@rot=='0' ? 'selected' : ''}>0</option>
					<option value='45' #{@rot=='45' ? 'selected' : ''}>45</option>
					<option value='90' #{@rot=='90' ? 'selected' : ''}>90</option>
				</select> : Grid Rotation<br>
				<select name='MAT' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='Current' #{@app=='Current' ? 'selected' : ''}>Current</option>
					<option value='Rand_Clr' #{@app=='Rand_Clr' ? 'selected' : ''}>Rand_Clr</option>
					<option value='Rand_Tex' #{@app=='Rand_Tex' ? 'selected' : ''}>Rand_Tex</option><br>
				</select> : Material#{@app!='Rand_Tex' ? '<!--' : '<br>'}
				&nbsp&nbsp<button id='RTS' onclick='ChangeSource(id)'>Source</button>#{@app!='Rand_Tex' ? '-->' : ''}<br><hr>
				<input type='text' name='RDS' value='#{@rds}' size=2 onChange='optionchanged(name,value)'/> : Random Seed<br><hr>
				<input type='text' name='TSZ' value='#{@txs}' size=5 onChange='optionchanged(name,value)'/> : Texture Size (w,h)<br>
				<input type='checkbox' name='ATE' value='Yes' #{@ate=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Align Texture to Longest Edge<br> 
				<input type='checkbox' name='WIG' value='Yes' #{@rtt=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Random Position Texture </input>
				#{@rtt=='No' ? '<!--' : ''}
				Inc: <input type='text' name ='RTI' value='#{@rti}' size=3 onchange='optionchanged(name,value)'/>
				#{@rtt=='No' ? '-->' : ''}<br> 
				<select name='WAG' style='width:60px' onChange='optionchanged(name,value)'>
					<option value='No' #{@rtr=='No' ? 'selected' : ''}>No</option>
					<option value='30' #{@rtr=='30' ? 'selected' : ''}>30</option>
					<option value='45' #{@rtr=='45' ? 'selected' : ''}>45</option>
					<option value='90' #{@rtr=='90' ? 'selected' : ''}>90</option>
					<option value='180' #{@rtr=='180' ? 'selected' : ''}>180</option>
					<option value='Rand' #{@rtr=='Rand' ? 'selected' : ''}>Rand</option>
				</select> : Random Rotation<br>									
				<hr>
				<input type='checkbox' name='WOB' value='Yes' #{@rfr=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Random Imperfections<br> 
				#{@rfr!='Yes' ? '<!--' : ''}
				Min:<input
type='text' name='RIn' value='#{@rin}' size=4 onChange='optionchanged(name,value)'/>
				Max:<input type='text' name='RIx' value='#{@rix}' size=4 onChange='optionchanged(name,value)'/> <br>
				#{@rfr!='Yes' ? '-->' : ''} 									
				<input type='checkbox' name='BVL' value='Yes' #{@bev=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Add Bevel to #{@@opt}<br>
				#{@bev!='Yes' ? '<!--' : ''}
				Size:<input type='text' name='BVS' value='#{@bvs}' size=4 onChange='optionchanged(name,value)'/><br>
				#{@bev!='Yes' ? '-->' : ''}
				<input type='checkbox' name='CBF' value='Yes' #{@cbf=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Create Behind Face<br>
				<input type='checkbox' name='CIG' value='Yes' #{@cig=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Create Individual Groups<br>
			</fieldset>
			HTML
		end
		
		def hopscotch_html
			html=<<-HTML
			<fieldset>
				<legend style='font-size:125%;color:red'><b> Size </b></legend>
				<table style='font-size:100%'>
					<tr><td align='right' width=54>Length:</td>
					<td><input type='text' name='BTL' value='#{@GX}' size=4 onChange='optionchanged(name,value)' /></td>
					<tr><td align='right'>Width:</td>
					<td><input type='text' name='BTW' value='#{@GY}' size=4 onChange='optionchanged(name,value)' /></td>
					<tr><td align='right' width=54>Gap Width:</td><td>
					<input type='text' name='BGW' value='#{@GW}' size=4 onChange='optionchanged(name,value)' /></td></tr>
					<tr><td align='right' width=54>Gap Depth:</td><td>
					<input type='text' name='BGD' value='#{@GD}' size=4 onChange='optionchanged(name,value)' /></td><td>
					<input type='checkbox' name='FWT' value='Yes' #{@fwt=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Fixed
					</td></tr>
				</table>
			</fieldset>
			<fieldset>
				<legend style='font-size:125%;color:red'><b> Options </b></legend>
				<select name='ORG' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='Corner' #{@spt=='Corner' ? 'selected' : ''}>Corner</option>
					<option value='Center' #{@spt=='Center' ? 'selected' : ''}>Center</option>
				</select> : Grid Origin<br>#{@@opt=='IrPoly' ? '<!--' : ''}
				<select name='ROT' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='0' #{@rot=='0' ? 'selected' : ''}>0</option>
					<option value='45' #{@rot=='45' ? 'selected' : ''}>45</option>
					<option value='90' #{@rot=='90' ? 'selected' : ''}>90</option>
				</select> : Grid Rotation<br>
				<select name='MAT' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='Current' #{@app=='Current' ? 'selected' : ''}>Current</option>
					<option value='Rand_Clr' #{@app=='Rand_Clr' ? 'selected' : ''}>Rand_Clr</option>
					<option value='Rand_Tex' #{@app=='Rand_Tex' ? 'selected' : ''}>Rand_Tex</option><br>
				</select> : Material#{@app!='Rand_Tex' ? '<!--' : '<br>'}
				&nbsp&nbsp<button id='RTS' onclick='ChangeSource(id)'>Source</button>#{@app!='Rand_Tex' ? '-->' : ''}<br><hr>
				<input type='text' name='RDS' value='#{@rds}' size=2 onChange='optionchanged(name,value)'/> : Random Seed<br><hr>
				<input type='text' name='TSZ' value='#{@txs}' size=5 onChange='optionchanged(name,value)'/> : Texture Size (w,h)<br>
				<input type='checkbox' name='ATE' value='Yes' #{@ate=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Align Texture to Longest Edge<br> 
				<input type='checkbox' name='WIG' value='Yes' #{@rtt=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Random Position Texture </input>
				#{@rtt=='No' ? '<!--' : ''}
				Inc: <input type='text' name ='RTI' value='#{@rti}' size=3 onchange='optionchanged(name,value)'/>
				#{@rtt=='No' ? '-->' : ''}<br> 
				<select name='WAG' style='width:60px' onChange='optionchanged(name,value)'>
					<option value='No' #{@rtr=='No' ? 'selected' : ''}>No</option>
					<option value='30' #{@rtr=='30' ? 'selected' : ''}>30</option>
					<option value='45' #{@rtr=='45' ? 'selected' : ''}>45</option>
					<option value='90' #{@rtr=='90' ? 'selected' : ''}>90</option>
					<option value='180' #{@rtr=='180' ? 'selected' : ''}>180</option>
					<option value='Rand' #{@rtr=='Rand' ? 'selected' : ''}>Rand</option>
				</select> : Random Rotation<br>									
				<hr>
				<input type='checkbox' name='WOB' value='Yes' #{@rfr=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Random Imperfections<br> 
				#{@rfr!='Yes' ? '<!--' : ''}
				Min:<input type='text' name='RIn' value='#{@rin}' size=4 onChange='optionchanged(name,value)'/>
				Max:<input type='text' name='RIx' value='#{@rix}' size=4 onChange='optionchanged(name,value)'/> <br>
				#{@rfr!='Yes' ? '-->' : ''} 									
				<input type='checkbox' name='BVL' value='Yes' #{@bev=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Add Bevel to #{@@opt}<br>
				#{@bev!='Yes' ? '<!--' : ''}
				Size:<input type='text' name='BVS' value='#{@bvs}' size=4 onChange='optionchanged(name,value)'/><br>
				#{@bev!='Yes' ? '-->' : ''}
				<input type='checkbox' name='CBF' value='Yes' #{@cbf=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Create Behind Face<br>
				<input type='checkbox' name='CIG' value='Yes' #{@cig=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Create Individual Groups<br>
			</fieldset>
			HTML
		end
		
		def irpoly_html
			html=<<-HTML
			<fieldset>
				<legend style='font-size:125%;color:red'><b> Size </b></legend>
				<table style='font-size:100%'>
					<tr><td align='right' width=54>Gap Width:</td><td>
					<input type='text' name='BGW' value='#{@GW}' size=4 onChange='optionchanged(name,value)' /></td></tr>
					<tr><td align='right' width=54>Gap Depth:</td><td>
					<input type='text' name='BGD' value='#{@GD}' size=4 onChange='optionchanged(name,value)' /></td><td>
					<input type='checkbox' name='FWT' value='Yes' #{@fwt=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Fixed</td></tr>
					<td align='right' width=54>Pt Density(0.1-1.0)</td>
					<td><input type='text' name='IPD' value='#{@ipd}' size=2 onChange='optionchanged(name,value)'/></td></tr>
				</table>
			</fieldset>
			<fieldset>
				<legend style='font-size:125%;color:red'><b> Options </b></legend>
				<select name='MAT' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='Current' #{@app=='Current' ? 'selected' : ''}>Current</option>
					<option value='Rand_Clr' #{@app=='Rand_Clr' ? 'selected' : ''}>Rand_Clr</option>
					<option value='Rand_Tex' #{@app=='Rand_Tex' ? 'selected' : ''}>Rand_Tex</option><br>
				</select> : Material#{@app!='Rand_Tex' ? '<!--' : '<br>'}
				&nbsp&nbsp<button id='RTS' onclick='ChangeSource(id)'>Source</button>#{@app!='Rand_Tex' ? '-->' : ''}<br><hr>
				<input type='text' name='RDS' value='#{@rds}' size=2 onChange='optionchanged(name,value)'/> : Random Seed<br><hr>
				<input type='text' name='TSZ' value='#{@txs}' size=5 onChange='optionchanged(name,value)'/> : Texture Size (w,h)<br>
				<input type='checkbox' name='WIG' value='Yes' #{@rtt=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Random Position Texture </input>
				#{@rtt=='No' ? '<!--' : ''}
				Inc: <input type='text' name ='RTI' value='#{@rti}' size=3 onchange='optionchanged(name,value)'/>
				#{@rtt=='No' ? '-->' : ''}<br> 
				<select name='WAG' style='width:60px' onChange='optionchanged(name,value)'>
					<option value='No' #{@rtr=='No' ? 'selected' : ''}>No</option>
					<option value='30' #{@rtr=='30' ? 'selected' : ''}>30</option>
					<option value='45' #{@rtr=='45' ? 'selected' : ''}>45</option>
					<option value='90' #{@rtr=='90' ? 'selected' : ''}>90</option>
					<option value='180' #{@rtr=='180' ? 'selected' : ''}>180</option>
					<option value='Rand' #{@rtr=='Rand' ? 'selected' : ''}>Rand</option>
				</select> : Random Rotation<br>									
				<hr>
				<input type='checkbox' name='WOB' value='Yes'
#{@rfr=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Random Imperfections<br> 
				#{@rfr!='Yes' ? '<!--' : ''}
				Min:<input type='text' name='RIn' value='#{@rin}' size=4 onChange='optionchanged(name,value)'/>
				Max:<input type='text' name='RIx' value='#{@rix}' size=4 onChange='optionchanged(name,value)'/> <br>
				#{@rfr!='Yes' ? '-->' : ''} 									
				<input type='checkbox' name='BVL' value='Yes' #{@bev=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Add Bevel to #{@@opt}<br>
				#{@bev!='Yes' ? '<!--' : ''}
				Size:<input type='text' name='BVS' value='#{@bvs}' size=4 onChange='optionchanged(name,value)'/><br>
				#{@bev!='Yes' ? '-->' : ''}
				<input type='checkbox' name='CBF' value='Yes' #{@cbf=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Create Behind Face<br>
				<input type='checkbox' name='CIG' value='Yes' #{@cig=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Create Individual Groups<br>
			</fieldset>
			HTML
		end
		
		def hexoctdia_html
			html=<<-HTML
			<fieldset>
				<legend style='font-size:125%;color:red'><b> Size </b></legend>
				<table style='font-size:100%'>
					<tr><td align='right' width=60>Side Length:</td>
					<td><input type='text' name='BTL' value='#{@GX}' size=4 onChange='optionchanged(name,value)' /></td></tr>
					<tr><td align='right' width=54>Gap Width:</td><td>
					<input type='text' name='BGW' value='#{@GW}' size=4 onChange='optionchanged(name,value)' /></td></tr>
					<tr><td align='right' width=54>Gap Depth:</td><td>
					<input type='text' name='BGD' value='#{@GD}' size=4 onChange='optionchanged(name,value)' /></td><td>
					<input type='checkbox' name='FWT' value='Yes' #{@fwt=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Fixed</td></tr>
				</table>
			</fieldset>
			<fieldset>
				<legend style='font-size:125%;color:red'><b> Options </b></legend>
				<select name='ORG' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='Corner' #{@spt=='Corner' ? 'selected' : ''}>Corner</option>
					<option value='Center' #{@spt=='Center' ? 'selected' : ''}>Center</option>
				</select> : Grid Origin<br>
				<select name='ROT' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='0' #{@rot=='0' ? 'selected' : ''}>0</option>
					<option value='45' #{@rot=='45' ? 'selected' : ''}>45</option>
					<option value='90' #{@rot=='90' ? 'selected' : ''}>90</option>
				</select> : Grid Rotation<br>
				<select name='MAT' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='Current' #{@app=='Current' ? 'selected' : ''}>Current</option>
					<option value='Rand_Clr' #{@app=='Rand_Clr' ? 'selected' : ''}>Rand_Clr</option>
					<option value='Rand_Tex' #{@app=='Rand_Tex' ? 'selected' : ''}>Rand_Tex</option><br>
				</select> : Material#{@app!='Rand_Tex' ? '<!--' : '<br>'}
				&nbsp&nbsp<button id='RTS' onclick='ChangeSource(id)'>Source</button>#{@app!='Rand_Tex' ? '-->' : ''}<br><hr>
				<input type='text' name='RDS' value='#{@rds}' size=2 onChange='optionchanged(name,value)'/> : Random Seed<br><hr>
				<input type='text' name='TSZ' value='#{@txs}' size=5 onChange='optionchanged(name,value)'/> : Texture Size (w,h)<br>
				<input type='checkbox' name='WIG' value='Yes' #{@rtt=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'>Random Position Texture </input>
				#{@rtt=='No' ? '<!--' : ''}
				Inc: <input type='text' name ='RTI' value='#{@rti}' size=3 onchange='optionchanged(name,value)'/>
				#{@rtt=='No' ? '-->' : ''}<br> 
				<select name='WAG' style='width:60px' onChange='optionchanged(name,value)'>
					<option value='No' #{@rtr=='No' ? 'selected' : ''}>No</option>
					<option value='30' #{@rtr=='30' ? 'selected' : ''}>30</option>
					<option value='45' #{@rtr=='45' ? 'selected' : ''}>45</option>
					<option value='90' #{@rtr=='90' ? 'selected' : ''}>90</option>
					<option value='180' #{@rtr=='180' ? 'selected' : ''}>180</option>
					<option value='Rand' #{@rtr=='Rand' ? 'selected' : ''}>Rand</option>
				</select> : Random Rotation<br>									
				<hr>
				<input type='checkbox' name='WOB' value='Yes' #{@rfr=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Random Imperfections<br> 
				#{@rfr!='Yes' ? '<!--' : ''}
				Min:<input type='text' name='RIn' value='#{@rin}' size=4 onChange='optionchanged(name,value)'/>
				Max:<input type='text' name='RIx' value='#{@rix}' size=4 onChange='optionchanged(name,value)'/> <br>
				#{@rfr!='Yes' ? '-->' : ''} 									
				<input type='checkbox' name='BVL' value='Yes' #{@bev=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Add Bevel to #{@@opt}<br>
				#{@bev!='Yes' ? '<!--' : ''}
				Size:<input type='text' name='BVS' value='#{@bvs}' size=4 onChange='optionchanged(name,value)'/><br>
				#{@bev!='Yes' ? '-->' : ''}
				<input type='checkbox' name='CBF' value='Yes' #{@cbf=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Create Behind Face<br>
				<input type='checkbox' name='CIG' value='Yes' #{@cig=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Create Individual Groups<br>
			</fieldset>
			HTML
		end
		
		def clapboard_html
			html=<<-HTML
			<fieldset>
				<legend style='font-size:125%;color:red'><b> Size </b></legend>
				<table style='font-size:100%'>
					<tr><td align='right' width=60>Thickness:</td>
					<td><input type='text' name='CBT' value='#{@cbt}' size=4 onChange='optionchanged(name,value)'/></td></tr>
					<tr><td align='right' width=60>Width:</td>
					<td><input type='text' name='CBW' value='#{@cbw}' size=4 onChange='optionchanged(name,value)'/></td></tr>
					<tr><td align='right' width=60>Overlap:</td>
					<td><input type='text' name='CBO' value='#{@cbo}' size=4 onChange='optionchanged(name,value)'/></td></tr>
				</table>
			</fieldset>
			<fieldset>
				<legend style='font-size:125%;color:red'><b> Options </b></legend>
				<input type='checkbox' name='CIG' value='Yes' #{@cig=='Yes' ? 'checked' : ''} onClick='optionchanged(name,value)'/>Create Individual Groups<br>
				<select name='MAT' style='width:90px' onChange='optionchanged(name,value)'>
					<option value='Current' #{@app=='Current' ? 'selected' : ''}>Current</option>
					<option value='Rand_Clr' #{@app=='Rand_Clr' ? 'selected' : ''}>Rand_Clr</option>
					<option value='Rand_Tex' #{@app=='Rand_Tex' ? 'selected' : ''}>Rand_Tex</option>
				</select> : Material#{@app!='Rand_Tex' ? '<!--' : '<br>'}
				&nbsp&nbsp<button id='RTS' onclick='ChangeSource(id)'>Source</button>#{@app!='Rand_Tex' ? '-->' : '<br>'}
				<textarea name='help' rows="10" cols="20">This pattern can only be placed on a vertical face. If you get a 'beep' that means the face you are trying to select is not vertical.</textarea><br>
			</fieldset>
			HTML
		end
		
		def onMouseMove(flags, x, y, view)
			@ip.pick view,x,y; view.tooltip = @ip.tooltip; view.refresh
			Sketchup::set_status_text "Select Grid Pattern, change options or sizes if needed then select Face for #{@@opt} pattern"
		end
		
		def onLButtonDown(flags, x, y, view)
			ph = view.pick_helper; ph.do_pick x,y; 
			face=ph.best_picked; @cp=@ip.position;
			if face.is_a?(Sketchup::Face)
				# JQL use material from picked face if defined
				@mat = @mod.materials.current
				@mat = face.back_material if face.back_material
				@mat = face.material if face.material
				#
				if @@opt=='Clapbrd'
					if face.normal.z==0
						@mod.start_operation "SDM_FloorGenerator",true
						self.cb_main(face)
						@mod.commit_operation
					else
						UI.beep; UI.messagebox "Clapboards can only be placed on a vertical face"
					end
					return
				end
				dmax = [@GX,@GY].max; 
				if (face.bounds.diagonal >= dmax); # make sure the rectangle is big enough to sub-divide
					unless @@opt=="BsktWv" || @@opt=='Hexgon' || @@opt=='Octgon' || @@opt=='IrPoly' || @@opt=='Diamonds'
						torb = (face.area/(@GX*@GY)).ceil
if (@GX <= 1 || @GY <= 1) || ( torb > 500) then
							return if UI.messagebox("Tile demensions may be to small. #{torb} #{@@opt} needed. Continue?",MB_YESNO)==7
							view.refresh; 
						end
					end
					@mod.start_operation "SDM_FloorGenerator",true
					eye = @vue.camera.eye; ctr=face.bounds.center;@rds>0 ? srand(@rds) : srand;
					face.reverse! if ((ctr.vector_to(eye)).angle_between(face.normal))>Math::PI/2.0
					@edges=face.edges;@norm=face.normal; l=0; fpts=[]; lpts=[]
					# save material applied to picked face
					@front_mat = face.material; @back_mat = face.back_material
					#save original picked face
					if @@opt=="Brick"
						for loop in face.loops
							for v in loop.vertices
								lpts<<v.position if v.position
							end
							fpts[l]=lpts; lpts=[]; l +=1
						end
					end
					
					if self.grid_data(face)
					
						# begin
							@ent.erase_entities(face);
							existing_faces=@ent.grep(Sketchup::Face); dump=@egrp.explode
							dump.grep(Sketchup::Edge).each{|e| e.find_faces};
							created_faces=@ent.grep(Sketchup::Face) - existing_faces;
							cnt=0; max=created_faces.length;new_faces=[]; @rds>0 ? srand(@rds) : srand
							fgrp=@ent.add_group;@fge=fgrp.entities;@fgt=fgrp.transformation;
							@app = "current" if @app=='Rand_Tex' && @textures.length==0
							created_faces.each{|f| 
								cnt += 1; self.progress_bar(cnt,max,"#{@@opt} offsets");
								f.reverse! unless f.normal.samedirection? @norm; 
								@GW>0 ? pts=self.g_offset(f,@HW) : pts=f.outer_loop.vertices.map{|v|v.position}
								if pts
									g = @fge.add_group; ge = g.entities
									face = g.entities.add_face(pts); new_faces << face
									face.reverse! unless face.normal.samedirection?(@norm)
									self.paint_it(face); old = ge.grep(Sketchup::Face)
									@fwt=='Yes' ? gd=@GD : (gd=@GD+(@GD*rand*(rand<=>0.5)));
									face.pushpull gd; 
									new = ge.grep(Sketchup::Face) - old
									new.reject!{|nf| !nf.normal.parallel?(@norm)}
									if new.length==1
										face = new[0]
										self.wig(face) if @rtt=="Yes" && @rti>0
										self.wag(face) unless @rtr=="No"
										self.wob(g,-1) if @rfr=="Yes"
										self.bev(face,@bvs) if @bev=="Yes"
									end
									g.explode unless @cig=='Yes'
								end
							}
							Sketchup.set_status_text "finishing and cleaning up"
							dump.each{|e| @ent.erase_entities(e) if e.valid? && e.is_a?(Sketchup::Edge)}; #delete grid lines
							#re-create original picked face
							if @@opt=="Brick"
								for i in 0...fpts.length
									f=@fge.add_face(fpts[i])
									@fge.erase_entities(f) if i > 0
								end
							end
							# JQL - create pattern behind the original picked face
							if @cbf=='Yes'
								cf=(@ent.grep(Sketchup::Face) - existing_faces)[0]; 
								for l in cf.loops
									nf=@fge.add_face(l.vertices.map{|v|v.position.transform(@fgt.inverse)});
									l.outer? ? nf.reverse! : nf.erase!; # leave face with default material to eliminate Z-fighting
									# l.outer? ? (nf.reverse!;nf.material=@front_material;nf.back_material=@back_mat) : nf.erase!
								end
								drop = @bev=='Yes' ? @GD+@bvs : @GD;	vector = @norm.reverse; vector.length = drop
								@ent.transform_entities(Geom::Transformation.new(vector),fgrp); 
								edges=cf.edges; cf.erase!; edges.each{|e|@ent.erase_entities(e) if e.faces.length==0}
							end
							#
							@mod.commit_operation
						# rescue Exception => e
							# @mod.abort_operation
							# UI.messagebox("Error #<#{e.class.name}:#{e.message}.>")
						# end
					end
					@last_opt = @@opt
				else
					UI.messagebox "This face is to small for a #{@GX} X #{@GY} #{@@opt} pattern.";return false
				end
			end
		end
		
		def cb_main(f)
			cb_spacing=@cbw-@cbo;
			lines = @ent.add_group; lent=lines.entities; ltrn=lines.transformation;
			minz = f.bounds.min.z; maxz = f.bounds.max.z
			norm = f.normal; norm.reverse! if norm.z < 0; xa,ya,za=norm.axes
			maxd = f.bounds.diagonal*2; ctr=f.bounds.center
			pt0 = ctr.offset(xa,-maxd/2).offset(ya,-maxd/2)
			pt0.z = (pt0.z/cb_spacing).floor*cb_spacing+@cbw/2
			ny=(maxd/cb_spacing).ceil
			for n in 1..ny
				pt1=pt0.offset(xa,maxd)
				lent.add_face(self.makeaface(pt0,pt1,norm))
				pt0.offset!(ya,cb_spacing)
			end
			cbgp = @ent.add_group; cbge=cbgp.entities; cbgt=cbgp.transformation
			for l in f.loops
				cbf = cbge.add_face(l.vertices.map{|v|v.position})
				cbf.erase! unless l.outer?
			end
			lent.intersect_with(true,ltrn,cbge,cbgt,false,cbgp)
			faces = cbge.grep(Sketchup::Face); 
			angle = Math.atan(@cbt/cb_spacing); #cbt = @cbt
			faces.each{|nf|
				rp = nf.bounds.max;xa,ya,za=nf.normal.axes;
				fgrp = cbge.add_group; fge = fgrp.entities
				cb = fge.add_face(nf.outer_loop.vertices.map{|v|v.position})
				cb.pushpull @cbt;
				if nf.bounds.min.z==minz
					next
				elsif nf.bounds.min.z <= @cbw
					ang = angle
				elsif nf.bounds.max.z==maxz
					unless nf.bounds.depth<@cbw/3
						spc = @cbt/Math.cos(angle)*Math.sin(angle)
						cbt = Math.sqrt(@cbt**2 - spc**2)
						ang = Math.atan(cbt/(nf.bounds.depth-spc))
					end
				else
					cbt = @cbt/Math.cos(angle)
					ang = Math.atan(cbt/cb_spacing)
				end
				bf = fge.grep(Sketchup::Face).find_all{|x|x.normal.transform(cbgt).z<-0.99 && x.bounds.min.z==fgrp.bounds.min.z}
				bf.each{|x|x.pushpull @cbo}
				tr = Geom::Transformation.rotation(rp,xa,-ang)
				cbge.transform_entities(tr,fgrp) 
				fgrp.explode if @cig=="No"
			}
			self.paint_it(cbgp); # cbgp.material=@mat
			lines.erase!; 
		end
		
		def onRButtonDown(flags, x, y, view)
			onCancel(flags,view)
		end
		 
		def onCancel(flags,view)
			Sketchup.send_action "selectSelectionTool:" 
		end
		
		def deactivate(view)
			@dlg_FG_Picker.close if @dlg_FG_Picker
			@@dlg_FG_Main.close; @@dlg_FG_Main=nil
			Sketchup.active_model.options["UnitsOptions"]["LengthUnit"]=@current_units
			Sketchup.active_model.options["UnitsOptions"]["LengthPrecision"] = @current_precision
		end
		 
		def draw(view)
			if( @ip.valid? && @ip.display? )
				@ip.draw(view)
			end			
			if @ip.face
				pts = @ip.face.outer_loop.vertices.map{|v| v.position}
				view.line_width=3
				view.drawing_color='yellow'
				view.draw GL_LINE_LOOP,pts
			end
		end
#
		def source_of_textures
			ans = UI.inputbox(["Materials From:"],["Folder"],["Folder|Model"],"Random Textures Source")
			if ans
				@dlg_FG_Picker.close if @dlg_FG_Picker
				case ans[0]
					when "Folder" then self.materials_from_file; @options = @textures_from_file;self.pickMaterials;
					when "Model" then @options=Sketchup.active_model.materials.map{|m|m.name};self.pickMaterials;
				end
			end
		end
#
		def materials_from_file
			@textures_from_file = []; @images = []; @image_path = File.dirname(__FILE__)+"/BTW_Textures/*.*"
			@image_path = Sketchup.read_default("FloorGenerator","Rand_Tex",@image_path)
			@image_path = (UI.openpanel("Random Texture Files",@image_path))
			unless @image_path==nil
				image_folder = File.dirname(@image_path.gsub('\\','/'));@images = []; 
				@images = Dir[image_folder+"/*.{jpg,png,tif,bmp,gif,tga,epx}"]
				@images.each{|i| @textures_from_file<<File.basename(i,'.*')};
				if @textures_from_file[0]
					@textures_from_file.each_with_index{|name,i|
						unless @mod.materials[name]
							mat = @mod.materials.add(name)
							mat.texture = @images[i]
							mat.texture.size = @txs if @txs && @txs != 0
						end
					}
					Sketchup.write_default("FloorGenerator","Rand_Tex",image_folder+"/*.*")
				else
					@app = "current"
				end
			else
				@app = "current"
			end
		end
#
		def pickMaterials
			@dlg_FG_Picker=UI::WebDialog.new("Material Picker", false,"WDID",300,200,10,10,true)
			html = <<-HTML
			<!DOCTYPE html>
			<html lang="en-US">
				<head>
					<meta charset="utf-8" />
					<meta content="IE=edge" http-equiv="X-UA-Compatible"
/>
				</head>
				<body>
					<form action='skp:selectMaterials@'>
						<select id='list' name='Material' multiple ></select>
						<br><br><input type='submit' name='submit' value='Select' /><br>
					</form>
					<script>
						
						function addToList(id,options)
						{
							var x = document.getElementById(id);
							for (i=0;i<options.length;i++){var option=document.createElement('option');option.text=options[i];x.add(option);};
							x.selectIndex=0;
						};
						
					</script>
					<script>
					
						window.location='skp:InitializeForm@';
						
					</script>
				</body>
			</html>
			HTML
			@dlg_FG_Picker.set_html(html)
			
			RUBY_PLATFORM =~ /(darwin)/ ? @dlg_FG_Picker.show_modal() : @dlg_FG_Picker.show();
			
			@dlg_FG_Picker.add_action_callback("InitializeForm") {
				@dlg_FG_Picker.execute_script("addToList('list',#{@options});");
			};
			
			@dlg_FG_Picker.add_action_callback("selectMaterials") {|d,p|
				p.gsub!("?",""); tokens=p.split("&"); #puts p
				@textures = []
				tokens.each{|t|
					var,val = t.split("="); #puts t
					@textures << val if var=='Material'
				}
			};
		end
#
##################################################
#	Compute the data points of the grid
##################################################
#	
		def grid_data(face)
			pts=face.outer_loop.vertices.collect{|v| v.position}
			ndx=0; cp=1e6; ls=0.0; lp=pts.length-1; # assume regular 4 sided rectangle
			pts.each_with_index{|p,i| d=p.distance(pts[i-1])+p.distance(pts[i-lp]); ndx=i if d>ls; ls=[ls,d].max}
			ctr=face.bounds.center;
			ctr=ctr.project_to_plane face.plane unless ctr.on_plane? face.plane
			d1=pts[ndx].distance(pts[ndx-lp]); d2=pts[ndx].distance(pts[ndx-1]);
			if d1 >= d2
				@v1=pts[ndx].vector_to(pts[ndx-lp]).normalize
				pol=ctr.project_to_line([pts[ndx],pts[ndx-lp]])
				rot = @rot.to_f; @dx = d1; @dy = d2
			else
				@v1=pts[ndx].vector_to(pts[ndx-1]).normalize
				pol=ctr.project_to_line([pts[ndx],pts[ndx-1]]);
				rot = -@rot.to_f; @dx = d2; @dy = d1
			end
			@v2=pol.vector_to(ctr).normalize; @v3=face.normal
				
			unless @@opt=='IrPoly'
			
				if @rot != "0"
					tr=Geom::Transformation.rotation(ctr,@norm,rot.degrees)
					@v1.transform! tr; @v2.transform! tr
				end
				
				@cor = pts.min_by{|p|p.distance(@cp)}
				
				dx = @GX + @GW; dy = @GY + @GW;
				nx=(face.bounds.diagonal*1.5/dx).ceil;ny=(face.bounds.diagonal*1.5/dy).ceil;
				(nx *= 2 if @flw=="No"; ny *= 2 if @fww=="No") if @@opt=="Wood"
				pt0 = ctr.offset(@v1,-dx*(nx/2)).offset(@v2,-dy*(ny/2))
				
				@data=[];row=[]; cnt=0; max=nx*ny; #@ent.add_cpoint(pt0)
					
				case @@opt
					when "Wood"
						yd = 0.0; @rds>0 ? srand(@rds) : srand
						for i in 0..ny
							p0=row[0]=pt0.offset(@v2,yd)
							d = 0.0; ty = dy
							for j in 1..nx
								tx=dx
								if j==1
									begin
										tx=rand*dx
									end until tx>=dx*0.25 && tx<=dx*0.75
								else
									if @flw=="No"
										begin
											tx=rand*dx
										end until tx>=dx*0.75
									end
								end
								d += tx; row[j]=p0.offset(@v1,d)
							end
							if @fww=="No"
								begin
									ty=rand*dy
								end until ty>=dy*0.5
							end
							row.push ty; yd += ty
							@data[i]=row;row=[]
						end
					when "Tweed"
						dx=@GY + @GW; dy=@GX + @GW;
						xd=dx/Math.cos(@twa.degrees)
						yd=dy*Math.cos(@twa.degrees)
						xx=dy*Math.sin(@twa.degrees)
						ny=((face.bounds.diagonal*1.5)/yd).ceil;nx=((face.bounds.diagonal*1.5)/xd).ceil;
						pt0 = ctr.offset(@v1,-(xd*(nx/2))).offset(@v2,-(yd*(ny/2)))
						for i in 0..ny
							row[0]=pt0.offset(@v2,yd*i)
							if i%2==1 then row[0].offset!(@v1,-xx) end
							for j in 1..nx
								row[j]=row[j-1].offset(@v1,xd)
							end
							@data[i]=row;row=[]
						end
					end
				end
				
				case @@opt
					when "Brick","Tile" ; self.brick_tile(face,dx,dy,nx,ny,pt0)
					when "Wood" ; self.wood(face,nx,ny)
					when "Tweed" ; self.tweed(face,nx,ny)
					when "Hbone" ; self.hbone(face)
					when "BsktWv" ; self.bsktwv(face,dx,dy) 
					when "HpScth1"; self.hopscotch(face,dx,dy)
					when "HpScth2" ; self.hopscotch2(face,dx,dy)
					when 'HpScth3' ; self.hopscotch3(face)
					when "HpScth4" ; self.hopscotch4(face,dx,dy)
					when "Hexgon" ; self.hexagon(face,@GX)
					when "Octgon" ; self.octagon(face,@GX)
					when "IrPoly" ; self.irregular_polygons(face)
					when "Wedge" ; self.wedge(face,dx,dy)
					when "I_Block"; self.i_block(face,dx,dy)
					when "Diamonds" ; self.diamonds(face,@GX)
					when "Clapbrd"; self.cb_main(face)
					else puts "#{@@opt} not found";return false
				end
				return true
		end
#
##################################################
#	Create brick/tile pattern grid on selected face
##################################################
#
		def brick_tile(f,dx,dy,nx,ny,pt0)
			tg=@ent.add_group;tge=tg.entities;tgt=tg.transformation
			for i in 0..ny+1
				p0=pt0.offset(@v2,dy*i);p1=p0.offset(@v1,dx*nx)
				tge.add_face(self.makeaface(p0,p1,@norm))
				unless i>0
					p1=p0.offset(@v2,dy*ny)
					tge.add_face(self.makeaface(p0,p1,@norm))
				end
			end
			cnt=0; max=nx*ny; md=1e9
			for i in 0..ny
				p0=pt0.offset(@v2,dy*i)
				i>0 ? xd=((i*@r2r)%100/100.0)*dx : xd=dx
				for j in 0..nx
					cnt+=1;self.progress_bar(cnt,max,"#{@@opt} Grid")
					p1=p0.offset(@v1,xd);xd=dx;p2=p1.offset(@v2,dy)
					tge.add_face(self.makeaface(p1,p2,@norm))
					(d=@cor.distance(p0); (cpt=p0;md=d) if md>d) if @spt=="Corner" && i>0
					p0=p1
				end
			end
			(tr = Geom::Transformation.new(cpt.vector_to(@cor)); 
			tge.transform_entities(tr,tge.to_a )) if @spt=="Corner"
			@egrp=@ent.add_group;@ege=@egrp.entities;@egt=@egrp.transformation
			Sketchup::set_status_text "Intersecting Grid and Face"
			tge.intersect_with(true,tgt,@ege,@egt,false,f)
			tg.erase! unless $sdm_debug; 
		end
#
##################################################
#	Create wood pattern grid on selected face
##################################################
#	
		def wood(f,nx,ny)
			tg=@ent.add_group;tge=tg.entities;tgt=tg.transformation
			cnt=0; max=nx*ny; md=1e9
			for i in 0...ny
				dy = @data[i][-1]; 
				for j in 1..nx
					cnt += 1; self.progress_bar(cnt,max,"Wood grid")
					tge.add_face(self.makeaface(@data[i][j-1],@data[i][j],@norm))
					tge.add_face(self.makeaface(@data[i][j],@data[i][j].offset(@v2,dy),@norm))
					(d=@cor.distance(@data[i][j-1]); (cpt=@data[i][j-1];md=d) if md>d) if @spt=="Corner" && i>0
				end
			end
			(tr = Geom::Transformation.new(cpt.vector_to(@cor)); 
			tge.transform_entities(tr,tge.to_a )) if @spt=="Corner"
			@egrp=@ent.add_group;@ege=@egrp.entities;@egt=@egrp.transformation
			Sketchup::set_status_text "Intersecting Grid and Face"
			tge.intersect_with(true,tgt,@ege,@egt,false,f)
			tg.erase! unless $sdm_debug; 
		end
#
##################################################
#	Create Tweed pattern grid on selected face
##################################################
#	
		def tweed(f,nx,ny)
		
			tg=@ent.add_group;tge=tg.entities;tgt=tg.transformation
			cnt=0; max=nx*ny; md=1e9
			for i in 1..ny
				for j in 1..nx
					cnt += 1; self.progress_bar(cnt,max,"Tweed grid")
					tge.add_face(self.makeaface(@data[i-1][j-1],@data[i][j-1],@norm))
					tge.add_face(self.makeaface(@data[i-1][j-1],@data[i-1][j],@norm))
					(d=@cor.distance(@data[i-1][j-1]); (cpt=@data[i-1][j-1];md=d) if md>d) if @spt=="Corner" && i>1
				end
				tge.add_face(self.makeaface(@data[i-1][nx],@data[i][nx],@norm))
			end
			(tr = Geom::Transformation.new(cpt.vector_to(@cor)); 
			tge.transform_entities(tr,tge.to_a )) if @spt=="Corner"
			@egrp=@ent.add_group;@ege=@egrp.entities;@egt=@egrp.transformation
			Sketchup::set_status_text "Intersecting Grid and Face"
			tge.intersect_with(true,tgt,@ege,@egt,false,f)
			tg.erase! unless $sdm_debug;
		end
#
##################################################
#	Create Herringbone pattern grid on selected face
##################################################
#	
		def hbone(f)
			dx=@GY + @GW;dy=@GX + @GW;ctr=f.bounds.center
			ny=((f.bounds.diagonal*1.2)/(dy*0.707107)).ceil;nx=((f.bounds.diagonal*1.2)/(dx/0.707107)).ceil;
			pt = ctr.offset(@v1,-((dx/0.707107)*(nx/2))).offset(@v2,-((dy/0.707107)*(ny/2))/2);
			vup=@v1.transform Geom::Transformation.rotation(pt,@norm,45.degrees)
			vdn=@v1.transform Geom::Transformation.rotation(pt,@norm,-45.degrees)
			tg=@ent.add_group; tge=tg.entities; tgt=tg.transformation
			xv=@v1;xv.length=dx/0.707107; yv=@v2;yv.length=dy/0.707107
			cnt=0; max=nx*ny; md=1e9; gp=pt;
			p0=pt#.offset(Geom::Vector3d.new(0,0,-1))
			for i in 0..ny/2
				for j in 0..nx
					cnt += 1; self.progress_bar(cnt,max,"H'bone grid")
					p1=p0.offset(vdn,dy);tge.add_face(self.makeaface(p0,p1,@norm))
					p2=p1.offset(vup,dx);tge.add_face(self.makeaface(p1,p2,@norm))
					p3=p2.offset(vdn,-dy);tge.add_face(self.makeaface(p2,p3,@norm))
					tge.add_face(self.makeaface(p3,p0,@norm))
					cnt += 1; self.progress_bar(cnt,max,"H'bone grid")
					p1=p0.offset(vup,dy);tge.add_face(self.makeaface(p0,p1,@norm))
					p2=p1.offset(vdn,-dx);tge.add_face(self.makeaface(p1,p2,@norm))
					p3=p2.offset(vup,-dy);tge.add_face(self.makeaface(p2,p3,@norm))
					tge.add_face(self.makeaface(p3,p0,@norm))
					(d=@cor.distance(gp);(cpt=gp;md=d) if md>d) if @spt=="Corner" && i>0
					p0 += xv; gp += xv
				end
					pt.offset!(yv); gp=pt
					p0=pt#.offset(Geom::Vector3d.new(0,0,-1))
			end
			(tr = Geom::Transformation.new(cpt.vector_to(@cor)); 
			tge.transform_entities(tr,tge.to_a )) if @spt=="Corner"
			@egrp=@ent.add_group;@ege=@egrp.entities;@egt=@egrp.transformation
			Sketchup::set_status_text "Intersecting Grid and Face"
			tge.intersect_with(true,tgt,@ege,@egt,false,f)
			tg.erase! unless $sdm_debug;
		end
#
##################################################
#	Create Basket Weave pattern on selected face
##################################################
#	
		def bsktwv (f,dx,dy)
			@bwb=3 unless [2,3,4].include?(@bwb)
			if dx==@GW then
				del=dy*@bwb*2
			elsif dy==@GW
				del=dx*2
			else
				del=[dx,dy*@bwb].max
				if del==dx then
					dy=dx/@bwb
					del=dx*2
				else
					dx=dy*@bwb
					del=dx*2
				end
			end
			name="BW-#{dx.to_l}X#{dy.to_l}X#{@bwb}"
			unless @mod.definitions[name]
				bw=@mod.definitions.add(name)
				be=bw.entities;pts=[];pts[0]=Geom::Point3d.new()
				v1=[1,0,0]; v2=[0,1,0]; norm=[0,0,1]
				tr=Geom::Transformation.new(pts[0],norm,90.degrees)
				for i in 0..@bwb-1
					pts<<pts[i].offset(v2,dy)
				end
				pts<<pts[@bwb].offset(v1,dx)
				for i in @bwb+1..@bwb*2
					pts<<pts[i].offset(v2,-dy)
				end
				for n in 1..4
					case @bwb
						when 2
							be.add_face(self.makeaface(pts[0],pts[2],norm))
							be.add_face(self.makeaface(pts[2],pts[3],norm))
							be.add_face(self.makeaface(pts[3],pts[5],norm))
							be.add_face(self.makeaface(pts[1],pts[4],norm))
						when 3
							be.add_face(self.makeaface(pts[0],pts[3],norm))
							be.add_face(self.makeaface(pts[3],pts[4],norm))
							be.add_face(self.makeaface(pts[4],pts[7],norm))
							be.add_face(self.makeaface(pts[1],pts[6],norm))
							be.add_face(self.makeaface(pts[2],pts[5],norm))
						when 4
							be.add_face(self.makeaface(pts[0],pts[4],norm))
							be.add_face(self.makeaface(pts[4],pts[5],norm))
							be.add_face(self.makeaface(pts[5],pts[9],norm))
							be.add_face(self.makeaface(pts[1],pts[8],norm))
							be.add_face(self.makeaface(pts[2],pts[7],norm))
							be.add_face(self.makeaface(pts[3],pts[6],norm))
					end
					pts.each{|p| p.transform! tr}
				end
				ci=@ent.add_instance(@mod.definitions[name],pts[0])
				ci.erase!
			end
			cmp = @mod.definitions[name]
			ctr=f.bounds.center; diag=f.bounds.diagonal*1.5
			del=dx*2;ny=nx=(diag/del).ceil;md=1e9;cnt=0;max=nx*ny
			org=ctr.offset(@v1,-(del*(nx/2))).offset(@v2,-(del*(ny/2)));
			tg=@ent.add_group;tge=tg.entities;tgt=tg.transformation
			for i in 0..ny
				p0=org.offset(@v2,del*i)
				for j in 0..nx
					cnt += 1; self.progress_bar(cnt,max,"BasketWeave Grid")
					pt=p0.offset(@v1,del*j)
					(d=@cor.distance(pt);(cpt=pt;md=d) if md>d) if @spt=="Corner" && i>0
					ci=tge.add_instance(cmp,Geom::Transformation.axes(pt,@v1,@v2,@norm))
				end
			end
			(tr = Geom::Transformation.new(cpt.vector_to(@cor)); 
			tge.transform_entities(tr,tge.to_a )) if @spt=="Corner"
			@egrp=@ent.add_group;@ege=@egrp.entities;@egt=@egrp.transformation
			Sketchup::set_status_text "Intersecting Grid and Face"
			tge.intersect_with(true,tgt,@ege,@egt,false,f)
			tg.erase! unless $sdm_debug;
		end
#
##################################################
#	Create HopScotch1 pattern on selected face
##################################################
#	
		def hopscotch(f,dx,dy)
			hx=dx/2.0;hy=dy/2.0;
			name="HS1-#{dx.to_l}x#{dy.to_l}"
			cmp=@mod.definitions[name];
			unless cmp
				p0=Geom::Point3d.new(); v1=[1,0,0]; v2=[0,1,0]; norm=[0,0,1]
				cmp=@mod.definitions.add(name);cpe=cmp.entities
				p1=p0.offset(v2,dy);cpe.add_face(self.makeaface(p0,p1,norm))
				p2=p1.offset(v1,dx);cpe.add_face(self.makeaface(p1,p2,norm))
				p3=p2.offset(v1,hx);cpe.add_face(self.makeaface(p2,p3,norm))
				p4=p3.offset(v2,-hy);cpe.add_face(self.makeaface(p3,p4,norm))
				p5=p4.offset(v1,-hx);cpe.add_face(self.makeaface(p4,p5,norm))
				p6=p2.offset(v2,-dy);cpe.add_face(self.makeaface(p2,p6,norm))
				cpe.add_face(self.makeaface(p6,p0,norm))
				ci=@ent.add_instance(cmp,p0);ci.erase!
			end
			ctr=f.bounds.center; dxx=dx+dx+hx
			tg=@ent.add_group;tge=tg.entities;tgt=tg.transformation
			nx=(f.bounds.diagonal*1.2/dxx).ceil;ny=(f.bounds.diagonal*1.2/hy).ceil
			pt0=ctr.offset(@v1,-(dxx*(nx/2))).offset(@v2,-(hy*(ny/2)))
			cnt=0; max=nx*ny; md=1e9;pt=pt0.clone;
			for i in 0..ny
				for j in 0..nx
					cnt += 1; self.progress_bar(cnt,max,"Hopscotch Grid")
					ci=tge.add_instance(cmp,Geom::Transformation.axes(pt,@v1,@v2,@norm))
					pt.offset!(@v1,dxx)
					(d=@cor.distance(pt);(cpt=pt.clone;md=d) if md>d) if @spt=="Corner" && i>0
				end
				case i%5
					when 0 then pt=pt0.offset(@v1,-dx).offset(@v2,hy);#v01
					when 1 then pt=pt0.offset(@v1,hx).offset(@v2,dy);#v02
					when 2 then pt=pt0.offset(@v1,-hx).offset(@v2,dy+hy);#v03
					when 3 then pt=pt0.offset(@v1,dx).offset(@v2,dy*2);#v04
					when 4 then pt=pt0.offset(@v2,dy*2+hy);	pt0.offset!(@v2,dy*2+hy);#v05
				end
			end
			(tr = Geom::Transformation.new(cpt.vector_to(@cor)); 
			tge.transform_entities(tr,tge.to_a )) if @spt=="Corner"
			@egrp=@ent.add_group;@ege=@egrp.entities;@egt=@egrp.transformation
			Sketchup::set_status_text "Intersecting Grid and Face"
			tge.intersect_with(true,tgt,@ege,@egt,false,f)
			tg.erase! unless $sdm_debug;
		end
#
#######################################################
#		Create HopScotch2 Pattern on selected face
#######################################################
#
		def hopscotch2(f,dx,dy)
			hx=dx/2.0;hy=dy/2.0;p0=Geom::Point3d.new();
			cpd = @mod.definitions;cid = "HS2-#{dx.to_l}x#{dy.to_l}"; cmp = cpd[cid]
			unless cmp
				cmp = cpd.add(cid);xa=[1,0,0];ya=[0,1,0];za=[0,0,1];
				p1=p0.offset(ya,dy);cmp.entities.add_face(self.makeaface(p0,p1,za))
				p2=p1.offset(xa,dx);cmp.entities.add_face(self.makeaface(p1,p2,za))
				p3=p2.offset(xa,hx);cmp.entities.add_face(self.makeaface(p2,p3,za))
				p4=p3.offset(ya,-hy);cmp.entities.add_face(self.makeaface(p3,p4,za))
				p5=p4.offset(ya,-hy);cmp.entities.add_face(self.makeaface(p4,p5,za))
				p6=p0.offset(xa,dx);p7=p6.offset(ya,hy)
				cmp.entities.add_face(self.makeaface(p5,p0,za))
				cmp.entities.add_face(self.makeaface(p6,p2,za))
				cmp.entities.add_face(self.makeaface(p7,p4,za))
				ci=@ent.add_instance(cmp,p0); ci.erase!
			end
			delx=dx+hx; diag=f.bounds.diagonal*1.2; ctr=f.bounds.center
			nx=(diag/delx).ceil;ny=(diag/dy).ceil
pt0=ctr.offset(@v1,-(delx*(nx/2+1))).offset(@v2,-(dy*(ny/2+1)))
			tg=@ent.add_group; tge=tg.entities; tgt=tg.transformation
			cnt=0; max=nx*ny; md=1e9; p0=pt0.clone
			for i in 0..ny
				p0=pt0.offset(@v2,dy*i)
				p0.offset!(@v1,-hx) if i%2==1
				for j in 0..nx
					cnt += 1; self.progress_bar(cnt,max,"No Name Grid")
					tge.add_instance(cmp,Geom::Transformation.axes(p0,@v1,@v2,@norm))
					(d=@cor.distance(p0);(cpt=p0.clone;md=d) if md>d) if @spt=="Corner" && j>0
					p0.offset!(@v1,delx)
				end
			end
			(tr = Geom::Transformation.new(cpt.vector_to(@cor)); 
			tge.transform_entities(tr,tge.to_a )) if @spt=="Corner"
			@egrp=@ent.add_group;@ege=@egrp.entities;@egt=@egrp.transformation
			Sketchup::set_status_text "Intersecting Grid and Face"
			tge.intersect_with(true,tgt,@ege,@egt,false,f)
			tg.erase! unless $sdm_debug;
		end
#
#######################################################
#		Create HopScotch3 Pattern on selected face
#######################################################
#
		def hopscotch3(f)
			cid="HS3-#{@GX}X#{@GY}"; cmp = @mod.definitions[cid]
			unless cmp
				cmp = @mod.definitions.add(cid);cde=cmp.entities; norm=[0,0,1]
				p0=[0.0,0.0,0.0];p1=[8.0,0.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[0.0,24.0,0.0];p1=[0.0,16.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[4.0,4.0,0.0];p1=[4.0,8.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[4.0,8.0,0.0];p1=[0.0,8.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[4.0,4.0,0.0];p1=[0.0,4.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[8.0,16.0,0.0];p1=[12.0,16.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[16.0,20.0,0.0];p1=[16.0,16.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[8.0,24.0,0.0];p1=[8.0,20.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[16.0,8.0,0.0];p1=[20.0,8.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[16.0,24.0,0.0];p1=[16.0,20.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[20.0,8.0,0.0];p1=[20.0,4.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[16.0,8.0,0.0];p1=[16.0,4.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[20.0,0.0,0.0];p1=[24.0,0.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[12.0,12.0,0.0];p1=[16.0,12.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[8.0,16.0,0.0];p1=[4.0,16.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[20.0,8.0,0.0];p1=[24.0,8.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[0.0,16.0,0.0];p1=[0.0,8.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[12.0,4.0,0.0];p1=[12.0,8.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[16.0,16.0,0.0];p1=[16.0,12.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[16.0,12.0,0.0];p1=[16.0,8.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[12.0,12.0,0.0];p1=[12.0,16.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[16.0,20.0,0.0];p1=[24.0,20.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[12.0,8.0,0.0];p1=[12.0,12.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[16.0,4.0,0.0];p1=[12.0,4.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[16.0,4.0,0.0];p1=[20.0,4.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[12.0,0.0,0.0];p1=[20.0,0.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[8.0,20.0,0.0];p1=[4.0,20.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[0.0,8.0,0.0];p1=[0.0,4.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[20.0,4.0,0.0];p1=[20.0,0.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[12.0,16.0,0.0];p1=[16.0,16.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[12.0,4.0,0.0];p1=[12.0,0.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[12.0,8.0,0.0];p1=[8.0,8.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[8.0,20.0,0.0];p1=[8.0,16.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[8.0,0.0,0.0];p1=[12.0,0.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[8.0,4.0,0.0];p1=[8.0,0.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[8.0,8.0,0.0];p1=[4.0,8.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[0.0,4.0,0.0];p1=[0.0,0.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[8.0,4.0,0.0];p1=[4.0,4.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[8.0,4.0,0.0];p1=[8.0,8.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[4.0,16.0,0.0];p1=[0.0,16.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[4.0,20.0,0.0];p1=[4.0,16.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				p0=[4.0,20.0,0.0];p1=[4.0,24.0,0.0];cde.add_face(self.makeaface(p0,p1,norm))
				unless @GX==24.0 && @GY==24.0
					xscl=@GX/24.0; yscl=@GY/24.0; zscl=1.0
					trs=Geom::Transformation.scaling(xscl,yscl,zscl)
					cde.transform_entities(trs,cde.to_a)
				end
			end
			dx = @GX; dy = @GY
			diag=f.bounds.diagonal*1.2;ctr=f.bounds.center
			nx=[(diag/dx).ceil,5].max;ny=[(diag/dy).ceil,5].max
			org=ctr.offset(@v1,-(dx*(nx/2))).offset(@v2,-(dy*(ny/2)));
			tg=@ent.add_group; tge=tg.entities; tgt=tg.transformation
			cnt=0; max=nx*ny; md=1e9;
			for i in 0...ny
				pt=org.offset(@v2,dy*i)
				 for j in 0...nx
					cnt += 1; self.progress_bar(cnt,max,"Irregular Polygon Grid")
					(d=@cor.distance(pt);(cpt=pt.clone;md=d) if md>d) if @spt=="Corner" && j>0
					ci=tge.add_instance(cmp,Geom::Transformation.axes(pt,@v1,@v2,@norm))
					pt.offset!(@v1,dx)
				 end
			end
			(tr = Geom::Transformation.new(cpt.vector_to(@cor)); 
			tge.transform_entities(tr,tge.to_a )) if @spt=="Corner"
			@egrp=@ent.add_group;@ege=@egrp.entities;@egt=@egrp.transformation
			Sketchup::set_status_text "Intersecting Grid and Face"
			tge.intersect_with(true,tgt,@ege,@egt,false,f)
			tg.erase! unless $sdm_debug;
		end
#
#######################################################
#		Create HopScotch4 Pattern on selected face
#######################################################
#
		def hopscotch4(f,dx,dy)
			cid="HS4-#{@GX}x#{@GY}"
			cmp=@mod.definitions[cid]
			unless cmp
				cmp=@mod.definitions.add(cid);cde=cmp.entities;	hx=dx/2;hy=dy/2
				vx=Geom::Vector3d.new(1,0,0);vy=Geom::Vector3d.new(0,1,0);
				vz=Geom::Vector3d.new(0,0,1); p0=Geom::Point3d.new(-hx,0,0);
				p1=p0.offset(vx,hx);cde.add_face(self.makeaface(p0,p1,vz))
				p2=p1.offset(vx,dx);cde.add_face(self.makeaface(p1,p2,vz))
				p3=p2.offset(vx,dx);cde.add_face(self.makeaface(p2,p3,vz))
				p4=p3.offset(vy,-hy);cde.add_face(self.makeaface(p3,p4,vz))
				p5=p1.offset(vy,hy);cde.add_face(self.makeaface(p1,p5,vz))
				p6=p5.offset(vx,-hx);cde.add_face(self.makeaface(p5,p6,vz))
				p7=p5.offset(vy,hy);cde.add_face(self.makeaface(p5,p7,vz))
				p8=p2.offset(vy,hy);cde.add_face(self.makeaface(p2,p8,vz))
				p9=p8.offset(vy,hy);cde.add_face(self.makeaface(p8,p9,vz))
				p10=p8.offset(vx,dx);cde.add_face(self.makeaface(p8,p10,vz));cde.add_face(self.makeaface(p10,p3,vz))
				p11=p10.offset(vx,dx);cde.add_face(self.makeaface(p10,p11,vz))
				p12=p11.offset(vy,-dy);cde.add_face(self.makeaface(p11,p12,vz))
			end
			diag=f.bounds.diagonal*1.2;ctr=f.bounds.center;dxx=dx*3+hx
			nx=[(diag/dxx).ceil,5].max;ny=[(diag/dy).ceil,5].max
			org=ctr.offset(@v1,-(dxx*(nx/2))).offset(@v2,-(dy*(ny/2)));
			tg=@ent.add_group; tge=tg.entities; tgt=tg.transformation
			cnt=0; max=nx*ny; md=1e9;p0=org.clone
			for i in 1..ny
				for j in 0..nx
					cnt += 1; self.progress_bar(cnt,max,"Irregular Polygon Grid")
					(d=@cor.distance(p0);(cpt=p0.clone;md=d) if md>d) if @spt=="Corner" && j>0
					tge.add_instance(cmp,Geom::Transformation.axes(p0,@v1,@v2,@norm))
					p0.offset!(@v1,dxx)
				end
				p0=org.offset(@v2,dy*i).offset(@v1,-hx*(i%7));
			end
			(tr = Geom::Transformation.new(cpt.vector_to(@cor)); 
			tge.transform_entities(tr,tge.to_a )) if @spt=="Corner"
			@egrp=@ent.add_group;@ege=@egrp.entities;@egt=@egrp.transformation
			Sketchup::set_status_text "Intersecting Grid and Face"
			tge.intersect_with(true,tgt,@ege,@egt,false,f)
			tg.erase! unless
$sdm_debug;
		end
#
##################################################
#	Create Hexagon pattern on selected face
##################################################
#
		def hexagon(face,side)
			cpd = @mod.definitions
			ang=30.0.degrees; rad=side+@HW/Math.cos(ang);
			cid = "Hex-#{side.to_l}"; cmp = cpd[cid]
			unless cmp
				org = [0,-rad,0];xa=[1,0,0];ya=[0,1,0];za=[0,0,1];
				cmp = cpd.add(cid);ctb=rad*Math.cos(ang);vec=[0,-rad,0]
				hex = @ent.add_ngon org,za,rad,6
				pts = hex.each.collect{|e| e.end.position}
				tr1=Geom::Transformation.rotation(org,za,ang)
				pts.each{|p| p.transform! tr1}
				for i in 0...pts.length
					cmp.entities.add_face(self.makeaface(pts[i-1],pts[i],za))
				end
				hex.each{|e| @ent.erase_entities(e)}
			end
			cos=Math.cos(ang); 
			ctb=rad*cos; c2c=ctb*2.0; r2r=c2c*cos
			xo1=ctb; xo2=ctb*2.0;yo1=rad; 
			ctr=face.bounds.center;diag=face.bounds.diagonal*1.2
			nx=(diag/c2c).ceil;ny=(diag/r2r).ceil;
			pt0=ctr.offset(@v1,-(c2c*(nx/2))).offset(@v2,-(r2r*(ny/2)))
			tg=@ent.add_group;tge=tg.entities;tgt=tg.transformation
			cnt=0; max=nx*ny; md=1e9; #puts "nx=#{nx}, ny=#{ny}, max=#{max}"
			for j in 0..ny
				 if j%2==1
					p0=pt0.offset(@v1,xo1).offset(@v2,yo1)
				 else
					p0=pt0.offset(@v1,xo2).offset(@v2,yo1)
				 end
				 tge.add_instance(cmp,Geom::Transformation.axes(p0,@v1,@v2,@norm))
				 for i in 0..nx 
					cnt += 1; self.progress_bar(cnt,max,"Hexagon Grid")
					tge.add_instance(cmp,Geom::Transformation.axes(p0,@v1,@v2,@norm))
					(d=@cor.distance(p0);(cpt=p0.clone;md=d) if md>d) if @spt=="Corner" && j>0
					p0.offset!(@v1,c2c);
				 end 
				 pt0.offset!(@v2,r2r); 
			end
			(tr = Geom::Transformation.new(cpt.vector_to(@cor)); 
			tge.transform_entities(tr,tge.to_a )) if @spt=="Corner"
			@egrp=@ent.add_group;@ege=@egrp.entities;@egt=@egrp.transformation
			Sketchup::set_status_text "Intersecting Grid and Face"
			tge.intersect_with true,tgt,@ege,@egt,false,face
			tg.erase! unless $sdm_debug;
		end
#
##################################################
#	Create Diamond pattern on selected face
##################################################
#
		def diamonds(face,side)
			rad=side+@HW/Math.cos(30.degrees);
			cid="Dia-#{side}";cmp=@mod.definitions[cid]
			unless cmp
				cmp=@mod.definitions.add(cid)
				p0=[0,0,0];za=[0,0,1]
				hex=@ent.add_ngon(p0,za,rad,6)
				pts=hex.each.collect{|e|e.start.position}
				for i in 0...pts.length
					cmp.entities.add_face(self.makeaface(pts[i-1],pts[i],za))
				end
				for i in 0...pts.length
					p1=p0.offset(p0.vector_to(pts[i-1]),p0.distance(pts[i-1])/2)
					cmp.entities.add_face(self.makeaface(p0,p1,za))
					p2=pts[i-1].offset(pts[i-1].vector_to(pts[i]),rad/2.0)
					cmp.entities.add_face(self.makeaface(p1,p2,za))
					p3=pts[i-2].offset(pts[i-2].vector_to(pts[i-1]),rad/2.0)
					cmp.entities.add_face(self.makeaface(p1,p3,za))
				end
				hex.each{|e| @ent.erase_entities(e)}
			end
			ctb=rad*Math.cos(30.degrees); c2c=rad*3.0;r2r=ctb*2.0
			ctr=face.bounds.center;diag=face.bounds.diagonal*1.2
			nx=(diag/c2c).ceil;ny=(diag/r2r).ceil;
			pt0=ctr.offset(@v1,-(c2c*(nx/2))).offset(@v2,-(r2r*(ny/2)))
			tg=@ent.add_group;tge=tg.entities;tgt=tg.transformation
			cnt=0; max=nx*ny; md=1e9;p0=pt0.clone
			for j in 0..ny
				for i in 0..nx 
					cnt += 1; self.progress_bar(cnt,max,"Hexagon Grid")
					tge.add_instance(cmp,Geom::Transformation.axes(p0,@v1,@v2,@norm))
					(d=@cor.distance(p0);(cpt=p0.clone;md=d) if md>d) if @spt=="Corner" && j>0
					p1=p0.offset(@v1,c2c/2.0).offset(@v2,-ctb);
					tge.add_instance(cmp,Geom::Transformation.axes(p1,@v1,@v2,@norm))
					(d=@cor.distance(p1);(cpt=p1.clone;md=d) if md>d) if @spt=="Corner" && j>0
					p0.offset!(@v1,c2c);
				end 
				pt0.offset!(@v2,r2r); p0=pt0.clone
			end
			(tr = Geom::Transformation.new(cpt.vector_to(@cor)); 
			tge.transform_entities(tr,tge.to_a )) if @spt=="Corner"
			@egrp=@ent.add_group;@ege=@egrp.entities;@egt=@egrp.transformation
			Sketchup::set_status_text "Intersecting Grid and Face"
			tge.intersect_with true,tgt,@ege,@egt,false,face
			tg.erase! unless $sdm_debug;
		end
#
##################################################
#	Create Octagon pattern on selected face
##################################################
#
		def octagon(face,side)
			half=side/2.0; ang=22.5.degrees; rad=half/Math.sin(ang); rad += @HW/Math.cos(ang)
			@d_area=(side+(Math.tan(ang)*@HW)*2)**2
			cpd = @mod.definitions;cid = "Oct-#{side.to_l}"; cmp = cpd[cid]
			unless cmp
				org = [@GW-half,@GW-half,0];xa=[1,0,0];ya=[0,1,0];za=[0,0,1];
				cmp = cpd.add(cid);
				hex = @ent.add_ngon org,za,rad,8
				pts = hex.each.collect{|e| e.end.position}
				tr1=Geom::Transformation.rotation(org,za,ang)
				pts.each{|p| p.transform! tr1}
				for i in 0...pts.length
					cmp.entities.add_face(self.makeaface(pts[i-1],pts[i],za))
				end
				hex.each{|e| @ent.erase_entities(e)}
			end
			ctb=half/Math.tan(ang); r2r=c2c=ctb*2.0+@GW;
			ctr=face.bounds.center;diag=face.bounds.diagonal*1.2
			nx=(diag/c2c).ceil;ny=(diag/r2r).ceil;
			pt0=ctr.offset(@v1,-(c2c*(nx/2))).offset(@v2,-(r2r*(ny/2)))
			tg=@ent.add_group;tge=tg.entities;tgt=tg.transformation
			p0=pt0.clone; cnt=0; max=nx*ny; md=1e9;
			for j in 0..ny
				 for i in 0..nx 
					cnt += 1; self.progress_bar(cnt,max,"Hexagon Grid")
					tge.add_instance(cmp,Geom::Transformation.axes(p0,@v1,@v2,@norm))
					(d=@cor.distance(p0);(cpt=p0.clone;md=d) if md>d) if @spt=="Corner" && j>0
					p0.offset!(@v1,c2c);
				 end 
				 p0=pt0.offset(@v2,r2r); pt0.offset!(@v2,r2r);
			end
			(tr = Geom::Transformation.new(cpt.vector_to(@cor)); 
			tge.transform_entities(tr,tge.to_a )) if @spt=="Corner"
			@egrp=@ent.add_group;@ege=@egrp.entities;@egt=@egrp.transformation
			Sketchup::set_status_text "Intersecting Grid and Face"
			tge.intersect_with true,tgt,@ege,@egt,false,face
			tg.erase! unless $sdm_debug;
		end
#
#######################################################
#		Create Irregular Polygon Pattern on selected face
#######################################################
#
		def irregular_polygons(face)
			require File.dirname(__FILE__)+'/delauney3.rb'
			require File.dirname(__FILE__)+'/VoronoiXYZ.rb';#Thanks to MattC
			ctr = face.bounds.center; diag = face.bounds.diagonal*1.2
			org = ctr.offset(@v1,-diag/2).offset(@v2,-diag/2)
			max=[(face.area/144*@ipd).floor,20].max;
			@sel.clear; nrm=face.normal; min=diag/max*2
			@rds>0 ? srand(@rds) : srand; pts = []; new_faces = []
			while max > 0
				x=diag*rand;y=diag*rand
				p=org.offset(@v1,x).offset(@v2,y)
				if face.classify_point(p)==1
					if self.proximity(pts,p,min) > min
						@sel.add @ent.add_cpoint(p);max -= 1
						pts << p
					end
				end
			end
			face.vertices.each{|v|@sel.add @ent.add_cpoint(v.position)}
			vgrp=MattC::VoronoiXYZ.voronoi(); 
			vgt=vgrp.transformation; 
			cgrp=@ent.add_group;cge=cgrp.entities;cgt=cgrp.transformation
			vgrp.entities.grep(Sketchup::Edge).each{|e|
				p1 = e.start.position.transform vgt; 
				p2 = e.end.position.transform vgt
				cge.add_face(makeaface(p1,p2,nrm))
			}
			@egrp=@ent.add_group;@ege=@egrp.entities;@egt=@egrp.transformation
			cge.intersect_with true,cgt,@ege,@egt,false,face
			vgrp.erase!; cgrp.erase!; @ent.erase_entities(@sel)
		end
		
		def proximity(old,new,min)
			prox = 1e6
			for o in old
				prox = [o.distance(new),prox].min
				break if prox < min
			end
			return prox
		end
#
#######################################################
#		Create Wedge Pattern on selected face
#######################################################
#
		def wedge(face,dx,dy)
			cid="Wedge-#{dx.to_l}x#{dy.to_l}"
			cmp=@mod.definitions[cid]
			unless cmp
				cmp=@mod.definitions.add(cid);cde=cmp.entities
				p0=Geom::Point3d.new(); v1=[1,0,0];v2=[0,1,0];norm=[0,0,1]
				p1=p0.offset(v1,-dx/2).offset(v2,dy/4);cde.add_face(self.makeaface(p0,p1,norm))
p2=p1.offset(v2,dy/2);cde.add_face(self.makeaface(p1,p2,norm))
				p3=p2.offset(v2,dy/4).offset(v1,dx/2);cde.add_face(self.makeaface(p2,p3,norm))
				p4=p3.offset(v1,dx/2).offset(v2,-dy/4);cde.add_face(self.makeaface(p3,p4,norm))
				p5=p4.offset(v2,-dy/2);cde.add_face(self.makeaface(p4,p5,norm))
				cde.add_face(self.makeaface(p5,p0,norm))
			end
			diag=face.bounds.diagonal*1.2;ctr=face.bounds.center
			nx=[(diag/dx).ceil,5].max;ny=[(diag/dy).ceil,5].max
			org=ctr.offset(@v1,-(dx*(nx/2))).offset(@v2,-(dy*(ny/2)));
			tg=@ent.add_group; tge=tg.entities; tgt=tg.transformation
			cnt=0; max=nx*ny; md=1e9; p0=org.clone
			for i in 0..ny
				pt=p0.offset(@v2,dy*0.75*i)
				pt.offset!(@v1,dx/2) if i%2==1
				for j in 0..nx
					cnt += 1; self.progress_bar(cnt,max,"Wedge Grid")
					(d=@cor.distance(pt);(cpt=pt.clone;md=d) if md>d) if @spt=="Corner" && j>0
					tge.add_instance(cmp,Geom::Transformation.axes(pt,@v1,@v2,@norm))
					pt.offset!(@v1,dx)
				end
			end
			(tr = Geom::Transformation.new(cpt.vector_to(@cor)); 
			tge.transform_entities(tr,tge.to_a )) if @spt=="Corner"
			@egrp=@ent.add_group;@ege=@egrp.entities;@egt=@egrp.transformation
			Sketchup::set_status_text "Intersecting Grid and Face"
			tge.intersect_with true,tgt,@ege,@egt,false,face
			tg.erase! unless $sdm_debug;
		end
#
#######################################################
#		Create I_Block Pattern on selected face
#######################################################
#
		def i_block(face,dx,dy)
			cid="I_Block-#{@GX}x#{@GY}"
			cpd=@mod.definitions[cid]
			unless cpd
				cpd=@mod.definitions.add(cid);cde=cpd.entities
				p0=[0,0,0];v1=[-1,0,0];v2=[0,1,0]; v3=[0,0,1];
				d1=dx*0.1875;d2=dx*0.125;d3=dx-((d1+d2)*2);dy=[dy,(d2+@GW)*2].max
				p1=p0.offset(v1,d1);cde.add_face(self.makeaface(p0,p1,v3));p0=p1
				p1=p0.offset(v1,d2).offset(v2,d2);cde.add_face(self.makeaface(p0,p1,v3));p0=p1
				p1=p0.offset(v1,d3);cde.add_face(self.makeaface(p0,p1,v3));p0=p1
				p1=p0.offset(v1,d2).offset(v2,-d2);cde.add_face(self.makeaface(p0,p1,v3));p0=p1
				p1=p0.offset(v1,d1);cde.add_face(self.makeaface(p0,p1,v3));p0=p1
				p1=p0.offset(v2,dy);cde.add_face(self.makeaface(p0,p1,v3));p0=p1
			end
			diag=face.bounds.diagonal*1.2; ctr=face.bounds.center
			nx=(diag/dx).ceil;dy-=dx*0.125;ny=(diag/dy).ceil
			org=ctr.offset(@v1,-(dx*(nx/2))).offset(@v2,-(dy*(ny/2)))
			tg=@ent.add_group; tge=tg.entities; tgt=tg.transformation
			cnt=0; max=nx*ny; md=1e9
			for i in 0..ny
				p0=org.offset(@v2,dy*i);p0.offset!(@v1,dx/2.0) if i%2==1
				for j in 0..nx
					cnt += 1; self.progress_bar(cnt,max,"I_Block Grid")
					(d=@cor.distance(p0);(cpt=p0.clone;md=d) if md>d) if @spt=="Corner" && j>0
					tge.add_instance(cpd,Geom::Transformation.axes(p0,@v1,@v2,@norm))
					p0.offset!(@v1,dx)
				end
			end
			(tr = Geom::Transformation.new(cpt.vector_to(@cor)); 
			tge.transform_entities(tr,tge.to_a )) if @spt=="Corner"
			@egrp=@ent.add_group;@ege=@egrp.entities;@egt=@egrp.transformation
			Sketchup::set_status_text "Intersecting Grid and Face"
			tge.intersect_with true,tgt,@ege,@egt,false,face
			tg.erase! unless $sdm_debug;
		end
#
########################################################
#	Common sub-routines
########################################################
#	
		def paint_it(f)
			if @app=="Current"
				f.material = @mat		
				f.material.texture.size = @txs if f.material && f.material.texture && @txs && @txs != 0
				self.ate(f)
			elsif @app=="Rand_Clr"
				name = @colors[rand(@colors.length)]
				unless @mod.materials[name]
					mat = @mod.materials.add(name) 
					mat.color = name
				end
				f.material = @mod.materials[name]
			elsif @app=="Rand_Tex"
				i=rand(@textures.length);name = @textures[i]
				f.material = @mod.materials[name]
				self.ate(f)
			end
		end
		
		def ate(f) #Align Texture to Edge
			if @ate=="Yes" && f.material && f.material.texture
				case @@opt
					when "Tweed","BsktWv","IrPoly"
						l=n=0;
						f.outer_loop.edges.each_with_index{|e,i| d=e.length;(n=i;l=d) if d>l}
						vector = f.edges[n].line[1]	# Align to longest bounding edge
					when "HpScth1","HpScth2","HpScth4"
						n=0; @GX>=@GY ? vector=@v1 : vector=@v2;
					when 'HpScth3',"Hbone"
						edges=f.outer_loop.edges
						j=edges.length-1;l=d=0
						for i in 0..j
							d+=edges[i].length;
							unless edges[i].line[1].parallel?(edges[i-j].line[1])
								(l=d;n=i;d=0)if l<d
							end
						end
						vector=edges[n].line[1]
					else
						n=0;vector = @v1	# Align to longest face edge
				end
				return unless f.normal.perpendicular? vector		# Skip if vector isn't in the plane of the face
				achorPoint = f.edges[n].line[0]					# Define point to rotate around
				textureWidth = f.material.texture.width
				vector.length = textureWidth					# Change vector's length to materials width
				points = [achorPoint, [0,0,0], [achorPoint[0]+vector[0],achorPoint[1]+vector[1],achorPoint[2]+vector[2]], [1,0,0]]	# Reposition material
				f.position_material(f.material, points, true)
			end
		end
		
		def wig(f)#Random Texture Translation
			if f.material && f.material.texture
				tw = Sketchup.create_texture_writer	# Create uv helper to get current material position
				uvh = f.get_UVHelper true, false, tw; pointPairs = []; #puts "rtt"
				vector = f.edges[0].line[1]	# Get a vector in the face's plane
				vector.length = rand(f.material.texture.height+f.material.texture.width)*@rti	# Set vector length
				trans = Geom::Transformation.rotation f.outer_loop.vertices[0].position, f.normal, rand(360).degrees	# Rotate vector randomly in plane
				vector.transform! trans; trans = Geom::Transformation.translation vector		# Create translation, move point by vector
				(0..1).each do |j|									# Loop some points around face
					point3d = f.outer_loop.vertices[j].position		# Select a 3d point
					point3dRotated = point3d.transform(trans)		# Move 3d point
					pointPairs << point3dRotated					# Save model's 3d point to array
					point2d = uvh.get_front_UVQ(point3d)
					pointPairs << point2d							# Save material's corresponding 2d point to array
				end#each
				f.position_material(f.material, pointPairs, true)	#Set material position (pair up model 3d points with texture 2d point)
			end
		end
		
		def wag(f)#Random Texture Rotation
			if f.material && f.material.texture
				tw = Sketchup.create_texture_writer					# Create uv helper to get current material position
				uvh = f.get_UVHelper true, false, tw;
				@rtr=="Rand" ? angle=rand(360) : (angle = @rtr.to_i; incs = 360/angle; angle*=rand(incs))
				trans = Geom::Transformation.rotation f.outer_loop.vertices[0].position, f.normal, angle.degrees	#Define rotation
				pointPairs = []; #puts "rtr angle=#{angle}"
				(0..1).each do |j|									# Loop some points around face
					point3d = f.outer_loop.vertices[j].position		# Selet a 3d point
					point3dRotated = point3d.transform(trans)		# Rotate 3d pont
					pointPairs << point3dRotated					# Save model's 3d point to array
					point2d = uvh.get_front_UVQ(point3d)
					pointPairs << point2d							# Save material's corresponding 2d point to array
				end#each
				f.position_material(f.material, pointPairs, true)	#Set material position (pair up model 3d points with texture 2d point)
			end
		end
		
		def wob(g,d)#Random Face Rotation
			i = rand(2); axis = [@v1,@v2][i];
			while d<@rin || d>@rix
				d = rand*@GD
			end
			case @@opt
				when "Brick","Tile","Wood"
					angle=Math.atan(d/[@GY,@GX][i])*(rand<=>0.5)
				else
					angle=Math.atan(d/(([[g.bounds.height,g.bounds.depth].max,g.bounds.width].max)/2))*(rand<=>0.5)
			end
			tr=Geom::Transformation.rotation(g.bounds.center,axis,angle)
			g.transform! tr
		end
		
		def bev(f,d)#Add Bevel to Face Edge
			p=self.g_offset(f,d)
			if p
				b=f.parent.entities.add_face(p)
				v=b.normal;v.length=d
				tr=Geom::Transformation.translation(v)
f.parent.entities.transform_entities(tr,b)
			end
		end
		
		def edge_to_close(f,p)
			return true if p[0].distance(p[1]) <= @GW
			for loop in f.loops
				loop.edges.each{|e| 
					if e.line[1].parallel?(p[0].vector_to(p[1]))
						for i in 0..1
							pp=p[i].project_to_line(e.line)
							if e.bounds.contains?(pp)
								if p[i].distance(pp) <= @GW
									return true
								end
							end
						end
					end
				}
			end
			return false
		end
	
		def g_offset(face,dist)
			return nil unless (dist.class==Fixnum || dist.class==Float || dist.class==Length)
			return nil if (@@opt != "I_Block" && !self.ctr_to_edge(face));
			@c_pts=face.outer_loop.vertices.collect{|v|v.position};
			unless dist==0
				edges=face.outer_loop.edges;last=edges.length-1
				0.upto(last) do |i|
					unless edges[i].length > @GW
						if edges[i].line[1].perpendicular?(edges[i-1].line[1])
							if edges[i].line[1].perpendicular?(edges[i-last].line[1])
								@c_pts -= [edges[i].start,edges[i].end]; #remove short edge between square corners
							end
						end
					end
				end
				last = @c_pts.length-1;@o_pts = []
				0.upto(last) do |a|
					vec1 = (@c_pts[a]-@c_pts[a-last]).normalize
					vec2 = (@c_pts[a]-@c_pts[a-1]).normalize
					if vec1.parallel? vec2
						ctr = face.bounds.center; 
						poe = ctr.project_to_line([@c_pts[a],vec1])
						vec3 = poe.vector_to(ctr); ang = 90.degrees
					else
						vec3=(vec1+vec2).normalize
						ang = vec1.angle_between(vec2)/2;
					end
					if vec3.valid?
						vec3.length = -dist/Math::sin(ang);
						t = Geom::Transformation.new(vec3)
						if face.classify_point(@c_pts[a].transform(t))==16
							t = Geom::Transformation.new(vec3.reverse);
						end
						@o_pts << @c_pts[a].transform(t)
					end
				end
				(@o_pts.length > 2) ? (return(@o_pts)) : (return nil)			
			else
				return nil
			end
			
		end
		
		def progress_bar(cnt,max,opt)
			pct = (cnt*100)/max; pct=[pct,100].min; @pb = "|"*pct
			Sketchup::set_status_text(@pb + " #{pct}% of #{opt} done.")
		end
	
		def makeaface(p1,p2,v)
			pts=[];
			pts<<p1.offset(v)
			pts<<p2.offset(v)
			pts<<p2.offset(v.reverse)
			pts<<p1.offset(v.reverse)
		end
		
		def ctr_to_edge(f)
			edges=f.edges; c=self.calc_centroid(f);
			edges.each{|e| return false if c.distance_to_line(e.line) <= @HW}
			return true
		end
		
		def calc_centroid(f)
			tx=0.0;ty=0.0;tz=0.0;
			p=f.outer_loop.vertices.collect{|v|v.position}
			p.each{|v| tx+=v.x;ty+=v.y;tz+=v.z}
			ax=tx/p.length;ay=ty/p.length;az=tz/p.length
			c=Geom::Point3d.new(ax,ay,az);#ent.add_cpoint(c)
			area = 0.0;cx = 0.0;cy = 0.0;cz = 0.0;
			for i in 0...p.length
				areat = (p[i].distance(p[i-1])*(c.distance_to_line([p[i],p[i].vector_to(p[i-1])])))/2.0
				area = area + areat;
				cx = cx + areat * ( p[i].x + p[i-1].x + c.x ) / 3.0;
				cy = cy + areat * ( p[i].y + p[i-1].y + c.y ) / 3.0;
				cz = cz + areat * ( p[i].z + p[i-1].z + c.z ) / 3.0;
			end
			cx = cx / area;cy = cy / area;cz = cz / area;
			Geom::Point3d.new(cx,cy,cz)
		end
		
	end
	
end
delauney3.rb
# Credit to Paul Bourke (pbourke@swin.edu.au) for original Fortran 77 Program :))
# August 2004 - Conversion and adaptation to Ruby by Carlos Fale (carlosfale@sapo.pt)
# September 2004 - Updated by Carlos Fale
#
# You can use this code, for non commercial purposes, however you like, providing the above credits remain in tact
# Return two logical values, first is TRUE if the point (xp, yp) lies inside the circumcircle made up by points (x1, y1), (x2, y2) and (x3, y3)
# and FALSE if not, second is TRUE if xc + r < xp and FALSE if not
# NOTE: A point on the edge is inside the circumcircle
###
### TIG made as delauney3 with class to avoid clashes
### otherwise as PBourke's (c)
###
class Delauney3
	def Delauney3::incircum(xp, yp, x1, y1, x2, y2, x3, y3)
		eps = 0.000001
		res = [FALSE, FALSE]
		if (y1 - y2).abs >= eps || (y2 - y3).abs >= eps
			if (y2 - y1).abs < eps
				m2 = -(x3 - x2) / (y3 - y2)
				mx2 = (x2 + x3) / 2
				my2 = (y2 + y3) / 2
				xc = (x1 + x2) / 2
				yc = m2 * (xc - mx2) + my2
			elsif (y3 - y2).abs < eps
				m1 = -(x2 - x1) / (y2 - y1)
				mx1 = (x1 + x2) / 2
				my1 = (y1 + y2) / 2
				xc = (x2 + x3) / 2
				yc = m1 * (xc - mx1) + my1
			else
				m1 = -(x2 - x1) / (y2 - y1)
				m2 = -(x3 - x2) / (y3 - y2)
				mx1 = (x1 + x2) / 2
				mx2 = (x2 + x3) / 2
				my1 = (y1 + y2) / 2
				my2 = (y2 + y3) / 2
				if (m1 - m2) == 0
					xc = (x1 + x2 + x3) / 3
					yc = (y1 + y2 + y3) / 3
				else
					xc = (m1 * mx1 - m2 * mx2 + my2 - my1) / (m1 - m2)
					yc = m1 * (xc - mx1) + my1
				end
			end
			dx = x2 - xc
			dy = y2 - yc
			rsqr = dx * dx + dy * dy
			r = Math.sqrt(rsqr)
			dx = xp - xc
			dy = yp - yc
			drsqr = dx * dx + dy * dy
			if drsqr < rsqr
				res[0] = TRUE
			end
			
			if xc + r < xp
				res[1] = TRUE
			end
		end
		return res
	end
	# Takes as input a array with NVERT lines, each line is a array with three values x, y, and z (vertex[j][0] = x value of j + 1 component) and
	# return a array with NTRI lines, each line is a array with three values i, j, and k (each value is the index of a point in the input array (vertex array))
	# i is the index of the first point, j is the index of the second point and k is the index of the third point,
	def Delauney3::triangulate(vert)
		# Sort the input array in x values
		vert.sort!
		
		nvert = vert.length
		triang = Array.new
		edges = Array.new
		complete = Array.new
		# Verbose
		Sketchup.set_status_text("Starting triangulation of " + nvert.to_s + " Points")
		# Find the minimum and maximum vertex bounds. This is to allow calculation of the bounding triagle
		xmin = vert[0][0]
		ymin = vert[0][1]
		xmax = xmin
		ymax = ymin
		for i in (2..nvert)
			x1 = vert[i - 1][0]
			y1 = vert[i - 1][1]
			xmin = [x1, xmin].min
			xmax = [x1, xmax].max
			ymin = [y1, ymin].min
			ymax = [y1, ymax].max
		end
		dx = xmax - xmin
		dy = ymax - ymin
		dmax = [dx, dy].max
		xmid = (xmin + xmax) / 2
		ymid = (ymin + ymax) / 2
		# Set up the supertriangle. This is a triangle which encompasses all the sample points. The supertriangle coordinates are added to the end
		# of the vertex list. The supertriangle is the first triangle in the triangles list.
		p1 = nvert + 1
		p2 = nvert + 2
		p3 = nvert + 3
		vert[p1 - 1] = [xmid - 2 * dmax, ymid - dmax, 0]
		vert[p2 - 1] = [xmid, ymid + 2 * dmax, 0]
		vert[p3 - 1] = [xmid + 2 * dmax, ymid - dmax, 0]
		triang[0] = [p1 - 1, p2 - 1, p3 - 1]
		complete[0] = FALSE
		ntri = 1
		# Include each point one at a time into the exixsting mesh
		for i in (1..nvert)
			xp = vert[i - 1][0]
			yp = vert[i - 1][1]
			nedge = 0
			
		# Verbose 
		Sketchup.set_status_text("Triangulating point " + i.to_s + " / " + nvert.to_s )
		
			# Set up the edge buffer. If the point (xp, yp) lies inside the circumcircle then the three edges of that triangle are added to the edge buffer.
			j = 0
			while j < ntri
				j = j +1
				if complete[j - 1] != TRUE
					p1 = triang[j - 1][0]
					p2 = triang[j - 1][1]
					p3 = triang[j - 1][2]
					x1 = vert[p1][0]
					y1 = vert[p1][1]
					x2 = vert[p2][0]
					y2 = vert[p2][1]
					x3 = vert[p3][0]
					y3 = vert[p3][1]
					inc = Delauney3::incircum(xp, yp, x1, y1, x2, y2, x3, y3)
					if inc[1] == TRUE
						complete[j - 1] = TRUE
					else
						if inc[0] == TRUE
							edges[nedge] = [p1, p2]
							edges[nedge + 1] = [p2, p3]
							edges[nedge + 2] = [p3, p1]
							nedge = nedge + 3
							triang[j - 1] = triang[ntri - 1]
							complete[j - 1] = complete[ntri - 1]
							j = j - 1
							ntri = ntri - 1
						end
					end
				end
			end
			# Tag multiple edges
			# NOTE: if all triangles are specified anticlockwise then all interior edges are pointing in direction.
			for j in (1..nedge - 1)
				if edges[j - 1][0]
!= -1 || edges[j - 1][1] != -1
					for k in ((j + 1)..nedge)
						if edges[k - 1][0] != -1 || edges[k - 1][1] != -1
							if edges[j - 1][0] == edges[k - 1][1]
								if edges[j - 1][1] == edges[k - 1][0]
									edges[j - 1] = [-1, -1]
									edges[k - 1] = [-1, -1]
								end
							end
						end
					end
				end
			end
			# Form new triangles for the current point. Skipping over any tagged adges. All edges are arranged in clockwise order.
			for j in (1..nedge)
				if edges[j - 1][0] != -1 || edges[j - 1][1] != -1
					ntri = ntri + 1
					triang[ntri - 1] = [edges[j - 1][0], edges[j - 1][1], i - 1]
					complete[ntri - 1] = FALSE
				end
			end
		end
		# Remove triangles with supertriangle vertices. These are triangles which have a vertex number greater than NVERT.
		i = 0
		while i < ntri
			i = i + 1
			if triang[i - 1][0] > nvert - 1 || triang[i - 1][1] > nvert - 1 || triang[i - 1][2] > nvert - 1
				triang[i - 1] = triang[ntri - 1]
				i = i - 1
				ntri = ntri - 1
			end
		end
		
	# Verbose
	Sketchup.set_status_text("Triangulation Completed: " + ntri.to_s + " Triangles Created.")
		return triang[0..ntri - 1]
	end
end#class
VoronoiXYZ.rb
# Modified by sdmitch for irregular polygon creation in FloorGenerator
require File.dirname(__FILE__)+'/delauney3.rb'
module MattC
	module VoronoiXYZ
		def self.voronoi()
			@mod = Sketchup.active_model
			@ent = @mod.active_entities
			@sel = @mod.selection
			###
			points_table = []
			points_table = self.points_to_array()
			###
			triangles = []
			if points_table[0]
				triangles = Delauney3::triangulate(points_table)
			else
				puts "No triangles were created."
				return nil
			end
			### group for tri's output
			point_groups=[]
			for i in 0..points_table.length-1
				point_groups[i]=[]
				triangles.each do |tri|
					if tri.include? i
						point_groups[i]<<tri
					end
				end
			end
			point_groups.each do |pg|
				pg.flatten!
				pg.uniq!
			end
			vgrp = @ent.add_group()
			grent=vgrp.entities
			conhull=[]
			qhull(@cpts).each do |p|
				for i in 0..points_table.length-1
					if p.position==points_table[i]
						conhull<<i
					end
				end
			end
			for i in 0..points_table.length-1
				connpoints=point_groups[i]
				if conhull.include?(i)
					j=conhull.index(i)
					if j == 0
						connpoints<<conhull[1]
						connpoints<<conhull[conhull.length-1]				
					else
						if j == conhull.length-1
							connpoints<<conhull[j-1]
							connpoints<<conhull[0]
						else
							connpoints<<conhull[j-1]
							connpoints<<conhull[j+1]
						end
					end
				end
				connpoints.uniq!
				connpoints.delete(i)
				sorted=sortradial(connpoints,i,points_table)
				cellpoints=voropoints(i,sorted,points_table,conhull)
				cellpoints=removedupilcates(cellpoints)
				if cellpoints.length>2
					grent.add_face(cellpoints)
				end
			end
			##### return everthing to original plane
			@ent.transform_entities(@trans.inverse,@cpts)
			vgrp.transform! @trans.inverse
			#####
		end#def
			
		def self.points_to_array()
			##### put selected ConstructionPoints on the XY plane
			@cpts = @sel.grep(Sketchup::ConstructionPoint)
			@bb = Geom::BoundingBox.new; @bb.add @cpts.map{|cp|cp.position};
			px,py,pz = plane = Geom.fit_plane_to_points(@cpts.map{|cp|cp.position})
			@cpts.each{|cp|
				pp = cp.position.project_to_plane(plane)
				vec = cp.position.vector_to(pp)
				@ent.transform_entities(Geom::Transformation.new(vec),cp)
			}
			x_axis = Geom::Vector3d.new(px,py,pz).axes[0]
			ang = Math.acos(pz); @max_length = @bb.diagonal/4
			@trans = Geom::Transformation.new(ORIGIN,x_axis,-ang)
			@ent.transform_entities(@trans,@cpts)
			#####
			points_array = [] 
			@cpts.each{|cpt| ### TIG'd
				x = cpt.position.x.to_f
				y = cpt.position.y.to_f
				z = cpt.position.z.to_f
				points_array << [x, y ,z]
			}
			points_array.uniq!
			return points_array
		end #of def
		def self.removedupilcates(points)
			uniqpoints=[]; temp=[]
			n=points.length
			for i in 0..n-1
				for j in i+1..n-1
					if points[i]==points[j] || points[i].distance(points[j]) > @max_length
						temp<<points[j]
					end
				end
			end
			uniqpoints=points-temp
			uniqpoints
		end
		
		def self.qhull(points)
			vector=Geom::Vector3d.new 1,0,0 
			pminy=[points[0]]
			for i in 1..points.length-1
				if points[i].position.y < pminy.last.position.y
					pminy<<points[i]
				end
			end
			vertices=[pminy.last]
			temp=[]
			angle=180.degrees
			for i in 0..points.length-1
				if (vertices.last.position!=points[i].position)&&(vector.angle_between(vertices.last.position.vector_to(points[i].position)) < angle)
					temp<<points[i]
					angle = vector.angle_between(vertices.last.position.vector_to(points[i].position))
				end
			end
			vertices<<temp.last
			angle=180.degrees
			for k in 1..points.length-1
				vector=vertices[vertices.length-2].position.vector_to(vertices.last.position)
				for i in 0..points.length-1
					if (vertices.last.position!=points[i].position)&&(vector.angle_between(vertices.last.position.vector_to(points[i].position))<angle)
						temp<<points[i]
						angle = vector.angle_between(vertices.last.position.vector_to(points[i].position))
					end
				end
				vertices<<temp.last
				angle=vector.angle_between(vertices[vertices.length-2].position.vector_to(vertices.last.position))+180.degrees
				if vertices.first==vertices.last
					break
				end	
			end
			vertices.delete_at(vertices.length-1)
			vertices
		end
		
		def self.sortradial(pointsind,bpointindex,pointstable)
			angles=[]; sortedp=[]
			vec=Geom::Vector3d.new(1,0,0) 
			pointsind.each do |p|
				if vec.cross(pointstable[bpointindex].vector_to(pointstable[p])).z>=0
					angles<<vec.angle_between(pointstable[bpointindex].vector_to(pointstable[p]))
				else
					angles<<360.degrees-vec.angle_between(pointstable[bpointindex].vector_to(pointstable[p]))
				end
			end
			angles.sort!
			for i in 0..angles.length-1
				for j in 0..pointsind.length-1
					if vec.cross(pointstable[bpointindex].vector_to(pointstable[pointsind[j]])).z>=0
						if vec.angle_between(pointstable[bpointindex].vector_to(pointstable[pointsind[j]]))==angles[i]
							sortedp<<pointsind[j]
						break
						end
					else
						if 360.degrees-vec.angle_between(pointstable[bpointindex].vector_to(pointstable[pointsind[j]]))==angles[i]
							sortedp<<pointsind[j]
						break
						end
					end
				end
			end
			sortedp
		end
		def self.voropoints(bpntindx,sorpntindx,pointstable,conhulindx)
			polygon=[]
			conhulindx.each do |i|
				polygon<<pointstable[i]
			end
			points=[]
			vec=Geom::Vector3d.new(0,0,1) 
			for i in 0..sorpntindx.length-1
				if i<sorpntindx.length-1
					j=i+1
				else
					j=0
				end
				test=[]
				if (conhulindx.include? bpntindx)
					test<<0
				else
					test<<1
				end
				if (conhulindx.include? sorpntindx[i])
					test<<0
				else
					test<<1
				end
				if (conhulindx.include? sorpntindx[j])
					test<<0
				else	
					test<<1
				end
				linevector=[pointstable[bpntindx].vector_to(pointstable[sorpntindx[i]]),pointstable[bpntindx].vector_to(pointstable[sorpntindx[j]])]
				midpoints=[Geom.linear_combination(0.5,pointstable[bpntindx],0.5,pointstable[sorpntindx[i]]),Geom.linear_combination(0.5,pointstable[bpntindx],0.5,pointstable[sorpntindx[j]])]
				midlines=[[midpoints[0],vec.cross(linevector[0])],[midpoints[1],vec.cross(linevector[1])]]
				int=Geom.intersect_line_line([midlines[0][0],midlines[0][1]], [midlines[1][0],midlines[1][1]])
				if (test[0]==0)&&(test[1]==0)&&(test[2]==0)
					intprim=int+int.vector_to(pointstable[bpntindx])+int.vector_to(pointstable[bpntindx])
					points<<intprim.project_to_line([midlines[0][0],midlines[0][1]])
					points<<intprim
					points<<intprim.project_to_line([midlines[1][0],midlines[1][1]])
				else
points<<int
				end
			end
			adjpoints=[]
			for i in 0..points.length-1
				if i==points.length-1
					j=0
				else
					j=i+1
				end
				if Geom.point_in_polygon_2D(points[i], polygon, true)
					adjpoints<<points[i]
					if Geom.point_in_polygon_2D(points[j], polygon, true)==false
						adjpoints<<Geom::Point3d.new(intersect_p_p_ps(points[i],points[j],polygon))
						if Geom.point_in_polygon_2D(pointstable[bpntindx], polygon, false)==false
							adjpoints<<Geom::Point3d.new(pointstable[bpntindx])
						end
					end
				else
					if Geom.point_in_polygon_2D(points[j], polygon, true)
						adjpoints<<Geom::Point3d.new(intersect_p_p_ps(points[i],points[j],polygon))
					end
				end
			end
			if adjpoints.length==0
				temp=intersections_ps_ps(points,polygon)
				if temp.length==2
					adjpoints<<Geom::Point3d.new(temp[0])
					adjpoints<<Geom::Point3d.new(temp[1])
					adjpoints<<Geom::Point3d.new(pointstable[bpntindx])
				end
			end
			adjpoints.reject! { |c| c.nil? }
			adjpoints
		end
		
		def self.intersect_p_p_ps(p1,p2,polygon)
			point=[]
			p1p2line=[p1,p1.vector_to(p2)]
			for i in 0..polygon.length-1
				if i==polygon.length-1
					j=0
				else
					j=i+1
				end
				ijline=[polygon[i],polygon[i].vector_to(polygon[j])]
				int=Geom.intersect_line_line(p1p2line, ijline)
				if (int)&&(point_is_between(p1,p2,int)&&point_is_between(polygon[i],polygon[j],int))
					point<<int
					break
				end
			end
			point[0]
		end
		
		def self.intersections_p_p_ps(p1,p2,polygon)
			point=[]
			p1p2line=[p1,p1.vector_to(p2)]
			for i in 0..polygon.length-1
				if i==polygon.length-1
					j=0
				else
					j=i+1
				end
				ijline=[polygon[i],polygon[i].vector_to(polygon[j])]
				int=Geom.intersect_line_line(p1p2line, ijline)
				if point_is_between(p1,p2,int)&&point_is_between(polygon[i],polygon[j],int)
					point<<int
				end
			end
			point
		end
		
		def self.intersections_ps_ps(points,polygon)
			point=[]
			for i in 0..polygon.length-1
				if i==polygon.length-1
					j=0
				else
					j=i+1
				end
				ijline=[polygon[i],polygon[i].vector_to(polygon[j])]
				for k in 0..points.length-1
					if k==points.length-1
						l=0
					else
						l=k+1
					end
					klline=[points[k],points[k].vector_to(points[l])]
					int=Geom.intersect_line_line(klline, ijline)
					if (int!=nil)&&(point_is_between(points[k],points[l],int))&&(point_is_between(polygon[i],polygon[j],int))
						point<<int
					end
				end
			end
			point.reject! { |c| c.nil? }
			point
		end
		
		def self.point_is_between(p1,p2,pt)
			bb=Geom::BoundingBox.new;bb.add p1,p2
			bb.contains?(pt)
		end	
	end#VoronoiXYZ
	
end
FG_Icons/Brick.jpg
FG_Icons/BsktWv.jpg
FG_Icons/Clapboard.jpg
FG_Icons/diamonds.jpg
FG_Icons/Hbone.jpg
FG_Icons/Hexgon.jpg
FG_Icons/HpScth1.jpg
FG_Icons/HpScth2.jpg
FG_Icons/HpScth3.jpg
FG_Icons/HpScth4.jpg
FG_Icons/I_Block.jpg
FG_Icons/IrPoly.jpg
FG_Icons/Octgon.jpg
FG_Icons/Tile.jpg
FG_Icons/Tweed.jpg
FG_Icons/Wedge.jpg
FG_Icons/Wood.jpg
FlrGenReset.rb
module SDM
	def flrgenreset
		patterns=["Brick","Tile","Wood","Tweed","Hbone","BsktWv","HpScth1","HpScth2","Rand_Tex","HpScth3","HpScth4","IrPoly","Hexgon","Octgon","Wedge","I_Block","Diamonds","Clapbrd"]
		patterns.each{|o| Sketchup.write_default("FloorGenerator",o,nil)};
		Sketchup.write_default("FloorGenerator","","Tile");
	end
end

Teste o Premium para desbloquear

Aproveite todos os benefícios por 3 dias sem pagar! 😉
Já tem cadastro?

Mais conteúdos dessa disciplina