Overview

The IFC Faceting library provides the following functions. Along with the IFCMesh and IFCMeshBuilder classes, these test whether an IFC object can be faceted, facet the item, and search for previously created facet data. Other functions interface the IFC axis placements and points RoseMath transform and vector operations.

ifcmesh_can_facet_item()

int ifcmesh_can_facet_item(
	IfcRepresentation * rep,
	IfcRepresentationItem * item
	);

The ifcmesh_can_facet_item() function tests whether a representation item can be faceted. This should be used as a boolean value, but there are three possible return values:

Certain types (shell-based surface models and face-based surface models) are normally faceted into a single mesh, but have sub-shells that could be meshed separately if desired. See ifcmesh_get_shell_items() for more discussion on this.

ifcmesh_facet_item()

IFCMesh * ifcmesh_facet_item(
	IfcRepresentation * rep,
	IfcRepresentationItem * item
	);

The ifcmesh_facet_item() function creates facets for a representation item and and returns a mesh. It is the responsibility of the caller to delete the mesh when finished.

We recommend using ifcmesh_worker_render() instead, because you can control the meshing options, it meshes in the background, caches data, and can be used to schedule meshing of several things in parallel.

ifcmesh_find_shell()

const IFCMesh * ifcmesh_find_shell(
	IfcRepresentation * rep,
	IfcRepresentationItem * it,
	RoseMeshWorkerContext * wc = 0
	);

The ifcmesh_find_shell() function returns a previously-created mesh associated with a representation item if one exists, or null otherwise. This function simply calls ifcmesh_worker_find_builder() and returns the shell associated with it.

ifcmesh_get_estimated_bounding_box()

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

The ifcmesh_get_estimated_bounding_box() function calculates the bounding box of a face using the trim curves.

ifcmesh_get_faceinfo()

const RoseMeshFaceInfo * ifcmesh_get_faceinfo(
	const RoseMeshFace * face
	);

const RoseMeshFaceInfo * ifcmesh_get_faceinfo(
	const RoseMesh * fs,
	unsigned face_idx
	);

The ifcmesh_get_faceinfo() function finds the IFC face property associated with a mesh face. If no face property is present, the function will return NULL. The property holds rendering status information.

ifcmesh_get_ifc_face()

IfcRepresentationItem * ifcmesh_get_ifc_face(
	const RoseMeshFace * face
	);
    
IfcRepresentationItem * ifcmesh_get_ifc_face(
	const RoseMesh * fs,
	unsigned face_idx
	);

The ifcmesh_get_ifc_face() function finds the IFC face for a mesh face. If no face association is present, the function will return NULL. Face associations are only created for a connected face set in an IfcFaceBasedSurfaceModel or other face-based solid.

ifcmesh_get_placement()

void ifcmesh_get_placement(
    RoseXform& xform,
    IfcObjectPlacement * place
    );

The ifcmesh_get_placement() function initializes a matrix from the information extracted from an IFC object placement.

ifcmesh_get_precision()

double ifcmesh_get_precision(
	IfcRepresentation * rep
	);

The ifcmesh_get_precision() function gets the precision from an IFC representation context, with appropriate behavior for omitted and derived values.

ifcmesh_get_shell_item()

IfcRepresentationItem * ifcmesh_get_shell_item(
	RoseAggregate * agg,
	unsigned idx
	);

The ifcmesh_get_shell_item() function returns representation items from the collection returned by ifcmesh_get_shell_items(). This collection is not strongly typed, and may contain nested SELECT instances of the representation items. The function compensates for that and returns a properly typed value.

ifcmesh_get_shell_items()

RoseAggregate * ifcmesh_get_shell_items(
	IfcRepresentationItem * items
	);

Certain types (shell-based surface models and face-based surface models) are normally faceted into a single mesh, but have sub-shells that could be meshed separately if desired. The ifcmesh_get_shell_items() function returns a collection of representation items for these sub-shells. The ifcmesh_get_shell_item() function returns individual elements of this collection cast as a representation item type.

