// File: tomfunkhouser[P]gaps/apps/msh2pts/msh2pts.cpp
// Function: SelectPoints(gaps::R3Mesh*, gaps::R3MeshProperty*, int)
static RNArray<Point *> *
SelectPoints(R3Mesh *mesh, R3MeshProperty *property, int selection_method)
{
  // Start statistics
  RNTime start_time;
  start_time.Read();

  // Update min spacing 
  if ((min_spacing < 0) && (min_normalized_spacing > 0)) {
    min_spacing = min_normalized_spacing * sqrt(mesh->Area());
  }

  // Update number of points
  if (num_points <= 0) {
    if (min_spacing > 0) num_points = mesh->NVertices();
    else num_points = 1024;
  }

  // Update min spacing
  if ((num_points > 0) && (min_spacing <= 0) && (min_relative_spacing > 0)) {
    min_spacing = min_relative_spacing * 2 * sqrt(mesh->Area() / (RN_PI * num_points));
  }

  // Select points using requested selection method 
  RNArray<Point *> *points = NULL;
  if (selection_method == RANDOM_VERTICES) 
    points = SelectVertexPoints(mesh, num_points, min_spacing);
  else if (selection_method == RANDOM_SURFACE_POINTS) 
    points= SelectRandomSurfacePoints(mesh, property, num_points);
  else if (selection_method == EXTERIOR_SURFACE_POINTS) 
    points= SelectExteriorSurfacePoints(mesh, num_points, min_spacing);
  else if (selection_method == NEAR_SURFACE_POINTS) 
    points= SelectNearSurfacePoints(mesh, property, num_points);
  else if (selection_method == VISIBLE_SURFACE_POINTS) 
    points= SelectVisibleSurfacePoints(mesh, num_points, min_spacing);
  else if (selection_method == ITERATIVE_FURTHEST_VERTEX) 
    points= SelectFurthestPoints(mesh, num_points, min_spacing);
  else if (selection_method == PROPERTY_MINIMA) 
    points= SelectPropertyExtrema(mesh, property, num_points, min_spacing, PROPERTY_MINIMA);
  else if (selection_method == PROPERTY_MAXIMA) 
    points= SelectPropertyExtrema(mesh, property, num_points, min_spacing, PROPERTY_MAXIMA);
  else if (selection_method == PROPERTY_EXTREMA)
    points= SelectPropertyExtrema(mesh, property, num_points, min_spacing, PROPERTY_EXTREMA);
  else if (selection_method == SCALE_SPACE_MINIMA) 
    points= SelectScaleSpaceExtrema(mesh, property, num_points, min_spacing, PROPERTY_MINIMA);
  else if (selection_method == SCALE_SPACE_MAXIMA) 
    points= SelectScaleSpaceExtrema(mesh, property, num_points, min_spacing, PROPERTY_MAXIMA);
  else if (selection_method == SCALE_SPACE_EXTREMA)
    points= SelectScaleSpaceExtrema(mesh, property, num_points, min_spacing, PROPERTY_EXTREMA);
  else if (selection_method == UNIFORM_IN_BBOX) 
    points= SelectPointsUniformInBBox(mesh, num_points);
  else if (selection_method == CENTER_OF_MASS) 
    points= SelectCenterOfMass(mesh);
  else if (selection_method == VERTEX_CLOSEST_TO_CENTER_OF_MASS) 
    points= SelectVertexClosestToCenterOfMass(mesh);

  // Check points
  if (!points) {
    RNFail("Error selecting points\n");
    return 0;
  }

  // Check if too few points
  if (min_points > 0) {
    while (points->NEntries() < min_points) {
      int face_index = (int) (RNRandomScalar() * mesh->NFaces());
      R3MeshFace *face = mesh->Face(face_index);
      R3Point position = mesh->RandomPointOnFace(face);
      const R3Vector& normal = mesh->FaceNormal(face);
      Point *point = new Point(position, normal);
      points->Insert(point);
    }
  }

  // Check if too many points
  if (max_points > 0) {
    while (points->NEntries() > max_points) {
      int k = RNRandomScalar() * points->NEntries();
      points->Swap(k, points->NEntries()-1);
      Point *point = points->Tail();
      points->RemoveTail();
      delete point;
    }
  }

  // Print message
  if (print_verbose) {
    fprintf(stdout, "Generated points ...\n");
    printf("  Time = %.2f seconds\n", start_time.Elapsed());
    printf("  # Points = %d\n", points->NEntries());
    printf("  Selection method = %d\n", selection_method);
    if (min_points > 0) printf("  Minimum # points = %d\n", min_points);
    if (max_points > 0) printf("  Maximum # points = %d\n", max_points);
    printf("  Requested # points = %d\n", num_points);
    printf("  Requested min spacing = %g\n", min_spacing);
    fflush(stdout);
  }

  // Return array of points
  return points;
}

