// File: /workspace/github_cpp_makefile_star2_O3/tomfunkhouser[P]gaps/pkgs/R2Shapes/R2Polygon.cpp
// Function: gaps::R2Polygon::Tangent(int, double) const
R2Line R2Polygon::
Tangent(int k, RNLength radius) const
{
  // Just checking
  if (npoints < 3) return R2null_line;

#if 0
  // Find first point
  R2Point *pointA = &points[(k - 1 + npoints) % npoints];
  if (radius > 0) {
    R2Point *prev = pointA;
    RNLength distance = R2Distance(*pointA, points[k]);
    if (distance < radius) {
      for (int i = 2;  i < npoints/3; i++) {
        pointA = &points[(k - i + npoints) % npoints];
        distance += R2Distance(*pointA, *prev);
        if (distance >= radius) break;
        prev = pointA;
      }
    }
  }

  // Find second point
  R2Point *pointB = &points[(k + 1) % npoints];
  if (radius > 0) {
    R2Point *prev = pointB;
    RNLength distance = R2Distance(*pointB, points[k]);
    if (distance < radius) {
      for (int i = 2;  i < npoints/3; i++) {
        pointB = &points[(k + i) % npoints];
        distance += R2Distance(*pointB, *prev);
        if (distance >= radius) break;
        prev = pointB;
      }
    }
  }

  // Compute vector along line
  R2Vector vector = *pointB - *pointA;
  vector.Normalize();
#else
  // Create array with points of patch within radius
  RNArray<R2Point *> patch;
  patch.Insert(&points[k]);

  // Add points searching one way
  RNLength distance = 0;
  R2Point *prev = &points[k];
  for (int i = 1; i < npoints/3; i++) {
    R2Point *current = &points[(k - i + npoints) % npoints];
    patch.Insert(current);
    distance += R2Distance(*current, *prev);
    if (distance >= radius) break;
    prev = current;
  }

  // Add points searching other way
  distance = 0;
  prev = &points[k];
  for (int i = 1; i < npoints/3; i++) {
    R2Point *current = &points[(k + i) % npoints];
    patch.Insert(current);
    distance += R2Distance(*current, *prev);
    if (distance >= radius) break;
    prev = current;
  }

  // Compute best fitting line to points in patch
  R2Point centroid = R2Centroid(patch);
  R2Diad diad = R2PrincipleAxes(centroid, patch);
  R2Vector vector = diad.Axis(0);

  // Flip vector if facing wrong direction
  R2Point& p1 = points[(k - 1 + npoints) % npoints];
  R2Point& p2 = points[(k + 1) % npoints];
  if (vector.Dot(p2 - p1) < 0) vector.Flip();
#endif

  // Flip if polygon is clockwise
  if (clockwise) vector = -vector;

  // Return tangent line
  return R2Line(points[k], vector);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movsd %xmm0, 0x28(%rsp)
movq %rdi, %r12
cmpl $0x2, 0x10(%rsi)
jg 0x63f8a
leaq 0x484233(%rip), %rsi    # 0x4e81b0
movq %r12, %rdi
callq 0x67ade
jmp 0x641cd
movl %edx, %r15d
movq %rsi, %r14
movq %rsp, %rbx
movq %rbx, %rdi
callq 0x6f80c
movq %r15, 0x18(%rsp)
movslq %r15d, %rax
shlq $0x4, %rax
movq 0x8(%r14), %rsi
movq %rax, 0x10(%rsp)
addq %rax, %rsi
movl 0xc(%rbx), %edx
movq %rbx, %rdi
callq 0x6f8a2
movl 0x10(%r14), %ecx
cmpl $0x6, %ecx
jl 0x640f3
movq %r12, 0x40(%rsp)
movq 0x8(%r14), %rbx
addq 0x10(%rsp), %rbx
movq 0x18(%rsp), %rax
leal -0x1(%rax), %r15d
movl $0x1, %r12d
xorpd %xmm0, %xmm0
movq %rsp, %r13
movsd %xmm0, 0x20(%rsp)
leal (%rcx,%r15), %eax
cltd
idivl %ecx
movslq %edx, %rbp
shlq $0x4, %rbp
addq 0x8(%r14), %rbp
movl 0xc(%rsp), %edx
movq %r13, %rdi
movq %rbp, %rsi
callq 0x6f8a2
movq %rbp, %rdi
movq %rbx, %rsi
callq 0x6c52b
movsd 0x20(%rsp), %xmm1
addsd %xmm0, %xmm1
ucomisd 0x28(%rsp), %xmm1
movl 0x10(%r14), %ecx
jae 0x64060
movapd %xmm1, %xmm0
incl %r12d
movslq %ecx, %rax
imulq $0x55555556, %rax, %rax # imm = 0x55555556
movq %rax, %rdx
shrq $0x3f, %rdx
shrq $0x20, %rax
addl %edx, %eax
decl %r15d
movq %rbp, %rbx
cmpl %eax, %r12d
jl 0x63fef
cmpl $0x6, %ecx
movq 0x40(%rsp), %r12
jl 0x640f3
movq 0x8(%r14), %rbp
addq 0x10(%rsp), %rbp
movl $0x1, %r15d
xorpd %xmm0, %xmm0
movq %rsp, %r13
movsd %xmm0, 0x20(%rsp)
movq 0x18(%rsp), %rax
addl %r15d, %eax
cltd
idivl %ecx
movslq %edx, %rbx
shlq $0x4, %rbx
addq 0x8(%r14), %rbx
movl 0xc(%rsp), %edx
movq %r13, %rdi
movq %rbx, %rsi
callq 0x6f8a2
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x6c52b
movsd 0x20(%rsp), %xmm1
addsd %xmm0, %xmm1
ucomisd 0x28(%rsp), %xmm1
jae 0x640f3
movapd %xmm1, %xmm0
incl %r15d
movslq 0x10(%r14), %rcx
imulq $0x55555556, %rcx, %rax # imm = 0x55555556
movq %rax, %rdx
shrq $0x3f, %rdx
shrq $0x20, %rax
addl %edx, %eax
movq %rbx, %rbp
cmpl %eax, %r15d
jl 0x64084
leaq 0x58(%rsp), %rdi
movq %rsp, %rsi
xorl %edx, %edx
callq 0x6d8dc
leaq 0x68(%rsp), %rdi
leaq 0x58(%rsp), %rsi
movq %rsp, %rdx
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x6d984
movq 0x18(%rsp), %rbx
leaq 0x30(%rsp), %rdi
leaq 0x68(%rsp), %rsi
callq 0x683dc
movq 0x8(%r14), %rdi
movl 0x10(%r14), %esi
leal (%rbx,%rsi), %eax
decl %eax
cltd
idivl %esi
movslq %edx, %rcx
shlq $0x4, %rcx
addq %rdi, %rcx
incl %ebx
movl %ebx, %eax
cltd
idivl %esi
movslq %edx, %rsi
shlq $0x4, %rsi
addq %rdi, %rsi
leaq 0x48(%rsp), %rdi
movq %rcx, %rdx
callq 0x682e3
leaq 0x30(%rsp), %rdi
leaq 0x48(%rsp), %rsi
callq 0x68540
xorpd %xmm1, %xmm1
ucomisd %xmm0, %xmm1
jbe 0x64188
leaq 0x30(%rsp), %rdi
callq 0x685fe
cmpl $0x0, 0x40(%r14)
je 0x641ad
leaq 0x48(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x6887f
leaq 0x30(%rsp), %rdi
leaq 0x48(%rsp), %rsi
callq 0x68720
movq 0x10(%rsp), %rsi
addq 0x8(%r14), %rsi
leaq 0x30(%rsp), %rdx
movq %r12, %rdi
xorl %ecx, %ecx
callq 0x67ba4
movq %rsp, %rdi
callq 0x6f876
movq %r12, %rax
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x641f2
jmp 0x641f2
jmp 0x641f2
jmp 0x641f2
jmp 0x641f2
jmp 0x641f2
jmp 0x641f2
jmp 0x641f2
movq %rax, %rbx
movq %rsp, %rdi
callq 0x6f876
movq %rbx, %rdi
callq 0xe7e0
nop