Skip to content

Commit b3f8094

Browse files
authored
Merge pull request #1632 from Creoox/addCapsInSectionedSurface
Add front and back caps in webifc::geometry::SectionedSurface
2 parents 0f1e606 + 99615b6 commit b3f8094

File tree

5 files changed

+93
-9
lines changed

5 files changed

+93
-9
lines changed

src/cpp/web-ifc/geometry/IfcGeometryProcessor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ namespace webifc::geometry
328328
case schema::IFCSECTIONEDSOLID:
329329
case schema::IFCSECTIONEDSURFACE:
330330
{
331-
auto geom = SectionedSurface(_geometryLoader.GetCrossSections3D(expressID));
331+
auto geom = SectionedSurface(_geometryLoader.GetCrossSections3D(expressID),EPS_SMALL);
332332
mesh.transformation = glm::dmat4(1);
333333
// TODO: this is getting problematic.....
334334
_expressIDToGeometry[expressID] = geom;

src/cpp/web-ifc/geometry/operations/bim-geometry/geometry.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ namespace bimGeometry
137137

138138
for (size_t i = 0; i < numFaces; i++)
139139
{
140-
planeData.push_back(-1);
140+
planeData.push_back(UINT32_MAX);
141141
}
142142

143143
Vec centroid = Vec(0, 0, 0);

src/cpp/web-ifc/geometry/operations/bim-geometry/geometry.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace bimGeometry {
2626
Face GetFace(size_t index) const;
2727
void buildPlanes();
2828
size_t AddPlane(const glm::dvec3 &normal, double d);
29-
void AddFace(glm::dvec3 a, glm::dvec3 b, glm::dvec3 c, uint32_t pId = -1);
29+
void AddFace(glm::dvec3 a, glm::dvec3 b, glm::dvec3 c, uint32_t pId = UINT32_MAX);
3030
void AddFace(uint32_t a, uint32_t b, uint32_t c, uint32_t pId);
3131
void AddPoint(glm::dvec4& pt, glm::dvec3& n);
3232
void AddPoint(const glm::dvec3& pt, const glm::dvec3& n);

src/cpp/web-ifc/geometry/operations/bim-geometry/utils.h

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,7 +1227,7 @@ namespace bimGeometry
12271227
return geom;
12281228
}
12291229

1230-
inline Geometry SectionedSurface(std::vector<std::vector<glm::dvec3>> profiles)
1230+
inline Geometry SectionedSurface(std::vector<std::vector<glm::dvec3>> profiles, bool buildCaps, double eps=0.0)
12311231
{
12321232
Geometry geom;
12331233

@@ -1275,12 +1275,94 @@ namespace bimGeometry
12751275
{
12761276
for (size_t j = 0; j < indices.size() - 2; j += 4)
12771277
{
1278-
geom.AddFace(indices[j], indices[j + 1], indices[j + 2], -1);
1279-
geom.AddFace(indices[j + 2], indices[j + 1], indices[j + 3], -1);
1278+
geom.AddFace(indices[j], indices[j + 1], indices[j + 2], UINT32_MAX);
1279+
geom.AddFace(indices[j + 2], indices[j + 1], indices[j + 3], UINT32_MAX);
12801280
}
12811281
}
12821282
}
12831283

1284+
if (buildCaps && profiles.size() >= 2)
1285+
{
1286+
// Process the first and last profiles for caps
1287+
for (size_t capIdx = 0; capIdx < profiles.size(); capIdx += profiles.size() - 1)
1288+
{
1289+
std::vector<glm::dvec3>& profile = profiles[capIdx];
1290+
if (profile.size() < 3) // Need at least 3 points for a polygon
1291+
{
1292+
continue;
1293+
}
1294+
1295+
// Convert profile to std::vector<Point> for bestProjection
1296+
std::vector<Point> poly3D;
1297+
for (const auto& p : profile)
1298+
{
1299+
poly3D.push_back({ p.x, p.y, p.z });
1300+
}
1301+
1302+
// Determine the best projection plane
1303+
Projection proj = bestProjection(poly3D);
1304+
1305+
// Convert profile to std::vector<std::vector<Point>> for projectTo2D
1306+
std::vector<std::vector<Point>> poly3DVec = { poly3D };
1307+
1308+
// Project to 2D
1309+
std::vector<std::vector<Point>> poly2D = projectTo2D(poly3DVec, proj);
1310+
1311+
// Convert to std::vector<std::vector<std::array<double, 2>>> for earcut
1312+
std::vector<std::vector<std::array<double, 2>>> polygon(1);
1313+
for (const auto& pt : poly2D[0])
1314+
{
1315+
polygon[0].push_back({ pt[0], pt[1] });
1316+
}
1317+
1318+
// Run earcut triangulation (assuming mapbox/earcut.hpp is included)
1319+
std::vector<uint32_t> capIndices = mapbox::earcut<uint32_t>(polygon);
1320+
1321+
// Compute average normal for the cap
1322+
glm::dvec3 avgNormal(0.0);
1323+
for (size_t i = 0; i < profile.size(); ++i)
1324+
{
1325+
glm::dvec3 p1 = profile[i];
1326+
glm::dvec3 p2 = profile[(i + 1) % profile.size()];
1327+
glm::dvec3 edge = p2 - p1;
1328+
glm::dvec3 crossVec = glm::cross(edge, glm::dvec3(0.0, 0.0, 1.0));
1329+
if (glm::length(crossVec) > eps)
1330+
{
1331+
avgNormal += glm::normalize(crossVec);
1332+
}
1333+
}
1334+
if (glm::length(avgNormal) < eps)
1335+
{
1336+
avgNormal = glm::dvec3(0.0, 0.0, 1.0);
1337+
}
1338+
else
1339+
{
1340+
avgNormal = glm::normalize(avgNormal);
1341+
}
1342+
1343+
// Add cap points to geometry with appropriate normal
1344+
uint32_t baseIndex = geom.numPoints;
1345+
for (const auto& p : profile)
1346+
{
1347+
// Use reversed normal for first cap (outward facing)
1348+
glm::dvec3 normal = (capIdx == 0) ? -avgNormal : avgNormal;
1349+
geom.AddPoint(p, normal);
1350+
}
1351+
1352+
// Add triangular faces for the cap
1353+
for (size_t i = 0; i < capIndices.size(); i += 3)
1354+
{
1355+
uint32_t i0 = baseIndex + capIndices[i];
1356+
uint32_t i1 = baseIndex + capIndices[i + 1];
1357+
uint32_t i2 = baseIndex + capIndices[i + 2];
1358+
// Reverse indices for first cap to ensure correct winding
1359+
if (capIdx == 0)
1360+
geom.AddFace(i0, i2, i1, UINT32_MAX);
1361+
else
1362+
geom.AddFace(i0, i1, i2, UINT32_MAX);
1363+
}
1364+
}
1365+
}
12841366
return geom;
12851367
}
12861368

