[mapnik-vector-tile] 04/04: Update clipper to 150f2c4f58a72c051bcad76c84f10362797bf5ab.

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Fri Mar 11 12:31:37 UTC 2016


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository mapnik-vector-tile.

commit 46232be8f065a01ea328199957aeb5d1bb5ace5d
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Fri Mar 11 13:31:10 2016 +0100

    Update clipper to 150f2c4f58a72c051bcad76c84f10362797bf5ab.
---
 debian/changelog   |   2 +-
 debian/clipper.cpp | 453 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 debian/clipper.hpp |   3 +
 3 files changed, 441 insertions(+), 17 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index fcd5352..715d990 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -5,7 +5,7 @@ mapnik-vector-tile (1.0.4+dfsg-1) UNRELEASED; urgency=medium
   * Refresh patches.
   * Bump protozero dependency to 1.3.0.
   * Bump Standards-Version to 3.9.7, no changes.
-  * Update clipper to b82601d67830a84179888360e3dea645c1125a26.
+  * Update clipper to 150f2c4f58a72c051bcad76c84f10362797bf5ab.
 
  -- Bas Couwenberg <sebastic at debian.org>  Fri, 11 Mar 2016 13:29:45 +0100
 
diff --git a/debian/clipper.cpp b/debian/clipper.cpp
index 3772e1e..bf369ec 100644
--- a/debian/clipper.cpp
+++ b/debian/clipper.cpp
@@ -633,7 +633,7 @@ void IntersectPoint(TEdge &Edge1, TEdge &Edge2, IntPoint &ip)
     ip.x = TopX(Edge1, ip.y);
     return;
   }
-  else if (Edge1.Dx == 0)
+  else if (Edge1.Dx == 0.0)
   {
     ip.x = Edge1.Bot.x;
     if (IsHorizontal(Edge2))
@@ -641,10 +641,14 @@ void IntersectPoint(TEdge &Edge1, TEdge &Edge2, IntPoint &ip)
     else
     {
       b2 = Edge2.Bot.y - (Edge2.Bot.x / Edge2.Dx);
-      ip.y = Round(ip.x / Edge2.Dx + b2);
+      if (Edge2.Bot.x == Edge1.Bot.x) ip.y = Round(ip.x / Edge2.Dx + b2);
+      else if (Edge2.Bot.x < Edge1.Bot.x) ip.y = Round((ip.x - 0.5) / Edge2.Dx + b2);
+      else ip.y = Round((ip.x + 0.5) / Edge2.Dx + b2);
+      if (Edge2.Dx > 0.0 && ip.y < Edge2.Bot.y) ip.y = Edge2.Bot.y;
+      else if (Edge2.Dx < 0.0 && ip.y > Edge2.Bot.y) ip.y = Edge2.Bot.y;
     }
   }
-  else if (Edge2.Dx == 0)
+  else if (Edge2.Dx == 0.0)
   {
     ip.x = Edge2.Bot.x;
     if (IsHorizontal(Edge1))
@@ -652,7 +656,11 @@ void IntersectPoint(TEdge &Edge1, TEdge &Edge2, IntPoint &ip)
     else
     {
       b1 = Edge1.Bot.y - (Edge1.Bot.x / Edge1.Dx);
-      ip.y = Round(ip.x / Edge1.Dx + b1);
+      if (Edge1.Bot.x == Edge2.Bot.x) ip.y = Round(ip.x / Edge1.Dx + b1);
+      else if (Edge1.Bot.x < Edge2.Bot.x) ip.y = Round((ip.x - 0.5) / Edge1.Dx + b1);
+      else ip.y = Round((ip.x + 0.5) / Edge1.Dx + b1);
+      if (Edge1.Dx > 0.0 && ip.y < Edge1.Bot.y) ip.y = Edge1.Bot.y;
+      else if (Edge1.Dx < 0.0 && ip.y > Edge1.Bot.y) ip.y = Edge1.Bot.y;
     }
   } 
   else 
