// File: /workspace/github_cpp_makefile_star2_O2/tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelUtils.cpp
// Function: gaps::CreatePlanarObjects(gaps::R3SurfelScene*, gaps::R3SurfelNode*, gaps::R3SurfelConstraint const*, gaps::R3SurfelObject*, gaps::R3SurfelNode*, int, double, double, double, double, double, int, double, double, double)
RNArray<R3SurfelObject *> *
CreatePlanarObjects(R3SurfelScene *scene, 
  R3SurfelNode *source_node, const R3SurfelConstraint *constraint,
  R3SurfelObject *parent_object, R3SurfelNode *parent_node,
  int max_neighbors, RNLength max_neighbor_distance, 
  RNLength max_offplane_distance, RNAngle max_normal_angle,
  RNArea min_area, RNScalar min_density, int min_points,
  RNLength grid_spacing, RNScalar accuracy_factor, 
  RNLength chunk_size)
{
  // Get convenient variables
  R3SurfelTree *tree = scene->Tree();
  if (!tree) return NULL;
  if (!source_node) source_node = tree->RootNode();
  const R3Box& source_bbox = source_node->BBox();
  int nxchunks = 1;
  int nychunks = 1;
  RNLength xchunk = source_bbox.XLength();
  RNLength ychunk = source_bbox.YLength();
  if (chunk_size > 0) {
    nxchunks = (int) (source_bbox.XLength() / chunk_size) + 1;
    nychunks = (int) (source_bbox.YLength() / chunk_size) + 1;
    xchunk = source_bbox.XLength() / nxchunks;
    ychunk = source_bbox.YLength() / nychunks;
  }

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

  // Fill array of objects chunk-by-chunk
  for (int j = 0; j < nychunks; j++) {
    for (int i = 0; i < nxchunks; i++) {
      // Compute chunk bounding box
      R3Box chunk_bbox = source_bbox;
      chunk_bbox[0][0] = source_bbox.XMin() + i     * xchunk;
      chunk_bbox[1][0] = source_bbox.XMin() + (i+1) * xchunk;
      chunk_bbox[0][1] = source_bbox.YMin() + j     * ychunk;
      chunk_bbox[1][1] = source_bbox.YMin() + (j+1) * ychunk;

      // Create graph
      R3SurfelBoxConstraint box_constraint(chunk_bbox);
      R3SurfelMultiConstraint multi_constraint;
      multi_constraint.InsertConstraint(&box_constraint);
      if (constraint) multi_constraint.InsertConstraint(constraint);
      R3SurfelPointGraph *graph = CreatePointGraph(scene, 
        source_node, &multi_constraint, 
        max_neighbors, max_neighbor_distance);
      if (!graph) continue;

      // Create planar grids
      RNArray<R3PlanarGrid *> *chunk_grids = CreatePlanarGrids(graph,
        max_offplane_distance, max_normal_angle, 
        min_area, min_density, min_points, 
        grid_spacing, accuracy_factor);
      if (!chunk_grids) { delete graph; continue; }

      // Delete graph
      delete graph;

      // Create objects 
      for (int k = 0; k < chunk_grids->NEntries(); k++) {
        R3PlanarGrid *grid = chunk_grids->Kth(k);
        char object_name[256];
        sprintf(object_name, "PlanarGrid%d\n", objects->NEntries());
        R3SurfelPlanarGridConstraint planar_grid_constraint(grid, max_offplane_distance);
        multi_constraint.InsertConstraint(&planar_grid_constraint);
        R3SurfelObject *object = CreateObject(scene, source_node, &multi_constraint, 
          parent_object, object_name, parent_node, object_name);
        multi_constraint.RemoveConstraint(&planar_grid_constraint);
        printf("  %6d/%6d %6d/%6d %6d/%6d : %9.3g %9.3g\n", j, nychunks, i, nxchunks, k, chunk_grids->NEntries(), grid->L1Norm(), grid->Area());
        if (object) objects->Insert(object);
        delete grid;
      }

      // Delete array of grids
      delete chunk_grids;
    }
  }

  // Return objects
  return objects;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2c8, %rsp            # imm = 0x2C8
movsd %xmm6, 0x88(%rsp)
movsd %xmm5, 0x80(%rsp)
movsd %xmm4, 0x78(%rsp)
movsd %xmm3, 0x70(%rsp)
movsd %xmm2, 0x68(%rsp)
movsd %xmm1, 0x30(%rsp)
movsd %xmm0, 0x98(%rsp)
movl %r9d, 0x1c(%rsp)
movq %r8, 0xc0(%rsp)
movq %rcx, 0xb8(%rsp)
movq %rdx, 0x28(%rsp)
movq %rdi, 0x38(%rsp)
movq 0x8(%rdi), %rax
testq %rax, %rax
je 0x27223
movq %rsi, %r15
movaps %xmm7, 0x50(%rsp)
testq %rsi, %rsi
jne 0x271bd
movq 0x18(%rax), %rax
movq (%rax), %r15
movq %r15, %rdi
callq 0x33720
movupd 0x8(%rax), %xmm0
movq %rax, 0x90(%rsp)
movupd 0x20(%rax), %xmm2
subpd %xmm0, %xmm2
xorpd %xmm0, %xmm0
movapd 0x50(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x27237
unpcklpd %xmm1, %xmm1            # xmm1 = xmm1[0,0]
movapd %xmm2, %xmm0
divpd %xmm1, %xmm0
cvttpd2dq %xmm0, %xmm0
pcmpeqd %xmm1, %xmm1
psubd %xmm1, %xmm0
cvtdq2pd %xmm0, %xmm1
divpd %xmm1, %xmm2
movapd %xmm2, 0x40(%rsp)
movd %xmm0, (%rsp)
pshufd $0x55, %xmm0, %xmm0     # xmm0 = xmm0[1,1,1,1]
movd %xmm0, 0x4(%rsp)
jmp 0x27247
xorl %eax, %eax
addq $0x2c8, %rsp            # imm = 0x2C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movapd %xmm2, 0x40(%rsp)
pushq $0x1
popq %rax
movl %eax, 0x4(%rsp)
movl %eax, (%rsp)
pushq $0x10
popq %rdi
callq 0x134f0
movq %rax, 0x8(%rsp)
movq %rax, %rdi
callq 0x9a7ae
movl (%rsp), %eax
testl %eax, %eax
movl $0x0, %ecx
cmovgl %eax, %ecx
movl %ecx, 0x20(%rsp)
movl 0x4(%rsp), %eax
testl %eax, %eax
movl $0x0, %ecx
cmovgl %eax, %ecx
movl %ecx, 0x14(%rsp)
movapd 0x40(%rsp), %xmm0
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
movapd %xmm1, 0xe0(%rsp)
leaq 0x128(%rsp), %r12
xorl %ecx, %ecx
movq 0x8(%rsp), %rax
movq %r15, 0xb0(%rsp)
movapd %xmm0, 0x40(%rsp)
cmpl 0x14(%rsp), %ecx
je 0x27225
cvtsi2sd %ecx, %xmm2
leal 0x1(%rcx), %edx
movl %edx, 0x18(%rsp)
cvtsi2sd %edx, %xmm3
xorl %edx, %edx
movapd 0xe0(%rsp), %xmm1
mulsd %xmm1, %xmm2
movsd %xmm2, 0xa8(%rsp)
mulsd %xmm1, %xmm3
movsd %xmm3, 0xa0(%rsp)
movq %rcx, 0xc8(%rsp)
cmpl 0x20(%rsp), %edx
je 0x27606
leaq 0xf0(%rsp), %r14
movq %r14, %rdi
movq 0x90(%rsp), %rbx
movq %rbx, %rsi
movq %rdx, %r13
callq 0x63ce6
cvtsi2sd %r13d, %xmm0
movapd 0x40(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd 0x8(%rbx), %xmm0
movq %r13, 0xd0(%rsp)
leal 0x1(%r13), %eax
movl %eax, 0x24(%rsp)
cvtsi2sd %eax, %xmm1
movsd %xmm0, 0xf8(%rsp)
mulsd %xmm2, %xmm1
addsd 0x8(%rbx), %xmm1
movsd %xmm1, 0x110(%rsp)
movsd 0x10(%rbx), %xmm0
addsd 0xa8(%rsp), %xmm0
movsd %xmm0, 0x100(%rsp)
movsd 0x10(%rbx), %xmm0
addsd 0xa0(%rsp), %xmm0
movsd %xmm0, 0x118(%rsp)
leaq 0x180(%rsp), %rdi
movq %r14, %rsi
callq 0x2d5c8
movq %r12, %rdi
callq 0x2ea82
movq %r12, %rdi
leaq 0x180(%rsp), %rsi
callq 0x2ea96
cmpq $0x0, 0x28(%rsp)
je 0x273cf
movq %r12, %rdi
movq 0x28(%rsp), %rsi
callq 0x2ea96
movq 0x38(%rsp), %rdi
movq %r15, %rsi
movq %r12, %rdx
movl 0x1c(%rsp), %ecx
movsd 0x98(%rsp), %xmm0
callq 0x21634
movq %rax, %r14
testq %rax, %rax
je 0x275d4
movq %r14, %rdi
movsd 0x30(%rsp), %xmm0
movsd 0x68(%rsp), %xmm1
movsd 0x70(%rsp), %xmm2
movsd 0x78(%rsp), %xmm3
movl 0x300(%rsp), %esi
movsd 0x80(%rsp), %xmm4
movsd 0x88(%rsp), %xmm5
callq 0x261d0
movq %rax, %rbp
movq (%r14), %rax
movq %r14, %rdi
callq *0x8(%rax)
testq %rbp, %rbp
je 0x275d4
xorl %ecx, %ecx
movslq 0xc(%rbp), %rax
cmpq %rax, %rcx
jge 0x275c1
movq (%rbp), %rax
movq %rcx, 0x50(%rsp)
movq (%rax,%rcx,8), %r13
movq 0x8(%rsp), %rax
movl 0xc(%rax), %edx
leaq 0x1c0(%rsp), %rdi
leaq 0xa1823(%rip), %rsi     # 0xc8c9c
xorl %eax, %eax
callq 0x130e0
leaq 0xfd7a1(%rip), %rax     # 0x124c28
movsd (%rax), %xmm1
xorpd %xmm2, %xmm2
xorpd %xmm3, %xmm3
leaq 0x140(%rsp), %rbx
movq %rbx, %rdi
movq %r13, %rsi
movsd 0x30(%rsp), %xmm0
pushq $0x4
popq %rdx
xorl %ecx, %ecx
pushq $0x1
popq %r8
callq 0x2db9a
movq %r12, %rdi
movq %rbx, %rsi
callq 0x2ea96
movq %rbp, %rbx
subq $0x8, %rsp
movq 0x40(%rsp), %rdi
movq %r15, %rsi
movq %r12, %r14
movq %r12, %rdx
movq 0xc0(%rsp), %rcx
leaq 0x1c8(%rsp), %r8
movq 0xc8(%rsp), %r9
pushq $0x1
pushq $0x0
pushq %r8
callq 0x22415
addq $0x20, %rsp
movq %rax, %r12
movq %r14, %rdi
leaq 0x140(%rsp), %rsi
callq 0x2eaa0
movl 0xc(%rbx), %ebp
leaq 0x130(%r13), %r15
movq %r15, %rdi
callq 0x84812
movsd %xmm0, 0xd8(%rsp)
movq %r15, %rdi
callq 0x28aea
movapd %xmm0, %xmm1
subq $0x8, %rsp
leaq 0xa1769(%rip), %rdi     # 0xc8caa
movq 0xd0(%rsp), %rsi
movl 0xc(%rsp), %edx
movq 0xd8(%rsp), %rcx
movl 0x8(%rsp), %r8d
movq 0x58(%rsp), %r9
movsd 0xe0(%rsp), %xmm0
movb $0x2, %al
pushq %rbp
callq 0x13070
popq %rcx
popq %rdx
testq %r12, %r12
je 0x27584
movq 0x8(%rsp), %rdi
movq %r12, %rsi
callq 0x1784c
movq %r13, %rdi
callq 0x6b18e
movl $0x240, %esi            # imm = 0x240
movq %r13, %rdi
callq 0x13500
leaq 0x140(%rsp), %rdi
callq 0x2ec74
movq 0x50(%rsp), %rcx
incq %rcx
movq 0xb0(%rsp), %r15
movq %r14, %r12
movq %rbx, %rbp
jmp 0x27448
movq %rbp, %rdi
callq 0x9a81c
movq %rbp, %rdi
pushq $0x10
popq %rsi
callq 0x13500
movq %r12, %rdi
callq 0x28504
leaq 0x180(%rsp), %rdi
callq 0x284c2
leaq 0xf0(%rsp), %rdi
callq 0x649ae
movl 0x24(%rsp), %eax
movl %eax, %edx
movq 0x8(%rsp), %rax
jmp 0x272f9
movl 0x18(%rsp), %ecx
jmp 0x272b3
movq %rax, %rbx
pushq $0x10
popq %rsi
movq 0x8(%rsp), %rdi
callq 0x13500
jmp 0x2766f
jmp 0x27631
movq %rax, %rbx
jmp 0x27662
movq %rax, %rbx
jmp 0x27655
jmp 0x27631
jmp 0x27631
movq %rax, %rbx
jmp 0x27648
jmp 0x27638
movq %rax, %rbx
leaq 0x140(%rsp), %rdi
callq 0x2ec74
leaq 0x128(%rsp), %rdi
callq 0x28504
leaq 0x180(%rsp), %rdi
callq 0x284c2
leaq 0xf0(%rsp), %rdi
callq 0x649ae
movq %rbx, %rdi
callq 0x138f0