Refactored headers for cleaner design, started stage 1

This commit is contained in:
Rory Healy 2021-09-09 17:10:24 +10:00
parent f7b25ecb92
commit fe1f457038
19 changed files with 229 additions and 135 deletions

View file

@ -16,12 +16,15 @@
# gcc -Wall -Wextra -Werror -pedantic -g -o main.o main.c -c # gcc -Wall -Wextra -Werror -pedantic -g -o main.o main.c -c
# Link command: # Link command:
voronoi2: common.o dcel.o voronoi.o input.o main.o voronoi2: common.o geometry.o dcel.o voronoi.o input.o main.o
gcc -Wall -Wextra -Werror -pedantic -g -o voronoi2 main.o input.o voronoi.o dcel.o common.o gcc -Wall -Wextra -Werror -pedantic -g -o voronoi2 main.o input.o voronoi.o dcel.o geometry.o common.o
common.o: common.c common.o: common.c
gcc -Wall -Wextra -Werror -pedantic -g -o common.o common.c -c gcc -Wall -Wextra -Werror -pedantic -g -o common.o common.c -c
geometry.o: geometry.c
gcc -Wall -Wextra -Werror -pedantic -g -o geometry.o geometry.c -c
dcel.o: dcel.c dcel.o: dcel.c
gcc -Wall -Wextra -Werror -pedantic -g -o dcel.o dcel.c -c gcc -Wall -Wextra -Werror -pedantic -g -o dcel.o dcel.c -c

View file

