Overview

The IFC mesher transforms IFC geometry and topology definitions into triangular meshes for display in OpenGL, WebGL and DirectX or for export to formats like STL, AMF, and 3MF.

The simplest way to make meshes is to call ifcx_mesh_make_all(), which makes meshes for all possible things in a file, then go through the model and call ifcx_mesh_find() on IfcRepresentationItem objects to get the computed mesh if one exists. Find return an IfcxMesh, which is a subclass of RoseMesh with extra functions to return the IFC source objects for faces and edges.

Alternatively, you can call ifcx_mesh_make() on an individual IfcProduct to create meshes for its geometry with any voids relations on the product. You can also call the make function on an individual representation item but this does not apply voids relations.

Meshing can take place in the background using multiple threads for speed and versions the "make" functions allow control over when the work must be completed.

The example below creates meshes for everything in a file. Then loops over all of the representatation items, and if a mesh was created for it, prints the mesh size.

RoseDesign * design;

// index the IFC assembly and style information so the mesher can
// find voids relations and color information for solids and faces.
ifcx_asm_tag(design);
ifcx_present_tag(design);

// create meshes for everything in the design
ifcx_mesh_make_all(design);

// Print all of the meshes.  A real program would walk the IFC product
// structure and print the meshes in context with the products that they
// are associated with.
RoseCursor objs;
RoseObject * obj;

objs.traverse(d);
objs.domain(ROSE_DOMAIN(IfcRepresentation));
while ((obj=objs.next()) != 0)
{
    IfcRepresentation * rep = ROSE_CAST(IfcRepresentation,obj);
    SetOfIfcRepresentationItem * items = rep->Items();
    unsigned i,sz;

    for (i=0, sz=items->size(); i<sz; i++)
    {
	IfcRepresentationItem * it = items->get(i);

	IfcxMesh * mesh = ifcx_mesh_find(it, rep);
	if (mesh)
	{
            printf (Item #%lu: mesh with %u triangles\n,
	            it->entity_id(), mesh->getFacetCount());
	}
    }
}

ifcx_mesh_can_make()

int ifcx_mesh_can_make(
	IfcRepresentationItem * item,
	IfcRepresentation * rep = 0
	);

The ifcx_mesh_can_make() function returns non-zero if a mesh can be created from the representation item, such as an IfcFacetedBrep or IfcExtrudedAreaSolid. It returns zero if no mesh can be made from the item, such as an IfcAxis2Placement3D. It also returns zero for an IfcMappedItem, since it is the underlying item that is meshed, not the mapping.

ifcx_mesh_delete()

void ifcx_mesh_delete(
	IfcRepresentationItem * item,
	IfcRepresentation * rep = 0,
	RoseMeshNotify * notify = 0
	);

The ifcx_mesh_delete() function deletes any mesh associated with the given representation item. If a representation or notify object are provided, only a mesh created with matching values will be deleted.

This is a wrapper around rose_mesh_cache_delete()

ifcx_mesh_delete_all()

void ifcx_mesh_delete_all(
	RoseDesign * design,
	RoseMeshNotify * notify = 0
	);

The ifcx_mesh_delete_all() function is an alias for rose_mesh_delete_all().

It deletes all meshes associated with data objects in the design. This function is not usually needed because all meshes are automatically deleted when the design is deleted.

ifcx_mesh_detach()

IfcxMesh * ifcx_mesh_detach(
	IfcRepresentationItem * item,
	IfcRepresentation * rep = 0,
	RoseMeshNotify * notify = 0
	);

The ifcx_mesh_detach() function finds the effective mesh associated with the given representation item. The association is removed and it becomes the responsibility of the caller to delete the mesh object when finished.

This is a wrapper around rose_mesh_cache_find() followed by rose_mesh_cache_detach()

ifcx_mesh_estimated_bounds()

int ifcx_mesh_estimated_bounds(
	RoseBoundingBox * bbox,
	IfcFace * face,
	IfcRepresentation * rep
	);

The ifcx_mesh_estimated_bounds() function sets the bounding box to the bounds computed from the trim curves of a face.

ifcx_mesh_find()

IfcxMesh * ifcx_mesh_find(
    IfcRepresentationItem * item,
    IfcRepresentation * rep = 0,
    RoseMeshNotify * notify = 0
    );

The ifcx_mesh_find() function finds the effective mesh associated with the given representation item. If a representation or notify object are provided, only a mesh created with matching values will be returned.

This is a wrapper around rose_mesh_cache_find() that will only return an instance of the IfcxMesh subtype.

ifcx_mesh_job_init()

IfcxMesh * ifcx_mesh_job_init(
	IfcRepresentationItem * item,
	IfcRepresentation * rep,
	RoseMeshOptions * opts,
	RoseMeshNotify * notify
	);

The ifcx_mesh_job_init() function is for internal use. Use one of the ifcx_mesh_make() functions instead. This creates a mesh and associates it with a representation item. It does not check if a mesh is already associated with the representation item and does not start the meshing process.

