Parametric.rb


#1

Goodmorning everyone.

I use the script parametric.rb in some of my scripts and I find it difficult to save the data for the selected face on which I perform the operations provided by my script so that it can be accessed again during edit mode.
I thank the help in advance.

Greetings

Tiziano Traini

# Copyright 2013, Trimble Navigation Limited

# Copyright 2018, By SOFTDEG di Traini Tiziano Certaldo (FI) ITALIA


# se usato in ambito professionale è gradita una donazione 
# PayPal : tiziano.traini@tin.it


# This software is provided as an example of using the Ruby interface
# to SketchUp.

# Permission to use, copy, modify, and distribute this software for 
# any purpose and without fee is hereby granted, provided that the above
# copyright notice appear in all copies.

# THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

#-----------------------------------------------------------------------------
# Name        :   SOFTDEG_Vetrate 1.1.0
# Description :   Un plugin per creare infissi civili parametrici.
# Menu Item   :   Tools->SOFTDEG_Vetrate
# Context Menu:   Edit SOFTDEG_Vetrate
# Usage       :   Rileva superficie e immetti le caratteristiche di una vetrata.
#             :   Per le modifiche successive tasto destro sulla vetrata e 
#             :   selezionare Edita SOFTDEG_Vetrata
#             :   
# Date        :   05/05/2018
# Type        :   Dialog Box
#-----------------------------------------------------------------------------
# Classes per creare ed editare vetrate parametriche

require 'sketchup.rb'
require 'SOFTDEG_vetrate/parametric.rb'


module SOFTDEG_Vetrate

class Vetrate < SOFTDEG_Vetrate::Parametric

#original offset by Rick Wilson
#Smustard
def offset_(face=nil, dist=0)
    return nil if not face or not face.valid?
	return nil if (not ((dist.class==Fixnum || dist.class==Float || dist.class==Length) && dist!=0))
    pi=Math::PI
	verts=face.outer_loop.vertices
	pts=[]
	
	0.upto(verts.length-1) do |i|
		vec1=(verts[i].position-verts[i-(verts.length-1)].position).normalize
		vec2=(verts[i].position-verts[i-1].position).normalize
		vec3=(vec1+vec2).normalize
		if vec3.valid?
			ang=vec1.angle_between(vec2)/2
			ang=pi/2 if vec1.parallel?(vec2)
			vec3.length=dist/Math::sin(ang)
			t=Geom::Transformation.new(vec3)
			if pts.length > 0
				if not (vec2.parallel?(pts.last.vector_to(verts[i].position.transform(t))))
					t=Geom::Transformation.new(vec3.reverse)
				end#if
			end#if
			pts.push(verts[i].position.transform(t))
		end#if
	end#upto
	face.parent.entities.add_face(pts) if pts[2]
  end#offset_

# Crea vetro doppio, singolo con spessore (thick_v) 0 oppure senza vetro con spessore (thick_v) negativo
def vetro(newFace,  width, thick, d_a, thick_v, container)
	
	frame = container.add_group
	group_container = frame.entities
	
	if thick_v == 0.mm
		thick_v=1.mm
		thick_vv=0.mm
	end
		
	da=d_a+(thick-thick_v)/2
	
	intFace=offset_(newFace,-width)
		
	telaio_i = intFace.outer_loop.vertices
	telaio_i = group_container.add_face(telaio_i)	
    
	if not telaio_i.normal.z == 1
		telaio_i.reverse!	
	end
	
	status = telaio_i.material = "vetro_01"
	status = telaio_i.back_material = "vetro_01"
	vetro1=telaio_i.pushpull((da+thick_v),true)	
		
	telaio_i.pushpull(da+(thick_v/2))
	
	@entities.erase_entities(telaio_i.outer_loop.edges,intFace.outer_loop.edges)
	
	intFace = offset_(newFace,-width)
		
	telaio_i = intFace.outer_loop.vertices
	telaio_i = group_container.add_face(telaio_i)	
	
	if not telaio_i.normal.z == 1
		telaio_i.reverse!	
	end
	
	status = telaio_i.material = "vetro_01"
	status = telaio_i.back_material = "vetro_01"
	
	if not thick_vv == 0.mm 
		vetro2 = telaio_i.pushpull(da,true)
		telaio_i.pushpull(da+(thick_v/2))
		@entities.erase_entities(telaio_i.outer_loop.edges,intFace.outer_loop.edges)
	else
		@entities.erase_entities(telaio_i, telaio_i.outer_loop.edges,intFace.outer_loop.edges)
	end
    
	newFace.erase!
	
	frame