@@ -665,6 +673,85 @@ void IntersectPoint(TEdge &Edge1, TEdge &Edge2, IntPoint &ip)
       ip.x = Round(Edge1.Dx * q + b1);
     else 
       ip.x = Round(Edge2.Dx * q + b2);
+    // the idea is simply to looking closer
+    // towards the origins of the lines (Edge1.Bot and Edge2.Bot)
+    // until we do not find pixels that both lines travel through
+    bool keep_searching = false;
+    double by1 = Edge1.Bot.y - (Edge1.Bot.x / Edge1.Dx);
+    double by2 = Edge2.Bot.y - (Edge2.Bot.x / Edge2.Dx);
+    double bx1 = Edge1.Bot.x - (Edge1.Bot.y * Edge1.Dx);
+    double bx2 = Edge2.Bot.x - (Edge2.Bot.y * Edge2.Dx);
+    do
+    {
+        keep_searching = false;
+        cInt y1 = ip.y;
+        cInt y2 = ip.y;
+        if (Edge1.Bot.x > ip.x)
+        {
+            y1 = Round((ip.x + 0.5) / Edge1.Dx + by1);
+            if (ip.y >= Edge1.Bot.y && y1 < Edge1.Bot.y) y1 = Edge1.Bot.y;
+            else if (ip.y <= Edge1.Bot.y && y1 > Edge1.Bot.y) y1 = Edge1.Bot.y;
+        }
+        else if (Edge1.Bot.x < ip.x)
+        {
+            y1 = Round((ip.x - 0.5) / Edge1.Dx + by1);
+        }
+        if (ip.y >= Edge1.Bot.y && y1 < Edge1.Bot.y) y1 = Edge1.Bot.y;
+        else if (ip.y <= Edge1.Bot.y && y1 > Edge1.Bot.y) y1 = Edge1.Bot.y;
+        if (Edge2.Bot.x > ip.x)
+        {
+            y2 = Round((ip.x + 0.5) / Edge2.Dx + by2);
+        }
+        else if (Edge2.Bot.x < ip.x)
+        {
+            y2 = Round((ip.x - 0.5) / Edge2.Dx + by2);
+        }
+        if (ip.y >= Edge2.Bot.y && y2 < Edge2.Bot.y) y2 = Edge2.Bot.y;
+        else if (ip.y <= Edge2.Bot.y && y2 > Edge2.Bot.y) y2 = Edge2.Bot.y;
+        cInt x1 = ip.x;
+        cInt x2 = ip.x;
+        if (Edge1.Bot.y > ip.y)
+        {
+            x1 = Round((ip.y + 0.5) * Edge1.Dx + bx1);
+        }
+        else if (Edge1.Bot.y < ip.y)
+        {
+            x1 = Round((ip.y - 0.5) * Edge1.Dx + bx1);
+        }
+        if (ip.x >= Edge1.Bot.x && x1 < Edge1.Bot.x) x1 = Edge1.Bot.x;
+        else if (ip.x <= Edge1.Bot.x && x1 > Edge1.Bot.x) x1 = Edge1.Bot.x;
+        if (Edge2.Bot.y > ip.y)
+        {
+            x2 = Round((ip.y + 0.5) * Edge2.Dx + bx2);
+        }
+        else if (Edge2.Bot.y < ip.y)
+        {
+            x2 = Round((ip.y - 0.5) * Edge2.Dx + bx2);
+        }
+        if (ip.x >= Edge2.Bot.x && x2 < Edge2.Bot.x) x2 = Edge2.Bot.x;
+        else if (ip.x <= Edge2.Bot.x && x2 > Edge2.Bot.x) x2 = Edge2.Bot.x;
+        if (y1 > ip.y && y2 > ip.y)
+        {
+            ip.y = std::min(y1,y2);
+            keep_searching = true;
+        }
+        else if (y1 < ip.y && y2 < ip.y)
+        {
+            ip.y = std::max(y1,y2);
+            keep_searching = true;
+        } 
+        if (x1 > ip.x && x2 > ip.x)
+        {
+            ip.x = std::min(x1,x2);
+            keep_searching = true;
+        }
+        else if (x1 < ip.x && x2 < ip.x)
+        {
+            ip.x = std::max(x1,x2);
+            keep_searching = true;
+        }
+    }
+    while (keep_searching);
   }
 
   if (ip.y < Edge1.Top.y || ip.y < Edge2.Top.y) 
