diff --git a/Makefile b/Makefile index 8efc526..c786681 100644 --- a/Makefile +++ b/Makefile @@ -16,12 +16,15 @@ # gcc -Wall -Wextra -Werror -pedantic -g -o main.o main.c -c # Link command: -voronoi2: common.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 +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 geometry.o common.o common.o: common.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 gcc -Wall -Wextra -Werror -pedantic -g -o dcel.o dcel.c -c diff --git a/common.c b/common.c index 374d165..d0bc6c3 100644 --- a/common.c +++ b/common.c @@ -2,7 +2,7 @@ * * Created by Rory Healy (healyr@student.unimelb.edu.au) * Created on 25th August 2021 - * Last modified 8th September 2021 + * Last modified 9th September 2021 * * Contains functions for general use throughout other files. * @@ -12,10 +12,18 @@ #include "common.h" #endif -/* Checks if a given pointer is null. Used for malloc() and realloc(). */ void checkNullPointer(void *ptr) { if (!ptr) { fputs("Error: Cannot allocate memory.\n", stderr); 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; +} diff --git a/common.h b/common.h index 2656928..7709843 100644 --- a/common.h +++ b/common.h @@ -12,9 +12,20 @@ #endif +#ifndef STRING_HEADER +#define STRING_HEADER + +#include + +#endif + #ifndef COMMON_HEADER #define COMMON_HEADER +/* Checks if a pointer assigned through dynamic memory allocation is NULL */ 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 diff --git a/common.o b/common.o index 7b4137c..734d90f 100644 Binary files a/common.o and b/common.o differ diff --git a/dcel.c b/dcel.c index a2ab3be..52af33b 100644 --- a/dcel.c +++ b/dcel.c @@ -2,7 +2,7 @@ * * Created by Rory Healy (healyr@student.unimelb.edu.au) * Created on 25th August 2021 - * Last modified 25th August 2021 + * Last modified 9th September 2021 * * Contains functions for the DCEL data structure, including creating, * splitting an edge, and identifying towers in faces. @@ -17,36 +17,17 @@ #include "common.h" #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. */ -vertex_t **readPolygon(vertex_t **vertices, FILE *polygonFile, int *numVertices) { +vertex_t **readPolygon(vertex_t **vertices, FILE *polygonFile, \ + int *numVertices) { double currentX, currentY; int maxSizeVertices = 1; while ((fscanf(polygonFile, "%lf %lf", ¤tX, ¤tY)) != EOF) { /* Check if there enough space in the towers array */ if (*numVertices == maxSizeVertices) { maxSizeVertices *= 2; - vertex_t **temp = realloc(vertices, maxSizeVertices * sizeof(*vertices)); + vertex_t **temp = realloc(vertices, \ + maxSizeVertices * sizeof(*vertices)); checkNullPointer(temp); vertices = temp; } diff --git a/dcel.h b/dcel.h index 5066490..cabca01 100644 --- a/dcel.h +++ b/dcel.h @@ -1,20 +1,32 @@ +#ifndef GEOMETRY_HEADER +#include "geometry.h" +#endif + #ifndef STDIO_HEADER - -#define STDIO_HEADER #include - #endif #ifndef DCEL_HEADER - #define DCEL_HEADER -typedef struct halfEdge halfEdge_t; -typedef struct vertex vertex_t; -typedef struct edge edge_t; -typedef struct face face_t; +typedef struct halfEdge { + struct halfEdge *previous; + struct halfEdge *next; + 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, \ int *numVertices); void freeVertices(vertex_t **vertices, int numVertices); + #endif diff --git a/dcel.o b/dcel.o index 4c5763b..bda734f 100644 Binary files a/dcel.o and b/dcel.o differ diff --git a/geometry.c b/geometry.c new file mode 100644 index 0000000..8dfe276 --- /dev/null +++ b/geometry.c @@ -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"; +} diff --git a/geometry.h b/geometry.h new file mode 100644 index 0000000..ddd4b3d --- /dev/null +++ b/geometry.h @@ -0,0 +1,9 @@ +#ifndef GEOMETRY_HEADER +#define GEOMETRY_HEADER + +typedef struct vertex { + double x; + double y; +} vertex_t; + +#endif \ No newline at end of file diff --git a/geometry.o b/geometry.o new file mode 100644 index 0000000..46d9a01 Binary files /dev/null and b/geometry.o differ diff --git a/input.c b/input.c index f2c7d63..bfae7eb 100644 --- a/input.c +++ b/input.c @@ -2,7 +2,7 @@ * * Created by Rory Healy (healyr@student.unimelb.edu.au) * 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 * each stage of the voronoi2 program. @@ -13,6 +13,10 @@ #include "input.h" #endif +#ifndef COMMON_HEADER +#include "common.h" +#endif + #define STAGE_1_ARG_COUNT 4 #define STAGE_2_ARG_COUNT 5 #define STAGE_3_ARG_COUNT 5 @@ -90,12 +94,3 @@ int getExpectedArgs(enum stages stage) { } 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; -} diff --git a/input.h b/input.h index 66e70bc..c8d5559 100644 --- a/input.h +++ b/input.h @@ -1,24 +1,3 @@ -#ifndef STDIO_HEADER -#define STDIO_HEADER - -#include - -#endif - -#ifndef STDLIB_HEADER -#define STDLIB_HEADER - -#include - -#endif - -#ifndef STRING_HEADER - -#define STRING_HEADER -#include - -#endif - #ifndef INPUT_HEADER #define INPUT_HEADER @@ -42,7 +21,4 @@ int getExpectedArgs(enum stages stage); /* Prints the corresponding usage strings for a given stage */ 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 diff --git a/input.o b/input.o index c647f13..325dbb4 100644 Binary files a/input.o and b/input.o differ diff --git a/main.c b/main.c index 0c653d2..24d23a2 100644 --- a/main.c +++ b/main.c @@ -2,7 +2,7 @@ * * Created by Rory Healy (healyr@student.unimelb.edu.au) * 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. * 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 */ switch(stage) { /* Expected usage: ./voronoi2 1 pointsFile outputFile */ - case STAGE_1: { - FILE *pointsFile = NULL, *outputFile = NULL; - pointsFile = safeFileOpen(&pointsFile, argv[2], "r"); - outputFile = safeFileOpen(&outputFile, argv[3], "w"); - - fclose(pointsFile); - fclose(outputFile); + case STAGE_1: + stage1(argv[2], argv[3]); break; - } /* Expected usage: ./voronoi2 2 pointsFile polygonFile outputFile */ - case STAGE_2: { - FILE *pointsFile = NULL, *polygonFile = NULL, *outputFile = NULL; - pointsFile = safeFileOpen(&pointsFile, argv[2], "r"); - polygonFile = safeFileOpen(&polygonFile, argv[3], "r"); - outputFile = safeFileOpen(&outputFile, argv[4], "w"); - - fclose(pointsFile); - fclose(polygonFile); - fclose(outputFile); + case STAGE_2: + stage2(argv[2], argv[3], argv[4]); break; - } /* Expected usage: ./voronoi2 3 dataFile polygonFile outputFile */ - case STAGE_3: { - FILE *dataFile = NULL, *polygonFile = NULL, *outputFile = NULL; - dataFile = safeFileOpen(&dataFile, argv[2], "r"); - polygonFile = safeFileOpen(&polygonFile, argv[3], "r"); - outputFile = safeFileOpen(&outputFile, argv[4], "w"); - - fclose(dataFile); - fclose(polygonFile); - fclose(outputFile); + case STAGE_3: + stage3(argv[2], argv[3], argv[4]); break; - } /* Expected usage: /voronoi2 4 dataFile polygonFile outputFile */ - case STAGE_4: { - FILE *dataFile = NULL, *polygonFile = NULL, *outputFile = NULL; - dataFile = safeFileOpen(&dataFile, argv[2], "r"); - polygonFile = safeFileOpen(&polygonFile, argv[3], "r"); - outputFile = safeFileOpen(&outputFile, argv[4], "w"); - - fclose(dataFile); - fclose(polygonFile); - fclose(outputFile); + case STAGE_4: + stage4(argv[2], argv[3], argv[4]); break; - } /* Return error if stage number isn't defined. */ case STAGE_ERROR: diff --git a/main.o b/main.o index e1b3a8b..af22448 100644 Binary files a/main.o and b/main.o differ diff --git a/voronoi.c b/voronoi.c index 0d02e27..816641e 100644 --- a/voronoi.c +++ b/voronoi.c @@ -2,10 +2,11 @@ * * Created by Rory Healy (healyr@student.unimelb.edu.au) * Created on 12th August 2021 - * Last modified 25th August 2021 - * - * Contains functions involving the reading of the dataset CSV file. + * Last modified 9th September 2021 * + * Contains functions involving the generation of the Voronoi diagram, and + * running each stage of the assignment. + * */ #ifndef COMMON_HEADER @@ -16,8 +17,6 @@ #include "voronoi.h" #endif -#include - #define BASE_10 10 #define MAX_CSV_ENTRY_LEN 512 #define MAX_FIELD_LEN 128 @@ -32,13 +31,12 @@ struct tower { 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 */ size_t lineBufferSize = MAX_CSV_ENTRY_LEN + 1; /* Stores the current line from the CSV */ - char *lineBuffer = malloc(lineBufferSize * sizeof(char)); + char *lineBuffer = malloc(lineBufferSize * sizeof(*lineBuffer)); checkNullPointer(lineBuffer); 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 */ towers[*numTowers] = malloc(sizeof(*towers[*numTowers])); - readCurrentLine(lineBuffer, towers[*numTowers]); + readCurrentTower(lineBuffer, towers[*numTowers]); *numTowers += 1; } free(lineBuffer); return towers; } -/* Takes a line from the CSV and converts the data into a tower_t format */ -void readCurrentLine(char* lineBuffer, tower_t* tower) { +void readCurrentTower(char *lineBuffer, tower_t *tower) { /* Stores the current CSV field for the current line */ char *token = strtok(lineBuffer, ","); size_t tokenLength; @@ -120,3 +117,103 @@ void freeTowers(tower_t **towers, int numTowers) { } 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); +} diff --git a/voronoi.h b/voronoi.h index 10113b1..a5e8d0c 100644 --- a/voronoi.h +++ b/voronoi.h @@ -1,25 +1,34 @@ -#ifndef STDIO_HEADER - -#define STDIO_HEADER -#include - -#endif - -#ifndef STDLIB_HEADER - -#define STDLIB_HEADER -#include - +#ifndef DCEL_HEADER +#include "dcel.h" #endif #ifndef VORONOI_HEADER - #define VORONOI_HEADER typedef struct tower tower_t; -tower_t** readTowers(tower_t **towers, FILE* datasetFile, int *numTowers); -void readCurrentLine(char* lineBuffer, tower_t* tower); +/* Reads the CSV file and stores the information in the towers array */ +tower_t **readTowers(tower_t **towers, FILE *datasetFile, int *numTowers); + +/* 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); +/* 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 diff --git a/voronoi.o b/voronoi.o index d96fd7c..7a5cc09 100644 Binary files a/voronoi.o and b/voronoi.o differ diff --git a/voronoi2 b/voronoi2 index 878fc9a..8f53c7b 100755 Binary files a/voronoi2 and b/voronoi2 differ