Skip to content
Snippets Groups Projects
Commit b68dc12b authored by tanguy.cavagna's avatar tanguy.cavagna :desktop:
Browse files

Merge branch 'feature-draw-line' into 'master'

Feature : line and cricle draw

See merge request physics/electric-field!1
parents 3d21a0aa 45b2743f
No related branches found
No related tags found
1 merge request!1Feature : line and cricle draw
draw.c 0 → 100644
/**
* @file draw.c
* @author Tanguy Cavagna (tanguy.cavagna@etu.hesge.ch)
* @brief Drawing library
* @version 0.1
* @date 2021-07-12
*
* @copyright Copyright (c) 2021
*
*/
#include "draw.h"
#include "math.h"
/**
* @brief Bresenham's line algorithme.
* Full understanding of the algorithme, but some parts of the
* implementation still blury.
* @see https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#All_cases
*
* @param ctxt Context to draw on
* @param p0 Start point
* @param p1 End point
* @param color Stroke color
*/
void gfx_draw_line(struct gfx_context_t *ctxt, coordinates_t p0, coordinates_t p1, uint32_t color) {
int x0 = p0.column, y0 = p0.row;
int x1 = p1.column, y1 = p1.row;
// Single pixel line
if (x0 == x1 && y0 == y1) {
gfx_putpixel(ctxt, x0, y0, color);
return;
}
int dx = abs(x1 - x0);
int sx = x0 < x1 ? 1 : -1; // Increase if x goes left to right and decrease if right to left
int dy = -abs(y1 - y0);
int sy = y0 < y1 ? 1 : -1; // Increase if y goes up to down and decrease if down to up
int err = dx + dy; // Error value between x and y
int e2;
while (true) {
gfx_putpixel(ctxt, x0, y0, color);
if (x0 == x1 && y0 == y1) break;
e2 = 2 * err;
if (e2 >= dy) { // e_xy + e_x > 0
err += dy;
x0 += sx;
}
if (e2 <= dx) { // e_xy + e_y < 0
err += dx;
y0 += sy;
}
}
}
/**
* @brief Andres's circle algorithm
* @see https://fr.wikipedia.org/wiki/Algorithme_de_tracé_de_cercle_d%27Andres#Algorithme
*
* @param ctxt Context to draw on
* @param c Center
* @param r Radius
* @param color Stroke color
*/
void gfx_draw_circle(struct gfx_context_t *ctxt, coordinates_t c, int r, uint32_t color) {
int xc = c.column;
int yc = c.row;
int x = 0;
int y = r;
int d = r - 1;
while (x < y) {
// Draw octants pixel
gfx_putpixel(ctxt, xc + x, yc + y, color);
gfx_putpixel(ctxt, xc + y, yc + x, color);
gfx_putpixel(ctxt, xc - x, yc + y, color);
gfx_putpixel(ctxt, xc - y, yc + x, color);
gfx_putpixel(ctxt, xc + x, yc - y, color);
gfx_putpixel(ctxt, xc + y, yc - x, color);
gfx_putpixel(ctxt, xc - x, yc - y, color);
gfx_putpixel(ctxt, xc - y, yc - x, color);
// Rotate
if (d >= 2 * x) {
d -= (2 * x) - 1;
x += 1;
} else if (d < 2 * (r - y)) {
d += (2 * y) - 1;
y -= 1;
} else {
d += 2 * (y - x - 1);
y -= 1;
x += 1;
}
}
}
\ No newline at end of file
draw.h 0 → 100644
/**
* @file draw.h
* @author Tanguy Cavagna (tanguy.cavagna@etu.hesge.ch)
* @brief Header of the draw file
* @version 0.1
* @date 2021-07-12
*
* @copyright Copyright (c) 2021
*
*/
#ifndef _DRAW_H_
#define _DRAW_H_
#include <stdlib.h>
#include <stdio.h>
#include "utils.h"
#include "gfx/gfx.h"
/**
* @brief Draw a line using the Bresenham's line algorithm
*
* @param ctxt Context to draw on
* @param p0 Start
* @param p1 End
* @param color Stroke color
*/
void gfx_draw_line(struct gfx_context_t *ctxt, coordinates_t p0, coordinates_t p1, uint32_t color);
/**
* @brief Draw a circle using _______
*
* @param ctxt Context to draw on
* @param c Center
* @param r Raidus
* @param color Stroke color
*/
void gfx_draw_circle(struct gfx_context_t *ctxt, coordinates_t c, int r, uint32_t color);
#endif // _DRAW_H_
File moved
File moved
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include "gfx.h"
#include "gfx/gfx.h"
#include "draw.h"
int main(void) {
const int WINDOW_SIZE_X = 500;
......
# see https://yuukidach.github.io/2019/08/05/makefile-learning/
# Variable setup
CC = gcc
CFLAGS = -Wall -Wextra -std=c11 -g -fsanitize=leak -fsanitize=address
CFLAGS = -Wall -Wextra -std=gnu11 -g -fsanitize=address -fsanitize=leak
LDFLAGS = -lm
LIBS = -lSDL2 -lm
LIBS = -lSDL2
TARGET = main
BIN = bin
SUBDIR = vector
RUN = ./$(BIN)/$(TARGET)
# Get source and object
SOURCE = $(wildcard *.c)
OBJECT = $(patsubst %,$(BIN)/%, $(notdir $(SOURCE:.c=.o)))
# Convert the source in object, but before all, run `$(BIN)` aka mkdir
$(BIN)/%.o: %.c | $(BIN)
$(CC) $(CFLAGS) -c $< -o $@
SRCS = $(wildcard *.c */*.c)
OBJS = $(addprefix $(BIN)/, $(SRCS:.c=.o))
PHONY := $(TARGET)
# Create the target
$(BIN)/$(TARGET): $(OBJECT)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(BIN)/$@ $(OBJS) $(LIBS) $(LDFLAGS)
$(RUN)
$(BIN):
mkdir -p $(BIN)
# Convert the source in object, but before all, run `$(BIN)` aka mkdir
$(BIN)/%.o: %.c
mkdir -p $(@D)
$(CC) $(CFLAGS) -o $@ -c $< $(LDFLAGS)
PHONY += help
# Echo the source and object values
help:
@echo "src: $(SOURCE)"
@echo "obj: $(OBJECT)"
@echo "src: $(SRCS)"
@echo "inc: $(INCS)"
@echo "obj: $(OBJS)"
PHONY += run
# Run the program
run:
$(RUN)
.PHONY: clean # Specify that the clean target is not a file
PHONY += clean
clean:
rm -rf bin
\ No newline at end of file
.PHONY: $(PHONY)
/*! \file Library for vector operations
All the operations are made with a Cartesian vector. If you want a Polar vector, call to_polar().
*/
// To be able to use mathematical constant defined in math.h
#ifndef __USE_MISC
#define __USE_MISC
#endif
#include <math.h>
#include <stdio.h>
#include "vector.h"
/*! \fn vector add_vector(vector v1, vector v2)
\brief Add two vector and return the final vector
\param v1 First vector to add
\param v2 Second vector to add
*/
vector add_vector(vector v1, vector v2) {
vector resultVector;
double finalX = v1.x + v2.x;
double finalY = v1.y + v2.y;
resultVector.x = finalX;
resultVector.y = finalY;
return resultVector;
}
/*! \fn vector sub_vector(vector v1, vector v2)
\brief Substract two vector and return the final vector
\param v1 First vector
\param v2 Vector we want to substract to the first
*/
vector sub_vector(vector v1, vector v2) {
// First we reverse the direction of the vector we want to substract
v2.x *= -1;
v2.y *= -1;
// Then add them as usual
return add_vector(v1, v2);
}
/*! \fn vector mult_by_scalar(vector v1, int scalar)
\brief Multiply a vector by a scalar
\param v1 Vector to multiply
\param scalar Scalar to use for the multiplication
*/
vector mult_by_scalar(vector v1, int scalar) {
vector resultVector = {v1.x * scalar, v1.y * scalar};
return resultVector;
}
/*! \fn double norm(vector v1)
\brief Get the norm of a given vector
\param v1 Vector to multiply
*/
double norm(vector v1) {
double vectorNorm;
vectorNorm = sqrt(pow(v1.x, 2) + pow(v1.y, 2));
return vectorNorm;
}
/*! \fn double dot_multiply(vector v1, vector v2)
\brief Multiply two vector with the dot product formula
\param v1 First vector to multiply
\param v2 Second vector to multiply
*/
double dot_multiply(vector v1, vector v2) {
return (v1.x * v2.x) + (v1.y * v2.y);
}
/*! \fn polarVector to_polar(vector v1)
\brief Convert a Cartesian vector to a Polar vector
\param v1 Cartesian vector
*/
polarVector to_polar(vector v1) {
polarVector p_vector;
p_vector.f = norm(v1);
p_vector.a = atan(v1.y / v1.x) * (180.0 / M_PI); // The atan return a radian angle. Use `* 180 / M_PI` to convert it in degree
return p_vector;
}
/*! \fn vector to_cartesian(polarVector v1)
\brief Convert a Polar vector to a Cartesian vector
\param v1 Polar vector
*/
vector to_cartesian(polarVector v1) {
vector c_vector;
// The cos work with radian angle. Convert degree to radiant inside the cos function to have the correct force
c_vector.x = v1.f * cos(v1.a * (M_PI / 180.0));
c_vector.y = v1.f * sin(v1.a * (M_PI / 180.0));
return c_vector;
}
/*! \file Abstract of the vector-lib file
Contains the skeleton of the vector-lib file. All the functions and structs are defined here.
*/
#ifndef VECTOR_H_ /* Header guard. Prevent the error of double inclusion inside a program. See : https://fr.wikipedia.org/wiki/Include_guard */
#define VECTOR_H_
/**
* @brief Cartesian vector
*/
typedef struct {
double x;
double y;
} vector;
/**
* @brief Polar vector used for representation only
*/
typedef struct {
double f; /* Force of the vector */
double a; /* Angle of the vector */
} polarVector;
vector add_vector(vector v1, vector v2); /* Add a vector to another and return the result as a vector */
vector sub_vector(vector v1, vector v2); /* Substract a vector to another vector and return the result as a vector */
vector mult_by_scalar(vector v1, int scalar); /* Multiply a vector by a scalar */
double dot_multiply(vector v1, vector v2); /* Multiply two vectors with the dot product formula */
double norm(vector v1); /* Get the norm of a given vector */
polarVector to_polar(vector v1); /* Convert a Cartesian vector to a Polar vector */
vector to_cartesian(polarVector v1); /* Convert a Polar vector to a Cartesian vector */
/* For the moment, the cross product hasn't be inplemented because it only work with vectors on 3 dimentionals plan. */
#endif /* VECTOR_H_ */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment