// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3OrientedBox.cpp
// Function: gaps::R3OrientedBox::R3OrientedBox(gaps::RNArray<gaps::R3Point*> const&)
R3OrientedBox::
R3OrientedBox(const RNArray<R3Point *>& points)
{
#if 0
    // This is correct, but produces bboxes that are too big (diagonal)
  
    // Compute coordinate system
    R3Point centroid = R3Centroid(points);
    R3Triad axes = R3PrincipleAxes(centroid, points);

    // Compute ranges
    R3Box r = R3null_box;
    for (int i = 0; i < points.NEntries(); i++) {
      R3Point *point = points.Kth(i);
      R3Vector v = *point - centroid;
      RNLength r0 = v.Dot(axes[0]);
      RNLength r1 = v.Dot(axes[1]);
      RNLength r2 = v.Dot(axes[2]);
      r.Union(R3Point(r0, r1, r2));
    }

    // Compute center
    R3Point c = r.Centroid();
    R3Point center = centroid + axes[0]*c[0] + axes[1]*c[1] + axes[2]*c[2];

    // Initialize everything
    Reset(center, axes[0], axes[1], r.XRadius(), r.YRadius(), r.ZRadius());
#else
    // Get centroid 
    R3Point centroid = R3Centroid(points);

    // Search for best axes
    R3Box best_range = R3null_box;
    R3Triad best_axes = R3xyz_triad;
    int nxsteps = 2;
    int nysteps = 2;
    int nzsteps = 4;
    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_Z, ix*0.5*RN_PI/nxsteps);
          axes.Rotate(RN_Z, iy*0.5*RN_PI/nysteps);
          axes.Rotate(RN_Z, iz*0.5*RN_PI/nzsteps);
    
          // Compute ranges
          R3Box range = R3null_box;
          for (int i = 0; i < points.NEntries(); i++) {
            R3Point *point = points.Kth(i);
            R3Vector v = *point - centroid;
            RNLength r0 = v.Dot(axes[0]);
            RNLength r1 = v.Dot(axes[1]);
            RNLength r2 = v.Dot(axes[2]);
            range.Union(R3Point(r0, r1, r2));
          }

          // Check if range is best
          if (best_range.IsEmpty() || (range.Volume() < best_range.Volume())) {
            best_range = range;
            best_axes = axes;
          }
        }
      }
    }
      
    // Compute center
    if (best_range.IsEmpty()) best_range = R3zero_box;
    R3Point c = best_range.Centroid();
    R3Point center = centroid + best_axes[0]*c[0] + best_axes[1]*c[1] + best_axes[2]*c[2];
           
    // Initialize everything
    Reset(center, best_axes[0], best_axes[1], best_range.XRadius(), best_range.YRadius(), best_range.ZRadius());
#endif
}

