// File: tomfunkhouser[P]gaps/pkgs/R2Shapes/R2Grid.cpp
// Function: gaps::R2Grid::ConnectedComponentCentroidFilter(double)
void R2Grid::
ConnectedComponentCentroidFilter(RNScalar isolevel)
{
  // Compute connected components
  int *sizes = new int [ grid_size ];
  int *components = new int [ grid_size ];
  int ncomponents = ConnectedComponents(isolevel, grid_size, NULL, sizes, components);
  if (ncomponents == 0) { Clear(0); return; }

  // Allocate and initalize centroids
  int *centroid_counts = new int [ ncomponents ];
  R2Point *centroid_positions = new R2Point [ ncomponents ];
  RNScalar *centroid_values = new RNScalar [ ncomponents ];
  for (int i = 0; i < ncomponents; i++) {
    centroid_counts[i] = 0;
    centroid_positions[i] = R2zero_point;
    centroid_values[i] = 0;
  }

  // Sum positions in every connected component
  for (int i = 0; i < grid_size; i++) {
    if (grid_values[i] == R2_GRID_UNKNOWN_VALUE) continue;
    int component = components[i];
    if ((component < 0) || (component >= ncomponents)) continue;
    int ix, iy;
    IndexToIndices(i, ix, iy);
    centroid_counts[component]++;
    centroid_positions[component][0] += ix;
    centroid_positions[component][1] += iy;
  }

  // Divide by counts
  for (int i = 0; i < ncomponents; i++) {
    if (centroid_counts[i] == 0) continue;
    centroid_positions[i] /= centroid_counts[i];
  }

  // Remember original values at centroids in grid
  for (int i = 0; i < ncomponents; i++) {
    if (centroid_counts[i] == 0) continue;
    int ix = (int) (centroid_positions[i][0] + 0.5);
    int iy = (int) (centroid_positions[i][1] + 0.5);
    if ((ix < 0) || (ix >= grid_resolution[0])) continue;
    if ((iy < 0) || (iy >= grid_resolution[1])) continue;
    centroid_values[i] = GridValue(ix, iy);
  }

  // Clear out entire grid
  Clear(0);

  // Set values at centroids of connected components
  for (int i = 0; i < ncomponents; i++) {
    if (centroid_counts[i] == 0) continue;
    int ix = (int) (centroid_positions[i][0] + 0.5);
    int iy = (int) (centroid_positions[i][1] + 0.5);
    if ((ix < 0) || (ix >= grid_resolution[0])) continue;
    if ((iy < 0) || (iy >= grid_resolution[1])) continue;
    SetGridValue(ix, iy, centroid_values[i]);
  }

  // Delete temporary memory
  delete [] centroid_counts;
  delete [] centroid_positions;
  delete [] centroid_values;
  delete [] components;
  delete [] sizes;
}