Prior to the v19 release, shell and face-based surface models had to be handled in this way. The faceter now creates a single mesh from all of the sub-shells, but you can still facet them individually if you prefer the old behavior. The ifcmesh_can_facet_item()() function has a special return value to indicate these types. This function used to be called ifcmesh_get_facet_items, but was changed in the v18 release.

unsigned i,sz;
IfcRepresentationItem * it = /* some item */;
RoseAggregate * subs = ifcmesh_get_shell_items(it);

for (i=0, sz=sub_items->size(); i<sz; i++) {
        IfcRepresentationItem * child = ifcmesh_get_shell_item(subs,i);

    /* process child item */
}

ifcmesh_get_style()

IfcStyledItemVec * ifcmesh_get_style(
	IfcRepresentationItem * item
	);

The ifcmesh_get_style() function gets the IfcStyledItem instances that reference a given representation_item. Before this function can be called, you must call ifcmesh_resolve_styles() first. This provides a fast and efficient way to traverse the back pointers from IfcStyledItem to a IfcRepresentationItem.

ifcmesh_get_surface_color()

unsigned ifcmesh_get_surface_color(
	IfcRepresentationItem * item
	);

The ifcmesh_get_surface_color() function returns the color associated with a given IfcRepresentation item. Before this function can be called, you must call ifcmesh_resolve_styles first.

The color is returned as a 24-bit RGB value. If the value is written in hexadecimal, the value has the following format: 0x00rrggbb (See below for a decoding example.)


/* Then loading the file: */
RoseDesign * des = ROSE.findDesign(...);
ifcmesh_resolve_styles(des);

    :
    :

/* to get the color */
IfcRepresentationItem * rep_item = ....;
unsigned color = ifcmesh_get_surface_color(rep_item);

double r = (color & 0xff0000) >> 16;
double g = (color & 0x00ff00) >> 8;
double b = (color & 0x0000ff);

printf ("r=%x g=%x b=%x\n", r, g, b);

ifcmesh_has_bad_topology()

int ifcmesh_has_bad_topology(
	IfcRepresentationItem * it
	);

The ifcmesh_has_bad_topology() function returns a flag that returns true if the IFC geometry is a face-based model with no explicit topology to indicate inside/outside.

ifcmesh_make_shell()


const IFCMesh * ifcmesh_make_shell(
	IfcRepresentation * rep,
	IfcRepresentationItem * it,
	RoseMeshWorkerContext * wc
	);

The ifcmesh_make_shell() function returns a previously-created mesh associated with a representation item if one exists. If one does not exist, a new mesh is created and associated with the object. A mesh may be rendered with multiple threads, but this function blocks until it is finished. Use the worker functions instead to submit many shells for faceting and then wait for the results. This function simply calls ifcmesh_worker_make_builder(), waits for any rendering to complete, and returns the shell associated with it.

Use ifcmesh_find_shell() to test if a mesh is present without creating anything.

ifcmesh_resolve_styles()

void ifcmesh_resolve_styles(
	RoseDesign * des
	);

The ifcmesh_resolve_styles() function traverses a RoseDesign and annotates it internally so that the IfcStyledItem instances can be found by ifcmesh_get_style and ifcmesh_get_surface_color functions.

ifcmesh_vec_put()

int ifcmesh_vec_put(
	double xyz[],
	IfcCartesianPoint * pt
	);
int ifcmesh_vec_put(
        RosePoint& xyz,
	IfcCartesianPoint * pt
	);

int ifcmesh_vec_put(
	double xyz[],
	IfcVertex * v
	);
int ifcmesh_vec_put(
        RosePoint& xyz,
	IfcVertex * v
	);

int ifcmesh_vec_put(
	double ijk[],
	IfcDirection * dir
	);