// Assembly:
subq $0x318, %rsp            # imm = 0x318
movq %rdi, 0x310(%rsp)
movq %rsi, 0x308(%rsp)
movq 0x310(%rsp), %rdi
movq %rdi, 0xc0(%rsp)
callq 0x45120
movq 0xc0(%rsp), %rdi
leaq 0xcee6d(%rip), %rax     # 0x16e088
movq %rax, (%rdi)
addq $0x8, %rdi
callq 0x4e450
jmp 0x9f229
movq 0x308(%rsp), %rsi
xorl %eax, %eax
movl %eax, %edx
leaq 0x2e0(%rsp), %rdi
callq 0x8cd30
jmp 0x9f244
leaq 0xd959d(%rip), %rsi     # 0x1787e8
leaq 0x2a8(%rsp), %rdi
callq 0x428c0
jmp 0x9f25a
leaq 0xd98a7(%rip), %rsi     # 0x178b08
leaq 0x260(%rsp), %rdi
callq 0x4ebe0
jmp 0x9f270
movl $0x2, 0x25c(%rsp)
movl $0x2, 0x258(%rsp)
movl $0x4, 0x254(%rsp)
movl $0x0, 0x250(%rsp)
movl 0x250(%rsp), %eax
cmpl 0x25c(%rsp), %eax
jge 0x9f6ee
movl $0x0, 0x24c(%rsp)
movl 0x24c(%rsp), %eax
cmpl 0x258(%rsp), %eax
jge 0x9f6d6
movl $0x0, 0x248(%rsp)
movl 0x248(%rsp), %eax
cmpl 0x254(%rsp), %eax
jge 0x9f6be
leaq 0xd9813(%rip), %rsi     # 0x178b08
leaq 0x200(%rsp), %rdi
callq 0x4ebe0
jmp 0x9f304
cvtsi2sdl 0x250(%rsp), %xmm0
movsd 0x93cfb(%rip), %xmm1    # 0x133010
mulsd %xmm1, %xmm0
leaq 0x975b8(%rip), %rax     # 0x1368d8
movsd (%rax), %xmm1
mulsd %xmm1, %xmm0
cvtsi2sdl 0x25c(%rsp), %xmm1
divsd %xmm1, %xmm0
leaq 0x200(%rsp), %rdi
movl $0x2, %esi
callq 0x4f1a0
jmp 0x9f349
cvtsi2sdl 0x24c(%rsp), %xmm0
movsd 0x93cb6(%rip), %xmm1    # 0x133010
mulsd %xmm1, %xmm0
leaq 0x97573(%rip), %rax     # 0x1368d8
movsd (%rax), %xmm1
mulsd %xmm1, %xmm0
cvtsi2sdl 0x258(%rsp), %xmm1
divsd %xmm1, %xmm0
leaq 0x200(%rsp), %rdi
movl $0x2, %esi
callq 0x4f1a0
jmp 0x9f38e
cvtsi2sdl 0x248(%rsp), %xmm0
movsd 0x93c71(%rip), %xmm1    # 0x133010
mulsd %xmm1, %xmm0
leaq 0x9752e(%rip), %rax     # 0x1368d8
movsd (%rax), %xmm1
mulsd %xmm1, %xmm0
cvtsi2sdl 0x254(%rsp), %xmm1
divsd %xmm1, %xmm0
leaq 0x200(%rsp), %rdi
movl $0x2, %esi
callq 0x4f1a0
jmp 0x9f3d3
leaq 0xd940e(%rip), %rsi     # 0x1787e8
leaq 0x1c8(%rsp), %rdi
callq 0x428c0
jmp 0x9f3e9
movl $0x0, 0x1c4(%rsp)
movl 0x1c4(%rsp), %eax
movl %eax, 0xb8(%rsp)
movq 0x308(%rsp), %rdi
callq 0x13600
movl %eax, 0xbc(%rsp)
jmp 0x9f418
movl 0xb8(%rsp), %eax
movl 0xbc(%rsp), %ecx
cmpl %ecx, %eax
jge 0x9f613
movq 0x308(%rsp), %rdi
movl 0x1c4(%rsp), %esi
callq 0xa1130
movq %rax, 0xb0(%rsp)
jmp 0x9f44c
movq 0xb0(%rsp), %rax
movq %rax, 0x1b8(%rsp)
movq 0x1b8(%rsp), %rsi
leaq 0x1a0(%rsp), %rdi
leaq 0x2e0(%rsp), %rdx
callq 0x6eeb0
jmp 0x9f47b
leaq 0x200(%rsp), %rdi
xorl %esi, %esi
callq 0x39fb0
movq %rax, 0xa8(%rsp)
jmp 0x9f494
movq 0xa8(%rsp), %rsi
leaq 0x1a0(%rsp), %rdi
callq 0x702c0
movsd %xmm0, 0xa0(%rsp)
jmp 0x9f4b4
movsd 0xa0(%rsp), %xmm0
movsd %xmm0, 0x198(%rsp)
leaq 0x200(%rsp), %rdi
movl $0x1, %esi
callq 0x39fb0
movq %rax, 0x98(%rsp)
jmp 0x9f4e2
movq 0x98(%rsp), %rsi
leaq 0x1a0(%rsp), %rdi
callq 0x702c0
movsd %xmm0, 0x90(%rsp)
jmp 0x9f502
movsd 0x90(%rsp), %xmm0
movsd %xmm0, 0x190(%rsp)
leaq 0x200(%rsp), %rdi
movl $0x2, %esi
callq 0x39fb0
movq %rax, 0x88(%rsp)
jmp 0x9f530
movq 0x88(%rsp), %rsi
leaq 0x1a0(%rsp), %rdi
callq 0x702c0
movsd %xmm0, 0x80(%rsp)
jmp 0x9f550
movsd 0x80(%rsp), %xmm0
movsd %xmm0, 0x188(%rsp)
movsd 0x198(%rsp), %xmm0
movsd 0x190(%rsp), %xmm1
movsd 0x188(%rsp), %xmm2
leaq 0x170(%rsp), %rdi
callq 0x6eb50
jmp 0x9f58c
leaq 0x1c8(%rsp), %rdi
leaq 0x170(%rsp), %rsi
callq 0x444b0
jmp 0x9f5a3
jmp 0x9f5a5
movl 0x1c4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1c4(%rsp)
jmp 0x9f3f4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x300(%rsp)
movl %eax, 0x2fc(%rsp)
jmp 0x9f947
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x300(%rsp)
movl %eax, 0x2fc(%rsp)
jmp 0x9f93a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x300(%rsp)
movl %eax, 0x2fc(%rsp)
leaq 0x1c8(%rsp), %rdi
callq 0x36a80
jmp 0x9f93a
leaq 0x2a8(%rsp), %rdi
callq 0x44d80
movl %eax, 0x7c(%rsp)
jmp 0x9f626
movl 0x7c(%rsp), %eax
cmpl $0x0, %eax
jne 0x9f66b
leaq 0x1c8(%rsp), %rdi
callq 0x44200
movsd %xmm0, 0x70(%rsp)
jmp 0x9f644
leaq 0x2a8(%rsp), %rdi
callq 0x44200
movsd %xmm0, 0x68(%rsp)
jmp 0x9f659
movsd 0x68(%rsp), %xmm0
movsd 0x70(%rsp), %xmm1
ucomisd %xmm1, %xmm0
jbe 0x9f69b
leaq 0x2a8(%rsp), %rdi
leaq 0x1c8(%rsp), %rsi
callq 0x37500
jmp 0x9f682
leaq 0x260(%rsp), %rdi
leaq 0x200(%rsp), %rsi
callq 0x4eb10
jmp 0x9f699
jmp 0x9f69b
leaq 0x1c8(%rsp), %rdi
callq 0x36a80
movl 0x248(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x248(%rsp)
jmp 0x9f2da
jmp 0x9f6c0
movl 0x24c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24c(%rsp)
jmp 0x9f2bb
jmp 0x9f6d8
movl 0x250(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x250(%rsp)
jmp 0x9f29c
leaq 0x2a8(%rsp), %rdi
callq 0x44d80
movl %eax, 0x64(%rsp)
jmp 0x9f701
movl 0x64(%rsp), %eax
cmpl $0x0, %eax
je 0x9f722
leaq 0xd902f(%rip), %rsi     # 0x178740
leaq 0x2a8(%rsp), %rdi
callq 0x37500
jmp 0x9f720
jmp 0x9f722
leaq 0x158(%rsp), %rdi
leaq 0x2a8(%rsp), %rsi
callq 0x44260
jmp 0x9f739
leaq 0x260(%rsp), %rdi
xorl %esi, %esi
callq 0x39fb0
movq %rax, 0x58(%rsp)
jmp 0x9f74f
leaq 0x158(%rsp), %rdi
xorl %esi, %esi
callq 0x36be0
movq %rax, 0x50(%rsp)
jmp 0x9f765
movq 0x58(%rsp), %rsi
movq 0x50(%rsp), %rax
movsd (%rax), %xmm0
leaq 0xf8(%rsp), %rdi
callq 0x70b80
jmp 0x9f782
leaq 0x110(%rsp), %rdi
leaq 0x2e0(%rsp), %rsi
leaq 0xf8(%rsp), %rdx
callq 0x6f110
jmp 0x9f7a1
leaq 0x260(%rsp), %rdi
movl $0x1, %esi
callq 0x39fb0
movq %rax, 0x48(%rsp)
jmp 0x9f7ba
leaq 0x158(%rsp), %rdi
movl $0x1, %esi
callq 0x36be0
movq %rax, 0x40(%rsp)
jmp 0x9f7d3
movq 0x48(%rsp), %rsi
movq 0x40(%rsp), %rax
movsd (%rax), %xmm0
leaq 0xe0(%rsp), %rdi
callq 0x70b80
jmp 0x9f7f0
leaq 0x128(%rsp), %rdi
leaq 0x110(%rsp), %rsi
leaq 0xe0(%rsp), %rdx
callq 0x6f110
jmp 0x9f80f
leaq 0x260(%rsp), %rdi
movl $0x2, %esi
callq 0x39fb0
movq %rax, 0x38(%rsp)
jmp 0x9f828
leaq 0x158(%rsp), %rdi
movl $0x2, %esi
callq 0x36be0
movq %rax, 0x30(%rsp)
jmp 0x9f841
movq 0x38(%rsp), %rsi
movq 0x30(%rsp), %rax
movsd (%rax), %xmm0
leaq 0xc8(%rsp), %rdi
callq 0x70b80
jmp 0x9f85e
leaq 0x140(%rsp), %rdi
leaq 0x128(%rsp), %rsi
leaq 0xc8(%rsp), %rdx
callq 0x6f110
jmp 0x9f87d
leaq 0x260(%rsp), %rdi
xorl %esi, %esi
callq 0x39fb0
movq %rax, 0x28(%rsp)
jmp 0x9f893
leaq 0x260(%rsp), %rdi
movl $0x1, %esi
callq 0x39fb0
movq %rax, 0x20(%rsp)
jmp 0x9f8ac
leaq 0x2a8(%rsp), %rdi
callq 0xa1150
movsd %xmm0, 0x18(%rsp)
jmp 0x9f8c1
leaq 0x2a8(%rsp), %rdi
callq 0xa1170
movsd %xmm0, 0x10(%rsp)
jmp 0x9f8d6
leaq 0x2a8(%rsp), %rdi
callq 0xa1190
movsd %xmm0, 0x8(%rsp)
jmp 0x9f8eb
movsd 0x8(%rsp), %xmm2
movsd 0x10(%rsp), %xmm1
movsd 0x18(%rsp), %xmm0
movq 0x20(%rsp), %rcx
movq 0x28(%rsp), %rdx
movq 0xc0(%rsp), %rdi
movq (%rdi), %rax
movq 0x268(%rax), %rax
leaq 0x140(%rsp), %rsi
callq *%rax
jmp 0x9f925
leaq 0x2a8(%rsp), %rdi
callq 0x36a80
addq $0x318, %rsp            # imm = 0x318
retq
leaq 0x2a8(%rsp), %rdi
callq 0x36a80
movq 0xc0(%rsp), %rdi
callq 0x45150
movq 0x300(%rsp), %rdi
callq 0xf890
nopw %cs:(%rax,%rax)