/** * Find the most distant point between the 2 knots. */ static uint knot_find_split_point( const struct PointData *pd, const struct Knot *knot_l, const struct Knot *knot_r, const uint knots_len, const uint dims) { uint split_point = SPLIT_POINT_INVALID; double split_point_dist_best = -DBL_MAX; const double *offset = &pd->points[knot_l->index * dims]; #ifdef USE_VLA double v_plane[dims]; double v_proj[dims]; double v_offset[dims]; #else double *v_plane = alloca(sizeof(double) * dims); double *v_proj = alloca(sizeof(double) * dims); double *v_offset = alloca(sizeof(double) * dims); #endif sub_vn_vnvn( v_plane, &pd->points[knot_l->index * dims], &pd->points[knot_r->index * dims], dims); normalize_vn(v_plane, dims); const uint knots_end = knots_len - 1; const struct Knot *k_step = knot_l; do { if (k_step->index != knots_end) { k_step += 1; } else { /* wrap around */ k_step = k_step - knots_end; } if (k_step != knot_r) { sub_vn_vnvn(v_offset, &pd->points[k_step->index * dims], offset, dims); project_plane_vn_vnvn_normalized(v_proj, v_offset, v_plane, dims); double split_point_dist_test = len_squared_vn(v_proj, dims); if (split_point_dist_test > split_point_dist_best) { split_point_dist_best = split_point_dist_test; split_point = k_step->index; } } else { break; } } while (true); return split_point; }
float normalize_vn_vn(float *array_tar, const float *array_src, const int size) { double d = len_squared_vn(array_src, size); float d_sqrt; if (d > 1.0e-35) { d_sqrt = (float)sqrt(d); mul_vn_vn_fl(array_tar, array_src, size, 1.0f / d_sqrt); } else { fill_vn_fl(array_tar, size, 0.0f); d_sqrt = 0.0f; } return d_sqrt; }