If you are developing software to read .3dm files, you might also read instance, or block, definitions, in addition to standard geometry.
Instances are named groups of objects that act as a single object in your model. They are useful for repeated objects such as symbols or components. Instances save you time since you can reuse the components instead of re-drawing them each time. An advantage of using instances for repeated content is that using instances requires less memory.
The definition of a instance object is represented by the ON_InstanceDefinition
class. An instance definition object maintains list of object ids.
An ON_InstanceRef
is a reference to an instance definition, long with transformation to apply to the definition.
If you are referencing the Example_read
sample included with the openNURBS toolkit, then after the 3DM file has been read, you can traverse a model’s instance references as follows:
ONX_Model model = ...
ON_wString writer;
ON_TextLog dump(writer);
dump.SetIndentSize(2);
ONX_ModelComponentIterator it(model, ON_ModelComponent::Type::InstanceDefinition);
const ON_ModelComponent* model_component = nullptr;
for (model_component = it.FirstComponent(); nullptr != model_component; model_component = it.NextComponent())
{
const ON_InstanceDefinition* idef = ON_InstanceDefinition::Cast(model_component);
if (nullptr != idef)
DumpInstanceDefinition(model, idef->Id(), dump, true);
}
wprintf(static_cast<const wchar_t*>(writer));
In this example, DumpInstanceDefinition
is a recursive function, as it is possible to construct instance references whose definition geometry contains one or more instance references.
static void DumpInstanceDefinition(ONX_Model& model, const ON_UUID& idef_id, ON_TextLog& dump, bool bRoot)
{
const ON_ModelComponentReference& idef_component_ref = model.ComponentFromId(ON_ModelComponent::Type::InstanceDefinition, idef_id);
const ON_InstanceDefinition* idef = ON_InstanceDefinition::Cast(idef_component_ref.ModelComponent());
if (idef)
{
dump.Print(L"Instance definition %d = %s\n", idef->Index(), static_cast<const wchar_t*>(idef->Name()));
const ON_SimpleArray<ON_UUID>& geometry_id_list = idef->InstanceGeometryIdList();
const int geometry_id_count = geometry_id_list.Count();
if (geometry_id_count > 0)
{
dump.PushIndent();
for (int i = 0; i < geometry_id_count; i++)
{
const ON_ModelComponentReference& model_component_ref = model.ComponentFromId(ON_ModelComponent::Type::ModelGeometry, geometry_id_list[i]);
const ON_ModelGeometryComponent* model_geometry = ON_ModelGeometryComponent::Cast(model_component_ref.ModelComponent());
if (nullptr != model_geometry)
{
const ON_Geometry* geometry = model_geometry->Geometry(nullptr);
if (nullptr != geometry)
{
const ON_InstanceRef* iref = ON_InstanceRef::Cast(geometry);
if (iref)
{
DumpInstanceDefinition(model, iref->m_instance_definition_uuid, dump, false);
}
else
{
ON_wString type = ObjectTypeToString(geometry->ObjectType());
dump.Print(L"Object %d = %s\n", i, static_cast<const wchar_t*>(type));
}
}
}
}
dump.PopIndent();
}
}
}
static ON_wString ObjectTypeToString(ON::object_type type)
{
ON_wString rc = L"Unknown";
switch (type)
{
case ON::object_type::point_object: rc = L"point"; break;
case ON::pointset_object: rc = L"pointset"; break;
case ON::curve_object: rc = L"curve"; break;
case ON::surface_object: rc = L"surface"; break;
case ON::brep_object: rc = L"brep"; break;
case ON::mesh_object: rc = L"mesh"; break;
case ON::layer_object: rc = L"layer"; break;
case ON::material_object: rc = L"material"; break;
case ON::light_object: rc = L"light"; break;
case ON::annotation_object: rc = L"annotation"; break;
case ON::userdata_object: rc = L"userdata"; break;
case ON::instance_definition: rc = L"instance_definition"; break;
case ON::instance_reference: rc = L"instance_reference"; break;
case ON::text_dot: rc = L"text_dot"; break;
case ON::grip_object: rc = L"grip"; break;
case ON::detail_object: rc = L"detail"; break;
case ON::hatch_object: rc = L"hatch"; break;
case ON::morph_control_object: rc = L"morph_control"; break;
case ON::subd_object: rc = L"subd"; break;
case ON::cage_object: rc = L"cage"; break;
case ON::phantom_object: rc = L"phantom"; break;
case ON::clipplane_object: rc = L"clipplane"; break;
case ON::extrusion_object: rc = L"extrusion"; break;
}
return rc;
}