369 void * coords_data,
size_t coords_size,
size_t coords_count,
373 double balance_point[3] = {0.0,0.0,0.0};
376 for (
size_t i = 0; i < coords_count; ++i) {
379 (
double*)(((
unsigned char*)coords_data) + i * coords_size);
380 balance_point[0] += coords[0];
381 balance_point[1] += coords[1];
382 balance_point[2] += coords[2];
385 if ((fabs(balance_point[0]) > 1e-9) ||
386 (fabs(balance_point[1]) > 1e-9) ||
387 (fabs(balance_point[2]) > 1e-9)) {
390 balance_point[0] = prev_gc_norm_vector[2];
391 balance_point[1] = prev_gc_norm_vector[0];
392 balance_point[2] = prev_gc_norm_vector[1];
418 for (
size_t j = begin; j < end; ++j)
432 size_t I_begin = I_FULL_size;
433 size_t U_begin = I_FULL_size + I_size;
434 size_t T_begin = I_FULL_size + I_size + U_size;
436 size_t I_end = I_begin + I_size;
437 size_t U_end = U_begin + U_size;
438 size_t T_end = T_begin + T_size;
440 while (I_end > I_begin && part_data[I_end-1].
node_type ==
I_NODE) I_end--;
441 while (U_end > U_begin && part_data[U_end-1].
node_type ==
U_NODE) U_end--;
442 while (T_end > T_begin && part_data[T_end-1].
node_type ==
T_NODE) T_end--;
444 for (
size_t i = 0; i < I_FULL_size; ++i)
452 I_begin = I_FULL_size;
453 for (
size_t i = I_begin; i < I_end; ++i)
465 U_begin = I_FULL_size + I_size;
466 T_begin = I_FULL_size + I_size + U_size;
467 for (
size_t i = U_begin; i < U_end; ++i)
478 size_t num_cell_ids,
size_t threshold,
struct sphere_part_node * parent_node,
479 double prev_gc_norm_vector[]) {
481 if (num_cell_ids == 0) {
487 part_data,
sizeof(*part_data), num_cell_ids,
493 size_t I_FULL_size = 0;
500 for (
size_t i = 0; i < num_cell_ids; ++i) {
538 max_inc_angle = inc_angle;
542 }
else if (angle.
cos < 0.0) {
558 I_size += I_FULL_size;
559 parent_node->
I_size = I_size;
560 parent_node->
U_size = U_size;
561 parent_node->
T_size = T_size;
567 parent_node->
I_angle = max_inc_angle;
581 for (
size_t i = 0; i < I_FULL_size; ++i) {
588 for (
size_t i = I_FULL_size; i < I_size; ++i) {
590 double GCp[3], bVp[3];
599 (fabs(bVp[0]) > 1e-9) || (fabs(bVp[1]) > 1e-9) ||
600 (fabs(bVp[2]) > 1e-9),
601 "projected vector is nearly identical to gc_norm_vector")
612 double bnd_circle_lat_cos =
615 M_PI_2 - acos(curr_bnd_circle.
inc_angle.
sin/bnd_circle_lat_cos);
632 for (
size_t i = 0; i < I_size; ++i)
633 local_cell_ids[i] = part_data[i].local_id;
634 parent_node->
I.
list = (
void*)local_cell_ids;
637 parent_node->
I.
list = NULL;
640 local_cell_ids += I_size;
643 if (U_size <= threshold) {
645 for (
size_t i = 0; i < U_size; ++i)
646 local_cell_ids[i] = part_data[i].local_id;
647 parent_node->
U = (
void*)local_cell_ids;
656 local_cell_ids += U_size;
659 if (T_size <= threshold) {
661 for (
size_t i = 0; i < T_size; ++i)
662 local_cell_ids[i] = part_data[i].local_id;
663 parent_node->
T = (
void*)local_cell_ids;
665 local_cell_ids += T_size;
681 struct point_id_xyz * points,
size_t num_points,
size_t threshold,
682 double prev_gc_norm_vector[],
size_t curr_tree_depth,
683 size_t * max_tree_depth,
int * list_flag) {
685 if (curr_tree_depth > *max_tree_depth) *max_tree_depth = curr_tree_depth;
691 points,
sizeof(*points), num_points, prev_gc_norm_vector,
gc_norm_vector);
702 for (
size_t i = 0; i < num_points; ++i) {
703 double * curr_coordinates_xyz = &(points[i].coordinates_xyz[0]);
709 list_flag[i] = (dot <= 0.0);
713 for (
size_t i = 0; i < num_points; ++i) {
714 if (list_flag[i]) ++
U_size;
728 for (;!list_flag[j];++j);
730 points[i] = points[j];
731 points[j] = temp_point;
741 if ((U_size <= threshold) || (U_size == num_points)) {
751 points, U_size, threshold, gc_norm_vector,
752 curr_tree_depth + 1, max_tree_depth, list_flag);
755 if ((T_size <= threshold) || (T_size == num_points)) {
757 node->
T = points + U_size;
765 points + U_size, T_size, threshold, gc_norm_vector,
766 curr_tree_depth + 1, max_tree_depth, list_flag);
777 double gc_norm_vector[3] = {0.0,0.0,1.0};
785 xmalloc(num_circles *
sizeof(*part_data));
786 for (
size_t i = 0; i < num_circles; ++i) {
800 const void * a,
const void * b) {
807 for (
int i = 0; i < 3; ++i)
820 xmalloc(*num_points *
sizeof(*points_int32));
822 double const scale = (double)(2 << 21);
824 size_t num_unmasked_points;
827 num_unmasked_points = *num_points;
828 for (
size_t i = 0; i < num_unmasked_points; ++i) {
830 points_int32[i].
idx = i;
831 for (
size_t j = 0; j < 3; ++j)
833 (int32_t)round(coordinates_xyz[i][j] * scale);
836 num_unmasked_points = 0;
837 for (
size_t i = 0; i < *num_points; ++i) {
839 if (!
mask[i])
continue;
840 points_int32[num_unmasked_points].
idx = i;
841 for (
size_t j = 0; j < 3; ++j)
843 (int32_t)round(coordinates_xyz[i][j] * scale);
844 num_unmasked_points++;
849 qsort(points_int32, num_unmasked_points,
853 dummy.
idx = SIZE_MAX;
859 size_t new_num_points = 0;
860 for (
size_t i = 0; i < num_unmasked_points; ++i, ++curr) {
862 size_t curr_idx = curr->
idx;
864 prev = points_int32 + new_num_points++;
865 if (prev != curr) *prev = *curr;
866 prev_id = ids[curr_idx];
868 yac_int curr_id = ids[curr_idx];
869 if (curr_id > prev_id) {
871 prev->
idx = curr_idx;
877 for (
size_t i = 0; i < new_num_points; ++i) {
878 size_t curr_idx = points_int32[i].
idx;
879 points[i].idx = curr_idx;
883 *num_points = new_num_points;
892 if (num_points == 0)
return NULL;
899 size_t max_tree_depth = 0;
901 int * list_flag =
xmalloc(num_points *
sizeof(*list_flag));
907 1, &max_tree_depth, list_flag);
922 if (num_points == 0)
return NULL;
932 int * list_flag =
xmalloc(num_points *
sizeof(*list_flag));
938 (
double[3]){0.0,0.0,1.0}, 1, &max_tree_depth, list_flag);
951 size_t ** restrict overlap_cells,
size_t * overlap_cells_array_size,
952 size_t * restrict num_overlap_cells,
953 struct overlaps * search_interval_tree_buffer,
double prev_gc_norm_vector[]) {
960 angle.
cos = fabs(angle.
cos);
967 (*overlap_cells)[(*num_overlap_cells)+i] =
973 double GCp[3], bVp[3];
980 (fabs(bVp[0]) > 1e-9) || (fabs(bVp[1]) > 1e-9) || (fabs(bVp[2]) > 1e-9),
981 "projected vector is nearly identical to gc_norm_vector")
987 double bnd_circle_lat_cos =
990 M_PI_2 - acos(bnd_circle.
inc_angle.
sin/bnd_circle_lat_cos);
1000 .left = base_angle - inc_angle,
1001 .right = base_angle + inc_angle},
1002 search_interval_tree_buffer);
1005 *num_overlap_cells +
1008 for (
size_t i = 0; i < search_interval_tree_buffer->
num_overlaps; ++i)
1009 (*overlap_cells)[(*num_overlap_cells)+i] =
1013 *num_overlap_cells += search_interval_tree_buffer->
num_overlaps;
1018 *num_overlap_cells + node->
I_size);
1019 memcpy(*overlap_cells + *num_overlap_cells, node->
I.
list,
1020 node->
I_size *
sizeof(**overlap_cells));
1021 *num_overlap_cells += node->
I_size;
1028 size_t ** restrict overlap_cells,
size_t * overlap_cells_array_size,
1029 size_t * restrict num_overlap_cells,
1030 struct overlaps * search_interval_tree_buffer,
double prev_gc_norm_vector[]) {
1035 *num_overlap_cells + node->
T_size);
1036 memcpy(*overlap_cells + *num_overlap_cells, node->
T,
1037 node->
T_size *
sizeof(**overlap_cells));
1038 *num_overlap_cells += node->
T_size;
1042 node->
T, bnd_circle, overlap_cells, overlap_cells_array_size,
1043 num_overlap_cells, search_interval_tree_buffer, node->
gc_norm_vector);
1049 *num_overlap_cells + node->
U_size);
1050 memcpy(*overlap_cells + *num_overlap_cells, node->
U,
1051 node->
U_size *
sizeof(**overlap_cells));
1052 *num_overlap_cells += node->
U_size;
1056 node->
U, bnd_circle, overlap_cells, overlap_cells_array_size,
1057 num_overlap_cells, search_interval_tree_buffer, node->
gc_norm_vector);
1061 node, bnd_circle, overlap_cells, overlap_cells_array_size,
1062 num_overlap_cells, search_interval_tree_buffer, prev_gc_norm_vector);
1067 size_t ** restrict overlap_cells,
size_t * overlap_cells_array_size,
1068 size_t * restrict num_overlap_cells,
1069 struct overlaps * search_interval_tree_buffer,
double prev_gc_norm_vector[]) {
1081 *num_overlap_cells + node->
T_size);
1082 memcpy(*overlap_cells + *num_overlap_cells, node->
T,
1083 node->
T_size *
sizeof(**overlap_cells));
1084 *num_overlap_cells += node->
T_size;
1088 node->
T, bnd_circle, overlap_cells, overlap_cells_array_size,
1089 num_overlap_cells, search_interval_tree_buffer,
1100 *num_overlap_cells + node->
U_size);
1101 memcpy(*overlap_cells + *num_overlap_cells, node->
U,
1102 node->
U_size *
sizeof(**overlap_cells));
1103 *num_overlap_cells += node->
U_size;
1107 node->
U, bnd_circle, overlap_cells, overlap_cells_array_size,
1108 num_overlap_cells, search_interval_tree_buffer,
1133 if (((angle_sum.
sin < 0.0) || (angle_sum.
cos <= 0.0)) ||
1134 (fabs(dot) <= angle_sum.
sin)) {
1136 node, bnd_circle, overlap_cells, overlap_cells_array_size,
1137 num_overlap_cells, search_interval_tree_buffer, prev_gc_norm_vector);
1143 size_t ** restrict overlap_cells,
1144 size_t * overlap_cells_array_size,
1145 size_t * restrict num_overlap_cells,
1146 struct overlaps * search_interval_tree_buffer,
1147 double prev_gc_norm_vector[]) {
1152 node, bnd_circle, overlap_cells, overlap_cells_array_size,
1153 num_overlap_cells, search_interval_tree_buffer, prev_gc_norm_vector);
1156 node, bnd_circle, overlap_cells, overlap_cells_array_size,
1157 num_overlap_cells, search_interval_tree_buffer, prev_gc_norm_vector);
1162 double * point_coordinates_xyz,
struct sin_cos_angle * best_angle,
1163 double (**result_coordinates_xyz)[3],
1164 size_t * result_coordinates_xyz_array_size,
size_t ** local_point_ids,
1165 size_t * local_point_ids_array_size,
size_t total_num_local_point_ids,
1166 size_t * num_local_point_ids) {
1168 size_t * local_point_ids_ = *local_point_ids;
1169 size_t local_point_ids_array_size_ = *local_point_ids_array_size;
1170 double (*result_coordinates_xyz_)[3];
1171 size_t result_coordinates_xyz_array_size_;
1172 size_t num_local_point_ids_ = *num_local_point_ids;
1174 if (result_coordinates_xyz != NULL) {
1175 result_coordinates_xyz_ = *result_coordinates_xyz;
1176 result_coordinates_xyz_array_size_ = *result_coordinates_xyz_array_size;
1178 result_coordinates_xyz_, result_coordinates_xyz_array_size_,
1179 total_num_local_point_ids + num_local_point_ids_ + num_points);
1180 *result_coordinates_xyz = result_coordinates_xyz_;
1181 *result_coordinates_xyz_array_size = result_coordinates_xyz_array_size_;
1182 result_coordinates_xyz_ += total_num_local_point_ids;
1185 local_point_ids_, local_point_ids_array_size_,
1186 total_num_local_point_ids + num_local_point_ids_ + num_points);
1187 *local_point_ids = local_point_ids_;
1188 *local_point_ids_array_size = local_point_ids_array_size_;
1189 local_point_ids_ += total_num_local_point_ids;
1193 for (
size_t i = 0; i < num_points; ++i) {
1197 points[i].coordinates_xyz, point_coordinates_xyz);
1201 if (compare > 0)
continue;
1206 *best_angle = curr_angle;
1207 num_local_point_ids_ = 1;
1208 if (result_coordinates_xyz != NULL) {
1209 result_coordinates_xyz_[0][0] = points[i].coordinates_xyz[0];
1210 result_coordinates_xyz_[0][1] = points[i].coordinates_xyz[1];
1211 result_coordinates_xyz_[0][2] = points[i].coordinates_xyz[2];
1213 local_point_ids_[0] = points[i].idx;
1218 if (result_coordinates_xyz != NULL) {
1219 result_coordinates_xyz_[num_local_point_ids_][0] =
1220 points[i].coordinates_xyz[0];
1221 result_coordinates_xyz_[num_local_point_ids_][1] =
1222 points[i].coordinates_xyz[1];
1223 result_coordinates_xyz_[num_local_point_ids_][2] =
1224 points[i].coordinates_xyz[2];
1226 local_point_ids_[num_local_point_ids_] = points[i].idx;
1227 num_local_point_ids_++;
1231 *num_local_point_ids = num_local_point_ids_;
1235 struct bounding_circle * bnd_circle,
double (**result_coordinates_xyz)[3],
1236 size_t * result_coordinates_xyz_array_size,
size_t ** local_point_ids,
1237 size_t * local_point_ids_array_size,
size_t total_num_local_point_ids,
1238 size_t * num_local_point_ids,
double * dot_stack,
1240 int * flags,
size_t curr_tree_depth) {
1242 double * point_coordinates_xyz = bnd_circle->
base_vector;
1245 double dot = dot_stack[curr_tree_depth];
1257 if ((dot < best_angle.
sin) | (best_angle.
cos <= 0.0)) {
1263 point_coordinates_xyz, &best_angle, result_coordinates_xyz,
1264 result_coordinates_xyz_array_size, local_point_ids,
1265 local_point_ids_array_size, total_num_local_point_ids,
1266 num_local_point_ids);
1276 dot_stack[curr_tree_depth] = dot;
1277 node_stack[curr_tree_depth] = node;
1278 flags[curr_tree_depth] = 0;
1291 if ((dot > - best_angle.
sin) || (best_angle.
cos <= 0.0)) {
1297 point_coordinates_xyz, &best_angle, result_coordinates_xyz,
1298 result_coordinates_xyz_array_size, local_point_ids,
1299 local_point_ids_array_size, total_num_local_point_ids,
1300 num_local_point_ids);
1310 dot_stack[curr_tree_depth] = dot;
1311 node_stack[curr_tree_depth] = node;
1312 flags[curr_tree_depth] = 0;
1320 if (curr_tree_depth == 0)
break;
1325 dot = dot_stack[curr_tree_depth];
1326 node = node_stack[curr_tree_depth];
1337 struct point_id_xyz * points,
size_t num_points,
double coordinate_xyz[3],
1338 size_t ** local_point_ids,
size_t * local_point_ids_array_size,
1339 double (**result_coordinates_xyz)[3],
1340 size_t * result_coordinates_xyz_array_size,
1341 size_t total_num_local_point_ids,
size_t * num_local_point_ids) {
1343 for (
size_t i = 0; i < num_points; ++i) {
1349 total_num_local_point_ids + 1);
1350 (*local_point_ids)[total_num_local_point_ids] = points[i].idx;
1351 if (result_coordinates_xyz != NULL) {
1353 *result_coordinates_xyz_array_size,
1354 total_num_local_point_ids + 1);
1355 memcpy((*result_coordinates_xyz) + total_num_local_point_ids,
1356 points[i].coordinates_xyz, 3 *
sizeof(
double));
1358 *num_local_point_ids = 1;
1368 double (*coordinates_xyz)[3],
1369 double * cos_angles,
1370 double (**result_coordinates_xyz)[3],
1371 size_t * result_coordinates_xyz_array_size,
1372 size_t ** local_point_ids,
1373 size_t * local_point_ids_array_size,
1374 size_t * num_local_point_ids) {
1376 memset(num_local_point_ids, 0, num_points *
sizeof(*num_local_point_ids));
1378 if (search == NULL)
return;
1382 size_t total_num_local_point_ids = 0;
1389 for (
size_t i = 0; i < num_points; ++i) {
1393 double * curr_coordinates_xyz = coordinates_xyz[i];
1395 size_t curr_tree_depth = 0;
1397 size_t curr_num_points = 0;
1402 double dot = curr_node->
gc_norm_vector[0]*curr_coordinates_xyz[0] +
1406 dot_stack[curr_tree_depth] = dot;
1407 node_stack[curr_tree_depth] = curr_node;
1408 flags[curr_tree_depth] = 0;
1413 flags[curr_tree_depth] =
U_FLAG;
1416 if (curr_node->
U_size > 0) {
1418 curr_num_points = curr_node->
U_size;
1421 flags[curr_tree_depth] =
T_FLAG;
1424 "if one branch is empty, the other has to be a leaf");
1426 curr_num_points = curr_node->
T_size;
1429 }
else curr_node = curr_node->
U;
1434 flags[curr_tree_depth] =
T_FLAG;
1437 if (curr_node->
T_size > 0) {
1439 curr_num_points = curr_node->
T_size;
1442 flags[curr_tree_depth] =
U_FLAG;
1445 "if one branch is empty, the other has to be a leaf");
1447 curr_num_points = curr_node->
U_size;
1450 }
else curr_node = curr_node->
T;
1458 points, curr_num_points, curr_coordinates_xyz, local_point_ids,
1459 local_point_ids_array_size, result_coordinates_xyz,
1460 result_coordinates_xyz_array_size, total_num_local_point_ids,
1461 num_local_point_ids + i)) {
1463 if (cos_angles != NULL) cos_angles[i] = 1.0;
1468 bnd_circle.
base_vector[0] = curr_coordinates_xyz[0];
1469 bnd_circle.
base_vector[1] = curr_coordinates_xyz[1];
1470 bnd_circle.
base_vector[2] = curr_coordinates_xyz[2];
1472 bnd_circle.
sq_crd = DBL_MAX;
1475 points, curr_num_points, curr_coordinates_xyz, &bnd_circle.
inc_angle,
1476 result_coordinates_xyz, result_coordinates_xyz_array_size,
1477 local_point_ids, local_point_ids_array_size, total_num_local_point_ids,
1478 num_local_point_ids + i);
1482 &bnd_circle, result_coordinates_xyz, result_coordinates_xyz_array_size,
1483 local_point_ids, local_point_ids_array_size, total_num_local_point_ids,
1484 num_local_point_ids + i, dot_stack, node_stack, flags, curr_tree_depth);
1486 if (cos_angles != NULL) cos_angles[i] = bnd_circle.
inc_angle.
cos;
1489 total_num_local_point_ids += num_local_point_ids[i];
1505 if (ret != 0)
return ret;
1511 size_t n,
struct point_id_xyz * points,
size_t num_points,
1513 size_t * results_array_size) {
1515 assert(num_points > 0);
1528#pragma _NEC novector
1530 for (
size_t i = 0; i < num_points; ++i) {
1532 results_[i].
point = points[i];
1534 points[i].coordinates_xyz[0] * point_coordinates_xyz[0] +
1535 points[i].coordinates_xyz[1] * point_coordinates_xyz[1] +
1536 points[i].coordinates_xyz[2] * point_coordinates_xyz[2]);
1541 if (num_points <= n)
return num_points;
1544 double min_cos_angle = results_[n - 1].
cos_angle;
1546 for (num_results = n;
1547 (num_results < num_points) &&
1548 !(fabs(min_cos_angle - results_[num_results].
cos_angle) > 0.0);
1555 size_t n, double * point_coordinates_xyz,
1560 size_t num_results_ = *num_results;
1566 double min_cos_angle = results_[num_results_-1].
cos_angle;
1569 for (
size_t i = 0; i < num_points; ++i) {
1571 double curr_cos_angle =
1572 points[i].coordinates_xyz[0] * point_coordinates_xyz[0] +
1573 points[i].coordinates_xyz[1] * point_coordinates_xyz[1] +
1574 points[i].coordinates_xyz[2] * point_coordinates_xyz[2];
1577 if (curr_cos_angle < min_cos_angle)
continue;
1580 {.
point = points[i], .cos_angle = curr_cos_angle};
1584 for (j = 0; j < num_results_; ++j) {
1587 &point, results_ + num_results_ - j - 1) < 0) {
1588 results_[num_results_ - j] = results_[num_results_ - j - 1];
1593 results_[num_results_ - j] = point;
1601 if (num_results_ > n) {
1603 size_t new_num_results;
1604 min_cos_angle = results_[n - 1].
cos_angle;
1606 for (new_num_results = n;
1607 (new_num_results < num_results_) &&
1608 !(fabs(min_cos_angle - results_[new_num_results].cos_angle) > 0.0);
1610 num_results_ = new_num_results;
1612 *num_results = num_results_;
1616 results_[num_results_-1].point.coordinates_xyz, point_coordinates_xyz);
1617 }
else return curr_angle;
1621 size_t n,
double * point_coordinates_xyz,
1623 size_t * num_results,
double * dot_stack,
1625 size_t curr_tree_depth) {
1629 (*results)[(*num_results)-1].point.coordinates_xyz,
1630 point_coordinates_xyz);
1635 double dot = dot_stack[curr_tree_depth];
1647 if ((dot < angle.
sin) | (angle.
cos <= 0.0)) {
1653 node->
U_size, results, results_array_size, num_results, angle);
1663 dot_stack[curr_tree_depth] = dot;
1664 node_stack[curr_tree_depth] = node;
1665 flags[curr_tree_depth] = 0;
1678 if ((dot > - angle.
sin) || (angle.
cos <= 0.0)) {
1684 node->
T_size, results, results_array_size, num_results, angle);
1694 dot_stack[curr_tree_depth] = dot;
1695 node_stack[curr_tree_depth] = node;
1696 flags[curr_tree_depth] = 0;
1704 if (curr_tree_depth == 0)
break;
1709 dot = dot_stack[curr_tree_depth];
1710 node = node_stack[curr_tree_depth];
1719 double (*coordinates_xyz)[3],
size_t n,
1720 double ** cos_angles,
1721 size_t * cos_angles_array_size,
1722 double (**result_coordinates_xyz)[3],
1723 size_t * result_coordinates_xyz_array_size,
1724 size_t ** local_point_ids,
1725 size_t * local_point_ids_array_size,
1726 size_t * num_local_point_ids) {
1728 if (num_points == 0)
return;
1730 if (cos_angles != NULL)
1735 search, num_points, coordinates_xyz, (cos_angles!=NULL)?*cos_angles:NULL,
1736 result_coordinates_xyz, result_coordinates_xyz_array_size,
1737 local_point_ids, local_point_ids_array_size, num_local_point_ids);
1739 size_t total_num_local_points = 0;
1740 for (
size_t i = 0; i < num_points; ++i)
1741 total_num_local_points += num_local_point_ids[i];
1743 if ((cos_angles != NULL) && (total_num_local_points > num_points)) {
1746 total_num_local_points);
1748 for (
size_t i = num_points - 1, offset = total_num_local_points - 1;
1749 i != (size_t)-1; i--) {
1751 for (
size_t j = 0; j < num_local_point_ids[i]; ++j, --offset)
1752 (*cos_angles)[offset] = (*cos_angles)[i];
1759 if (search == NULL) {
1760 memset(num_local_point_ids, 0, num_points *
sizeof(*num_local_point_ids));
1766 size_t total_num_local_point_ids = 0;
1774 size_t results_array_size = 0;
1776 for (
size_t i = 0; i < num_points; ++i) {
1780 double * curr_coordinates_xyz = coordinates_xyz[i];
1782 size_t curr_tree_depth = 0;
1784 size_t curr_num_points = 0;
1789 double dot = curr_node->
gc_norm_vector[0]*curr_coordinates_xyz[0] +
1793 dot_stack[curr_tree_depth] = dot;
1794 node_stack[curr_tree_depth] = curr_node;
1795 flags[curr_tree_depth] = 0;
1800 if (curr_node->
U_size < n) {
1803 curr_num_points = curr_node->
U_size + curr_node->
T_size;
1807 flags[curr_tree_depth] =
U_FLAG;
1808 curr_num_points = curr_node->
U_size;
1812 flags[curr_tree_depth] =
U_FLAG;
1813 curr_node = curr_node->
U;
1818 if (curr_node->
T_size < n) {
1821 curr_num_points = curr_node->
U_size + curr_node->
T_size;
1825 points += curr_node->
U_size;
1826 flags[curr_tree_depth] =
T_FLAG;
1827 curr_num_points = curr_node->
T_size;
1831 points += curr_node->
U_size;
1832 flags[curr_tree_depth] =
T_FLAG;
1833 curr_node = curr_node->
T;
1840 assert(curr_num_points > 0);
1842 size_t num_results =
1844 n, points, curr_num_points, curr_coordinates_xyz,
1845 &results, &results_array_size);
1849 n, curr_coordinates_xyz, &results, &results_array_size, &num_results,
1850 dot_stack, node_stack, flags, curr_tree_depth);
1854 total_num_local_point_ids + num_results);
1855 size_t * local_point_ids_ =
1856 (*local_point_ids) + total_num_local_point_ids;
1857 double * cos_angles_;
1858 if (cos_angles != NULL) {
1860 total_num_local_point_ids + num_results);
1861 cos_angles_ = (*cos_angles) + total_num_local_point_ids;
1865 double (*result_coordinates_xyz_)[3];
1866 if (result_coordinates_xyz != NULL) {
1868 *result_coordinates_xyz_array_size,
1869 total_num_local_point_ids + num_results);
1870 result_coordinates_xyz_ =
1871 (*result_coordinates_xyz) + total_num_local_point_ids;
1873 result_coordinates_xyz_ = NULL;
1876 for (
size_t j = 0; j < num_results; ++j) {
1878 local_point_ids_[j] = results[j].
point.
idx;
1879 if (cos_angles_ != NULL) cos_angles_[j] = results[j].
cos_angle;
1880 if (result_coordinates_xyz_ != NULL) {
1887 num_local_point_ids[i] = num_results;
1888 total_num_local_point_ids += num_results;
1900 size_t n,
size_t ** local_point_ids,
size_t * local_point_ids_array_size,
1901 size_t * num_local_point_ids) {
1903 if (num_bnd_circles == 0)
return;
1905 if (search == NULL) {
1907 num_local_point_ids, 0, num_bnd_circles *
sizeof(*num_local_point_ids));
1913 size_t total_num_local_point_ids = 0;
1921 size_t results_array_size = 0;
1923 for (
size_t i = 0; i < num_bnd_circles; ++i) {
1927 double * curr_coordinates_xyz = bnd_circles[i].
base_vector;
1929 size_t curr_tree_depth = 0;
1931 size_t curr_num_points = 0;
1936 double dot = curr_node->
gc_norm_vector[0]*curr_coordinates_xyz[0] +
1940 dot_stack[curr_tree_depth] = dot;
1941 node_stack[curr_tree_depth] = curr_node;
1942 flags[curr_tree_depth] = 0;
1947 if (curr_node->
U_size < n) {
1950 curr_num_points = curr_node->
U_size + curr_node->
T_size;
1954 flags[curr_tree_depth] =
U_FLAG;
1955 curr_num_points = curr_node->
U_size;
1959 flags[curr_tree_depth] =
U_FLAG;
1960 curr_node = curr_node->
U;
1965 if (curr_node->
T_size < n) {
1968 curr_num_points = curr_node->
U_size + curr_node->
T_size;
1972 points += curr_node->
U_size;
1973 flags[curr_tree_depth] =
T_FLAG;
1974 curr_num_points = curr_node->
T_size;
1978 points += curr_node->
U_size;
1979 flags[curr_tree_depth] =
T_FLAG;
1980 curr_node = curr_node->
T;
1987 YAC_ASSERT(curr_num_points > 0,
"insufficient number of points");
1989 size_t num_results =
1991 n, points, curr_num_points, curr_coordinates_xyz,
1992 &results, &results_array_size);
1996 n, curr_coordinates_xyz, &results, &results_array_size, &num_results,
1997 dot_stack, node_stack, flags, curr_tree_depth);
1999 for (; num_results > 0; --num_results)
2000 if (results[num_results-1].cos_angle >= bnd_circles[i].inc_angle.cos)
2005 total_num_local_point_ids + num_results);
2006 size_t * local_point_ids_ =
2007 (*local_point_ids) + total_num_local_point_ids;
2009 for (
size_t j = 0; j < num_results; ++j)
2010 local_point_ids_[j] = results[j].point.idx;
2012 num_local_point_ids[i] = num_results;
2013 total_num_local_point_ids += num_results;
2035 "ERRROR(yac_point_sphere_part_search_NNN_ubound): "
2036 "invalid point sphere part search (has to be != NULL)");
2037 YAC_ASSERT(n > 0,
"invalid n (has to be > 0)")
2040 size_t temp_angles_array_size = 0;
2044 for (
size_t i = 0; i < num_points; ++i) {
2048 double * curr_coordinates_xyz = coordinates_xyz[i];
2051 size_t curr_num_points = 0;
2056 double dot = curr_node->
gc_norm_vector[0]*curr_coordinates_xyz[0] +
2063 if (curr_node->
U_size < n) {
2065 curr_num_points = curr_node->
U_size + curr_node->
T_size;
2069 curr_num_points = curr_node->
U_size;
2073 curr_node = curr_node->
U;
2078 if (curr_node->
T_size < n) {
2080 curr_num_points = curr_node->
U_size + curr_node->
T_size;
2084 points += curr_node->
U_size;
2085 curr_num_points = curr_node->
T_size;
2089 points += curr_node->
U_size;
2090 curr_node = curr_node->
T;
2096 curr_num_points >= n,
"failed to find a sufficient number of points");
2105 curr_coordinates_xyz, points[0].coordinates_xyz);
2106 for (
size_t j = 1; j < curr_num_points; ++j) {
2109 curr_coordinates_xyz, points[j].coordinates_xyz);
2111 best_angle = curr_angle;
2113 angles[i] = best_angle;
2119 temp_angles, temp_angles_array_size, curr_num_points);
2120 for (
size_t j = 0; j < curr_num_points; ++j)
2123 curr_coordinates_xyz, points[j].coordinates_xyz);
2126 temp_angles, curr_num_points,
sizeof(*temp_angles),
2129 angles[i] = temp_angles[n-1];
2141 size_t ** local_point_ids,
size_t * local_point_ids_array_size,
2142 size_t * num_local_point_ids) {
2144 double const * search_coord = bnd_circle->
base_vector;
2167 *num_local_point_ids + node->
U_size);
2171 for (
size_t i = 0; i < node->
U_size; ++i) {
2175 (*local_point_ids)[*num_local_point_ids] = leaf_points[i].
idx;
2176 (*num_local_point_ids)++;
2182 node->
U, points, bnd_circle,
2183 local_point_ids, local_point_ids_array_size, num_local_point_ids);
2198 *num_local_point_ids + node->
T_size);
2203 for (
size_t i = 0; i < node->
T_size; ++i) {
2207 (*local_point_ids)[*num_local_point_ids] = leaf_points[i].
idx;
2208 (*num_local_point_ids)++;
2214 node->
T, points + node->
U_size, bnd_circle,
2215 local_point_ids, local_point_ids_array_size, num_local_point_ids);
2223 size_t ** local_point_ids,
size_t * local_point_ids_array_size,
2224 size_t * num_local_point_ids) {
2226 if (num_bnd_circles == 0)
return;
2228 if (search == NULL) {
2230 num_local_point_ids, 0, num_bnd_circles *
sizeof(*num_local_point_ids));
2237 size_t total_num_local_point_ids = 0;
2240 for (
size_t i = 0; i < num_bnd_circles; ++i) {
2242 size_t const start_count = total_num_local_point_ids;
2247 base_node, points, &bnd_circles[i],
2248 local_point_ids, local_point_ids_array_size, &total_num_local_point_ids);
2251 num_local_point_ids[i] = total_num_local_point_ids - start_count;
2257 size_t ** overlap_cells,
2258 size_t * overlap_cells_array_size,
2259 size_t * num_overlap_cells,
2260 struct overlaps * search_interval_tree_buffer,
2261 double prev_gc_norm_vector[]) {
2273 *num_overlap_cells + node->
T_size);
2274 memcpy(*overlap_cells + *num_overlap_cells, node->
T,
2275 node->
T_size *
sizeof(**overlap_cells));
2276 *num_overlap_cells += node->
T_size;
2280 overlap_cells_array_size, num_overlap_cells,
2291 *num_overlap_cells + node->
U_size);
2292 memcpy(*overlap_cells + *num_overlap_cells, node->
U,
2293 node->
U_size *
sizeof(**overlap_cells));
2294 *num_overlap_cells += node->
U_size;
2298 overlap_cells_array_size, num_overlap_cells,
2310 double GCp[3], bVp[3];
2317 if ((fabs(bVp[0]) > 1e-9) || (fabs(bVp[1]) > 1e-9) ||
2318 (fabs(bVp[2]) > 1e-9)) {
2321 search_interval.
left=base_angle;
2322 search_interval.
right=base_angle;
2324 search_interval.
left = -M_PI;
2325 search_interval.
right = M_PI;
2331 search_interval, search_interval_tree_buffer);
2334 *num_overlap_cells +
2337 for (
size_t i = 0; i < search_interval_tree_buffer->
num_overlaps;
2339 (*overlap_cells)[(*num_overlap_cells)+i] =
2344 *num_overlap_cells += search_interval_tree_buffer->
num_overlaps;
2349 *num_overlap_cells + node->
I_size);
2350 memcpy(*overlap_cells + *num_overlap_cells, node->
I.
list,
2351 node->
I_size *
sizeof(**overlap_cells));
2352 *num_overlap_cells += node->
I_size;
2359 size_t count,
size_t ** cells,
size_t * num_cells_per_coordinate) {
2363 size_t * temp_search_results = NULL;
2364 size_t temp_search_results_array_size = 0;
2365 size_t num_temp_search_results = 0;
2367 struct overlaps search_interval_tree_buffer = {0, 0, NULL};
2370 num_cells_per_coordinate, 0, count *
sizeof(*num_cells_per_coordinate));
2371 size_t * cells_ = NULL;
2372 size_t cells_array_size = 0;
2376 for (
size_t i = 0; i < count; ++i) {
2378 double * curr_coordinates_xyz = &(coordinates_xyz[i][0]);
2380 num_temp_search_results = 0;
2382 double gc_norm_vector[3] = {0.0,0.0,1.0};
2384 search_point(base_node, curr_coordinates_xyz, &temp_search_results,
2385 &temp_search_results_array_size, &num_temp_search_results,
2386 &search_interval_tree_buffer, gc_norm_vector);
2389 cells_, cells_array_size,
num_cells + num_temp_search_results);
2391 memcpy(cells_ +
num_cells, temp_search_results,
2392 num_temp_search_results *
sizeof(*temp_search_results));
2393 num_cells_per_coordinate[i] = num_temp_search_results;
2397 free(temp_search_results);
2398 free(search_interval_tree_buffer.
overlap_iv);
2405 size_t count,
size_t ** cells,
size_t * num_cells_per_bnd_circle) {
2409 size_t * temp_search_results = NULL;
2410 size_t temp_search_results_array_size = 0;
2411 size_t num_temp_search_results = 0;
2413 struct overlaps search_interval_tree_buffer = {0, 0, NULL};
2416 num_cells_per_bnd_circle, 0, count *
sizeof(*num_cells_per_bnd_circle));
2417 size_t * cells_ = NULL;
2418 size_t cells_array_size = 0;
2422 for (
size_t i = 0; i < count; ++i) {
2424 num_temp_search_results = 0;
2426 double gc_norm_vector[3] = {0.0,0.0,1.0};
2429 &temp_search_results_array_size, &num_temp_search_results,
2430 &search_interval_tree_buffer, gc_norm_vector);
2433 cells_, cells_array_size,
num_cells + num_temp_search_results);
2435 memcpy(cells_ +
num_cells, temp_search_results,
2436 num_temp_search_results *
sizeof(*temp_search_results));
2437 num_cells_per_bnd_circle[i] = num_temp_search_results;
2441 free(temp_search_results);
2442 free(search_interval_tree_buffer.
overlap_iv);
2480 if (search == NULL)
return;
2489 if (search == NULL)
return;
#define YAC_ASSERT(exp, msg)
struct bounding_circle const *const const_bounding_circle_pointer
#define ENSURE_ARRAY_SIZE(arrayp, curr_array_size, req_size)
static struct sin_cos_angle get_vector_angle_2(double const a[3], double const b[3])
static double clamp_abs_one(double val)
static const struct sin_cos_angle SIN_COS_ZERO
static int points_are_identically(double const *a, double const *b)
static const struct sin_cos_angle SIN_COS_M_PI
static struct sin_cos_angle sum_angles_no_check(struct sin_cos_angle a, struct sin_cos_angle b)
static void crossproduct_kahan(double const a[], double const b[], double cross[])
static const struct sin_cos_angle SIN_COS_M_PI_2
static int compare_angles(struct sin_cos_angle a, struct sin_cos_angle b)
static void normalise_vector(double v[])
static double get_vector_angle(double const a[3], double const b[3])
static struct sin_cos_angle sin_cos_angle_new(double sin, double cos)
void yac_search_interval_tree(struct interval_node tree[], size_t num_nodes, struct interval query, struct overlaps *overlaps)
void yac_generate_interval_tree(struct interval_node intervals[], size_t num_nodes)
#define xrealloc(ptr, size)
static int leaf_contains_matching_point(struct point_id_xyz *points, size_t num_points, double coordinate_xyz[3], size_t **local_point_ids, size_t *local_point_ids_array_size, double(**result_coordinates_xyz)[3], size_t *result_coordinates_xyz_array_size, size_t total_num_local_point_ids, size_t *num_local_point_ids)
static size_t initial_point_bnd_search_NNN(size_t n, struct point_id_xyz *points, size_t num_points, double *point_coordinates_xyz, struct point_id_xyz_angle **results, size_t *results_array_size)
static void search_point(struct sphere_part_node *node, double point[], size_t **overlap_cells, size_t *overlap_cells_array_size, size_t *num_overlap_cells, struct overlaps *search_interval_tree_buffer, double prev_gc_norm_vector[])
static int compare_point_idx_xyz(void const *a, void const *b)
void yac_point_sphere_part_search_NNN_ubound(struct point_sphere_part_search *search, size_t num_points, yac_coordinate_pointer coordinates_xyz, size_t n, struct sin_cos_angle *angles)
static size_t swap_node_type(struct temp_partition_data *part_data, size_t i, int node_type, size_t begin, size_t end)
static void check_leaf_NN(struct point_id_xyz *points, size_t num_points, double *point_coordinates_xyz, struct sin_cos_angle *best_angle, double(**result_coordinates_xyz)[3], size_t *result_coordinates_xyz_array_size, size_t **local_point_ids, size_t *local_point_ids_array_size, size_t total_num_local_point_ids, size_t *num_local_point_ids)
static struct point_id_xyz * get_unique_points(size_t *num_points, yac_const_coordinate_pointer coordinates_xyz, yac_int const *ids, int const *mask)
void yac_bnd_sphere_part_search_do_bnd_circle_search(struct bnd_sphere_part_search *search, struct bounding_circle *bnd_circles, size_t count, size_t **cells, size_t *num_cells_per_bnd_circle)
static void compute_gc_norm_vector(void *coords_data, size_t coords_size, size_t coords_count, double prev_gc_norm_vector[], double gc_norm_vector[])
static struct point_sphere_part_node * partition_point_data(struct point_id_xyz *points, size_t num_points, size_t threshold, double prev_gc_norm_vector[], size_t curr_tree_depth, size_t *max_tree_depth, int *list_flag)
static void point_search_NN(struct bounding_circle *bnd_circle, double(**result_coordinates_xyz)[3], size_t *result_coordinates_xyz_array_size, size_t **local_point_ids, size_t *local_point_ids_array_size, size_t total_num_local_point_ids, size_t *num_local_point_ids, double *dot_stack, struct point_sphere_part_node **node_stack, int *flags, size_t curr_tree_depth)
void yac_point_sphere_part_search_NNN_bnd_circle(struct point_sphere_part_search *search, size_t num_bnd_circles, struct bounding_circle *bnd_circles, size_t n, size_t **local_point_ids, size_t *local_point_ids_array_size, size_t *num_local_point_ids)
struct bnd_sphere_part_search * yac_bnd_sphere_part_search_new(struct bounding_circle *circles, size_t num_circles)
static void search_bnd_circle_I_node(struct sphere_part_node *node, struct bounding_circle bnd_circle, size_t **restrict overlap_cells, size_t *overlap_cells_array_size, size_t *restrict num_overlap_cells, struct overlaps *search_interval_tree_buffer, double prev_gc_norm_vector[])
static void search_big_bnd_circle(struct sphere_part_node *node, struct bounding_circle bnd_circle, size_t **restrict overlap_cells, size_t *overlap_cells_array_size, size_t *restrict num_overlap_cells, struct overlaps *search_interval_tree_buffer, double prev_gc_norm_vector[])
TODO change to iterative implementation and allocate overlap_cells first.
static void sort_partition_data(struct temp_partition_data *part_data, size_t I_FULL_size, size_t I_size, size_t U_size, size_t T_size)
static void partition_data(size_t *local_cell_ids, struct temp_partition_data *part_data, size_t num_cell_ids, size_t threshold, struct sphere_part_node *parent_node, double prev_gc_norm_vector[])
void yac_delete_point_sphere_part_search(struct point_sphere_part_search *search)
struct point_sphere_part_search * yac_point_sphere_part_search_mask_new(size_t num_points, yac_const_coordinate_pointer coordinates_xyz, yac_int const *ids, int const *mask)
void yac_bnd_sphere_part_search_delete(struct bnd_sphere_part_search *search)
struct point_sphere_part_search * yac_point_sphere_part_search_new(size_t num_points, yac_const_coordinate_pointer coordinates_xyz, yac_int const *ids)
static struct sin_cos_angle check_leaf_NNN(size_t n, double *point_coordinates_xyz, struct point_id_xyz *points, size_t num_points, struct point_id_xyz_angle **results, size_t *results_array_size, size_t *num_results, struct sin_cos_angle curr_angle)
static void search_bnd_circle_points(struct point_sphere_part_node const *node, struct point_id_xyz const *points, struct bounding_circle const *bnd_circle, size_t **local_point_ids, size_t *local_point_ids_array_size, size_t *num_local_point_ids)
static int compare_angles_(void const *a, void const *b)
static struct sphere_part_node * get_sphere_part_node()
static void free_sphere_part_tree(struct sphere_part_node tree)
static int compare_point_id_xyz_angle(const void *a, const void *b)
void yac_bnd_sphere_part_search_do_point_search(struct bnd_sphere_part_search *search, yac_coordinate_pointer coordinates_xyz, size_t count, size_t **cells, size_t *num_cells_per_coordinate)
void yac_point_sphere_part_search_bnd_circle(struct point_sphere_part_search *search, size_t num_bnd_circles, const_bounding_circle_pointer bnd_circles, size_t **local_point_ids, size_t *local_point_ids_array_size, size_t *num_local_point_ids)
static void search_small_bnd_circle(struct sphere_part_node *node, struct bounding_circle bnd_circle, size_t **restrict overlap_cells, size_t *overlap_cells_array_size, size_t *restrict num_overlap_cells, struct overlaps *search_interval_tree_buffer, double prev_gc_norm_vector[])
static void swap_partition_data(struct temp_partition_data *a, struct temp_partition_data *b)
static void init_sphere_part_node(struct sphere_part_node *node)
static void search_bnd_circle(struct sphere_part_node *node, struct bounding_circle bnd_circle, size_t **restrict overlap_cells, size_t *overlap_cells_array_size, size_t *restrict num_overlap_cells, struct overlaps *search_interval_tree_buffer, double prev_gc_norm_vector[])
void yac_point_sphere_part_search_NN(struct point_sphere_part_search *search, size_t num_points, double(*coordinates_xyz)[3], double *cos_angles, double(**result_coordinates_xyz)[3], size_t *result_coordinates_xyz_array_size, size_t **local_point_ids, size_t *local_point_ids_array_size, size_t *num_local_point_ids)
void yac_point_sphere_part_search_NNN(struct point_sphere_part_search *search, size_t num_points, double(*coordinates_xyz)[3], size_t n, double **cos_angles, size_t *cos_angles_array_size, double(**result_coordinates_xyz)[3], size_t *result_coordinates_xyz_array_size, size_t **local_point_ids, size_t *local_point_ids_array_size, size_t *num_local_point_ids)
static void free_point_sphere_part_tree(struct point_sphere_part_node *tree)
static int compare_points_int32_coord(const void *a, const void *b)
static void point_search_NNN(size_t n, double *point_coordinates_xyz, struct point_id_xyz_angle **results, size_t *results_array_size, size_t *num_results, double *dot_stack, struct point_sphere_part_node **node_stack, int *flags, size_t curr_tree_depth)
algorithm for searching cells and points on a grid
struct sphere_part_node base_node
struct sin_cos_angle inc_angle
angle between the middle point and the boundary of the spherical cap
struct point_id_xyz point
int32_t coordinate_xyz[3]
double coordinates_xyz[3]
struct point_sphere_part_node base_node
struct point_id_xyz * points
struct sin_cos_angle I_angle
struct bounding_circle bnd_circle
struct interval_node * head_node
double const (* yac_const_coordinate_pointer)[3]
double(* yac_coordinate_pointer)[3]