All of the example code snippets found below are extracted from the examples
folder.
- Attention
- The sample code provided here and in the
examples
folder is provided as-is. You are free to use it and adapt it as needed.
Attaching attributes to B-Rep faces and edges
This snippet was extracted from examples/attrib/main.cpp
.
for( auto const part : parts ) {
A3DRootBaseAttributeAdd( part, const_cast<char*>("part"), const_cast<char*>("foobar") );
for( auto const brep_model : brep_models ) {
A3DVector3dData scale;
A3D_INITIALIZE_DATA( A3DVector3dData, scale );
scale.m_dX = scale.m_dY = scale.m_dZ = ( topo_context->m_bHaveScale ? topo_context->m_dScale : 1. );
for( auto const face : faces ) {
ts3d::attachFaceAttributes( face, scale );
}
for( auto const edge : edges ) {
auto const &edge_instances = edge_instance_path_map[edge];
for( auto const &edge_instance : edge_instances ) {
auto const face_it = std::find_if( std::begin( edge_instance ), std::end( edge_instance ), [](A3DEntity *ntt ) {
});
if( std::end( edge_instance ) != face_it ) {
owning_faces.insert( *face_it );
}
}
ts3d::attachEdgeAttributes( edge, owning_faces, scale );
}
}
}
Constructing a Bill of Materials
This snippet was extracted from examples/bom/main.cpp
.
for( auto part_definition : part_definitions ) {
auto const part_name = part_instance.
getName().empty() ?
"<unknown>" : part_instance.getName();
std::cout << "\"" << part_name << "\": "
<< "(" << instance_paths[part_definition].size()
<< " instance"
<< (1 != instance_paths[part_definition].size() ? "s)" : ")")
<< std::endl;
}
Comparing tessellation to B-Rep
This snippet was extracted from examples/compare_brep_tess/main.cpp
.
for( auto ri_instance : ri_instances ) {
if( SHOULD_FORCE_RETESSELLATION ) {
A3DRWParamsTessellationData tess_params;
A3D_INITIALIZE_DATA( A3DRWParamsTessellationData, tess_params );
tess_params.m_eTessellationLevelOfDetail = kA3DTessLODMedium;
tess_params.m_bAccurateTessellation = false;
CheckResult( A3DRiRepresentationItemComputeTessellation( ri_instance.back(), &tess_params ) );
}
auto const brep_scale = context_d->m_bHaveScale ? context_d->m_dScale : 1.;
if( nullptr == tess3d ) {
continue;
}
auto const n_tess_faces = tess3d->
faceSize();
if( n_tess_faces != brep_faces.size() ) {
std::cerr << "FAILURE: n_tess_faces (" << n_tess_faces << ") != brep_faces.size() (" << brep_faces.size() << ")" << std::endl;
failure_encountered = true;
}
auto const max_face_idx = std::min( static_cast<std::size_t>( n_tess_faces ), brep_faces.size() );
for( auto face_idx = 0u; face_idx < max_face_idx; ++face_idx ) {
auto const tess_face = tess3d->getIndexMeshForFace( face_idx );
auto const brep_face = brep_faces[face_idx].back();
auto const surface = face_d->m_pSurface;
auto const tess_loops = tess_face.loops();
auto const n_tess_loops = tess_loops.size();
if( n_tess_loops != brep_loops.size() ) {
std::cerr << "FAILURE: n_tess_loops (" << n_tess_loops << ") != brep_loops.size() (" << brep_loops.size() << ")" << std::endl;
failure_encountered = true;
}
auto const max_loop_idx = std::min( n_tess_loops, brep_loops.size() );
for( auto loop_idx = 0u; loop_idx < max_loop_idx; ++loop_idx ) {
auto const &tess_loop = tess_loops[loop_idx];
auto const n_tess_edges = tess_loop._edges.size();
if( n_tess_edges != brep_coedges.size() ) {
std::cerr << "FAILURE: n_tess_edges ( " << n_tess_edges << ") != brep_coedges.size() (" << brep_coedges.size() << ")" << std::endl;
failure_encountered = true;
}
auto const max_edge_idx = std::min(n_tess_edges, brep_coedges.size());
for( auto edge_idx = 0u; edge_idx < max_edge_idx; ++edge_idx ) {
auto const &tess_edge = tess_loop._edges[edge_idx];
auto const brep_coedge = brep_coedges[edge_idx];
A3DCrvBase const *curve = nullptr;
CheckResult( A3DTopoEdgeGetOrCompute3DCurve( brep_model_d->m_pBrepData, coedge_d->m_pEdge, &curve ) );
A3DIntervalData interval;
A3D_INITIALIZE_DATA( A3DIntervalData, interval );
if( edge_d->m_bHasTrimDomain ) {
interval = edge_d->m_sInterval;
} else {
CheckResult( A3DCrvGetInterval( curve, &interval ) );
}
for( auto const vertex_index : tess_edge._vertices ) {
A3DVector3dData pt;
A3D_INITIALIZE_DATA( A3DVector3dData, pt );
pt.m_dX = tess3d->coords()[vertex_index] / brep_scale;
pt.m_dY = tess3d->coords()[vertex_index + 1] / brep_scale;
pt.m_dZ = tess3d->coords()[vertex_index + 2] / brep_scale;
auto min_curve_distance = std::numeric_limits<double>::max();
A3DUns32 n_solutions = 0u;
A3DDouble *parameters = nullptr, *distances = nullptr;
if( CheckResult( A3DCrvProjectPoint( curve, &pt, &n_solutions, ¶meters, &distances ) ) ) {
for( auto n_solution = 0u; n_solution < n_solutions; ++n_solution ) {
if( distances[n_solution] < min_curve_distance ) {
min_curve_distance = distances[n_solution];
}
}
CheckResult( A3DCrvProjectPoint( nullptr, &pt, &n_solutions, ¶meters, &distances ) );
}
auto const curve_error = min_curve_distance;
if( curve_error > TOLERANCE ) {
std::cerr << "FAILURE: [Distance to curve] " << curve_error << " > " << TOLERANCE << std::endl;
failure_encountered = true;
}
auto min_surf_distance = std::numeric_limits<double>::max();
A3DVector2dData *face_solutions = nullptr;
if( CheckResult( A3DSurfProjectPoint( surface, &pt, &n_solutions, &face_solutions, &distances ) ) ) {
for( auto n_solution = 0u; n_solution < n_solutions; ++n_solution ) {
if( distances[n_solution] < min_surf_distance ) {
min_surf_distance = distances[n_solution];
}
}
CheckResult( A3DSurfProjectPoint( nullptr, &pt, &n_solutions, &face_solutions, &distances ) );
}
auto const surface_error = min_surf_distance;
if( surface_error > TOLERANCE ) {
std::cerr << "FAILURE: [Distance to surface] " << surface_error << " > " << TOLERANCE << std::endl;
failure_encountered = true;
}
}
}
}
}
}
How to access Markup/PMI Linked Items
This snippet was extracted from examples/pmi_linked_items/main.cpp
.
std::cout << "This file contains " << all_markups.size() << " markups." << std::endl;
for( auto const this_markup : all_markups ) {
if( ! linked_items.empty() ) {
std::cout << "Mark-up: \"" << markup_instance.getName() << "\" [" << markup_instance.getType() << "]" << std::endl;
}
for( auto const linked_item : linked_items ) {
std::cout <<
"Unhandled reference type: " <<
ts3d::Instance( { d->m_pReference } ).getType() << std::endl;
continue;
}
auto const topo_brep_data_ptr = t->m_pBrepData;
if( nullptr == topo_brep_data_ptr ) {
continue;
}
switch( t->m_eTopoItemType ) {
case kA3DTypeTopoConnex:
{
auto const connex =
ts3d::getLeafInstances( topo_brep_data_ptr, t->m_eTopoItemType )[t->m_puiAdditionalIndexes[0]];
std::cout << "The linked connex contains " << d->m_uiShellSize << " shell(s)." << std::endl;
}
break;
case kA3DTypeTopoShell:
{
auto const shell =
ts3d::getLeafInstances( topo_brep_data_ptr, t->m_eTopoItemType )[t->m_puiAdditionalIndexes[0]];
std::cout << "The linked shell contains " << d->m_uiFaceSize << " face(s)." << std::endl;
}
break;
case kA3DTypeTopoFace:
{
auto const face =
ts3d::getLeafInstances( topo_brep_data_ptr, t->m_eTopoItemType )[t->m_puiAdditionalIndexes[0]];
std::cout <<
"The linked face has a surface type: " <<
ts3d::Instance( { d->m_pSurface } ).getType() <<
" and contains " << d->m_uiLoopSize <<
" loop(s)." << std::endl;
auto const part_def = getPartDefinition( this_markup );
if( nullptr != part_def ) {
if( ! ri_brep_models.empty() ) {
auto const ri_brep_model = ri_brep_models.back();
if( auto const tess = std::dynamic_pointer_cast<ts3d::Tess3DInstance>( ri_instance.getTessellation() ) ) {
auto const index_mesh = tess->getIndexMeshForFace( t->m_puiAdditionalIndexes[0] );
std::cout << "The face's tessellation contains " << index_mesh.vertices().size()/3u << " triangles." << std::endl;
}
}
}
}
break;
case kA3DTypeTopoEdge:
case kA3DTypeTopoCoEdge:
{
auto const face = faces[t->m_puiAdditionalIndexes[0]].back();
auto const loop = loops[t->m_puiAdditionalIndexes[1]].back();
auto const coedge = coedges[t->m_puiAdditionalIndexes[2]].back();
std::cout <<
"The linked coedge has a curve type: " <<
ts3d::Instance( { curve } ).getType() << std::endl;
auto const part_def = getPartDefinition( this_markup );
if( nullptr != part_def ) {
if( ! ri_brep_models.empty() ) {
auto const ri_brep_model = ri_brep_models.back();
if( auto const tess = std::dynamic_pointer_cast<ts3d::Tess3DInstance>( ri_instance.getTessellation() ) ) {
auto const index_mesh = tess->getIndexMeshForFace( t->m_puiAdditionalIndexes[0] );
auto const tess_loop = index_mesh.loops()[t->m_puiAdditionalIndexes[1]];
auto const tess_edge = tess_loop._edges[t->m_puiAdditionalIndexes[2]];
std::cout << "The edge's tessellation contains " << tess_edge._vertices.size() << " points." << std::endl;
}
}
}
}
break;
case kA3DTypeTopoUniqueVertex:
case kA3DTypeTopoMultipleVertex:
{
auto const face = faces[t->m_puiAdditionalIndexes[0]].back();
auto const loop = loops[t->m_puiAdditionalIndexes[1]].back();
auto const edge = edges[t->m_puiAdditionalIndexes[2]].back();
auto const vertex = vertices[t->m_puiAdditionalIndexes[3]].back();
if( kA3DTypeTopoUniqueVertex == vertex_type ) {
std::cout << "The linked vertex is at (" << d->m_sPoint.m_dX << ", " << d->m_sPoint.m_dY << ", " << d->m_sPoint.m_dZ << ")" << std::endl;
} else {
std::cout << "The linked vertex has multiple positions at: " << std::endl;
for( auto idx = 0u; idx < d->m_uiSize; ++idx ) {
std::cout << "(" << d->m_pPts[idx].m_dX << ", " << d->m_pPts[idx].m_dY << ", " << d->m_pPts[idx].m_dZ << ")" << std::endl;
}
}
}
break;
default:
break;
}
}
std::cout << std::endl;
}
Print curve types that make up a wire body
This snippet was extract from examples/wire_body_curve_types/main.cpp
.
std::cout << "There are " << wire_edges.size() << " single wire edges." << std::endl;
for( auto const we : wire_edges ) {
std::cout <<
"Curve: " << i.
getType();
if (d->m_bHasTrimDomain) {
std::cout << " [" << d->m_sInterval.m_dMin << ", " << d->m_sInterval.m_dMax << "]";
}
std::cout << std::endl;
switch (i.leafType()) {
case kA3DTypeCrvPolyLine:
{
std::cout << curve_data->m_uiSize << " pts" << std::endl;
}
break;
case kA3DTypeCrvCircle:
{
auto const &o = curve_data->m_sTrsf.m_sOrigin;
std::cout << "Center (" << o.m_dX << ", " << o.m_dY << ", " << o.m_dZ << ")" << std::endl;
std::cout << "Radius: " << curve_data->m_dRadius << std::endl;
}
break;
case kA3DTypeCrvEllipse:
{
auto const &o = curve_data->m_sTrsf.m_sOrigin;
std::cout << "Center (" << o.m_dX << ", " << o.m_dY << ", " << o.m_dZ << ")" << std::endl;
std::cout << "X Radius: " << curve_data->m_dXRadius << std::endl;
std::cout << "Y Radius: " << curve_data->m_dYRadius << std::endl;
}
break;
case kA3DTypeCrvLine:
{
auto const &o = curve_data->m_sTrsf.m_sOrigin;
auto const &x = curve_data->m_sTrsf.m_sXVector;
auto const &y = curve_data->m_sTrsf.m_sYVector;
std::cout << "Origin (" << o.m_dX << ", " << o.m_dY << ", " << o.m_dZ << ")" << std::endl;
std::cout << "X (" << x.m_dX << ", " << x.m_dY << ", " << x.m_dZ << ")" << std::endl;
std::cout << "Y (" << y.m_dX << ", " << y.m_dY << ", " << y.m_dZ << ")" << std::endl;
}
break;
}
}
Write an OBJ file
This snippet was extract from examples/obj/main.cpp
.
for( auto ri_instance : ri_instances ) {
if( !ri.Instance::getNetShow() ) {
continue;
}
if( nullptr == tess3d ) {
continue;
}
obj_file << "o " << name << std::endl;
auto const net_style = ri.Instance::getNetStyle();
auto const mtl = getMaterial( net_style );
if( !mtl.empty() ) {
obj_file << "usemtl " << mtl << std::endl;
}
auto const exchange_coords = tess3d->coords();
auto const n_coords = tess3d->coordsSize();
for( auto idx = 0u; idx < n_coords; idx += 3 ) {
auto v = net_matrix *
ts3d::VectorType( exchange_coords[idx], exchange_coords[idx+1], exchange_coords[idx+2], 1. );
obj_file << "v " << v(0) << " " << v(1) << " " << v(2) << std::endl;
}
auto const exchange_normals = tess3d->normals();
auto const n_normals = tess3d->normalsSize();
for( auto idx = 0u; idx < n_normals; idx += 3 ) {
auto n = net_matrix *
ts3d::VectorType( exchange_normals[idx], exchange_normals[idx+1], exchange_normals[idx+2], 0. );
obj_file << "vn " << n(0) << " " << n(1) << " " << n(2) << std::endl;
}
for( auto idx = 0u; idx < tess3d->faceSize(); ++idx ) {
auto const face_mesh = tess3d->getIndexMeshForFace( idx );
auto const n_vertices = face_mesh.vertices().size();
for(auto idx = 0u; idx < n_vertices; ++idx ) {
if( 0 == idx % 3 ) {
obj_file << std::endl << "f";
}
obj_file << " -" << (n_coords - face_mesh.vertices()[idx])/3 << "//-" << (n_normals - face_mesh.normals()[idx])/3;
}
}
obj_file << std::endl;
}
Print the product structure
These snippers were extracted from examples/print_structure/main.cpp
void printNameAndRecurse( A3DEntity *owner, unsigned int level ) {
for( auto idx = 0u; idx < level; ++idx ) {
std::cout << '\t';
}
level++;
for( auto const child : children ) {
printNameAndRecurse( child, level );
}
}
This function is used in the body of main as follows.
loader.Import( i );
if( nullptr == loader.m_psModelFile ) {
std::cerr << "The specified file could not be loaded." << std::endl;
return -1;
}
auto level = 0u;
printNameAndRecurse( loader.m_psModelFile, level );