Skip to content

Remove multiple allocations caused by push_back in Extrude method #1397

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 35 additions & 16 deletions src/cpp/web-ifc/geometry/operations/geometryutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -581,19 +581,38 @@ namespace webifc::geometry
{
spdlog::debug("[Extrude({})]");
IfcGeometry geom;
std::vector<bool> 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();
if (glm::length(lastToFirstPoint) > 1e-8) {
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<bool> 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<double, 2>;
int polygonCount = 1 + profile.holes.size(); // Main profile + holes
std::vector<std::vector<Point>> 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;

Expand All @@ -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);
Expand All @@ -631,6 +644,17 @@ namespace webifc::geometry

std::vector<uint32_t> indices = mapbox::earcut<uint32_t>(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
Expand Down Expand Up @@ -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;
Expand Down
25 changes: 0 additions & 25 deletions src/cpp/web-ifc/parsing/IfcTokenChunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
5 changes: 0 additions & 5 deletions src/cpp/web-ifc/parsing/IfcTokenStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
18 changes: 11 additions & 7 deletions src/cpp/web-ifc/parsing/IfcTokenStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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 <typename T> T Read(const size_t ptr)
{
Expand Down
Loading