ifcx_mesh_make()

// Mesh all geometry associated with a product, including product void relations
void ifcx_mesh_make(
	IfcProduct * p,
	RoseMeshOptions * opts = 0,
	RoseMeshNotify * notify = 0
	);

// Mesh one representation item
IfcxMesh * ifcx_mesh_make(
	IfcRepresentationItem * item,
	IfcRepresentation * rep,
	RoseMeshOptions * opts = 0,
	RoseMeshNotify * notify = 0
	);

The ifcx_mesh_make() functions create meshes for IFC geometry. The first version builds meshes for all of the geometry associated with a product, including calculating boolean removals for voids relations. This must be done at the product level because voids are relationships between products.

The assembly structure must have been previously indexed by calling ifcx_asm_tag() for voids relations to be found. The IFC style information should also have been previously indexed by calling ifcx_present_tag() for the meshes to have color information for solids, faces, and material.

A second version of the function calls ifcx_mesh_find() and returns an existing mesh for an IFC geometry object if present. If one is not present and can be made, it starts a meshing job, possibly using several threads, and waits until the mesh is ready. This operates on a single geometry object and does not apply any product voids relations.

An options structure can be provided to control tolerance and other values used by the mesher. Meshing can take place in the background using multiple threads for speed. The three versions of this function allow control over when the work must be completed.

A notify object can be provided to distinguish meshes made for a particular purpose and to get update messages as portions of meshes become available.

// read design
ifcx_asm_tag(design);		// index assemblies
ifcx_present_tag(design);	// index color/transparency

// mesh all products
ifcx_mesh_make_all(design);

// OR mesh one product
IfcProduct * p;
ifcx_mesh_make(p);

IfcRepresentationItem * it;
IfcRepresentation * rep;
IfcxMesh * mesh;

// everything now completed, use them
for (i=0; i<sz; i++) {
    mesh = ifcx_mesh_find(get_item(i), get_rep(i));
    // do something -- ready to use
}

ifcx_mesh_make_all()

void ifcx_mesh_make_all(          // return when done 
	RoseDesign * design,
	RoseMeshOptions * opts = 0,
	RoseMeshNotify * notify = 0
	);

void ifcx_mesh_make_all_start(    // return after starting 
	RoseDesign * design,
	RoseMeshOptions * opts = 0,
	RoseMeshNotify * notify = 0
	);

void ifcx_mesh_make_all_job(      // return immediately 
	RoseDesign * design,
	RoseMeshOptions * opts = 0,
	RoseMeshNotify * notify = 0
	);

The ifcx_mesh_make_all() functions create meshes for everything in the design. An options structure can be provided to control tolerance and other values used by the mesher. After this function is called, ifcx_mesh_find() will return an existing mesh object for everything that can be meshed.

The three versions of this function allow control over when the work must be completed and follow the convention used by ifcx_mesh_make().

The ifcx_mesh_make_all() function will return when all meshes are complete. The ifcx_mesh_make_all_start() function will begin work on all meshes and then return. Call wait or wait all when you completed data. The ifcx_mesh_make_all_job() function prepares everything but you must start start and wait for meshes individually.

A notify object can be provided to distinguish meshes made for a particular purpose and to get update messages as portions of meshes become available.

RoseDesign * design;
IfcxMesh * mesh;

// prepare all meshes
ifcx_mesh_make_all(design);

// everything now completed, use them
for (i=0; i<sz; i++) {
    mesh = ifcx_mesh_find(get_item(i), get_rep(i));
    // do something -- ready to use
}


// ANOTHER POSSIBIILITY
// start background work on all meshes
ifcx_mesh_make_all_start(design);

( do other setup) 

// block until all meshes are ready
rose_mesh_job_wait_all();

ifcx_mesh_make_job()

IfcxMesh * ifcx_mesh_make_job(      // return immediately 
	IfcRepresentationItem * item,
	IfcRepresentation * rep,
	RoseMeshOptions * opts = 0,
	RoseMeshNotify * notify = 0
	);

The ifcx_mesh_make_job() function calls ifcx_mesh_find() and returns an existing mesh for an IFC geometry object if present. If one is not present and can be made, it creates an empty mesh and prepares a meshing job which can be started at a later time with the rose_mesh_job_start() and rose_mesh_job_wait() functions.

ifcx_mesh_make_start()

// Mesh all geometry associated with a product, including product void relations
void ifcx_mesh_make_start(
	IfcProduct * p,
	RoseMeshOptions * opts = 0,
	RoseMeshNotify * notify = 0
	);

// Mesh one representation item
IfcxMesh * ifcx_mesh_make_start(
	IfcRepresentationItem * item,
	IfcRepresentation * rep,
	RoseMeshOptions * opts = 0,
	RoseMeshNotify * notify = 0
	);

The ifcx_mesh_make_start() functions create meshes in the same manner as ifcx_mesh_make(), but return immediately rather than waiting for the meshes to complete. Call rose_mesh_job_wait() on a particular mesh when you need to guarantee a completed mesh.