// File: /workspace/github_cpp_makefile_star2_O2/tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Mesh.cpp
// Function: gaps::R3Mesh::FillHole(gaps::R3MeshEdge*, double, double)
void R3Mesh::
FillHole(R3MeshEdge *seed_edge, RNLength max_perimeter, RNLength max_planar_deviation)
{
  // Check if seed edge is on boundary
  R3MeshFace *seed_face = FaceOnEdge(seed_edge);
  if (!seed_face) return; 
  if (FaceAcrossEdge(seed_edge, seed_face)) return;
  R3MeshVertex *seed_vertex = VertexOnEdge(seed_edge, seed_face, RN_CCW);

  // Create counterclockwise linked list of boundary vertices
  R3mesh_mark++;
  R3MeshBoundaryVertexData *head = NULL;
  R3MeshBoundaryVertexData *tail = NULL;
  R3MeshEdge *edge = seed_edge;
  R3MeshVertex *vertex = seed_vertex;
  // R3MeshFace *face = seed_face;
  do {
    // Create boundary vertex 
    R3MeshBoundaryVertexData *vdata = new R3MeshBoundaryVertexData();
    vdata->vertex = vertex;
    vdata->edge = edge;
    vdata->prev = NULL;
    vdata->next = NULL;
    vdata->heappointer = NULL;
    vdata->error = 0;

    // Mark vertex (so can detect figure 8)
    SetVertexMark(vertex, R3mesh_mark);

    // Add boundary vertex to list
    if (!head) head = vdata;
    if (tail) tail->next = vdata;
    vdata->prev = tail;
    tail = vdata;

    // Update vdata error 
    if (vdata->prev) {
      R3MeshVertex *prev_vertex = vdata->prev->vertex;
      R3MeshVertex *next_vertex = VertexAcrossEdge(vdata->edge, vdata->vertex);
      const R3Point& position = VertexPosition(vertex);
      const R3Point& prev_position = VertexPosition(prev_vertex);
      const R3Point& next_position = VertexPosition(next_vertex);
      const R3Vector& prev_normal = VertexNormal(prev_vertex);
      const R3Vector& next_normal = VertexNormal(next_vertex);
      R3Vector prev_vector = prev_position - position;
      R3Vector next_vector = next_position - position;
      R3Vector cross = prev_vector % next_vector;
      RNAngle interior_angle = R3InteriorAngle(prev_vector, next_vector);
      if (cross.Dot(VertexNormal(vdata->vertex)) > 0) interior_angle = RN_TWO_PI - interior_angle;
      RNAngle normal_angle = R3InteriorAngle(prev_normal, next_normal);
      vdata->error = interior_angle + normal_angle;
    }

    // Find next vertex
    vertex = VertexAcrossEdge(edge, vertex);

    // Check for repeated vertex (figure 8)
    if (VertexMark(vertex) == R3mesh_mark) {
      if (vertex != seed_vertex) {
        // Find previous instance of repeated vertex
        R3MeshBoundaryVertexData *vdata = tail->prev;
        while (vdata->vertex != vertex) vdata = vdata->prev;

        // Remove part of list before repeated vertex
        head = vdata;
        vdata = head->prev;
        head->prev = NULL;
        while (vdata) { 
          R3MeshBoundaryVertexData *prev = vdata->prev; 
          delete vdata; 
          vdata = prev; 
        }

        // Now have a complete loop
        break;
      }
    }

    // Find next edge
    R3MeshEdge *e = edge;
    while (e) {
      R3MeshFace *f = FaceOnVertex(vertex, e, RN_CCW);
      if (!f) { assert(e != edge); edge = e; break; }
      e = EdgeOnFace(f, vertex, RN_CW);
      if (!e || (e == edge)) return; 
    } 

    // Find next face
    // face = FaceOnVertex(vertex, edge, RN_CW);
  } while (vertex != seed_vertex);

  // Complete loop
  if (head && tail) {
    // Add link between head and tail
    head->prev = tail;
    tail->next = head;

    // Update head error 
    if (head) {
      R3MeshBoundaryVertexData *vdata = head;
      R3MeshVertex *prev_vertex = vdata->prev->vertex;
      R3MeshVertex *next_vertex = vdata->next->vertex;
      const R3Point& position = VertexPosition(vertex);
      const R3Point& prev_position = VertexPosition(prev_vertex);
      const R3Point& next_position = VertexPosition(next_vertex);
      const R3Vector& prev_normal = VertexNormal(prev_vertex);
      const R3Vector& next_normal = VertexNormal(next_vertex);
      R3Vector prev_vector = prev_position - position;
      R3Vector next_vector = next_position - position;
      R3Vector cross = prev_vector % next_vector;
      RNAngle interior_angle = R3InteriorAngle(prev_vector, next_vector);
      if (cross.Dot(VertexNormal(vdata->vertex)) > 0) interior_angle = RN_TWO_PI - interior_angle;
      RNAngle normal_angle = R3InteriorAngle(prev_normal, next_normal);
      vdata->error = interior_angle + normal_angle;
    }
  }

  // Split any edges spanning (back side of) boundary
  R3MeshBoundaryVertexData *vdata = head;
  do {
    R3MeshVertex *vertex = vdata->vertex;
    for (int i = 0; i < VertexValence(vertex); i++) {
      R3MeshEdge *edge = EdgeOnVertex(vertex, i);
      if (edge == vdata->edge) continue;
      if (edge == vdata->prev->edge) continue;
      R3MeshVertex *neighbor = VertexAcrossEdge(edge, vertex);
      if (VertexMark(neighbor)) SubdivideEdge(edge);
    }
    vdata = vdata->next;
  } while (vdata != head);

  // Mark hole boundary
  UnmarkHoleBoundary(this, head);

  // Check hole boundary
  if (!CheckHoleBoundary(this, head, max_perimeter, max_planar_deviation)) return;

  // Fill hole boundary
  FillHoleBoundary(this, head);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xf8, %rsp
movsd %xmm1, 0x10(%rsp)
movsd %xmm0, 0x18(%rsp)
movq %rsi, %r15
movq %rdi, (%rsp)
movq 0x18(%rsi), %rax
movq 0x20(%rsi), %rdx
movq %rdx, %rcx
testq %rdx, %rdx
jne 0x16732
movq %rax, %rcx
testq %rax, %rax
je 0x1673e
cmpq %rcx, %rax
cmovneq %rax, %rdx
testq %rdx, %rdx
je 0x16750
addq $0xf8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorl %edx, %edx
cmpq %rcx, %rax
sete %dl
movq 0x8(%r15,%rdx,8), %rdx
movl 0xc3d5d(%rip), %ebx     # 0xda4c0
incl %ebx
movl %ebx, 0xc3d55(%rip)     # 0xda4c0
leaq 0x847f6(%rip), %rax     # 0x9af68
movsd (%rax), %xmm0
movsd %xmm0, 0x68(%rsp)
xorl %r12d, %r12d
pushq $0x30
popq %rdi
movq %rdx, %r14
xorl %ebp, %ebp
movq %rdx, 0x30(%rsp)
callq 0xe450
xorpd %xmm0, %xmm0
movq %rax, %r13
movq %r14, (%rax)
movq %r15, 0x8(%rax)
addq $0x10, %rax
movupd %xmm0, 0x10(%r13)
movupd %xmm0, 0x20(%r13)
movl %ebx, 0x88(%r14)
testq %rbp, %rbp
cmoveq %r13, %rbp
testq %r12, %r12
movq %rax, 0xb8(%rsp)
je 0x168e9
movq %rbp, 0x8(%rsp)
movq %r13, 0x18(%r12)
movq %r12, 0x10(%r13)
movq 0x8(%r15), %rbp
cmpq %r14, %rbp
jne 0x167e9
movq 0x10(%r15), %rbp
movq (%r12), %rsi
leaq 0x18(%r14), %rbx
leaq 0x18(%rsi), %rax
movq %rax, 0xc0(%rsp)
leaq 0x18(%rbp), %rax
movq %rax, 0x70(%rsp)
movq (%rsp), %r12
movq %r12, %rdi
callq 0x21234
movq %rax, 0x20(%rsp)
movq %r12, %rdi
movq %rbp, %rsi
callq 0x21234
movq %rax, 0x60(%rsp)
leaq 0x80(%rsp), %rdi
movq 0xc0(%rsp), %rsi
movq %rbx, %rdx
callq 0x37d29
leaq 0x40(%rsp), %rbp
movq %rbp, %rdi
movq 0x70(%rsp), %rsi
movq %rbx, %rdx
callq 0x37d29
leaq 0xc8(%rsp), %rdi
leaq 0x80(%rsp), %rbx
movq %rbx, %rsi
movq %rbp, %rdx
callq 0x389be
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x4555f
movapd %xmm0, 0x70(%rsp)
movq (%r13), %rsi
movq %r12, %rdi
callq 0x21234
leaq 0xc8(%rsp), %rdi
movq %rax, %rsi
callq 0x38586
movsd 0x68(%rsp), %xmm1
movapd 0x70(%rsp), %xmm2
subsd %xmm2, %xmm1
xorpd %xmm3, %xmm3
cmpltsd %xmm0, %xmm3
andpd %xmm3, %xmm1
andnpd %xmm2, %xmm3
orpd %xmm1, %xmm3
movapd %xmm3, 0x70(%rsp)
movq 0x20(%rsp), %rdi
movq 0x60(%rsp), %rsi
callq 0x4555f
addsd 0x70(%rsp), %xmm0
movsd %xmm0, 0x28(%r13)
movq 0x8(%rsp), %rbp
jmp 0x168ed
andq $0x0, (%rax)
movq 0x8(%r15), %rax
cmpq %r14, %rax
movq %rax, %r14
movq 0x30(%rsp), %rdx
pushq $0x30
popq %rdi
pushq $0x20
popq %rsi
pushq $0x28
popq %r8
jne 0x1690c
movq 0x10(%r15), %r14
movl 0xc3bae(%rip), %ebx     # 0xda4c0
movq %r15, %rax
cmpq %rdx, %r14
je 0x1692a
movq %r15, %rax
cmpl %ebx, 0x88(%r14)
je 0x16bf6
xorl %ecx, %ecx
cmpq %r14, 0x8(%rax)
setne %cl
movq 0x18(%rax,%rcx,8), %rcx
testq %rcx, %rcx
je 0x16973
movq %rdi, %rax
cmpq %r14, 0x8(%rcx)
je 0x1695c
movq %rsi, %rax
cmpq %r14, 0x10(%rcx)
je 0x1695c
movq %r8, %rax
cmpq %r14, 0x18(%rcx)
jne 0x1673e
movq (%rcx,%rax), %rax
testq %rax, %rax
je 0x1673e
cmpq %r15, %rax
jne 0x1692a
jmp 0x1673e
movq %rax, %r15
movq %r13, %r12
cmpq %rdx, %r14
jne 0x1678c
movq %r13, 0x10(%rbp)
movq %rbp, 0x18(%r13)
movq (%r13), %rsi
movq 0x18(%rbp), %rax
movq (%rax), %r15
addq $0x18, %r14
leaq 0x18(%rsi), %r12
leaq 0x18(%r15), %rbx
movq (%rsp), %r13
movq %r13, %rdi
callq 0x21234
movq %rax, 0x30(%rsp)
movq %r13, %rdi
movq %r15, %rsi
callq 0x21234
movq %rax, 0x8(%rsp)
movq %rbp, %r15
leaq 0x80(%rsp), %rbp
movq %rbp, %rdi
movq %r12, %rsi
movq %r14, %rdx
callq 0x37d29
leaq 0x40(%rsp), %r12
movq %r12, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x37d29
leaq 0xc8(%rsp), %r14
movq %r14, %rdi
movq %rbp, %rsi
movq %r12, %rdx
callq 0x389be
movq %rbp, %rdi
movq %r15, %rbp
movq %r12, %rsi
callq 0x4555f
movapd %xmm0, 0x20(%rsp)
movq (%r15), %rsi
movq %r13, %rdi
callq 0x21234
movq %r14, %rdi
movq %rax, %rsi
callq 0x38586
movsd 0x68(%rsp), %xmm1
movapd 0x20(%rsp), %xmm2
subsd %xmm2, %xmm1
xorpd %xmm3, %xmm3
cmpltsd %xmm0, %xmm3
andpd %xmm3, %xmm1
andnpd %xmm2, %xmm3
orpd %xmm1, %xmm3
movapd %xmm3, 0x20(%rsp)
movq 0x30(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0x4555f
addsd 0x20(%rsp), %xmm0
movsd %xmm0, 0x28(%r15)
movq %r15, %rbx
movq (%rbx), %r14
xorl %r15d, %r15d
movslq 0x14(%r14), %rax
cmpq %rax, %r15
jge 0x16ac6
movq 0x8(%r14), %rax
movq (%rax,%r15,8), %rsi
cmpq 0x8(%rbx), %rsi
je 0x16ac1
movq 0x10(%rbx), %rax
cmpq 0x8(%rax), %rsi
je 0x16ac1
movq 0x8(%rsi), %rax
cmpq %r14, %rax
jne 0x16aab
movq 0x10(%rsi), %rax
cmpl $0x0, 0x88(%rax)
je 0x16ac1
movq (%rsp), %rdi
movq (%rdi), %rax
callq *0xc8(%rax)
incq %r15
jmp 0x16a7d
movq 0x18(%rbx), %rbx
cmpq %rbp, %rbx
jne 0x16a77
movq %rbp, %rax
movq 0x8(%rax), %rcx
testq %rcx, %rcx
je 0x16adf
andl $0x0, 0x48(%rcx)
movq 0x18(%rax), %rax
cmpq %rbp, %rax
jne 0x16ad2
xorpd %xmm1, %xmm1
movsd 0x18(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x16b32
movq %rbp, %rbx
movq 0x8(%rbx), %rsi
testq %rsi, %rsi
je 0x16b1d
movq (%rsp), %rdi
movsd %xmm1, 0x30(%rsp)
callq 0x10db2
movsd 0x30(%rsp), %xmm1
addsd %xmm0, %xmm1
ucomisd 0x18(%rsp), %xmm1
ja 0x1673e
movq 0x18(%rbx), %rbx
cmpq %rbp, %rbx
jne 0x16afb
xorpd %xmm0, %xmm0
movsd 0x10(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x16c39
xorpd %xmm0, %xmm0
leaq 0x40(%rsp), %rbx
movapd %xmm0, (%rbx)
andq $0x0, 0x10(%rbx)
movq %rbp, %r14
movq (%r14), %rsi
testq %rsi, %rsi
je 0x16b6f
addq $0x18, %rsi
movq %rbx, %rdi
callq 0x2241e
movq 0x18(%r14), %r14
cmpq %rbp, %r14
jne 0x16b5b
movq 0x40(%rsp), %rsi
movq 0x48(%rsp), %rax
subq %rsi, %rax
pushq $0x18
popq %r14
cqto
idivq %r14
cmpl $0x4, %eax
jl 0x16c2f
leaq 0x80(%rsp), %rdi
xorl %r15d, %r15d
movl %eax, %edx
xorl %ecx, %ecx
callq 0x36b16
leaq 0x80(%rsp), %rbx
movl %r15d, %r15d
movq 0x40(%rsp), %rdi
movq 0x48(%rsp), %rax
subq %rdi, %rax
cqto
idivq %r14
cmpq %r15, %rax
jbe 0x16c2f
imulq $0x18, %r15, %rax
addq %rax, %rdi
movq %rbx, %rsi
callq 0x433d6
incl %r15d
ucomisd 0x10(%rsp), %xmm0
jbe 0x16bb3
leaq 0x40(%rsp), %rdi
callq 0x22640
jmp 0x1673e
movq 0xb8(%rsp), %rax
movq (%rax), %rbp
leaq 0x10(%rbp), %rax
cmpq %r14, (%rbp)
jne 0x16bfe
movq (%rax), %rdi
andq $0x0, (%rax)
pushq $0x30
popq %rbx
testq %rdi, %rdi
je 0x16982
movq 0x10(%rdi), %r15
movq %rbx, %rsi
callq 0xe460
movq %r15, %rdi
jmp 0x16c15
leaq 0x40(%rsp), %rdi
callq 0x22640
xorpd %xmm0, %xmm0
leaq 0x80(%rsp), %rbx
movapd %xmm0, (%rbx)
movupd %xmm0, 0x18(%rbx)
andq $0x0, 0x28(%rbx)
movl $0x1, 0x30(%rbx)
movabsq $0x2000000028, %rax     # imm = 0x2000000028
movq %rax, 0x10(%rbx)
movq %rbp, %r14
movq %rbx, %rdi
movq %r14, %rsi
callq 0x22666
movq 0x18(%r14), %r14
cmpq %rbp, %r14
jne 0x16c6b
leaq 0xc8(%rsp), %rbp
movl 0x88(%rsp), %eax
cmpl $0x4, %eax
jl 0x16e23
leaq 0x80(%rsp), %rdi
callq 0x2276e
movq %rax, %rbx
movq (%rax), %r15
movq 0x10(%rax), %rax
movq 0x18(%rbx), %rcx
movq %rax, 0x20(%rsp)
movq (%rax), %rsi
movq %rcx, 0x60(%rsp)
movq (%rcx), %rcx
movq (%rsp), %rdi
movq (%rdi), %rax
movq %r15, %rdx
xorl %r8d, %r8d
callq *0x48(%rax)
testq %rax, %rax
je 0x16e91
movq (%rsp), %rdi
movq %rax, %rsi
movq %r15, %rdx
callq 0x221a0
movq 0x10(%rbx), %rcx
movq %rax, 0x8(%rcx)
movq 0x18(%rbx), %rax
movq %rax, 0x18(%rcx)
movq %rcx, 0x10(%rax)
movq %rbx, %rdi
pushq $0x30
popq %rsi
callq 0xe460
addq $0x18, %r15
xorl %eax, %eax
cmpl $0x2, %eax
je 0x16c87
movl %eax, 0x10(%rsp)
testl %eax, %eax
movq 0x60(%rsp), %r14
cmoveq 0x20(%rsp), %r14
movq 0x10(%r14), %rax
movq 0x18(%r14), %rcx
movq (%rsp), %rbx
movq (%rax), %r13
movq (%rcx), %r12
movq %rbx, %rdi
movq %r13, %rsi
callq 0x21234
movq %rax, 0x18(%rsp)
movq %rbx, %rdi
movq %r12, %rsi
callq 0x21234
movq %rax, %rbx
addq $0x18, %r13
leaq 0x40(%rsp), %rdi
movq %r13, %rsi
movq %r15, %rdx
callq 0x37d29
addq $0x18, %r12
movq %rbp, %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x37d29
leaq 0xe0(%rsp), %rdi
leaq 0x40(%rsp), %r12
movq %r12, %rsi
movq %rbp, %rdx
callq 0x389be
movq %r12, %rdi
movq %rbp, %rsi
callq 0x4555f
movapd %xmm0, 0x30(%rsp)
movq (%r14), %rsi
movq (%rsp), %rdi
callq 0x21234
leaq 0xe0(%rsp), %rdi
movq %rax, %rsi
callq 0x38586
movsd %xmm0, 0x8(%rsp)
movq 0x18(%rsp), %rdi
movq %rbx, %rsi
callq 0x4555f
movsd 0x68(%rsp), %xmm1
movapd 0x30(%rsp), %xmm3
subsd %xmm3, %xmm1
xorpd %xmm2, %xmm2
cmpltsd 0x8(%rsp), %xmm2
andpd %xmm2, %xmm1
andnpd %xmm3, %xmm2
orpd %xmm1, %xmm2
addsd %xmm0, %xmm2
movsd %xmm2, 0x28(%r14)
leaq 0x80(%rsp), %rdi
movq %r14, %rsi
callq 0x2280e
movl 0x10(%rsp), %eax
incl %eax
jmp 0x16d0f
cmpl $0x3, %eax
jne 0x16e91
leaq 0x80(%rsp), %rdi
callq 0x2276e
movq %rax, %rbx
movq (%rax), %rdx
movq 0x10(%rax), %rax
movq (%rax), %rsi
movq 0x18(%rbx), %rax
movq (%rax), %rcx
movq (%rsp), %rdi
movq (%rdi), %rax
xorl %r8d, %r8d
callq *0x48(%rax)
pushq $0x30
popq %rsi
movq %rbx, %rdi
callq 0xe460
leaq 0x80(%rsp), %rdi
callq 0x2276e
pushq $0x30
popq %rsi
movq %rax, %rdi
callq 0xe460
leaq 0x80(%rsp), %rdi
callq 0x2276e
pushq $0x30
popq %rsi
movq %rax, %rdi
callq 0xe460
leaq 0x80(%rsp), %rdi
callq 0x22888
jmp 0x1673e
jmp 0x16ecc
jmp 0x16eab
jmp 0x16ecc
jmp 0x16eab
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x22640
jmp 0x16edc
jmp 0x16ecc
jmp 0x16ecc
jmp 0x16ecc
jmp 0x16ecc
jmp 0x16ecc
jmp 0x16ecc
jmp 0x16ecc
jmp 0x16ecc
jmp 0x16ecc
movq %rax, %rbx
leaq 0x80(%rsp), %rdi
callq 0x22888
movq %rbx, %rdi
callq 0xe810