fixed the issue of entire Y-axis being plotted due to an overflow error
This commit is contained in:
		
							
								
								
									
										56
									
								
								src/main.zig
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								src/main.zig
									
									
									
									
									
								
							@@ -17,20 +17,21 @@ pub fn main() !void {
 | 
			
		||||
    defer rl.closeWindow();
 | 
			
		||||
 | 
			
		||||
    rl.setTargetFPS(60);
 | 
			
		||||
 | 
			
		||||
    // todo move away from being a loop, a static trigonometry should not be redrawn every frame
 | 
			
		||||
    rl.beginDrawing();
 | 
			
		||||
 | 
			
		||||
    rl.clearBackground(rl.Color.white);
 | 
			
		||||
 | 
			
		||||
    try markAxis(allocator);
 | 
			
		||||
    plotGraph();
 | 
			
		||||
    drawAxis();
 | 
			
		||||
    try markAxis(allocator);
 | 
			
		||||
 | 
			
		||||
    rl.endDrawing();
 | 
			
		||||
 | 
			
		||||
    while (!rl.windowShouldClose()) {
 | 
			
		||||
        rl.beginDrawing();
 | 
			
		||||
        // DEBUG
 | 
			
		||||
        // const pos = rl.getMousePosition();
 | 
			
		||||
        // std.debug.print("x: {d} y:{}\n", .{ pos.x, pos.y });
 | 
			
		||||
        rl.endDrawing();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -55,7 +56,7 @@ fn markAxis(allocator: std.mem.Allocator) !void {
 | 
			
		||||
    var cnt: usize = 0;
 | 
			
		||||
    var i: i32 = start_x;
 | 
			
		||||
    while (i <= SCREENWIDTH) : (i += SCALE) {
 | 
			
		||||
        // get
 | 
			
		||||
        // int to string
 | 
			
		||||
        const text = try std.fmt.bufPrintZ(&buf, "{}", .{cnt});
 | 
			
		||||
        cnt += 1;
 | 
			
		||||
        // 0 is due to us working with C-style strings
 | 
			
		||||
@@ -75,17 +76,30 @@ fn markAxis(allocator: std.mem.Allocator) !void {
 | 
			
		||||
        rl.drawText(text_back, SCREENWIDTH - i - diff - diff / 2, start_y + diff, font_size, rl.Color.black);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // start at 1 as we're not drawing 0 this time
 | 
			
		||||
    cnt = 1;
 | 
			
		||||
    i = start_y;
 | 
			
		||||
    while (i <= SCREENHEIGHT) : (i += SCALE) {
 | 
			
		||||
        // +y
 | 
			
		||||
        rl.drawCircle(start_x, @intCast(i), radius, rl.Color.black);
 | 
			
		||||
        // skip 0 as it is already rendered during x scale
 | 
			
		||||
        if (i == start_y) continue;
 | 
			
		||||
 | 
			
		||||
        const text = try std.fmt.bufPrintZ(&buf, "{}", .{cnt});
 | 
			
		||||
        cnt += 1;
 | 
			
		||||
        var text_back = try allocator.allocSentinel(u8, text.len + 1, 0);
 | 
			
		||||
        defer allocator.free(text_back);
 | 
			
		||||
        @memcpy(text_back[0..1], "-");
 | 
			
		||||
        @memcpy(text_back[1..], text);
 | 
			
		||||
 | 
			
		||||
        // -y
 | 
			
		||||
        rl.drawCircle(start_x, @intCast(i), radius, rl.Color.black);
 | 
			
		||||
        rl.drawText(text_back, start_x + diff, @as(i32, @intCast(i)) - diff, font_size, rl.Color.black);
 | 
			
		||||
 | 
			
		||||
        // +y
 | 
			
		||||
        rl.drawCircle(start_x, SCREENHEIGHT - i, radius, rl.Color.black);
 | 
			
		||||
        rl.drawText(text, start_x + diff, SCREENHEIGHT - i - diff, font_size, rl.Color.black);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// todo in the future we will do calculations only once and just repeat displaying
 | 
			
		||||
fn plotGraph() void {
 | 
			
		||||
    const diff: f32 = 0.01;
 | 
			
		||||
    const thickness = 2.5;
 | 
			
		||||
@@ -94,36 +108,36 @@ fn plotGraph() void {
 | 
			
		||||
    while (x_value <= SCREENWIDTH) : (x_value += diff) {
 | 
			
		||||
        const cur_pos = adjustForGridSystem(rl.Vector2{
 | 
			
		||||
            .x = x_value,
 | 
			
		||||
            .y = getY(x_value),
 | 
			
		||||
            .y = getY(x_value) catch {
 | 
			
		||||
                continue;
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // this is to ensure the value doesn't wrap around to zero causing the entire Y-axis to be graphed
 | 
			
		||||
        if (cur_pos.y > SCREENHEIGHT) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const next_pos = adjustForGridSystem(rl.Vector2{
 | 
			
		||||
            .x = x_value + diff,
 | 
			
		||||
            .y = getY(x_value + diff),
 | 
			
		||||
            .y = getY(x_value + diff) catch {
 | 
			
		||||
                continue;
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // test
 | 
			
		||||
        if (cur_pos.x == 0 or next_pos.x == 0) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        rl.drawLineEx(cur_pos, next_pos, thickness, rl.Color.dark_blue);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// f(x)
 | 
			
		||||
fn getY(x: f32) f32 {
 | 
			
		||||
    const min_threshold = 1e-3;
 | 
			
		||||
    const a = x / 10;
 | 
			
		||||
    var b: f32 = 1.0;
 | 
			
		||||
    if (b == 0) b = a / min_threshold;
 | 
			
		||||
 | 
			
		||||
    return a / b;
 | 
			
		||||
fn getY(x: f32) !f32 {
 | 
			
		||||
    return math.calculate(x, -3, .Power);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn adjustForGridSystem(input_vector: rl.Vector2) rl.Vector2 {
 | 
			
		||||
    // std.debug.print("{d} => {d}\n", .{ input_vector.x, input_vector.x * SCALE });
 | 
			
		||||
    const new_vector = rl.Vector2{
 | 
			
		||||
        // we add screenwidth because in traditional gui libraries the grid starts in top left and not in the center like the coordinate system
 | 
			
		||||
        .x = input_vector.x * SCALE + SCREENWIDTH / 2,
 | 
			
		||||
        .y = -input_vector.y * SCALE + SCREENHEIGHT / 2, // minus is there because y works the opposite in gui libraries than in coordination system
 | 
			
		||||
    };
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										36
									
								
								src/math.zig
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								src/math.zig
									
									
									
									
									
								
							@@ -1,4 +1,36 @@
 | 
			
		||||
pub fn abs(a: f32) f32 {
 | 
			
		||||
const std = @import("std");
 | 
			
		||||
 | 
			
		||||
pub const MathOperation = enum {
 | 
			
		||||
    Division,
 | 
			
		||||
    Power,
 | 
			
		||||
    Root,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
pub fn calculate(first: f32, second: f32, op: MathOperation) !f32 {
 | 
			
		||||
    switch (op) {
 | 
			
		||||
        .Division => {
 | 
			
		||||
            if (second == 0) {
 | 
			
		||||
                return error.InvalidParam;
 | 
			
		||||
            }
 | 
			
		||||
            return first / second;
 | 
			
		||||
        },
 | 
			
		||||
        .Power => {
 | 
			
		||||
            if (first == 0) std.debug.print("KOK", .{});
 | 
			
		||||
            if (first == 0 and second < 0) {
 | 
			
		||||
                return error.InvalidParam;
 | 
			
		||||
            }
 | 
			
		||||
            return pow(first, @intFromFloat(second));
 | 
			
		||||
        },
 | 
			
		||||
        .Root => {
 | 
			
		||||
            if (first < 0 or second < 0) {
 | 
			
		||||
                return error.InvalidParam;
 | 
			
		||||
            }
 | 
			
		||||
            return std.math.sqrt(second);
 | 
			
		||||
        },
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn abs(a: f32) f32 {
 | 
			
		||||
    if (a < 0) {
 | 
			
		||||
        return -a;
 | 
			
		||||
    }
 | 
			
		||||
@@ -6,7 +38,7 @@ pub fn abs(a: f32) f32 {
 | 
			
		||||
    return a;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn pow(a: f32, b: i32) f32 {
 | 
			
		||||
fn pow(a: f32, b: i32) f32 {
 | 
			
		||||
    var res: f32 = 1.0;
 | 
			
		||||
    var n: usize = undefined;
 | 
			
		||||
    var f: f32 = undefined;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user