// Assembly:
subq $0xf8, %rsp
movq %rdi, 0xf0(%rsp)
movsd %xmm0, 0xe8(%rsp)
movq 0xf0(%rsp), %rax
movq %rax, 0x70(%rsp)
movslq 0xcc(%rax), %rax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0xf030
movq %rax, %rcx
movq 0x70(%rsp), %rax
movq %rcx, 0xe0(%rsp)
movslq 0xcc(%rax), %rax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0xf030
movq 0x70(%rsp), %rdi
movq %rax, 0xd8(%rsp)
movsd 0xe8(%rsp), %xmm0
movl 0xcc(%rdi), %esi
movq 0xe0(%rsp), %rcx
movq 0xd8(%rsp), %r8
xorl %eax, %eax
movl %eax, %edx
callq 0xb45c0
movl %eax, 0xd4(%rsp)
cmpl $0x0, 0xd4(%rsp)
jne 0xb53cd
movq 0x70(%rsp), %rdi
xorps %xmm0, %xmm0
callq 0xa9d20
jmp 0xb5a19
movslq 0xd4(%rsp), %rax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0xf030
movq %rax, 0xc8(%rsp)
movslq 0xd4(%rsp), %rax
movq %rax, 0x60(%rsp)
movl $0x10, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, 0x58(%rsp)
callq 0xf030
movq %rax, %rcx
movq 0x60(%rsp), %rax
movq %rcx, 0x68(%rsp)
cmpq $0x0, %rax
je 0xb548b
movq 0x68(%rsp), %rax
movq 0x60(%rsp), %rdx
shlq $0x4, %rdx
movq %rax, %rcx
addq %rdx, %rcx
movq %rcx, 0x48(%rsp)
movq %rax, 0x50(%rsp)
movq 0x50(%rsp), %rdi
movq %rdi, 0x40(%rsp)
callq 0xc3130
jmp 0xb5473
movq 0x48(%rsp), %rcx
movq 0x40(%rsp), %rax
addq $0x10, %rax
cmpq %rcx, %rax
movq %rax, 0x50(%rsp)
jne 0xb5462
movq 0x68(%rsp), %rax
movq %rax, 0xc0(%rsp)
movslq 0xd4(%rsp), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0xf030
movq %rax, 0xa8(%rsp)
movl $0x0, 0xa4(%rsp)
movl 0xa4(%rsp), %eax
cmpl 0xd4(%rsp), %eax
jge 0xb5575
movq 0xc8(%rsp), %rax
movslq 0xa4(%rsp), %rcx
movl $0x0, (%rax,%rcx,4)
movq 0xc0(%rsp), %rdi
movslq 0xa4(%rsp), %rax
shlq $0x4, %rax
addq %rax, %rdi
leaq 0x4c58fb(%rip), %rsi    # 0x57ae18
callq 0xc33e0
movq 0xa8(%rsp), %rax
movslq 0xa4(%rsp), %rcx
xorps %xmm0, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl 0xa4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa4(%rsp)
jmp 0xb54d4
movq 0x58(%rsp), %rsi
movq 0x68(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb8(%rsp)
movl %eax, 0xb4(%rsp)
callq 0xf990
jmp 0xb5a21
movl $0x0, 0xa0(%rsp)
movq 0x70(%rsp), %rcx
movl 0xa0(%rsp), %eax
cmpl 0xcc(%rcx), %eax
jge 0xb56c8
movq 0x70(%rsp), %rax
movq 0xb8(%rax), %rax
movslq 0xa0(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
movsd 0x7e8f7(%rip), %xmm1    # 0x133eb0
ucomisd %xmm1, %xmm0
jne 0xb55c6
jp 0xb55c6
jmp 0xb56b2
movq 0xd8(%rsp), %rax
movslq 0xa0(%rsp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, 0x9c(%rsp)
cmpl $0x0, 0x9c(%rsp)
jl 0xb55fa
movl 0x9c(%rsp), %eax
cmpl 0xd4(%rsp), %eax
jl 0xb55ff
jmp 0xb56b2
movq 0x70(%rsp), %rdi
movl 0xa0(%rsp), %esi
leaq 0x98(%rsp), %rdx
leaq 0x94(%rsp), %rcx
callq 0xb9440
movq 0xc8(%rsp), %rax
movslq 0x9c(%rsp), %rcx
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
movl %edx, (%rax,%rcx,4)
cvtsi2sdl 0x98(%rsp), %xmm0
movsd %xmm0, 0x30(%rsp)
movq 0xc0(%rsp), %rdi
movslq 0x9c(%rsp), %rax
shlq $0x4, %rax
addq %rax, %rdi
xorl %esi, %esi
callq 0xa5b60
movsd 0x30(%rsp), %xmm0
addsd (%rax), %xmm0
movsd %xmm0, (%rax)
cvtsi2sdl 0x94(%rsp), %xmm0
movsd %xmm0, 0x38(%rsp)
movq 0xc0(%rsp), %rdi
movslq 0x9c(%rsp), %rax
shlq $0x4, %rax
addq %rax, %rdi
movl $0x1, %esi
callq 0xa5b60
movsd 0x38(%rsp), %xmm0
addsd (%rax), %xmm0
movsd %xmm0, (%rax)
movl 0xa0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa0(%rsp)
jmp 0xb5580
movl $0x0, 0x90(%rsp)
movl 0x90(%rsp), %eax
cmpl 0xd4(%rsp), %eax
jge 0xb573f
movq 0xc8(%rsp), %rax
movslq 0x90(%rsp), %rcx
cmpl $0x0, (%rax,%rcx,4)
jne 0xb56fb
jmp 0xb572c
movq 0xc8(%rsp), %rax
movslq 0x90(%rsp), %rcx
cvtsi2sdl (%rax,%rcx,4), %xmm0
movq 0xc0(%rsp), %rdi
movslq 0x90(%rsp), %rax
shlq $0x4, %rax
addq %rax, %rdi
callq 0xc3660
movl 0x90(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x90(%rsp)
jmp 0xb56d3
movl $0x0, 0x8c(%rsp)
movl 0x8c(%rsp), %eax
cmpl 0xd4(%rsp), %eax
jge 0xb5869
movq 0xc8(%rsp), %rax
movslq 0x8c(%rsp), %rcx
cmpl $0x0, (%rax,%rcx,4)
jne 0xb5779
jmp 0xb5853
movq 0xc0(%rsp), %rdi
movslq 0x8c(%rsp), %rax
shlq $0x4, %rax
addq %rax, %rdi
xorl %esi, %esi
callq 0xa5b60
movsd 0x7d871(%rip), %xmm0    # 0x133010
addsd (%rax), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x88(%rsp)
movq 0xc0(%rsp), %rdi
movslq 0x8c(%rsp), %rax
shlq $0x4, %rax
addq %rax, %rdi
movl $0x1, %esi
callq 0xa5b60
movsd 0x7d839(%rip), %xmm0    # 0x133010
addsd (%rax), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x84(%rsp)
cmpl $0x0, 0x88(%rsp)
jl 0xb5804
movq 0x70(%rsp), %rcx
movl 0x88(%rsp), %eax
cmpl 0xc0(%rcx), %eax
jl 0xb5806
jmp 0xb5853
cmpl $0x0, 0x84(%rsp)
jl 0xb5824
movq 0x70(%rsp), %rcx
movl 0x84(%rsp), %eax
cmpl 0xc4(%rcx), %eax
jl 0xb5826
jmp 0xb5853
movq 0x70(%rsp), %rdi
movl 0x88(%rsp), %esi
movl 0x84(%rsp), %edx
callq 0xb92a0
movq 0xa8(%rsp), %rax
movslq 0x8c(%rsp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl 0x8c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8c(%rsp)
jmp 0xb574a
movq 0x70(%rsp), %rdi
xorps %xmm0, %xmm0
callq 0xa9d20
movl $0x0, 0x80(%rsp)
movl 0x80(%rsp), %eax
cmpl 0xd4(%rsp), %eax
jge 0xb5988
movq 0xc8(%rsp), %rax
movslq 0x80(%rsp), %rcx
cmpl $0x0, (%rax,%rcx,4)
jne 0xb58b0
jmp 0xb5972
movq 0xc0(%rsp), %rdi
movslq 0x80(%rsp), %rax
shlq $0x4, %rax
addq %rax, %rdi
xorl %esi, %esi
callq 0xa5b60
movsd 0x7d73a(%rip), %xmm0    # 0x133010
addsd (%rax), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x7c(%rsp)
movq 0xc0(%rsp), %rdi
movslq 0x80(%rsp), %rax
shlq $0x4, %rax
addq %rax, %rdi
movl $0x1, %esi
callq 0xa5b60
movsd 0x7d705(%rip), %xmm0    # 0x133010
addsd (%rax), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x78(%rsp)
cmpl $0x0, 0x7c(%rsp)
jl 0xb592f
movq 0x70(%rsp), %rcx
movl 0x7c(%rsp), %eax
cmpl 0xc0(%rcx), %eax
jl 0xb5931
jmp 0xb5972
cmpl $0x0, 0x78(%rsp)
jl 0xb5949
movq 0x70(%rsp), %rcx
movl 0x78(%rsp), %eax
cmpl 0xc4(%rcx), %eax
jl 0xb594b
jmp 0xb5972
movq 0x70(%rsp), %rdi
movl 0x7c(%rsp), %esi
movl 0x78(%rsp), %edx
movq 0xa8(%rsp), %rax
movslq 0x80(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
callq 0x6bc00
movl 0x80(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x80(%rsp)
jmp 0xb5881
movq 0xc8(%rsp), %rax
movq %rax, 0x28(%rsp)
cmpq $0x0, %rax
je 0xb59a5
movq 0x28(%rsp), %rdi
callq 0xf670
movq 0xc0(%rsp), %rax
movq %rax, 0x20(%rsp)
cmpq $0x0, %rax
je 0xb59c2
movq 0x20(%rsp), %rdi
callq 0xf670
movq 0xa8(%rsp), %rax
movq %rax, 0x18(%rsp)
cmpq $0x0, %rax
je 0xb59df
movq 0x18(%rsp), %rdi
callq 0xf670
movq 0xd8(%rsp), %rax
movq %rax, 0x10(%rsp)
cmpq $0x0, %rax
je 0xb59fc
movq 0x10(%rsp), %rdi
callq 0xf670
movq 0xe0(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0xb5a19
movq 0x8(%rsp), %rdi
callq 0xf670
addq $0xf8, %rsp
retq
movq 0xb8(%rsp), %rdi
callq 0xf890
nop