From f24427cd76026be8142e49dddf66343845ae9d89 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 3 Mar 2017 21:40:40 +0100 Subject: [PATCH] Another Clipper optimization. When adding a set of paths to Clipper, allocate the edges in a single continuous vector. --- xs/src/clipper.cpp | 88 +++++++++++++++++++++++++++++++++++----------- xs/src/clipper.hpp | 1 + 2 files changed, 68 insertions(+), 21 deletions(-) diff --git a/xs/src/clipper.cpp b/xs/src/clipper.cpp index 7ead760bf..91d8442f4 100644 --- a/xs/src/clipper.cpp +++ b/xs/src/clipper.cpp @@ -896,6 +896,72 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward) //------------------------------------------------------------------------------ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) +{ + PROFILE_FUNC(); + // Remove duplicate end point from a closed input path. + // Remove duplicate points from the end of the input path. + int highI = (int)pg.size() -1; + if (Closed) + while (highI > 0 && (pg[highI] == pg[0])) + --highI; + while (highI > 0 && (pg[highI] == pg[highI -1])) + --highI; + if ((Closed && highI < 2) || (!Closed && highI < 1)) + return false; + + // Allocate a new edge array. + std::vector edges(highI + 1); + // Fill in the edge array. + bool result = AddPathInternal(pg, highI, PolyTyp, Closed, edges.data()); + if (result) + // Success, remember the edge array. + m_edges.emplace_back(std::move(edges)); + return result; +} + +bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed) +{ + PROFILE_FUNC(); + std::vector num_edges(ppg.size(), 0); + int num_edges_total = 0; + for (size_t i = 0; i < ppg.size(); ++ i) { + const Path &pg = ppg[i]; + // Remove duplicate end point from a closed input path. + // Remove duplicate points from the end of the input path. + int highI = (int)pg.size() -1; + if (Closed) + while (highI > 0 && (pg[highI] == pg[0])) + --highI; + while (highI > 0 && (pg[highI] == pg[highI -1])) + --highI; + if ((Closed && highI < 2) || (!Closed && highI < 1)) + highI = -1; + num_edges[i] = highI + 1; + num_edges_total += highI + 1; + } + if (num_edges_total == 0) + return false; + + // Allocate a new edge array. + std::vector edges(num_edges_total); + // Fill in the edge array. + bool result = false; + TEdge *p_edge = edges.data(); + for (Paths::size_type i = 0; i < ppg.size(); ++i) + if (num_edges[i]) { + bool res = AddPathInternal(ppg[i], num_edges[i] - 1, PolyTyp, Closed, p_edge); + if (res) { + p_edge += num_edges[i]; + result = true; + } + } + if (result) + // At least some edges were generated. Remember the edge array. + m_edges.emplace_back(std::move(edges)); + return result; +} + +bool ClipperBase::AddPathInternal(const Path &pg, int highI, PolyType PolyTyp, bool Closed, TEdge* edges) { PROFILE_FUNC(); #ifdef use_lines @@ -906,15 +972,7 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) throw clipperException("AddPath: Open paths have been disabled."); #endif - // Remove duplicate end point from a closed input path. - // Remove duplicate points from the end of the input path. - int highI = (int)pg.size() -1; - if (Closed) while (highI > 0 && (pg[highI] == pg[0])) --highI; - while (highI > 0 && (pg[highI] == pg[highI -1])) --highI; - if ((Closed && highI < 2) || (!Closed && highI < 1)) return false; - - //create a new edge array ... - std::vector edges(highI + 1); + assert(highI >= 0 && highI < pg.size()); //1. Basic (first) edge initialization ... try @@ -1018,11 +1076,9 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) E = E->Next; } m_MinimaList.push_back(locMin); - m_edges.emplace_back(std::move(edges)); return true; } - m_edges.emplace_back(std::move(edges)); bool leftBoundIsForward; TEdge* EMin = 0; @@ -1079,16 +1135,6 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) } //------------------------------------------------------------------------------ -bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed) -{ - PROFILE_FUNC(); - bool result = false; - for (Paths::size_type i = 0; i < ppg.size(); ++i) - if (AddPath(ppg[i], PolyTyp, Closed)) result = true; - return result; -} -//------------------------------------------------------------------------------ - void ClipperBase::Clear() { PROFILE_FUNC(); diff --git a/xs/src/clipper.hpp b/xs/src/clipper.hpp index e62e27e89..6969c861c 100644 --- a/xs/src/clipper.hpp +++ b/xs/src/clipper.hpp @@ -291,6 +291,7 @@ public: bool PreserveCollinear() const {return m_PreserveCollinear;}; void PreserveCollinear(bool value) {m_PreserveCollinear = value;}; protected: + bool AddPathInternal(const Path &pg, int highI, PolyType PolyTyp, bool Closed, TEdge* edges); TEdge* AddBoundsToLML(TEdge *e, bool IsClosed); virtual void Reset(); TEdge* ProcessBound(TEdge* E, bool IsClockwise);