Hello! And thank you for your help so far. I did some further experimentation, however, I was unable to achieve what I wanted to do.
Overall, what I am trying to achieve is a data-deformed sculpture. I have an array (“ratings”), which I want to use to deform a donut-shaped sculpture. Here is what I created in the first place:
# Code example 1
model = Sketchup.active_model
entities = model.active_entities
model.active_entities.clear!
diameter = 24.cm
thickness = 2.cm
height = 4.cm
steps = 12
circle_steps = 365
radius = diameter/2.0
base_points = Array.new
hole_points = Array.new
ratings1 = [1,2,3,4,5,6,7,8,9,8,7,6]
def month_face (entities, month)
# Find the face that corresponds to a month by its color.
targetColor = Sketchup::Color.new(0, 255, month*20)
faces = []
entities.each do |entity|
if entity.is_a? Sketchup::Face
if entity.material != nil
if entity.material.color.to_i == targetColor.to_i
# If the face's color matches the target color: that's what we're looking for.
return entity
end
end
end
end
return nil
end
# Construct the basic shape.
for step in 1..steps
x = (radius+thickness) * Math.sin(2 * Math::PI * (step / steps.to_f))
y = (radius+thickness) * Math.cos(2 * Math::PI * (step / steps.to_f))
base_points << [x, y, 0]
end
# Construct the hole in the middle (for later).
for step in 1..circle_steps
x = (radius) * Math.sin(2 * Math::PI * (step / circle_steps.to_f))
y = (radius) * Math.cos(2 * Math::PI * (step / circle_steps.to_f))
hole_points << [x, y, 0]
end
edge_tapering = 0.96
edge_height = height*0.2
body_height = height*0.8
ring = entities.add_group
shape = ring.entities.add_face base_points # Start with the basic shape
normal_transformation = Geom::Transformation.scaling 1
edge_tapering_transformation = Geom::Transformation.scaling edge_tapering
entities.transform_entities(edge_tapering_transformation, shape)
shape.pushpull(edge_height, true)
faces = []
ring.entities.each do |e|
if e.is_a? Sketchup::Face
faces << e
end
end
extrusionFace = faces[1]
undo_edge_tapering_transformation = edge_tapering_transformation.inverse
entities.transform_entities(undo_edge_tapering_transformation, extrusionFace)
extrusionFace.pushpull(body_height, false)
faces = []
ring.entities.each do |e|
if e.is_a? Sketchup::Face
faces << e
end
end
extrusionFace = faces[13]
entities.transform_entities(normal_transformation, extrusionFace)
extrusionFace.pushpull(edge_height, true)
faces = []
ring.entities.each do |e|
if e.is_a? Sketchup::Face
faces << e
end
end
extrusionFace = faces[26]
entities.transform_entities(edge_tapering_transformation, extrusionFace)
shape = ring.entities.add_face hole_points
shape.pushpull(ring.local_bounds.depth)
faces = []
ring.entities.each do |e|
if e.is_a? Sketchup::Face
faces << e
end
end
faces[13].erase! # Remove the hole
ring.explode
faces = []
entities.each do |e|
if e.is_a? Sketchup::Face
faces << e
end
end
# Label the vertices:
for month in 0..11
face = faces[12+month]
face.material = [0, 255, month*20] # This works correctly: the colors' blue value increases around the donut.
if (false)
rating1_vertex(face).set_attribute "diary_points", "month", month
rating1_vertex(face).set_attribute "diary_points", "rating", 1
rating2_vertex(face).set_attribute "diary_points", "month", month
rating2_vertex(face).set_attribute "diary_points", "rating", 2
end
end
# Transform the donut:
for month in 0...steps
face = month_face(entities, month)
if face != nil
t1 = Geom::Transformation.new([0,0,+((10-ratings1[month]).to_f/10.0+month/50.0)*height.to_f/3.0])
t1 = Geom::Transformation.new([0,0,-0.3])
# Apply the transformation, created from ratings1[month], to the top-left-most (viewed from the outside) vertex of the month's face
# vertex = ?
#entities.transform_entities(t1, vertex)
# Apply the same thing from ratings2[] to the bottom side. (Same problem - I can't find the correct vertex.)
#t2 = Geom::Transformation.new([0,0,-((10-ratings2[month]).to_f/10.0+month/50.0)*height.to_f/3.0])
end
end
… and it works pretty well! If you change the values in the ratings array, the shape gets deformed accordingly. Great! However, the hole in the middle needs to be really round - and that started to make things a whole lot more complicated:
# Code example 2
model = Sketchup.active_model
entities = model.active_entities
model.active_entities.clear!
diameter = 24.cm
thickness = 2.cm
height = 4.cm
steps = 12
circle_steps = 365
radius = diameter/2.0
base_points = Array.new
hole_points = Array.new
ratings1 = [1,2,3,4,5,6,7,8,9,8,7,6]
def month_face (entities, month)
# Find the face that corresponds to a month by its color.
targetColor = Sketchup::Color.new(0, 255, month*20)
faces = []
entities.each do |entity|
if entity.is_a? Sketchup::Face
if entity.material != nil
if entity.material.color.to_i == targetColor.to_i
# If the face's color matches the target color: that's what we're looking for.
return entity
end
end
end
end
return nil
end
# Construct the basic shape.
for step in 1..steps
x = (radius+thickness) * Math.sin(2 * Math::PI * (step / steps.to_f))
y = (radius+thickness) * Math.cos(2 * Math::PI * (step / steps.to_f))
base_points << [x, y, 0]
end
# Construct the hole in the middle (for later).
for step in 1..circle_steps
x = (radius) * Math.sin(2 * Math::PI * (step / circle_steps.to_f))
y = (radius) * Math.cos(2 * Math::PI * (step / circle_steps.to_f))
hole_points << [x, y, 0]
end
edge_tapering = 0.96
edge_height = height*0.2
body_height = height*0.8
ring = entities.add_group
shape = ring.entities.add_face base_points # Start with the basic shape
normal_transformation = Geom::Transformation.scaling 1
edge_tapering_transformation = Geom::Transformation.scaling edge_tapering
entities.transform_entities(edge_tapering_transformation, shape)
shape.pushpull(edge_height, true)
faces = []
ring.entities.each do |e|
if e.is_a? Sketchup::Face
faces << e
end
end
extrusionFace = faces[1]
undo_edge_tapering_transformation = edge_tapering_transformation.inverse
entities.transform_entities(undo_edge_tapering_transformation, extrusionFace)
extrusionFace.pushpull(body_height, false)
faces = []
ring.entities.each do |e|
if e.is_a? Sketchup::Face
faces << e
end
end
extrusionFace = faces[13]
entities.transform_entities(normal_transformation, extrusionFace)
extrusionFace.pushpull(edge_height, true)
faces = []
ring.entities.each do |e|
if e.is_a? Sketchup::Face
faces << e
end
end
extrusionFace = faces[26]
entities.transform_entities(edge_tapering_transformation, extrusionFace)
shape = ring.entities.add_face hole_points
shape.pushpull(ring.local_bounds.depth)
faces = []
ring.entities.each do |e|
if e.is_a? Sketchup::Face
faces << e
end
end
faces[13].erase! # Remove the hole
ring.explode
faces = []
entities.each do |e|
if e.is_a? Sketchup::Face
faces << e
end
end
# Label the vertices:
for month in 0..11
face = faces[12+month]
face.material = [0, 255, month*20] # This works correctly: the colors' blue value increases around the donut.
if (false)
rating1_vertex(face).set_attribute "diary_points", "month", month
rating1_vertex(face).set_attribute "diary_points", "rating", 1
rating2_vertex(face).set_attribute "diary_points", "month", month
rating2_vertex(face).set_attribute "diary_points", "rating", 2
end
end
# Transform the donut:
for month in 0...steps
face = month_face(entities, month)
if face != nil
t1 = Geom::Transformation.new([0,0,+((10-ratings1[month]).to_f/10.0+month/50.0)*height.to_f/3.0])
t1 = Geom::Transformation.new([0,0,-0.3])
# Apply the transformation, created from ratings1[month], to the top-left-most (viewed from the outside) vertex of the month's face
# vertex = ?
#entities.transform_entities(t1, vertex)
# Apply the same thing from ratings2[] to the bottom side. (Same problem - I can't find the correct vertex.)
#t2 = Geom::Transformation.new([0,0,-((10-ratings2[month]).to_f/10.0+month/50.0)*height.to_f/3.0])
end
end
In this one, I have a hard time finding the correct vertices to move - if I save references to them, I often get errors a la “You are trying to refer to a deleted Entity.”.
I also chamfer the donut’s edges in this one - however, I noticed that the edges’ heights are different. Is that because I apply a transformation to them? Both should be equal (0.2*height), but the top one is bigger.
Also, my script makes Sketchup crash quite often. Am I doing things structurally wrong?
If it’s easier (less tesselating?), an option could be to make a disc object, deform it, and then pushpull a hole into the middle of it. I’m not sure that this would solve my problem, though.
Again, thanks for all your help!
Fabian
(I’m not sure if my previous reply got uploaded, so I’m writing it again - I hope this doesn’t apply twice.)