windows11で、sketchup6 その30

# 概要
windows11に、sketchup6を入れてみた。
rubyで、3Dを書く。
subdivision、見つけたので、やってみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/4c39a55e-b0de-4975-9a71-87734314ab5b.png)

# サンプルコード

```

require 'sketchup.rb'

#loop_subdiv_mesh

class Sketchup::Face
	def loop_centroid
		pts = []
		self.outer_loop.vertices.each do |v|
			pts.push v.position
		end
		loop_subdiv_average_points(pts).project_to_plane(self.plane)
	end
	def loop_simple_convex_nontriangle
		((self.loops.length == 1) && (self.edges.length > 3) && (self.outer_loop.convex?))
	end
	def loop_triangulate(tform)
		if (self.loop_simple_convex_nontriangle)
			self.loop_triangulate_convex(tform)
		else
			self.loop_triangulate_nonconvex(tform)
		end
	end
	def loop_triangulate_convex(tform)
		cent = self.loop_centroid.transform!(tform)
		face_array = []
		self.outer_loop.edges.each do |edge|
			pts = []
			pts.push edge.start.position.transform!(tform)
			pts.push edge.end.position.transform!(tform)
			pts.push cent
			face_array.push pts
		end
		face_array
	end
	def loop_triangulate_nonconvex(tform)
		face_array = []
		mesh = self.mesh 0
		mesh.transform! tform
		for i in 1..mesh.count_polygons do
			pts = []
			pts = mesh.polygon_points_at(i)
			unless(loop_subdiv_colinear?(pts))
				face_array.push pts
			end
		end
		face_array
	end
end

class Sketchup::Edge
	def loop_subdiv_point
		pts = []
		weights = []
		point = nil
		self.faces.each do |face|
			face.vertices.each do |vertex|
				if (!self.used_by? vertex)
					pts.push vertex.position
				end
			end
		end
		point = Geom::Point3d.linear_combination 0.5, self.start.position, 0.5, self.end.position
		if (pts.length > 1)
			p1 = Geom::Point3d.linear_combination 0.5, pts[0], 0.5, pts[1]
			point = Geom::Point3d.linear_combination 0.25, p1, 0.75, point
		end
		@subdivpoint=point
	end
	def getlooppoint
		if (@subdivpoint.nil?)
			self.loop_subdiv_point
		end
		@subdivpoint
	end
end

class Sketchup::Vertex
	def loop_subdiv_point
		n = 0; 
		b = 0; 
		pts = []; 
		point = nil
		n = self.edges.length
		if (n > 3)
			b = 3.0 / (8.0 * n)
		elsif (n == 3)
			b = 0.1875
		elsif (n == 2)
			b = 0.25
		end
		if (n > 1)
			self.edges.each do |edge|
				v = edge.other_vertex self
				pts.push(v.position)
			end
			point = loop_subdiv_average_points(pts)
			point = Geom::Point3d.linear_combination(n * b, point, 1 - (n * b), self.position)
		end
		point
	end
end

def loop_subdiv_colinear?(pts)
	return if (pts.length < 3)
	pts[0].on_line?(pts[1], pts[2])
end

def loop_subdiv_average_points(pts)
	x = 0;
	y = 0;
	z = 0
	pts.each do |pt|
		x += pt.x
		y += pt.y
		z += pt.z
	end
	Geom::Point3d.new(x / pts.length, y / pts.length, z / pts.length)
end

def loop_subdiv_erase_mesh(layer)
	model = Sketchup.active_model
	ent_arr = []
	model.entities.each do |element|
		if ((element.layer == layer))
			ent_arr.push element
		end
	end
	ent_arr.each {|e| 
		e.erase! if not e.deleted?
	}
end

def loop_subdiv_find_faces(others, entity_array, entities, tform)
	entities.each do |entity|
		if (entity.typename == "Group")
			others = loop_subdiv_find_faces(others, entity_array, entity.entities, tform * entity.transformation)
		elsif (entity.typename == "ComponentInstance")
			others = loop_subdiv_find_faces(others, entity_array, entity.definition.entities, tform * entity.transformation)
		elsif (entity.typename == "Face")
			entity_array.push [entity, tform, entity.material, entity.back_material]
		else
			others = others + 1
		end
	end
	others
end

def loop_getvertices(sel, faces_array)
	vertices = []
	$all_verts = []
	sel.each do |ent|
		if ent.class == Sketchup::Face
			pts = []
			ent.edges.each do |edge|
				vertices.push(edge.vertices)
				pts.push(edge.getlooppoint)
			end
			faces_array.push [pts, ent.material, ent.back_material]
		end
	end
	vertices.flatten!
	vertices.uniq!
	$all_verts = vertices
end

def loop_vertices_calculate(faces_array)
	$all_verts.each do |v|
		v1 = v.loop_subdiv_point
		v.faces.each do |face|
			pts = [v1]
			face.edges.each do |edge|
				if (v.used_by? edge)
					pts.push edge.getlooppoint
				end
				faces_array.push [pts, face.material, face.back_material]
			end
		end
	end
end

def loop_subdivide(ents, repeats = 1, soften = true)
	if (ents.length > 0)
		model = Sketchup.active_model
		original_layer =  model.active_layer
		faces_array = []
		others = loop_subdiv_find_faces(0, faces_array, ents, Geom::Transformation.new())
		loop_layer_name = "Loop_subdiv-" + rand(10000000).to_s + "-"
		model.active_layer = model.layers.add(loop_layer_name)
		entities = model.entities
		$oldlayer = model.active_layer
		new_faces_array = []
		$problem_faces = []
		$sel = model.selection
		$sel.clear
		delete_edges = []
		faces_array.each do |faceTform|
			face = faceTform[0]
			tform = faceTform[1]
			new_faces = []
			faces = []
			faces = face.loop_triangulate(tform)
			face.edges.each {|e| 
				e.layer = $oldlayer
			}
			face.erase!
			faces.each do |pts|
				face = entities.add_face(pts)
				face.material = faceTform[2]
				face.back_material = faceTform[3]
				new_faces_array.push face
			end
		end
		for i in (1..repeats)
			faces_array = []
			loop_getvertices(new_faces_array, faces_array)
			loop_vertices_calculate(faces_array)
			newlayer = model.layers.add(loop_layer_name + i.to_s)
			model.active_layer = (newlayer)
			loop_subdiv_erase_mesh($oldlayer)
			new_faces_array = []
			faces_array.each do |facedata|
				face = entities.add_face(facedata[0])
				face.material = facedata[1]
				face.back_material = facedata[2]
				if (soften == true)
					face.edges.each do |edge|
						edge.soft = true
						edge.smooth = true
					end
				end
				new_faces_array.push(face)
			end
			$oldlayer = newlayer
		end
		model.layers.purge_unused
		model.active_layer = original_layer
	end
end

def loop_subdiv_mesh
	model = Sketchup.active_model
	ss = model.selection
	if (Sketchup.version_number == 7)
		model.start_operation("loop subdivision", true)
	else
		model.start_operation("loop subdivision")
	end
	if ss.empty?
		answer = UI.messagebox("No objects selected. Subdivide entire model?", MB_YESNOCANCEL)
		if (answer == 6)
			divide_ents = model.entities
		else
			divide_ents = ss
		end
	else
		divide_ents = ss
	end
	option_result = loop_subdiv_options_dialog
	subdiv_count = option_result[0].to_i
	soften = (option_result[1] == "yes")
	loop_subdivide(divide_ents, subdiv_count, soften)
	model.commit_operation
end

def loop_subdiv_options_dialog
	options_list = ["1", "2", "3", "4"].join("|")
	prompts = ["How many times?", "Soften and smooth edges?"]
	enums = [options_list, "yes|no"]
	values = ["1", "yes"]
	results = inputbox prompts, values, enums, "Repeat subdivision ?"
	return if not results
	results
end


```

以上。