// File: /workspace/github_cpp_makefile_star2_O3/hzeller[P]gcode-multi-shell-extrude/third_party/clipper.cpp
// Function: ClipperLib::Clipper::JoinPoints(ClipperLib::Join*, ClipperLib::OutRec*, ClipperLib::OutRec*)
bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
{
  OutPt *op1 = j->OutPt1, *op1b;
  OutPt *op2 = j->OutPt2, *op2b;

  //There are 3 kinds of joins for output polygons ...
  //1. Horizontal joins where Join.OutPt1 & Join.OutPt2 are a vertices anywhere
  //along (horizontal) collinear edges (& Join.OffPt is on the same horizontal).
  //2. Non-horizontal joins where Join.OutPt1 & Join.OutPt2 are at the same
  //location at the Bottom of the overlapping segment (& Join.OffPt is above).
  //3. StrictSimple joins where edges touch but are not collinear and where
  //Join.OutPt1, Join.OutPt2 & Join.OffPt all share the same point.
  bool isHorizontal = (j->OutPt1->Pt.Y == j->OffPt.Y);

  if (isHorizontal  && (j->OffPt == j->OutPt1->Pt) &&
  (j->OffPt == j->OutPt2->Pt))
  {
    //Strictly Simple join ...
    op1b = j->OutPt1->Next;
    while (op1b != op1 && (op1b->Pt == j->OffPt)) 
      op1b = op1b->Next;
    bool reverse1 = (op1b->Pt.Y > j->OffPt.Y);
    op2b = j->OutPt2->Next;
    while (op2b != op2 && (op2b->Pt == j->OffPt)) 
      op2b = op2b->Next;
    bool reverse2 = (op2b->Pt.Y > j->OffPt.Y);
    if (reverse1 == reverse2) return false;
    if (reverse1)
    {
      op1b = DupOutPt(op1, false);
      op2b = DupOutPt(op2, true);
      op1->Prev = op2;
      op2->Next = op1;
      op1b->Next = op2b;
      op2b->Prev = op1b;
      j->OutPt1 = op1;
      j->OutPt2 = op1b;
      return true;
    } else
    {
      op1b = DupOutPt(op1, true);
      op2b = DupOutPt(op2, false);
      op1->Next = op2;
      op2->Prev = op1;
      op1b->Prev = op2b;
      op2b->Next = op1b;
      j->OutPt1 = op1;
      j->OutPt2 = op1b;
      return true;
    }
  } 
  else if (isHorizontal)
  {
    //treat horizontal joins differently to non-horizontal joins since with
    //them we're not yet sure where the overlapping is. OutPt1.Pt & OutPt2.Pt
    //may be anywhere along the horizontal edge.
    op1b = op1;
    while (op1->Prev->Pt.Y == op1->Pt.Y && op1->Prev != op1b && op1->Prev != op2)
      op1 = op1->Prev;
    while (op1b->Next->Pt.Y == op1b->Pt.Y && op1b->Next != op1 && op1b->Next != op2)
      op1b = op1b->Next;
    if (op1b->Next == op1 || op1b->Next == op2) return false; //a flat 'polygon'

    op2b = op2;
    while (op2->Prev->Pt.Y == op2->Pt.Y && op2->Prev != op2b && op2->Prev != op1b)
      op2 = op2->Prev;
    while (op2b->Next->Pt.Y == op2b->Pt.Y && op2b->Next != op2 && op2b->Next != op1)
      op2b = op2b->Next;
    if (op2b->Next == op2 || op2b->Next == op1) return false; //a flat 'polygon'

    cInt Left, Right;
    //Op1 --> Op1b & Op2 --> Op2b are the extremites of the horizontal edges
    if (!GetOverlap(op1->Pt.X, op1b->Pt.X, op2->Pt.X, op2b->Pt.X, Left, Right))
      return false;

    //DiscardLeftSide: when overlapping edges are joined, a spike will created
    //which needs to be cleaned up. However, we don't want Op1 or Op2 caught up
    //on the discard Side as either may still be needed for other joins ...
    IntPoint Pt;
    bool DiscardLeftSide;
    if (op1->Pt.X >= Left && op1->Pt.X <= Right) 
    {
      Pt = op1->Pt; DiscardLeftSide = (op1->Pt.X > op1b->Pt.X);
    } 
    else if (op2->Pt.X >= Left&& op2->Pt.X <= Right) 
    {
      Pt = op2->Pt; DiscardLeftSide = (op2->Pt.X > op2b->Pt.X);
    } 
    else if (op1b->Pt.X >= Left && op1b->Pt.X <= Right)
    {
      Pt = op1b->Pt; DiscardLeftSide = op1b->Pt.X > op1->Pt.X;
    } 
    else
    {
      Pt = op2b->Pt; DiscardLeftSide = (op2b->Pt.X > op2->Pt.X);
    }
    j->OutPt1 = op1; j->OutPt2 = op2;
    return JoinHorz(op1, op1b, op2, op2b, Pt, DiscardLeftSide);
  } else
  {
    //nb: For non-horizontal joins ...
    //    1. Jr.OutPt1.Pt.Y == Jr.OutPt2.Pt.Y
    //    2. Jr.OutPt1.Pt > Jr.OffPt.Y

    //make sure the polygons are correctly oriented ...
    op1b = op1->Next;
    while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Next;
    bool Reverse1 = ((op1b->Pt.Y > op1->Pt.Y) ||
      !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange));
    if (Reverse1)
    {
      op1b = op1->Prev;
      while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Prev;
      if ((op1b->Pt.Y > op1->Pt.Y) ||
        !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)) return false;
    };
    op2b = op2->Next;
    while ((op2b->Pt == op2->Pt) && (op2b != op2))op2b = op2b->Next;
    bool Reverse2 = ((op2b->Pt.Y > op2->Pt.Y) ||
      !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange));
    if (Reverse2)
    {
      op2b = op2->Prev;
      while ((op2b->Pt == op2->Pt) && (op2b != op2)) op2b = op2b->Prev;
      if ((op2b->Pt.Y > op2->Pt.Y) ||
        !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)) return false;
    }

    if ((op1b == op1) || (op2b == op2) || (op1b == op2b) ||
      ((outRec1 == outRec2) && (Reverse1 == Reverse2))) return false;

    if (Reverse1)
    {
      op1b = DupOutPt(op1, false);
      op2b = DupOutPt(op2, true);
      op1->Prev = op2;
      op2->Next = op1;
      op1b->Next = op2b;
      op2b->Prev = op1b;
      j->OutPt1 = op1;
      j->OutPt2 = op1b;
      return true;
    } else
    {
      op1b = DupOutPt(op1, true);
      op2b = DupOutPt(op2, false);
      op1->Next = op2;
      op2->Prev = op1;
      op1b->Prev = op2b;
      op2b->Next = op1b;
      j->OutPt1 = op1;
      j->OutPt2 = op1b;
      return true;
    }
  }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rsi, %r10
