// File: tomfunkhouser[P]gaps/apps/msh2pts/msh2pts.cpp
// Function: SelectFurthestPoints(gaps::R3Mesh*, gaps::RNArray<gaps::R3MeshVertex*> const&, int, double)
static RNArray<Point *> *
SelectFurthestPoints(R3Mesh *mesh, const RNArray<R3MeshVertex *>& seeds, int npoints, double min_spacing)
{
  // Check/adjust number of points
  if (npoints > mesh->NVertices()) npoints = mesh->NVertices();

  // Allocate array of points
  RNArray<Point *> *points = new RNArray<Point *>();
  if (!points) {
    RNFail("Unable to allocate array of points\n");
    return NULL;
  }

  // Allocate vertex data
  VertexData *vertex_data = new VertexData [ mesh->NVertices() ];
  if (!vertex_data) {
    RNFail("Unable to allocate vertex data\n");
    return NULL;
  }

  // Initialize vertex data
  for (int i = 0; i < mesh->NVertices(); i++) {
    R3MeshVertex *vertex = mesh->Vertex(i);
    VertexData *data = &vertex_data[i];
    mesh->SetVertexData(vertex, data);
    data->vertex = vertex;
    data->distance = FLT_MAX;
    data->closest_seed = NULL;
    data->heappointer = NULL;
  }

  // Copy seeds 
  RNArray<R3MeshVertex *> vertices;
  for (int i = 0; i < seeds.NEntries(); i++) {
    R3MeshVertex *vertex = seeds.Kth(i);
    Point *point = new Point(mesh, vertex);
    points->Insert(point);
    vertices.Insert(vertex);
  }

  // Create random starting vertex in each connected component, if none provided
  RNArray<R3MeshVertex *> tmp;
  if (seeds.IsEmpty()) {
    int *marks = new int [ mesh->NVertices() ];
    for (int i = 0; i < mesh->NVertices(); i++) marks[i] = 0;
    for (int i = 0; i < mesh->NVertices(); i++) {
      R3MeshVertex *vertex = mesh->Vertex(i);

      // Check if already marked
      if (marks[i] != 0) continue;
      marks[i] = 1;

      // Check if completely disconnected
      if (mesh->VertexValence(vertex) == 0) continue;

      // Select vertex as temporary seed
      vertices.Insert(vertex);
      tmp.Insert(vertex);

      // Mark connected component
      RNArray<R3MeshVertex *> connected_component;
      mesh->FindConnectedVertices(vertex, connected_component);
      for (int j = 0; j < connected_component.NEntries(); j++) {
        R3MeshVertex *connected_vertex = connected_component.Kth(j);
        marks[mesh->VertexID(connected_vertex)] = 1;
      }
    }
  }

  // Iteratively find furthest vertex
  while (vertices.NEntries() - tmp.NEntries() < npoints) {
    R3MeshVertex *vertex = FindFurthestVertex(mesh, vertices, vertex_data);
    if (!vertex) break;
    VertexData *data = &vertex_data[mesh->VertexID(vertex)];
    if ((min_spacing > 0) && (data->distance < min_spacing)) break;
    if (tmp.FindEntry(data->closest_seed)) { 
      tmp.Remove(data->closest_seed); 
      vertices.Remove(data->closest_seed);
    }
    Point *point = new Point(mesh, vertex);
    points->Insert(point);
    vertices.Insert(vertex);
  }

  // Delete vertex data
  delete [] vertex_data;

  // Return points
  return points;
}

