Skip to content

Commit c3c53ac

Browse files
committed
Multithreaded splitfaces code
1 parent 090cb8a commit c3c53ac

File tree

4 files changed

+87
-52
lines changed

4 files changed

+87
-52
lines changed

inc/cjCreator.cpp

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -604,13 +604,17 @@ void CJGeoCreator::SplitInAndOuterHFaces(const TopoDS_Shape& inputFaces, std::ve
604604

605605
TopoDS_Solid CJGeoCreator::extrudeFace(const TopoDS_Face& evalFace, bool downwards, double splittingFaceHeight)
606606
{
607+
if (evalFace.IsNull()) { return {}; }
608+
TopoDS_Face projectedFace = helperFunctions::projectFaceFlat(evalFace, splittingFaceHeight);
609+
610+
if (projectedFace.IsNull()) { return {}; }
611+
607612
BRep_Builder brepBuilder;
608613
BRepBuilderAPI_Sewing brepSewer(SettingsCollection::getInstance().precision());
609614
TopoDS_Shell shell;
610615
brepBuilder.MakeShell(shell);
611616
TopoDS_Solid solidShape;
612617
brepBuilder.MakeSolid(solidShape);
613-
TopoDS_Face projectedFace = helperFunctions::projectFaceFlat(evalFace, splittingFaceHeight);
614618

615619
std::vector<TopoDS_Wire> wireList;
616620
TopoDS_Wire outerWire = BRepTools::OuterWire(evalFace);
@@ -711,6 +715,9 @@ TopoDS_Solid CJGeoCreator::extrudeFace(const TopoDS_Face& evalFace, bool downwar
711715

712716
gp_Pnt p0 = helperFunctions::getFirstPointShape(evalFace);
713717
gp_Vec normal = helperFunctions::computeFaceNormal(evalFace);
718+
719+
if (normal.Magnitude() < 1e-6) { return{}; }
720+
714721
Handle(Geom_Plane) plane = new Geom_Plane(p0, normal);
715722

716723
Handle(Geom_Plane) planeFlat = new Geom_Plane(gp_Pnt(0, 0, splittingFaceHeight), gp_Vec(0, 0, -1));
@@ -959,11 +966,42 @@ std::vector<TopoDS_Face> CJGeoCreator::getSplitFaces(
959966
const std::vector<TopoDS_Face>& inputFaceList,
960967
bgi::rtree<std::pair<BoostBox3D, TopoDS_Face>, bgi::rstar<25>> cuttingFaceIdx
961968
)
969+
{
970+
// split the range over cores
971+
int coreUse = SettingsCollection::getInstance().threadcount();
972+
if (coreUse > inputFaceList.size())
973+
{
974+
while (coreUse > inputFaceList.size()) { coreUse /= 2; }
975+
}
976+
977+
int splitListSize = static_cast<int>(floor(inputFaceList.size() / coreUse));
978+
979+
std::vector<std::thread> threadList;
980+
std::mutex processMutex;
981+
std::vector<TopoDS_Face> outSplitFaceList;
982+
983+
for (size_t i = 0; i < coreUse; i++)
984+
{
985+
auto startIdx = inputFaceList.begin() + i * splitListSize;
986+
auto endIdx = (i == coreUse - 1) ? inputFaceList.end() : startIdx + splitListSize;
987+
988+
std::vector<TopoDS_Face> sublist(startIdx, endIdx);
989+
threadList.emplace_back([this, &outSplitFaceList, &processMutex, sublist, &cuttingFaceIdx]() { getSplitFaces(outSplitFaceList, processMutex, sublist, cuttingFaceIdx); });
990+
}
991+
992+
for (auto& thread : threadList) {
993+
if (thread.joinable()) {
994+
thread.join();
995+
}
996+
}
997+
return outSplitFaceList;
998+
}
999+
1000+
void CJGeoCreator::getSplitFaces(std::vector<TopoDS_Face>& outFaceList, std::mutex& listMutex, const std::vector<TopoDS_Face>& inputFaceList, bgi::rtree<std::pair<BoostBox3D, TopoDS_Face>, bgi::rstar<25>> cuttingFaceIdx)
9621001
{
9631002
double precision = SettingsCollection::getInstance().precisionCoarse();
9641003

9651004
// split the topfaces with the cutting faces
966-
std::vector<TopoDS_Face> splitFaceList;
9671005
for (const TopoDS_Face& currentRoofSurface : inputFaceList)
9681006
{
9691007
if (currentRoofSurface.IsNull()) { continue; }
@@ -973,7 +1011,9 @@ std::vector<TopoDS_Face> CJGeoCreator::getSplitFaces(
9731011

9741012
if (qResult.size() <= 1)
9751013
{
976-
splitFaceList.emplace_back(currentRoofSurface);
1014+
listMutex.lock();
1015+
outFaceList.emplace_back(currentRoofSurface);
1016+
listMutex.unlock();
9771017
continue;
9781018
}
9791019

@@ -986,7 +1026,7 @@ std::vector<TopoDS_Face> CJGeoCreator::getSplitFaces(
9861026
{
9871027
TopoDS_Face currentSplitter = cuttingFace;
9881028
if (currentSplitter.IsEqual(currentRoofSurface)) { continue; }
989-
1029+
9901030
divider.AddTool(currentSplitter);
9911031
}
9921032
divider.Perform();
@@ -997,10 +1037,12 @@ std::vector<TopoDS_Face> CJGeoCreator::getSplitFaces(
9971037
TopExp::MapShapes(subFace, TopAbs_EDGE, aMap);
9981038

9991039
if (aMap.Size() <= 2) { continue; }
1000-
splitFaceList.emplace_back(subFace);
1040+
listMutex.lock();
1041+
outFaceList.emplace_back(subFace);
1042+
listMutex.unlock();
10011043
}
10021044
}
1003-
return splitFaceList;
1045+
return;
10041046
}
10051047

10061048
std::vector<TopoDS_Face> CJGeoCreator::getVisTopSurfaces(const std::vector<TopoDS_Face>& faceList, double lowestZ, const std::vector<TopoDS_Face>& bufferSurfaceList)
@@ -1117,7 +1159,7 @@ std::vector<TopoDS_Shape> CJGeoCreator::computePrisms(const std::vector<TopoDS_F
11171159

11181160
// remove dub faces and split them
11191161
bgi::rtree<std::pair<BoostBox3D, TopoDS_Face>, bgi::rstar<25>> cuttingFaceIdx = indexUniqueFaces(splittingfaceIdx);
1120-
for (const auto& [currentBox, currentFace] : cuttingFaceIdx) { toBesSplitFaceList.emplace_back(currentFace); }
1162+
for (const auto& [currentBox, currentFace] : cuttingFaceIdx) { toBesSplitFaceList.emplace_back(currentFace);}
11211163

11221164
std::vector<TopoDS_Face> splitFaceList = getSplitFaces(toBesSplitFaceList, cuttingFaceIdx);
11231165

@@ -1615,33 +1657,6 @@ void CJGeoCreator::printTime(std::chrono::steady_clock::time_point startTime, st
16151657
}
16161658

16171659

1618-
bool CJGeoCreator::surfaceIsIncapsulated(const TopoDS_Face& innerSurface, const TopoDS_Shape& encapsulatedShape) //TODO: might be dup
1619-
{
1620-
double precision = SettingsCollection::getInstance().precision();
1621-
for (TopExp_Explorer explorer(encapsulatedShape, TopAbs_FACE); explorer.More(); explorer.Next())
1622-
{
1623-
const TopoDS_Face& outerSurface = TopoDS::Face(explorer.Current());
1624-
bool encapsulated = true;
1625-
1626-
for (TopExp_Explorer explorer2(innerSurface, TopAbs_VERTEX); explorer2.More(); explorer2.Next())
1627-
{
1628-
const TopoDS_Vertex& vertex = TopoDS::Vertex(explorer2.Current());
1629-
1630-
if (!helperFunctions::pointOnShape(outerSurface, BRep_Tool::Pnt(vertex)))
1631-
{
1632-
encapsulated = false;
1633-
break;
1634-
}
1635-
}
1636-
if (encapsulated)
1637-
{
1638-
return true;
1639-
}
1640-
}
1641-
return false;
1642-
}
1643-
1644-
16451660
TopoDS_Face makeFace(const std::vector<gp_Pnt>& voxelPointList, const std::vector<int>& pointFaceIndx) {
16461661
gp_Pnt p0(voxelPointList[pointFaceIndx[0]]);
16471662
gp_Pnt p1(voxelPointList[pointFaceIndx[1]]);

inc/cjCreator.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,14 @@ class CJGeoCreator {
187187
bgi::rtree<std::pair<BoostBox3D, TopoDS_Face>, bgi::rstar<25>> cuttingFaceIdx
188188
);
189189

190+
/// splits the surfaces with extruded solid copies
191+
void getSplitFaces(
192+
std::vector<TopoDS_Face>& outFaceList,
193+
std::mutex& listMutex,
194+
const std::vector<TopoDS_Face>& inputFaceList,
195+
bgi::rtree<std::pair<BoostBox3D, TopoDS_Face>, bgi::rstar<25>> cuttingFaceIdx
196+
);
197+
190198

191199
// generic shape simplification code
192200

@@ -206,9 +214,6 @@ class CJGeoCreator {
206214
/// outputs the time delta between the start and end time
207215
void printTime(std::chrono::steady_clock::time_point startTime, std::chrono::steady_clock::time_point endTime);
208216

209-
/// checks if surface is encapsulated by another shape
210-
bool surfaceIsIncapsulated(const TopoDS_Face& innerSurface, const TopoDS_Shape& encapsulatedShape);
211-
212217
/// create spatial index for voxels and lookup
213218
void populateVoxelIndex(
214219
bgi::rtree<std::pair<BoostBox3D, std::shared_ptr<voxel>>, bgi::rstar<25>>* voxelIndex,

inc/helper.cpp

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,6 +1265,31 @@ bool helperFunctions::coplanarOverlapping(const TopoDS_Face& leftFace, const Top
12651265

12661266
}
12671267

1268+
bool helperFunctions::surfaceIsIncapsulated(const TopoDS_Face& innerSurface, const TopoDS_Face& outerSurface)
1269+
{
1270+
double precision = SettingsCollection::getInstance().precision();
1271+
for (TopExp_Explorer explorer(innerSurface, TopAbs_VERTEX); explorer.More(); explorer.Next())
1272+
{
1273+
const TopoDS_Vertex& vertex = TopoDS::Vertex(explorer.Current());
1274+
gp_Pnt currentPoint = BRep_Tool::Pnt(vertex);
1275+
1276+
if (!pointOnFace(outerSurface, currentPoint) && !pointOnWire(outerSurface, currentPoint))
1277+
{
1278+
return false;
1279+
}
1280+
}
1281+
1282+
std::vector<gp_Pnt> pointList = getPointListOnFace(innerSurface);
1283+
for (const gp_Pnt& currentPoint : pointList)
1284+
{
1285+
if (!pointOnFace(outerSurface, currentPoint))
1286+
{
1287+
return false;
1288+
}
1289+
}
1290+
return true;
1291+
}
1292+
12681293
double helperFunctions::tVolume(const gp_Pnt& p, const std::vector<gp_Pnt>& vertices) {
12691294
const gp_Pnt& vert0 = vertices[0];
12701295
const gp_Pnt& vert1 = vertices[1];
@@ -1808,6 +1833,7 @@ TopoDS_Face helperFunctions::projectFaceFlat(const TopoDS_Face& theFace, double
18081833
if (!outerWire.Closed()) { return TopoDS_Face(); }
18091834

18101835
TopoDS_Wire flattenedWire = projectWireFlat(outerWire, height);
1836+
if (flattenedWire.IsNull()) { return TopoDS_Face(); }
18111837
flattenedWire.Orientation(TopAbs_FORWARD);
18121838

18131839
BRepBuilderAPI_MakeFace faceMaker(plane, flattenedWire, precision);
@@ -1817,7 +1843,6 @@ TopoDS_Face helperFunctions::projectFaceFlat(const TopoDS_Face& theFace, double
18171843
if (currentWire.IsEqual(outerWire)) { continue; }
18181844
TopoDS_Wire currentFlatWire = projectWireFlat(currentWire, height);
18191845
currentFlatWire.Orientation(TopAbs_REVERSED);
1820-
18211846
BRepBuilderAPI_MakeFace faceMaker2(currentFlatWire);
18221847
if (!faceMaker2.IsDone()) { continue; }
18231848
TopoDS_Face innerFace = faceMaker2.Face();
@@ -1832,7 +1857,6 @@ TopoDS_Face helperFunctions::projectFaceFlat(const TopoDS_Face& theFace, double
18321857
}
18331858
flatFace = faceMaker.Face();
18341859
}
1835-
18361860
fixFace(&flatFace);
18371861
return flatFace;
18381862
}
@@ -2606,18 +2630,7 @@ std::vector<TopoDS_Face> helperFunctions::planarFaces2Outline(const std::vector<
26062630
bool useFace = true;
26072631
for (size_t j = i + 1; j < flattenedAreaFaceList.size(); j++)
26082632
{
2609-
bool freeFace = false;
2610-
TopoDS_Face otherFace = flattenedAreaFaceList[j].second;
2611-
for (TopExp_Explorer vertExpl(currentFace, TopAbs_VERTEX); vertExpl.More(); vertExpl.Next()) {
2612-
TopoDS_Vertex currentVertex = TopoDS::Vertex(vertExpl.Current());
2613-
gp_Pnt currentPoint = BRep_Tool::Pnt(currentVertex);
2614-
if (!pointOnFace(otherFace, currentPoint) && !pointOnWire(otherFace, currentPoint))
2615-
{
2616-
freeFace = true;
2617-
break;
2618-
}
2619-
}
2620-
if (!freeFace)
2633+
if (surfaceIsIncapsulated(currentFace, flattenedAreaFaceList[j].second))
26212634
{
26222635
useFace = false;
26232636
break;

inc/helper.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#define USE_IFC2x3
1+
#define USE_IFC4x3
22

33
#ifdef USE_IFC2x3
44
#define IfcSchema Ifc2x3
@@ -187,6 +187,8 @@ struct helperFunctions{
187187
static bool faceFaceNeighbour(const TopoDS_Face& leftFace, const TopoDS_Face& rightFace);
188188
/// check if coplanar surfaces overlap based on points
189189
static bool coplanarOverlapping(const TopoDS_Face& leftFace, const TopoDS_Face& rightFace);
190+
/// checks if surface is encapsulated by another shape
191+
static bool surfaceIsIncapsulated(const TopoDS_Face& innerSurface, const TopoDS_Face& outerSurface);
190192

191193
/// line surface intersection related code
192194

0 commit comments

Comments
 (0)