// File: tomfunkhouser[P]gaps/apps/msh2msh/msh2msh.cpp
// Function: DeleteSmallConnectedComponents(gaps::R3Mesh*, double)
static int
DeleteSmallConnectedComponents(R3Mesh *mesh, RNArea min_area)
{
  // Start statistics
  RNTime start_time;
  start_time.Read();
  int total_ncomponents = 0;
  int small_ncomponents = 0;

  // Allocate seed marks
  if (mesh->NFaces() == 0) return 0;
  int *components = new int [ mesh->NFaces() ];
  for (int i = 0; i < mesh->NFaces(); i++) components[i]  = -1;

  // Iterate finding connected components
  int seed_index = 0;
  RNArray<R3MeshFace *> small_component_faces;
  for (;;) {
    // Find an unmarked face
    R3MeshFace *seed = NULL;
    for (; seed_index < mesh->NFaces(); seed_index++) {
      R3MeshFace *face = mesh->Face(seed_index);
      if (components[seed_index] < 0) {
        seed = face;
        break;
      }
    }

    // Check if found a new component
    if (!seed) break;

    // Mark connected component
    R3mesh_mark++;
    RNArea area = 0;
    RNArray<R3MeshFace *> stack;
    RNArray<R3MeshFace *> component;
    stack.InsertTail(seed);
    mesh->SetFaceMark(seed, R3mesh_mark);
    while (!stack.IsEmpty()) {
      R3MeshFace *face = stack.Tail();
      stack.RemoveTail();

      // Add face to component
      component.Insert(face);
      area += mesh->FaceArea(face);
      components[mesh->FaceID(face)] = total_ncomponents;

      // Check neighbors
      for (int i = 0; i < 3; i++) {
        R3MeshFace *neighbor = mesh->FaceOnFace(face, i);
        if (!neighbor) continue;
        if (mesh->FaceMark(neighbor) == R3mesh_mark) continue;
        mesh->SetFaceMark(neighbor, R3mesh_mark);
        stack.InsertTail(neighbor);
      }
    }

    // Check component
    if (component.NEntries() == 0) continue;

    // Mark component for deletion if too small
    if (area < min_area) {
      small_component_faces.Append(component);
      small_ncomponents++;
    }

    // Increment number of components
    total_ncomponents++;
  }

  // Delete deletable faces
  for (int i = 0; i < small_component_faces.NEntries(); i++) {
    R3MeshFace *face = small_component_faces.Kth(i);
    mesh->DeleteFace(face);
  }

  // Delete components
  delete [] components;

  // Print debug statistics
  if (print_verbose) {
    printf("  Deleted small connected components ...\n");
    printf("    Time = %.2f seconds\n", start_time.Elapsed());
    printf("    # Deleted Components = %d\n", small_ncomponents);
    printf("    # Deleted Faces = %d\n", small_component_faces.NEntries());
    printf("    # Remaining Components = %d\n", total_ncomponents - small_ncomponents);
    printf("    # Remaining Faces = %d\n", mesh->NFaces());
    fflush(stdout);
  }

  // Return success
  return 1;
}

