SketchUp / api-issue-tracker

Public issue tracker for the SketchUp and LayOut's APIs
https://developer.sketchup.com/
38 stars 10 forks source link

Sketchup::InstancePath.leaf give nil result when last item is a group or a component #995

Open tomboul26 opened 3 months ago

tomboul26 commented 3 months ago

and drawing_element_visible? has the error Leaf must be a type of Sketchup::Drawingelement when last item of instancePath is a group or a component for the same reason with this code

def test(entities, path = [])
  entities.each { | ent | 
    if(ent.is_a?(Sketchup::Drawingelement))
      pa = Sketchup::InstancePath.new(path + [ent])
      puts "its a drawing element #{ent.class.to_s} " + getName(ent) + "  valid = #{pa.valid?} leaf = #{pa.leaf.to_s} root = " + getName(pa.root)  # even when it's a Sketchup::group
      #vis = ent.model.drawing_element_visible?(pa) 
    end
    if ent.is_a?(Sketchup::Group) 
      test(ent.entities, path + [ent])
    end
    if ent.is_a?(Sketchup::ComponentInstance) 
      test(ent.definition.entities, path + [ent])
    end
  }
end

def getName(entity, id = "")
  cm = entity.class.to_s.gsub("Sketchup::", "")
  if(cm != "Group" && entity.respond_to?(:definition))
      entity = entity.definition
  end
  if(entity.respond_to?(:name) && entity.name)
      name = "#{cm}_#{entity.name}"
  else
      if(entity.respond_to?(:entityID) && entity.entityID != nil)
          name = "#{cm}_entityID_#{entity.entityID}"
      else 
          name = "#{cm}_id_#{id}"
      end
  end
  return(name)
end

