Hi Author,
Let me offer a few comments:
1. The most likely reason of the behavior you observe is data races for face triangulations or edge polygons. Even if the code looks correct it may work incorrectly on shared data. The races for face triangulations can be if you have IsSame() or IsPartner() faces, i.e. sharing the same BRep_TFace which contains Poly_Triangulation.
Races for edges (which can be much more probable) can be if your faces share edges. For instance, if you explored a shell (solid) and put into this vector you will certainly have races.
There are tools to detect data races so you might want to try. We prefer Intel Inspector XE but perhaps your choice could be different.
To run BRepMeshes in parallel you must ensure no shared edges between individual elements. Below is the excerpt from our code from the test library to quickly check that. Feel free to reuse/adjust.
2. When you triangulate faces independently you will get a non water-tight mesh as boundaries will be meshed individually. Perhaps that's not an issue but make sure you understand that.
3. Using FastDiscret vs IncrementalMesh should have no impact, as the latter just calls the former. So even if you currently do not observe sporadic crashes/hangs/etc, this could be pure luck.
4. You might want to revisit your approach depending on what objective you are trying to achieve and what data you are working with. If you work with solids or shells, just invoke BRepMesher on it with enabled SetParallel() and let it do the work. If you work with individual shapes (faces) first sort them out into individual groups without shared subshapes between each other and then apply your code.
Good luck!
Commenter-1
//This is our specific API, ignore that and just get the idea.
/*! Returns true if there are at least two bodies that have common subshapes.*/
bool HasSharedTopology (const ModelData_Model& theModel)
{
ModelG_WriterHelper::PartVecType aVec;
ModelData_SceneGraphElementAnyFilter aFilter;
ModelG_WriterHelper::AccumulateParts (theModel, aFilter, aVec, true /*theUniqueParts*/);
cadex_unordered_set<TopoDS_Shape>::type aSet; //std::unordered_set with hasher/equal based on using TopoDS::IsSame(), you can substitute with TopTools_MapOfShape
bool aHasBRep = false;
const TopLoc_Location aLoc0;
for (size_t i = 0; i < aVec.size(); ++i) {
const auto& aPart = aVec[i].first;
auto aBRep = aPart.BRepRepresentation();
if (!aBRep)
continue;
aHasBRep = true;
const auto& aBodyList = aBRep.Get();
for (size_t j = 0; j < aBodyList.Size(); ++j) {
const auto& aBody = aBodyList[j];
const TopoDS_Shape& aShape = aBody;
TopTools_IndexedMapOfShape aSMap, aPMap; //map of unique shapes (not IsSame, IsPartner)
TopExp::MapShapes (aShape, aSMap);
for (int k = 1; k <= aSMap.Extent(); ++k) {
aPMap.Add (aSMap(k).Located (aLoc0));
}
//now check if aPMap contains any subshapes already available in aSet
for (int k = 1; k <= aPMap.Extent(); ++k) {
const auto& aSubshape = aPMap (k);
auto r = aSet.insert (aSubshape);
if (!r.second)
return true;
}
}
}
if (!aHasBRep)
return false; //ensure that at least one B-Rep was encountered
return false;
}