@@ -1963,6 +2050,14 @@ void Clipper::ClearJoins()
 }
 //------------------------------------------------------------------------------
 
+void Clipper::ClearSSJoins()
+{
+  for (JoinList::size_type i = 0; i < m_SSJoins.size(); i++)
+    delete m_SSJoins[i];
+  m_SSJoins.resize(0);
+}
+//------------------------------------------------------------------------------
+
 void Clipper::ClearGhostJoins()
 {
   for (JoinList::size_type i = 0; i < m_GhostJoins.size(); i++)
@@ -1981,6 +2076,16 @@ void Clipper::AddGhostJoin(OutPt *op, const IntPoint OffPt)
 }
 //------------------------------------------------------------------------------
 
+void Clipper::AddSSJoin(OutPt *op1, OutPt *op2, const IntPoint OffPt)
+{
+  Join* j = new Join;
+  j->OutPt1 = op1;
+  j->OutPt2 = op2;
+  j->OffPt = OffPt;
+  m_SSJoins.push_back(j);
+}
+//------------------------------------------------------------------------------
+
 void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
 {
   const LocalMinimum *lm;
@@ -1996,14 +2101,46 @@ void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
       InsertEdgeIntoAEL(rb, 0);
       SetWindingCount(*rb);
       if (IsContributing(*rb))
-        Op1 = AddOutPt(rb, rb->Bot); 
+      {
+          Op1 = AddOutPt(rb, rb->Bot); 
+          TEdge* ePrev = rb->PrevInAEL;
+          if ((rb->OutIdx >= 0) && (rb->WindDelta != 0) && ePrev && (ePrev->OutIdx >= 0) &&
+            (ePrev->Curr.x == rb->Curr.x) && (ePrev->WindDelta != 0))
+          {
+            IntPoint pt = rb->Curr;
+            AddOutPt(ePrev, pt);
+          }
+          TEdge* eNext = rb->NextInAEL;
+          if ((rb->OutIdx >= 0) && (rb->WindDelta != 0) && eNext && (eNext->OutIdx >= 0) &&
+            (eNext->Curr.x == rb->Curr.x) && (eNext->WindDelta != 0))
+          {
+            IntPoint pt = rb->Curr;
+            AddOutPt(eNext, pt);
+          }
+      }
     } 
     else if (!rb)
     {
       InsertEdgeIntoAEL(lb, 0);
       SetWindingCount(*lb);
       if (IsContributing(*lb))
-        Op1 = AddOutPt(lb, lb->Bot);
+      {
+          Op1 = AddOutPt(lb, lb->Bot);
+          TEdge* ePrev = lb->PrevInAEL;
+          if ((lb->OutIdx >= 0) && (lb->WindDelta != 0) && ePrev && (ePrev->OutIdx >= 0) &&
+            (ePrev->Curr.x == lb->Curr.x) && (ePrev->WindDelta != 0))
+          {
+            IntPoint pt = lb->Curr;
+            AddOutPt(ePrev, pt);
+          }
+          TEdge* eNext = lb->NextInAEL;
+          if ((lb->OutIdx >= 0) && (lb->WindDelta != 0) && eNext && (eNext->OutIdx >= 0) &&
+            (eNext->Curr.x == lb->Curr.x) && (eNext->WindDelta != 0))
+          {
+            IntPoint pt = lb->Curr;
+            AddOutPt(eNext, pt);
+          }
+      }
       InsertScanbeam(lb->Top.y);
     }
     else
