// File: /workspace/github_cpp_makefile_star2_O2/tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelUtils.cpp
// Function: gaps::EstimateOrientedBBox(gaps::R3SurfelPointSet*)
R3OrientedBox 
EstimateOrientedBBox(R3SurfelPointSet *pointset)
{
  // Check pointset
  if (pointset->NPoints() == 0) return R3null_oriented_box;
    
  // Get centroid 
  R3Point centroid = pointset->Centroid();

  // Search for best axes
  int nxsteps = 1;
  int nysteps = 1;
  int nzsteps = 16;
  RNVolume best_volume = FLT_MAX;
  R3OrientedBox best_obb = R3null_oriented_box;
  for (int ix = 0; ix < nxsteps; ix++) {
    for (int iy = 0; iy < nysteps; iy++) {
      for (int iz = 0; iz < nzsteps; iz++) {
        R3Triad axes = R3xyz_triad;
        axes.Rotate(RN_X, ix*0.5*RN_PI/nxsteps);
        axes.Rotate(RN_Y, iy*0.5*RN_PI/nysteps);
        axes.Rotate(RN_Z, iz*0.5*RN_PI/nzsteps);

        // Compute oriented bbox
        R3OrientedBox obb = EstimateOrientedBBox(pointset, centroid, axes);
        RNVolume volume = obb.Volume();
        if (volume < best_volume) {
          best_volume = volume;
          best_obb = obb;
        }
      }
    }
  }
      
  // Check if should rotate around Z by 90 degrees to make axis0 the longer axis
  if (best_obb.Radius(0) < best_obb.Radius(1)) {
    best_obb.Reset(best_obb.Center(), best_obb.Axis(1), -(best_obb.Axis(0)),
      best_obb.Radius(1), best_obb.Radius(0), best_obb.Radius(2));
  }

  // Return best oriented box
  return best_obb;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x108, %rsp            # imm = 0x108
movq %rdi, %rbx
cmpl $0x0, 0x10(%rsi)
je 0x26130
movq %rsi, %r14
leaq 0x28(%rsp), %rdi
callq 0x2f6e6
leaq 0xff7db(%rip), %rsi     # 0x1257b0
movq %rbx, 0x8(%rsp)
movq %rbx, %rdi
callq 0x629ec
leaq 0xab76f(%rip), %rax     # 0xd1758
movsd (%rax), %xmm0
xorpd %xmm1, %xmm1
movsd %xmm0, 0x20(%rsp)
mulsd %xmm0, %xmm1
movsd %xmm1, 0x18(%rsp)
movsd 0xa215f(%rip), %xmm0    # 0xc8168
movsd %xmm0, 0x10(%rsp)
movb $0x1, %r12b
leaq 0xc0(%rsp), %r13
pushq $0x1
popq %rbp
pushq $0x2
popq %rbx
leaq 0x40(%rsp), %r15
testb $0x1, %r12b
je 0x260eb
movb $0x1, %al
xorl %r12d, %r12d
testb $0x1, %al
je 0x26025
cmpl $0x10, %r12d
je 0x260e4
movq %r13, %rdi
leaq 0xffcbc(%rip), %rsi     # 0x125d08
callq 0x672a8
movq %r13, %rdi
xorl %esi, %esi
movsd 0x18(%rsp), %xmm0
callq 0x67522
movq %r13, %rdi
movl %ebp, %esi
movsd 0x18(%rsp), %xmm0
callq 0x67522
cvtsi2sd %r12d, %xmm0
mulsd 0xa20ba(%rip), %xmm0    # 0xc8138
mulsd 0x20(%rsp), %xmm0
mulsd 0xa2a7c(%rip), %xmm0    # 0xc8b08
movq %r13, %rdi
movl %ebx, %esi
callq 0x67522
movq %r15, %rdi
movq %r14, %rsi
leaq 0x28(%rsp), %rdx
movq %r13, %rcx
callq 0x25d19
movq %r15, %rdi
callq 0x63460
movapd %xmm0, %xmm1
movsd 0x10(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x260d4
movq 0x8(%rsp), %rdi
movq %r15, %rsi
movsd %xmm1, 0x10(%rsp)
callq 0x28684
movq %r15, %rdi
callq 0x649ae
incl %r12d
jmp 0x26038
xorl %eax, %eax
jmp 0x26031
movq 0x8(%rsp), %rbx
movsd 0x70(%rbx), %xmm0
ucomisd 0x68(%rbx), %xmm0
jbe 0x2613f
leaq 0x20(%rbx), %rsi
leaq 0x40(%rsp), %rdi
callq 0x792e2
leaq 0x38(%rbx), %rdx
leaq 0x8(%rbx), %rsi
movsd 0x68(%rbx), %xmm1
movsd 0x70(%rbx), %xmm0
movsd 0x78(%rbx), %xmm2
leaq 0x40(%rsp), %rcx
movq %rbx, %rdi
callq 0x63a9c
jmp 0x2613f
leaq 0xff679(%rip), %rsi     # 0x1257b0
movq %rbx, %rdi
callq 0x629ec
movq %rbx, %rax
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x26167
jmp 0x26167
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x649ae
jmp 0x2616a
movq %rax, %rbx
movq 0x8(%rsp), %rdi
callq 0x649ae
movq %rbx, %rdi
callq 0x138f0