Compare commits

...

3 Commits

Author SHA1 Message Date
c618d22f0b fix: lerp target in ParamChange::MLinAlg 2024-12-03 15:56:36 +01:00
585fdc3a7e feat: add support for centering the screen around best/midpoint
Pressing 'c' will center the screen around the average position of the
particles. Pressing 'f' will center the screen on each frame.

Pressing 'b' will center the screen around the best found point.
2024-11-26 00:08:47 +01:00
4dae604485 feat: add support for drawing velocity vectors 2024-11-26 00:08:19 +01:00
4 changed files with 81 additions and 15 deletions

View File

@@ -40,19 +40,23 @@ struct Screen {
Symbol &at(int x, int y); Symbol &at(int x, int y);
Symbol &at(float x, float y); Symbol &at(float x, float y);
void resize(std::size_t n);
void resize(std::size_t x, std::size_t y); void resize(std::size_t x, std::size_t y);
void move_to(float x, float y);
std::pair<float, float> screen_to_xy(int w, int h); std::pair<float, float> screen_to_xy(int w, int h);
std::pair<int, int> xy_to_screen(float x, float y); std::pair<int, int> xy_to_screen(float x, float y);
Screen(std::size_t n) : buf(nullptr) { resize(n); } Screen(std::size_t x, std::size_t y) : buf(nullptr)
Screen(std::size_t x, std::size_t y) : buf(nullptr) { resize(x, y); } { resize(x, y); move_to(0, 0); }
~Screen() { delete[] buf; } ~Screen() { delete[] buf; }
std::vector<const vec<2>*> points; std::vector<const vec<2>*> points;
std::vector<std::pair<const vec<2>*,const vec<2>*>> vecs;
char_shader_t shader; char_shader_t shader;
bool draw_vecs = true;
private: private:
Symbol *buf; Symbol *buf;
Symbol _dummy; Symbol _dummy;

View File

@@ -66,9 +66,9 @@ namespace ParamChange {
float visc, float nostal, float peerp, int curr, int max) { float visc, float nostal, float peerp, int curr, int max) {
float pct_done = (float)curr / (float)max; float pct_done = (float)curr / (float)max;
return { return {
visc - (0.9f - 0.4f) * pct_done, visc - (visc - 0.4f) * pct_done,
nostal - (2.5f - 0.5f) * pct_done, nostal - (nostal - 0.5f) * pct_done,
peerp + (2.5f - 0.5f) * pct_done, peerp - (peerp - 2.5f) * pct_done,
}; };
} }
}; };
@@ -80,9 +80,9 @@ namespace ParamChange {
float pct_done = (float)curr / (float)max; float pct_done = (float)curr / (float)max;
float scale_factor = (std::tanh(steepness * (pct_done - 0.5)) + 1) / 2; float scale_factor = (std::tanh(steepness * (pct_done - 0.5)) + 1) / 2;
return { return {
visc - (0.9f - 0.4f) * scale_factor, visc - (visc - 0.4f) * scale_factor,
nostal - (2.5f - 0.5f) * scale_factor, nostal - (nostal - 0.5f) * scale_factor,
peerp + (2.5f - 0.5f) * scale_factor, peerp - (peerp - 2.5f) * scale_factor,
}; };
} }
}; };
@@ -132,6 +132,7 @@ struct Particle : public Agent<vec<N>> {
} }
const vec<N> &get_position() const { return position; }; const vec<N> &get_position() const { return position; };
const vec<N> &get_velocity() const { return velocity; };
private: private:
A alg; A alg;

View File