@@ -2014,7 +2151,23 @@ void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
       rb->WindCnt = lb->WindCnt;
       rb->WindCnt2 = lb->WindCnt2;
       if (IsContributing(*lb))
-        Op1 = AddLocalMinPoly(lb, rb, lb->Bot);      
+      {
+          Op1 = AddLocalMinPoly(lb, rb, lb->Bot);      
+          TEdge* ePrev = lb->PrevInAEL;
+          if ((lb->OutIdx >= 0) && (lb->WindDelta != 0) && ePrev && (ePrev->OutIdx >= 0) &&
+            (ePrev->Curr.x == lb->Curr.x) && (ePrev->WindDelta != 0))
+          {
+            IntPoint pt = lb->Curr;
+            AddOutPt(ePrev, pt);
+          }
+          TEdge* eNext = rb->NextInAEL;
+          if ((rb->OutIdx >= 0) && (rb->WindDelta != 0) && eNext && (eNext->OutIdx >= 0) &&
+            (eNext->Curr.x == rb->Curr.x) && (eNext->WindDelta != 0))
+          {
+            IntPoint pt = rb->Curr;
+            AddOutPt(eNext, pt);
+          }
+      }
       InsertScanbeam(lb->Top.y);
     }
 
@@ -2793,6 +2946,27 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
     if(horzEdge->OutIdx >= 0)
     {
       op1 = AddOutPt( horzEdge, horzEdge->Top);
+      //When StrictlySimple and 'horzEdge' is being touched by another edge, then
+      //make sure both edges have a vertex here ...
+      if (m_StrictSimple)
+      {  
+        TEdge* ePrev = horzEdge->PrevInAEL;
+        if ((horzEdge->WindDelta != 0) && ePrev && (ePrev->OutIdx >= 0) &&
+          (ePrev->Curr.x == horzEdge->Top.x) && (ePrev->WindDelta != 0))
+        {
+          IntPoint pt = horzEdge->Top;
+          OutPt* op = AddOutPt(ePrev, pt);
+          AddJoin(op, op1, pt); //StrictlySimple (type-3) join
+        }
+        TEdge* eNext = horzEdge->NextInAEL;
+        if ((horzEdge->WindDelta != 0) && eNext && (eNext->OutIdx >= 0) &&
+          (eNext->Curr.x == horzEdge->Top.x) && (eNext->WindDelta != 0))
+        {
+          IntPoint pt = horzEdge->Top;
+          OutPt* op = AddOutPt(eNext, pt);
+          AddJoin(op, op1, pt); //StrictlySimple (type-3) join
+        }
+      }
       UpdateEdgeIntoAEL(horzEdge);
       if (horzEdge->WindDelta == 0) return;
       //nb: HorzEdge is no longer horizontal here
@@ -2962,17 +3136,96 @@ void Clipper::DoMaxima(TEdge *e)
   if (!eMaxPair)
   {
     if (e->OutIdx >= 0)
+    {
       AddOutPt(e, e->Top);
+      if (e->WindDelta != 0)
+      {
+          TEdge* ePrev = e->PrevInAEL;
+          while (ePrev)
+          {
+            if (e->Top == ePrev->Top)
+            {
+                ePrev = ePrev->PrevInAEL;
+                continue;
+            }
+            if (ePrev->Curr.x != e->Curr.x) break;
+            if ((ePrev->OutIdx >= 0) && (ePrev->WindDelta != 0))
+            {
+              IntPoint pt = e->Curr;
+              AddOutPt(ePrev, pt);
+            }
+            ePrev = ePrev->PrevInAEL;
+          }
+          TEdge* eNext = e->NextInAEL;
+          while (eNext)
+          {
+            if (e->Top == eNext->Top)
+            {
+                eNext = eNext->NextInAEL;
+                continue;
+            }
+            if (eNext->Curr.x != e->Curr.x) break;
+            if ((eNext->OutIdx >= 0) && (eNext->WindDelta != 0))
+            {
+              IntPoint pt = e->Curr;
+              AddOutPt(eNext, pt);
+            }
+            eNext = eNext->NextInAEL;
+          }
+      }
+    }
     DeleteFromAEL(e);
     return;
   }
-
+  
+  IntPoint pt = e->Top;
   TEdge* eNext = e->NextInAEL;
-  while(eNext && eNext != eMaxPair)
+  TEdge* ePrev = e->PrevInAEL;
+  if (e->WindDelta != 0)
+  {
+      while (eNext)
+      {
+        if (pt == eNext->Top)
+        {
+            eNext = eNext->NextInAEL;
+            continue;
+        }
+        if (TopX(*eNext, pt.y) != pt.x)
+        {
+            eNext = 0;
+            break;
+        }
+        else if ((eNext->OutIdx >= 0) && (eNext->WindDelta != 0))
+        {
+            break;
+        }
+        eNext = eNext->NextInAEL;
+      }
+      while (ePrev)
+      {
+        if (pt == ePrev->Top)
+        {
+            ePrev = ePrev->PrevInAEL;
+            continue;
+        }
+        if (TopX(*ePrev, pt.y) != pt.x)
+        {
+            ePrev = 0;
+            break;
+        }
+        else if ((ePrev->OutIdx >= 0) && (ePrev->WindDelta != 0))
+        {
+            break;
+        }
+        ePrev = ePrev->PrevInAEL;
+      }
+  }
+  TEdge* eNext2 = e->NextInAEL;
+  while(eNext2 && eNext2 != eMaxPair)
   {
-    IntersectEdges(e, eNext, e->Top);
-    SwapPositionsInAEL(e, eNext);
-    eNext = e->NextInAEL;
+    IntersectEdges(e, eNext2, e->Top);
+    SwapPositionsInAEL(e, eNext2);
+    eNext2 = e->NextInAEL;
   }
 
   if(e->OutIdx == Unassigned && eMaxPair->OutIdx == Unassigned)
@@ -2982,9 +3235,17 @@ void Clipper::DoMaxima(TEdge *e)
   }
   else if( e->OutIdx >= 0 && eMaxPair->OutIdx >= 0 )
   {
-    if (e->OutIdx >= 0) AddLocalMaxPoly(e, eMaxPair, e->Top);
-    DeleteFromAEL(e);
-    DeleteFromAEL(eMaxPair);
+      AddLocalMaxPoly(e, eMaxPair, e->Top);
+      if (ePrev)
+      {
+        AddOutPt(ePrev, pt);
+      }
+      if (eNext)
+      {
+        AddOutPt(eNext, pt);
+      }
+      DeleteFromAEL(e);
+      DeleteFromAEL(eMaxPair);
   }
 #ifdef use_lines
   else if (e->WindDelta == 0)
