// File: tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelUtils.cpp
// Function: gaps::CreatePointSet(gaps::R3SurfelScene*, gaps::R3Point&, double, double, double, double, double, double, int)
R3SurfelPointSet *
CreatePointSet(R3SurfelScene *scene, R3Point& origin, 
  RNLength max_radius, RNLength min_height, RNLength max_height, RNLength max_spacing,
  RNVolume min_volume, RNVolume max_volume, int min_points)
{
  // Check origin Z coordinate
  R3SurfelPointSet *surfels2 = NULL;
  if (origin.Z() == RN_UNKNOWN) {
    // Extract points within XY radius
    R3SurfelCylinderConstraint cylinder_constraint(origin, max_radius);
    R3SurfelPointSet *surfels1 = CreatePointSet(scene, NULL, &cylinder_constraint);
    if (!surfels1) return NULL;
    
    // Check minimum number of points
    if ((min_points > 0) && (surfels1->NPoints() < min_points)) {
      delete surfels1;
      return NULL;
    }
    
    // Compute support plane
    RNScalar support_count = 0;
    R3Plane support_plane = EstimateSupportPlane(surfels1, 0.1, &support_count);

    // Move origin to support plane
    if ((support_count > 16) && (fabs(support_plane[2]) > 0.5)) {
      RNScalar support_z = -(origin[0]*support_plane[0] + origin[1]*support_plane[1] + support_plane[3]) / support_plane[2];
      origin[2] = support_z;
    }
    else {
      origin[2] = surfels1->BBox().ZMin();
    }

    // Remove points that are too low or too high
    R3SurfelCylinderConstraint z_constraint(origin, max_radius, origin[2] + min_height, origin[2] + max_height);
    surfels2 = CreatePointSet(surfels1, &z_constraint);
    delete surfels1;
    if (!surfels2) return NULL;
  }
  else {
    // Extract points with cylinder
    R3SurfelCylinderConstraint cylinder_constraint(origin, max_radius, origin[2] + min_height, origin[2] + max_height);
    surfels2 = CreatePointSet(scene, NULL, &cylinder_constraint);
    if (!surfels2) return NULL;
  }

  // Check minimum number of points
  if ((min_points > 0) && (surfels2->NPoints() < min_points)) {
    delete surfels2;
    return NULL;
  }

  // Remove points that are not connected
  R3SurfelPointSet *surfels3 = surfels2;
  if (max_spacing > 0) {
    surfels3 = CreateConnectedPointSet(surfels2, origin, max_radius,
      min_height, max_height, min_volume, max_volume, max_spacing, 256);
    delete surfels2;
    if (!surfels3) return NULL;
  }
  
  // Check minimum number of points
  if ((min_points > 0) && (surfels3->NPoints() < min_points)) {
    delete surfels3;
    return NULL;
  }

  // Return pointset
  return surfels3;
}