movq %rdi, %rsi
movq (%r10), %rbp
movq 0x8(%r10), %r15
leaq 0x8(%rbp), %rdi
movq 0x8(%rbp), %r14
movq 0x10(%rbp), %r12
movq 0x18(%r10), %r9
cmpq %r9, %r12
jne 0xe2d4
movq 0x10(%r10), %rax
movq %rbp, %rcx
cmpq %r14, %rax
jne 0xe1f4
movq %rbp, %rcx
cmpq 0x8(%r15), %rax
jne 0xe1f4
movq %rbp, %rcx
cmpq 0x10(%r15), %r12
jne 0xe1f4
leaq 0x8(%r15), %r8
movq %rbp, %rdx
movq 0x18(%rdx), %rdx
cmpq %rbp, %rdx
je 0xe535
movq 0x10(%rdx), %rcx
cmpq %rax, 0x8(%rdx)
jne 0xe539
cmpq %r12, %rcx
je 0xe1cf
jmp 0xe539
movq %rcx, %rdi
movq 0x20(%rcx), %rcx
cmpq %rbp, %rcx
je 0xe20b
cmpq %r12, 0x10(%rcx)
jne 0xe20b
cmpq %r15, %rcx
jne 0xe1f4
leaq 0x10(%rdi), %r9
movq %rbp, %rsi
movq 0x18(%rbp), %rbp
cmpq %rdi, %rbp
je 0xe226
cmpq %r12, 0x10(%rbp)
jne 0xe226
cmpq %r15, %rbp
jne 0xe20f
cmpq %r15, %rbp
sete %al
cmpq %rdi, %rbp
sete %cl
orb %al, %cl
jne 0xe67a
movq %r10, %rbp
leaq 0x10(%rsi), %rax
movq 0x10(%r15), %r8
movq %r15, %rcx
movq %rcx, %rdx
movq 0x20(%rcx), %rcx
cmpq %rsi, %rcx
je 0xe25f
cmpq %r8, 0x10(%rcx)
jne 0xe25f
cmpq %r15, %rcx
jne 0xe248
leaq 0x10(%rdx), %r10
movq %r15, %rcx
movq 0x18(%r15), %r15
cmpq %rdi, %r15
je 0xe27a
cmpq %rdx, %r15
je 0xe27a
cmpq %r8, 0x10(%r15)
je 0xe263
cmpq %rdi, %r15
sete %r8b
cmpq %rdx, %r15
sete %r11b
orb %r8b, %r11b
jne 0xe67a
movq 0x8(%rdi), %r15
movq 0x8(%rsi), %r8
movq 0x8(%rdx), %r14
movq 0x8(%rcx), %rbx
cmpq %rbx, %r14
setl 0x20(%rsp)
cmpq %r8, %r15
setl %r11b
jge 0xe618
cmpq %rbx, %r14
jge 0xe633
cmpq %r14, %r15
movq %r14, %r12
cmovgq %r15, %r12
cmpq %r8, %rbx
movq %r8, %r13
jmp 0xe62d
movq %rdx, 0x48(%rsp)
movq %rcx, 0x50(%rsp)
movq %rdi, 0x20(%rsp)
leaq 0x18(%rbp), %rax
movq (%rax), %r13
movq 0x8(%r13), %rdx
movq 0x10(%r13), %rcx
cmpq %rbp, %r13
je 0xe305
cmpq %r14, %rdx
jne 0xe305
leaq 0x18(%r13), %rax
cmpq %r12, %rcx
je 0xe2e7
cmpq %r12, %rcx
movq %r10, 0x28(%rsp)
jg 0xe359
movq 0x10(%r10), %r8
movq (%rsi), %rax
movq -0x18(%rax), %rax
movzbl 0x18(%rsi,%rax), %eax
movl %eax, 0x14(%rsp)
movl %eax, (%rsp)
movq %r14, %rdi
movq %rsi, 0x38(%rsp)
movq %r12, %rsi
movq %r8, 0x18(%rsp)
movq %r9, %rbx
callq 0x8a01
movq 0x38(%rsp), %rsi
movq %rbx, %r9
movq 0x28(%rsp), %r10
testb %al, %al
je 0xe359
movl $0x0, 0x34(%rsp)
jmp 0xe3c0
movq %rbp, %r13
movq 0x20(%r13), %r13
movq 0x8(%r13), %rdx
movq 0x10(%r13), %rcx
cmpq %rbp, %r13
je 0xe377
cmpq %r14, %rdx
jne 0xe377
cmpq %r12, %rcx
je 0xe35c
cmpq %r12, %rcx
jg 0xe67a
movq 0x10(%r10), %r8
movq (%rsi), %rax
movq -0x18(%rax), %rax
movzbl 0x18(%rsi,%rax), %eax
movl %eax, 0x14(%rsp)
movl %eax, (%rsp)
movq %r14, %rdi
movq %r12, %rsi
movq %r8, 0x18(%rsp)
movq %r9, %rbx
callq 0x8a01
testb %al, %al
je 0xe67a
movb $0x1, %al
movl %eax, 0x34(%rsp)
movq 0x28(%rsp), %r10
movq %rbx, %r9
leaq 0x18(%r15), %rax
leaq 0x8(%r15), %rcx
movq %rcx, 0x40(%rsp)
movq 0x8(%r15), %r14
movq 0x10(%r15), %r12
movq (%rax), %rbx
movq 0x8(%rbx), %rdx
movq 0x10(%rbx), %rcx
cmpq %r14, %rdx
jne 0xe3f3
cmpq %r12, %rcx
jne 0xe3f3
leaq 0x18(%rbx), %rax
cmpq %r15, %rbx
jne 0xe3d5
cmpq %r12, %rcx
jg 0xe42c
movzbl 0x14(%rsp), %eax
movl %eax, (%rsp)
movq %r14, %rdi
movq %r12, %rsi
movq 0x18(%rsp), %r8
movq %r9, 0x38(%rsp)
movq 0x38(%rsp), %r9
callq 0x8a01
movq 0x38(%rsp), %r9
movq 0x28(%rsp), %r10
testb %al, %al
je 0xe42c
xorl %ecx, %ecx
jmp 0xe47b
movq %r15, %rbx
movq 0x20(%rbx), %rbx
movq 0x8(%rbx), %rdx
movq 0x10(%rbx), %rcx
cmpq %r14, %rdx
jne 0xe44a
cmpq %r12, %rcx
jne 0xe44a
cmpq %r15, %rbx
jne 0xe42f
cmpq %r12, %rcx
jg 0xe67a
movzbl 0x14(%rsp), %eax
movl %eax, (%rsp)
movq %r14, %rdi
movq %r12, %rsi
movq %r10, %r14
movq 0x18(%rsp), %r8
callq 0x8a01
movq %r14, %r10
movb $0x1, %cl
testb %al, %al
je 0xe67a
xorl %r14d, %r14d
cmpq %rbx, %r13
je 0xe67d
cmpq %rbp, %r13
je 0xe67d
cmpq %r15, %rbx
je 0xe67d
movq 0x48(%rsp), %rax
cmpq 0x50(%rsp), %rax
sete %al
movl 0x34(%rsp), %r12d
xorb %r12b, %cl
xorb $0x1, %cl
testb %cl, %al
jne 0xe67a
movq %r10, %rbx
movl $0x28, %edi
callq 0x3210
movq %rax, %r14
movq 0x20(%rsp), %rax
movups (%rax), %xmm0
movups %xmm0, 0x8(%r14)
movl (%rbp), %eax
movl %eax, (%r14)
testb %r12b, %r12b
je 0xe6a8
movq 0x20(%rbp), %rax
movq %rax, 0x20(%r14)
movq %rbp, 0x18(%r14)
movq %r14, 0x18(%rax)
movq %r14, 0x20(%rbp)
movl $0x28, %edi
callq 0x3210
movq 0x40(%rsp), %rcx
movups (%rcx), %xmm0
movups %xmm0, 0x8(%rax)
movl (%r15), %ecx
movl %ecx, (%rax)
movq 0x18(%r15), %rcx
movq %rcx, 0x18(%rax)
movq %rax, 0x20(%rcx)
movq %r15, 0x20(%rbp)
movq %rbp, 0x18(%r15)
movq %rax, 0x18(%r14)
movq %r14, 0x20(%rax)
jmp 0xe6f3
movq 0x10(%rdx), %rcx
movq %r15, %rsi
movq 0x18(%rsi), %rsi
cmpq %r15, %rsi
je 0xe556
movq 0x10(%rsi), %rdx
cmpq %rax, 0x8(%rsi)
jne 0xe55a
cmpq %r12, %rdx
je 0xe53c
jmp 0xe55a
movq 0x10(%rsi), %rdx
cmpq %r12, %rcx
setg %al
cmpq %r12, %rdx
setle %r14b
xorb %al, %r14b
jne 0xe612
xorl %eax, %eax
movq %rdi, 0x20(%rsp)
xorl %r13d, %r13d
cmpq %r12, %rcx
setle %al
movq %rax, %r12
setg %r13b
movl $0x28, %edi
movq %r10, 0x28(%rsp)
movq %r8, 0x18(%rsp)
callq 0x3210
movq %rax, %rbx
movq 0x20(%rsp), %rax
movups (%rax), %xmm0
movups %xmm0, 0x8(%rbx)
movl (%rbp), %eax
movl %eax, (%rbx)
movq 0x18(%rbp,%r13,8), %rax
movq %rax, 0x18(%rbx,%r13,8)
movq %rbp, 0x18(%rbx,%r12,8)
movq %rbx, 0x18(%rax,%r12,8)
movq %rbx, 0x18(%rbp,%r13,8)
movl $0x28, %edi
callq 0x3210
movq 0x18(%rsp), %rcx
movups (%rcx), %xmm0
movups %xmm0, 0x8(%rax)
movl (%r15), %ecx
movl %ecx, (%rax)
movq 0x18(%r15,%r12,8), %rcx
movq %rcx, 0x18(%rax,%r12,8)
movq %rax, 0x18(%rcx,%r13,8)
movq %r15, 0x18(%rbp,%r13,8)
movq %rbp, 0x18(%r15,%r12,8)
movq %rax, 0x18(%rbx,%r12,8)
movq %rbx, 0x18(%rax,%r13,8)
movq 0x28(%rsp), %rax
movq %rbp, (%rax)
movq %rbx, 0x8(%rax)
xorb $0x1, %r14b
jmp 0xe67d
cmpq %rbx, %r14
jge 0xe645
cmpq %r14, %r8
movq %r14, %r12
cmovgq %r8, %r12
cmpq %r15, %rbx
movq %r15, %r13
cmovlq %rbx, %r13
jmp 0xe659
cmpq %rbx, %r15
movq %rbx, %r12
cmovgq %r15, %r12
cmpq %r8, %r14
movq %r8, %r13
jmp 0xe655
cmpq %rbx, %r8
movq %rbx, %r12
cmovgq %r8, %r12
cmpq %r15, %r14
movq %r15, %r13
cmovlq %r14, %r13
cmpq %r13, %r12
jge 0xe67a
cmpq %r12, %r15
jl 0xe68f
cmpq %r13, %r15
jg 0xe68f
cmpq %r8, %r15
setg %r11b
movq %r9, %rax
movq %r15, %r8
jmp 0xe718
xorl %r14d, %r14d
movl %r14d, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpq %r12, %r14
jl 0xe702
cmpq %r13, %r14
jg 0xe702
cmpq %rbx, %r14
setg %r11b
movq %r10, %rax
movq %r14, %r8
jmp 0xe718
movq 0x18(%rbp), %rax
movq %rax, 0x18(%r14)
movq %rbp, 0x20(%r14)
movq %r14, 0x20(%rax)
movq %r14, 0x18(%rbp)
movl $0x28, %edi
callq 0x3210
movq 0x40(%rsp), %rcx
movups (%rcx), %xmm0
movups %xmm0, 0x8(%rax)
movl (%r15), %ecx
movl %ecx, (%rax)
movq 0x20(%r15), %rcx
movq %rcx, 0x20(%rax)
movq %rax, 0x18(%rcx)
movq %r15, 0x18(%rbp)
movq %rbp, 0x20(%r15)
movq %rax, 0x20(%r14)
movq %r14, 0x18(%rax)
movq %rbp, (%rbx)
movq %r14, 0x8(%rbx)
movb $0x1, %r14b
jmp 0xe67d
cmpq %r12, %r8
jl 0xe70c
cmpq %r13, %r8
jle 0xe718
leaq 0x10(%rcx), %rax
movq %rbx, %r8
movb 0x20(%rsp), %r11b
movq (%rax), %r9
movq %rdi, (%rbp)
movq %rdx, 0x8(%rbp)
movzbl %r11b, %eax
movl %eax, (%rsp)
callq 0xde8e
jmp 0xe680