// Assembly:
subq $0x138, %rsp            # imm = 0x138
movq %rdi, 0x128(%rsp)
movsd %xmm0, 0x120(%rsp)
leaq 0x110(%rsp), %rdi
callq 0xc35d0
leaq 0x110(%rsp), %rdi
callq 0x165f0
movl $0x0, 0x10c(%rsp)
movl $0x0, 0x108(%rsp)
movq 0x128(%rsp), %rdi
callq 0x164b0
cmpl $0x0, %eax
jne 0x1514a
movl $0x0, 0x134(%rsp)
jmp 0x15798
movq 0x128(%rsp), %rdi
callq 0x164b0
cltq
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0xf030
movq %rax, 0x100(%rsp)
movl $0x0, 0xfc(%rsp)
movl 0xfc(%rsp), %eax
movl %eax, 0x74(%rsp)
movq 0x128(%rsp), %rdi
callq 0x164b0
movl %eax, %ecx
movl 0x74(%rsp), %eax
cmpl %ecx, %eax
jge 0x151d9
movq 0x100(%rsp), %rax
movslq 0xfc(%rsp), %rcx
movl $0xffffffff, (%rax,%rcx,4) # imm = 0xFFFFFFFF
movl 0xfc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xfc(%rsp)
jmp 0x1518d
movl $0x0, 0xf8(%rsp)
leaq 0xe8(%rsp), %rdi
callq 0x168f0
movq $0x0, 0xe0(%rsp)
movl 0xf8(%rsp), %eax
movl %eax, 0x6c(%rsp)
movq 0x128(%rsp), %rdi
callq 0x164b0
movl %eax, 0x70(%rsp)
jmp 0x1521b
movl 0x6c(%rsp), %eax
movl 0x70(%rsp), %ecx
cmpl %ecx, %eax
jge 0x152ac
movq 0x128(%rsp), %rdi
movl 0xf8(%rsp), %esi
callq 0x164d0
movq %rax, 0x60(%rsp)
jmp 0x15246
movq 0x60(%rsp), %rax
movq %rax, 0xc8(%rsp)
movq 0x100(%rsp), %rax
movslq 0xf8(%rsp), %rcx
cmpl $0x0, (%rax,%rcx,4)
jge 0x15294
movq 0xc8(%rsp), %rax
movq %rax, 0xe0(%rsp)
jmp 0x152ac
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xd8(%rsp)
movl %eax, 0xd4(%rsp)
jmp 0x15789
jmp 0x15296
movl 0xf8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xf8(%rsp)
jmp 0x151fd
cmpq $0x0, 0xe0(%rsp)
jne 0x152bc
jmp 0x155f0
leaq 0x14b20d(%rip), %rax    # 0x1604d0
movl (%rax), %ecx
incl %ecx
movl %ecx, (%rax)
movq $0x0, 0xc0(%rsp)
leaq 0xb0(%rsp), %rdi
callq 0x168f0
jmp 0x152e4
leaq 0xa0(%rsp), %rdi
callq 0x168f0
jmp 0x152f3
movq 0xe0(%rsp), %rsi
leaq 0xb0(%rsp), %rdi
callq 0x16c30
jmp 0x1530a
movq 0x128(%rsp), %rdi
movq 0xe0(%rsp), %rsi
leaq 0x14b1af(%rip), %rax    # 0x1604d0
movl (%rax), %edx
callq 0x16c60
jmp 0x1532a
jmp 0x1532c
leaq 0xb0(%rsp), %rdi
callq 0x16c80
movl %eax, 0x5c(%rsp)
jmp 0x1533f
movl 0x5c(%rsp), %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x15354
jmp 0x15532
leaq 0xb0(%rsp), %rdi
callq 0x16ca0
movq %rax, 0x50(%rsp)
jmp 0x15368
movq 0x50(%rsp), %rax
movq %rax, 0x98(%rsp)
leaq 0xb0(%rsp), %rdi
callq 0x16cb0
jmp 0x15384
movq 0x98(%rsp), %rsi
leaq 0xa0(%rsp), %rdi
callq 0x16970
jmp 0x1539b
movq 0x128(%rsp), %rdi
movq 0x98(%rsp), %rsi
callq 0x16900
movsd %xmm0, 0x48(%rsp)
jmp 0x153b8
movsd 0x48(%rsp), %xmm1
movsd 0xc0(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xc0(%rsp)
movl 0x10c(%rsp), %eax
movl %eax, 0x34(%rsp)
movq 0x100(%rsp), %rax
movq %rax, 0x38(%rsp)
movq 0x128(%rsp), %rdi
movq 0x98(%rsp), %rsi
callq 0x16cd0
movl %eax, 0x44(%rsp)
jmp 0x15407
movq 0x38(%rsp), %rax
movl 0x34(%rsp), %edx
movl 0x44(%rsp), %ecx
movslq %ecx, %rcx
movl %edx, (%rax,%rcx,4)
movl $0x0, 0x94(%rsp)
cmpl $0x3, 0x94(%rsp)
jge 0x1552d
movq 0x128(%rsp), %rdi
movq 0x98(%rsp), %rsi
movl 0x94(%rsp), %edx
callq 0x16cf0
movq %rax, 0x28(%rsp)
jmp 0x15456
movq 0x28(%rsp), %rax
movq %rax, 0x88(%rsp)
cmpq $0x0, 0x88(%rsp)
jne 0x154b2
jmp 0x15517
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xd8(%rsp)
movl %eax, 0xd4(%rsp)
jmp 0x155de
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xd8(%rsp)
movl %eax, 0xd4(%rsp)
leaq 0xa0(%rsp), %rdi
callq 0x169c0
jmp 0x155de
movq 0x128(%rsp), %rdi
movq 0x88(%rsp), %rsi
callq 0x16d30
movl %eax, 0x24(%rsp)
jmp 0x154cd
movl 0x24(%rsp), %eax
leaq 0x14aff8(%rip), %rcx    # 0x1604d0
cmpl (%rcx), %eax
jne 0x154de
jmp 0x15517
movq 0x128(%rsp), %rdi
movq 0x88(%rsp), %rsi
leaq 0x14afdb(%rip), %rax    # 0x1604d0
movl (%rax), %edx
callq 0x16c60
jmp 0x154fe
movq 0x88(%rsp), %rsi
leaq 0xb0(%rsp), %rdi
callq 0x16c30
jmp 0x15515
jmp 0x15517
movl 0x94(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x94(%rsp)
jmp 0x15425
jmp 0x1532c
leaq 0xa0(%rsp), %rdi
callq 0x16650
cmpl $0x0, %eax
jne 0x15551
movl $0x6, 0x84(%rsp)
jmp 0x155ad
movsd 0xc0(%rsp), %xmm1
movsd 0x120(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x15591
leaq 0xe8(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
callq 0xc47d0
jmp 0x15580
movl 0x108(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x108(%rsp)
movl 0x10c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x10c(%rsp)
movl $0x0, 0x84(%rsp)
leaq 0xa0(%rsp), %rdi
callq 0x169c0
leaq 0xb0(%rsp), %rdi
callq 0x169c0
movl 0x84(%rsp), %eax
testl %eax, %eax
je 0x155d9
jmp 0x155d4
jmp 0x151f1
jmp 0x151f1
leaq 0xb0(%rsp), %rdi
callq 0x169c0
jmp 0x15789
movl $0x0, 0x80(%rsp)
movl 0x80(%rsp), %eax
movl %eax, 0x20(%rsp)
leaq 0xe8(%rsp), %rdi
callq 0x16650
movl %eax, %ecx
movl 0x20(%rsp), %eax
cmpl %ecx, %eax
jge 0x1566f
movl 0x80(%rsp), %esi
leaq 0xe8(%rsp), %rdi
callq 0x169a0
movq %rax, 0x18(%rsp)
jmp 0x15638
movq 0x18(%rsp), %rax
movq %rax, 0x78(%rsp)
movq 0x128(%rsp), %rdi
movq 0x78(%rsp), %rsi
movq (%rdi), %rax
movq 0x70(%rax), %rax
callq *%rax
jmp 0x1565a
jmp 0x1565c
movl 0x80(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x80(%rsp)
jmp 0x155fb
movq 0x100(%rsp), %rax
movq %rax, 0x10(%rsp)
cmpq $0x0, %rax
je 0x1568c
movq 0x10(%rsp), %rdi
callq 0xf630
cmpl $0x0, 0x14b801(%rip)    # 0x160e94
je 0x15764
leaq 0x110cbe(%rip), %rdi    # 0x12635e
xorl %eax, %eax
callq 0xf070
jmp 0x156a9
leaq 0x110(%rsp), %rdi
callq 0xc3690
movsd %xmm0, 0x8(%rsp)
jmp 0x156be
movsd 0x8(%rsp), %xmm0
leaq 0x110c44(%rip), %rdi    # 0x12630f
movb $0x1, %al
callq 0xf070
jmp 0x156d4
movl 0x108(%rsp), %esi
leaq 0x110ca6(%rip), %rdi    # 0x126388
xorl %eax, %eax
callq 0xf070
jmp 0x156eb
leaq 0xe8(%rsp), %rdi
callq 0x16650
movl %eax, %esi
leaq 0x110c27(%rip), %rdi    # 0x126328
xorl %eax, %eax
callq 0xf070
jmp 0x1570a
movl 0x10c(%rsp), %esi
movl 0x108(%rsp), %eax
subl %eax, %esi
leaq 0x110c86(%rip), %rdi    # 0x1263a7
xorl %eax, %eax
callq 0xf070
jmp 0x1572a
movq 0x128(%rsp), %rdi
callq 0x164b0
movl %eax, 0x4(%rsp)
jmp 0x1573d
movl 0x4(%rsp), %esi
leaq 0x110bfa(%rip), %rdi    # 0x126342
xorl %eax, %eax
callq 0xf070
jmp 0x15751
movq 0x14a838(%rip), %rax    # 0x15ff90
movq (%rax), %rdi
callq 0xf5a0
jmp 0x15762
jmp 0x15764
movl $0x1, 0x134(%rsp)
movl $0x1, 0x84(%rsp)
leaq 0xe8(%rsp), %rdi
callq 0x169c0
jmp 0x15798
leaq 0xe8(%rsp), %rdi
callq 0x169c0
jmp 0x157a7
movl 0x134(%rsp), %eax
addq $0x138, %rsp            # imm = 0x138
retq
movq 0xd8(%rsp), %rdi
callq 0xf820
nopw %cs:(%rax,%rax)