41#define USE_CONVEX_CROSS_PRODUCT_ENSURE
54#define USE_ANGLE_ITER_ORDER_ASSERT
64 return (sincos[0] * p[0]) + (sincos[1] * p[1]);
69 return (sincos[1] * p[0]) - (sincos[0] * p[1]);
108 return (((p1[0] - p0[0]) * (p2[1] - p0[1])) - ((p2[0] - p0[0]) * (p1[1] - p0[1])));
115 const int r_points[],
118#ifdef USE_CONVEX_CROSS_PRODUCT_ENSURE
119 int bot = r_points_range[0];
120 int top = r_points_range[1];
121 while (
top - bot >= 2) {
129 points[r_points[
top - 1]],
131 points[r_points[bot]],
133 points[r_points[
top]]) >= 0.0f))
142 points[r_points[
top]],
144 points[r_points[bot + 1]],
146 points[r_points[bot]]) >= 0.0f))
154 r_points_range[0] = bot;
155 r_points_range[1] =
top;
170#ifdef USE_CONVEX_CROSS_PRODUCT_ENSURE
174 (
is_left(points[r_points[
top - 1]], points[index], points[r_points[
top]]) >= 0.0f)))
182 r_points[++
top] = index;
198 const int minmin = 0;
199 const int maxmax = points_num - 1;
206 float xmin = points[0][0];
207 for (
i = 1;
i <= maxmax;
i++) {
208 if (points[
i][0] != xmin) {
214 if (minmax == maxmax) {
216 if (points[minmax][1] != points[minmin][1]) {
226 xmax = points[maxmax][0];
227 for (
i = maxmax - 1;
i >= 0;
i--) {
228 if (points[
i][0] != xmax) {
239 while (++
i <= maxmin) {
241 if ((
i < maxmin) && (
is_left(points[minmin], points[maxmin], points[
i]) >= 0.0f)) {
247 if (
is_left(points[r_points[
top - 1]], points[r_points[
top]], points[
i]) > 0.0f) {
256 if (maxmax != maxmin) {
262 while (--
i >= minmax) {
264 if ((
i > minmax) && (
is_left(points[maxmax], points[minmax], points[
i]) >= 0.0f)) {
270 if (
is_left(points[r_points[
top - 1]], points[r_points[
top]], points[
i]) > 0.0f) {
276 if (points[
i][0] == points[r_points[0]][0] && points[
i][1] == points[r_points[0]][1]) {
283 if (minmax != minmin && r_points[0] != minmin) {
300 const int points_num,
311 const int points_num = int(points.
size());
313 if (points_num < 2) {
314 if (points_num == 1) {
322 for (
int i = 0;
i < points_num;
i++) {
327 std::sort(points_map, points_map + points_num, [points](
const int &a_index,
const int &b_index) {
328 const float *a = points[a_index];
329 const float *
b = points[b_index];
346 for (
int i = 0;
i < points_num;
i++) {
353 for (
int i = points_hull_range[0];
i <= points_hull_range[1];
i++) {
354 r_points[
i] = points_map[r_points[
i]];
360 const int points_hull_num = (points_hull_range[1] - points_hull_range[0]) + 1;
362 return points_hull_num;
371#if defined(USE_BRUTE_FORCE_ASSERT) && !defined(NDEBUG)
372static float2 convexhull_aabb_fit_hull_2d_brute_force(
const float (*points_hull)[2],
375 float area_best = std::numeric_limits<float>::max();
376 float2 sincos_best = {0.0f, 1.0f};
378 for (
int i = 0;
i < points_hull_num;
i++) {
379 const int i_next = (
i + 1) % points_hull_num;
381 float dvec_length = 0.0f;
383 float2(points_hull[i_next]) -
float2(points_hull[
i]), dvec_length);
384 if (
UNLIKELY(dvec_length == 0.0f)) {
389 {std::numeric_limits<float>::max(), -std::numeric_limits<float>::max()},
390 {std::numeric_limits<float>::max(), -std::numeric_limits<float>::max()},
394 for (
int j = 0; j < points_hull_num; j++) {
406 if (area_test > area_best) {
411 if (area_test < area_best) {
412 area_best = area_test;
413 sincos_best = sincos;
440 if (sincos[0] < 0.0f) {
441 if (sincos[1] < 0.0f) {
445 else if ((sincos[0] == -1.0f) && (sincos[1] == 0.0f)) {
455 if (sincos[1] < 0.0f) {
459 else if ((sincos[0] == 0.0f) && (sincos[1] == 1.0f)) {
547 prev_p = &iter->
next;
558 const int i_curr = hstep.
index;
561 float dir_length = 0.0f;
563 hstep.
index = i_next;
564 if (
LIKELY(dir_length != 0.0f)) {
578 const int points_hull_num)
580 const int points_hull_num_minus_1 = points_hull_num - 1;
585 for (
int axis = 0; axis < 2; axis++) {
586 range[axis][0] = points_hull[0][axis];
587 range[axis][1] = points_hull[0][axis];
593 for (
int i = 1;
i < points_hull_num;
i++) {
594 const float *p = points_hull[
i];
595 for (
int axis = 0; axis < 2; axis++) {
596 if (range[axis][0] < p[axis]) {
597 range[axis][0] = p[axis];
600 if (range[axis][1] > p[axis]) {
601 range[axis][1] = p[axis];
612 for (
int axis = 0; axis < 2; axis++) {
613 for (
int i = 0;
i < 2;
i++) {
615 int i_curr = i_orig, i_prev;
619 while ((i_prev = (i_curr + points_hull_num_minus_1) % points_hull_num) != i_orig) {
620 float dir_length = 0.0f;
622 float2(points_hull[i_curr]) -
float2(points_hull[i_prev]), dir_length);
623 if (
LIKELY(dir_length != 0.0f)) {
629 if (
LIKELY(sincos_test_canonical[0] != 1.0f)) {
648 for (
int axis = 0; axis < 2; axis++) {
649 for (
int i = 0;
i < 2;
i++) {
663#ifdef USE_ANGLE_ITER_ORDER_ASSERT
672#ifdef USE_ANGLE_ITER_ORDER_ASSERT
692template<
int Axis,
int AxisSign>
694 const int points_hull_num,
704 const int index_init = *index_p;
705 int index_best = index_init;
706 float value_init = (Axis == 0) ?
sincos_rotate_cw_x(sincos, points_hull[index_best]) :
708 float value_best = value_init;
711 const int index_test = (index_init +
count) % points_hull_num;
712 const float value_test = (Axis == 0) ?
sincos_rotate_cw_x(sincos, points_hull[index_test]) :
714 if ((AxisSign == -1) ? (value_test > value_best) : (value_test < value_best)) {
717 value_best = value_test;
718 index_best = index_test;
721 *index_p = index_best;
727 float area_best = std::numeric_limits<float>::max();
728 float2 sincos_best = {0.0f, 1.0f};
729 int index_best = std::numeric_limits<int>::max();
745 points_hull, points_hull_num, hstep->angle.sincos_canonical, &bounds_index[0].
min),
747 points_hull, points_hull_num, hstep->angle.sincos_canonical, &bounds_index[0].
max)},
749 points_hull, points_hull_num, hstep->angle.sincos_canonical, &bounds_index[1].
min),
751 points_hull, points_hull_num, hstep->angle.sincos_canonical, &bounds_index[1].
max)},
754 const float area_test = (bounds_test[0].
max - bounds_test[0].
min) *
755 (bounds_test[1].
max - bounds_test[1].
min);
757 if (area_test < area_best ||
760 ((area_test == area_best) && (hstep->angle.index < index_best)))
762 area_best = area_test;
763 sincos_best = hstep->angle.sincos;
764 index_best = hstep->angle.index;
770 const float angle = (area_best != std::numeric_limits<float>::max()) ?
771 atan2(sincos_best[0], sincos_best[1]) :
774#if defined(USE_BRUTE_FORCE_ASSERT) && !defined(NDEBUG)
777 const float2 sincos_test = convexhull_aabb_fit_hull_2d_brute_force(points_hull,
779 if (sincos_best != sincos_test) {
790 const int points_num = int(points.
size());
798 if (points_hull_num > 1) {
800 for (
int j = 0; j < points_hull_num; j++) {
801 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])
#define UNUSED_VARS_NDEBUG(...)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Read Guarded memory(de)allocation.
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
constexpr int64_t size() const
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 void convexhull_2d_stack_finalize(const float2 *points, const int r_points[], blender::int2 &r_points_range)
static float sincos_rotate_cw_x(const float2 &sincos, const float2 &p)
static void convexhull_2d_angle_iter_step(HullAngleIter &hiter)
int BLI_convexhull_2d(blender::Span< float2 > points, int r_points[])
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 int convexhull_2d_sorted_impl(const float2 *points, const int points_num, int r_points[])
float BLI_convexhull_aabb_fit_points_2d(blender::Span< float2 > points)
static blender::int2 convexhull_2d_sorted(const float2 *points, const int points_num, int r_points[])
static float is_left(const float2 &p0, const float2 &p1, const float2 &p2)
static void convexhull_2d_stack_push(const float2 *points, int r_points[], int &top, int index)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
ccl_device_inline float3 atan2(const float3 y, const float3 x)
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< int32_t, 2 > int2
VecBase< float, 2 > float2
const float(* points_hull)[2]
HullAngleStep * axis_ordered