diff --git a/xs/src/ClipperUtils.cpp b/xs/src/ClipperUtils.cpp index 2989783ee..12c90996f 100644 --- a/xs/src/ClipperUtils.cpp +++ b/xs/src/ClipperUtils.cpp @@ -1,6 +1,14 @@ #include "ClipperUtils.hpp" #include "Geometry.hpp" +#ifndef use_lines + #error "use_lines directive is not enabled in clipper.hpp" +#endif + +#ifdef use_deprecated + #error "use_deprecated is not disabled in clipper.hpp" +#endif + namespace Slic3r { //----------------------------------------------------------- diff --git a/xs/src/clipper.cpp b/xs/src/clipper.cpp index 936e2524d..9070ecb1b 100644 --- a/xs/src/clipper.cpp +++ b/xs/src/clipper.cpp @@ -2,7 +2,7 @@ * * * Author : Angus Johnson * * Version : 6.1.5 * -* Date : 22 May 2014 * +* Date : 24 May 2014 * * Website : http://www.angusj.com * * Copyright : Angus Johnson 2010-2014 * * * @@ -898,112 +898,39 @@ TEdge* FindNextLocMin(TEdge* E) } //------------------------------------------------------------------------------ -TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise) +TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward) { TEdge *EStart = E, *Result = E; TEdge *Horz = 0; cInt StartX; - if (IsHorizontal(*E)) - { - //first we need to be careful here with open paths because this - //may not be a true local minima (ie may be following a skip edge). - //also, watch for adjacent horz edges to start heading left - //before finishing right ... - if (IsClockwise) - { - if (E->Prev->Bot.Y == E->Bot.Y) StartX = E->Prev->Bot.X; - else StartX = E->Prev->Top.X; - } - else - { - if (E->Next->Bot.Y == E->Bot.Y) StartX = E->Next->Bot.X; - else StartX = E->Next->Top.X; - } - if (E->Bot.X != StartX) ReverseHorizontal(*E); - } - - if (Result->OutIdx != Skip) - { - if (IsClockwise) - { - while (Result->Top.Y == Result->Next->Bot.Y && Result->Next->OutIdx != Skip) - Result = Result->Next; - if (IsHorizontal(*Result) && Result->Next->OutIdx != Skip) - { - //nb: at the top of a bound, horizontals are added to the bound - //only when the preceding edge attaches to the horizontal's left vertex - //unless a Skip edge is encountered when that becomes the top divide - Horz = Result; - while (IsHorizontal(*Horz->Prev)) Horz = Horz->Prev; - if (Horz->Prev->Top.X == Result->Next->Top.X) - { - if (!IsClockwise) Result = Horz->Prev; - } - else if (Horz->Prev->Top.X > Result->Next->Top.X) Result = Horz->Prev; - } - while (E != Result) - { - E->NextInLML = E->Next; - if (IsHorizontal(*E) && E != EStart && - E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E); - E = E->Next; - } - if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Prev->Top.X) - ReverseHorizontal(*E); - Result = Result->Next; //move to the edge just beyond current bound - } else - { - while (Result->Top.Y == Result->Prev->Bot.Y && Result->Prev->OutIdx != Skip) - Result = Result->Prev; - if (IsHorizontal(*Result) && Result->Prev->OutIdx != Skip) - { - Horz = Result; - while (IsHorizontal(*Horz->Next)) Horz = Horz->Next; - if (Horz->Next->Top.X == Result->Prev->Top.X) - { - if (!IsClockwise) Result = Horz->Next; - } - else if (Horz->Next->Top.X > Result->Prev->Top.X) Result = Horz->Next; - } - while (E != Result) - { - E->NextInLML = E->Prev; - if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) - ReverseHorizontal(*E); - E = E->Prev; - } - if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) - ReverseHorizontal(*E); - Result = Result->Prev; //move to the edge just beyond current bound - } - } - - if (Result->OutIdx == Skip) + if (E->OutIdx == Skip) { //if edges still remain in the current bound beyond the skip edge then //create another LocMin and call ProcessBound once more - E = Result; - if (IsClockwise) + if (NextIsForward) { while (E->Top.Y == E->Next->Bot.Y) E = E->Next; //don't include top horizontals when parsing a bound a second time, //they will be contained in the opposite bound ... while (E != Result && IsHorizontal(*E)) E = E->Prev; - } else + } + else { while (E->Top.Y == E->Prev->Bot.Y) E = E->Prev; while (E != Result && IsHorizontal(*E)) E = E->Next; } + if (E == Result) { - if (IsClockwise) Result = E->Next; + if (NextIsForward) Result = E->Next; else Result = E->Prev; - } else + } + else { //there are more edges in the bound beyond result starting with E - if (IsClockwise) - E = Result->Next; + if (NextIsForward) + E = Result->Next; else E = Result->Prev; LocalMinima* locMin = new LocalMinima; @@ -1012,10 +939,85 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise) locMin->LeftBound = 0; locMin->RightBound = E; locMin->RightBound->WindDelta = 0; - Result = ProcessBound(locMin->RightBound, IsClockwise); + Result = ProcessBound(locMin->RightBound, NextIsForward); InsertLocalMinima(locMin); } + return Result; } + + if (IsHorizontal(*E)) + { + //we need to be careful with open paths because this may not be + //a true local minima (ie may be following a skip edge). + //Also, watch for adjacent horz edges that can head left + //before finishing right ... + if (NextIsForward) + { + if (E->Prev->Bot.Y == E->Bot.Y) StartX = E->Prev->Bot.X; + else StartX = E->Prev->Top.X; + } + else + { + if (E->Next->Bot.Y == E->Bot.Y) StartX = E->Next->Bot.X; + else StartX = E->Next->Top.X; + } + if (E->Bot.X != StartX) ReverseHorizontal(*E); + } + + if (NextIsForward) + { + while (Result->Top.Y == Result->Next->Bot.Y && Result->Next->OutIdx != Skip) + Result = Result->Next; + if (IsHorizontal(*Result) && Result->Next->OutIdx != Skip) + { + //nb: at the top of a bound, horizontals are added to the bound + //only when the preceding edge attaches to the horizontal's left vertex + //unless a Skip edge is encountered when that becomes the top divide + Horz = Result; + while (IsHorizontal(*Horz->Prev)) Horz = Horz->Prev; + if (Horz->Prev->Top.X == Result->Next->Top.X) + { + if (!NextIsForward) Result = Horz->Prev; + } + else if (Horz->Prev->Top.X > Result->Next->Top.X) Result = Horz->Prev; + } + while (E != Result) + { + E->NextInLML = E->Next; + if (IsHorizontal(*E) && E != EStart && + E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E); + E = E->Next; + } + if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Prev->Top.X) + ReverseHorizontal(*E); + Result = Result->Next; //move to the edge just beyond current bound + } else + { + while (Result->Top.Y == Result->Prev->Bot.Y && Result->Prev->OutIdx != Skip) + Result = Result->Prev; + if (IsHorizontal(*Result) && Result->Prev->OutIdx != Skip) + { + Horz = Result; + while (IsHorizontal(*Horz->Next)) Horz = Horz->Next; + if (Horz->Next->Top.X == Result->Prev->Top.X) + { + if (!NextIsForward) Result = Horz->Next; + } + else if (Horz->Next->Top.X > Result->Prev->Top.X) Result = Horz->Next; + } + + while (E != Result) + { + E->NextInLML = E->Prev; + if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) + ReverseHorizontal(*E); + E = E->Prev; + } + if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) + ReverseHorizontal(*E); + Result = Result->Prev; //move to the edge just beyond current bound + } + return Result; } //------------------------------------------------------------------------------ @@ -1148,7 +1150,7 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) } m_edges.push_back(edges); - bool clockwise; + bool nextIsForward; TEdge* EMin = 0; //workaround to avoid an endless loop in the while loop below when @@ -1170,12 +1172,12 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) { locMin->LeftBound = E->Prev; locMin->RightBound = E; - clockwise = false; //Q.nextInLML = Q.prev + nextIsForward = false; //Q.nextInLML = Q.prev } else { locMin->LeftBound = E; locMin->RightBound = E->Prev; - clockwise = true; //Q.nextInLML = Q.next + nextIsForward = true; //Q.nextInLML = Q.next } locMin->LeftBound->Side = esLeft; locMin->RightBound->Side = esRight; @@ -1186,15 +1188,15 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) else locMin->LeftBound->WindDelta = 1; locMin->RightBound->WindDelta = -locMin->LeftBound->WindDelta; - E = ProcessBound(locMin->LeftBound, clockwise); - TEdge* E2 = ProcessBound(locMin->RightBound, !clockwise); + E = ProcessBound(locMin->LeftBound, nextIsForward); + TEdge* E2 = ProcessBound(locMin->RightBound, !nextIsForward); if (locMin->LeftBound->OutIdx == Skip) locMin->LeftBound = 0; else if (locMin->RightBound->OutIdx == Skip) locMin->RightBound = 0; InsertLocalMinima(locMin); - if (!clockwise) E = E2; + if (!nextIsForward) E = E2; } return true; } diff --git a/xs/src/clipper.hpp b/xs/src/clipper.hpp index 7922abe18..9927a97ad 100644 --- a/xs/src/clipper.hpp +++ b/xs/src/clipper.hpp @@ -2,7 +2,7 @@ * * * Author : Angus Johnson * * Version : 6.1.5 * -* Date : 22 May 2014 * +* Date : 24 May 2014 * * Website : http://www.angusj.com * * Copyright : Angus Johnson 2010-2014 * * * diff --git a/xs/t/11_clipper.t b/xs/t/11_clipper.t index efa051fe7..89d173e39 100644 --- a/xs/t/11_clipper.t +++ b/xs/t/11_clipper.t @@ -155,7 +155,7 @@ if (0) { # Clipper does not preserve polyline orientation } } -# Disabled until Clipper bug #96 (our issue #2028) is fixed +# Clipper bug #96 (our GH #2028) if (0) { my $subject = Slic3r::Polyline->new( [44735000,31936670],[55270000,31936670],[55270000,25270000],[74730000,25270000],[74730000,44730000],[68063296,44730000],[68063296,55270000],[74730000,55270000],[74730000,74730000],[55270000,74730000],[55270000,68063296],[44730000,68063296],[44730000,74730000],[25270000,74730000],[25270000,55270000],[31936670,55270000],[31936670,44730000],[25270000,44730000],[25270000,25270000],[44730000,25270000],[44730000,31936670]