int ifcmesh_vec_put(
        RoseDirection& ijk,
	IfcDirection * dir
	);

int ifcmesh_vec2d_put(
	double xy[],
	IfcCartesianPoint * pt
	);
int ifcmesh_vec2d_put(
        RosePoint2D& xy,
	IfcCartesianPoint * pt
	);

int ifcmesh_vec2d_put(
	double ij[],
	IfcDirection * dir
	);
int ifcmesh_vec2d_put(
        RoseDirection2D& ij,
& ij,
	IfcDirection * dir
	);

The ifcmesh_vec_put() function is an IFC-specific version of the rose_vec_put() function. It extracts coordinate or direction data from an IFC object and assigns it to all three elements of an array, a RoseDirection, or a RosePoint. The function returns nonzero if the assignment succeeded or zero if there was a problem. The ifcmesh_vec2d_put() versions extract a 2D result.

With a cartesian point, the coordinates list is extracted. If the point or coordinates list are null, or if the list does not contain enough coordinates, zero will be substituted for the missing values. The assignment will always succeed unless it is passed a null destination array.

RosePoint dst_pt;
IfcCartesianPoint * pt = get_some_point();

ifcmesh_vec_put(dst_pt, pt);

With a direction, the ratios list is extracted. If the direction or list are null, or if the list does not contain enough ratios, zero will be substituted for the missing values. The assignment will always succeed unless it is passed a null destination array. Use rose_vec_is_zero() to test for missing direction data.

RoseDirection dst_dir;
IfcDirection * dir = get_some_dir();

ifcmesh_vec_put(dst_dir, dir);
if (rose_vec_is_zero(dst_dir))
        printf ("MISSING DIRECTION DATA!!\n");

rose_vec_normalize(dst_dir);  // if you want normalized data

With a vertex, the function will cast it to a IfcVertexPoint and set the array from the cartesian point referenced as the vertex_geometry. The function will set the array to all zeros and return zero if the vertex is not a IfcVertexPoint, or of the vertex_geometry is missing or not a cartesian point.

RosePoint dst_pt;
IfcVertex * vtx = get_some_topology();

if (!ifcmesh_vec_put(dst_pt, vtx))
        printf ("BAD VERTEX DATA!!\n");

ifcmesh_worker_find_builder()

IFCMeshBuilder * ifcmesh_worker_find_builder(
	IfcRepresentation * rep,
	IfcRepresentationItem * item,
	RoseMeshWorkerContext * context = 0
	);

The ifcmesh_worker_find_builder() function returns an existing mesh builder for faceting the given context, representation, and item, or null if one has not been created. If the context is omitted, the function returns the first builder found. Use ifcmesh_worker_make_builder() to search for the mesh builder and create it if it does not yet exist.

ifcmesh_worker_is_design_queued()

int ifcmesh_worker_is_design_queued(
	RoseDesign * des,
	RoseMeshWorkerContext * context
	);

The ifcmesh_worker_is_design_queued() function returns true if ifcmesh_worker_render_design() has already been called on the given design.

ifcmesh_worker_make_builder()

IFCMeshBuilder * ifcmesh_worker_make_builder(
	IfcRepresentation * rep,
	IfcRepresentationItem * item,
	RoseMeshWorkerContext * context
	);

The ifcmesh_worker_make_builder() function creates or returns an existing mesh builder for faceting the given context, representation, and item. If one exists, it is returned, otherwise a new builder is created and cached with the representation_item for future use. The ifcmesh_worker_find_builder() function just looks for the mesh builder but does not create one.

ifcmesh_worker_render()

int ifcmesh_worker_render(
	IfcRepresentation * rep,
	IfcRepresentationItem * item,
	RoseMeshWorkerContext * context
	);

The ifcmesh_worker_render() function calls ifcmesh_worker_make_builder() to find or create a builder, and then rose_mesh_worker_render() to submit it to the processing queue.