end #def

# Crea telaio/anta/cornice mediante dimensioni e sfalsamento in asse e offset dalla faccia di partenza (foro muratura)
def anta(newFace1, d_o, d_a, width_a, thick_a, container)
	
	frame = container.add_group
	group_container = frame.entities
	
	newFacet = newFace1.outer_loop.vertices
	newFacet = container.add_face(newFacet)
	
	if  d_o == 0.mm
		newFace = newFace1
	else
		newFace = offset_(newFacet,d_o)
		newFacet.erase!
	end
		
	intFace = offset_(newFace,-width_a)
		
	telaio_e = newFace.outer_loop.vertices
	telaio_e = group_container.add_face(telaio_e)	
    
	telaio_i = intFace.outer_loop.vertices
	telaio_i = group_container.add_face(telaio_i)
	telaio_i.erase!
	
	status = telaio_e.material = "legno_01"
		
	if not telaio_e.normal.z == 1
		telaio_e.reverse!
	end
		
	anta1=telaio_e.pushpull((d_a+thick_a),true)

	if not telaio_e.normal.z == 1
		telaio_e.reverse!
	end 
		
	telaio_e.pushpull -d_a
		
	if not d_o == 0
		@entities.erase_entities(newFace.outer_loop.edges, intFace.outer_loop.edges)
	else
		@entities.erase_entities(intFace.outer_loop.edges)
		newFacet.erase!
	end
	
	frame
	
end #def



def create_entities(data, container)

	# imposta costanti
	anta_a=20.mm 	# Sfalsamento anta dal telaio
	thick_c=70.mm 	# Spessore Cornice
	thick_a=70.mm 	# Spessore Infisso Anta
	lista_t=10.mm	# Spessore lista interna
	lista_d_a=20.mm	# Sfalsamento lista dall'anta


	# Set values from input data
	a99 = data["a99"] # faccia di partenza
	a0 = data["a0"].to_l # Cornice esterna Larghezza
    a1 = data["a1"].to_l # Telaio infisso Larghezza
	a11= data["a11"].to_l # Lista rifinitura interna Larghezza
    a2 = data["a2"].to_l # Spessore Vetro
	a3 = data["a3"].to_l # Stecche oriz. Larghezza
	a4 = data["a4"].to_l # Stecche vert. Larghezza
	a5 = data["a5"].to_int # N Stecche orizzontali
	a6 = data["a6"].to_int # N Stecche verticali
	
	if a2 > (thick_c-20.mm)
		a2=(thick_c-20.mm).to_l
		data["a2"]=a2
	end
	
	
 	# Remember values for next use
	@@face = a99
	@@width_c = a0
	@@width_a = a1
	@@lista_w = a11
	@@thik_v = a2
	@@width_so = a3
	@@width_sv = a4
	@@ns_o = a5
	@@ns_v = a6
		
	

	
	# Inizio creazione vetrata

	model = Sketchup.active_model
    @entities = model.active_entities
    sel = model.selection
	
	# Definisce i due materiali utilizzati
	mats=model.materials
	if mats["legno_01"]==nil
		legno=mats.add("legno_01")
		legno.color="Brown"
	end#if
	if mats["vetro_01"]==nil
		vetro=mats.add("vetro_01")
		vetro.color="Gray"
		vetro.alpha=0.25
	end#if
	  
	
      
    if Sketchup.version_number < 7000000
        model.start_operation "Vetrate"
    else
        model.start_operation "Vetrate", true
    end
	  
	faces = sel.select{|e| e.typename == 'Face'}
	  
	#if not faces.length > 0
	  
	#end
	   
    model.start_operation("Crea Telaio")
    
	faces.each do |face|
	
	
		#crea gruppo della faccia originale
		tgroup=@entities.add_group
		tentities=tgroup.entities
		iface=face.outer_loop.vertices
		oface=tentities.add_face(iface)
		
		#crea telaio esterno
		newFace0=oface
		cornice_o=a0
		cornice_a=0.mm
		cornice=anta(newFace0,cornice_o,cornice_a, 2*a0, thick_c, container)
		
		#crea lista di finitura interna
		if a11 > 0
			newFace1=oface
			# ottimizza sfalsamento cornice finitura interna
			if a0 < lista_d_a
				lista_d_a=a0/2
			end
			
			lista_o=lista_d_a+a11
			lista=anta(newFace1, lista_o, thick_c, a11, lista_t, container)
					
		end

		#crea anta interna
		if a1 > 0
			newFace2=oface
			anta_o = 0.mm
			anta=anta(newFace2,anta_o, anta_a, a1, thick_a, container)
		else
			a1=a0
			anta_a=0
		end
			
		#crea vetro
		newFace3=oface
		if a2 >= 0.mm								
			vetro=vetro(newFace3, a1, thick_a, anta_a, a2, container)
		end
		
		face.erase!

		tgroup.erase!
				
    end
    model.commit_operation
    