@ -2,7 +2,7 @@
* *
* Created by Rory Healy (healyr@student.unimelb.edu.au) * Created by Rory Healy (healyr@student.unimelb.edu.au)
* Created on 25th August 2021 * Created on 25th August 2021
* Last modified 8th September 2021 * Last modified 9th September 2021
* *
* Contains functions for general use throughout other files. * Contains functions for general use throughout other files.
* *
@ -12,10 +12,18 @@
#include "common.h" #include "common.h"
#endif #endif
/* Checks if a given pointer is null. Used for malloc() and realloc(). */
void checkNullPointer(void *ptr) { void checkNullPointer(void *ptr) {
if (!ptr) { if (!ptr) {
fputs("Error: Cannot allocate memory.\n", stderr); fputs("Error: Cannot allocate memory.\n", stderr);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
FILE *safeFileOpen(FILE **f, char *fileName, char *mode) {
*f = fopen(fileName, mode);
if (*f == NULL) {
fprintf(stderr, "Error: Unable to open file %s\n", fileName);
exit(EXIT_FAILURE);
}
return *f;
}

View file

@ -12,9 +12,20 @@
#endif #endif
#ifndef STRING_HEADER
#define STRING_HEADER
#include <string.h>
#endif
#ifndef COMMON_HEADER #ifndef COMMON_HEADER
#define COMMON_HEADER #define COMMON_HEADER
/* Checks if a pointer assigned through dynamic memory allocation is NULL */
void checkNullPointer(void *ptr); void checkNullPointer(void *ptr);
/* Opens a file and checks if the file is safe to use */
FILE *safeFileOpen(FILE **f, char *fileName, char *mode);
#endif #endif

BIN
common.o

Binary file not shown.

29
dcel.c
View file

@ -2,7 +2,7 @@
* *
* Created by Rory Healy (healyr@student.unimelb.edu.au) * Created by Rory Healy (healyr@student.unimelb.edu.au)
* Created on 25th August 2021 * Created on 25th August 2021
* Last modified 25th August 2021 * Last modified 9th September 2021
* *
* Contains functions for the DCEL data structure, including creating, * Contains functions for the DCEL data structure, including creating,
* splitting an edge, and identifying towers in faces. * splitting an edge, and identifying towers in faces.
@ -17,36 +17,17 @@
#include "common.h" #include "common.h"
#endif #endif
struct halfEdge {
halfEdge_t *previous;
halfEdge_t *next;
halfEdge_t *twin;
int face;
int edge;
};
struct vertex {
double x;
double y;
};
struct edge {
halfEdge_t halfEdge;
};
struct face {
halfEdge_t start;
};
/* Reads the polygon file and stores the information in the vertices array. */ /* Reads the polygon file and stores the information in the vertices array. */
vertex_t **readPolygon(vertex_t **vertices, FILE *polygonFile, int *numVertices) { vertex_t **readPolygon(vertex_t **vertices, FILE *polygonFile, \
int *numVertices) {
double currentX, currentY; double currentX, currentY;
int maxSizeVertices = 1; int maxSizeVertices = 1;
while ((fscanf(polygonFile, "%lf %lf", &currentX, &currentY)) != EOF) { while ((fscanf(polygonFile, "%lf %lf", &currentX, &currentY)) != EOF) {
/* Check if there enough space in the towers array */ /* Check if there enough space in the towers array */
if (*numVertices == maxSizeVertices) { if (*numVertices == maxSizeVertices) {
maxSizeVertices *= 2; maxSizeVertices *= 2;
vertex_t **temp = realloc(vertices, maxSizeVertices * sizeof(*vertices)); vertex_t **temp = realloc(vertices, \
maxSizeVertices * sizeof(*vertices));
checkNullPointer(temp); checkNullPointer(temp);
vertices = temp; vertices = temp;
} }

28
dcel.h
View file

@ -1,20 +1,32 @@
#ifndef GEOMETRY_HEADER
#include "geometry.h"
#endif
#ifndef STDIO_HEADER #ifndef STDIO_HEADER
#define STDIO_HEADER
#include <stdio.h> #include <stdio.h>
#endif #endif
#ifndef DCEL_HEADER #ifndef DCEL_HEADER
#define DCEL_HEADER #define DCEL_HEADER
typedef struct halfEdge halfEdge_t; typedef struct halfEdge {
typedef struct vertex vertex_t; struct halfEdge *previous;
typedef struct edge edge_t; struct halfEdge *next;
typedef struct face face_t; struct halfEdge *twin;
int face;
int edge;
} halfEdge_t;
typedef struct edge {
halfEdge_t halfEdge;
} edge_t;
typedef struct face {
halfEdge_t start;
} face_t;
vertex_t **readPolygon(vertex_t **vertices, FILE *polygonFile, \ vertex_t **readPolygon(vertex_t **vertices, FILE *polygonFile, \
int *numVertices); int *numVertices);
void freeVertices(vertex_t **vertices, int numVertices); void freeVertices(vertex_t **vertices, int numVertices);
#endif #endif

BIN
dcel.o

Binary file not shown.

23
geometry.c Normal file
View file

@ -0,0 +1,23 @@
/* geometry.c
*
* Created by Rory Healy (healyr@student.unimelb.edu.au)
* Created on 9th September 2021
* Last modified 9th September 2021
*
* A small library of functions used in the geometric construction of a
* Voronoi diagram.
*
*/
#ifndef GEOMETRY_HEADER
#include "geometry.h"
#endif
#ifndef COMMON_HEADER
#include "common.h"
#endif
char *getBisectorEquation(vertex_t *vertexA, vertex_t *vertexB) {
printf("x: %lf y: %lf\n", vertexA->x, vertexB->y);
return "hi";
}

9
geometry.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef GEOMETRY_HEADER
#define GEOMETRY_HEADER
typedef struct vertex {
double x;
double y;
} vertex_t;
#endif

BIN
geometry.o Normal file

Binary file not shown.

15
input.c
View file

@ -2,7 +2,7 @@
* *
* Created by Rory Healy (healyr@student.unimelb.edu.au) * Created by Rory Healy (healyr@student.unimelb.edu.au)
* Created on 8th September 2021 * Created on 8th September 2021
* Last modified 8th September 2021 * Last modified 9th September 2021
* *
* Contains functions for ensuring correct input arguments are given for * Contains functions for ensuring correct input arguments are given for
* each stage of the voronoi2 program. * each stage of the voronoi2 program.
@ -13,6 +13,10 @@
#include "input.h" #include "input.h"
#endif #endif
#ifndef COMMON_HEADER
#include "common.h"
#endif
#define STAGE_1_ARG_COUNT 4 #define STAGE_1_ARG_COUNT 4
#define STAGE_2_ARG_COUNT 5 #define STAGE_2_ARG_COUNT 5
#define STAGE_3_ARG_COUNT 5 #define STAGE_3_ARG_COUNT 5
@ -90,12 +94,3 @@ int getExpectedArgs(enum stages stage) {
} }
return -1; return -1;
} }
FILE *safeFileOpen(FILE **f, char *fileName, char *mode) {
*f = fopen(fileName, mode);
if (*f == NULL) {
fprintf(stderr, "Error: Unable to open file %s\n", fileName);
exit(EXIT_FAILURE);
}
return *f;
}

24
input.h
View file

@ -1,24 +1,3 @@
#ifndef STDIO_HEADER
#define STDIO_HEADER
#include <stdio.h>
#endif
#ifndef STDLIB_HEADER
#define STDLIB_HEADER
#include <stdlib.h>
#endif
#ifndef STRING_HEADER
#define STRING_HEADER
#include <string.h>
#endif
#ifndef INPUT_HEADER #ifndef INPUT_HEADER
#define INPUT_HEADER #define INPUT_HEADER
@ -42,7 +21,4 @@ int getExpectedArgs(enum stages stage);
/* Prints the corresponding usage strings for a given stage */ /* Prints the corresponding usage strings for a given stage */
void printArgError(enum stages stage, char *errorMessage); void printArgError(enum stages stage, char *errorMessage);
/* Opens a file and checks if the file is safe to use */
FILE *safeFileOpen(FILE **f, char *fileName, char *mode);
#endif #endif

BIN
input.o

Binary file not shown.

48
main.c
View file

@ -2,7 +2,7 @@
* *
* Created by Rory Healy (healyr@student.unimelb.edu.au) * Created by Rory Healy (healyr@student.unimelb.edu.au)
* Created on 25th August 2021 * Created on 25th August 2021
* Last modified 8th September 2021 * Last modified 9th September 2021
* *
* Lists the watchtowers that are in each face of the polygon. * Lists the watchtowers that are in each face of the polygon.
* The polygon can be split using a pair of integers, which represent * The polygon can be split using a pair of integers, which represent
@ -74,54 +74,24 @@ int main(int argc, char **argv) {
/* Then run the program according to the stage given */ /* Then run the program according to the stage given */
switch(stage) { switch(stage) {
/* Expected usage: ./voronoi2 1 pointsFile outputFile */ /* Expected usage: ./voronoi2 1 pointsFile outputFile */
case STAGE_1: { case STAGE_1:
FILE *pointsFile = NULL, *outputFile = NULL; stage1(argv[2], argv[3]);
pointsFile = safeFileOpen(&pointsFile, argv[2], "r");
outputFile = safeFileOpen(&outputFile, argv[3], "w");
fclose(pointsFile);
fclose(outputFile);
break; break;
}
/* Expected usage: ./voronoi2 2 pointsFile polygonFile outputFile */ /* Expected usage: ./voronoi2 2 pointsFile polygonFile outputFile */
case STAGE_2: { case STAGE_2:
FILE *pointsFile = NULL, *polygonFile = NULL, *outputFile = NULL; stage2(argv[2], argv[3], argv[4]);
pointsFile = safeFileOpen(&pointsFile, argv[2], "r");
polygonFile = safeFileOpen(&polygonFile, argv[3], "r");
outputFile = safeFileOpen(&outputFile, argv[4], "w");
fclose(pointsFile);
fclose(polygonFile);
fclose(outputFile);
break; break;
}
/* Expected usage: ./voronoi2 3 dataFile polygonFile outputFile */ /* Expected usage: ./voronoi2 3 dataFile polygonFile outputFile */
case STAGE_3: { case STAGE_3:
FILE *dataFile = NULL, *polygonFile = NULL, *outputFile = NULL; stage3(argv[2], argv[3], argv[4]);
dataFile = safeFileOpen(&dataFile, argv[2], "r");
polygonFile = safeFileOpen(&polygonFile, argv[3], "r");
outputFile = safeFileOpen(&outputFile, argv[4], "w");
fclose(dataFile);
fclose(polygonFile);
fclose(outputFile);
break; break;
}
/* Expected usage: /voronoi2 4 dataFile polygonFile outputFile */ /* Expected usage: /voronoi2 4 dataFile polygonFile outputFile */
case STAGE_4: { case STAGE_4:
FILE *dataFile = NULL, *polygonFile = NULL, *outputFile = NULL; stage4(argv[2], argv[3], argv[4]);
dataFile = safeFileOpen(&dataFile, argv[2], "r");
polygonFile = safeFileOpen(&polygonFile, argv[3], "r");
outputFile = safeFileOpen(&outputFile, argv[4], "w");
fclose(dataFile);
fclose(polygonFile);
fclose(outputFile);
break; break;
}
/* Return error if stage number isn't defined. */ /* Return error if stage number isn't defined. */
case STAGE_ERROR: case STAGE_ERROR:

BIN
main.o

Binary file not shown.

115
voronoi.c
View file

@ -2,9 +2,10 @@
* *
* Created by Rory Healy (healyr@student.unimelb.edu.au) * Created by Rory Healy (healyr@student.unimelb.edu.au)
* Created on 12th August 2021 * Created on 12th August 2021
* Last modified 25th August 2021 * Last modified 9th September 2021
* *
* Contains functions involving the reading of the dataset CSV file. * Contains functions involving the generation of the Voronoi diagram, and
* running each stage of the assignment.
* *
*/ */
@ -16,8 +17,6 @@
#include "voronoi.h" #include "voronoi.h"
#endif #endif
#include <string.h>
#define BASE_10 10 #define BASE_10 10
#define MAX_CSV_ENTRY_LEN 512 #define MAX_CSV_ENTRY_LEN 512
#define MAX_FIELD_LEN 128 #define MAX_FIELD_LEN 128
@ -32,13 +31,12 @@ struct tower {
double y; double y;
}; };
/* Reads the CSV file and stores the information in the towers array. */
tower_t **readTowers(tower_t **towers, FILE *datasetFile, int *numTowers) { tower_t **readTowers(tower_t **towers, FILE *datasetFile, int *numTowers) {
/* Maximum length of a single CSV line */ /* Maximum length of a single CSV line */
size_t lineBufferSize = MAX_CSV_ENTRY_LEN + 1; size_t lineBufferSize = MAX_CSV_ENTRY_LEN + 1;
/* Stores the current line from the CSV */ /* Stores the current line from the CSV */
char *lineBuffer = malloc(lineBufferSize * sizeof(char)); char *lineBuffer = malloc(lineBufferSize * sizeof(*lineBuffer));
checkNullPointer(lineBuffer); checkNullPointer(lineBuffer);
int maxSizetowers = 1; int maxSizetowers = 1;
@ -57,15 +55,14 @@ tower_t **readTowers(tower_t **towers, FILE* datasetFile, int *numTowers) {
/* The current tower being filled in with information */ /* The current tower being filled in with information */
towers[*numTowers] = malloc(sizeof(*towers[*numTowers])); towers[*numTowers] = malloc(sizeof(*towers[*numTowers]));
readCurrentLine(lineBuffer, towers[*numTowers]); readCurrentTower(lineBuffer, towers[*numTowers]);
*numTowers += 1; *numTowers += 1;
} }
free(lineBuffer); free(lineBuffer);
return towers; return towers;
} }
/* Takes a line from the CSV and converts the data into a tower_t format */ void readCurrentTower(char *lineBuffer, tower_t *tower) {
void readCurrentLine(char* lineBuffer, tower_t* tower) {
/* Stores the current CSV field for the current line */ /* Stores the current CSV field for the current line */
char *token = strtok(lineBuffer, ","); char *token = strtok(lineBuffer, ",");
size_t tokenLength; size_t tokenLength;
@ -120,3 +117,103 @@ void freeTowers(tower_t **towers, int numTowers) {
} }
free(towers); free(towers);
} }
vertex_t **readPoints(vertex_t **points, FILE *pointsFile, int *numPoints) {
/* Current length of a single points line */
size_t lineBufferSize = 1;
/* Stores the current line from the points file */
char *lineBuffer = malloc(lineBufferSize * sizeof(*lineBuffer));
checkNullPointer(lineBuffer);
/* Assuming that pointsFile is valid, there must be at least two points */
int maxSizePoints = 2;
while (getline(&lineBuffer, &lineBufferSize, pointsFile) > 0) {
/* Check if there is enough space in the points array */
if (*numPoints == maxSizePoints) {
maxSizePoints *= 2;
vertex_t **temp = realloc(points, maxSizePoints * sizeof(*points));
checkNullPointer(temp);
points = temp;
}
double xCoordinateA, yCoordinateA, xCoordinateB, yCoordinateB;
sscanf(lineBuffer, "%lf %lf %lf %lf", &xCoordinateA, &yCoordinateA, \
&xCoordinateB, &yCoordinateB);
points[*numPoints] = malloc(sizeof(*points[*numPoints]));
points[*numPoints]->x = xCoordinateA;
points[*numPoints]->y = yCoordinateA;
*numPoints += 1;
points[*numPoints] = malloc(sizeof(*points[*numPoints]));
points[*numPoints]->x = xCoordinateB;
points[*numPoints]->y = yCoordinateB;
*numPoints += 1;
}
free(lineBuffer);
return points;
}
void freePoints(vertex_t **points, int numPoints) {
for (int i = 0; i < numPoints; i++) {
free(points[i]);
}
free(points);
}
void stage1(char *pointsFileName, char *outputFileName) {
FILE *pointsFile = NULL, *outputFile = NULL;
pointsFile = safeFileOpen(&pointsFile, pointsFileName, "r");
outputFile = safeFileOpen(&outputFile, outputFileName, "w");
vertex_t **points = malloc(sizeof(*points));
checkNullPointer(points);
int numPoints = 0;
// points = readPoints(points, pointsFile, &numPoints);
freePoints(points, numPoints);
fclose(pointsFile);
fclose(outputFile);
}
void stage2(char *pointsFileName, char *polygonFileName, char *outputFileName) {
FILE *pointsFile = NULL, *polygonFile = NULL, *outputFile = NULL;
pointsFile = safeFileOpen(&pointsFile, pointsFileName, "r");
polygonFile = safeFileOpen(&polygonFile, polygonFileName, "r");
outputFile = safeFileOpen(&outputFile, outputFileName, "w");
fclose(pointsFile);
fclose(polygonFile);
fclose(outputFile);
}
void stage3(char *dataFileName, char *polygonFileName, char *outputFileName) {
FILE *dataFile = NULL, *polygonFile = NULL, *outputFile = NULL;
dataFile = safeFileOpen(&dataFile, dataFileName, "r");
polygonFile = safeFileOpen(&polygonFile, polygonFileName, "r");
outputFile = safeFileOpen(&outputFile, outputFileName, "w");
fclose(dataFile);
fclose(polygonFile);
fclose(outputFile);
}
void stage4(char *dataFileName, char *polygonFileName, char *outputFileName) {
FILE *dataFile = NULL, *polygonFile = NULL, *outputFile = NULL;
dataFile = safeFileOpen(&dataFile, dataFileName, "r");
polygonFile = safeFileOpen(&polygonFile, polygonFileName, "r");
outputFile = safeFileOpen(&outputFile, outputFileName, "w");
fclose(dataFile);
fclose(polygonFile);
fclose(outputFile);
}

View file

@ -1,25 +1,34 @@
#ifndef STDIO_HEADER #ifndef DCEL_HEADER
#include "dcel.h"
#define STDIO_HEADER
#include <stdio.h>
#endif
#ifndef STDLIB_HEADER
#define STDLIB_HEADER
#include <stdlib.h>
#endif #endif
#ifndef VORONOI_HEADER #ifndef VORONOI_HEADER
#define VORONOI_HEADER #define VORONOI_HEADER
typedef struct tower tower_t; typedef struct tower tower_t;
/* Reads the CSV file and stores the information in the towers array */
tower_t **readTowers(tower_t **towers, FILE *datasetFile, int *numTowers); tower_t **readTowers(tower_t **towers, FILE *datasetFile, int *numTowers);
void readCurrentLine(char* lineBuffer, tower_t* tower);
/* Reads the current row from the CSV into a new tower */
void readCurrentTower(char *lineBuffer, tower_t *tower);
/* Takes a line from the CSV and converts the data into a tower_t format */
void freeTowers(tower_t **towers, int numTowers); void freeTowers(tower_t **towers, int numTowers);
/* Reads a points file and stores the information in the points array */
vertex_t **readPoints(vertex_t **points, FILE *pointsFile, int *numPoints);
/* Outputs the bisector equations from pointsFile into outputFile */
void stage1(char *pointsFileName, char *outputFileName);
/* Outputs the intersections the bisectors make with the polygon */
void stage2(char *pointsFileName, char *polygonFileName, char *outputFileName);
/* Constructs a Voronoi diagram and prints the resulting diameters */
void stage3(char *dataFileName, char *polygonFileName, char *outputFileName);
/* Same as stage3, but prints diameters in ascending order */
void stage4(char *dataFileName, char *polygonFileName, char *outputFileName);
#endif #endif

BIN
voronoi.o

Binary file not shown.

BIN
voronoi2

Binary file not shown.