mirror of
https://github.com/Team4388/auto_planner.git
synced 2026-06-09 00:38:06 -06:00
Add files via upload
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
#include "bezier.h"
|
||||
#include "mathutils.h"
|
||||
#include "../motion.h"
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
BezierPath make_bezier_path(int n, point bezier[n]) {
|
||||
BezierPath path = {
|
||||
.arr = malloc(sizeof(point) * n),
|
||||
.cap = n,
|
||||
.len = n,
|
||||
};
|
||||
|
||||
memcpy(path.arr, bezier, sizeof(point) * n);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
void free_bezier(BezierPath *path) {
|
||||
free(path->arr);
|
||||
*path = (BezierPath) {
|
||||
.arr = NULL,
|
||||
.cap = 0,
|
||||
.len = 0,
|
||||
.selected = -1,
|
||||
};
|
||||
}
|
||||
|
||||
double get_bez_distance(BezierPath *bezier, double res) {
|
||||
double dist = 0;
|
||||
|
||||
for (int i = 0; i < bezier->len; i += 2) {
|
||||
point prev = bezier->arr[i];
|
||||
|
||||
for (float j = 0; j < 1.f; j += res) {
|
||||
point percent_a = lerp_point(bezier->arr[i ], bezier->arr[i + 1], j);
|
||||
point percent_b = lerp_point(bezier->arr[i + 1], bezier->arr[i + 2], j);
|
||||
|
||||
point curve = lerp_point(percent_a, percent_b, j);
|
||||
dist += get_distance(prev, curve);
|
||||
|
||||
prev = curve;
|
||||
}
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
bool select_bez_point(int x, int y, BezierPath *path, Field *field) {
|
||||
for (int i = 0; i < path->len; i++) {
|
||||
point node = scale_to_screen(
|
||||
path->arr[i].x,
|
||||
path->arr[i].y,
|
||||
FIELD_RESCALED);
|
||||
rect handle = { node.x - 5, node.y - 5, 10, 10 };
|
||||
|
||||
if (within_box((point) { x, y }, handle)) {
|
||||
path->selected = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void move_point(int x, int y, BezierPath *path, Field *field) {
|
||||
if (path->selected == -1) return;
|
||||
path->arr[path->selected] = scale_to_field(x, y, FIELD_RESCALED);
|
||||
}
|
||||
|
||||
#define DIST 0.01
|
||||
#define DIST_SQ (DIST * DIST)
|
||||
|
||||
/* fuck how do I do this shit?
|
||||
* the issue is traveling a consistent distance along the curve
|
||||
* instead of a percentage of each bezier.
|
||||
*
|
||||
* this is a very slow implementation of `arc length parameterization`
|
||||
*
|
||||
* I don't factor in ramping, which could lead to some problems */
|
||||
void save_bezier(BezierPath *path, const char *filename, double speed) {
|
||||
if (speed < DIST) {
|
||||
printf("bezier cannot be exported with speed %f\n", speed);
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *file;
|
||||
fopen_s(&file, filename, "w+");
|
||||
fprintf(file, "%f,%f,%f,%f,%d\n", 0.f, 0.f, 0.f, 0.f, 0);
|
||||
|
||||
uint32_t time_ms = 0;
|
||||
|
||||
for (int i = 0; i < path->len-1; i += 2) {
|
||||
point prev = path->arr[i];
|
||||
|
||||
for (float j = 0; j < 1.f; j += 0.001) {
|
||||
point percent_a = lerp_point(path->arr[i ], path->arr[i + 1], j);
|
||||
point percent_b = lerp_point(path->arr[i + 1], path->arr[i + 2], j);
|
||||
|
||||
point curve = lerp_point(percent_a, percent_b, j);
|
||||
|
||||
double dist_sq =
|
||||
(prev.x - curve.x) * (prev.x - curve.x) +
|
||||
(prev.y - curve.y) * (prev.y - curve.y);
|
||||
|
||||
if (dist_sq > DIST_SQ) {
|
||||
// are the component distances correct or should I apply normalization?
|
||||
double dist = sqrt(dist_sq);
|
||||
double dist_x = curve.x - prev.x;
|
||||
double dist_y = curve.y - prev.y;
|
||||
|
||||
// does this make sense? am i going insane?
|
||||
double time_sec = dist / speed;
|
||||
double left_x = (dist_y / time_sec) / speed;
|
||||
double left_y = (dist_x / time_sec) / speed;
|
||||
|
||||
time_ms += (uint32_t) (time_sec * 1000);
|
||||
|
||||
fprintf(file, "%f,%f,%f,%f,%d\n",
|
||||
left_x, left_y, 0.f, 0.f, time_ms);
|
||||
prev = curve;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
printf("saved bezier path %s\n", filename);
|
||||
}
|
||||
Reference in New Issue
Block a user