// File: tomfunkhouser[P]gaps/apps/sfl2pts/sfl2pts.cpp
// Function: WritePoints(gaps::RNArray<PlyPoint*> const&, char const*)
static int
WritePoints(const RNArray<PlyPoint *>& points, const char *filename)
{
  // Start statistics
  RNTime start_time;
  start_time.Read();

  // Parse input filename extension
  const char *extension;
  if (!(extension = strrchr(filename, '.'))) {
    printf("Filename %s has no extension (e.g., .ply)\n", filename);
    return 0;
  }

  // Check file type
  if (!strcmp(extension, ".ply")) {
    // Define ply element names
    char *elem_names[] = { (char *) "vertex" };

    // Define property information for a point 
    static PlyProperty vert_props[] = { 
      {(char *) "x", PLY_FLOAT, PLY_FLOAT, offsetof(PlyPoint,x), 0, 0, 0, 0},
      {(char *) "y", PLY_FLOAT, PLY_FLOAT, offsetof(PlyPoint,y), 0, 0, 0, 0},
      {(char *) "z", PLY_FLOAT, PLY_FLOAT, offsetof(PlyPoint,z), 0, 0, 0, 0},
      {(char *) "nx", PLY_FLOAT, PLY_FLOAT, offsetof(PlyPoint,nx), 0, 0, 0, 0},
      {(char *) "ny", PLY_FLOAT, PLY_FLOAT, offsetof(PlyPoint,ny), 0, 0, 0, 0},
      {(char *) "nz", PLY_FLOAT, PLY_FLOAT, offsetof(PlyPoint,nz), 0, 0, 0, 0},
      {(char *) "red", PLY_UCHAR, PLY_UCHAR, offsetof(PlyPoint,red), 0, 0, 0, 0},
      {(char *) "green", PLY_UCHAR, PLY_UCHAR, offsetof(PlyPoint,green), 0, 0, 0, 0},
      {(char *) "blue", PLY_UCHAR, PLY_UCHAR, offsetof(PlyPoint,blue), 0, 0, 0, 0},
      {(char *) "confidence", PLY_FLOAT, PLY_FLOAT, offsetof(PlyPoint,confidence), 0, 0, 0, 0},
      {(char *) "value", PLY_FLOAT, PLY_FLOAT, offsetof(PlyPoint,radius), 0, 0, 0, 0}
    };

    // Open ply file
    float version;
    PlyFile *ply = ply_open_for_writing((char *) filename, 1, elem_names, PLY_BINARY_NATIVE, &version);
    if (!ply) return -1;

    // Describe point properties
    ply_element_count(ply, (char *) "vertex", points.NEntries());
    ply_describe_property(ply, (char *) "vertex", &vert_props[0]);
    ply_describe_property(ply, (char *) "vertex", &vert_props[1]);
    ply_describe_property(ply, (char *) "vertex", &vert_props[2]);
    ply_describe_property(ply, (char *) "vertex", &vert_props[3]);
    ply_describe_property(ply, (char *) "vertex", &vert_props[4]);
    ply_describe_property(ply, (char *) "vertex", &vert_props[5]);
    ply_describe_property(ply, (char *) "vertex", &vert_props[6]);
    ply_describe_property(ply, (char *) "vertex", &vert_props[7]);
    ply_describe_property(ply, (char *) "vertex", &vert_props[8]);
    ply_describe_property(ply, (char *) "vertex", &vert_props[9]);
    ply_describe_property(ply, (char *) "vertex", &vert_props[10]);

    // Complete header
    ply_header_complete(ply);

    // Write points
    ply_put_element_setup(ply, (char *) "vertex");
    for (int i = 0; i < points.NEntries(); i++) {
      ply_put_element(ply, (void *) points[i]);
    }

    // Close the file 
    ply_close(ply);
  }
  else if (!strcmp(extension, ".xyzn")) {
    // Open file
    FILE *fp = stdout;
    if (filename) {
      fp = fopen(filename, "w");
      if (!fp) {
        RNFail("Unable to open output file %s\n", filename);
        return FALSE;
      }
    }

    // Write points
    for (int i = 0; i < points.NEntries(); i++) {
      PlyPoint *point = points[i];
      fprintf(fp, "%g %g %g   %g %g %g\n",
        point->x, point->y, point->z,
        point->nx, point->ny, point->nz);
    }

    // Close file
    if (filename) fclose(fp);
  }
  else if (!strcmp(extension, ".xyz")) {
    // Open file
    FILE *fp = stdout;
    if (filename) {
      fp = fopen(filename, "w");
      if (!fp) {
        RNFail("Unable to open output file %s\n", filename);
        return FALSE;
      }
    }

    // Write points
    for (int i = 0; i < points.NEntries(); i++) {
      PlyPoint *point = points[i];
      fprintf(fp, "%g %g %g\n", point->x, point->y, point->z);
    }

    // Close file
    if (filename) fclose(fp);
  }
  else if (!strcmp(extension, ".pts")) {
    // Open file
    FILE *fp = stdout;
    if (filename) {
      fp = fopen(filename, "wb");
      if (!fp) {
        RNFail("Unable to open output file %s\n", filename);
        return FALSE;
      }
    }

    // Write points
    float coordinates[6];
    for (int i = 0; i < points.NEntries(); i++) {
      PlyPoint *point = points[i];
      coordinates[0] = point->x;
      coordinates[1] = point->y;
      coordinates[2] = point->z;
      coordinates[3] = point->nx;
      coordinates[4] = point->ny;
      coordinates[5] = point->nz;
      if (fwrite(coordinates, sizeof(float), 6, fp) != (unsigned int) 6) {
        RNFail("Unable to write point to output file %s\n", filename);
        return FALSE;
      }
    }

    // Close file
    if (filename) fclose(fp);
  }
  else {
    // Create mesh
    R3Mesh mesh;
    for (int i = 0; i < points.NEntries(); i++) {
      PlyPoint *point = points[i];
      R3Point position(point->x, point->y, point->z);
      R3Vector normal(point->nx, point->ny, point->nz);
      mesh.CreateVertex(position, normal);
    }

    // Write mesh file
    if (!mesh.WriteFile(filename)) return FALSE;
  }

  // Print statistics
  if (print_verbose) {
    printf("Wrote points to %s ...\n", filename);
    printf("  Time = %.2f seconds\n", start_time.Elapsed());
    printf("  # Points = %u\n", points.NEntries());
    fflush(stdout);
  }

  // Return success
  return 1;
}

