// File: tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelUtils.cpp
// Function: gaps::MaskToSelectedConnectedComponent(gaps::R3Grid*, double, gaps::R3Point const&, double, double)
static int
MaskToSelectedConnectedComponent(R3Grid *grid, RNScalar isolevel, 
  const R3Point& center, 
  RNScalar min_component_volume, RNScalar max_component_volume)
{
  // Check grid size
  if (grid->NEntries() == 0) return 0;

  // Get convenient variables
  RNScalar length_scale = grid->WorldToGridScaleFactor();
  RNScalar volume_scale = length_scale * length_scale * length_scale;
  int min_component_size = (int) (min_component_volume * volume_scale);
  int max_component_size = (int) (max_component_volume * volume_scale);
  int status = 0;

  // Allocate temporary memory for connectec components
  int *component_sizes = new int [ grid->NEntries() ];
  int *component_seeds = new int [ grid->NEntries() ];
  int *component_membership = new int [ grid->NEntries() ];

  // Compute connected component of grid
  int ncomponents = grid->ConnectedComponents(isolevel, grid->NEntries(), 
    component_seeds, component_sizes, component_membership);
  if (ncomponents > 0) {
    // Check if grid cell containing center point is in a connected component
    int center_index = 0;
    R3Point grid_position = grid->GridPosition(center);
    int closest_component = -1;
    int center_i = (int) (grid_position[0] + 0.5);
    if ((center_i >= 0) && (center_i < grid->XResolution())) {
      int center_j = (int) (grid_position[1] + 0.5);
      if ((center_j >= 0) && (center_j < grid->YResolution())) {
        int center_k = (int) (grid_position[2] + 0.5);
        if ((center_k >= 0) && (center_k < grid->ZResolution())) {
          grid->IndicesToIndex(center_i, center_j, center_k, center_index);
          closest_component = component_membership[center_index];
          if (min_component_size > 0) {
            if (closest_component >= 0) { // to silence compiler
              if (component_sizes[closest_component] < min_component_size) {
                closest_component = -1;
              }
            }
          }
          if (max_component_size > 0) {
            if (closest_component >= 0) { // to silence compiler
              if (component_sizes[closest_component] > max_component_size) {
                closest_component = -1;
              }
            }
          }
        }
      }
    }

    // If not, find component whose size is big enough and whose seed is closest to center point
    if (closest_component < 0) {
      RNLength closest_dd = FLT_MAX;
      for (int i = 0; i < ncomponents; i++) {
        int seed_i, seed_j, seed_k;
        if ((min_component_size > 0) && (component_sizes[i] < min_component_size)) continue;
        if ((max_component_size > 0) && (component_sizes[i] > max_component_size)) continue;
        grid->IndexToIndices(component_seeds[i], seed_i, seed_j, seed_k);
        RNLength dd = R3SquaredDistance(R3Point(seed_i, seed_j, seed_k), grid_position);
        if (dd < closest_dd) { closest_dd = dd; closest_component = i; }       
      }
    }

    // Zero all grid entries outside selected connected component
    if (closest_component >= 0) {
      status = 1;
      for (int i = 0; i < grid->NEntries(); i++) {
        if (component_membership[i] == closest_component) grid->SetGridValue(i, 1);
        else grid->SetGridValue(i, 0);
      }
    }
  }

  // Delete temporary memory
  delete [] component_sizes;
  delete [] component_seeds;
  delete [] component_membership;

  // Return status
  return status;
}

