Retrieve position of face vertex in global frame of reference

Hello,

In sketchup API, I was trying to retrieve the position of outer loop vertices of a face using:
face.outer_loop.vertices

However, I am not able to get the position in the global fame of reference.

Thanks!
@thomthom

Positions obtained from vertices are always locale to their parent - not global.

In order to work out the global position you need the combined transformation for all the parent instances. How you do that depend on context of how your extension work.

For instance, if your extension works on the active_entities at all time, then you can obtain the transformation via model.edit_transform.

But if you are traversing the whole model, say if you do a model export, then you need to keep track of the instance transformations as you dig down into the model hierarchy.

module Example

  def self.get_entities(instance)
    if entity.is_a?(Sketchup::Group)
      entity.entities
    else
      entity.definition.entities
    end
  end

  def self.walk(entities, transformation = IDENTITY)
    entities.each { |entity|
      case entity
      when Sketchup::Face
        global_points = face.outer_loop.vertices.map { |vertex|
          vertex.position.transform(transformation)
        }
        # Do stuff to global position of vertices here...
      when Sketchup::Group, Sketchup::ComponentInstance
        entities = get_entities(instance)
        walk(entities, entity.transformation * transformation)
      end
    }
  end

end

I used the following:

mod = Sketchup.active_model # Open model
ent = mod.entities # All entities in model
sel = mod.selection # Current selection

def walk(face, transformation = IDENTITY)
  global_points = face.outer_loop.vertices.map { |vertex|
    vertex.position.transform(transformation)
  }
end

sel[0].entities.each { |ent|
  if ent.typename=="Face"
      puts walk(ent)
    end
}

On the graphics screen, I selected a group, which contains some faces. But still I am retrieving the local coordinates. Is there anything wrong with my understanding?

Thanks!

Okkkk Got it now!!

This worked for me:

mod = Sketchup.active_model # Open model
ent = mod.entities # All entities in model
sel = mod.selection # Current selection

def walk(face, transformation = IDENTITY)
  global_points = face.outer_loop.vertices.map { |vertex|
    vertex.position.transform(transformation)
  }
end

sel[0].entities.each { |ent|
  if ent.typename=="Face"
      puts walk(ent, sel[0].transformation)
    end
}

Thanks @thomthom

Is very slow. Using Ruby core is_a?() method is much faster:

ent.is_a? Sketchup::Face

Hey, on the margins of this question, I would ask why when I created a new point using:
pt = Geom::Point3d.new(1,0,1)
puts pt
(0.0254m, 0m, 0.0254m)

It returning values in inches? (I guess)
I have set meters as the model unit though

Is it the same issue as global and local like it follows the parents or something like this?

Thanks

The SketchUp engine uses Inches internally.

pt = Geom::Point3d.new( 1.mm, 0, 1.mm )

See the API methods added to the Numeric class:

… and the API specific Length class:


Also see ThomThom’s blog:

Thanks @DanRathbun
appreciate it!

1 Like

A strong +1 for that - it’s the number one performance killer I see in SketchUp extensions. To the point I even wrote a little article at one point:

Oh I see. Thanks!

This topic was automatically closed after 91 days. New replies are no longer allowed.