// File: hzeller[P]gcode-multi-shell-extrude/third_party/clipper.cpp
// Function: ClipperLib::Clipper::JoinCommonEdges()
void Clipper::JoinCommonEdges()
{
  for (JoinList::size_type i = 0; i < m_Joins.size(); i++)
  {
    Join* join = m_Joins[i];

    OutRec *outRec1 = GetOutRec(join->OutPt1->Idx);
    OutRec *outRec2 = GetOutRec(join->OutPt2->Idx);

    if (!outRec1->Pts || !outRec2->Pts) continue;

    //get the polygon fragment with the correct hole state (FirstLeft)
    //before calling JoinPoints() ...
    OutRec *holeStateRec;
    if (outRec1 == outRec2) holeStateRec = outRec1;
    else if (Param1RightOfParam2(outRec1, outRec2)) holeStateRec = outRec2;
    else if (Param1RightOfParam2(outRec2, outRec1)) holeStateRec = outRec1;
    else holeStateRec = GetLowermostRec(outRec1, outRec2);

    if (!JoinPoints(join, outRec1, outRec2)) continue;

    if (outRec1 == outRec2)
    {
      //instead of joining two polygons, we've just created a new one by
      //splitting one polygon into two.
      outRec1->Pts = join->OutPt1;
      outRec1->BottomPt = 0;
      outRec2 = CreateOutRec();
      outRec2->Pts = join->OutPt2;

      //update all OutRec2.Pts Idx's ...
      UpdateOutPtIdxs(*outRec2);

      //We now need to check every OutRec.FirstLeft pointer. If it points
      //to OutRec1 it may need to point to OutRec2 instead ...
      if (m_UsingPolyTree)
        for (PolyOutList::size_type j = 0; j < m_PolyOuts.size() - 1; j++)
        {
          OutRec* oRec = m_PolyOuts[j];
          if (!oRec->Pts || ParseFirstLeft(oRec->FirstLeft) != outRec1 ||
            oRec->IsHole == outRec1->IsHole) continue;
          if (Poly2ContainsPoly1(oRec->Pts, join->OutPt2))
            oRec->FirstLeft = outRec2;
        }

      if (Poly2ContainsPoly1(outRec2->Pts, outRec1->Pts))
      {
        //outRec2 is contained by outRec1 ...
        outRec2->IsHole = !outRec1->IsHole;
        outRec2->FirstLeft = outRec1;

        //fixup FirstLeft pointers that may need reassigning to OutRec1
        if (m_UsingPolyTree) FixupFirstLefts2(outRec2, outRec1);

        if ((outRec2->IsHole ^ m_ReverseOutput) == (Area(*outRec2) > 0))
          ReversePolyPtLinks(outRec2->Pts);
            
      } else if (Poly2ContainsPoly1(outRec1->Pts, outRec2->Pts))
      {
        //outRec1 is contained by outRec2 ...
        outRec2->IsHole = outRec1->IsHole;
        outRec1->IsHole = !outRec2->IsHole;
        outRec2->FirstLeft = outRec1->FirstLeft;
        outRec1->FirstLeft = outRec2;

        //fixup FirstLeft pointers that may need reassigning to OutRec1
        if (m_UsingPolyTree) FixupFirstLefts2(outRec1, outRec2);

        if ((outRec1->IsHole ^ m_ReverseOutput) == (Area(*outRec1) > 0))
          ReversePolyPtLinks(outRec1->Pts);
      } 
      else
      {
        //the 2 polygons are completely separate ...
        outRec2->IsHole = outRec1->IsHole;
        outRec2->FirstLeft = outRec1->FirstLeft;

        //fixup FirstLeft pointers that may need reassigning to OutRec2
        if (m_UsingPolyTree) FixupFirstLefts1(outRec1, outRec2);
      }
     
    } else
    {
      //joined 2 polygons together ...

      outRec2->Pts = 0;
      outRec2->BottomPt = 0;
      outRec2->Idx = outRec1->Idx;

      outRec1->IsHole = holeStateRec->IsHole;
      if (holeStateRec == outRec2) 
        outRec1->FirstLeft = outRec2->FirstLeft;
      outRec2->FirstLeft = outRec1;

      //fixup FirstLeft pointers that may need reassigning to OutRec1
      if (m_UsingPolyTree) FixupFirstLefts2(outRec2, outRec1);
    }
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x48(%rbp)
movq $0x0, -0x10(%rbp)
movq -0x48(%rbp), %rdi
movq -0x10(%rbp), %rax
movq %rax, -0x50(%rbp)
addq $0x20, %rdi
callq 0x20f90
movq %rax, %rcx
movq -0x50(%rbp), %rax
cmpq %rcx, %rax
jae 0x16713
movq -0x48(%rbp), %rdi
addq $0x20, %rdi
movq -0x10(%rbp), %rsi
callq 0x20fb0
movq -0x48(%rbp), %rdi
movq (%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rax
movl (%rax), %esi
callq 0x18a30
movq -0x48(%rbp), %rdi
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movl (%rax), %esi
callq 0x18a30
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rax
cmpq $0x0, 0x18(%rax)
je 0x1631c
movq -0x28(%rbp), %rax
cmpq $0x0, 0x18(%rax)
jne 0x16321
jmp 0x16702
movq -0x20(%rbp), %rax
cmpq -0x28(%rbp), %rax
jne 0x16335
movq -0x20(%rbp), %rax
movq %rax, -0x30(%rbp)
jmp 0x16384
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0x189f0
testb $0x1, %al
jne 0x16348
jmp 0x16352
movq -0x28(%rbp), %rax
movq %rax, -0x30(%rbp)
jmp 0x16382
movq -0x28(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x189f0
testb $0x1, %al
jne 0x16365
jmp 0x1636f
movq -0x20(%rbp), %rax
movq %rax, -0x30(%rbp)
jmp 0x16380
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0x188a0
movq %rax, -0x30(%rbp)
jmp 0x16382
jmp 0x16384
movq -0x48(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
movq -0x28(%rbp), %rcx
callq 0x1ac20
testb $0x1, %al
jne 0x163a2
jmp 0x16702
movq -0x20(%rbp), %rax
cmpq -0x28(%rbp), %rax
jne 0x16685
movq -0x48(%rbp), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x20(%rbp), %rax
movq $0x0, 0x20(%rax)
callq 0x18ab0
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x28(%rbp), %rdi
callq 0x21990
movq -0x48(%rbp), %rax
testb $0x1, 0xbd(%rax)
je 0x164c4
movq $0x0, -0x38(%rbp)
movq -0x48(%rbp), %rdi
movq -0x38(%rbp), %rax
movq %rax, -0x58(%rbp)
addq $0x8, %rdi
callq 0x20d70
movq %rax, %rcx
movq -0x58(%rbp), %rax
subq $0x1, %rcx
cmpq %rcx, %rax
jae 0x164c2
movq -0x48(%rbp), %rdi
addq $0x8, %rdi
movq -0x38(%rbp), %rsi
callq 0x20d90
movq (%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
cmpq $0x0, 0x18(%rax)
je 0x16486
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x1b980
cmpq -0x20(%rbp), %rax
jne 0x16486
movq -0x40(%rbp), %rax
movb 0x4(%rax), %al
andb $0x1, %al
movzbl %al, %eax
movq -0x20(%rbp), %rcx
movb 0x4(%rcx), %cl
andb $0x1, %cl
movzbl %cl, %ecx
cmpl %ecx, %eax
jne 0x16488
jmp 0x164b1
movq -0x40(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rsi
callq 0x11850
testb $0x1, %al
jne 0x164a3
jmp 0x164af
movq -0x28(%rbp), %rcx
movq -0x40(%rbp), %rax
movq %rcx, 0x8(%rax)
jmp 0x164b1
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
jmp 0x1640a
jmp 0x164c4
movq -0x28(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x20(%rbp), %rax
movq 0x18(%rax), %rsi
callq 0x11850
testb $0x1, %al
jne 0x164e2
jmp 0x16573
movq -0x48(%rbp), %rax
movq -0x20(%rbp), %rcx
movb 0x4(%rcx), %dl
xorb $-0x1, %dl
movq -0x28(%rbp), %rcx
andb $0x1, %dl
movb %dl, 0x4(%rcx)
movq -0x20(%rbp), %rdx
movq -0x28(%rbp), %rcx
movq %rdx, 0x8(%rcx)
testb $0x1, 0xbd(%rax)
je 0x16520
movq -0x48(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x1b8f0
movq -0x48(%rbp), %rcx
movq -0x28(%rbp), %rax
movb 0x4(%rax), %al
andb $0x1, %al
movzbl %al, %eax
movb 0xbc(%rcx), %cl
andb $0x1, %cl
movzbl %cl, %ecx
xorl %ecx, %eax
movl %eax, -0x5c(%rbp)
movq -0x28(%rbp), %rdi
callq 0x110f0
movl -0x5c(%rbp), %eax
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
seta %cl
andb $0x1, %cl
movzbl %cl, %ecx
cmpl %ecx, %eax
jne 0x1656e
movq -0x28(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x11ec0
jmp 0x16683
movq -0x20(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x28(%rbp), %rax
movq 0x18(%rax), %rsi
callq 0x11850
testb $0x1, %al
jne 0x16591
jmp 0x16640
movq -0x48(%rbp), %rax
movq -0x20(%rbp), %rcx
movb 0x4(%rcx), %dl
movq -0x28(%rbp), %rcx
andb $0x1, %dl
movb %dl, 0x4(%rcx)
movq -0x28(%rbp), %rcx
movb 0x4(%rcx), %dl
xorb $-0x1, %dl
movq -0x20(%rbp), %rcx
andb $0x1, %dl
movb %dl, 0x4(%rcx)
movq -0x20(%rbp), %rcx
movq 0x8(%rcx), %rdx
movq -0x28(%rbp), %rcx
movq %rdx, 0x8(%rcx)
movq -0x28(%rbp), %rdx
movq -0x20(%rbp), %rcx
movq %rdx, 0x8(%rcx)
testb $0x1, 0xbd(%rax)
je 0x165f0
movq -0x48(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x28(%rbp), %rdx
callq 0x1b8f0
movq -0x48(%rbp), %rcx
movq -0x20(%rbp), %rax
movb 0x4(%rax), %al
andb $0x1, %al
movzbl %al, %eax
movb 0xbc(%rcx), %cl
andb $0x1, %cl
movzbl %cl, %ecx
xorl %ecx, %eax
movl %eax, -0x60(%rbp)
movq -0x20(%rbp), %rdi
callq 0x110f0
movl -0x60(%rbp), %eax
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
seta %cl
andb $0x1, %cl
movzbl %cl, %ecx
cmpl %ecx, %eax
jne 0x1663e
movq -0x20(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x11ec0
jmp 0x16681
movq -0x48(%rbp), %rax
movq -0x20(%rbp), %rcx
movb 0x4(%rcx), %dl
movq -0x28(%rbp), %rcx
andb $0x1, %dl
movb %dl, 0x4(%rcx)
movq -0x20(%rbp), %rcx
movq 0x8(%rcx), %rdx
movq -0x28(%rbp), %rcx
movq %rdx, 0x8(%rcx)
testb $0x1, 0xbd(%rax)
je 0x1667f
movq -0x48(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x28(%rbp), %rdx
callq 0x1b830
jmp 0x16681
jmp 0x16683
jmp 0x16700
movq -0x28(%rbp), %rax
movq $0x0, 0x18(%rax)
movq -0x28(%rbp), %rax
movq $0x0, 0x20(%rax)
movq -0x20(%rbp), %rax
movl (%rax), %ecx
movq -0x28(%rbp), %rax
movl %ecx, (%rax)
movq -0x30(%rbp), %rax
movb 0x4(%rax), %cl
movq -0x20(%rbp), %rax
andb $0x1, %cl
movb %cl, 0x4(%rax)
movq -0x30(%rbp), %rax
cmpq -0x28(%rbp), %rax
jne 0x166d4
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x48(%rbp), %rax
movq -0x20(%rbp), %rdx
movq -0x28(%rbp), %rcx
movq %rdx, 0x8(%rcx)
testb $0x1, 0xbd(%rax)
je 0x166fe
movq -0x48(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x1b8f0
jmp 0x16700
jmp 0x16702
movq -0x10(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x10(%rbp)
jmp 0x1629c
addq $0x60, %rsp
popq %rbp
retq
nopl (%rax)