88 lines
2.7 KiB
C
88 lines
2.7 KiB
C
#include <stdint.h>
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#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));
|
|
}
|