Skip to content

Commit

Permalink
Support for IFCINDEXEDPOLYCURVE 3D issue 420
Browse files Browse the repository at this point in the history
  • Loading branch information
QuimMoya committed Sep 1, 2023
1 parent 90d356f commit 12d9df1
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 5 deletions.
44 changes: 40 additions & 4 deletions src/wasm/geometry/IfcGeometryLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1261,7 +1261,7 @@ namespace webifc::geometry
case schema::IFCINDEXEDPOLYCURVE:
{
_loader.MoveToArgumentOffset(expressID, 0);
auto pts2DRef = _loader.GetRefArgument();
auto ptsRef = _loader.GetRefArgument();

_loader.MoveToArgumentOffset(expressID, 2);

Expand All @@ -1287,15 +1287,15 @@ namespace webifc::geometry
{
if (sg.type == "IFCLINEINDEX")
{
auto pts = ReadIfcCartesianPointList2D(pts2DRef);
auto pts = ReadIfcCartesianPointList2D(ptsRef);
for (auto &pt : sg.indexs)
{
curve.Add(pts[pt - 1]);
}
}
if (sg.type == "IFCARCINDEX")
{
auto pts = ReadIfcCartesianPointList2D(pts2DRef);
auto pts = ReadIfcCartesianPointList2D(ptsRef);
IfcCurve arc = BuildArc3Pt(pts[sg.indexs[0] - 1], pts[sg.indexs[1] - 1], pts[sg.indexs[2] - 1],_circleSegments);
for (auto &pt : arc.points)
{
Expand All @@ -1306,7 +1306,43 @@ namespace webifc::geometry
}
else
{
auto pts = ReadIfcCartesianPointList2D(pts2DRef);
auto pts = ReadIfcCartesianPointList2D(ptsRef);
for (auto &pt : pts)
{
curve.Add(pt);
}
}
}
else if (dimensions == 3)
{
_loader.MoveToArgumentOffset(expressID, 1);
if (_loader.GetTokenType() != parsing::IfcTokenType::EMPTY)
{
auto pnSegment = ReadCurveIndices();
for (auto &sg : pnSegment)
{
if (sg.type == "IFCLINEINDEX")
{
auto pts = ReadIfcCartesianPointList3D(ptsRef);
for (auto &pt : sg.indexs)
{
curve.Add(pts[pt - 1]);
}
}
if (sg.type == "IFCARCINDEX")
{
auto pts = ReadIfcCartesianPointList3D(ptsRef);
IfcCurve arc = Build3DArc3Pt(pts[sg.indexs[0] - 1], pts[sg.indexs[1] - 1], pts[sg.indexs[2] - 1],_circleSegments, EPS_MINISCULE);
for (auto &pt : arc.points)
{
curve.Add(pt);
}
}
}
}
else
{
auto pts = ReadIfcCartesianPointList3D(ptsRef);
for (auto &pt : pts)
{
curve.Add(pt);
Expand Down
76 changes: 76 additions & 0 deletions src/wasm/geometry/operations/curve-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,82 @@ namespace webifc::geometry {
return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x) >= 0;
}

inline IfcCurve Build3DArc3Pt(const glm::dvec3 &p1, const glm::dvec3 &p2, const glm::dvec3 &p3, uint16_t circleSegments, double EPS_MINSIZE)
{
// Calculate the center of the circle
glm::dvec3 v1 = p2 - p1;
glm::dvec3 v2 = p3 - p1;
glm::dvec3 normal = glm::normalize(glm::cross(v1, v2));
glm::dvec3 mid1 = 0.5 * (p1 + p2);
glm::dvec3 mid2 = 0.5 * (p1 + p3);
glm::dvec3 center;

if (glm::length(glm::cross(v1, v2)) < EPS_MINSIZE)
{
// Points are collinear, so there's no unique circle.
// You can handle this case differently or return an error.
// For simplicity, let's return an empty curve.
return IfcCurve();
}
else
{
// Calculate the center of the circle
double Cx = p2.x-p1.x;
double Cy = p2.y-p1.y;
double Cz = p2.z-p1.z;
double Bx = p3.x-p1.x;
double By = p3.y-p1.y;
double Bz = p3.z-p1.z;
double B2 = p1.x*p1.x-p3.x*p3.x+p1.y*p1.y-p3.y*p3.y+p1.z*p1.z-p3.z*p3.z;
double C2 = p1.x*p1.x-p2.x*p2.x+p1.y*p1.y-p2.y*p2.y+p1.z*p1.z-p2.z*p2.z;

double CByz = Cy*Bz-Cz*By;
double CBxz = Cx*Bz-Cz*Bx;
double CBxy = Cx*By-Cy*Bx;
double ZZ1 = -(Bz-Cz*Bx/Cx)/(By-Cy*Bx/Cx);
double Z01 = -(B2-Bx/Cx*C2)/(2*(By-Cy*Bx/Cx));
double ZZ2 = -(ZZ1*Cy+Cz)/Cx;
double Z02 = -(2*Z01*Cy+C2)/(2*Cx);

double dz = -((Z02-p1.x)*CByz-(Z01-p1.y)*CBxz-p1.z*CBxy)/(ZZ2*CByz-ZZ1*CBxz+CBxy);
double dx = ZZ2*dz + Z02;
double dy = ZZ1*dz + Z01;

center = glm::dvec3(dx, dy, dz);
}

// Calculate the radius
double radius = glm::distance(center, p1);

// Using geometrical subdivision to create points on the arc
std::vector<glm::dvec3> pointList;
pointList.push_back(p1);
pointList.push_back(p2);
pointList.push_back(p3);

while (pointList.size() < (size_t)circleSegments)
{
std::vector<glm::dvec3> tempPointList;
for (size_t j = 0; j < pointList.size() - 1; j++)
{
glm::dvec3 pt = (pointList[j] + pointList[j + 1]) / 2.0;
glm::dvec3 vc = glm::normalize(pt - center);
pt = center + vc * radius;
tempPointList.push_back(pointList[j]);
tempPointList.push_back(pt);
}
tempPointList.push_back(pointList.back());
pointList = tempPointList;
}

IfcCurve curve;
for (size_t j = 0; j < pointList.size(); j++)
{
curve.Add(pointList.at(j));
}

return curve;
}

inline IfcCurve BuildArc3Pt(const glm::dvec2 &p1, const glm::dvec2 &p2, const glm::dvec2 &p3,uint16_t circleSegments)
{
Expand Down
5 changes: 4 additions & 1 deletion src/wasm/web-ifc-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,9 @@ int main()
// std::string content = ReadFile("C:/Users/qmoya/Desktop/PROGRAMES/VSCODE/IFC.JS/issues/#452/452.ifc");
// std::string content = ReadFile("C:/Users/qmoya/Desktop/PROGRAMES/VSCODE/IFC.JS/issues/#451/Snowdon Towers Sample Architectural_IFC2x3.ifc");
// std::string content = ReadFile("C:/Users/qmoya/Desktop/PROGRAMES/VSCODE/IFC.JS/issues/#464/464.ifc");
std::string content = ReadFile("C:/Users/qmoya/Desktop/PROGRAMES/VSCODE/IFC.JS/issues/#harry/harry.ifc");
// std::string content = ReadFile("C:/Users/qmoya/Desktop/PROGRAMES/VSCODE/IFC.JS/issues/#harry/harry.ifc");
// std::string content = ReadFile("C:/Users/qmoya/Desktop/PROGRAMES/VSCODE/IFC.JS/issues/#473/473.ifc");
std::string content = ReadFile("C:/Users/qmoya/Desktop/PROGRAMES/VSCODE/IFC.JS/issues/#420/420.ifc");

webifc::utility::LoaderSettings set;
set.COORDINATE_TO_ORIGIN = true;
Expand Down Expand Up @@ -348,6 +350,7 @@ int main()
// SpecificLoadTest(loader, geometryLoader, 964810); // 464.ifc
// SpecificLoadTest(loader, geometryLoader, 961485); // 464.ifc
// SpecificLoadTest(loader, geometryLoader, 961645); // 464.ifc
// SpecificLoadTest(loader, geometryLoader, 743259); // harry.ifc

auto meshes = LoadAllTest(loader, geometryLoader);
// auto alignments = GetAlignments(loader, geometryLoader);
Expand Down

0 comments on commit 12d9df1

Please sign in to comment.