end #end def

def default_parameters
		# Set starting defaults 
		if !defined? @@width_c  # then no previous values input
			defaults = {"a0" => 40.mm, "a1" => 80.mm, "a11" => 70.mm, "a2" => 30.mm, "a3" => 40.mm, "a4" => 40.mm, "a5" => 0, "a6" => 0 , "a99" => nil }
		else
			# Reuse last inputs as defaults
			defaults = {"a0" => @@width_c, "a1" => @@width_a, "a11" => @@lista_w, "a2" => @@thik_v, "a3" => @@width_so, "a4" => @@width_sv, "a5" => @@ns_o, "a6" => @@ns_v, "a99" => @@face  }
		end # if
end # default_parameters

def translate_key(key)
    prompt = key
    case( key )
        
        when "a0"	
			prompt = " Cornice esterna Larghezza "
		when "a1"
			prompt = " Telaio infisso Larghezza "
		when "a11"
			prompt = " Lista rifinitura interna Larghezza "
		when "a2"
            prompt = " Spessore Vetro "
		when "a3"
			prompt = " Stecche oriz. Larghezza "
		when "a4"
			prompt = " Stecche vert. Larghezza "
		when "a5"
			prompt = " N Stecche orizzontali "
		when "a6"
			prompt = " N Stecche verticali "	
		
    end
    prompt
end

end # Class Vetrate


#=============================================================================

if (not $Vetrate_menu_loaded)
   	
	### commands
    cmd1=UI::Command.new("SOFTDEG_Vetrate") { Vetrate.new } 
	cmd1.tooltip='Vetrate Irregolari Parametriche - donazione PayPal: tiziano.traini@tin.it'
    cmd1.status_bar_text='Vetrate Irregolari: Seleziona una faccia ...'
    cmd1.small_icon=File.join('SOFTDEG_vetrate', 'SOFTDEG_Vetrate_16x16.png')
    cmd1.large_icon=File.join('SOFTDEG_vetrate', 'SOFTDEG_Vetrate_24x24.png')
	###
    
	menu=UI.menu("Tools").add_item(cmd1) 
	toolbar=UI::Toolbar.new('SOFTDEG_Vetrate')
    toolbar.add_item(cmd1)
    toolbar.restore if toolbar.get_last_state.abs==1 #TB_VISIBLE/NEVER
	
	$Vetrate_menu_loaded = true
end	

end # module SOFTDEG_Vetrate


#2

Read …

… please edit your previous post.


Please also search this category for “parametric.rb” …

https://forums.sketchup.com/search?q=parametric.%20category%3A12


#3

Good evening,
I apologize for the incorrect formatting of the code …

I immediately try to check the discussion at the link that kindly signaled me …

I’m trying to adapt my parametric plug-ins a) windows, patio doors and doors, b) uneven splaying of the wall hole with threshold and niche underneath, even to non-quadrangular openings.

But I think I will need the help of the forum that I left in programming for almost 30 years (clipper and delphi) and it is not easy to open the mind to almost 50 years.

Greetings Tiziano Traini



#4

(1) Ruby uses 2 space indents, not 4.


(2) Your code blocks, classes and methods are not indented properly.


(3) faces = sel.select{|e| e.typename == 'Face'}
Do not use #typename, it is SLOW! … Use:

faces = sel.grep(Sketchup::Face)

Most SketchUp collection type classes have the Enumerable module mixed into them. (This is where the #grep method comes from.)


(4) Do not use global variables. Use @@menu_loaded ||= false at top of your extension module instead of a $Vetrate_menu_loaded global variable. Then set it true after the menus have been loaded.


(5) Use an outer company module and an inner extension module.

Read the guidelines …
https://extensions.sketchup.com/en/developer_center/ew_developer


Data is saved into Attribute Dictionary objects. Parametric code should do this for you.


Selecting Groups by Name
#5

Good morning Dan

Thank you for the advice

this afternoon I have some free hours and I will try to fix the code

Thanks again

Tiziano Traini