// File: /workspace/github_cpp_makefile_star2_O1/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 $0x48, %rsp
movq %rsi, %r10
movq (%rsi), %rbp
movq 0x8(%rsi), %r13
leaq 0x8(%rbp), %rbx
movq 0x8(%rbp), %r15
movq 0x10(%rbp), %rsi
movq 0x18(%r10), %r9
cmpq %r9, %rsi
jne 0xe71e
movq 0x10(%r10), %rax
movq %rbp, %rdx
cmpq %r15, %rax
jne 0xe646
movq 0x18(%r10), %rcx
movq %rbp, %rdx
cmpq 0x10(%rbp), %rcx
jne 0xe646
movq %rbp, %rdx
cmpq 0x8(%r13), %rax
jne 0xe646
movq %rbp, %rdx
cmpq 0x10(%r13), %rcx
jne 0xe646
leaq 0x8(%r13), %rdi
movq %rbp, %rdx
movq 0x18(%rdx), %rdx
cmpq %rbp, %rdx
je 0xe568
cmpq %rax, 0x8(%rdx)
jne 0xe568
cmpq %rcx, 0x10(%rdx)
je 0xe553
movq 0x10(%rdx), %rdx
movq %r13, %rsi
movq 0x18(%rsi), %rsi
cmpq %r13, %rsi
je 0xe584
cmpq %rax, 0x8(%rsi)
jne 0xe584
cmpq %rcx, 0x10(%rsi)
je 0xe56f
cmpq %r9, %rdx
setg %al
cmpq %r9, 0x10(%rsi)
setle %r15b
xorb %al, %r15b
jne 0xe63d
xorl %r14d, %r14d
xorl %r12d, %r12d
cmpq %r9, %rdx
setle %r14b
setg %r12b
movq %rdi, 0x20(%rsp)
movl $0x28, %edi
movq %r10, 0x18(%rsp)
callq 0x3210
movq %rbx, %rcx
movq %rax, %rbx
movups (%rcx), %xmm0
movups %xmm0, 0x8(%rax)
movl (%rbp), %eax
movl %eax, (%rbx)
movq 0x18(%rbp,%r12,8), %rax
movq %rax, 0x18(%rbx,%r12,8)
movq %rbp, 0x18(%rbx,%r14,8)
movq %rbx, 0x18(%rax,%r14,8)
movq %rbx, 0x18(%rbp,%r12,8)
movl $0x28, %edi
callq 0x3210
movq 0x20(%rsp), %rcx
movups (%rcx), %xmm0
movups %xmm0, 0x8(%rax)
movl (%r13), %ecx
movl %ecx, (%rax)
movq 0x18(%r13,%r14,8), %rcx
movq %rcx, 0x18(%rax,%r14,8)
movq %r13, 0x18(%rax,%r12,8)
movq %rax, 0x18(%rcx,%r12,8)
movq %rax, 0x18(%r13,%r14,8)
movq %r13, 0x18(%rbp,%r12,8)
movq %rbp, 0x18(%r13,%r14,8)
movq %rax, 0x18(%rbx,%r14,8)
movq %rbx, 0x18(%rax,%r12,8)
movq 0x18(%rsp), %rax
movq %rbx, 0x8(%rax)
xorb $0x1, %r15b
jmp 0xea5d
movq %rdx, %rdi
movq 0x20(%rdx), %rdx
cmpq %rbp, %rdx
je 0xe661
movq 0x10(%rdi), %rax
cmpq %rax, 0x10(%rdx)
jne 0xe661
cmpq %r13, %rdx
jne 0xe646
movq %rbp, %rsi
movq 0x18(%rbp), %rbp
cmpq %rdi, %rbp
je 0xe67c
movq 0x10(%rsi), %rax
cmpq %rax, 0x10(%rbp)
jne 0xe67c
cmpq %r13, %rbp
jne 0xe661
cmpq %r13, %rbp
sete %al
cmpq %rdi, %rbp
sete %cl
orb %al, %cl
jne 0xea5a
movq %r13, %rax
movq %rax, %rdx
movq 0x20(%rax), %rax
cmpq %rsi, %rax
je 0xe6bf
movq 0x10(%rdx), %rcx
cmpq %rcx, 0x10(%rax)
jne 0xe6bf
cmpq %r13, %rax
jne 0xe693
jmp 0xe6bf
cmpq %rdx, %r13
je 0xe6cb
movq 0x10(%rcx), %rax
cmpq %rax, 0x10(%r13)
jne 0xe6cb
movq %r13, %rcx
movq 0x18(%r13), %r13
cmpq %rdi, %r13
jne 0xe6b0
cmpq %rdi, %r13
sete %al
cmpq %rdx, %r13
sete %r8b
orb %al, %r8b
jne 0xea5a
movq %r10, %r15
movq 0x8(%rdi), %r11
movq 0x8(%rsi), %r10
movq 0x8(%rdx), %r9
movq 0x8(%rcx), %r8
cmpq %r10, %r11
setl %al
jge 0xe99f
cmpq %r8, %r9
jge 0xea16
cmpq %r9, %r11
movq %r9, %rbx
cmovgq %r11, %rbx
cmpq %r10, %r8
movq %r10, %r14
jmp 0xe9b8
movq %rdx, 0x38(%rsp)
movq %rcx, 0x40(%rsp)
movq %rbx, 0x30(%rsp)
leaq 0x18(%rbp), %rax
movq 0x10(%rbp), %rbx
movq (%rax), %r14
movq 0x8(%r14), %rdx
cmpq %rbp, %r14
je 0xe750
cmpq %r15, %rdx
jne 0xe750
leaq 0x18(%r14), %rax
cmpq %rbx, 0x10(%r14)
je 0xe735
movq 0x10(%r14), %rcx
movb $0x1, %r12b
cmpq %rsi, %rcx
movq %rdi, 0x20(%rsp)
jg 0xe7a7
movq 0x10(%r10), %r8
movq (%rdi), %rax
movq -0x18(%rax), %rax
movzbl 0x18(%rdi,%rax), %eax
movl %eax, (%rsp)
movq %r15, %rdi
movq %rsi, 0x10(%rsp)
movq 0x10(%rsp), %rsi
movq %r9, %r12
movq %r10, 0x18(%rsp)
callq 0x8d2a
movq 0x10(%rsp), %rsi
movq 0x20(%rsp), %rdi
movq %r12, %r9
movq 0x18(%rsp), %r10
movl %eax, %r12d
xorb $0x1, %r12b
testb %r12b, %r12b
je 0xe808
movq %rbp, %r14
movq 0x20(%r14), %r14
movq 0x8(%r14), %rdx
cmpq %rbp, %r14
je 0xe7c7
cmpq %r15, %rdx
jne 0xe7c7
cmpq %rbx, 0x10(%r14)
je 0xe7af
movq 0x10(%r14), %rcx
cmpq %rsi, %rcx
jg 0xea5a
movq 0x10(%r10), %r8
movq (%rdi), %rax
movq -0x18(%rax), %rax
movzbl 0x18(%rdi,%rax), %eax
movl %eax, (%rsp)
movq %r15, %rdi
movq %r9, %r15
movq %r10, %rbx
callq 0x8d2a
movq 0x20(%rsp), %rdi
movq %r15, %r9
movq %rbx, %r10
testb %al, %al
je 0xea5a
movb %r12b, 0xf(%rsp)
leaq 0x18(%r13), %rax
movq 0x8(%r13), %r15
movq 0x10(%r13), %r12
movq (%rax), %rbx
movq 0x8(%rbx), %rdx
cmpq %r15, %rdx
jne 0xe834
cmpq %r12, 0x10(%rbx)
jne 0xe834
leaq 0x18(%rbx), %rax
cmpq %r13, %rbx
jne 0xe819
movq 0x10(%rbx), %rcx
movq 0x10(%r13), %rsi
movb $0x1, %r11b
cmpq %rsi, %rcx
jg 0xe88e
movq 0x10(%r10), %r8
movq (%rdi), %rax
movq -0x18(%rax), %rax
movzbl 0x18(%rdi,%rax), %eax
movl %eax, (%rsp)
movq %r15, %rdi
movq %r9, 0x10(%rsp)
movq 0x10(%rsp), %r9
movq %r10, 0x18(%rsp)
movq %rsi, 0x28(%rsp)
callq 0x8d2a
movq 0x28(%rsp), %rsi
movq 0x20(%rsp), %rdi
movq 0x10(%rsp), %r9
movq 0x18(%rsp), %r10
movl %eax, %r11d
xorb $0x1, %r11b
testb %r11b, %r11b
je 0xe8ea
movq %r13, %rbx
movq 0x20(%rbx), %rbx
movq 0x8(%rbx), %rdx
cmpq %r15, %rdx
jne 0xe8ae
cmpq %r12, 0x10(%rbx)
jne 0xe8ae
cmpq %r13, %rbx
jne 0xe896
movq 0x10(%rbx), %rcx
cmpq %rsi, %rcx
jg 0xea5a
movq 0x10(%r10), %r8
movq (%rdi), %rax
movq -0x18(%rax), %rax
movzbl 0x18(%rdi,%rax), %eax
movl %eax, (%rsp)
movq %r15, %rdi
movl %r11d, %r12d
movq %r10, %r15
callq 0x8d2a
movl %r12d, %r11d
movq %r15, %r10
testb %al, %al
je 0xea5a
xorl %r15d, %r15d
cmpq %rbx, %r14
je 0xea5d
cmpq %rbp, %r14
je 0xea5d
cmpq %r13, %rbx
je 0xea5d
movq 0x38(%rsp), %rax
cmpq 0x40(%rsp), %rax
movb 0xf(%rsp), %r12b
jne 0xe922
xorb %r12b, %r11b
je 0xea5a
movq %r10, %r14
leaq 0x8(%r13), %rbx
movl $0x28, %edi
callq 0x3210
movq %rax, %r15
movq 0x30(%rsp), %rax
movups (%rax), %xmm0
movups %xmm0, 0x8(%r15)
movl (%rbp), %eax
movl %eax, (%r15)
testb %r12b, %r12b
je 0xe9be
movq 0x20(%rbp), %rax
movq %rax, 0x20(%r15)
movq %rbp, 0x18(%r15)
movq %r15, 0x18(%rax)
movq %r15, 0x20(%rbp)
movl $0x28, %edi
callq 0x3210
movups (%rbx), %xmm0
movups %xmm0, 0x8(%rax)
movl (%r13), %ecx
movl %ecx, (%rax)
movq 0x18(%r13), %rcx
movq %rcx, 0x18(%rax)
movq %r13, 0x20(%rax)
movq %rax, 0x20(%rcx)
movq %rax, 0x18(%r13)
movq %r13, 0x20(%rbp)
movq %rbp, 0x18(%r13)
movq %rax, 0x18(%r15)
movq %r15, 0x20(%rax)
jmp 0xea0d
cmpq %r8, %r9
jge 0xea28
cmpq %r9, %r10
movq %r9, %rbx
cmovgq %r10, %rbx
cmpq %r11, %r8
movq %r11, %r14
cmovlq %r8, %r14
jmp 0xea3c
movq 0x18(%rbp), %rax
movq %rax, 0x18(%r15)
movq %rbp, 0x20(%r15)
movq %r15, 0x20(%rax)
movq %r15, 0x18(%rbp)
movl $0x28, %edi
callq 0x3210
movups (%rbx), %xmm0
movups %xmm0, 0x8(%rax)
movl (%r13), %ecx
movl %ecx, (%rax)
movq 0x20(%r13), %rcx
movq %rcx, 0x20(%rax)
movq %r13, 0x18(%rax)
movq %rax, 0x18(%rcx)
movq %rax, 0x20(%r13)
movq %r13, 0x18(%rbp)
movq %rbp, 0x20(%r13)
movq %rax, 0x20(%r15)
movq %r15, 0x18(%rax)
movq %r15, 0x8(%r14)
movb $0x1, %r15b
jmp 0xea5d
cmpq %r8, %r11
movq %r8, %rbx
cmovgq %r11, %rbx
cmpq %r10, %r9
movq %r10, %r14
jmp 0xea38
cmpq %r8, %r10
movq %r8, %rbx
cmovgq %r10, %rbx
cmpq %r11, %r9
movq %r11, %r14
cmovlq %r9, %r14
cmpq %r14, %rbx
jge 0xea5a
cmpq %rbx, %r11
jl 0xea6f
cmpq %r14, %r11
jg 0xea6f
leaq 0x10(%rdi), %rbx
cmpq %r10, %r11
setg %al
movq %r11, %r8
jmp 0xeaa5
xorl %r15d, %r15d
movl %r15d, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpq %rbx, %r9
jl 0xea88
cmpq %r14, %r9
jg 0xea88
leaq 0x10(%rdx), %rbx
cmpq %r8, %r9
setg %al
movq %r9, %r8
jmp 0xeaa5
cmpq %rbx, %r10
jl 0xea9b
cmpq %r14, %r10
jg 0xea9b
leaq 0x10(%rsi), %rbx
movq %r10, %r8
jmp 0xeaa5
leaq 0x10(%rcx), %rbx
cmpq %r9, %r8
setg %al
movq (%rbx), %r9
movq %rdi, (%r15)
movq %rdx, 0x8(%r15)
movzbl %al, %eax
movl %eax, (%rsp)
callq 0xe2aa
jmp 0xea60