I want the rectangles to be copied and rotated, but keep the exact distance between these the same, like the midle one. without needing to calculate anything.
The image below is what i tried to do. The left one is my input. The third one is what i tried and rotate them piece by piece.
Then i tried this: copy / 12 the rectangles in the midpoint of the rectangle. Then rotate by hand 45°/12 every piece. But the distance between is different. Is there a magic mathmatical formula to do this?
SketchUp is quite capable of doing the calculation for you.
It is also tedious to manually create the positions and fully depends on the dimensions of the rectangle and the radius of rotation.
Copy/rotate the rectangle (a component!) as you did.
Then stitch the created rectangles head<>tail to eachother. To get the total length that they all need while rotated. This should be subtracted from the overall length between first and last rectangle.
The resulting edge from the subtraction can then be divided by 12 to get the required constant length betwee the subsequent rectangles, head<>tail.
It’s all a matter of shifting rectangles but ShetchUp does all the calculations.
I think they need the distance between the geometry of the rectangle to be the same, not the center to center distance… like it those were railing pickets and the minimum to code was 4", they could rotate however you want so long as the distance between the rectangles was the same 4" (or less).
OK. Thanks for the clarification. I was in the process of setting up a dynamic component that could distribute copies of a component and rotate them to the correct angle but was based on the distance between the origins of the components not the space between. I scrapped it and removed my post since I was going down the wrong path.
With the help of Gemini AI I have the ruby code to create copies of the rectangle and set the rotation of each one to the desired angle, but it still needs to be completed with the possibility of setting the gap between the two closest points of the rotated rectangles.
ruby code - test at your own risk!
module MS_Tools
module RotatedArray
def self.create_array
model = Sketchup.active_model
selection = model.selection
if selection.empty? || selection.length > 1
UI.messagebox("Selectează o singură componentă sau un singur grup!")
return
end
entity = selection.first
unless entity.is_a?(Sketchup::ComponentInstance) || entity.is_a?(Sketchup::Group)
UI.messagebox("Elementul selectat trebuie să fie o Componentă sau un Grup.")
return
end
prompts = ["Număr copii:", "Unghi rotire / pas (grade):", "Distanță liberă (cm):"]
defaults = [10, 5.0, 50.0]
input = UI.inputbox(prompts, defaults, "Multiplicare și Rotire Incrementală")
return unless input
num_copies = input[0].to_i
angle_deg = input[1].to_f
clearance = input[2].to_f.cm
step_angle_rad = angle_deg.degrees
model.start_operation('Multiplicare Rotită Exactă', true)
parent = entity.parent
# Salvăm instanțele create pentru a le calcula colțurile exacte
instances = [entity]
current_y = 0.0
base_trans = entity.transformation
num_copies.times do |i|
prev_inst = instances.last
prev_tr = prev_inst.transformation
# Unghiul pentru noua piesă
new_angle = step_angle_rad * (i + 1)
# Matrice de rotire pură pentru noua piesă
t_rot = Geom::Transformation.rotation(ORIGIN, Z_AXIS, new_angle)
# Aflăm punctele (colțurile) piesei anterioare în spațiul mondial (World Coordinates)
prev_points = get_instance_corners(prev_inst)
# Calculăm decalajul Y necesar încât min_dist(prev_points, new_points) == clearance
# Facem un calcul exact pe axa Y:
# Punctele noii piese înainte de translația Y (doar rotite):
temp_tr = base_trans * t_rot
untranslated_new_pts = get_points_with_transform(entity, temp_tr)
# Găsim Y-ul minim astfel încât distanța minimă între orice punct din prev și new să fie clearance
# Deoarece mișcarea e pe Y, căutăm deplasarea dy pe Y
dy = calculate_required_y_shift(prev_points, untranslated_new_pts, clearance)
current_y += dy
final_tr = base_trans * Geom::Transformation.translation(Geom::Vector3d.new(0, dy, 0)) * (Geom::Transformation.rotation(ORIGIN, Z_AXIS, new_angle))
# Păstrăm poziționarea cumulativă corectă
if entity.is_a?(Sketchup::ComponentInstance)
new_inst = parent.entities.add_instance(entity.definition, final_tr)
else
new_inst = parent.entities.add_group(entity.definition.entities.to_a)
new_inst.transformation = final_tr
end
instances << new_inst
end
model.commit_operation
end
private
def self.get_instance_corners(inst)
bb = inst.definition.bounds
tr = inst.transformation
corners = []
8.times { |idx| corners << bb.corner(idx).transform(tr) }
corners
end
def self.get_points_with_transform(entity, tr)
bb = entity.definition.bounds
corners = []
8.times { |idx| corners << bb.corner(idx).transform(tr) }
corners
end
def self.calculate_required_y_shift(pts_below, pts_above_untranslated, target_dist)
# Căutăm translația pe Y (shift_y) astfel încât distanța minimă 3D între colțuri să fie exact target_dist
# Pentru că translația pe Y modifică distanța direct, calculăm offset-ul necesar între cele mai apropiate puncte.
max_required_y = 0.0
pts_below.each do |p1|
pts_above_untranslated.each do |p2|
# p2_translated = p2 + [0, shift_y, 0]
# Vrem |p2_translated - p1| >= target_dist
dx = p2.x - p1.x
dz = p2.z - p1.z
# Distanța în planul XZ între cele două puncte
xz_dist_sq = dx*dx + dz*dz
if target_dist*target_dist > xz_dist_sq
dy_needed = Math.sqrt(target_dist*target_dist - xz_dist_sq) - (p2.y - p1.y)
max_required_y = dy_needed if dy_needed > max_required_y
else
# Dacă distanța pe XZ e deja mai mare decât target_dist, p2 trebuie doar să fie deasupra lui p1 pe Y
dy_needed = (p1.y - p2.y)
max_required_y = dy_needed if dy_needed > max_required_y
end
end
end
max_required_y
end
end
end
MS_Tools::RotatedArray.create_array
goal (remains to be solved) - Equal gap between rotated rectangles
In Blender, with the help of the Array modifier and the Align and Distribute extension, I can create the entire process to have that equal gap between elements.