// File: tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelTree.cpp
// Function: gaps::R3SurfelTree::SplitNode(gaps::R3SurfelNode*, int, int, double, double, double, double, int)
int R3SurfelTree::
SplitNode(R3SurfelNode *node,  
    int max_parts_per_node, int max_blocks_per_node, 
    RNScalar max_leaf_complexity, RNScalar max_block_complexity,
    RNLength max_leaf_extent, RNLength max_block_extent,
    int max_levels)
{
  // Initialize return value
  int status = 0;

  // Just checking
  if (max_block_complexity > max_leaf_complexity) {
    max_block_complexity = max_leaf_complexity;
  }

  // Check if node is leaf
  if (node->NParts() == 0) {
    // Split blocks
    if (((max_block_complexity > 0) && (node->Complexity() > max_block_complexity)) ||
        ((max_block_extent > 0) && (node->BBox().LongestAxisLength() > max_block_extent))) {
      status |= SplitBlocks(node, max_block_complexity, max_block_extent);
    }

    // Check if node should be split 
    if (node->TreeLevel() < max_levels) {
      // Determine number of parts
      int nparts = 1;
      if (max_blocks_per_node > 0) {
        int n = node->NBlocks() / max_blocks_per_node + 1;
        if (n > nparts) nparts = n;
      }
      if (max_leaf_complexity > 0) {
        int n = (int) (node->Complexity() / max_leaf_complexity) + 1;
        if (n > nparts) nparts = n;
      }
      if (max_leaf_extent > 0) {
        int n = (int) (node->BBox().LongestAxisLength() / max_leaf_extent) + 1;
        if (n > nparts) nparts = n;
      }
      if (max_parts_per_node > 0) {
        if (nparts > max_parts_per_node) nparts = max_parts_per_node;
      }
      if (nparts > node->NBlocks()) {
        nparts = node->NBlocks();
      }

      // Split node into parts with K means clustering of blocks
      if (nparts > 1) {
        status |= SplitLeafNodeWithKMeansClusteringOfBlocks(this, node, nparts);
      }
    }
  }
  else {
    // Check if node should be split
    if (node->TreeLevel() < max_levels) {
      // Determine number of parts
      int nparts = node->NParts() / max_parts_per_node + 1;
      if (nparts > max_parts_per_node) nparts = max_parts_per_node;

      // Split node into parts with K means clustering of parts
      if (nparts > 1) {
        status |= SplitInteriorNodeWithKMeansClusteringOfParts(this, node, nparts);
      }
    }
  }

  // Return whether anything was split
  return status;
}