// Assembly:
subq $0x288, %rsp            # imm = 0x288
movq %rdi, 0x278(%rsp)
movq %rsi, 0x270(%rsp)
leaq 0x260(%rsp), %rdi
callq 0x143310
leaq 0x260(%rsp), %rdi
callq 0x18850
movq 0x270(%rsp), %rdi
movl $0x2e, %esi
callq 0x13630
movq %rax, 0x258(%rsp)
cmpq $0x0, %rax
jne 0x17c37
movq 0x270(%rsp), %rsi
leaq 0x18e6b6(%rip), %rdi    # 0x1a62d6
movb $0x0, %al
callq 0x13070
movl $0x0, 0x284(%rsp)
jmp 0x1857b
movq 0x258(%rsp), %rdi
leaq 0x18e6bb(%rip), %rsi    # 0x1a6301
callq 0x137e0
cmpl $0x0, %eax
jne 0x17ee1
movq 0x1d8fc5(%rip), %rax    # 0x1f0c20
movq %rax, 0x250(%rsp)
movq 0x270(%rsp), %rdi
leaq 0x250(%rsp), %rdx
movl $0x1, %esi
movl $0x4, %ecx
leaq 0x24c(%rsp), %r8
callq 0xfccd0
movq %rax, 0x240(%rsp)
cmpq $0x0, 0x240(%rsp)
jne 0x17cad
movl $0xffffffff, 0x284(%rsp) # imm = 0xFFFFFFFF
jmp 0x1857b
movq 0x240(%rsp), %rax
movq %rax, 0x38(%rsp)
movq 0x278(%rsp), %rdi
callq 0x18810
movq 0x38(%rsp), %rdi
movl %eax, %edx
leaq 0x19050d(%rip), %rsi    # 0x1a81e2
callq 0xfd3f0
movq 0x240(%rsp), %rdi
leaq 0x1904f9(%rip), %rsi    # 0x1a81e2
leaq 0x1de8b0(%rip), %rdx    # 0x1f65a0
callq 0xfd080
movq 0x240(%rsp), %rdi
leaq 0x1904de(%rip), %rsi    # 0x1a81e2
leaq 0x1de895(%rip), %rdx    # 0x1f65a0
addq $0x28, %rdx
callq 0xfd080
movq 0x240(%rsp), %rdi
leaq 0x1904bf(%rip), %rsi    # 0x1a81e2
leaq 0x1de876(%rip), %rdx    # 0x1f65a0
addq $0x50, %rdx
callq 0xfd080
movq 0x240(%rsp), %rdi
leaq 0x1904a0(%rip), %rsi    # 0x1a81e2
leaq 0x1de857(%rip), %rdx    # 0x1f65a0
addq $0x78, %rdx
callq 0xfd080
movq 0x240(%rsp), %rdi
leaq 0x190481(%rip), %rsi    # 0x1a81e2
leaq 0x1de838(%rip), %rdx    # 0x1f65a0
addq $0xa0, %rdx
callq 0xfd080
movq 0x240(%rsp), %rdi
leaq 0x19045f(%rip), %rsi    # 0x1a81e2
leaq 0x1de816(%rip), %rdx    # 0x1f65a0
addq $0xc8, %rdx
callq 0xfd080
movq 0x240(%rsp), %rdi
leaq 0x19043d(%rip), %rsi    # 0x1a81e2
leaq 0x1de7f4(%rip), %rdx    # 0x1f65a0
addq $0xf0, %rdx
callq 0xfd080
movq 0x240(%rsp), %rdi
leaq 0x19041b(%rip), %rsi    # 0x1a81e2
leaq 0x1de7d2(%rip), %rdx    # 0x1f65a0
addq $0x118, %rdx            # imm = 0x118
callq 0xfd080
movq 0x240(%rsp), %rdi
leaq 0x1903f9(%rip), %rsi    # 0x1a81e2
leaq 0x1de7b0(%rip), %rdx    # 0x1f65a0
addq $0x140, %rdx            # imm = 0x140
callq 0xfd080
movq 0x240(%rsp), %rdi
leaq 0x1903d7(%rip), %rsi    # 0x1a81e2
leaq 0x1de78e(%rip), %rdx    # 0x1f65a0
addq $0x168, %rdx            # imm = 0x168
callq 0xfd080
movq 0x240(%rsp), %rdi
leaq 0x1903b5(%rip), %rsi    # 0x1a81e2
leaq 0x1de76c(%rip), %rdx    # 0x1f65a0
addq $0x190, %rdx            # imm = 0x190
callq 0xfd080
movq 0x240(%rsp), %rdi
callq 0xfd460
movq 0x240(%rsp), %rdi
leaq 0x190386(%rip), %rsi    # 0x1a81e2
callq 0xfd790
movl $0x0, 0x23c(%rsp)
movl 0x23c(%rsp), %eax
movl %eax, 0x34(%rsp)
movq 0x278(%rsp), %rdi
callq 0x18810
movl %eax, %ecx
movl 0x34(%rsp), %eax
cmpl %ecx, %eax
jge 0x17ecf
movq 0x240(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x278(%rsp), %rdi
movl 0x23c(%rsp), %esi
callq 0x19330
movq 0x28(%rsp), %rdi
movq %rax, %rsi
callq 0xfd800
movl 0x23c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x23c(%rsp)
jmp 0x17e6c
movq 0x240(%rsp), %rdi
callq 0x100480
jmp 0x1850a
movq 0x258(%rsp), %rdi
leaq 0x18e42e(%rip), %rsi    # 0x1a631e
callq 0x137e0
cmpl $0x0, %eax
jne 0x18065
movq 0x1de08b(%rip), %rax    # 0x1f5f90
movq (%rax), %rax
movq %rax, 0x230(%rsp)
cmpq $0x0, 0x270(%rsp)
je 0x17f6a
movq 0x270(%rsp), %rdi
leaq 0x1911d4(%rip), %rsi    # 0x1a90fe
callq 0x13690
movq %rax, 0x230(%rsp)
cmpq $0x0, 0x230(%rsp)
jne 0x17f68
movq 0x270(%rsp), %rsi
leaq 0x18e3d3(%rip), %rdi    # 0x1a6324
movb $0x0, %al
callq 0x148290
movl $0x0, 0x284(%rsp)
jmp 0x1857b
jmp 0x17f6a
movl $0x0, 0x22c(%rsp)
movl 0x22c(%rsp), %eax
movl %eax, 0x24(%rsp)
movq 0x278(%rsp), %rdi
callq 0x18810
movl %eax, %ecx
movl 0x24(%rsp), %eax
cmpl %ecx, %eax
jge 0x18048
movq 0x278(%rsp), %rdi
movl 0x22c(%rsp), %esi
callq 0x19330
movq %rax, 0x220(%rsp)
movq 0x230(%rsp), %rdi
movq 0x220(%rsp), %rax
movss (%rax), %xmm0
cvtss2sd %xmm0, %xmm0
movq 0x220(%rsp), %rax
movss 0x4(%rax), %xmm1
cvtss2sd %xmm1, %xmm1
movq 0x220(%rsp), %rax
movss 0x8(%rax), %xmm2
cvtss2sd %xmm2, %xmm2
movq 0x220(%rsp), %rax
movss 0xc(%rax), %xmm3
cvtss2sd %xmm3, %xmm3
movq 0x220(%rsp), %rax
movss 0x10(%rax), %xmm4
cvtss2sd %xmm4, %xmm4
movq 0x220(%rsp), %rax
movss 0x14(%rax), %xmm5
cvtss2sd %xmm5, %xmm5
leaq 0x18e318(%rip), %rsi    # 0x1a6343
movb $0x6, %al
callq 0x13810
movl 0x22c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x22c(%rsp)
jmp 0x17f75
cmpq $0x0, 0x270(%rsp)
je 0x18060
movq 0x230(%rsp), %rdi
callq 0x13560
jmp 0x18508
movq 0x258(%rsp), %rdi
leaq 0x18e2e4(%rip), %rsi    # 0x1a6358
callq 0x137e0
cmpl $0x0, %eax
jne 0x181b2
movq 0x1ddf07(%rip), %rax    # 0x1f5f90
movq (%rax), %rax
movq %rax, 0x218(%rsp)
cmpq $0x0, 0x270(%rsp)
je 0x180ee
movq 0x270(%rsp), %rdi
leaq 0x191050(%rip), %rsi    # 0x1a90fe
callq 0x13690
movq %rax, 0x218(%rsp)
cmpq $0x0, 0x218(%rsp)
jne 0x180ec
movq 0x270(%rsp), %rsi
leaq 0x18e24f(%rip), %rdi    # 0x1a6324
movb $0x0, %al
callq 0x148290
movl $0x0, 0x284(%rsp)
jmp 0x1857b
jmp 0x180ee
movl $0x0, 0x214(%rsp)
movl 0x214(%rsp), %eax
movl %eax, 0x20(%rsp)
movq 0x278(%rsp), %rdi
callq 0x18810
movl %eax, %ecx
movl 0x20(%rsp), %eax
cmpl %ecx, %eax
jge 0x18195
movq 0x278(%rsp), %rdi
movl 0x214(%rsp), %esi
callq 0x19330
movq %rax, 0x208(%rsp)
movq 0x218(%rsp), %rdi
movq 0x208(%rsp), %rax
movss (%rax), %xmm0
cvtss2sd %xmm0, %xmm0
movq 0x208(%rsp), %rax
movss 0x4(%rax), %xmm1
cvtss2sd %xmm1, %xmm1
movq 0x208(%rsp), %rax
movss 0x8(%rax), %xmm2
cvtss2sd %xmm2, %xmm2
leaq 0x18e1d6(%rip), %rsi    # 0x1a634e
movb $0x3, %al
callq 0x13810
movl 0x214(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x214(%rsp)
jmp 0x180f9
cmpq $0x0, 0x270(%rsp)
je 0x181ad
movq 0x218(%rsp), %rdi
callq 0x13560
jmp 0x18506
movq 0x258(%rsp), %rdi
leaq 0x18e19c(%rip), %rsi    # 0x1a635d
callq 0x137e0
cmpl $0x0, %eax
jne 0x1838b
movq 0x1dddba(%rip), %rax    # 0x1f5f90
movq (%rax), %rax
movq %rax, 0x200(%rsp)
cmpq $0x0, 0x270(%rsp)
je 0x1823b
movq 0x270(%rsp), %rdi
leaq 0x18e167(%rip), %rsi    # 0x1a6362
callq 0x13690
movq %rax, 0x200(%rsp)
cmpq $0x0, 0x200(%rsp)
jne 0x18239
movq 0x270(%rsp), %rsi
leaq 0x18e102(%rip), %rdi    # 0x1a6324
movb $0x0, %al
callq 0x148290
movl $0x0, 0x284(%rsp)
jmp 0x1857b
jmp 0x1823b
movl $0x0, 0x1dc(%rsp)
movl 0x1dc(%rsp), %eax
movl %eax, 0x1c(%rsp)
movq 0x278(%rsp), %rdi
callq 0x18810
movl %eax, %ecx
movl 0x1c(%rsp), %eax
cmpl %ecx, %eax
jge 0x1836e
movq 0x278(%rsp), %rdi
movl 0x1dc(%rsp), %esi
callq 0x19330
movq %rax, 0x1d0(%rsp)
movq 0x1d0(%rsp), %rax
movss (%rax), %xmm0
movss %xmm0, 0x1e0(%rsp)
movq 0x1d0(%rsp), %rax
movss 0x4(%rax), %xmm0
movss %xmm0, 0x1e4(%rsp)
movq 0x1d0(%rsp), %rax
movss 0x8(%rax), %xmm0
movss %xmm0, 0x1e8(%rsp)
movq 0x1d0(%rsp), %rax
movss 0xc(%rax), %xmm0
movss %xmm0, 0x1ec(%rsp)
movq 0x1d0(%rsp), %rax
movss 0x10(%rax), %xmm0
movss %xmm0, 0x1f0(%rsp)
movq 0x1d0(%rsp), %rax
movss 0x14(%rax), %xmm0
movss %xmm0, 0x1f4(%rsp)
leaq 0x1e0(%rsp), %rdi
movq 0x200(%rsp), %rcx
movl $0x4, %esi
movl $0x6, %edx
callq 0x13a80
cmpq $0x6, %rax
je 0x18356
movq 0x270(%rsp), %rsi
leaq 0x18e026(%rip), %rdi    # 0x1a6365
movb $0x0, %al
callq 0x148290
movl $0x0, 0x284(%rsp)
jmp 0x1857b
jmp 0x18358
movl 0x1dc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1dc(%rsp)
jmp 0x18246
cmpq $0x0, 0x270(%rsp)
je 0x18386
movq 0x200(%rsp), %rdi
callq 0x13560
jmp 0x18504
leaq 0x98(%rsp), %rdi
callq 0x9a1f0
movl $0x0, 0x94(%rsp)
movl 0x94(%rsp), %eax
movl %eax, 0x14(%rsp)
movq 0x278(%rsp), %rdi
callq 0x18810
movl %eax, 0x18(%rsp)
jmp 0x183c1
movl 0x14(%rsp), %eax
movl 0x18(%rsp), %ecx
cmpl %ecx, %eax
jge 0x184a8
movq 0x278(%rsp), %rdi
movl 0x94(%rsp), %esi
callq 0x19330
movq %rax, 0x8(%rsp)
jmp 0x183ec
movq 0x8(%rsp), %rax
movq %rax, 0x78(%rsp)
movq 0x78(%rsp), %rax
movss (%rax), %xmm0
movss 0x4(%rax), %xmm1
cvtss2sd %xmm0, %xmm0
cvtss2sd %xmm1, %xmm1
movss 0x8(%rax), %xmm2
cvtss2sd %xmm2, %xmm2
leaq 0x60(%rsp), %rdi
callq 0xfa130
jmp 0x18421
movq 0x78(%rsp), %rax
movss 0xc(%rax), %xmm0
movss 0x10(%rax), %xmm1
cvtss2sd %xmm0, %xmm0
cvtss2sd %xmm1, %xmm1
movss 0x14(%rax), %xmm2
cvtss2sd %xmm2, %xmm2
leaq 0x48(%rsp), %rdi
callq 0xfb290
jmp 0x1844d
xorl %eax, %eax
movl %eax, %ecx
leaq 0x98(%rsp), %rdi
leaq 0x60(%rsp), %rsi
leaq 0x48(%rsp), %rdx
callq 0xa08d0
jmp 0x1846a
jmp 0x1846c
movl 0x94(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x94(%rsp)
jmp 0x183a3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x88(%rsp)
movl %eax, 0x84(%rsp)
leaq 0x98(%rsp), %rdi
callq 0x9b0f0
jmp 0x1858a
movq 0x270(%rsp), %rsi
leaq 0x98(%rsp), %rdi
callq 0xb9ed0
movl %eax, 0x4(%rsp)
jmp 0x184c3
movl 0x4(%rsp), %eax
cmpl $0x0, %eax
jne 0x184e1
movl $0x0, 0x284(%rsp)
movl $0x1, 0x44(%rsp)
jmp 0x184e9
movl $0x0, 0x44(%rsp)
leaq 0x98(%rsp), %rdi
callq 0x9b0f0
movl 0x44(%rsp), %eax
testl %eax, %eax
je 0x18502
jmp 0x18500
jmp 0x1857b
jmp 0x18504
jmp 0x18506
jmp 0x18508
jmp 0x1850a
cmpl $0x0, 0x1e72b7(%rip)    # 0x1ff7c8
je 0x18570
movq 0x270(%rsp), %rsi
leaq 0x18de6c(%rip), %rdi    # 0x1a638e
movb $0x0, %al
callq 0x13070
leaq 0x260(%rsp), %rdi
callq 0x1433d0
leaq 0x18dc8a(%rip), %rdi    # 0x1a61c7
movb $0x1, %al
callq 0x13070
movq 0x278(%rsp), %rdi
callq 0x18810
movl %eax, %esi
leaq 0x18dd29(%rip), %rdi    # 0x1a6283
movb $0x0, %al
callq 0x13070
movq 0x1dda28(%rip), %rax    # 0x1f5f90
movq (%rax), %rdi
callq 0x13680
movl $0x1, 0x284(%rsp)
movl 0x284(%rsp), %eax
addq $0x288, %rsp            # imm = 0x288
retq
movq 0x88(%rsp), %rdi
callq 0x13970
nopw (%rax,%rax)