@@ -3471,8 +3732,165 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
   if (isHorizontal  && (j->OffPt == j->OutPt1->Pt) &&
   (j->OffPt == j->OutPt2->Pt))
   {
+    if (outRec1 != outRec2)
+    {
+        // First Op1 Next and Op2 Prev
+        op1b = j->OutPt1->Next;
+        while (op1b != op1 && (op1b->Pt == j->OffPt)) 
+          op1b = op1b->Next;
+        op2b = j->OutPt2->Prev;
+        while (op2b != op2 && (op2b->Pt == j->OffPt)) 
+          op2b = op2b->Prev;
+        if (op1b->Pt == op2b->Pt)
+        {
+            OutPt* op1b_prev = op1b->Prev;
+            OutPt* op2b_next = op2b->Next;
+            op1b->Prev = op2b;
+            op2b->Next = op1b;
+            op1b_prev->Next = op2b_next;
+            op2b_next->Prev = op1b_prev;
+            return true;
+        }
+        bool reverse1 = (op1b->Pt.y > j->OffPt.y);
+        
+        // Second Op1 Prev and Op2 Next
+        op2b = j->OutPt2->Next;
+        while (op2b != op2 && (op2b->Pt == j->OffPt)) 
+          op2b = op2b->Next;
+        op1b = j->OutPt1->Prev;
+        while (op1b != op1 && (op1b->Pt == j->OffPt)) 
+          op1b = op1b->Prev;
+        if (op2b->Pt == op1b->Pt)
+        {
+            OutPt* op2b_prev = op2b->Prev;
+            OutPt* op1b_next = op1b->Next;
+            op2b->Prev = op1b;
+            op1b->Next = op2b;
+            op2b_prev->Next = op1b_next;
+            op1b_next->Prev = op2b_prev;
+            return true;
+        }
+        bool reverse2 = (op2b->Pt.y > j->OffPt.y);
+        if (reverse1 == reverse2) return false;
+        // See if there was a situation where these 
+        // two were split into seperate polygons
+        // with a SS join
+        for (auto & sj : m_SSJoins)
+        {
+            if (!sj->OutPt1 || !sj->OutPt2) continue;
+            OutRec *sjOutRec1 = GetOutRec(sj->OutPt1->Idx);
+            OutRec *sjOutRec2 = GetOutRec(sj->OutPt2->Idx);
+            if (sjOutRec1->Idx == outRec1->Idx && sjOutRec2->Idx == outRec2->Idx)
+            {
+                // We a previous SS join that has the same ids, so we might need to make
+                // a different join type.
+                op1b = j->OutPt1->Next;
+                while (op1b != op1 && op1b != sj->OutPt1)
+                {
+                    op1b = op1b->Next;
+                }
+                if (op1b == op1) continue;
+                op2b = j->OutPt2->Next;
+                while (op2b != op2 && op2b != sj->OutPt2)
+                {
+                    op2b = op2b->Next;
+                }
+                if (op2b == op2) continue;
+                OutPt* op1b_next = op1b->Next;
+                OutPt* op2b_next = op2b->Next;
+                OutPt* op1_next = op1->Next;
+                OutPt* op2_next = op2->Next;
+                op2b->Next= op1b_next;
+                op1b->Next = op2b_next;
+                op2b_next->Prev = op1b;
+                op1b_next->Prev = op2b;
+                op2->Next= op1_next;
+                op1->Next = op2_next;
+                op2_next->Prev = op1;
+                op1_next->Prev = op2;
+                sj->OutPt1 = 0;
+                sj->OutPt2 = 0;
+            }
+            else if (sjOutRec1->Idx == outRec2->Idx && sjOutRec2->Idx == outRec1->Idx)
+            {
+                // We a previous SS join that has the same ids, so we might need to make
+                // a different join type.
+                op1b = j->OutPt1->Next;
+                while (op1b != op1 && op1b != sj->OutPt2)
+                {
+                    op1b = op1b->Next;
+                }
+                if (op1b == op1) continue;
+                op2b = j->OutPt2->Next;
+                while (op2b != op2 && op2b != sj->OutPt1)
+                {
+                    op2b = op2b->Next;
+                }
+                if (op2b == op2) continue;
+                OutPt* op1b_next = op1b->Next;
+                OutPt* op2b_next = op2b->Next;
+                OutPt* op1_next = op1->Next;
+                OutPt* op2_next = op2->Next;
+                op2b->Next= op1b_next;
+                op1b->Next = op2b_next;
+                op2b_next->Prev = op1b;
+                op1b_next->Prev = op2b;
+                op2->Next= op1_next;
+                op1->Next = op2_next;
+                op2_next->Prev = op1;
+                op1_next->Prev = op2;
+                sj->OutPt1 = 0;
+                sj->OutPt2 = 0;
+            }
+            else
+            {
+                continue;
+            }
+            // We still will return false here
+            // because if we returned true it would 
+            // continue and think these two polygons should be merged
+            bool holeState = (Area(j->OutPt1) > 0) && m_ReverseOutput;
+            if (outRec1->IsHole == holeState) // outRec1 is "parent"
+            {
+                outRec1->Pts = j->OutPt2;
+                outRec1->BottomPt = 0;
+                outRec2->Pts = 0;
+                outRec2->BottomPt = 0;
+                outRec2->Idx = outRec1->Idx;
+                outRec2->FirstLeft = outRec1;
+                outRec2->IsHole = outRec1->IsHole;
+                if (m_UsingPolyTree) FixupFirstLefts3(outRec2, outRec1);
+                OutRec * outRec3 = CreateOutRec();
+                outRec3->Pts = j->OutPt1;
+                UpdateOutPtIdxs(*outRec1);
+                UpdateOutPtIdxs(*outRec3);
+                outRec3->FirstLeft = outRec1->FirstLeft;
+                //fixup FirstLeft pointers that may need reassigning to OutRec3
+                if (m_UsingPolyTree) FixupFirstLefts1(outRec1, outRec3);
+            }
+            else
+            {
+                outRec2->Pts = j->OutPt1;
+                outRec2->BottomPt = 0;
+                outRec1->Pts = 0;
+                outRec1->BottomPt = 0;
+                outRec1->Idx = outRec2->Idx;
+                outRec1->FirstLeft = outRec2;
+                outRec1->IsHole = outRec2->IsHole;
+                if (m_UsingPolyTree) FixupFirstLefts3(outRec1, outRec2);
+                OutRec * outRec3 = CreateOutRec();
+                outRec3->Pts = j->OutPt2;
+                UpdateOutPtIdxs(*outRec2);
+                UpdateOutPtIdxs(*outRec3);
+                outRec3->FirstLeft = outRec2->FirstLeft;
+                //fixup FirstLeft pointers that may need reassigning to OutRec3
+                if (m_UsingPolyTree) FixupFirstLefts1(outRec2, outRec3);
+            }
+            return false;
+        }
+        return false;
+    }
     //Strictly Simple join ...
-    if (outRec1 != outRec2) return false;
     op1b = j->OutPt1->Next;
     while (op1b != op1 && (op1b->Pt == j->OffPt)) 
       op1b = op1b->Next;
@@ -3492,6 +3910,7 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
       op2b->Prev = op1b;
       j->OutPt1 = op1;
       j->OutPt2 = op1b;
+      AddSSJoin(op1, op1b, j->OffPt);
       return true;
     } else
     {
@@ -3503,6 +3922,7 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
       op2b->Next = op1b;
       j->OutPt1 = op1;
       j->OutPt2 = op1b;
+      AddSSJoin(op1, op1b, j->OffPt);
       return true;
     }
   } 
@@ -3760,6 +4180,7 @@ void Clipper::JoinCommonEdges()
       if (m_UsingPolyTree) FixupFirstLefts3(outRec2, outRec1);
     }
   }
+  ClearSSJoins();
 }
 
 //------------------------------------------------------------------------------
diff --git a/debian/clipper.hpp b/debian/clipper.hpp
index 7831b0b..d0845fe 100644
--- a/debian/clipper.hpp
+++ b/debian/clipper.hpp
@@ -320,6 +320,7 @@ protected:
 private:
   JoinList         m_Joins;
   JoinList         m_GhostJoins;
+  JoinList         m_SSJoins;
   IntersectList    m_IntersectList;
   ClipType         m_ClipType;
   typedef std::list<cInt> MaximaList;
@@ -373,7 +374,9 @@ private:
   void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt);
   void ClearJoins();
   void ClearGhostJoins();
+  void ClearSSJoins();
   void AddGhostJoin(OutPt *op, const IntPoint offPt);
+  void AddSSJoin(OutPt *op1, OutPt *op2, const IntPoint offPt);
   bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2);
   void JoinCommonEdges();
   void DoSimplePolygons();

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/mapnik-vector-tile.git



More information about the Pkg-grass-devel mailing list