// Assembly:
subq $0x68, %rsp
movq %rdi, 0x60(%rsp)
movq %rsi, 0x58(%rsp)
movl %edx, 0x54(%rsp)
movl %ecx, 0x50(%rsp)
movsd %xmm0, 0x48(%rsp)
movsd %xmm1, 0x40(%rsp)
movsd %xmm2, 0x38(%rsp)
movsd %xmm3, 0x30(%rsp)
movl %r8d, 0x2c(%rsp)
movq 0x60(%rsp), %rax
movq %rax, 0x8(%rsp)
movl $0x0, 0x28(%rsp)
movsd 0x40(%rsp), %xmm0
ucomisd 0x48(%rsp), %xmm0
jbe 0x6317f
movsd 0x48(%rsp), %xmm0
movsd %xmm0, 0x40(%rsp)
movq 0x58(%rsp), %rdi
callq 0x31660
cmpl $0x0, %eax
jne 0x6333c
movsd 0x40(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x631b3
movq 0x58(%rsp), %rdi
callq 0x5ecb0
ucomisd 0x40(%rsp), %xmm0
ja 0x631dc
movsd 0x30(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x63200
movq 0x58(%rsp), %rdi
callq 0x5ee30
movq %rax, %rdi
callq 0xcb1d0
ucomisd 0x30(%rsp), %xmm0
jbe 0x63200
movq 0x8(%rsp), %rdi
movq 0x58(%rsp), %rsi
movsd 0x40(%rsp), %xmm0
movsd 0x30(%rsp), %xmm1
movq (%rdi), %rax
callq *0x40(%rax)
orl 0x28(%rsp), %eax
movl %eax, 0x28(%rsp)
movq 0x58(%rsp), %rdi
callq 0x5f270
cmpl 0x2c(%rsp), %eax
jge 0x6333a
movl $0x1, 0x24(%rsp)
cmpl $0x0, 0x50(%rsp)
jle 0x6324d
movq 0x58(%rsp), %rdi
callq 0x186b0
cltd
idivl 0x50(%rsp)
addl $0x1, %eax
movl %eax, 0x20(%rsp)
movl 0x20(%rsp), %eax
cmpl 0x24(%rsp), %eax
jle 0x6324b
movl 0x20(%rsp), %eax
movl %eax, 0x24(%rsp)
jmp 0x6324d
movsd 0x48(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x6328b
movq 0x58(%rsp), %rdi
callq 0x5ecb0
divsd 0x48(%rsp), %xmm0
cvttsd2si %xmm0, %eax
addl $0x1, %eax
movl %eax, 0x1c(%rsp)
movl 0x1c(%rsp), %eax
cmpl 0x24(%rsp), %eax
jle 0x63289
movl 0x1c(%rsp), %eax
movl %eax, 0x24(%rsp)
jmp 0x6328b
movsd 0x38(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x632d1
movq 0x58(%rsp), %rdi
callq 0x5ee30
movq %rax, %rdi
callq 0xcb1d0
divsd 0x38(%rsp), %xmm0
cvttsd2si %xmm0, %eax
addl $0x1, %eax
movl %eax, 0x18(%rsp)
movl 0x18(%rsp), %eax
cmpl 0x24(%rsp), %eax
jle 0x632cf
movl 0x18(%rsp), %eax
movl %eax, 0x24(%rsp)
jmp 0x632d1
cmpl $0x0, 0x54(%rsp)
jle 0x632ec
movl 0x24(%rsp), %eax
cmpl 0x54(%rsp), %eax
jle 0x632ea
movl 0x54(%rsp), %eax
movl %eax, 0x24(%rsp)
jmp 0x632ec
movl 0x24(%rsp), %eax
movl %eax, 0x4(%rsp)
movq 0x58(%rsp), %rdi
callq 0x186b0
movl %eax, %ecx
movl 0x4(%rsp), %eax
cmpl %ecx, %eax
jle 0x63316
movq 0x58(%rsp), %rdi
callq 0x186b0
movl %eax, 0x24(%rsp)
cmpl $0x1, 0x24(%rsp)
jle 0x63338
movq 0x8(%rsp), %rdi
movq 0x58(%rsp), %rsi
movl 0x24(%rsp), %edx
callq 0x633b0
orl 0x28(%rsp), %eax
movl %eax, 0x28(%rsp)
jmp 0x6333a
jmp 0x6339a
movq 0x58(%rsp), %rdi
callq 0x5f270
cmpl 0x2c(%rsp), %eax
jge 0x63398
movq 0x58(%rsp), %rdi
callq 0x31660
cltd
idivl 0x54(%rsp)
addl $0x1, %eax
movl %eax, 0x14(%rsp)
movl 0x14(%rsp), %eax
cmpl 0x54(%rsp), %eax
jle 0x63374
movl 0x54(%rsp), %eax
movl %eax, 0x14(%rsp)
cmpl $0x1, 0x14(%rsp)
jle 0x63396
movq 0x8(%rsp), %rdi
movq 0x58(%rsp), %rsi
movl 0x14(%rsp), %edx
callq 0x63dc0
orl 0x28(%rsp), %eax
movl %eax, 0x28(%rsp)
jmp 0x63398
jmp 0x6339a
movl 0x28(%rsp), %eax
addq $0x68, %rsp
retq
nopw %cs:(%rax,%rax)