// Assembly:
subq $0x118, %rsp            # imm = 0x118
movq %rdi, 0x108(%rsp)
movsd %xmm0, 0x100(%rsp)
movq %rsi, 0xf8(%rsp)
movsd %xmm1, 0xf0(%rsp)
movsd %xmm2, 0xe8(%rsp)
movq 0x108(%rsp), %rdi
callq 0x43fd0
cmpl $0x0, %eax
jne 0x3a494
movl $0x0, 0x114(%rsp)
jmp 0x3aa54
movq 0x108(%rsp), %rdi
callq 0x44040
movsd %xmm0, 0xe0(%rsp)
movsd 0xe0(%rsp), %xmm0
mulsd 0xe0(%rsp), %xmm0
mulsd 0xe0(%rsp), %xmm0
movsd %xmm0, 0xd8(%rsp)
movsd 0xf0(%rsp), %xmm0
mulsd 0xd8(%rsp), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0xd4(%rsp)
movsd 0xe8(%rsp), %xmm0
mulsd 0xd8(%rsp), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0xd0(%rsp)
movl $0x0, 0xcc(%rsp)
movq 0x108(%rsp), %rdi
callq 0x43fd0
cltq
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x13030
movq %rax, 0xc0(%rsp)
movq 0x108(%rsp), %rdi
callq 0x43fd0
cltq
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x13030
movq %rax, 0xb8(%rsp)
movq 0x108(%rsp), %rdi
callq 0x43fd0
cltq
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x13030
movq %rax, 0xb0(%rsp)
movq 0x108(%rsp), %rax
movq %rax, 0x30(%rsp)
movsd 0x100(%rsp), %xmm0
movsd %xmm0, 0x38(%rsp)
movq 0x108(%rsp), %rdi
callq 0x43fd0
movq 0x30(%rsp), %rdi
movsd 0x38(%rsp), %xmm0
movl %eax, %esi
movq 0xb8(%rsp), %rdx
movq 0xc0(%rsp), %rcx
movq 0xb0(%rsp), %r8
callq 0xf24d0
movl %eax, 0xac(%rsp)
cmpl $0x0, 0xac(%rsp)
jle 0x3a9ef
movl $0x0, 0xa8(%rsp)
movq 0x108(%rsp), %rsi
movq 0xf8(%rsp), %rdx
leaq 0x90(%rsp), %rdi
callq 0x44060
movl $0xffffffff, 0x8c(%rsp) # imm = 0xFFFFFFFF
leaq 0x90(%rsp), %rdi
xorl %esi, %esi
callq 0x1bde0
movsd 0x169aeb(%rip), %xmm0   # 0x1a4158
addsd (%rax), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x88(%rsp)
cmpl $0x0, 0x88(%rsp)
jl 0x3a832
movl 0x88(%rsp), %eax
movl %eax, 0x2c(%rsp)
movq 0x108(%rsp), %rdi
callq 0x454c0
movl %eax, %ecx
movl 0x2c(%rsp), %eax
cmpl %ecx, %eax
jge 0x3a832
leaq 0x90(%rsp), %rdi
movl $0x1, %esi
callq 0x1bde0
movsd 0x169a8e(%rip), %xmm0   # 0x1a4158
addsd (%rax), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x84(%rsp)
cmpl $0x0, 0x84(%rsp)
jl 0x3a830
movl 0x84(%rsp), %eax
movl %eax, 0x28(%rsp)
movq 0x108(%rsp), %rdi
callq 0x454e0
movl %eax, %ecx
movl 0x28(%rsp), %eax
cmpl %ecx, %eax
jge 0x3a830
leaq 0x90(%rsp), %rdi
movl $0x2, %esi
callq 0x1bde0
movsd 0x169a31(%rip), %xmm0   # 0x1a4158
addsd (%rax), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x80(%rsp)
cmpl $0x0, 0x80(%rsp)
jl 0x3a82e
movl 0x80(%rsp), %eax
movl %eax, 0x24(%rsp)
movq 0x108(%rsp), %rdi
callq 0x45500
movl %eax, %ecx
movl 0x24(%rsp), %eax
cmpl %ecx, %eax
jge 0x3a82e
movq 0x108(%rsp), %rdi
movl 0x88(%rsp), %esi
movl 0x84(%rsp), %edx
movl 0x80(%rsp), %ecx
leaq 0xa8(%rsp), %r8
callq 0x45520
movq 0xb0(%rsp), %rax
movslq 0xa8(%rsp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, 0x8c(%rsp)
cmpl $0x0, 0xd4(%rsp)
jle 0x3a7ed
cmpl $0x0, 0x8c(%rsp)
jl 0x3a7eb
movq 0xc0(%rsp), %rax
movslq 0x8c(%rsp), %rcx
movl (%rax,%rcx,4), %eax
cmpl 0xd4(%rsp), %eax
jge 0x3a7e9
movl $0xffffffff, 0x8c(%rsp) # imm = 0xFFFFFFFF
jmp 0x3a7eb
jmp 0x3a7ed
cmpl $0x0, 0xd0(%rsp)
jle 0x3a82c
cmpl $0x0, 0x8c(%rsp)
jl 0x3a82a
movq 0xc0(%rsp), %rax
movslq 0x8c(%rsp), %rcx
movl (%rax,%rcx,4), %eax
cmpl 0xd0(%rsp), %eax
jle 0x3a828
movl $0xffffffff, 0x8c(%rsp) # imm = 0xFFFFFFFF
jmp 0x3a82a
jmp 0x3a82c
jmp 0x3a82e
jmp 0x3a830
jmp 0x3a832
cmpl $0x0, 0x8c(%rsp)
jge 0x3a954
movsd 0x169948(%rip), %xmm0   # 0x1a4190
movsd %xmm0, 0x78(%rsp)
movl $0x0, 0x74(%rsp)
movl 0x74(%rsp), %eax
cmpl 0xac(%rsp), %eax
jge 0x3a952
cmpl $0x0, 0xd4(%rsp)
jle 0x3a88f
movq 0xc0(%rsp), %rax
movslq 0x74(%rsp), %rcx
movl (%rax,%rcx,4), %eax
cmpl 0xd4(%rsp), %eax
jge 0x3a88f
jmp 0x3a942
cmpl $0x0, 0xd0(%rsp)
jle 0x3a8b7
movq 0xc0(%rsp), %rax
movslq 0x74(%rsp), %rcx
movl (%rax,%rcx,4), %eax
cmpl 0xd0(%rsp), %eax
jle 0x3a8b7
jmp 0x3a942
movq 0x108(%rsp), %rdi
movq 0xb8(%rsp), %rax
movslq 0x74(%rsp), %rcx
movl (%rax,%rcx,4), %esi
leaq 0x70(%rsp), %rdx
leaq 0x6c(%rsp), %rcx
leaq 0x68(%rsp), %r8
callq 0x45560
cvtsi2sdl 0x70(%rsp), %xmm0
cvtsi2sdl 0x6c(%rsp), %xmm1
cvtsi2sdl 0x68(%rsp), %xmm2
leaq 0x48(%rsp), %rdi
callq 0xf8350
leaq 0x48(%rsp), %rdi
leaq 0x90(%rsp), %rsi
callq 0x8e7b0
movsd %xmm0, 0x60(%rsp)
movsd 0x60(%rsp), %xmm1
movsd 0x78(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x3a940
movsd 0x60(%rsp), %xmm0
movsd %xmm0, 0x78(%rsp)
movl 0x74(%rsp), %eax
movl %eax, 0x8c(%rsp)
jmp 0x3a942
movl 0x74(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x74(%rsp)
jmp 0x3a856
jmp 0x3a954
cmpl $0x0, 0x8c(%rsp)
jl 0x3a9ed
movl $0x1, 0xcc(%rsp)
movl $0x0, 0x44(%rsp)
movl 0x44(%rsp), %eax
movl %eax, 0x20(%rsp)
movq 0x108(%rsp), %rdi
callq 0x43fd0
movl %eax, %ecx
movl 0x20(%rsp), %eax
cmpl %ecx, %eax
jge 0x3a9eb
movq 0xb0(%rsp), %rax
movslq 0x44(%rsp), %rcx
movl (%rax,%rcx,4), %eax
cmpl 0x8c(%rsp), %eax
jne 0x3a9c8
movq 0x108(%rsp), %rdi
movl 0x44(%rsp), %esi
movsd 0x1697a7(%rip), %xmm0   # 0x1a4168
callq 0x45490
jmp 0x3a9dc
movq 0x108(%rsp), %rdi
movl 0x44(%rsp), %esi
xorps %xmm0, %xmm0
callq 0x45490
jmp 0x3a9de
movl 0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x44(%rsp)
jmp 0x3a975
jmp 0x3a9ed
jmp 0x3a9ef
movq 0xc0(%rsp), %rax
movq %rax, 0x18(%rsp)
cmpq $0x0, %rax
je 0x3aa0c
movq 0x18(%rsp), %rdi
callq 0x13750
movq 0xb8(%rsp), %rax
movq %rax, 0x10(%rsp)
cmpq $0x0, %rax
je 0x3aa29
movq 0x10(%rsp), %rdi
callq 0x13750
movq 0xb0(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x3aa46
movq 0x8(%rsp), %rdi
callq 0x13750
movl 0xcc(%rsp), %eax
movl %eax, 0x114(%rsp)
movl 0x114(%rsp), %eax
addq $0x118, %rsp            # imm = 0x118
retq
nopw %cs:(%rax,%rax)