From 6a6439576bed48ee1e5381a39fc913486cde95d4 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 26 May 2014 17:21:31 +0200 Subject: [PATCH] Update Clipper to r468. #2028 --- xs/src/clipper.cpp | 193 +++++++++++++++++++++++---------------------- xs/src/clipper.hpp | 2 +- xs/t/11_clipper.t | 6 +- 3 files changed, 102 insertions(+), 99 deletions(-) diff --git a/xs/src/clipper.cpp b/xs/src/clipper.cpp index 936e2524..249f87c3 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 : 26 May 2014 * * Website : http://www.angusj.com * * Copyright : Angus Johnson 2010-2014 * * * @@ -898,112 +898,38 @@ TEdge* FindNextLocMin(TEdge* E) } //------------------------------------------------------------------------------ -TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise) +TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward) { - TEdge *EStart = E, *Result = E; + TEdge *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; @@ -1011,11 +937,88 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise) locMin->Y = E->Bot.Y; locMin->LeftBound = 0; locMin->RightBound = E; - locMin->RightBound->WindDelta = 0; - Result = ProcessBound(locMin->RightBound, IsClockwise); + E->WindDelta = 0; + Result = ProcessBound(E, NextIsForward); InsertLocalMinima(locMin); } + return Result; } + + TEdge *EStart; + + if (IsHorizontal(*E)) + { + //We need to be careful with open paths because this may not be a + //true local minima (ie E may be following a skip edge). + //Also, consecutive horz. edges may start heading left before going right. + if (NextIsForward) + EStart = E->Prev; + else + EStart = E->Next; + if (IsHorizontal(*EStart)) //ie an adjoining horizontal skip edge + { + if (EStart->Bot.X != E->Bot.X && EStart->Top.X != E->Bot.X) + ReverseHorizontal(*E); + } + else if (EStart->Bot.X != E->Bot.X) + ReverseHorizontal(*E); + } + + EStart = 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 +1151,7 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) } m_edges.push_back(edges); - bool clockwise; + bool leftBoundIsForward; TEdge* EMin = 0; //workaround to avoid an endless loop in the while loop below when @@ -1170,12 +1173,12 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) { locMin->LeftBound = E->Prev; locMin->RightBound = E; - clockwise = false; //Q.nextInLML = Q.prev + leftBoundIsForward = false; //Q.nextInLML = Q.prev } else { locMin->LeftBound = E; locMin->RightBound = E->Prev; - clockwise = true; //Q.nextInLML = Q.next + leftBoundIsForward = true; //Q.nextInLML = Q.next } locMin->LeftBound->Side = esLeft; locMin->RightBound->Side = esRight; @@ -1186,15 +1189,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, leftBoundIsForward); + TEdge* E2 = ProcessBound(locMin->RightBound, !leftBoundIsForward); if (locMin->LeftBound->OutIdx == Skip) locMin->LeftBound = 0; else if (locMin->RightBound->OutIdx == Skip) locMin->RightBound = 0; InsertLocalMinima(locMin); - if (!clockwise) E = E2; + if (!leftBoundIsForward) E = E2; } return true; } diff --git a/xs/src/clipper.hpp b/xs/src/clipper.hpp index 7922abe1..9927a97a 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 efa051fe..e9905323 100644 --- a/xs/t/11_clipper.t +++ b/xs/t/11_clipper.t @@ -4,7 +4,7 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 18; +use Test::More tests => 19; my $square = Slic3r::Polygon->new( # ccw [200, 100], @@ -155,8 +155,8 @@ if (0) { # Clipper does not preserve polyline orientation } } -# Disabled until Clipper bug #96 (our issue #2028) is fixed -if (0) { +# Clipper bug #96 (our GH #2028) +{ 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] );