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);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "mathutils.h"
|
||||
#include "../motion.h"
|
||||
|
||||
typedef point Bezier[3];
|
||||
|
||||
typedef struct {
|
||||
point *arr;
|
||||
int cap;
|
||||
int len;
|
||||
int selected;
|
||||
} BezierPath;
|
||||
|
||||
#define BEZIER_TO_PATH(path) make_bezier_path(3, path)
|
||||
#define RES 0.025
|
||||
|
||||
BezierPath make_bezier_path(int n, point bezier[n]);
|
||||
void free_bezier(BezierPath *path);
|
||||
|
||||
// is this actually needed?
|
||||
// maybe, depending on how I do playback and stuff
|
||||
double get_bez_distance(BezierPath *bezier, double res);
|
||||
bool select_bez_point(int x, int y, BezierPath *path, Field *field);
|
||||
void move_point(int x, int y, BezierPath *path, Field *field);
|
||||
|
||||
// TODO: void deselect_bez_point(BezierPath *path);
|
||||
|
||||
void save_bezier(BezierPath *path, const char *filename, double speed);
|
||||
@@ -0,0 +1,49 @@
|
||||
#include "mathutils.h"
|
||||
#include "../../gfx/gfx.h"
|
||||
#include <corecrt_math.h>
|
||||
|
||||
point scale_to_screen(
|
||||
double x,
|
||||
double y,
|
||||
double w_meters,
|
||||
double h_meters,
|
||||
double x_off,
|
||||
double y_off)
|
||||
{
|
||||
return (point) {
|
||||
.x = x * ((double) SCREEN_WIDTH / w_meters) + x_off,
|
||||
.y = y * ((double) SCREEN_HEIGHT / h_meters) + y_off,
|
||||
};
|
||||
}
|
||||
|
||||
point scale_to_field(
|
||||
double x,
|
||||
double y,
|
||||
double w_meters,
|
||||
double h_meters,
|
||||
double x_off,
|
||||
double y_off)
|
||||
{
|
||||
return (point) {
|
||||
.x = (x - x_off) / ((double) SCREEN_WIDTH / w_meters),
|
||||
.y = (y - y_off) / ((double) SCREEN_HEIGHT / h_meters),
|
||||
};
|
||||
}
|
||||
|
||||
bool within_box(point p, rect r) {
|
||||
return p.x >= r.x && p.y >= r.y &&
|
||||
p.x <= r.x + r.w && p.y <= r.y + r.h;
|
||||
}
|
||||
|
||||
point lerp_point(point a, point b, float p) {
|
||||
return (point) {
|
||||
a.x + (b.x - a.x) * p,
|
||||
a.y + (b.y - a.y) * p
|
||||
};
|
||||
}
|
||||
|
||||
double get_distance(point a, point b) {
|
||||
return sqrt(
|
||||
(a.x - b.x) * (a.x - b.x) +
|
||||
(a.y - b.y) * (a.y - b.y));
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
double x, y;
|
||||
} point;
|
||||
|
||||
typedef struct {
|
||||
double x, y, w, h;
|
||||
} rect;
|
||||
|
||||
#define FIELD_RESCALED field->w_meters, field->h_meters, 0, 0
|
||||
|
||||
// Rescales field coordinates to pixels
|
||||
point scale_to_screen(
|
||||
double x,
|
||||
double y,
|
||||
double w_meters,
|
||||
double h_meters,
|
||||
double x_off,
|
||||
double y_off);
|
||||
|
||||
// Rescales pixel coordinates to meters
|
||||
point scale_to_field(
|
||||
double x,
|
||||
double y,
|
||||
double w_meters,
|
||||
double h_meters,
|
||||
double x_off,
|
||||
double y_off);
|
||||
|
||||
bool within_box(point p, rect r);
|
||||
point lerp_point(point a, point b, float p);
|
||||
double get_distance(point a, point b);
|
||||
Reference in New Issue
Block a user