// Assembly:
subq $0xd8, %rsp
movq %rdi, 0xc8(%rsp)
movq %rsi, 0xc0(%rsp)
movl %edx, 0xbc(%rsp)
leaq 0xa8(%rsp), %rdi
callq 0xe7be0
leaq 0xa8(%rsp), %rdi
callq 0x1b2d0
xorps %xmm0, %xmm0
ucomisd 0x17435d(%rip), %xmm0   # 0x188510
jbe 0x141fb
movsd 0x17435b(%rip), %xmm0   # 0x188518
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x141fb
movsd 0x17434a(%rip), %xmm0   # 0x188518
movsd %xmm0, 0x48(%rsp)
movq 0xc8(%rsp), %rdi
callq 0x41930
callq 0xf390
movaps %xmm0, %xmm1
movsd 0x48(%rsp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, 0x174315(%rip)   # 0x188510
cmpl $0x0, 0x174302(%rip)    # 0x188504
jg 0x14236
movsd 0x174304(%rip), %xmm0   # 0x188510
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x1422a
movq 0xc8(%rsp), %rdi
callq 0x1b460
movl %eax, 0x1742dc(%rip)    # 0x188504
jmp 0x14234
movl $0x400, 0x1742d0(%rip)  # imm = 0x400
jmp 0x14236
cmpl $0x0, 0x1742c7(%rip)    # 0x188504
jle 0x142b5
xorps %xmm0, %xmm0
ucomisd 0x1742c6(%rip), %xmm0   # 0x188510
jb 0x142b5
movsd 0x1742cc(%rip), %xmm0   # 0x188520
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x142b5
movsd 0x135db3(%rip), %xmm0   # 0x14a018
mulsd 0x1742b3(%rip), %xmm0   # 0x188520
movsd %xmm0, 0x40(%rsp)
movq 0xc8(%rsp), %rdi
callq 0x41930
leaq 0x139ca1(%rip), %rax    # 0x14df28
movsd (%rax), %xmm1
cvtsi2sdl 0x174271(%rip), %xmm2 # 0x188504
mulsd %xmm2, %xmm1
divsd %xmm1, %xmm0
callq 0xf390
movaps %xmm0, %xmm1
movsd 0x40(%rsp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, 0x17425b(%rip)   # 0x188510
movq $0x0, 0xa0(%rsp)
cmpl $0x0, 0xbc(%rsp)
jne 0x142f3
movq 0xc8(%rsp), %rdi
movl 0x17422b(%rip), %esi    # 0x188504
movsd 0x17422f(%rip), %xmm0   # 0x188510
callq 0x14910
movq %rax, 0xa0(%rsp)
jmp 0x145e7
cmpl $0x1, 0xbc(%rsp)
jne 0x14325
movq 0xc8(%rsp), %rdi
movq 0xc0(%rsp), %rsi
movl 0x1741f1(%rip), %edx    # 0x188504
callq 0x14e20
movq %rax, 0xa0(%rsp)
jmp 0x145e5
cmpl $0x3, 0xbc(%rsp)
jne 0x14357
movq 0xc8(%rsp), %rdi
movl 0x1741c7(%rip), %esi    # 0x188504
movsd 0x1741cb(%rip), %xmm0   # 0x188510
callq 0x153e0
movq %rax, 0xa0(%rsp)
jmp 0x145e3
cmpl $0x4, 0xbc(%rsp)
jne 0x14389
movq 0xc8(%rsp), %rdi
movq 0xc0(%rsp), %rsi
movl 0x17418d(%rip), %edx    # 0x188504
callq 0x16120
movq %rax, 0xa0(%rsp)
jmp 0x145e1
cmpl $0x5, 0xbc(%rsp)
jne 0x143bb
movq 0xc8(%rsp), %rdi
movl 0x174163(%rip), %esi    # 0x188504
movsd 0x174167(%rip), %xmm0   # 0x188510
callq 0x16c40
movq %rax, 0xa0(%rsp)
jmp 0x145df
cmpl $0x2, 0xbc(%rsp)
jne 0x143ed
movq 0xc8(%rsp), %rdi
movl 0x174131(%rip), %esi    # 0x188504
movsd 0x174135(%rip), %xmm0   # 0x188510
callq 0x17850
movq %rax, 0xa0(%rsp)
jmp 0x145dd
cmpl $0xb, 0xbc(%rsp)
jne 0x1442c
movq 0xc8(%rsp), %rdi
movq 0xc0(%rsp), %rsi
movl 0x1740f7(%rip), %edx    # 0x188504
movsd 0x1740fb(%rip), %xmm0   # 0x188510
movl $0xb, %ecx
callq 0x178d0
movq %rax, 0xa0(%rsp)
jmp 0x145db
cmpl $0xa, 0xbc(%rsp)
jne 0x1446b
movq 0xc8(%rsp), %rdi
movq 0xc0(%rsp), %rsi
movl 0x1740b8(%rip), %edx    # 0x188504
movsd 0x1740bc(%rip), %xmm0   # 0x188510
movl $0xa, %ecx
callq 0x178d0
movq %rax, 0xa0(%rsp)
jmp 0x145d9
cmpl $0xc, 0xbc(%rsp)
jne 0x144aa
movq 0xc8(%rsp), %rdi
movq 0xc0(%rsp), %rsi
movl 0x174079(%rip), %edx    # 0x188504
movsd 0x17407d(%rip), %xmm0   # 0x188510
movl $0xc, %ecx
callq 0x178d0
movq %rax, 0xa0(%rsp)
jmp 0x145d7
cmpl $0x8, 0xbc(%rsp)
jne 0x144e9
movq 0xc8(%rsp), %rdi
movq 0xc0(%rsp), %rsi
movl 0x17403a(%rip), %edx    # 0x188504
movsd 0x17403e(%rip), %xmm0   # 0x188510
movl $0xb, %ecx
callq 0x18270
movq %rax, 0xa0(%rsp)
jmp 0x145d5
cmpl $0x7, 0xbc(%rsp)
jne 0x14528
movq 0xc8(%rsp), %rdi
movq 0xc0(%rsp), %rsi
movl 0x173ffb(%rip), %edx    # 0x188504
movsd 0x173fff(%rip), %xmm0   # 0x188510
movl $0xa, %ecx
callq 0x18270
movq %rax, 0xa0(%rsp)
jmp 0x145d3
cmpl $0x9, 0xbc(%rsp)
jne 0x14564
movq 0xc8(%rsp), %rdi
movq 0xc0(%rsp), %rsi
movl 0x173fbc(%rip), %edx    # 0x188504
movsd 0x173fc0(%rip), %xmm0   # 0x188510
movl $0xc, %ecx
callq 0x18270
movq %rax, 0xa0(%rsp)
jmp 0x145d1
cmpl $0x6, 0xbc(%rsp)
jne 0x1458b
movq 0xc8(%rsp), %rdi
movl 0x173f88(%rip), %esi    # 0x188504
callq 0x18bd0
movq %rax, 0xa0(%rsp)
jmp 0x145cf
cmpl $0xd, 0xbc(%rsp)
jne 0x145ac
movq 0xc8(%rsp), %rdi
callq 0x19120
movq %rax, 0xa0(%rsp)
jmp 0x145cd
cmpl $0xe, 0xbc(%rsp)
jne 0x145cb
movq 0xc8(%rsp), %rdi
callq 0x19230
movq %rax, 0xa0(%rsp)
jmp 0x145cd
jmp 0x145cf
jmp 0x145d1
jmp 0x145d3
jmp 0x145d5
jmp 0x145d7
jmp 0x145d9
jmp 0x145db
jmp 0x145dd
jmp 0x145df
jmp 0x145e1
jmp 0x145e3
jmp 0x145e5
jmp 0x145e7
cmpq $0x0, 0xa0(%rsp)
jne 0x14611
leaq 0x135f53(%rip), %rdi    # 0x14a54c
movb $0x0, %al
callq 0xebe00
movq $0x0, 0xd0(%rsp)
jmp 0x148ef
cmpl $0x0, 0x173ef4(%rip)    # 0x18850c
jle 0x1472a
jmp 0x14620
movq 0xa0(%rsp), %rdi
callq 0x1b2f0
cmpl 0x173ed9(%rip), %eax    # 0x18850c
jge 0x14728
callq 0xeb5e0
movsd %xmm0, 0x28(%rsp)
movq 0xc8(%rsp), %rdi
callq 0x1b420
movsd 0x28(%rsp), %xmm0
cvtsi2sd %eax, %xmm1
mulsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x9c(%rsp)
movq 0xc8(%rsp), %rdi
movl 0x9c(%rsp), %esi
callq 0x1b480
movq %rax, 0x90(%rsp)
movq 0xc8(%rsp), %rsi
movq 0x90(%rsp), %rdx
leaq 0x78(%rsp), %rdi
movq %rdi, 0x30(%rsp)
callq 0x51c70
movq 0xc8(%rsp), %rdi
movq 0x90(%rsp), %rsi
callq 0x1b4b0
movq %rax, 0x70(%rsp)
movl $0x48, %edi
callq 0xf4d0
movq 0x30(%rsp), %rsi
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x38(%rsp)
movq 0x70(%rsp), %rdx
callq 0x1b4e0
jmp 0x146e5
movq 0x38(%rsp), %rax
movq %rax, 0x68(%rsp)
movq 0xa0(%rsp), %rdi
movq 0x68(%rsp), %rsi
callq 0x1b540
jmp 0x14620
movq 0x38(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x60(%rsp)
movl %eax, 0x5c(%rsp)
movl $0x48, %esi
callq 0xf4e0
jmp 0x148ff
jmp 0x1472a
cmpl $0x0, 0x173dd7(%rip)    # 0x188508
jle 0x147fa
jmp 0x14739
movq 0xa0(%rsp), %rdi
callq 0x1b2f0
cmpl 0x173dbc(%rip), %eax    # 0x188508
jle 0x147f8
callq 0xeb5e0
movsd %xmm0, 0x8(%rsp)
movq 0xa0(%rsp), %rdi
callq 0x1b2f0
movsd 0x8(%rsp), %xmm0
cvtsi2sd %eax, %xmm1
mulsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x58(%rsp)
movq 0xa0(%rsp), %rax
movq %rax, 0x10(%rsp)
movl 0x58(%rsp), %eax
movl %eax, 0x1c(%rsp)
movq 0xa0(%rsp), %rdi
callq 0x1b2f0
movq 0x10(%rsp), %rdi
movl 0x1c(%rsp), %esi
movl %eax, %edx
subl $0x1, %edx
callq 0xe8d90
movq 0xa0(%rsp), %rdi
callq 0x1b570
movq %rax, 0x50(%rsp)
movq 0xa0(%rsp), %rdi
callq 0x1b580
movq 0x50(%rsp), %rax
movq %rax, 0x20(%rsp)
cmpq $0x0, %rax
je 0x147f3
movq 0x20(%rsp), %rdi
movl $0x48, %esi
callq 0xf4e0
jmp 0x14739
jmp 0x147fa
cmpl $0x0, 0x17cdcf(%rip)    # 0x1915d0
je 0x148df
movq 0x173782(%rip), %rax    # 0x187f90
movq (%rax), %rdi
leaq 0x135d4c(%rip), %rsi    # 0x14a564
movb $0x0, %al
callq 0xf740
leaq 0xa8(%rsp), %rdi
callq 0xe7ca0
leaq 0x135942(%rip), %rdi    # 0x14a175
movb $0x1, %al
callq 0xf070
movq 0xa0(%rsp), %rdi
callq 0x1b2f0
movl %eax, %esi
leaq 0x135d2a(%rip), %rdi    # 0x14a57a
movb $0x0, %al
callq 0xf070
movl 0xbc(%rsp), %esi
leaq 0x135d26(%rip), %rdi    # 0x14a58b
movb $0x0, %al
callq 0xf070
cmpl $0x0, 0x173c99(%rip)    # 0x18850c
jle 0x14889
movl 0x173c91(%rip), %esi    # 0x18850c
leaq 0x135d22(%rip), %rdi    # 0x14a5a4
movb $0x0, %al
callq 0xf070
cmpl $0x0, 0x173c78(%rip)    # 0x188508
jle 0x148a6
movl 0x173c70(%rip), %esi    # 0x188508
leaq 0x135d1e(%rip), %rdi    # 0x14a5bd
movb $0x0, %al
callq 0xf070
movl 0x173c58(%rip), %esi    # 0x188504
leaq 0x135d23(%rip), %rdi    # 0x14a5d6
movb $0x0, %al
callq 0xf070
movsd 0x173c4e(%rip), %xmm0   # 0x188510
leaq 0x135d28(%rip), %rdi    # 0x14a5f1
movb $0x1, %al
callq 0xf070
movq 0x1736b9(%rip), %rax    # 0x187f90
movq (%rax), %rdi
callq 0xf5e0
movq 0xa0(%rsp), %rax
movq %rax, 0xd0(%rsp)
movq 0xd0(%rsp), %rax
addq $0xd8, %rsp
retq
movq 0x60(%rsp), %rdi
callq 0xf8a0
nopl (%rax)