// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Mesh.cpp
// Function: gaps::CheckHoleBoundary(gaps::R3Mesh*, gaps::R3MeshBoundaryVertexData*, double, double)
static RNBoolean
CheckHoleBoundary(R3Mesh *mesh, R3MeshBoundaryVertexData *head,
  RNLength max_perimeter, RNLength max_planar_deviation)
{
  // Just checking
  // AssertBoundaryVertexData(mesh, head);

  // Check perimeter
  if (max_perimeter > 0) {
    RNLength perimeter = 0;
    R3MeshBoundaryVertexData *vdata = head;
    if (vdata) do {
      if (vdata->edge) perimeter += mesh->EdgeLength(vdata->edge);
      if (perimeter > max_perimeter) return FALSE;
      vdata = vdata->next;
    } while (vdata != head);
  }

  // Check planar deviation
  if (max_planar_deviation > 0) {
    // Find points
    std::vector<R3Point> points;
    R3MeshBoundaryVertexData *vdata = head;
    if (vdata) do {
      if (vdata->vertex) points.push_back(mesh->VertexPosition(vdata->vertex));
      vdata = vdata->next;
    } while (vdata != head);


    // Check points
    int npoints = points.size();
    if (npoints > 3) {
      // Compute best fitting plane
      R3Plane plane(&points[0], npoints, FALSE);

      // Check deviation from best fitting plane
      for (unsigned int i = 0; i < points.size(); i++) {
        if (R3Distance(plane, points[i]) > max_planar_deviation) return FALSE;
      }
    }
  }

  // Passed all tests
  return TRUE;
}

// Assembly:
subq $0xa8, %rsp
movq %rdi, 0x98(%rsp)
movq %rsi, 0x90(%rsp)
movsd %xmm0, 0x88(%rsp)
movsd %xmm1, 0x80(%rsp)
movsd 0x88(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x20d0f
xorps %xmm0, %xmm0
movsd %xmm0, 0x78(%rsp)
movq 0x90(%rsp), %rax
movq %rax, 0x70(%rsp)
cmpq $0x0, 0x70(%rsp)
je 0x20d0d
jmp 0x20c9f
movq 0x70(%rsp), %rax
cmpq $0x0, 0x8(%rax)
je 0x20ccd
movq 0x98(%rsp), %rdi
movq 0x70(%rsp), %rax
movq 0x8(%rax), %rsi
callq 0x13cc0
addsd 0x78(%rsp), %xmm0
movsd %xmm0, 0x78(%rsp)
movsd 0x78(%rsp), %xmm0
ucomisd 0x88(%rsp), %xmm0
jbe 0x20cee
movl $0x0, 0xa4(%rsp)
jmp 0x20ea2
movq 0x70(%rsp), %rax
movq 0x18(%rax), %rax
movq %rax, 0x70(%rsp)
movq 0x70(%rsp), %rax
cmpq 0x90(%rsp), %rax
jne 0x20c9f
jmp 0x20d0d
jmp 0x20d0f
movsd 0x80(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x20e97
leaq 0x58(%rsp), %rdi
callq 0x3a760
movq 0x90(%rsp), %rax
movq %rax, 0x50(%rsp)
cmpq $0x0, 0x50(%rsp)
je 0x20db3
jmp 0x20d46
movq 0x50(%rsp), %rax
cmpq $0x0, (%rax)
je 0x20d94
movq 0x98(%rsp), %rdi
movq 0x50(%rsp), %rax
movq (%rax), %rsi
callq 0x13660
movq %rax, %rsi
leaq 0x58(%rsp), %rdi
callq 0x3a770
jmp 0x20d75
jmp 0x20d94
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x48(%rsp)
movl %eax, 0x44(%rsp)
leaq 0x58(%rsp), %rdi
callq 0x3a850
jmp 0x20eb1
movq 0x50(%rsp), %rax
movq 0x18(%rax), %rax
movq %rax, 0x50(%rsp)
movq 0x50(%rsp), %rax
cmpq 0x90(%rsp), %rax
jne 0x20d46
jmp 0x20db3
leaq 0x58(%rsp), %rdi
callq 0x3a7e0
movl %eax, 0x40(%rsp)
cmpl $0x3, 0x40(%rsp)
jle 0x20e77
xorl %eax, %eax
movl %eax, 0x14(%rsp)
movl %eax, %esi
leaq 0x58(%rsp), %rdi
callq 0x3a800
movl 0x14(%rsp), %ecx
movq %rax, %rsi
movl 0x40(%rsp), %edx
leaq 0x20(%rsp), %rdi
callq 0x6cba0
jmp 0x20df5
movl $0x0, 0x1c(%rsp)
movl 0x1c(%rsp), %eax
movq %rax, 0x8(%rsp)
leaq 0x58(%rsp), %rdi
callq 0x3a7e0
movq %rax, %rcx
movq 0x8(%rsp), %rax
cmpq %rcx, %rax
jae 0x20e75
movl 0x1c(%rsp), %eax
movl %eax, %esi
leaq 0x58(%rsp), %rdi
callq 0x3a800
movq %rax, %rsi
leaq 0x20(%rsp), %rdi
callq 0x3a820
movsd %xmm0, (%rsp)
jmp 0x20e41
movsd (%rsp), %xmm0
ucomisd 0x80(%rsp), %xmm0
jbe 0x20e66
movl $0x0, 0xa4(%rsp)
movl $0x1, 0x18(%rsp)
jmp 0x20e7f
jmp 0x20e68
movl 0x1c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1c(%rsp)
jmp 0x20dfd
jmp 0x20e77
movl $0x0, 0x18(%rsp)
leaq 0x58(%rsp), %rdi
callq 0x3a850
movl 0x18(%rsp), %eax
testl %eax, %eax
je 0x20e95
jmp 0x20e93
jmp 0x20ea2
jmp 0x20e97
movl $0x1, 0xa4(%rsp)
movl 0xa4(%rsp), %eax
addq $0xa8, %rsp
retq
movq 0x48(%rsp), %rdi
callq 0xf890
nopl (%rax,%rax)