// File: /workspace/github_cpp_makefile_star2_O2/tomfunkhouser[P]gaps/pkgs/R3Utils/R3Segmentation.cpp
// Function: gaps::R3Segmentation::CreateNeighbors(int, double, double, double, double, double, double, double, int)
int R3Segmentation::
CreateNeighbors(
  int max_neighbor_count,
  double max_neighbor_distance,
  double max_neighbor_primitive_distance,
  double max_neighbor_normal_angle,
  double max_neighbor_color_difference,
  double max_neighbor_distance_factor,
  double max_neighbor_timestamp_difference,
  double max_neighbor_category_difference,
  RNBoolean partition_identifiers)
{
  // Create kdtree of points
  R3SegmentationPoint tmp; int position_offset = (unsigned char *) &(tmp.position) - (unsigned char *) &tmp;
  kdtree = new R3Kdtree<R3SegmentationPoint *>(points, position_offset);
  if (!kdtree) {
    RNFail("Unable to create kdtree\n");
    return 0;
  }
  
  // Create arrays of neighbor points
  for (int i = 0; i < points.NEntries(); i++) {
    R3SegmentationPoint *point = points.Kth(i);

    // Refine maximum distance for this point
    RNScalar max_d = max_neighbor_distance;
    if ((max_neighbor_distance_factor > 0) && (point->radius1 > 0)) 
      max_d = max_neighbor_distance_factor * point->radius1;
    if (max_d == 0) max_d = 10 * point->radius1;
    if (max_d == 0) max_d = 1;

    // Create neighbors
    double min_affinity = 0;
    RNArray<R3SegmentationPoint *> neighbors;
    if (kdtree->FindClosest(point, 0, max_d, max_neighbor_count, neighbors)) {
      for (int j = 0; j < neighbors.NEntries(); j++) {
        R3SegmentationPoint *neighbor = neighbors.Kth(j);
        if (neighbor == point) continue;
        
        // Check identifier
        if (partition_identifiers) {
          if (point->identifier != neighbor->identifier) continue;
        }

        // Compute affinity
        RNScalar affinity = R3SegmentationPointAffinity(point, neighbor,
          max_d, max_neighbor_primitive_distance,
          max_neighbor_normal_angle, max_neighbor_color_difference,
          max_neighbor_timestamp_difference,
          max_neighbor_category_difference, min_affinity);
        if (affinity <= min_affinity) continue;
        
        // Insert neighbor
        if ((max_neighbor_count > 0) &&
            (neighbors.NEntries() - j > max_neighbor_count - point->neighbors.NEntries())) {
          // Find slot for neighbor in list sorted by affinity
          int slot = point->neighbors.NEntries();
          while (slot > 0) {
            RNScalar s_affinity = point->neighbors[slot-1]->cluster_affinity;
            if (s_affinity > affinity) break;
            slot--;
          }
          if (slot < max_neighbor_count) {
            neighbor->cluster_affinity = affinity;
            point->neighbors.InsertKth(neighbor, slot);
            point->neighbors.Truncate(max_neighbor_count);
          }
          if (point->neighbors.NEntries() == max_neighbor_count) {
            min_affinity = point->neighbors[point->neighbors.NEntries()-1]->cluster_affinity;
          }
        }
        else {
          // Insert neighbor at end of unconstrained list
          point->neighbors.Insert(neighbor);
        }
      }
    }
  }

  // Reset cluster affinities
  for (int i = 0; i < points.NEntries(); i++) {
    R3SegmentationPoint *point = points.Kth(i);
    point->cluster_affinity = 0;
  }
  
  // Return success
  return 1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1f8, %rsp            # imm = 0x1F8
movl %edx, 0x34(%rsp)
movsd %xmm6, 0x58(%rsp)
movsd %xmm5, 0xb8(%rsp)
movsd %xmm4, 0x38(%rsp)
movsd %xmm3, 0x98(%rsp)
movsd %xmm2, 0x48(%rsp)
movapd %xmm1, 0x70(%rsp)
movsd %xmm0, 0x40(%rsp)
movl %esi, %ebp
movq %rdi, %rbx
leaq 0x118(%rsp), %rdi
callq 0x2721c
pushq $0x60
popq %rdi
callq 0x15620
movq %rax, %r14
pushq $0x8
popq %rdx
movq %rax, %rdi
movq %rbx, %rsi
callq 0x19f36
movq %r14, 0x10(%rbx)
leaq 0xce8ab(%rip), %rax     # 0xf8aa8
movsd (%rax), %xmm0
movsd %xmm0, 0x90(%rsp)
movl %ebp, %eax
movq %rax, 0x88(%rsp)
movapd 0x70(%rsp), %xmm0
unpcklpd %xmm0, %xmm0            # xmm0 = xmm0[0,0]
movapd %xmm0, 0xe0(%rsp)
xorl %edx, %edx
leaq 0x60(%rsp), %r14
movq %rbx, 0xa0(%rsp)
movslq 0xc(%rbx), %rcx
movq (%rbx), %rax
cmpq %rcx, %rdx
jge 0x2a7cf
movsd 0x38(%rsp), %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
movq (%rax,%rdx,8), %r13
movsd 0x40(%rsp), %xmm2
jbe 0x2a27c
movsd 0x50(%r13), %xmm0
ucomisd %xmm1, %xmm0
movsd 0x40(%rsp), %xmm2
jbe 0x2a27c
mulsd 0x38(%rsp), %xmm0
movapd %xmm0, %xmm2
movapd %xmm2, 0x10(%rsp)
ucomisd %xmm1, %xmm2
jne 0x2a29e
jp 0x2a29e
movsd 0x50(%r13), %xmm0
mulsd 0xc4f80(%rip), %xmm0    # 0xef218
movapd %xmm0, 0x10(%rsp)
movq %rdx, 0xa8(%rsp)
movq %r14, %rdi
callq 0xb1eda
movapd 0x10(%rsp), %xmm3
movapd %xmm3, %xmm2
cmpeqsd 0xc3d87(%rip), %xmm2    # 0xee048
movapd %xmm2, %xmm0
movsd 0xc3d43(%rip), %xmm1    # 0xee010
andpd %xmm1, %xmm0
andnpd %xmm3, %xmm2
orpd %xmm0, %xmm2
movq 0x10(%rbx), %rdi
xorpd %xmm0, %xmm0
movq %r13, %rsi
movapd %xmm2, 0xd0(%rsp)
movapd %xmm2, %xmm1
movl %ebp, %ebx
movl %ebp, %edx
movq %r14, %rcx
xorl %r8d, %r8d
callq 0x2c3ea
testl %eax, %eax
je 0x2a7a8
movapd 0xd0(%rsp), %xmm0
mulsd %xmm0, %xmm0
movsd %xmm0, 0xb0(%rsp)
leaq 0x8(%r13), %rax
movq %rax, 0x28(%rsp)
leaq 0x20(%r13), %rax
movq %rax, 0x50(%rsp)
leaq 0xb0(%r13), %r14
xorpd %xmm0, %xmm0
movsd %xmm0, 0x8(%rsp)
xorl %ebp, %ebp
movslq 0x6c(%rsp), %rax
cmpq %rax, %rbp
jge 0x2a7a8
movq 0x60(%rsp), %rax
movq (%rax,%rbp,8), %r12
cmpq %r13, %r12
je 0x2a750
cmpl $0x0, 0x34(%rsp)
je 0x2a37f
movl 0xa8(%r13), %eax
cmpl 0xa8(%r12), %eax
jne 0x2a750
movsd 0x58(%rsp), %xmm0
ucomisd 0xc3cbb(%rip), %xmm0    # 0xee048
movsd 0xc3c7b(%rip), %xmm0    # 0xee010
movapd %xmm0, 0x10(%rsp)
jbe 0x2a3c0
movl 0x90(%r13), %eax
movsd 0xc3c64(%rip), %xmm0    # 0xee010
movapd %xmm0, 0x10(%rsp)
cmpl 0x90(%r12), %eax
jne 0x2a529
movsd 0xb8(%rsp), %xmm1
ucomisd 0xc3c77(%rip), %xmm1    # 0xee048
jbe 0x2a426
movsd 0x68(%r13), %xmm0
subsd 0x68(%r12), %xmm0
andpd 0xc4108(%rip), %xmm0    # 0xee4f0
xorpd %xmm3, %xmm3
ucomisd %xmm1, %xmm0
ja 0x2a6f2
divsd %xmm1, %xmm0
movsd 0xc3c0e(%rip), %xmm1    # 0xee010
subsd %xmm0, %xmm1
movapd 0x10(%rsp), %xmm2
mulsd %xmm1, %xmm2
movsd 0x8(%rsp), %xmm0
movapd %xmm2, 0x10(%rsp)
ucomisd %xmm2, %xmm0
ja 0x2a6f2
movapd 0xd0(%rsp), %xmm0
ucomisd 0xc3c11(%rip), %xmm0    # 0xee048
jbe 0x2a48f
leaq 0x8(%r12), %rsi
movq 0x28(%rsp), %rdi
callq 0x60e51
xorpd %xmm3, %xmm3
movsd 0xb0(%rsp), %xmm1
ucomisd %xmm1, %xmm0
ja 0x2a6f2
divsd %xmm1, %xmm0
movsd 0xc3ba5(%rip), %xmm1    # 0xee010
subsd %xmm0, %xmm1
movapd 0x10(%rsp), %xmm2
mulsd %xmm1, %xmm2
movsd 0x8(%rsp), %xmm0
movapd %xmm2, 0x10(%rsp)
ucomisd %xmm2, %xmm0
ja 0x2a6f2
movapd 0x70(%rsp), %xmm0
ucomisd 0xc3bab(%rip), %xmm0    # 0xee048
jbe 0x2a5c9
leaq 0xf8(%rsp), %rdi
movq 0x28(%rsp), %rsi
movq 0x50(%rsp), %rdx
callq 0x8f028
leaq 0x8(%r12), %r15
movq %r15, %rdi
leaq 0xf8(%rsp), %rsi
callq 0x61036
movapd %xmm0, 0xc0(%rsp)
xorpd %xmm3, %xmm3
movapd 0xc0(%rsp), %xmm0
ucomisd 0x70(%rsp), %xmm0
ja 0x2a6f2
leaq 0x20(%r12), %rdx
leaq 0xf8(%rsp), %rdi
movq %r15, %rsi
callq 0x8f028
movq 0x28(%rsp), %rdi
leaq 0xf8(%rsp), %rsi
callq 0x61036
ucomisd 0x70(%rsp), %xmm0
jbe 0x2a57b
xorpd %xmm3, %xmm3
jmp 0x2a6f2
movsd 0x98(%r13), %xmm0
minsd 0x98(%r12), %xmm0
xorpd %xmm3, %xmm3
movsd 0x58(%rsp), %xmm1
ucomisd %xmm1, %xmm0
ja 0x2a6f2
divsd %xmm1, %xmm0
movsd 0xc3ab4(%rip), %xmm1    # 0xee010
subsd %xmm0, %xmm1
movsd 0x8(%rsp), %xmm0
movapd %xmm1, 0x10(%rsp)
ucomisd %xmm1, %xmm0
jbe 0x2a3c0
jmp 0x2a6f2
movapd 0xc0(%rsp), %xmm1
unpcklpd %xmm0, %xmm1            # xmm1 = xmm1[0],xmm0[0]
divpd 0xe0(%rsp), %xmm1
movapd 0xc3f67(%rip), %xmm0    # 0xee500
subpd %xmm1, %xmm0
movapd 0x10(%rsp), %xmm1
mulsd %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
mulsd %xmm0, %xmm1
movsd 0x8(%rsp), %xmm0
movapd %xmm1, 0x10(%rsp)
ucomisd %xmm1, %xmm0
xorpd %xmm3, %xmm3
ja 0x2a6f2
movsd 0x48(%rsp), %xmm0
ucomisd 0xc3a71(%rip), %xmm0    # 0xee048
jbe 0x2a662
leaq 0x20(%r12), %rsi
movq 0x50(%rsp), %rdi
callq 0x90dca
movapd %xmm0, %xmm1
ucomisd 0xc49d8(%rip), %xmm0    # 0xeefd0
movsd 0x90(%rsp), %xmm0
jbe 0x2a61e
xorpd %xmm0, %xmm0
movsd 0xc3a01(%rip), %xmm2    # 0xee010
ucomisd %xmm1, %xmm2
jbe 0x2a61e
movapd %xmm1, %xmm0
callq 0x155c0
xorpd %xmm3, %xmm3
movsd 0x48(%rsp), %xmm1
ucomisd %xmm1, %xmm0
ja 0x2a6f2
divsd %xmm1, %xmm0
movsd 0xc39d2(%rip), %xmm1    # 0xee010
subsd %xmm0, %xmm1
movapd 0x10(%rsp), %xmm2
mulsd %xmm1, %xmm2
movsd 0x8(%rsp), %xmm0
movapd %xmm2, 0x10(%rsp)
ucomisd %xmm2, %xmm0
ja 0x2a6f2
movsd 0x98(%rsp), %xmm2
ucomisd 0xc39d5(%rip), %xmm2    # 0xee048
jbe 0x2a6ec
movupd 0x78(%r13), %xmm0
movupd 0x78(%r12), %xmm1
subpd %xmm1, %xmm0
movapd 0xc3e62(%rip), %xmm3    # 0xee4f0
andpd %xmm3, %xmm0
pshufd $0xee, %xmm0, %xmm1     # xmm1 = xmm0[2,3,2,3]
addsd %xmm0, %xmm1
movsd 0x88(%r13), %xmm0
subsd 0x88(%r12), %xmm0
andpd %xmm3, %xmm0
addsd %xmm1, %xmm0
xorpd %xmm3, %xmm3
ucomisd %xmm2, %xmm0
ja 0x2a6f2
divsd %xmm2, %xmm0
movsd 0xc3944(%rip), %xmm1    # 0xee010
subsd %xmm0, %xmm1
movapd 0x10(%rsp), %xmm2
mulsd %xmm1, %xmm2
movsd 0x8(%rsp), %xmm0
ucomisd %xmm2, %xmm0
ja 0x2a6f2
movapd %xmm2, %xmm3
jmp 0x2a6f2
movapd 0x10(%rsp), %xmm3
movsd 0x8(%rsp), %xmm0
ucomisd %xmm3, %xmm0
jae 0x2a750
testl %ebx, %ebx
jle 0x2a745
movl %ebx, %edx
movl 0x6c(%rsp), %ecx
subl %ebp, %ecx
movl 0xbc(%r13), %eax
subl %eax, %edx
cmpl %edx, %ecx
jle 0x2a745
movl %eax, %ecx
sarl $0x1f, %ecx
andl %eax, %ecx
leal 0x1(%rax), %edx
movq %rax, %rsi
testl %esi, %esi
jle 0x2a758
movq (%r14), %rdi
movq -0x8(%rdi,%rsi,8), %rdi
decq %rsi
movsd 0xc8(%rdi), %xmm0
decl %edx
ucomisd %xmm3, %xmm0
jbe 0x2a724
jmp 0x2a75a
movq %r14, %rdi
movq %r12, %rsi
callq 0x1a04c
incq %rbp
jmp 0x2a343
movl %ecx, %edx
cmpl %ebx, %edx
jge 0x2a784
movsd %xmm3, 0xc8(%r12)
movq %r14, %rdi
movq %r12, %rsi
callq 0xb1f78
movq %r14, %rdi
movl %ebx, %esi
callq 0xb2124
movl 0xbc(%r13), %eax
cmpl %ebx, %eax
jne 0x2a750
movq (%r14), %rax
movq 0x88(%rsp), %rcx
movq -0x8(%rax,%rcx,8), %rax
movsd 0xc8(%rax), %xmm0
movsd %xmm0, 0x8(%rsp)
jmp 0x2a750
leaq 0x60(%rsp), %r14
movq %r14, %rdi
callq 0xb1f48
movq 0xa8(%rsp), %rdx
incq %rdx
movl %ebx, %ebp
movq 0xa0(%rsp), %rbx
jmp 0x2a236
xorl %edx, %edx
testl %ecx, %ecx
cmovlel %edx, %ecx
cmpq %rdx, %rcx
je 0x2a7ec
movq (%rax,%rdx,8), %rsi
andq $0x0, 0xc8(%rsi)
incq %rdx
jmp 0x2a7d6
leaq 0x1c8(%rsp), %rdi
callq 0xb1f48
pushq $0x1
popq %rax
addq $0x1f8, %rsp            # imm = 0x1F8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
pushq $0x60
popq %rsi
movq %r14, %rdi
callq 0x15630
jmp 0x2a836
jmp 0x2a820
movq %rax, %rbx
jmp 0x2a836
jmp 0x2a829
jmp 0x2a829
movq %rax, %rbx
leaq 0x60(%rsp), %rdi
callq 0xb1f48
leaq 0x1c8(%rsp), %rdi
callq 0xb1f48
movq %rbx, %rdi
callq 0x15af0
nop