// File: /workspace/github_cpp_makefile_star2_O2/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, %r14
movq %rdi, %r10
movq (%rsi), %r13
movq 0x8(%rsi), %rdi
movq 0x8(%r13), %r12
movq 0x10(%r13), %rbp
movq 0x18(%rsi), %r9
cmpq %r9, %rbp
jne 0xc98a
movq 0x10(%r14), %rax
movq %r13, %rcx
cmpq %r12, %rax
jne 0xc852
movq %r13, %rcx
cmpq 0x8(%rdi), %rax
jne 0xc852
movq %r13, %rcx
cmpq 0x10(%rdi), %rbp
jne 0xc852
movq %r13, %rdx
movq 0x18(%rdx), %rdx
cmpq %r13, %rdx
je 0xcb9c
movq 0x10(%rdx), %rcx
cmpq %rax, 0x8(%rdx)
jne 0xcba0
cmpq %rbp, %rcx
je 0xc82d
jmp 0xcba0
movq %rcx, %r12
movq 0x20(%rcx), %rcx
cmpq %r13, %rcx
je 0xc869
cmpq %rbp, 0x10(%rcx)
jne 0xc869
cmpq %rdi, %rcx
jne 0xc852
leaq 0x10(%r12), %rdx
movq %r13, %rbx
movq 0x18(%r13), %r13
cmpq %r12, %r13
je 0xc885
cmpq %rbp, 0x10(%r13)
jne 0xc885
cmpq %rdi, %r13
jne 0xc86e
cmpq %rdi, %r13
sete %al
cmpq %r12, %r13
sete %cl
orb %al, %cl
jne 0xcb87
movq %r14, %r13
leaq 0x10(%rbx), %rsi
movq 0x10(%rdi), %rax
movq %rdi, %rcx
movq %rcx, %r15
movq 0x20(%rcx), %rcx
cmpq %rbx, %rcx
je 0xc8be
cmpq %rax, 0x10(%rcx)
jne 0xc8be
cmpq %rdi, %rcx
jne 0xc8a7
leaq 0x10(%r15), %r14
movq %rdi, %rbp
movq 0x18(%rdi), %rdi
cmpq %r12, %rdi
je 0xc8d9
cmpq %r15, %rdi
je 0xc8d9
cmpq %rax, 0x10(%rdi)
je 0xc8c2
cmpq %r12, %rdi
sete %al
cmpq %r15, %rdi
sete %cl
orb %al, %cl
jne 0xcb87
movq %rsi, 0x18(%rsp)
movq %rdx, 0x10(%rsp)
movq 0x8(%r12), %rdi
movq 0x8(%rbx), %rsi
movq 0x8(%r15), %rdx
movq 0x8(%rbp), %rcx
leaq 0x50(%rsp), %r8
leaq 0x48(%rsp), %r9
callq 0xc4f5
testb %al, %al
je 0xcb87
movq 0x8(%r12), %r8
movq 0x50(%rsp), %rcx
cmpq %rcx, %r8
setl %al
movq 0x48(%rsp), %rdx
cmpq %rdx, %r8
setg %sil
orb %al, %sil
je 0xcc2a
movq 0x8(%r15), %rax
cmpq %rcx, %rax
setl %sil
cmpq %rdx, %rax
setg %dil
orb %sil, %dil
je 0xcc79
movq 0x8(%rbx), %rsi
cmpq %rcx, %rsi
setl %cl
cmpq %rdx, %rsi
setg %dl
orb %cl, %dl
je 0xcc85
leaq 0x10(%rbp), %r14
movq 0x8(%rbp), %r8
cmpq %rax, %r8
setg %cl
jmp 0xcc93
movq %rdx, 0x38(%rsp)
movq %rcx, 0x40(%rsp)
leaq 0x18(%r13), %rax
movq (%rax), %r15
movq 0x8(%r15), %rdx
movq 0x10(%r15), %rcx
cmpq %r13, %r15
je 0xc9b6
cmpq %r12, %rdx
jne 0xc9b6
leaq 0x18(%r15), %rax
cmpq %rbp, %rcx
je 0xc998
cmpq %rbp, %rcx
movq %rdi, 0x10(%rsp)
jg 0xca0a
movq 0x10(%r14), %r8
movq (%r10), %rax
movq -0x18(%rax), %rax
movzbl 0x18(%r10,%rax), %eax
movl %eax, 0x18(%rsp)
movl %eax, (%rsp)
movq %r12, %rdi
movq %rbp, %rsi
movq %r8, 0x28(%rsp)
movq %r9, %rbx
movq %r10, 0x20(%rsp)
callq 0x7f57
movq 0x20(%rsp), %r10
movq %rbx, %r9
movq 0x10(%rsp), %rsi
testb %al, %al
je 0xca0a
movq %r14, 0x20(%rsp)
xorl %ebp, %ebp
jmp 0xca74
movq %r13, %r15
movq 0x20(%r15), %r15
movq 0x8(%r15), %rdx
movq 0x10(%r15), %rcx
cmpq %r13, %r15
je 0xca28
cmpq %r12, %rdx
jne 0xca28
cmpq %rbp, %rcx
je 0xca0d
cmpq %rbp, %rcx
jg 0xcb87
movq 0x10(%r14), %r8
movq (%r10), %rax
movq -0x18(%rax), %rax
movzbl 0x18(%r10,%rax), %eax
movl %eax, 0x18(%rsp)
movl %eax, (%rsp)
movq %r12, %rdi
movq %rbp, %rsi
movq %r8, 0x28(%rsp)
movq %r9, %rbx
callq 0x7f57
testb %al, %al
je 0xcb87
movq %r14, 0x20(%rsp)
movb $0x1, %bpl
movq 0x10(%rsp), %rsi
movq %rbx, %r9
leaq 0x18(%rsi), %rax
movq 0x8(%rsi), %rbx
movq 0x10(%rsi), %r12
movq (%rax), %r14
movq 0x8(%r14), %rdx
movq 0x10(%r14), %rcx
cmpq %rbx, %rdx
jne 0xca9e
cmpq %r12, %rcx
jne 0xca9e
leaq 0x18(%r14), %rax
cmpq %rsi, %r14
jne 0xca80
movzbl 0x18(%rsp), %eax
cmpq %r12, %rcx
jg 0xcade
movl %eax, (%rsp)
movq %rbx, %rdi
movq %r12, %rsi
movq 0x28(%rsp), %r8
movl %ebp, 0x18(%rsp)
movq %r9, %rbp
movl %eax, 0x34(%rsp)
callq 0x7f57
movq %rbp, %r9
movl 0x18(%rsp), %ebp
movq 0x10(%rsp), %rsi
testb %al, %al
movl 0x34(%rsp), %eax
je 0xcade
xorl %ecx, %ecx
jmp 0xcb23
movq %rsi, %r14
movq 0x20(%r14), %r14
movq 0x8(%r14), %rdx
movq 0x10(%r14), %rcx
cmpq %rbx, %rdx
jne 0xcafc
cmpq %r12, %rcx
jne 0xcafc
cmpq %rsi, %r14
jne 0xcae1
cmpq %r12, %rcx
jg 0xcb87
movl %eax, (%rsp)
movq %rbx, %rdi
movq %r12, %rsi
movq 0x28(%rsp), %r8
callq 0x7f57
movq 0x10(%rsp), %rsi
movb $0x1, %cl
testb %al, %al
je 0xcb87
xorl %r12d, %r12d
cmpq %r14, %r15
je 0xcb8a
cmpq %r13, %r15
je 0xcb8a
cmpq %rsi, %r14
je 0xcb8a
movq 0x38(%rsp), %rax
cmpq 0x40(%rsp), %rax
sete %al
xorb %bpl, %cl
xorb $0x1, %cl
testb %cl, %al
jne 0xcb87
testb %bpl, %bpl
je 0xcc38
movq %r13, %rdi
xorl %esi, %esi
callq 0xc55b
movq %rax, %rbx
pushq $0x1
popq %rsi
movq 0x10(%rsp), %r14
movq %r14, %rdi
callq 0xc55b
movq %r14, 0x20(%r13)
movq %r13, 0x18(%r14)
movq %rax, 0x18(%rbx)
movq %rbx, 0x20(%rax)
jmp 0xcc65
xorl %r12d, %r12d
movl %r12d, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x10(%rdx), %rcx
movq %rdi, %rsi
movq 0x18(%rsi), %rsi
cmpq %rdi, %rsi
je 0xcbbd
movq 0x10(%rsi), %rdx
cmpq %rax, 0x8(%rsi)
jne 0xcbc1
cmpq %rbp, %rdx
je 0xcba3
jmp 0xcbc1
movq 0x10(%rsi), %rdx
cmpq %rbp, %rcx
setg %al
cmpq %rbp, %rdx
setle %r12b
xorb %al, %r12b
jne 0xcc21
xorl %ebx, %ebx
xorl %r15d, %r15d
cmpq %rbp, %rcx
setle %bl
setg %r15b
movq %rdi, 0x10(%rsp)
movq %r13, %rdi
movl %ebx, %esi
callq 0xc55b
movq %rax, %rbp
movq 0x10(%rsp), %rdi
movl %r15d, %esi
callq 0xc55b
movq 0x10(%rsp), %rcx
movq %rcx, 0x18(%r13,%r15,8)
movq %r13, 0x18(%rcx,%rbx,8)
movq %rax, 0x18(%rbp,%rbx,8)
movq %rbp, 0x18(%rax,%r15,8)
movq %r13, (%r14)
movq %rbp, 0x8(%r14)
xorb $0x1, %r12b
jmp 0xcb8a
cmpq 0x8(%rbx), %r8
setg %cl
movq 0x10(%rsp), %r14
jmp 0xcc93
pushq $0x1
popq %rsi
movq %r13, %rdi
callq 0xc55b
movq %rax, %rbx
movq 0x10(%rsp), %r14
movq %r14, %rdi
xorl %esi, %esi
callq 0xc55b
movq %r14, 0x18(%r13)
movq %r13, 0x20(%r14)
movq %rax, 0x20(%rbx)
movq %rbx, 0x18(%rax)
movq 0x20(%rsp), %rax
movq %r13, (%rax)
movq %rbx, 0x8(%rax)
movb $0x1, %r12b
jmp 0xcb8a
cmpq 0x8(%rbp), %rax
setg %cl
movq %rax, %r8
jmp 0xcc93
cmpq %r8, %rsi
setg %cl
movq 0x18(%rsp), %r14
movq %rsi, %r8
movq (%r14), %r9
movq %r12, (%r13)
movq %r15, 0x8(%r13)
movzbl %cl, %eax
movl %eax, (%rsp)
movq %r12, %rdi
movq %rbx, %rsi
movq %r15, %rdx
movq %rbp, %rcx
callq 0xc5a5
movl %eax, %r12d
jmp 0xcb8a
nop