diff --git a/src/cpp/web-ifc/geometry/operations/geometryutils.h b/src/cpp/web-ifc/geometry/operations/geometryutils.h index 748d7f79..95e864d3 100644 --- a/src/cpp/web-ifc/geometry/operations/geometryutils.h +++ b/src/cpp/web-ifc/geometry/operations/geometryutils.h @@ -581,7 +581,6 @@ namespace webifc::geometry { spdlog::debug("[Extrude({})]"); IfcGeometry geom; - std::vector holesIndicesHash; // check if first point is equal to last point, otherwise the outer loop of the shape is not closed glm::dvec3 lastToFirstPoint = profile.curve.points.front() - profile.curve.points.back(); @@ -589,11 +588,31 @@ namespace webifc::geometry profile.curve.points.push_back(profile.curve.points.front()); } + size_t nofHolePoints = 0; + for (const auto &hole : profile.holes) { + nofHolePoints += hole.points.size(); + }; + std::vector holesIndicesHash(profile.curve.points.size() + nofHolePoints, false); + auto holesIndicesHashCursor = profile.curve.points.size(); + + // Reservation space for geometry + { + const auto currentSize = geom.vertexData.size(); + const auto profilePointSize = profile.curve.points.size() * 6; + const auto holesPointSize = nofHolePoints * 6; + const auto addedPointsToProfile = (profile.curve.points.size() + nofHolePoints) * 6; + geom.vertexData.reserve(currentSize + profilePointSize + holesPointSize + addedPointsToProfile); + } + // build the caps { using Point = std::array; int polygonCount = 1 + profile.holes.size(); // Main profile + holes std::vector> polygon(polygonCount); + for (size_t i = 0; i < polygonCount; i++) { + if (i == 0) { polygon[i].reserve(profile.curve.points.size()); } + else { polygon[i].reserve(profile.holes[i - 1].points.size()); } + } glm::dvec3 normal = dir; @@ -606,19 +625,13 @@ namespace webifc::geometry polygon[0].push_back({pt.x, pt.y}); } - for (size_t i = 0; i < profile.curve.points.size(); i++) - { - holesIndicesHash.push_back(false); - } - for (size_t i = 0; i < profile.holes.size(); i++) { IfcCurve hole = profile.holes[i]; - int pointCount = hole.points.size(); - for (int j = 0; j < pointCount; j++) + for (int j = 0; j < hole.points.size(); j++) { - holesIndicesHash.push_back(j == 0); + holesIndicesHash[holesIndicesHashCursor++] = j == 0; glm::dvec2 pt = hole.points[j]; glm::dvec4 et = glm::dvec4(glm::dvec3(pt, 0) + dir * distance, 1); @@ -631,6 +644,17 @@ namespace webifc::geometry std::vector indices = mapbox::earcut(polygon); + // Reservation space for faces + { + const auto currrentIndiciesSize = geom.indexData.size(); + const auto nofIndices = indices.size() * 2; + const auto capIndicies = (profile.curve.points.size() - 1 - profile.holes.size()) * 6; + geom.indexData.reserve(currrentIndiciesSize + nofIndices + capIndicies); + + const auto currentFaceSize = geom.planeData.size(); + geom.planeData.reserve(currentFaceSize + (nofIndices + capIndicies) / 3); + } + if (indices.size() < 3) { // probably a degenerate polygon @@ -715,13 +739,8 @@ namespace webifc::geometry uint32_t tr = capSize + i - 0; // this winding should be correct - geom.AddFace(geom.GetPoint(tl), - geom.GetPoint(br), - geom.GetPoint(bl)); - - geom.AddFace(geom.GetPoint(tl), - geom.GetPoint(tr), - geom.GetPoint(br)); + geom.AddFace(tl, br, bl); + geom.AddFace(tl, tr, br); } return geom; diff --git a/src/cpp/web-ifc/parsing/IfcTokenChunk.cpp b/src/cpp/web-ifc/parsing/IfcTokenChunk.cpp index 2aa797dd..e3c20821 100644 --- a/src/cpp/web-ifc/parsing/IfcTokenChunk.cpp +++ b/src/cpp/web-ifc/parsing/IfcTokenChunk.cpp @@ -24,31 +24,6 @@ namespace webifc::parsing return true; } - bool IfcTokenStream::IfcTokenChunk::Clear() - { - return Clear(false); - } - - size_t IfcTokenStream::IfcTokenChunk::GetTokenRef() - { - return _startRef; - } - - size_t IfcTokenStream::IfcTokenChunk::TokenSize() - { - return _currentSize; - } - - bool IfcTokenStream::IfcTokenChunk::IsLoaded() - { - return _loaded; - } - - size_t IfcTokenStream::IfcTokenChunk::GetMaxSize() - { - return _chunkSize; - } - std::string_view IfcTokenStream::IfcTokenChunk::ReadString(const size_t ptr,const size_t size) { if (!_loaded) Load(); diff --git a/src/cpp/web-ifc/parsing/IfcTokenStream.cpp b/src/cpp/web-ifc/parsing/IfcTokenStream.cpp index 6c28a8dd..b04fc1af 100644 --- a/src/cpp/web-ifc/parsing/IfcTokenStream.cpp +++ b/src/cpp/web-ifc/parsing/IfcTokenStream.cpp @@ -149,11 +149,6 @@ namespace webifc::parsing _readPtr--; } - bool IfcTokenStream::IsAtEnd() - { - return _currentChunk >= _chunks.size()-1 && _readPtr >= _chunks.back().TokenSize(); - } - size_t IfcTokenStream::GetReadOffset() { return _cChunk->GetTokenRef() + _readPtr; diff --git a/src/cpp/web-ifc/parsing/IfcTokenStream.h b/src/cpp/web-ifc/parsing/IfcTokenStream.h index 98ac9580..4b1dac24 100644 --- a/src/cpp/web-ifc/parsing/IfcTokenStream.h +++ b/src/cpp/web-ifc/parsing/IfcTokenStream.h @@ -56,7 +56,9 @@ namespace webifc::parsing void Forward(const size_t size); std::string_view ReadString(); void Back(); - bool IsAtEnd(); + inline bool IsAtEnd() const noexcept { + return _currentChunk >= _chunks.size() - 1 && _readPtr >= _chunks.back().TokenSize(); + }; void MoveTo(const size_t pos); size_t GetReadOffset(); size_t GetTotalSize(); @@ -95,14 +97,16 @@ namespace webifc::parsing class IfcTokenChunk { public: - IfcTokenChunk(const size_t chunkSize, const size_t startRef, const size_t fileStartRef, IfcFileStream *_fileStream); + IfcTokenChunk(const size_t chunkSize, const size_t startRef, const size_t fileStartRef, IfcFileStream *_fileStream); bool Clear(bool force); - bool Clear(); - bool IsLoaded(); - size_t TokenSize(); - size_t GetTokenRef(); + inline bool Clear() { return Clear(false); } + inline bool IsLoaded() const noexcept { return _loaded; } + inline size_t TokenSize() const noexcept { return _currentSize; } + inline size_t GetTokenRef() const noexcept { return _startRef; } + inline size_t GetMaxSize() const noexcept { return _chunkSize; } + void Push(void *v, const size_t size); - size_t GetMaxSize(); + std::string_view ReadString(const size_t ptr,const size_t size); template T Read(const size_t ptr) {