// File: tomfunkhouser[P]gaps/pkgs/GSV/GSVMesh.cpp
// Function: gaps::GSVMesh::WriteARFFFile(gaps::GSVScan*, char const*) const
int GSVMesh::
WriteARFFFile(GSVScan *scan, const char *filename) const
{
  // Open file
  FILE *fp = fopen(filename, "w");
  if (!fp) {
    RNFail("Unable to open ARFF file %s\n", filename);
    return 0;
  }
  
  // Write header
  fprintf(fp, "@relation GSV\n");
  fprintf(fp, "\n");

  // Write property names
  fprintf(fp, "@attribute ScanlineIndex real\n");
  fprintf(fp, "@attribute PointIndex real\n");
  fprintf(fp, "@attribute Timestamp real\n");
  fprintf(fp, "@attribute PositionX real\n");
  fprintf(fp, "@attribute PositionY real\n");
  fprintf(fp, "@attribute PositionZ real\n");
  fprintf(fp, "@attribute NormalX real\n");
  fprintf(fp, "@attribute NormalY real\n");
  fprintf(fp, "@attribute NormalZ real\n");
  fprintf(fp, "@attribute GroundZ real\n");
  fprintf(fp, "@attribute Height real\n");
  fprintf(fp, "@attribute LaserDepth real\n");
  fprintf(fp, "@attribute LaserDistance real\n");
  fprintf(fp, "@attribute LaserAngle real\n");
  fprintf(fp, "@attribute LaserViewpointX real\n");
  fprintf(fp, "@attribute LaserViewpointY real\n");
  fprintf(fp, "@attribute LaserViewpointZ real\n");
  fprintf(fp, "@attribute LaserTowardsX real\n");
  fprintf(fp, "@attribute LaserTowardsY real\n");
  fprintf(fp, "@attribute LaserTowardsZ real\n");
  fprintf(fp, "@attribute LaserUpX real\n");
  fprintf(fp, "@attribute LaserUpY real\n");
  fprintf(fp, "@attribute LaserUpZ real\n");
  fprintf(fp, "@attribute BoundaryType real\n");
  fprintf(fp, "\n");
  
  // Write property values (one line per vertex)
  fprintf(fp, "@data\n\n");
  for (int i = 0; i < NVertices(); i++) {
    GSVMeshVertex *vertex = Vertex(i);
    const R3Point& position = VertexPosition(vertex);
    const R3Vector& normal = VertexNormal(vertex);
    GSVScanline *scanline = VertexScanline(vertex);
    RNCoord groundZ = (scanline) ? scanline->EstimatedGroundZ() : -1;
    RNLength height = position.Z() - groundZ;
    R3Point viewpoint = VertexLaserViewpoint(vertex);
    R3Vector towards = VertexLaserTowards(vertex);
    R3Vector up = VertexLaserUp(vertex);
    fprintf(fp, "%d ", VertexScanlineIndex(vertex));
    fprintf(fp, "%d ", VertexPointIndex(vertex));
    fprintf(fp, "%g ", VertexTimestamp(vertex));
    fprintf(fp, "%g ", position.X());
    fprintf(fp, "%g ", position.Y());
    fprintf(fp, "%g ", position.Z());
    fprintf(fp, "%g ", normal.X());
    fprintf(fp, "%g ", normal.Y());
    fprintf(fp, "%g ", normal.Z());
    fprintf(fp, "%g ", groundZ);
    fprintf(fp, "%g ", height);
    fprintf(fp, "%g ", VertexLaserDepth(vertex));
    fprintf(fp, "%g ", VertexLaserDistance(vertex));
    fprintf(fp, "%g ", VertexLaserAngle(vertex));
    fprintf(fp, "%g ", viewpoint.X());
    fprintf(fp, "%g ", viewpoint.Y());
    fprintf(fp, "%g ", viewpoint.Z());
    fprintf(fp, "%g ", towards.X());
    fprintf(fp, "%g ", towards.Y());
    fprintf(fp, "%g ", towards.Z());
    fprintf(fp, "%g ", up.X());
    fprintf(fp, "%g ", up.Y());
    fprintf(fp, "%g ", up.Z());
    fprintf(fp, "%d ", VertexBoundaryType(vertex));
    fprintf(fp, "\n");
  }

  // Close file
  fclose(fp);

  // Return success
  return 1;
}

