#include #include #include #include #ifdef _WIN32 #define EXPORT __declspec(dllexport) #else #define EXPORT __attribute__((visibility("default"))) #endif EXPORT int find_sharpest_seam_c(const double* pts, int M, int stride, double scale) { if (M < 3) return 0; int64_t x_buf[1024]; int64_t y_buf[1024]; int64_t* x = (M <= 1024) ? x_buf : (int64_t*)malloc(M * sizeof(int64_t)); int64_t* y = (M <= 1024) ? y_buf : (int64_t*)malloc(M * sizeof(int64_t)); for (int i = 0; i < M; ++i) { x[i] = (int64_t)llround(pts[i * stride + 0] * scale); y[i] = (int64_t)llround(pts[i * stride + 1] * scale); } int64_t signed_area = (x[M - 1] * y[0] - x[0] * y[M - 1]); for (int i = 0; i < M - 1; ++i) { signed_area += (x[i] * y[i + 1] - x[i + 1] * y[i]); } if (signed_area == 0) { if (M > 1024) { free(x); free(y); } return 0; } int best_idx = 0; double min_cos_concave = 2.0; int best_concave_idx = -1; double min_cos_overall = 2.0; for (int i = 0; i < M; ++i) { int prev = (i == 0) ? M - 1 : i - 1; int next = (i == M - 1) ? 0 : i + 1; int64_t vin_x = x[i] - x[prev]; int64_t vin_y = y[i] - y[prev]; int64_t vout_x = x[next] - x[i]; int64_t vout_y = y[next] - y[i]; int64_t l2_in = vin_x * vin_x + vin_y * vin_y; int64_t l2_out = vout_x * vout_x + vout_y * vout_y; if (l2_in == 0 || l2_out == 0) continue; int64_t cross = vin_x * vout_y - vin_y * vout_x; int is_concave = (signed_area > 0) ? (cross < 0) : (cross > 0); double dot = (double)(vin_x * vout_x + vin_y * vout_y); double denom = sqrt((double)l2_in * (double)l2_out); double cos_ang = dot / denom; if (is_concave) { if (cos_ang < min_cos_concave) { min_cos_concave = cos_ang; best_concave_idx = i; } } if (cos_ang < min_cos_overall) { min_cos_overall = cos_ang; best_idx = i; } } if (M > 1024) { free(x); free(y); } if (best_concave_idx >= 0) return best_concave_idx; return best_idx; } EXPORT void align_path_seam_sharpest_c(const double* in_pts, int M, int stride, double* out_pts, double scale) { int best_idx = find_sharpest_seam_c(in_pts, M, stride, scale); if (best_idx == 0) { memcpy(out_pts, in_pts, (M + 1) * stride * sizeof(double)); return; } int split = M - best_idx; memcpy(out_pts, in_pts + (best_idx * stride), split * stride * sizeof(double)); memcpy(out_pts + (split * stride), in_pts, (best_idx + 1) * stride * sizeof(double)); }