1. Tuk Bredsdorff
  2. Geodome frames for SU

Source

Geodome frames for SU / geodome_frame.rb

# Tuk Bredsdorff, 2012.
# Script to add a timber frame to a geodome model.

require "sketchup.rb"

# Default width, depth
STRUT_SIZE = [5.cm, 10.cm]

# Primary strut colors. If there are more strut lengths
# than colors here then a random one will be assigned.
PRIMARY_COLORS = ["Red", "Green", "Blue", "Yellow"]
STRUT_NAMES = ["A", "B", "C", "D"]

$strut_lengths = nil
$strut_counts = nil

def edges_in_selection
	selection = Sketchup.active_model.selection
	return selection.find_all { |e| e.kind_of?(Sketchup::Edge) }
end

# Create a strut (as a box in a group)
# along an edge, facing a center point.
def create_strut edge, center, size
	entities = Sketchup.active_model.active_entities
	width, depth = size
	
	vec_to_center = edge.start.position.vector_to center
	plane_intersecting_with_center = Geom.fit_plane_to_points center, edge.start.position, edge.end.position
	
	# We need a vector in the plane of the top of the strut.
	# It is the same as the normal to the plane intersecting with the center
	# which is the same as the three first values in the plane we just calculated.
	width_vec = Geom::Vector3d.new plane_intersecting_with_center[0..2]
	width_vec.length = width / 2
	
	# We add half a strut-width to the end points
	# of the edge to get the corners of the top of the strut.
	e1 = edge.start.position + width_vec
	e2 = edge.start.position - width_vec
	e3 = edge.end.position - width_vec
	e4 = edge.end.position + width_vec
	
	# We add a group for the strut and create the strut top face
	strut_group = entities.add_group
	strut_top_rect = [e1, e2, e3, e4]
	strut_top_face = strut_group.entities.add_face strut_top_rect
	
	# Push pull the top face to create the final strut
	strut_top_face.pushpull -depth
	
	return strut_group
end

# Look up colors and names given a strut length
def strut_properties length
	count = $strut_lengths[length.to_s]
	index = $strut_counts.index count
	color = PRIMARY_COLORS[index]
	name = STRUT_NAMES[index]
	return {'color'=>color, 'name'=>name}
end

# Loops through all edges in the current selection and
# creates struts. And adds all the struts to a group.
def create_frame edges, center, size
	all_struts = []
	edges.each_with_index { | edge, index |
		strut = create_strut edge, center, size
		props = strut_properties edge.length
		strut.name = props["name"]
		strut.material = props["color"]
		all_struts << strut
	}
	frame_group = Sketchup.active_model.active_entities.add_group all_struts
	frame_group.name = "Geodome frame"
end

# Print all entities.
# TODO: Fails. Test properly for entities attribute?
def print_entities entities=nil
	if not entities
		entities = Sketchup.active_model.entities
	end
	
	for e in entities
		puts e
		if e.entities
			print_entities e.entities
		end
	end
end

# Which strut lengths are this dome composed of?
def find_strut_lengths
	strut_lengths = {}
	
	for e in edges_in_selection
		# Uses Length.to_s to get the length in
		# in the users current units and precision :-) .
		rounded_str = e.length.to_s 
		if not strut_lengths[rounded_str]
			strut_lengths[rounded_str] = 1
		else
			strut_lengths[rounded_str]+= 1
		end
	end
	
	return strut_lengths
end

def print_strut_lengths
	puts "#{$strut_counts.nitems} strut lengths:"
	find_strut_lengths.each do |length, count|
		props = strut_properties length
		name = props["name"]
		color = props["color"]
		puts "#{count} x #{name} (#{color}): #{length}"
	end
end

def main
	Sketchup.active_model.start_operation "Geodome frame", true
		selection = Sketchup.active_model.selection
		
		# For now we assume the geodesic dome
		# has its center in the origin.
		center = [0, 0, 0]
		
		if selection.count > 0
			edges = edges_in_selection
			if edges.nitems > 0
				prompts = ["Width:", "Depth:"]
				size = inputbox prompts, STRUT_SIZE, "Strut Dimensions"
				if size
					$strut_lengths = find_strut_lengths
					$strut_counts = $strut_lengths.values.sort
					
					create_frame edges, center, size
					print_strut_lengths
				end
			else
				UI.messagebox "No edges in selection to build from."
			end
		else
			UI.messagebox "Please select geodome geometry for construction."
		end
	Sketchup.active_model.commit_operation
end

unless file_loaded? __FILE__
	UI.menu("Plugins").add_item("Create geodome frame") { main }
end

file_loaded __FILE__