and this simple sketchup project (i can't upload a sketchup project here) 2024-08-23_10h29_21 i have this result :

test(Sketchup.active_model.entities)
its a drawing element Sketchup::Group Group_comp  valid = true leaf =  root = Group_comp
its a drawing element Sketchup::Group Group_comp 1 2  valid = true leaf =  root = Group_comp
its a drawing element Sketchup::ComponentInstance ComponentInstance_comp 2  valid = true leaf =  root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_144  valid = true leaf = #<Sketchup::Edge:0x000000001dc59eb0> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_145  valid = true leaf = #<Sketchup::Edge:0x000000001dc59438> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_146  valid = true leaf = #<Sketchup::Edge:0x000000001dc58bc8> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_147  valid = true leaf = #<Sketchup::Edge:0x000000001dc58128> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_148  valid = true leaf = #<Sketchup::Edge:0x000000001dc57598> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_149  valid = true leaf = #<Sketchup::Edge:0x000000001dc56710> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_150  valid = true leaf = #<Sketchup::Edge:0x000000001dc551d0> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_151  valid = true leaf = #<Sketchup::Edge:0x000000001dc54348> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_152  valid = true leaf = #<Sketchup::Edge:0x000000001dc50db0> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_153  valid = true leaf = #<Sketchup::Edge:0x000000001dc50220> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_154  valid = true leaf = #<Sketchup::Edge:0x000000001dc9df48> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_155  valid = true leaf = #<Sketchup::Edge:0x000000001dc9ca08> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_156  valid = true leaf = #<Sketchup::Face:0x000000001dc9ba18> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_162  valid = true leaf = #<Sketchup::Face:0x000000001dc989a8> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_168  valid = true leaf = #<Sketchup::Face:0x000000001dc97c38> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_174  valid = true leaf = #<Sketchup::Face:0x000000001dc96cc0> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_180  valid = true leaf = #<Sketchup::Face:0x000000001dc95e38> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_186  valid = true leaf = #<Sketchup::Face:0x000000001dc95320> root = Group_comp
its a drawing element Sketchup::ComponentInstance ComponentInstance_comp 1  valid = true leaf =  root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_76  valid = true leaf = #<Sketchup::Edge:0x000000001dc93d68> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_77  valid = true leaf = #<Sketchup::Edge:0x000000001dc934d0> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_78  valid = true leaf = #<Sketchup::Edge:0x000000001dc92e90> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_79  valid = true leaf = #<Sketchup::Edge:0x000000001dc92558> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_80  valid = true leaf = #<Sketchup::Edge:0x000000001dc91e00> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_81  valid = true leaf = #<Sketchup::Edge:0x000000001dc918d8> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_82  valid = true leaf = #<Sketchup::Edge:0x000000001dc91248> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_83  valid = true leaf = #<Sketchup::Edge:0x000000001dc90848> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_84  valid = true leaf = #<Sketchup::Edge:0x000000001dc90050> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_85  valid = true leaf = #<Sketchup::Edge:0x000000001da1e100> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_86  valid = true leaf = #<Sketchup::Edge:0x000000001da1c878> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_87  valid = true leaf = #<Sketchup::Edge:0x000000001da1abe0> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_88  valid = true leaf = #<Sketchup::Face:0x000000001da18930> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_94  valid = true leaf = #<Sketchup::Face:0x000000001da16fb8> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_100  valid = true leaf = #<Sketchup::Face:0x000000001da16720> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_106  valid = true leaf = #<Sketchup::Face:0x000000001da16158> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_112  valid = true leaf = #<Sketchup::Face:0x000000001da15960> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_118  valid = true leaf = #<Sketchup::Face:0x000000001da15230> root = Group_comp
its a drawing element Sketchup::Group Group_comp 3 4  valid = true leaf =  root = Group_comp
its a drawing element Sketchup::ComponentInstance ComponentInstance_comp 3  valid = true leaf =  root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_212  valid = true leaf = #<Sketchup::Edge:0x000000001da13f70> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_213  valid = true leaf = #<Sketchup::Edge:0x000000001da138e0> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_214  valid = true leaf = #<Sketchup::Edge:0x000000001da120f8> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_215  valid = true leaf = #<Sketchup::Edge:0x000000001da11a90> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_216  valid = true leaf = #<Sketchup::Edge:0x000000001da111f8> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_217  valid = true leaf = #<Sketchup::Edge:0x000000001da106e0> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_218  valid = true leaf = #<Sketchup::Edge:0x000000001d9cfd70> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_219  valid = true leaf = #<Sketchup::Edge:0x000000001d9cf528> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_220  valid = true leaf = #<Sketchup::Edge:0x000000001d9ceb50> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_221  valid = true leaf = #<Sketchup::Edge:0x000000001d9cdf98> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_222  valid = true leaf = #<Sketchup::Edge:0x000000001d9cd688> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_223  valid = true leaf = #<Sketchup::Edge:0x000000001d9ccdf0> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_224  valid = true leaf = #<Sketchup::Face:0x000000001d9cc648> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_230  valid = true leaf = #<Sketchup::Face:0x000000001d9cbe78> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_236  valid = true leaf = #<Sketchup::Face:0x000000001d9cb3b0> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_242  valid = true leaf = #<Sketchup::Face:0x000000001d9ca640> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_248  valid = true leaf = #<Sketchup::Face:0x000000001d9c8278> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_254  valid = true leaf = #<Sketchup::Face:0x000000001d9c6a18> root = Group_comp
its a drawing element Sketchup::ComponentInstance ComponentInstance_comp 4  valid = true leaf =  root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_280  valid = true leaf = #<Sketchup::Edge:0x000000001d9c4718> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_281  valid = true leaf = #<Sketchup::Edge:0x000000001d9c3638> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_282  valid = true leaf = #<Sketchup::Edge:0x000000001d9c2c38> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_283  valid = true leaf = #<Sketchup::Edge:0x000000001d9c1e28> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_284  valid = true leaf = #<Sketchup::Edge:0x000000001d9c17e8> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_285  valid = true leaf = #<Sketchup::Edge:0x000000001d9c11f8> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_286  valid = true leaf = #<Sketchup::Edge:0x000000001d9c0c08> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_287  valid = true leaf = #<Sketchup::Edge:0x000000001d9c05a0> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_288  valid = true leaf = #<Sketchup::Edge:0x0000000021ddfc90> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_289  valid = true leaf = #<Sketchup::Edge:0x0000000021ddf768> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_290  valid = true leaf = #<Sketchup::Edge:0x0000000021ddf290> root = Group_comp
its a drawing element Sketchup::Edge Edge_entityID_291  valid = true leaf = #<Sketchup::Edge:0x0000000021ddee30> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_292  valid = true leaf = #<Sketchup::Face:0x0000000021dde868> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_298  valid = true leaf = #<Sketchup::Face:0x0000000021dde408> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_304  valid = true leaf = #<Sketchup::Face:0x0000000021dddf30> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_310  valid = true leaf = #<Sketchup::Face:0x0000000021dddad0> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_316  valid = true leaf = #<Sketchup::Face:0x0000000021ddd5f8> root = Group_comp
its a drawing element Sketchup::Face Face_entityID_322  valid = true leaf = #<Sketchup::Face:0x0000000021ddd198> root = Group_comp
=> #<Sketchup::Entities:0x0000000021dda8d0>

leaf is always empty when group or component is the last item of instancePath

I commented this line #vis = ent.model.drawing_element_visible?(pa), otherwise I always had this error Leaf must be a type of Sketchup::Drawingelement

as leaf return nil, this is perhaps the reason why we have this error with ent.model.drawing_element_visible?(pa) when the last item of the instancePath is a group or a component

tomboul26 commented 3 months ago

also the documentation https://ruby.sketchup.com/Sketchup/Model.html#drawing_element_visible%3F-instance_method is wrong

module Example

  def self.instance?(entity)
    entity.is_a?([Sketchup](https://ruby.sketchup.com/Sketchup.html)::[ComponentInstance](https://ruby.sketchup.com/Sketchup/ComponentInstance.html)) || entity.is_a?([Sketchup](https://ruby.sketchup.com/Sketchup.html)::[Group](https://ruby.sketchup.com/Sketchup/Group.html))
  end

  # Walk the visible entities in the model, taking into account
  # "DrawHiddenGeometry" and "DrawHiddenObjects" rendering options.
  def self.walk(entities, transformation = [IDENTITY](https://ruby.sketchup.com/top-level-namespace.html#IDENTITY-constant), path = [], &block)
    entities.each { |entity|
      entity_path = path + [entity]
      next unless entity.model.drawing_element_visible?(entity_path)
      block.call(entity, transformation, path)
      if instance?(entity)
        child_entities = entity.definition.entities
        child_transformation = transformation * entity.transformation
        walk(child_entities, child_transformation, entity_path, &block)
      end
    }
  end

end

model = [Sketchup](https://ruby.sketchup.com/Sketchup.html).[active_model](https://ruby.sketchup.com/Sketchup.html#active_model-class_method)
Example.walk(model.entities) do |entity, transformation, path|
  # Do something to every visible entity in the model...
end

before entity.model.drawing_element_visible?(entity_path) you have to test if the leaf of instancePath is nil or not

thomthom commented 3 months ago

A leaf is a drawing element that is not a containers (group / component). That's per design. Whether that was the best choice is a different matter, but if we change this now it might break existing extensions. But we can at least improve documentation.

thomthom commented 3 months ago

Btw, avoid string comparison of class names when checking types - it quickly becomes a bottleneck.

  # instead of:
  if(cm != "Group" && entity.respond_to?(:definition))
      entity = entity.definition
  end

  # prefer type checking:
  if entity.is_a?(Sketchup::Group) && entity.respond_to?(:definition)
      entity = entity.definition
  end
tomboul26 commented 3 months ago

Thank you thomthom

A leaf is a drawing element that is not a containers (group / component). That's per design. Whether that was the best choice is a different matter, but if we change this now it might break existing extensions. But we can at least improve documentation.

Yes you have to change the documentation for leaf instance method :

The leaf of an instance path is the last element which can be any entity that can be represented in the model. This is normally a Drawingelement, but could be a Vertex. An instance can also be a leaf.

because it's seem that "group" or "component" are also Drawingelement.

group.is_a?(Sketchup::Drawingelement) or component.is_a?(Sketchup::Drawingelement) return true

There si also a problem with the use of drawing_element_visible?(entity_path) you have to correct the documentation (this fabulous documentation very well done šŸ‘ šŸ‘ šŸ‘ ) but also the example "Traversing every visible entity in the model".

Btw, avoid string comparison of class names when checking types - it quickly becomes a bottleneck.

Yes you're absolutely right, i'm total beginner in ruby sletchup and this getName function was only used to display the name of a group or component on the sketchup ruby console, I had to indicate it here so that everyone can run the code I gave