// Assembly:
subq $0x178, %rsp            # imm = 0x178
movq %rdi, 0x168(%rsp)
movq %rsi, 0x160(%rsp)
movq %rdx, 0x158(%rsp)
movq 0x168(%rsp), %rax
movq %rax, 0xc8(%rsp)
movq 0x158(%rsp), %rdi
leaq 0x20e4a0(%rip), %rsi    # 0x26bc4e
callq 0x2a520
movq %rax, 0x150(%rsp)
cmpq $0x0, 0x150(%rsp)
jne 0x5d7ec
movq 0x158(%rsp), %rsi
leaq 0x209e59(%rip), %rdi    # 0x26762e
movb $0x0, %al
callq 0x1cbff0
movl $0x0, 0x174(%rsp)
jmp 0x5e084
movq 0x150(%rsp), %rdi
leaq 0x209e50(%rip), %rsi    # 0x26764b
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x2095f5(%rip), %rsi    # 0x266e06
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e33(%rip), %rsi    # 0x26765a
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e3c(%rip), %rsi    # 0x267679
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e42(%rip), %rsi    # 0x267695
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e47(%rip), %rsi    # 0x2676b0
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e4c(%rip), %rsi    # 0x2676cb
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e51(%rip), %rsi    # 0x2676e6
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e56(%rip), %rsi    # 0x267701
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e59(%rip), %rsi    # 0x26771a
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e5c(%rip), %rsi    # 0x267733
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e5f(%rip), %rsi    # 0x26774c
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e62(%rip), %rsi    # 0x267765
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e64(%rip), %rsi    # 0x26777d
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e6a(%rip), %rsi    # 0x267799
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e73(%rip), %rsi    # 0x2677b8
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e79(%rip), %rsi    # 0x2677d4
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e84(%rip), %rsi    # 0x2677f5
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e8f(%rip), %rsi    # 0x267816
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209e9a(%rip), %rsi    # 0x267837
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209ea3(%rip), %rsi    # 0x267856
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209eac(%rip), %rsi    # 0x267875
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209eb5(%rip), %rsi    # 0x267894
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209eb9(%rip), %rsi    # 0x2678ae
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209ebd(%rip), %rsi    # 0x2678c8
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209ec1(%rip), %rsi    # 0x2678e2
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x2093cf(%rip), %rsi    # 0x266e06
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x209eb3(%rip), %rsi    # 0x267900
movb $0x0, %al
callq 0x293c0
movl $0x0, 0x14c(%rsp)
movq 0xc8(%rsp), %rdi
movl 0x14c(%rsp), %eax
movl %eax, 0xc4(%rsp)
callq 0x391c0
movl %eax, %ecx
movl 0xc4(%rsp), %eax
cmpl %ecx, %eax
jge 0x5e06c
movq 0xc8(%rsp), %rdi
movl 0x14c(%rsp), %esi
callq 0x5e390
movq 0xc8(%rsp), %rdi
movq %rax, 0x140(%rsp)
movq 0x140(%rsp), %rsi
callq 0x391a0
movq 0xc8(%rsp), %rdi
movq %rax, 0x138(%rsp)
movq 0x140(%rsp), %rsi
callq 0x39210
movq 0xc8(%rsp), %rdi
movq %rax, 0x130(%rsp)
movq 0x140(%rsp), %rsi
callq 0x5e150
movq %rax, 0x128(%rsp)
cmpq $0x0, 0x128(%rsp)
je 0x5db21
movq 0x128(%rsp), %rdi
callq 0x570a0
movsd %xmm0, 0xb8(%rsp)
jmp 0x5db34
movsd 0x2084df(%rip), %xmm0   # 0x266008
movsd %xmm0, 0xb8(%rsp)
jmp 0x5db34
movsd 0xb8(%rsp), %xmm0
movsd %xmm0, 0x120(%rsp)
movq 0x138(%rsp), %rdi
callq 0x38c20
movq 0xc8(%rsp), %rsi
subsd 0x120(%rsp), %xmm0
movsd %xmm0, 0x118(%rsp)
movq 0x140(%rsp), %rdx
leaq 0x100(%rsp), %rdi
callq 0x5a4a0
movq 0xc8(%rsp), %rsi
movq 0x140(%rsp), %rdx
leaq 0xe8(%rsp), %rdi
callq 0x5a530
movq 0xc8(%rsp), %rsi
movq 0x140(%rsp), %rdx
leaq 0xd0(%rsp), %rdi
callq 0x5a5b0
movq 0xc8(%rsp), %rdi
movq 0x150(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x140(%rsp), %rsi
callq 0x5a630
movq 0x8(%rsp), %rdi
movl %eax, %edx
leaq 0x20a2c8(%rip), %rsi    # 0x267eb4
movb $0x0, %al
callq 0x293c0
movq 0xc8(%rsp), %rdi
movq 0x150(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x140(%rsp), %rsi
callq 0x5e180
movq 0x10(%rsp), %rdi
movl %eax, %edx
leaq 0x20a291(%rip), %rsi    # 0x267eb4
movb $0x0, %al
callq 0x293c0
movq 0xc8(%rsp), %rdi
movq 0x150(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x140(%rsp), %rsi
callq 0x5a050
movq 0x18(%rsp), %rdi
leaq 0x20a267(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0x150(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0x138(%rsp), %rdi
callq 0x38bb0
movq 0x20(%rsp), %rdi
leaq 0x20a23a(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0x150(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x138(%rsp), %rdi
callq 0x38c10
movq 0x28(%rsp), %rdi
leaq 0x20a20d(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0x150(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x138(%rsp), %rdi
callq 0x38c20
movq 0x30(%rsp), %rdi
leaq 0x20a1e0(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0x150(%rsp), %rax
movq %rax, 0x38(%rsp)
movq 0x130(%rsp), %rdi
callq 0x38c80
movq 0x38(%rsp), %rdi
leaq 0x20a1b3(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0x150(%rsp), %rax
movq %rax, 0x40(%rsp)
movq 0x130(%rsp), %rdi
callq 0x38c90
movq 0x40(%rsp), %rdi
leaq 0x20a186(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0x150(%rsp), %rax
movq %rax, 0x48(%rsp)
movq 0x130(%rsp), %rdi
callq 0x38ca0
movq 0x48(%rsp), %rdi
leaq 0x20a159(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
movsd 0x120(%rsp), %xmm0
leaq 0x20a13a(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
movsd 0x118(%rsp), %xmm0
leaq 0x20a11b(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0xc8(%rsp), %rdi
movq 0x150(%rsp), %rax
movq %rax, 0x50(%rsp)
movq 0x140(%rsp), %rsi
callq 0x5a320
movq 0x50(%rsp), %rdi
leaq 0x20a0e6(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0xc8(%rsp), %rdi
movq 0x150(%rsp), %rax
movq %rax, 0x58(%rsp)
movq 0x140(%rsp), %rsi
callq 0x5a400
movq 0x58(%rsp), %rdi
leaq 0x20a0b1(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0xc8(%rsp), %rdi
movq 0x150(%rsp), %rax
movq %rax, 0x60(%rsp)
movq 0x140(%rsp), %rsi
callq 0x5a140
movq 0x60(%rsp), %rdi
leaq 0x20a07c(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0x150(%rsp), %rax
movq %rax, 0x68(%rsp)
leaq 0x100(%rsp), %rdi
callq 0x38bb0
movq 0x68(%rsp), %rdi
leaq 0x20a04f(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0x150(%rsp), %rax
movq %rax, 0x70(%rsp)
leaq 0x100(%rsp), %rdi
callq 0x38c10
movq 0x70(%rsp), %rdi
leaq 0x20a022(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0x150(%rsp), %rax
movq %rax, 0x78(%rsp)
leaq 0x100(%rsp), %rdi
callq 0x38c20
movq 0x78(%rsp), %rdi
leaq 0x209ff5(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0x150(%rsp), %rax
movq %rax, 0x80(%rsp)
leaq 0xe8(%rsp), %rdi
callq 0x38c80
movq 0x80(%rsp), %rdi
leaq 0x209fc2(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0x150(%rsp), %rax
movq %rax, 0x88(%rsp)
leaq 0xe8(%rsp), %rdi
callq 0x38c90
movq 0x88(%rsp), %rdi
leaq 0x209f8f(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0x150(%rsp), %rax
movq %rax, 0x90(%rsp)
leaq 0xe8(%rsp), %rdi
callq 0x38ca0
movq 0x90(%rsp), %rdi
leaq 0x209f5c(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0x150(%rsp), %rax
movq %rax, 0x98(%rsp)
leaq 0xd0(%rsp), %rdi
callq 0x38c80
movq 0x98(%rsp), %rdi
leaq 0x209f29(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0x150(%rsp), %rax
movq %rax, 0xa0(%rsp)
leaq 0xd0(%rsp), %rdi
callq 0x38c90
movq 0xa0(%rsp), %rdi
leaq 0x209ef6(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0x150(%rsp), %rax
movq %rax, 0xa8(%rsp)
leaq 0xd0(%rsp), %rdi
callq 0x38ca0
movq 0xa8(%rsp), %rdi
leaq 0x209ec3(%rip), %rsi    # 0x267ebf
movb $0x1, %al
callq 0x293c0
movq 0xc8(%rsp), %rdi
movq 0x150(%rsp), %rax
movq %rax, 0xb0(%rsp)
movq 0x140(%rsp), %rsi
callq 0x5e1a0
movq 0xb0(%rsp), %rdi
movl %eax, %edx
leaq 0x209e7b(%rip), %rsi    # 0x267eb4
movb $0x0, %al
callq 0x293c0
movq 0x150(%rsp), %rdi
leaq 0x208db7(%rip), %rsi    # 0x266e06
movb $0x0, %al
callq 0x293c0
movl 0x14c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x14c(%rsp)
jmp 0x5da5f
movq 0x150(%rsp), %rdi
callq 0x297e0
movl $0x1, 0x174(%rsp)
movl 0x174(%rsp), %eax
addq $0x178, %rsp            # imm = 0x178
retq
nopw %cs:(%rax,%rax)