test@test-fujitsu:~/kaihatsu/butsuri$ gcc diff_anim.c -o diff_anim -lSDL2 -lm
test@test-fujitsu:~/kaihatsu/butsuri$ ./diff_anim
diff_anim.c
#include <SDL2/SDL.h>
#include <stdio.h>
#include <math.h>
const int WIDTH = 800;
const int HEIGHT = 600;
// 物理空間の範囲
const float X_MIN = -10.0f;
const float X_MAX = 10.0f;
const float Y_MIN = -5.0f;
const float Y_MAX = 105.0f; // x^2 なので最大100くらい
// 関数と微分
float f(float x) { return x * x; }
float f_prime(float x) { return 2 * x; } // x²の微分後
// 物理座標 → 画面座標変換
int to_screen_x(float x) {
return (int)((x - X_MIN) / (X_MAX - X_MIN) * WIDTH);
}
int to_screen_y(float y) {
return (int)(HEIGHT - (y - Y_MIN) / (Y_MAX - Y_MIN) * HEIGHT);
}
int main(int argc, char* argv[]) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("微分可視化",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
WIDTH, HEIGHT, 0);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
float x0 = X_MIN; // 直線の描画開始位置
float speed = 0.05f; // 物理空間での移動量
int running = 1;
SDL_Event e;
// 曲線の事前描画用の枠を準備
SDL_Texture* curve_texture = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_RGBA8888,
SDL_TEXTUREACCESS_TARGET,
WIDTH, HEIGHT);
// 描画用前準備
SDL_SetRenderTarget(renderer, curve_texture);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); // 背景白設定
SDL_RenderClear(renderer); // 白で塗り潰す
// x²の曲線をcurve_textureに描画 毎回書き直さなくて良い用にここに入れておく
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); // 青: 曲線 (赤, 緑, 青, 透明度)
for (float x = X_MIN; x <= X_MAX; x += 0.01f) {
int sx = to_screen_x(x);
int sy = to_screen_y(f(x));
SDL_RenderDrawPoint(renderer, sx, sy);
}
SDL_SetRenderTarget(renderer, NULL); // 元のレンダラーに戻す
while (running) {
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) running = 0;
}
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer);
// curve_textureに描画した曲線を画面上へ描画
SDL_RenderCopy(renderer, curve_texture, NULL, NULL);
// 接線描画(点周辺 ±1 の範囲のみ)
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); // 赤: 接線
float y0 = f(x0);
float slope = f_prime(x0); // 傾きを計算する
for (float dx = -1.0f; dx <= 1.0f; dx += 0.01f) { // -1〜1の範囲で点を描画し直線にする
float x = x0 + dx;
float y_line = y0 + slope * dx;
SDL_RenderDrawPoint(renderer, to_screen_x(x), to_screen_y(y_line));
}
// 画面に描いたものを実際に表示する
SDL_RenderPresent(renderer);
SDL_Delay(16); // 約60FPS
x0 += speed;
if (x0 > X_MAX) x0 = X_MIN;
}
SDL_DestroyTexture(curve_texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