@@ -8,6 +8,7 @@ static constexpr int kFPS = 60;
static constexpr float kDT = 1.0 / kFPS; static constexpr float kDT = 1.0 / kFPS;
float f(vec<2> x) { float f(vec<2> x) {
// return std::pow(x.x, 2) + std::pow(x.y, 2);
return 50 * (std::pow(std::sin((x.x - 10)/2),2) + std::pow(std::sin(x.y/2),2)) + return 50 * (std::pow(std::sin((x.x - 10)/2),2) + std::pow(std::sin(x.y/2),2)) +
std::pow(std::abs(x.x - 3.141592653589), 1.2) + std::pow(std::abs(x.y), 1.2); std::pow(std::abs(x.x - 3.141592653589), 1.2) + std::pow(std::abs(x.y), 1.2);
} }
@@ -53,6 +54,10 @@ main(int argc, char **argv) {
for(const auto &p : swarm.get_particles()) { for(const auto &p : swarm.get_particles()) {
scr.points.push_back(&p.get_position()); scr.points.push_back(&p.get_position());
scr.vecs.push_back({
&p.get_position(),
&p.get_velocity(),
});
} }
enter_noncanonical_mode(); enter_noncanonical_mode();
@@ -61,6 +66,7 @@ main(int argc, char **argv) {
bool pause = false; bool pause = false;
bool frame_step = false; bool frame_step = false;
bool auto_follow = false;
// initialize colorizer scale/translate // initialize colorizer scale/translate
scr.draw(); scr.draw();
@@ -75,6 +81,15 @@ main(int argc, char **argv) {
255, 255, 255, x.x, x.y, y); 255, 255, 255, x.x, x.y, y);
}; };
auto center_screen = [&]() -> void {
vec<2> pos = 0;
for(const auto &p : swarm.get_particles()) {
pos += p.get_position();
}
pos /= swarm.get_particles().size();
scr.move_to(pos.x, pos.y);
};
// We draw to the screen at a rate of `kFPS', but step()ing the swarm at // We draw to the screen at a rate of `kFPS', but step()ing the swarm at
// this rate would be far too fast to be interesting to look at. On the // this rate would be far too fast to be interesting to look at. On the
// other hand, step()ing once a second is too slow. // other hand, step()ing once a second is too slow.
@@ -98,6 +113,8 @@ main(int argc, char **argv) {
printf("Current iteration: %d\nCurrent frame: %d\n", i * 4 / kFPS, i); printf("Current iteration: %d\nCurrent frame: %d\n", i * 4 / kFPS, i);
} }
if(auto_follow) center_screen();
if(frame_step) { if(frame_step) {
pause = true; pause = true;
frame_step = false; frame_step = false;
@@ -174,11 +191,30 @@ main(int argc, char **argv) {
update_and_draw(); update_and_draw();
break; break;
case 'v':
scr.draw_vecs = !scr.draw_vecs;
break;
case 'b': {
const auto [_, b] = swarm.best();
scr.move_to(b.x, b.y);
break;
}
case 'c':
center_screen();
break;
case 'f':
auto_follow = !auto_follow;
break;
case 'h': case 'h':
printf(" movement zoom coloring pause step \n" printf(" movement zoom coloring pause step \n"
" W io IK LO SPC ., \n" " W io IK LO SPC ., \n"
" ASD \n" " ASD \n"
" quit: q \n"); " [%c] draw (v)elocities quit: q \n",
scr.draw_vecs ? 'x' : ' ');
break; break;
} }

View File

@@ -4,11 +4,6 @@
/* Screen */ /* Screen */
void Screen::resize(std::size_t n) {
w = n; h = 1;
buf = (Symbol *)realloc(buf, n * sizeof(Symbol));
}
void Screen::resize(std::size_t x, std::size_t y) { void Screen::resize(std::size_t x, std::size_t y) {
w = x; h = y; w = x; h = y;
buf = (Symbol *)realloc(buf, x * y * sizeof(Symbol)); buf = (Symbol *)realloc(buf, x * y * sizeof(Symbol));
@@ -41,6 +36,10 @@ std::pair<int, int> Screen::xy_to_screen(float x, float y) {
}; };
} }
void Screen::move_to(float x, float y) {
dx = x - w*sx/2;
dy = y - h*sy/2;
}
void Screen::clear() { void Screen::clear() {
static const Symbol s {' ', {0,0,0}}; static const Symbol s {' ', {0,0,0}};
@@ -57,6 +56,32 @@ void Screen::draw() {
} }
} }
// draw lines for each velocity vector
if(draw_vecs) {
for(const auto &[start, vel] : vecs) {
auto end = *start + (*vel) / 3;
if(start->x == end.x) {
// TODO: draw horizontal/vertical lines
continue;
}
auto a = (end.y - start->y) / (end.x - start->x);
auto b = start->y - a * start->x;
for(int i = 0; i < w; ++i) {
const auto [x, _] = screen_to_xy(i, 0);
if(x < std::min(start->x, end.x)
|| x > std::max(start->x, end.x)) continue;
auto y = a*x + b;
at(x, y) = Symbol{
.sym = '+',
.color = { 0.75, 0, 0 },
};
}
}
}
// write out a '#' wherever we have a point registered // write out a '#' wherever we have a point registered
for(const auto &p : points) { for(const auto &p : points) {
at(p->x, p->y) = {.sym = '#', .color = 1}; at(p->x, p->y) = {.sym = '#', .color = 1};