src/cpp/web-ifc/geometry/operations/geometryutils.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ namespace webifc::geometry
6262
{
6363
if (i >= ifcGeom.planeData.size())
6464
{
65-
ifcGeom.planeData.push_back(-1);
65+
ifcGeom.planeData.push_back(UINT32_MAX);
6666
}
6767
}
6868
}
@@ -329,7 +329,7 @@ namespace webifc::geometry
329329
}
330330
}
331331

332-
inline IfcGeometry SectionedSurface(IfcCrossSections profiles_)
332+
inline IfcGeometry SectionedSurface(IfcCrossSections profiles_, bool buildCaps)
333333
{
334334
spdlog::debug("[SectionedSurface({})]");
335335

@@ -342,10 +342,12 @@ namespace webifc::geometry
342342
{
343343
profile.push_back({profiles_.curves[i].points[j].x, profiles_.curves[i].points[j].y, profiles_.curves[i].points[j].z});
344344
}
345+
345346
profiles.push_back(profile);
346347
}
347348

348-
return ToIfcGeometry(bimGeometry::SectionedSurface(profiles));
349+
IfcGeometry geom = ToIfcGeometry(bimGeometry::SectionedSurface(profiles, buildCaps));
350+
return geom;
349351
}
350352

351353
inline IfcGeometry Extrude(IfcProfile profile, glm::dvec3 dir, double distance, glm::dvec3 cuttingPlaneNormal = glm::dvec3(0), glm::dvec3 cuttingPlanePos = glm::dvec3(0))

0 commit comments

Comments
 (0)