// Assembly:
subq $0x178, %rsp            # imm = 0x178
movq %rdi, 0x168(%rsp)
movq %rsi, 0x160(%rsp)
movl %edx, 0x15c(%rsp)
movsd %xmm0, 0x150(%rsp)
movl 0x15c(%rsp), %eax
movl %eax, 0x8c(%rsp)
movq 0x168(%rsp), %rdi
callq 0x1b460
movl %eax, %ecx
movl 0x8c(%rsp), %eax
cmpl %ecx, %eax
jle 0x198d3
movq 0x168(%rsp), %rdi
callq 0x1b460
movl %eax, 0x15c(%rsp)
movl $0x10, %edi
callq 0xf4d0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x80(%rsp)
callq 0x1b5a0
jmp 0x198f2
movq 0x80(%rsp), %rax
movq %rax, 0x148(%rsp)
cmpq $0x0, 0x148(%rsp)
jne 0x19957
leaq 0x130cfb(%rip), %rdi    # 0x14a60f
movb $0x0, %al
callq 0xebe00
movq $0x0, 0x170(%rsp)
jmp 0x1a0d5
movq 0x80(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
movl $0x10, %esi
callq 0xf4e0
jmp 0x1a0e5
movq 0x168(%rsp), %rdi
callq 0x1b460
cltq
movl $0x20, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0xf030
movq %rax, 0x130(%rsp)
cmpq $0x0, 0x130(%rsp)
jne 0x199b9
leaq 0x130cad(%rip), %rdi    # 0x14a64e
movb $0x0, %al
callq 0xebe00
movq $0x0, 0x170(%rsp)
jmp 0x1a0d5
movl $0x0, 0x12c(%rsp)
movl 0x12c(%rsp), %eax
movl %eax, 0x7c(%rsp)
movq 0x168(%rsp), %rdi
callq 0x1b460
movl %eax, %ecx
movl 0x7c(%rsp), %eax
cmpl %ecx, %eax
jge 0x19aa0
movq 0x168(%rsp), %rdi
movl 0x12c(%rsp), %esi
callq 0x1b5b0
movq %rax, 0x120(%rsp)
movq 0x130(%rsp), %rax
movslq 0x12c(%rsp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, 0x118(%rsp)
movq 0x168(%rsp), %rdi
movq 0x120(%rsp), %rsi
movq 0x118(%rsp), %rdx
callq 0x1e560
movq 0x120(%rsp), %rcx
movq 0x118(%rsp), %rax
movq %rcx, (%rax)
movq 0x118(%rsp), %rax
movsd 0x1305a3(%rip), %xmm0   # 0x14a008
movsd %xmm0, 0x8(%rax)
movq 0x118(%rsp), %rax
movq $0x0, 0x10(%rax)
movq 0x118(%rsp), %rax
movq $0x0, 0x18(%rax)
movl 0x12c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x12c(%rsp)
jmp 0x199c4
leaq 0x108(%rsp), %rdi
callq 0x1e540
movl $0x0, 0x104(%rsp)
movl 0x104(%rsp), %eax
movl %eax, 0x78(%rsp)
movq 0x160(%rsp), %rdi
callq 0x1b2f0
movl %eax, %ecx
movl 0x78(%rsp), %eax
cmpl %ecx, %eax
jge 0x19bc7
movq 0x160(%rsp), %rdi
movl 0x104(%rsp), %esi
callq 0x1e590
movq %rax, 0x70(%rsp)
jmp 0x19af9
movq 0x70(%rsp), %rax
movq %rax, 0xf8(%rsp)
movl $0x48, %edi
callq 0xf4d0
movq %rax, 0x68(%rsp)
jmp 0x19b17
movq 0x68(%rsp), %rdi
movq 0x168(%rsp), %rsi
movq 0xf8(%rsp), %rdx
callq 0x1b650
jmp 0x19b33
movq 0x68(%rsp), %rax
movq %rax, 0xf0(%rsp)
movq 0x148(%rsp), %rdi
movq 0xf0(%rsp), %rsi
callq 0x1b540
jmp 0x19b57
movq 0xf8(%rsp), %rsi
leaq 0x108(%rsp), %rdi
callq 0x1e5b0
jmp 0x19b6e
jmp 0x19b70
movl 0x104(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x104(%rsp)
jmp 0x19ab8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
jmp 0x1a0c6
movq 0x68(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
movl $0x48, %esi
callq 0xf4e0
jmp 0x1a0c6
leaq 0xe0(%rsp), %rdi
callq 0x1e540
jmp 0x19bd6
movq 0x160(%rsp), %rdi
callq 0x1bd90
cmpl $0x0, %eax
je 0x19e97
movq 0x168(%rsp), %rdi
callq 0x1b460
cltq
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
movq $-0x1, %rax
cmovoq %rax, %rdi
callq 0xf030
movq %rax, 0x60(%rsp)
jmp 0x19c1d
movq 0x60(%rsp), %rax
movq %rax, 0xd8(%rsp)
movl $0x0, 0xd4(%rsp)
movl 0xd4(%rsp), %eax
movl %eax, 0x5c(%rsp)
movq 0x168(%rsp), %rdi
callq 0x1b460
movl %eax, %ecx
movl 0x5c(%rsp), %eax
cmpl %ecx, %eax
jge 0x19c9a
movq 0xd8(%rsp), %rax
movslq 0xd4(%rsp), %rcx
movl $0x0, (%rax,%rcx,4)
movl 0xd4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xd4(%rsp)
jmp 0x19c35
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
jmp 0x1a0b9
movl $0x0, 0xd0(%rsp)
movl 0xd0(%rsp), %eax
movl %eax, 0x58(%rsp)
movq 0x168(%rsp), %rdi
callq 0x1b460
movl %eax, %ecx
movl 0x58(%rsp), %eax
cmpl %ecx, %eax
jge 0x19e95
movq 0x168(%rsp), %rdi
movl 0xd0(%rsp), %esi
callq 0x1b5b0
movq %rax, 0x50(%rsp)
jmp 0x19ce6
movq 0x50(%rsp), %rax
movq %rax, 0xc8(%rsp)
movq 0xd8(%rsp), %rax
movslq 0xd0(%rsp), %rcx
cmpl $0x0, (%rax,%rcx,4)
je 0x19d0e
jmp 0x19e7f
movq 0xd8(%rsp), %rax
movslq 0xd0(%rsp), %rcx
movl $0x1, (%rax,%rcx,4)
movq 0x168(%rsp), %rdi
movq 0xc8(%rsp), %rsi
callq 0x1e5e0
movl %eax, 0x4c(%rsp)
jmp 0x19d40
movl 0x4c(%rsp), %eax
cmpl $0x0, %eax
jne 0x19d4e
jmp 0x19e7f
movq 0xc8(%rsp), %rsi
leaq 0x108(%rsp), %rdi
callq 0x1e5b0
jmp 0x19d65
movq 0xc8(%rsp), %rsi
leaq 0xe0(%rsp), %rdi
callq 0x1e5b0
jmp 0x19d7c
leaq 0xb8(%rsp), %rdi
callq 0x1e540
jmp 0x19d8b
movq 0x168(%rsp), %rdi
movq 0xc8(%rsp), %rsi
leaq 0xb8(%rsp), %rdx
callq 0x45460
jmp 0x19daa
movl $0x0, 0xb4(%rsp)
movl 0xb4(%rsp), %eax
movl %eax, 0x48(%rsp)
leaq 0xb8(%rsp), %rdi
callq 0x1b2f0
movl %eax, %ecx
movl 0x48(%rsp), %eax
cmpl %ecx, %eax
jge 0x19e72
movl 0xb4(%rsp), %esi
leaq 0xb8(%rsp), %rdi
callq 0x1e590
movq %rax, 0x40(%rsp)
jmp 0x19df6
movq 0x40(%rsp), %rax
movq %rax, 0xa8(%rsp)
movq 0xd8(%rsp), %rax
movq %rax, 0x38(%rsp)
movq 0x168(%rsp), %rdi
movq 0xa8(%rsp), %rsi
callq 0x1b320
movl %eax, %ecx
movq 0x38(%rsp), %rax
movslq %ecx, %rcx
movl $0x1, (%rax,%rcx,4)
movl 0xb4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xb4(%rsp)
jmp 0x19db5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
leaq 0xb8(%rsp), %rdi
callq 0x1e550
jmp 0x1a0b9
leaq 0xb8(%rsp), %rdi
callq 0x1e550
movl 0xd0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xd0(%rsp)
jmp 0x19ca5
jmp 0x19e97
jmp 0x19e99
leaq 0x108(%rsp), %rdi
callq 0x1b2f0
movl %eax, 0x34(%rsp)
leaq 0xe0(%rsp), %rdi
callq 0x1b2f0
movl %eax, %ecx
movl 0x34(%rsp), %eax
subl %ecx, %eax
cmpl 0x15c(%rsp), %eax
jge 0x1a070
movq 0x168(%rsp), %rdi
movq 0x130(%rsp), %rdx
leaq 0x108(%rsp), %rsi
callq 0x1a100
movq %rax, 0x28(%rsp)
jmp 0x19ef0
movq 0x28(%rsp), %rax
movq %rax, 0xa0(%rsp)
cmpq $0x0, 0xa0(%rsp)
jne 0x19f0d
jmp 0x1a070
movq 0x130(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0x168(%rsp), %rdi
movq 0xa0(%rsp), %rsi
callq 0x1b320
movl %eax, %ecx
movq 0x20(%rsp), %rax
movslq %ecx, %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, 0x98(%rsp)
movsd 0x150(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x19f7b
movq 0x98(%rsp), %rax
movsd 0x8(%rax), %xmm1
movsd 0x150(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x19f7b
jmp 0x1a070
movq 0x98(%rsp), %rax
movq 0x10(%rax), %rsi
leaq 0xe0(%rsp), %rdi
callq 0x1e610
movq %rax, 0x18(%rsp)
jmp 0x19f9b
movq 0x18(%rsp), %rax
cmpq $0x0, %rax
je 0x19fde
movq 0x98(%rsp), %rax
movq 0x10(%rax), %rsi
leaq 0xe0(%rsp), %rdi
callq 0x1e640
jmp 0x19fc1
movq 0x98(%rsp), %rax
movq 0x10(%rax), %rsi
leaq 0x108(%rsp), %rdi
callq 0x1e640
jmp 0x19fdc
jmp 0x19fde
movl $0x48, %edi
callq 0xf4d0
movq %rax, 0x10(%rsp)
jmp 0x19fef
movq 0x10(%rsp), %rdi
movq 0x168(%rsp), %rsi
movq 0xa0(%rsp), %rdx
callq 0x1b650
jmp 0x1a00b
movq 0x10(%rsp), %rax
movq %rax, 0x90(%rsp)
movq 0x148(%rsp), %rdi
movq 0x90(%rsp), %rsi
callq 0x1b540
jmp 0x1a02f
movq 0xa0(%rsp), %rsi
leaq 0x108(%rsp), %rdi
callq 0x1e5b0
jmp 0x1a046
jmp 0x19e99
movq 0x10(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
movl $0x48, %esi
callq 0xf4e0
jmp 0x1a0b9
movq 0x130(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x1a08d
movq 0x8(%rsp), %rdi
callq 0xf680
movq 0x148(%rsp), %rax
movq %rax, 0x170(%rsp)
leaq 0xe0(%rsp), %rdi
callq 0x1e550
leaq 0x108(%rsp), %rdi
callq 0x1e550
jmp 0x1a0d5
leaq 0xe0(%rsp), %rdi
callq 0x1e550
leaq 0x108(%rsp), %rdi
callq 0x1e550
jmp 0x1a0e5
movq 0x170(%rsp), %rax
addq $0x178, %rsp            # imm = 0x178
retq
movq 0x140(%rsp), %rdi
callq 0xf8a0
nopw %cs:(%rax,%rax)