ifcmesh_worker_render_design()

void ifcmesh_worker_render_design(
	RoseDesign * des,
	RoseMeshWorkerContext * context,
	int force = 0   /* render the design, even it it has already been done*/
	);

The ifcmesh_worker_render_design() function creates workers for all of the shells in a design and submits them to the processing queue. Afterwards, you can find the mesh for a particular shell by calling ifcmesh_worker_find_builder() and getting the mesh from that with IFCMeshBuilder::getIfcMesh().

RoseDesign * d;
RoseMeshWorkerContext context;
RoseMeshOptions facet_opts;
context.setFacetOptions(&facet_opts);

// create meshes for everything in the design
ifcmesh_worker_render_design(d, &context);
rose_mesh_worker_wait_all();

ifcmesh_worker_wait()

const IFCMesh * ifcmesh_worker_wait(
	IfcRepresentation * rep,
	IfcRepresentationItem * item,
	RoseMeshWorkerContext * context,
	int flush=1
	);

The ifcmesh_worker_wait() function finds the builder for the given context, representation, and item, and calls rose_mesh_worker_wait() to block until faceting of the item is complete.

ifcmesh_xform_compose()

void ifcmesh_xform_compose(
	RoseXform& result,
	const RoseXform& xform,
	IfcCartesianTransformationOperator * op
	);

void ifcmesh_xform_compose(
	RoseXform& xform,
	IfcCartesianTransformationOperator * op
	);

void ifcmesh_xform_compose(
	RoseXform& result,
	const RoseXform& xform,
	IfcAxis2Placement * ap
	);

void ifcmesh_xform_compose(
	RoseXform& xform,
	IfcAxis2Placement * ap
	);

The ifcmesh_xform_compose() function calls rose_xform_compose() to transform a matrix with a matrix built from an IFC object. The result is calculated by matrix multiplication orig_xform * ifx_obj_xform.

ifcmesh_xform_put()

int ifcmesh_xform_put(
	double xf[16],
	IfcAxis2Placement3D * ap
	);
int ifcmesh_xform_put(
        RoseXform& xf,
	IfcAxis2Placement3D * ap
	);

int ifcmesh_xform_put(
	double xf[16],
	IfcAxis2Placement * ap
	);
int ifcmesh_xform_put(
        RoseXform& xf,
	IfcAxis2Placement * ap
	);

int ifcmesh_xform_put(
	double xf[16],
	IfcAxis1Placement * ap
	);
int ifcmesh_xform_put(
        RoseXform& xf,
	IfcAxis1Placement * ap
	);

int ifcmesh_xform_put(
	double xf[16],
	IfcCartesianTransformationOperator * cto
	);
int ifcmesh_xform_put(
        RoseXform& xf,
	IfcCartesianTransformationOperator * cto
	);

int ifcmesh_xform_put(
	double xf[16],
	IfcObjectPlacement * place
	);
int ifcmesh_xform_put(
        RoseXform& xf,
	IfcObjectPlacement * place
	);


int ifcmesh_xform2d_put(
	double xf[9],
	IfcAxis2Placement2D * ap
	);
int ifcmesh_xform2d_put(
        RoseXform2D& xf,
	IfcAxis2Placement2D * ap
	);

The ifcmesh_xform_put() function extracts coordinates and axis directions from IFC placement or transform data and constructs a RoseXform or array of sixteen doubles. The function returns nonzero if the assignment succeeded or zero if there was a problem.

When assigning an axis placement, the result will be a normalized, right-handed, orthogonal matrix with all defaults handled properly as with rose_xform_put_dirs().

When assigning an cartesian transformation operator, the result will be normalized during construction but may then have a scaling factor applied. It is also possible for a CTO to encode a left-handed coordinate system. This function extracts data from the IFC instance and calls rose_xform_put_cto().

When assigning an IfcObjectPlacement, the function composes any transforms necessary for "relative to" placements.