// Assembly:
subq $0x278, %rsp            # imm = 0x278
movq %rdi, 0x268(%rsp)
movq %rsi, 0x260(%rsp)
movsd %xmm0, 0x258(%rsp)
movsd %xmm1, 0x250(%rsp)
movsd %xmm2, 0x248(%rsp)
movsd %xmm3, 0x240(%rsp)
movsd %xmm4, 0x238(%rsp)
movsd %xmm5, 0x230(%rsp)
movl %edx, 0x22c(%rsp)
movq $0x0, 0x220(%rsp)
movq 0x260(%rsp), %rdi
callq 0x187a0
movsd 0x171c7b(%rip), %xmm1   # 0x1a4180
ucomisd %xmm1, %xmm0
jne 0x32a46
jp 0x32a46
movq 0x260(%rsp), %rsi
movsd 0x258(%rsp), %xmm0
leaq 0x1e8(%rsp), %rdi
movq %rdi, 0x118(%rsp)
movsd 0x171c4a(%rip), %xmm1   # 0x1a4188
movsd 0x171c4a(%rip), %xmm2   # 0x1a4190
callq 0x50f30
movq 0x118(%rsp), %rdx
movq 0x268(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x32220
movq %rax, 0x120(%rsp)
jmp 0x3256e
movq 0x120(%rsp), %rax
movq %rax, 0x1e0(%rsp)
cmpq $0x0, 0x1e0(%rsp)
jne 0x325be
movq $0x0, 0x270(%rsp)
movl $0x1, 0x1d0(%rsp)
jmp 0x32a10
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1d8(%rsp)
movl %eax, 0x1d4(%rsp)
jmp 0x32a34
cmpl $0x0, 0x22c(%rsp)
jle 0x3262e
movq 0x1e0(%rsp), %rdi
callq 0x18700
movl %eax, 0x114(%rsp)
jmp 0x325de
movl 0x114(%rsp), %eax
cmpl 0x22c(%rsp), %eax
jge 0x3262e
movq 0x1e0(%rsp), %rax
movq %rax, 0x108(%rsp)
cmpq $0x0, %rax
je 0x32612
movq 0x108(%rsp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
movq $0x0, 0x270(%rsp)
movl $0x1, 0x1d0(%rsp)
jmp 0x32a10
movq $0x0, 0x1c8(%rsp)
movq 0x1e0(%rsp), %rsi
leaq 0x1a8(%rsp), %rdi
movsd 0x171d46(%rip), %xmm0   # 0x1a4398
leaq 0x1c8(%rsp), %rdx
callq 0x32cf0
jmp 0x32661
movsd 0x1c8(%rsp), %xmm0
movsd 0x171ade(%rip), %xmm1   # 0x1a4150
ucomisd %xmm1, %xmm0
jbe 0x32872
leaq 0x1a8(%rsp), %rdi
movl $0x2, %esi
callq 0x43580
movq %rax, 0x100(%rsp)
jmp 0x32698
movq 0x100(%rsp), %rax
movsd (%rax), %xmm0
movaps 0x171d15(%rip), %xmm1   # 0x1a43c0
pand %xmm1, %xmm0
movsd 0x171aa1(%rip), %xmm1   # 0x1a4158
ucomisd %xmm1, %xmm0
jbe 0x32872
movq 0x260(%rsp), %rdi
xorl %esi, %esi
callq 0x1bde0
movq %rax, 0xf8(%rsp)
jmp 0x326da
movq 0xf8(%rsp), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0xe8(%rsp)
leaq 0x1a8(%rsp), %rdi
xorl %esi, %esi
callq 0x43580
movq %rax, 0xf0(%rsp)
jmp 0x32708
movq 0xf0(%rsp), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0xd8(%rsp)
movq 0x260(%rsp), %rdi
movl $0x1, %esi
callq 0x1bde0
movq %rax, 0xe0(%rsp)
jmp 0x32739
movq 0xe0(%rsp), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0xc8(%rsp)
leaq 0x1a8(%rsp), %rdi
movl $0x1, %esi
callq 0x43580
movq %rax, 0xd0(%rsp)
jmp 0x3276a
movsd 0xd8(%rsp), %xmm2
movsd 0xe8(%rsp), %xmm0
movsd 0xc8(%rsp), %xmm1
movq 0xd0(%rsp), %rax
movsd (%rax), %xmm3
mulsd %xmm3, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xb8(%rsp)
leaq 0x1a8(%rsp), %rdi
movl $0x3, %esi
callq 0x43580
movq %rax, 0xc0(%rsp)
jmp 0x327c2
movsd 0xb8(%rsp), %xmm0
movq 0xc0(%rsp), %rax
movsd (%rax), %xmm1
addsd %xmm1, %xmm0
movaps 0x17233e(%rip), %xmm1   # 0x1a4b20
pxor %xmm1, %xmm0
movsd %xmm0, 0xa8(%rsp)
leaq 0x1a8(%rsp), %rdi
movl $0x2, %esi
callq 0x43580
movq %rax, 0xb0(%rsp)
jmp 0x3280b
movsd 0xa8(%rsp), %xmm0
movq 0xb0(%rsp), %rax
movsd (%rax), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x1a0(%rsp)
movsd 0x1a0(%rsp), %xmm0
movsd %xmm0, 0x98(%rsp)
movq 0x260(%rsp), %rdi
movl $0x2, %esi
callq 0x1bde0
movq %rax, 0xa0(%rsp)
jmp 0x3285b
movq 0xa0(%rsp), %rax
movsd 0x98(%rsp), %xmm0
movsd %xmm0, (%rax)
jmp 0x328d2
movq 0x1e0(%rsp), %rdi
callq 0x435d0
movq %rax, 0x90(%rsp)
jmp 0x32889
movq 0x90(%rsp), %rdi
callq 0x435e0
movsd %xmm0, 0x88(%rsp)
jmp 0x328a1
movq 0x260(%rsp), %rdi
movl $0x2, %esi
callq 0x1bde0
movq %rax, 0x80(%rsp)
jmp 0x328bd
movq 0x80(%rsp), %rax
movsd 0x88(%rsp), %xmm0
movsd %xmm0, (%rax)
movq 0x260(%rsp), %rdi
movq %rdi, 0x68(%rsp)
movsd 0x258(%rsp), %xmm0
movsd %xmm0, 0x70(%rsp)
movl $0x2, %esi
callq 0x1bde0
movq %rax, 0x78(%rsp)
jmp 0x328ff
movq 0x78(%rsp), %rax
movsd (%rax), %xmm0
movsd 0x250(%rsp), %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, 0x58(%rsp)
movq 0x260(%rsp), %rdi
movl $0x2, %esi
callq 0x1bde0
movq %rax, 0x60(%rsp)
jmp 0x32934
movsd 0x58(%rsp), %xmm1
movsd 0x70(%rsp), %xmm0
movq 0x68(%rsp), %rsi
movq 0x60(%rsp), %rax
movsd (%rax), %xmm2
movsd 0x248(%rsp), %xmm3
addsd %xmm3, %xmm2
leaq 0x168(%rsp), %rdi
callq 0x50f30
jmp 0x3296a
movq 0x1e0(%rsp), %rdi
leaq 0x168(%rsp), %rsi
callq 0x32140
movq %rax, 0x50(%rsp)
jmp 0x32986
movq 0x50(%rsp), %rax
movq %rax, 0x220(%rsp)
movq 0x1e0(%rsp), %rax
movq %rax, 0x48(%rsp)
cmpq $0x0, %rax
je 0x329b1
movq 0x48(%rsp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
cmpq $0x0, 0x220(%rsp)
jne 0x329f8
movq $0x0, 0x270(%rsp)
movl $0x1, 0x1d0(%rsp)
jmp 0x32a03
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1d8(%rsp)
movl %eax, 0x1d4(%rsp)
leaq 0x168(%rsp), %rdi
callq 0x43600
jmp 0x32a34
movl $0x0, 0x1d0(%rsp)
leaq 0x168(%rsp), %rdi
callq 0x43600
leaq 0x1e8(%rsp), %rdi
callq 0x43600
movl 0x1d0(%rsp), %eax
testl %eax, %eax
je 0x32a2f
jmp 0x32a2a
jmp 0x32ccc
jmp 0x32b6c
leaq 0x1e8(%rsp), %rdi
callq 0x43600
jmp 0x32cdc
movq 0x260(%rsp), %rdi
movq %rdi, 0x20(%rsp)
movsd 0x258(%rsp), %xmm0
movsd %xmm0, 0x28(%rsp)
movl $0x2, %esi
movl %esi, 0x1c(%rsp)
callq 0x1bde0
movl 0x1c(%rsp), %esi
movsd (%rax), %xmm0
movsd 0x250(%rsp), %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, 0x30(%rsp)
movq 0x260(%rsp), %rdi
callq 0x1bde0
movq 0x20(%rsp), %rsi
movsd 0x28(%rsp), %xmm0
movsd 0x30(%rsp), %xmm1
movsd (%rax), %xmm2
movsd 0x248(%rsp), %xmm3
addsd %xmm3, %xmm2
leaq 0x130(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x50f30
movq 0x38(%rsp), %rdx
movq 0x268(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x32220
movq %rax, 0x40(%rsp)
jmp 0x32ae9
movq 0x40(%rsp), %rax
movq %rax, 0x220(%rsp)
cmpq $0x0, 0x220(%rsp)
jne 0x32b40
movq $0x0, 0x270(%rsp)
movl $0x1, 0x1d0(%rsp)
jmp 0x32b4b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1d8(%rsp)
movl %eax, 0x1d4(%rsp)
leaq 0x130(%rsp), %rdi
callq 0x43600
jmp 0x32cdc
movl $0x0, 0x1d0(%rsp)
leaq 0x130(%rsp), %rdi
callq 0x43600
movl 0x1d0(%rsp), %eax
testl %eax, %eax
je 0x32b6a
jmp 0x32b65
jmp 0x32ccc
jmp 0x32b6c
cmpl $0x0, 0x22c(%rsp)
jle 0x32bbb
movq 0x220(%rsp), %rdi
callq 0x18700
cmpl 0x22c(%rsp), %eax
jge 0x32bbb
movq 0x220(%rsp), %rax
movq %rax, 0x10(%rsp)
cmpq $0x0, %rax
je 0x32baa
movq 0x10(%rsp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
movq $0x0, 0x270(%rsp)
jmp 0x32ccc
movq 0x220(%rsp), %rax
movq %rax, 0x128(%rsp)
movsd 0x240(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x32c72
movq 0x220(%rsp), %rdi
movq 0x260(%rsp), %rsi
movsd 0x258(%rsp), %xmm0
movsd 0x250(%rsp), %xmm1
movsd 0x248(%rsp), %xmm2
movsd 0x238(%rsp), %xmm3
movsd 0x230(%rsp), %xmm4
movsd 0x240(%rsp), %xmm5
movl $0x100, %edx            # imm = 0x100
callq 0x332f0
movq %rax, 0x128(%rsp)
movq 0x220(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x32c57
movq 0x8(%rsp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
cmpq $0x0, 0x128(%rsp)
jne 0x32c70
movq $0x0, 0x270(%rsp)
jmp 0x32ccc
jmp 0x32c72
cmpl $0x0, 0x22c(%rsp)
jle 0x32cbc
movq 0x128(%rsp), %rdi
callq 0x18700
cmpl 0x22c(%rsp), %eax
jge 0x32cbc
movq 0x128(%rsp), %rax
movq %rax, (%rsp)
cmpq $0x0, %rax
je 0x32cae
movq (%rsp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
movq $0x0, 0x270(%rsp)
jmp 0x32ccc
movq 0x128(%rsp), %rax
movq %rax, 0x270(%rsp)
movq 0x270(%rsp), %rax
addq $0x278, %rsp            # imm = 0x278
retq
movq 0x1d8(%rsp), %rdi
callq 0x13970
nopl (%rax)