Filtering unused component with C-API

I’m doing an exporter and I want to avoid component with no instance.

It’s morelike purge_unused but with no change o skp file. I mus keep it as it is.

In my sample I don’t want to export “Steve” for example

If I check model entities

size_t num_instances = 0;
size_t num_groups = 0;
SU_CALL(SUEntitiesGetNumInstances(entities, &num_instances));
SU_CALL(SUEntitiesGetNumGroups(entities, &num_groups));

if I check num_instance != 0 && num_groups != 0, my exporter will not export “Steve” neither the “table” because it’s a group.

Wha is the right approach, recursivity ?

Is this a typo? Or should it read “num_instances” instead of “num_instance”?

it’s just an error when I type the sample.

if (num_instances != 0 && num_groups != 0) {
// don't go further
}

I can simplify my question : how to get non-instanciated component definition with C-API without missing groups ?

Philippe

This returns the number of component instances and groups in the Entities collection. So all you get there is the number of instances in the root of the model (not even recursively.)

Btw, Steve is a component - not a group.

In the Ruby API you can query the component definitions for how many instances it has. It appear that the C API doesn’t expose this…

However, I’m trying to understand how to iterate the model when you export. Are you exporting individual components from the model? Instead of the full model hierarchy?

If you traverse the model hierarchy then you can just export everything you traverse.

If you are traversing the list of definitions and trying to export the ones who have at least an instance - then I can see it being a little less trivial when we don’t expose the instance count. I’ll check with my colleagues to make sure. If we don’t have that property exposed yet you’d have to traverse the whole model tree and count each instance for each definition.

Additionally, unlike the Ruby API which let you traverse the definition list and get images and groups as well - the C API return ONLY components.

But I’m still confused, you said:

Meaning you call SUModelGetEntities? In which case that is the same as Sketchup.active_model.entities in the Ruby API. That is the root context of the model. Note that this entities collection is not a list of ALL the entities in the model. You would have to recurse into the entities of groups and components to get that.

Hello tt,

Thanks very much for your answer. You are totally right.

I think it would be good to add this “detail” in exporter sample skp2xml.
For anyone looking for the solution, here is some pseudo-code :

Explore SU Model entities recursively starting from Model.entities
// in SU SDK

SUEntitiesRef model_entities;
SU_CALL(SUModelGetEntities(model_, &model_entities));
WriteEntities (model_entities);

Hold a global map (key,value) = (definition_name, instance_num)

entities are explored with WriteEntities (recursively):

    void CXmlExporter::WriteEntities(SUEntitiesRef entities) {
    
    	WriteGroups(entities);
    	WriteComponentInstances(entities);
    	WriteGeometries(entities);
    }

  

void CXmlExporter::WriteComponentInstances(SUEntitiesRef entities) {
       SUEntitiesGetInstances(entities, num_instances);
        std::vector<SUComponentInstanceRef> instances(num_instances);
        SUEntitiesGetInstances(entities, num_instances, &instances[0], &num_instances));
        for each entity {
          SUComponentInstanceGetDefinition(instance, &definition));
          SUComponentDefinitionGetName(component_definition, name);
//------------------------------------------------------
              IncrementInstanceCount(name);
//------------------------------------------------------

        }

}

// same with WriteGroups

After the SU Model has been traversed
I export only definition with num_instances > 0

  • Steve is no more exported then
  • Table group is exported

// typedef CMap< std::string, long > CMapOfString2Long;
/ From SU SDK with some customization :

XmlModelInfo {
	std::vector<XmlLayerInfo> layers_;
	std::vector<XmlMaterialInfo> materials_;
	std::vector<XmlComponentDefinitionInfo> definitions_;
        XmlEntitiesInfo		entities_;

	CMapOfString2Long	instances_count_;
    	void IncrementInstanceCount(std::string definition_name) {
    		size_t num_instances(0);
    		if (instances_count_.contains(definition_name))
    			num_instances = instances_count_.at(definition_name);
    
    		instances_count_.bind(definition_name, ++num_instances);
    	}
}

I’ll file an issue internally to expose the instance count for definitions. (SU-31176)

2 Likes