46 return (sincos[0] * p[0]) + (sincos[1] * p[1]);
51 return (sincos[1] * p[0]) - (sincos[0] * p[1]);
75static float is_left(
const float p0[2],
const float p1[2],
const float p2[2])
77 return (p1[0] - p0[0]) * (p2[1] - p0[1]) - (p2[0] - p0[0]) * (p1[1] - p0[1]);
91 const int maxmax = points_num - 1;
98 float xmin = points[0][0];
99 for (i = 1; i <= maxmax; i++) {
100 if (points[i][0] != xmin) {
106 if (minmax == maxmax) {
107 r_points[++
top] = minmin;
108 if (points[minmax][1] != points[minmin][1]) {
110 r_points[++
top] = minmax;
118 xmax = points[maxmax][0];
119 for (i = maxmax - 1; i >= 0; i--) {
120 if (points[i][0] != xmax) {
127 r_points[++
top] = minmin;
129 while (++i <= maxmin) {
131 if ((i < maxmin) && (
is_left(points[minmin], points[maxmin], points[i]) >= 0)) {
137 if (
is_left(points[r_points[top - 1]], points[r_points[top]], points[i]) > 0.0f) {
147 if (maxmax != maxmin) {
148 r_points[++
top] = maxmax;
153 while (--i >= minmax) {
155 if ((i > minmax) && (
is_left(points[maxmax], points[minmax], points[i]) >= 0)) {
161 if (
is_left(points[r_points[top - 1]], points[r_points[top]], points[i]) > 0.0f) {
167 if (points[i][0] == points[r_points[0]][0] && points[i][1] == points[r_points[0]][1]) {
175 if (minmax != minmin && r_points[0] != minmin) {
176 r_points[++
top] = minmin;
186 if (points_num < 2) {
187 if (points_num == 1) {
192 int *points_map =
static_cast<int *
>(
MEM_mallocN(
sizeof(
int) *
size_t(points_num), __func__));
193 float(*points_sort)[2] =
static_cast<float(*)[2]
>(
194 MEM_mallocN(
sizeof(*points_sort) *
size_t(points_num), __func__));
196 for (
int i = 0; i < points_num; i++) {
201 std::sort(points_map, points_map + points_num, [points](
const int &a_index,
const int &b_index) {
202 const float *a = points[a_index];
203 const float *
b = points[b_index];
220 for (
int i = 0; i < points_num; i++) {
221 copy_v2_v2(points_sort[i], points[points_map[i]]);
227 for (
int i = 0; i < points_hull_num; i++) {
228 r_points[i] = points_map[r_points[i]];
235 return points_hull_num;
244#if defined(USE_BRUTE_FORCE_ASSERT) && !defined(NDEBUG)
245static float2 convexhull_aabb_fit_hull_2d_brute_force(
const float (*points_hull)[2],
249 float2 sincos_best = {0.0f, 1.0f};
251 for (
int i = 0; i < points_hull_num; i++) {
252 const int i_next = (i + 1) % points_hull_num;
254 float dvec_length = 0.0f;
256 float2(points_hull[i_next]) -
float2(points_hull[i]), dvec_length);
257 if (
UNLIKELY(dvec_length == 0.0f)) {
264 for (
int j = 0; j < points_hull_num; j++) {
275 area_test = (bounds[0].
max - bounds[0].
min) * (bounds[1].max - bounds[1].
min);
276 if (area_test > area_best) {
281 if (area_test < area_best) {
282 area_best = area_test;
283 sincos_best = sincos;
310 if (sincos[0] < 0.0f) {
311 if (sincos[1] < 0.0f) {
312 result[0] = -sincos[0];
313 result[1] = -sincos[1];
315 else if ((sincos[0] == -1.0f) && (sincos[1] == 0.0f)) {
316 result[0] = -sincos[0];
317 result[1] = sincos[1];
320 result[0] = sincos[1];
321 result[1] = -sincos[0];
325 if (sincos[1] < 0.0f) {
326 result[0] = -sincos[1];
327 result[1] = sincos[0];
329 else if ((sincos[0] == 0.0f) && (sincos[1] == 1.0f)) {
330 result[0] = sincos[1];
331 result[1] = sincos[0];
359 if (a.sincos_canonical[0] <
b.sincos_canonical[0]) {
362 if (a.sincos_canonical[0] >
b.sincos_canonical[0]) {
366 if (a.sincos_canonical[1] >
b.sincos_canonical[1]) {
369 if (a.sincos_canonical[1] <
b.sincos_canonical[1]) {
374 if (a.index >
b.index) {
377 if (a.index <
b.index) {
417 prev_p = &iter->
next;
428 const int i_curr = hstep.
index;
431 float dir_length = 0.0f;
433 hstep.
index = i_next;
434 if (
LIKELY(dir_length != 0.0f)) {
448 const int points_hull_num)
450 const int points_hull_num_minus_1 = points_hull_num - 1;
455 for (
int axis = 0; axis < 2; axis++) {
456 range[axis][0] = points_hull[0][axis];
457 range[axis][1] = points_hull[0][axis];
463 for (
int i = 1; i < points_hull_num; i++) {
464 const float *p = points_hull[i];
465 for (
int axis = 0; axis < 2; axis++) {
466 if (range[axis][0] < p[axis]) {
467 range[axis][0] = p[axis];
470 if (range[axis][1] > p[axis]) {
471 range[axis][1] = p[axis];
482 for (
int axis = 0; axis < 2; axis++) {
483 for (
int i = 0; i < 2; i++) {
484 const int i_orig = hiter.
axis[axis][i].
index;
485 int i_curr = i_orig, i_prev;
489 while ((i_prev = (i_curr + points_hull_num_minus_1) % points_hull_num) != i_orig) {
490 float dir_length = 0.0f;
492 float2(points_hull[i_curr]) -
float2(points_hull[i_prev]), dir_length);
493 if (
LIKELY(dir_length != 0.0f)) {
495 if (
math::abs(sincos_test[axis]) > 0.5f) {
499 if (
LIKELY(sincos_test_canonical[0] != 1.0f)) {
518 for (
int axis = 0; axis < 2; axis++) {
519 for (
int i = 0; i < 2; i++) {
533#ifdef USE_ANGLE_ITER_ORDER_ASSERT
542#ifdef USE_ANGLE_ITER_ORDER_ASSERT
561template<
int Axis,
int AxisSign>
563 const int points_hull_num,
573 const int index_init = *index_p;
574 int index_best = index_init;
575 float value_init = (Axis == 0) ?
sincos_rotate_cw_x(sincos, points_hull[index_best]) :
577 float value_best = value_init;
580 const int index_test = (index_init +
count) % points_hull_num;
581 const float value_test = (Axis == 0) ?
sincos_rotate_cw_x(sincos, points_hull[index_test]) :
583 if ((AxisSign == -1) ? (value_test > value_best) : (value_test < value_best)) {
586 value_best = value_test;
587 index_best = index_test;
590 *index_p = index_best;
597 float2 sincos_best = {0.0f, 1.0f};
598 int index_best = INT_MAX;
614 points_hull, points_hull_num, hstep->angle.sincos_canonical, &bounds_index[0].
min),
616 points_hull, points_hull_num, hstep->angle.sincos_canonical, &bounds_index[0].
max)},
618 points_hull, points_hull_num, hstep->angle.sincos_canonical, &bounds_index[1].
min),
620 points_hull, points_hull_num, hstep->angle.sincos_canonical, &bounds_index[1].
max)},
623 const float area_test = (bounds_test[0].
max - bounds_test[0].
min) *
624 (bounds_test[1].max - bounds_test[1].
min);
626 if (area_test < area_best ||
629 ((area_test == area_best) && (hstep->angle.index < index_best)))
631 area_best = area_test;
632 sincos_best = hstep->angle.sincos;
633 index_best = hstep->angle.index;
639 const float angle = (area_best !=
FLT_MAX) ?
float(atan2(sincos_best[0], sincos_best[1])) : 0.0f;
641#if defined(USE_BRUTE_FORCE_ASSERT) && !defined(NDEBUG)
644 const float2 sincos_test = convexhull_aabb_fit_hull_2d_brute_force(points_hull,
646 if (sincos_best != sincos_test) {
660 int *index_map =
static_cast<int *
>(
661 MEM_mallocN(
sizeof(*index_map) *
size_t(points_num), __func__));
665 if (points_hull_num > 1) {
666 float(*points_hull)[2] =
static_cast<float(*)[2]
>(
667 MEM_mallocN(
sizeof(*points_hull) *
size_t(points_hull_num), __func__));
668 for (
int j = 0; j < points_hull_num; j++) {
669 copy_v2_v2(points_hull[j], points[index_map[j]]);
void BLI_kdtree_nd_ insert(KDTree *tree, int index, const float co[KD_DIMS]) ATTR_NONNULL(1
MINLINE void copy_v2_v2(float r[2], const float a[2])
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Read Guarded memory(de)allocation.
local_group_size(16, 16) .push_constant(Type b
static int hull_angle_canonical_cmp(const AngleCanonical &a, const AngleCanonical &b)
static HullAngleIter convexhull_2d_angle_iter_init(const float(*points_hull)[2], const int points_hull_num)
static float convexhull_aabb_fit_hull_2d(const float(*points_hull)[2], int points_hull_num)
static void hull_angle_insert_ordered(HullAngleIter &hiter, HullAngleStep *insert)
static float convexhull_2d_compute_extent_on_axis(const float(*points_hull)[2], const int points_hull_num, const float2 &sincos, int *index_p)
static float2 sincos_canonical(const float2 &sincos)
static int convexhull_2d_sorted(const float(*points)[2], const int points_num, int r_points[])
float BLI_convexhull_aabb_fit_points_2d(const float(*points)[2], int points_num)
int BLI_convexhull_2d(const float(*points)[2], const int points_num, int r_points[])
static float sincos_rotate_cw_x(const float2 &sincos, const float2 &p)
static void convexhull_2d_angle_iter_step(HullAngleIter &hiter)
static float sincos_rotate_cw_y(const float2 &sincos, const float2 &p)
static bool convexhull_2d_angle_iter_step_on_axis(const HullAngleIter &hiter, HullAngleStep &hstep)
static float is_left(const float p0[2], const float p1[2], const float p2[2])
draw_view in_light_buf[] float
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
QuaternionBase< T > normalize_and_get_length(const QuaternionBase< T > &q, T &out_length)
T min(const T &a, const T &b)
T max(const T &a, const T &b)
VecBase< float, 2 > float2
const float(* points_hull)[2]
HullAngleStep * axis_ordered