When the object is a nested group my transformation accumulation is affected and cannot draw correctly globally

# Function to transform faces in @new_faces to global coordinates

def transform_faces_to_global
return unless @new_faces # Ensure there is data to process

@new_faces.each do |face|
next unless face.valid? # Skip deleted faces

parent = face.parent
next unless parent.valid? # Skip if parent has also been deleted

# Get the appropriate transformation by iterating over the entire path of the face
transformation = case parent
when Sketchup::Model
Geom::Transformation.new # If the face is in the parent model
when Sketchup::Group, Sketchup::ComponentInstance
cumulative_transformation = parent.transformation
current = parent
# Iterate over parent objects if they exist and have transformation
while current.respond_to?(:parent) && current.parent.respond_to?(:transformation)
current = current.parent
cumulative_transformation = current.transformation * cumulative_transformation
end
cumulative_transformation
when Sketchup::ComponentDefinition
# Get the transformation from the first instance of ComponentDefinition (if any)
parent.instances.first&.transformation || Geom::Transformation.new
else
Geom::Transformation.new # Default if not recognized
end

# Transform face vertex coordinates to global coordinates
global_vertices = face.vertices.map { |v| v.position.transform(transformation) }

# Debugging log (if needed)
# puts "🔹 Face #{face} has global coordinates:"
# global_vertices.each_with_index do |point, index|
# puts " - Point #{index + 1}: (#{point.x.to_m}, #{point.y.to_m}, #{point.z.to_m})"
# end
end
end

def get_face_transformation(face)
return Geom::Transformation.new unless face&.valid? && @selected_faces.include?(face)

 parent = face.parent
 transformation = Geom::Transformation.new

 case parent
 when Sketchup::ComponentDefinition
 # Get the transformation from the first instance of ComponentDefinition if there is one
 instance = parent.instances.first
 if instance && instance.valid?
 transformation = instance.transformation
 current = instance
 while current.respond_to?(:parent) && current.parent.respond_to?(:transformation)
 current = current.parent
 transformation = current.transformation * transformation
 end
 end
 when Sketchup::Group, Sketchup::ComponentInstance
 transformation = parent.transformation
 current = parent
 while current.respond_to?(:parent) && current.parent.respond_to?(:transformation)
 current = current.parent
 transformation = current.transformation * transformation
 end
 else. else
 transformation = Geom::Transformation.new
 end

 transformation. transformation
end



# --- Helper functions ---

# --- Draw Function ---

# --- Draw Function ---

def draw(view)
# 1) Redraw the main face (if any)
if @selected_face && @selected_face.valid?
draw_face_2d(view, @selected_face, @selected_transformation)
end

# 2) Check state to draw preview
preview_distance = nil

if @dragging # If dragging, prioritize @pushpull_distance and cancel @user_pull_distance
@user_pull_distance = nil # Cancel preview from user input
preview_distance = @pushpull_distance
elsif @user_pull_distance # If not dragging but has @user_pull_distance, use it
preview_distance = @user_pull_distance
end

# If there is a valid preview distance, draw preview
if @selected_face && preview_distance
draw_drag_preview(view, @selected_face, preview_distance, @selected_transformation)
end

return unless @selected_faces && !@selected_faces.empty?

transform_faces_to_global # Transform coordinates before drawing

# 3) Draw new faces created after Push/Pull
if @new_faces && !@new_faces.empty?
view.drawing_color = "blue"

@new_faces.each do |face|
next unless face.valid? && @selected_faces.include?(face)

 transformation = get_face_transformation(face)

 draw_face_2d(view, face, transformation)

 # Check status to draw preview
 preview_distance = nil

 if @dragging
 @user_pull_distance = nil # Remove preview from user input when dragging
 preview_distance = @pushpull_distance
 elsif @user_pull_distance
 preview_distance = @user_pull_distance
 end

 if preview_distance
 draw_drag_preview(view, face, preview_distance, transformation)
 end
 end
 end

 #4) Redraw all selected faces
 @selected_faces.each do |face|
 next unless face.valid?

 transformation = get_face_transformation(face)

 draw_face_2d(view, face, transformation)

 # Check status to draw preview
 preview_distance = nil

 if @dragging
 @user_pull_distance = nil # Remove preview from user input when dragging
 preview_distance = @pushpull_distance
 elsif @user_pull_distance
 preview_distance = @user_pull_distance
 end

 if preview_distance
 draw_drag_preview(view, face, preview_distance, transformation)
 end
 end
end

Post code correctly in the forum and please edit your previous post.

…

…

This when clause will never be true as group and component instrances do not have an Entities collection. Only their “parent” definitions do.

(a) Please make your topic title more concise and put the lenghty question or challenge statement in the opening post.

(b) You cannot build a composite transformation from the bottom back up to the model root. You need to build an InstanecPath array from the root down to the leaf instance as the user “drills” down.

This has been covered multiple times here in this category.

1 Like

tks Dan, I modified the condition, the problem is that I only apply the transform to the parent group and ignore its child groups.