Home > User Guide > Display and User Input > Faceting
Faceting Parts and Reading Facet Data
To facet, call api_set_mesh_manager and either api_facet_entity or api_facet_entities. Spatial provides two versatile mesh managers, LINKED_MESH_MANAGER and LINKED_MESH (derived from SEQUENTIAL_MESH), however, if neither meets your needs, then you may create one. The function "main" is code that demonstrates how to use one of the existing mesh managers, LINKED_MESH_MANAGER. The code also demonstrates how to use refinements, which are optional.
The function get_facet_area reads the facet data created in the function "main". The data created by the mesh manager is passed in the function api_set_mesh_manager. Note that facet data is attached to FACEs as an attribute. The accuracy of the facets is verified by comparing the area of the facets to the area of the surfaces of the part.
#include "acis.hxx" #include "api.hxx" #include "kernapi.hxx" #include "ckoutcom.hxx" #include "transf.hxx" #include "transfrm.hxx" #include "body.hxx" #include "cstrapi.hxx" #include "af_api.hxx" #include "LinkedMeshManager.hxx" #include "idx_mesh.hxx" static void init_acis(); static void term_acis(); static double get_facet_area(ENTITY* entity); //---------------------------------------------------------- // If argv[1] exists, it is assumed to be a sat file to be tested. // Otherwise, a simple part is constructed and tested. //---------------------------------------------------------- int main( int argc, char *argv[] ) { outcome res; // Standard ACIS initialization. init_acis(); ENTITY_LIST ents; // If a sat file is given, read it. Else, create a cone. if ( argc > 1 ) { // Open the given sat file. FILE *fsat = acis_fopen( argv[1], "r" ); if (!fsat) { printf( "Unable to open given sat file: %s\n", argv[1] ); exit( -1 ); } // Restore the entities within. res = api_restore_entity_list( fsat, TRUE /* text */, ents ); check_outcome( res ); // Done with the file handle. acis_fclose( fsat ); } else { // Create a cone. Apply some different kinds of transforms to make it interesting. BODY * cone = NULL; res = api_solid_cylinder_cone( SPAposition(0, 0, 0), SPAposition(0, 0, 30), 25, 25, 0, NULL, cone ); check_outcome( res ); SPAtransf rotate_xform = rotate_transf(M_PI / 6, SPAvector(0, 1, 0)); SPAtransf scale_xform = scale_transf(2.0); SPAtransf translate_xform = translate_transf(SPAvector(1, 2, 3)); SPAtransf xform = rotate_xform; res = api_transform_entity(cone, xform); check_outcome( res ); ents.add( cone ); } // Create a refinement object. REFINEMENT * ref = 0; res = api_create_refinement( ref ); check_outcome( res ); // Specify a normal tolerance of 15 degrees. Use API blocks because we're // modifying an entity outside the scope of an ACIS api. API_BEGIN ref->set_normal_tol( 15 ); API_END double facet_area = 0; double surf_area = 0; // Use exception blocks to protect against leaks in the event of an // unexpected exception. EXCEPTION_BEGIN MESH_MANAGER * MM = NULL; EXCEPTION_TRY // Use the linked-mesh mesh manager. This is recommended as a // good general purpose mesh manager. (Also the same mesh manager used // by the Scheme Aide Toolkit.) // MM = ACIS_NEW INDEXED_MESH_MANAGER; MM = ACIS_NEW LINKED_MESH_MANAGER; res = api_set_mesh_manager( MM ); check_outcome( res ); // Facet each entity. ENTITY *ent; for ( ents.init(); ent = ents.next(); ) { // Set the refinement for this entity. res = api_set_entity_refinement( ent, ref, FALSE ); check_outcome( res ); // Facet. res = api_facet_entity( ent ); check_outcome( res ); // Compute area of facets. facet_area += get_facet_area(ent); // Compute area of surfaces. double target_tol = 0.001; double real_tol; double curr_surf_area; res = api_ent_area( ent, target_tol, curr_surf_area, real_tol ); check_outcome( res ); surf_area += curr_surf_area; } // Done with the refinement. ref->lose(); EXCEPTION_CATCH_TRUE // Delete the mesh manager. ACIS_DELETE MM; EXCEPTION_END // Print results. double percent_error = (1 - facet_area / surf_area) * 100; printf("Facet area = %lf, surface area = %lf, percent error = %lf%%\n", facet_area, surf_area, percent_error); // Final cleanup. res = api_del_entity_list( ents ); check_outcome( res ); // Standard ACIS termination. term_acis(); // Return 0 if all is okay. // Return 99 if faceting does not approximate the real surface area well enough. return (0 <= percent_error && percent_error <= 1.0) ? 0 : 99; } //---------------------------------------------------------- // Enough to initialize ACIS and the Faceter. //---------------------------------------------------------- static void init_acis() { // Configuring the ACIS memory manager for optimum performance in release // builds; check for leaks in debug builds. base_configuration bc; bc.enable_freelists = TRUE; #ifdef _DEBUG bc.enable_audit_leaks = TRUE; #else bc.enable_audit_leaks = FALSE; #endif logical ib = initialize_base(& bc); if ( !ib ) { printf( "Failed to initialize the base!\n" ); exit( -1 ); } check_outcome( api_start_modeller( 0 ) ); check_outcome( api_initialize_faceter() ); } //---------------------------------------------------------- // Enough to terminate ACIS and the Faceter. //---------------------------------------------------------- static void term_acis() { // For this example, no real need to check for return // values when terminating. Just keep bringing things down. api_terminate_faceter(); api_stop_modeller(); terminate_base(); } double get_facet_area( ENTITY* entity ) { // Returns the area of the indexed or linked facets currently attached to the entity. double area = 0; // Create a list of all of the faces of the entity. ENTITY_LIST faces; api_get_faces( entity, faces ); // Get the transform attached to the body. SPAtransf xform; ENTITY * owner; api_get_owner( entity, owner ); if ( is_BODY(owner) ) { BODY * body; body = (BODY *)owner; if ( body->transform() ) xform = body->transform()->transform(); } // For every face, compute the area. FACE *face; for ( faces.init(); face = (FACE*)(faces.next()); ) { // Find the attribute for facets attached to the face. This is the mesh. MESH * face_mesh = NULL; af_query( (ENTITY*)face, IDX_MESH_APP, IDX_MESH_ID, face_mesh ); if ( face_mesh == NULL ) { printf( "No indexed mesh or linked mesh available for a face\n" ); continue; } SEQUENTIAL_MESH *mesh = (SEQUENTIAL_MESH*)face_mesh; // For every facet (or polygon) compute the area. int polygon_count = mesh->get_num_polygon(); MESH_POLYGON mesh_polygon; mesh->get_first_polygon(mesh_polygon); for ( int polygon_index = 0; polygon_index < polygon_count; polygon_index++ ) { int polynode_count = mesh->get_num_polynode( mesh_polygon ); double polygon_area = 0; // Consider the polygon as a fan of triangles, all sharing one node. // Each triangle is formed by one fixed node and two other consecutive nodes. // Compute area of each triangle (negative areas indicated concavity). // Use the first node as the fixed node. MESH_POLYNODE mesh_polynode; mesh->get_first_polynode( mesh_polygon, mesh_polynode ); const SPAposition & fixed_pos = mesh->get_position( mesh_polynode ); // Make the first edge of the first triangle using a vector. mesh->get_next_polynode( mesh_polynode ); SPAvector prev_edge ( mesh->get_position( mesh_polynode ) - fixed_pos ); prev_edge *= xform; // For every remaining node, create triangles and add up the areas. for ( int polynode_index = 2; polynode_index < polynode_count; polynode_index++ ) { // Make the other edge of the triangle. mesh->get_next_polynode( mesh_polynode ); SPAvector curr_edge ( mesh->get_position( mesh_polynode ) - fixed_pos ); curr_edge *= xform; // Compute the area of the parellelogram. SPAvector n ( prev_edge * curr_edge ); double mag = n.len(); // Total the area (negative areas indicated concavity) polygon_area += mag; // Use this last edge as the first edge of the next triangle. prev_edge = curr_edge; } // Total the areas of all the facets. area += polygon_area; // Get the next facet. mesh->get_next_polygon( mesh_polygon ); } } // Currently we have area of paralleograms. The triangles are half of the paralleograms. area /= 2.0; return area; }
Related topics:
Refinements
Mesh Managers
Step-by-Step Faceting
Discarding or Keeping Facet Data
Faceting Functions and Classes
Faceting Using Scheme[Top]
© 1989-2007 Spatial Corp., a Dassault Systèmes company. All rights reserved.