Task 2 completed

This commit is contained in:
Rory Healy 2021-09-13 12:27:17 +10:00
parent b1697a0c30
commit 11b8feaa6e
18 changed files with 370 additions and 457 deletions

46
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,46 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Voronoi2 - 1",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/voronoi2",
"args": ["1", "pp_inside.txt", "output.txt"],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
},
{
"name": "Voronoi2 - 2",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/voronoi2",
"args": ["2", "pp_inside.txt", "polygon_square.txt", "output.txt"],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}

View file

@ -1,24 +1,8 @@
# Link command:
#voronoi1: common.o dcel.o voronoi.o main.o
# gcc -Wall -Wextra -Werror -pedantic -g -o voronoi1 main.o voronoi.o dcel.o common.o
# Compilation commands:
#common.o: common.c
# gcc -Wall -Wextra -Werror -pedantic -g -o common.o common.c -c
#
#dcel.o: dcel.c
# gcc -Wall -Wextra -Werror -pedantic -g -o dcel.o dcel.c -c
#
#voronoi.o: voronoi.c
# gcc -Wall -Wextra -Werror -pedantic -g -o voronoi.o voronoi.c -c
#
#main.o: main.c
# gcc -Wall -Wextra -Werror -pedantic -g -o main.o main.c -c
# Link command:
voronoi2: common.o towers.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 towers.o common.o -lm
gcc -Wall -Wextra -Werror -pedantic -g -o voronoi2 main.o input.o voronoi.o dcel.o towers.o common.o
# Compilation commands
common.o: common.c
gcc -Wall -Wextra -Werror -pedantic -g -o common.o common.c -c
@ -31,8 +15,8 @@ dcel.o: dcel.c
voronoi.o: voronoi.c
gcc -Wall -Wextra -Werror -pedantic -g -o voronoi.o voronoi.c -c
main.o: main.c
gcc -Wall -Wextra -Werror -pedantic -g -o main.o main.c -c
input.o: input.c
gcc -Wall -Wextra -Werror -pedantic -g -o input.o input.c -c
main.o: main.c
gcc -Wall -Wextra -Werror -pedantic -g -o main.o main.c -c

View file

@ -19,13 +19,6 @@
#endif
#ifndef MATH_HEADER
#define MATH_HEADER
#include <math.h>
#endif
#ifndef COMMON_HEADER
#define COMMON_HEADER

BIN
common.o

Binary file not shown.

437
dcel.c
View file

@ -2,7 +2,7 @@
*
* Created by Rory Healy (healyr@student.unimelb.edu.au)
* Created on 25th August 2021
* Last modified 11th September 2021
* Last modified 13th September 2021
*
* Contains functions for the DCEL data structure, including initialisation,
* splitting an edge, and identifying towers in faces.
@ -16,74 +16,145 @@
#include "dcel.h"
#endif
/* Deprecated by Grady's sample solution */
vertex_t **readPolygon(vertex_t **vertices, FILE *polygonFile, \
int *numVertices) {
double currentX, currentY;
int maxSizeVertices = 1;
while ((fscanf(polygonFile, "%lf %lf", &currentX, &currentY)) != EOF) {
/* Check if there enough space in the towers array */
if (*numVertices == maxSizeVertices) {
maxSizeVertices *= 2;
vertex_t **temp = realloc(vertices, \
maxSizeVertices * sizeof(*vertices));
void freePoints(vertex_t **points, int numPoints) {
for (int i = 0; i < numPoints; i++) {
free(points[i]);
}
free(points);
}
void freeBisectors(bisector_t **bisectors, int numBisectors) {
for (int i = 0; i < numBisectors; i++) {
free(bisectors[i]->mid);
free(bisectors[i]);
}
free(bisectors);
}
void freeIntersections(intersection_t **intersections, int numIntersections) {
for (int i = 0; i < numIntersections; i++) {
free(intersections[i]->fromPoint);
free(intersections[i]->toPoint);
free(intersections[i]);
}
free(intersections);
}
bisector_t **getBisectors(bisector_t **bisectors, vertex_t **points, \
int numBisectors) {
for (int i = 0; i < numBisectors; i++) {
bisectors[i] = malloc(sizeof(*bisectors[i]));
bisectors[i]->mid = malloc(sizeof(*bisectors[i]->mid));
/* Calculate midpoint of the two points */
bisectors[i]->mid->x = (points[2 * i]->x + points[2 * i + 1]->x) / 2;
bisectors[i]->mid->y = (points[2 * i]->y + points[2 * i + 1]->y) / 2;
/* Calculating bisector slope according to slope of AB */
if (points[2 * i]->x == points[2 * i + 1]->x) {
/* The line segment AB has an infinite gradient,
* so the orthogonal line will have zero slope.
*/
bisectors[i]->slope = 0;
bisectors[i]->isSlopeInfinite = 0;
} else if (points[2 * i]->y == points[2 * i + 1]->y) {
/* The line segment AB has gradient of zero, so
* the orthogonal line will have an infinite slope.
*/
bisectors[i]->isSlopeInfinite = 1;
/* Not actually zero, just a placeholder to prevent
* accidental errors
*/
bisectors[i]->slope = 0;
} else {
/* The line segment AB has a non-zero and finite gradient,
* so the gradient of the bisector can be calculated.
*/
bisectors[i]->isSlopeInfinite = 0;
bisectors[i]->slope = -1 / \
((points[2 * i + 1]->y - points[2 * i]->y) / \
(points[2 * i + 1]->x - points[2 * i]->x));
}
}
return bisectors;
}
vertex_t *getBisectorPoint(double distance, bisector_t *b, int direction) {
vertex_t *returnPoint = malloc(sizeof(*returnPoint));
if (b->isSlopeInfinite) {
/* Vertical line - just add vertical distance */
returnPoint->x = b->mid->x;
returnPoint->y = b->mid->y + (distance * direction);
} else if (b->slope == 0) {
/* Horizontal line - just add horizontal distance */
returnPoint->x = b->mid->x + (distance * direction);
returnPoint->y = b->mid->y;
} else {
/* Not horizontal or vertical - add distance to x, then find
* y-intercept of the bisector, and plug it in to y = mx + c to find
* the corresponding y-value.
*/
double c = b->mid->y - b->slope * b->mid->x;
returnPoint->x = b->mid->x + (distance * direction);
returnPoint->y = b->slope * returnPoint->x + c;
}
return returnPoint;
}
intersection_t *newIntersection() {
intersection_t *intersection = malloc(sizeof(*intersection));
checkNullPointer(intersection);
intersection->fromPoint = malloc(sizeof(*intersection->fromPoint));
checkNullPointer(intersection->fromPoint);
intersection->toPoint = malloc(sizeof(*intersection->toPoint));
checkNullPointer(intersection->toPoint);
return intersection;
}
vertex_t **readPoints(vertex_t **points, FILE *pointsFile, int *numPoints) {
/* Initial size of buffer is 1 as getline() reallocs as needed */
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) {
/* Ensure there is enough space in the points array */
if (*numPoints == maxSizePoints) {
maxSizePoints *= 2;
vertex_t **temp = realloc(points, maxSizePoints * sizeof(*points));
checkNullPointer(temp);
vertices = temp;
points = temp;
}
/* The current vertex being filled in with information */
vertices[*numVertices] = malloc(sizeof(*vertices[*numVertices]));
vertices[*numVertices]->x = currentX;
vertices[*numVertices]->y = currentY;
*numVertices += 1;
}
return vertices;
}
double xCoordinateA, yCoordinateA, xCoordinateB, yCoordinateB;
sscanf(lineBuffer, "%lf %lf %lf %lf", &xCoordinateA, &yCoordinateA, \
&xCoordinateB, &yCoordinateB);
void freeVertices(vertex_t **vertices, int numVertices) {
for (int i = 0; i < numVertices; i++) {
free(vertices[i]);
}
free(vertices);
}
points[*numPoints] = malloc(sizeof(*points[*numPoints]));
points[*numPoints]->x = xCoordinateA;
points[*numPoints]->y = yCoordinateA;
*numPoints += 1;
bisector_t *getBisector(vertex_t *pointA, vertex_t *pointB) {
bisector_t *newBisector = malloc(sizeof(*newBisector));
checkNullPointer(newBisector);
double midpointX = (pointA->x + pointB->x) / 2;
double midpointY = (pointA->y + pointB->y) / 2;
newBisector->midX = midpointX;
newBisector->midY = midpointY;
/* Calculating bisector slope according to slope of AB */
if (pointA->x == pointB->x) {
/* The line segment AB has an infinite gradient,
* so the orthogonal line will have zero slope.
*/
newBisector->slope = 0;
newBisector->isSlopeInfinite = 0;
} else if (pointA->y == pointB->y) {
/* The line segment AB has gradient of zero, so
* the orthogonal line will have an infinite slope.
*/
newBisector->isSlopeInfinite = 1;
/* Not actually zero, just a placeholder to prevent
* accidental errors
*/
newBisector->slope = 0;
} else {
/* The line segment AB has a non-zero and finite gradient,
* so the gradient of the bisector can be calculated.
*/
newBisector->isSlopeInfinite = 0;
newBisector->slope = -1 / \
((pointB->y - pointA->y) / (pointB->x - pointA->x));
points[*numPoints] = malloc(sizeof(*points[*numPoints]));
points[*numPoints]->x = xCoordinateB;
points[*numPoints]->y = yCoordinateB;
*numPoints += 1;
}
return newBisector;
free(lineBuffer);
return points;
}
/* Here on out is the base code from Grady, with some alterations from me */
@ -99,48 +170,6 @@ bisector_t *getBisector(vertex_t *pointA, vertex_t *pointB) {
#define OUTSIDE (-1)
#define NODIAMETER (-1)
double dist_2D(double x1, double y1, double x2, double y2) {
return sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));
}
double inv_dist_2D(double x1, double y1, double m, double c1, double d) {
/* Solve sqrt((y - y1)^2 + (x - x1)^2) = d^2 for x by substituting
* y = mx + c1, which gives an equation for x
* Using this, you can find a point that lies on the line y = mx + c1
* that is of distance d away from (x1, y1).
*/
double a = m * m + 1;
double b = 2 * c1 * m - 2 * x1 - 2 * m * y1;
double c = c1 * c1 + x1 * x1 + y1 * y1 - 2 * c1 * y1 - d * d;
return (-b + sqrt(b * b - 4 * a * c)) / (2 * a);
}
vertex_t *getBisectorPoint(double distance, bisector_t *b) {
vertex_t *returnPoint = malloc(sizeof(*returnPoint));
if (b->isSlopeInfinite) {
returnPoint->x = b->midX;
returnPoint->y = b->midY + distance;
} else if (b->slope == 0) {
returnPoint->x = b->midX + distance;
returnPoint->y = b->midY;
} else {
/* Find the y-intercept of the bisector, use it to find the general
* form of the bisector in the form of y = mx + c
*/
double c = b->midY - b->slope * b->midX;
returnPoint->x = inv_dist_2D(b->midX, b->midY, b->slope, c, distance);
returnPoint->y = b->slope * returnPoint->x + c;
}
/* Due to floating-point precision, there may be a situation where the
* distance between the bisector midpoint and returnPoint is slightly less
* than distance, but unless getBisectorPoint needs to guarentee that this
* distance is greater than distance, it shouldn't be an issue.
*/
return returnPoint;
}
/*
This intersection is based on code by Joseph O'Rourke and is provided for use in
COMP20003 Assignment 2.
@ -246,14 +275,17 @@ enum intersectType intersects(halfEdge_t *he, bisector_t *b, \
double heEy = dcel->vertices[he->endVertex].y;
/* Bisector x, y twin */
double bSx = b->startX;
double bSy = b->startY;
double bEx = b->endX;
double bEy = b->endY;
vertex_t *startPoint = getBisectorPoint(minLength, b, -1);
vertex_t *endPoint = getBisectorPoint(minLength, b, 1);
double bSx = startPoint->x;
double bSy = startPoint->y;
double bEx = endPoint->x;
double bEy = endPoint->y;
free(startPoint);
free(endPoint);
/* Fill in segment. */
// min-length not used here?
printf("In intersets(): minlength = %lf\n", minLength);
/* Parametric equation parameters */
double t1, t2;
@ -344,53 +376,6 @@ enum intersectType intersects(halfEdge_t *he, bisector_t *b, \
}
}
char *getIntersectionString(intersection_t *intersection) {
/*
FILL IN
*/
if (!intersection) {
return NULL;
}
char *returnString = NULL;
if (0 <= 0) {
/* Find out memory needed. */
int stringLength = snprintf(returnString, 0,
"From Edge %d (%lf, %lf) to Edge %d (%lf, %lf)",
0, 0.0, 0.0,
0, 0.0, 0.0);
returnString = malloc(sizeof(*returnString) * (stringLength + 1));
checkNullPointer(returnString);
sprintf(returnString, "From Edge %d (%lf, %lf) to Edge %d (%lf, %lf)",
0, 0.0, 0.0,
0, 0.0, 0.0);
} else {
/* Find out memory needed. */
int stringLength = snprintf(returnString, 0,
"From Edge %d (%lf, %lf) to Edge %d (%lf, %lf)",
0, 0.0, 0.0,
0, 0.0, 0.0);
returnString = malloc(sizeof(*returnString) * (stringLength + 1));
checkNullPointer(returnString);
sprintf(returnString, "From Edge %d (%lf, %lf) to Edge %d (%lf, %lf)",
0, 0.0, 0.0,
0, 0.0, 0.0);
}
return returnString;
}
void freeIntersection(intersection_t *intersection) {
if (!intersection) {
return;
}
free(intersection);
}
DCEL_t *newDCEL() {
/* Setup DCEL. */
DCEL_t *dcel = malloc(sizeof(*dcel));
@ -1026,82 +1011,72 @@ int inFace(DCEL_t *dcel, double x, double y, int faceIndex) {
return 1;
}
int getDCELPointCount(DCEL_t *dcel) {
if (!dcel) {
return 0;
intersection_t **getIntersections(intersection_t **intersections, \
int *numIntersections, bisector_t **bisectors, int numBisectors, \
DCEL_t *dcel, int face, double minLength) {
int maxSizeIntersections = 1;
for (int i = 0; i < numBisectors; i++) {
intersection_t *currentIntersection = NULL;
/* Intersection coordinates */
double x, y;
/* Flag is raised when first intersection is found */
int isIntersectionFound = 0;
halfEdge_t *startHE = (dcel->faces)[face].start;
halfEdge_t *currentHE = startHE;
int startVertex = startHE->startVertex;
int first = 1;
/* Loop through the face until the starting vertex is reached */
while (first || currentHE->startVertex != startVertex) {
enum intersectType typeOfIntersection = \
intersects(currentHE, bisectors[i], dcel, minLength, &x, &y);
switch (typeOfIntersection) {
case INTERSECT:
case SAME_LINE_OVERLAP:
case ENDS_OVERLAP:
if (!isIntersectionFound) {
/* First point of intersection */
isIntersectionFound = 1;
currentIntersection = newIntersection();
currentIntersection->fromPoint->x = x;
currentIntersection->fromPoint->y = y;
currentIntersection->fromEdge = currentHE->edge;
} else {
/* Second point of intersection */
currentIntersection->toPoint->x = x;
currentIntersection->toPoint->y = y;
currentIntersection->toEdge = currentHE->edge;
}
break;
case DOESNT_INTERSECT:
default:
break;
}
currentHE = currentHE->next;
first = 0;
}
/* If there is an intersection, add it to the array */
if (currentIntersection != NULL) {
/* Ensure there is enough space in the array */
if (*numIntersections == maxSizeIntersections) {
maxSizeIntersections *= 2;
intersection_t **temp = realloc(intersections, maxSizeIntersections * sizeof(*intersections));
checkNullPointer(temp);
intersections = temp;
}
intersections[*numIntersections] = currentIntersection;
*numIntersections += 1;
}
}
return dcel->verticesUsed;
}
double getDCELVertexX(DCEL_t *dcel, int vertex) {
return (dcel->vertices)[vertex].x;
}
double getDCELVertexY(DCEL_t *dcel, int vertex) {
return (dcel->vertices)[vertex].y;
}
int getDCELEdgeCount(DCEL_t *dcel) {
if (!dcel) {
return 0;
}
return dcel->edgesUsed;
}
int getDCELEdgeVertexStart(DCEL_t *dcel, int edge) {
if (!dcel) {
return 0;
}
return (dcel->edges)[edge].halfEdge->startVertex;
}
int getDCELEdgeVertexEnd(DCEL_t *dcel, int edge) {
if (!dcel) {
return 0;
}
return (dcel->edges)[edge].halfEdge->endVertex;
}
int getDCELEdgeVertexPairStart(DCEL_t *dcel, int edge) {
if (!dcel) {
return 0;
}
return (dcel->edges)[edge].halfEdge->twin->startVertex;
}
int getDCELEdgeVertexPairEnd(DCEL_t *dcel, int edge) {
if (!dcel) {
return 0;
}
return (dcel->edges)[edge].halfEdge->twin->endVertex;
}
int DCELhasEdge(DCEL_t *dcel, int edge) {
if ((dcel->edges)[edge].halfEdge->face != NOFACE) {
return 1;
} else {
return 0;
}
}
int DCELhasEdgePair(DCEL_t *dcel, int edge) {
if ((dcel->edges)[edge].halfEdge->face == NOFACE) {
return 0;
}
if ((dcel->edges)[edge].halfEdge->twin) {
return 1;
} else {
return 0;
}
}
intersection_t *getIntersection(bisector_t *b, DCEL_t *dcel, int face,
double minLength) {
// FILL IN
printf("In getIntersection(): bisector start: %lf, dcel numfaces = %d" \
"face = %d, minLength = %lf\n", b->startX, dcel->facesAllocated, \
face, minLength);
return NULL;
return intersections;
}
double getDiameter(DCEL_t *dcel, int faceIndex) {

139
dcel.h
View file

@ -20,25 +20,15 @@ typedef struct vertex {
} vertex_t;
typedef struct bisector {
double startX;
double startY;
double endX;
double endY;
/* This refers to the midpoint of the line segment AB, not the midpoint
* of the bisector itself.
*/
double midX;
double midY;
vertex_t *mid;
int isSlopeInfinite;
double slope;
} bisector_t;
typedef struct halfEdgeLabel {
struct halfEdgeLabel *previous;
struct halfEdgeLabel *next;
struct halfEdgeLabel *twin;
typedef struct halfEdge {
struct halfEdge *previous;
struct halfEdge *next;
struct halfEdge *twin;
int face;
int edge;
int startVertex;
@ -47,6 +37,7 @@ typedef struct halfEdgeLabel {
typedef struct edge {
halfEdge_t *halfEdge;
tower_t *tower;
} edge_t;
typedef struct face {
@ -63,7 +54,10 @@ typedef struct split {
} split_t;
typedef struct intersection {
vertex_t intersectionPoint;
int fromEdge;
int toEdge;
vertex_t *fromPoint;
vertex_t *toPoint;
} intersection_t;
typedef struct DCEL {
@ -136,9 +130,6 @@ int vertexMatch(vertex_t *v1, vertex_t *v2);
/* Gets the string for the given bisector equation. */
char *getBisectorEquation(bisector_t *b);
/* Frees the given bisector. */
void freeBisector(bisector_t *bisector);
/* Representation of no face */
#define NOFACE (-1)
@ -148,18 +139,6 @@ void freeBisector(bisector_t *bisector);
/* Default minimum length for bisector in each direction */
#define DEFAULTMINLENGTH (200)
/* Gets the intersection between the given bisector and the given DCEL
* for the given face.
*/
intersection_t *getIntersection(bisector_t *b, DCEL_t *dcel, \
int face, double minLength);
/* Gets the string for the given intersection. */
char *getIntersectionString(intersection_t *intersection);
/* Frees a given intersection. */
void freeIntersection(intersection_t *intersection);
/* Applies a given split to the DCEL. */
void applySplit(split_t *split, DCEL_t *dcel);
@ -172,6 +151,13 @@ int getFaceCount(DCEL_t *dcel);
/* Returns 1 if the given x,y point is inside the given face. */
int inFace(DCEL_t *dcel, double x, double y, int faceIndex);
/* Gets the intersection between the given bisector and the given DCEL
* for the given face.
*/
intersection_t **getIntersections(intersection_t **intersections, \
int *numIntersections, bisector_t **bisectors, int numBisectors, \
DCEL_t *dcel, int face, double minLength);
/* Gets the diameter of the given face. */
double getDiameter(DCEL_t *dcel, int faceIndex);
@ -180,60 +166,7 @@ double getDiameter(DCEL_t *dcel, int faceIndex);
*/
void incrementalVoronoi(DCEL_t *dcel, tower_t *watchTower);
/* Returns the number of vertices in the DCEL. */
int getDCELPointCount(DCEL_t *dcel);
/* Get x value of given vertex in DCEL. */
double getDCELVertexX(DCEL_t *dcel, int vertex);
/* Get y value of given vertex in DCEL. */
double getDCELVertexY(DCEL_t *dcel, int vertex);
/* Returns the number of edges in the DCEL. */
int getDCELEdgeCount(DCEL_t *dcel);
/* Get start vertex of given edge in DCEL. */
int getDCELEdgeVertexStart(DCEL_t *dcel, int edge);
/* Get end vertex of given edge in DCEL. */
int getDCELEdgeVertexEnd(DCEL_t *dcel, int edge);
/* Get start vertex of paired given edge in DCEL. */
int getDCELEdgeVertexPairStart(DCEL_t *dcel, int edge);
/* Get end vertex of paired given edge in DCEL. */
int getDCELEdgeVertexPairEnd(DCEL_t *dcel, int edge);
/* Check if the DCEL has the given edge. */
int DCELhasEdge(DCEL_t *dcel, int edge);
/* Check if the DCEL has a pair for the given edge. */
int DCELhasEdgePair(DCEL_t *dcel, int edge);
/* My own functions */
/* Reads the polygon file and stores the information in the vertices array */
vertex_t **readPolygon(vertex_t **vertices, FILE *polygonFile, \
int *numVertices);
/* Frees an array of vertices */
void freeVertices(vertex_t **vertices, int numVertices);
/* Calculates and returns the equation of a bisector of two points */
bisector_t *getBisector(vertex_t *pointA, vertex_t *pointB);
/* Euclidian distance between two 2D points */
double dist_2D(double x1, double y1, double x2, double y2);
/* Returns a value for x that ensures the point (x, y) is at least d (distance)
* away from (x1, y1) whilst ensuring (x, y) is on the line y = mx + c1.
*/
double inv_dist_2D(double x1, double y1, double m, double c, double d);
/* Returns a point at least distance away from the midpoint of the bisector given */
vertex_t *getBisectorPoint(double distance, bisector_t *b);
/* O'Rourke's functions */
/* O'Rourke's intersection functions */
/* Returns -1, 0 or 1, based on the area enclosed by the three points. 0 corresponds
to no area enclosed.
*/
@ -254,8 +187,42 @@ enum intersectType parallelIntersects(double heSx, double heSy, \
double heEx, double heEy, double bSx, double bSy, \
double bEx, double bEy, double *x, double *y);
/* Tests if */
/* Tests if a half edge and a bisector intersect */
enum intersectType intersects(halfEdge_t *he, bisector_t *b, \
DCEL_t *dcel, double minLength, double *x, double *y);
/* My own functions */
/* Reads the polygon file and stores the information in the vertices array */
vertex_t **readPolygon(vertex_t **vertices, FILE *polygonFile, \
int *numVertices);
/* Frees an array of vertices */
void freeVertices(vertex_t **vertices, int numVertices);
/* Calculates and returns the equation of a bisector of two points */
bisector_t **getBisectors(bisector_t **bisectors, vertex_t **points, \
int numPoints);
/* Returns a point at least distance away from the midpoint of the
* bisector given. If direction is 0, then the point is +distance away in the
* x-direction, otherwise -distance away in the x-direction.
*/
vertex_t *getBisectorPoint(double distance, bisector_t *b, int direction);
/* Create a new intersection */
intersection_t *newIntersection();
/* Frees an array of bisectors */
void freeBisectors(bisector_t **bisectors, int numBisectors);
/* Frees an array of points */
void freePoints(vertex_t **points, int numPoints);
/* Frees an array of intersections */
void freeIntersections(intersection_t **intersections, int numIntersections);
/* Reads a points file and stores the information in the points array */
vertex_t **readPoints(vertex_t **points, FILE *pointsFile, int *numPoints);
#endif

BIN
dcel.o

Binary file not shown.

View file

@ -5,7 +5,7 @@
* Last modified 9th September 2021
*
* Contains functions for ensuring correct input arguments are given for
* each stage of the voronoi2 program.
* each stage of the voronoi2 program. Adapted from Grady's base code on Ed.
*
*/

BIN
input.o

Binary file not shown.

42
main.c
View file

@ -12,14 +12,6 @@
*
*/
#ifndef DCEL_HEADER
#include "dcel.h"
#endif
#ifndef COMMON_HEADER
#include "common.h"
#endif
#ifndef VORONOI_HEADER
#include "voronoi.h"
#endif
@ -28,38 +20,6 @@
#include "input.h"
#endif
// int main(int argc, char **argv) {
// /* Input and output files */
// FILE *datasetFile = NULL, *polygonFile = NULL, *outputFile = NULL;
// checkInputArgs(argc, argv, &datasetFile, &polygonFile, &outputFile);
// /* Stores information about the towers given in dataset file */
// tower_t **towers = malloc(sizeof(*towers));
// checkNullPointer(towers);
// int numTowers = 0;
// towers = readTowers(towers, datasetFile, &numTowers);
// /* Stores information about the vertices in the polygon file */
// vertex_t **vertices = malloc(sizeof(*vertices));
// checkNullPointer(vertices);
// int numVertices = 0;
// vertices = readPolygon(vertices, polygonFile, &numVertices);
// /* Create DCEL structure from vertices */
// /* Check for splits, split the polygon if needed */
// /* Counts towers in each polygon, outputs to outputFile */
// /* Cleaning up data */
// freeTowers(towers, numTowers);
// freeVertices(vertices, numVertices);
// fclose(datasetFile);
// fclose(polygonFile);
// fclose(outputFile);
// return 0;
// }
int main(int argc, char **argv) {
/* Ensure input arguments are correct */
if (argc == 1) {
@ -96,7 +56,7 @@ int main(int argc, char **argv) {
/* Return error if stage number isn't defined. */
case STAGE_ERROR:
default:
fprintf(stderr, "Stage was not handled ENUM value (%d)\n", stage);
printArgError(stage, "Invalid stage entered.");
exit(EXIT_FAILURE);
}

BIN
main.o

Binary file not shown.

View file

@ -0,0 +1,6 @@
From Edge 0 (140.900000, -34.700000) to Edge 2 (150.000000, -34.700000)
From Edge 0 (140.900000, -35.200000) to Edge 2 (150.000000, -35.200000)
From Edge 1 (147.100000, -33.900000) to Edge 3 (147.100000, -39.200000)
From Edge 1 (147.100000, -33.900000) to Edge 3 (147.100000, -39.200000)
From Edge 1 (147.600000, -33.900000) to Edge 3 (147.600000, -39.200000)
From Edge 1 (146.900000, -33.900000) to Edge 3 (141.600000, -39.200000)

View file

@ -1,4 +1,13 @@
/* voronoi.c
*
* Created by Rory Healy (healyr@student.unimelb.edu.au)
* Created on 11th September 2021
* Last modified 13th September 2021
*
* Contains functions for reading a CSV of watchtower information into an
* array of towers.
*
*/
#ifndef TOWERS_HEADER
#include "towers.h"
@ -10,7 +19,7 @@
#define NUM_CSV_FIELDS 6
tower_t **readTowers(tower_t **towers, FILE *datasetFile, int *numTowers) {
/* Maximum length of a single CSV line */
/* Maximum length of a single CSV line (+1 for null char in string) */
size_t lineBufferSize = MAX_CSV_ENTRY_LEN + 1;
/* Stores the current line from the CSV */
@ -22,7 +31,7 @@ tower_t **readTowers(tower_t **towers, FILE *datasetFile, int *numTowers) {
/* Discard the header line, then read the rest of the CSV */
getline(&lineBuffer, &lineBufferSize, datasetFile);
while (getline(&lineBuffer, &lineBufferSize, datasetFile) > 0) {
/* Check if there enough space in the towers array */
/* Ensure there is enough space in the towers array */
if (*numTowers == maxSizetowers) {
maxSizetowers *= 2;
tower_t **temp = realloc(towers, maxSizetowers * sizeof(*towers));

BIN
towers.o

Binary file not shown.

View file

@ -2,75 +2,32 @@
*
* Created by Rory Healy (healyr@student.unimelb.edu.au)
* Created on 12th August 2021
* Last modified 11th September 2021
* Last modified 13th September 2021
*
* Contains functions involving the generation of the Voronoi diagram, and
* running each stage of the assignment.
*
*/
#ifndef COMMON_HEADER
#include "common.h"
#endif
#ifndef VORONOI_HEADER
#include "voronoi.h"
#endif
vertex_t **readPoints(vertex_t **points, FILE *pointsFile, int *numPoints) {
/* Initial size of buffer is 1 as getline() reallocs as needed */
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 stage1PrintBisector(bisector_t *bisector, FILE *outputFile) {
if (bisector->isSlopeInfinite) {
/* Cannot print infinite slope, so print only x-intercept */
fprintf(outputFile, "x = %lf\n", bisector->midX);
fprintf(outputFile, "x = %lf\n", bisector->mid->x);
} else {
fprintf(outputFile, "y = %lf * (x - %lf) + %lf\n", \
bisector->slope, bisector->midX, bisector->midY);
bisector->slope, bisector->mid->x, bisector->mid->y);
}
}
void freePoints(vertex_t **points, int numPoints) {
for (int i = 0; i < numPoints; i++) {
free(points[i]);
}
free(points);
void stage2PrintIntersection(intersection_t *intersection, FILE *outputFile) {
fprintf(outputFile, "From Edge %d (%lf, %lf) to Edge %d (%lf, %lf)\n", \
intersection->fromEdge, intersection->fromPoint->x, \
intersection->fromPoint->y, intersection->toEdge, \
intersection->toPoint->x, intersection->toPoint->y);
}
void stage1(char *pointsFileName, char *outputFileName) {
@ -84,23 +41,27 @@ void stage1(char *pointsFileName, char *outputFileName) {
int numPoints = 0;
points = readPoints(points, pointsFile, &numPoints);
/* There are half as many bisectors as points */
int numBisectors = numPoints / 2;
bisector_t **bisectors = malloc(sizeof(*bisectors) * numBisectors);
checkNullPointer(bisectors);
bisectors = getBisectors(bisectors, points, numBisectors);
/* For each pair, calculate and print the bisector to outputFile */
for (int i = 0; i < numPoints; i += 2) {
bisector_t *currBisector = getBisector(points[i], points[i + 1]);
stage1PrintBisector(currBisector, outputFile);
free(currBisector);
for (int i = 0; i < numBisectors; i++) {
stage1PrintBisector(bisectors[i], outputFile);
}
/* Clean up */
freePoints(points, numPoints);
freeBisectors(bisectors, numBisectors);
fclose(pointsFile);
fclose(outputFile);
}
void stage2(char *pointsFileName, char *polygonFileName, char *outputFileName) {
FILE *pointsFile = NULL, *polygonFile = NULL, *outputFile = NULL;
FILE *pointsFile = NULL, *outputFile = NULL;
pointsFile = safeFileOpen(&pointsFile, pointsFileName, "r");
polygonFile = safeFileOpen(&polygonFile, polygonFileName, "r");
outputFile = safeFileOpen(&outputFile, outputFileName, "w");
/* Points are given as pairs, so initialise 2 points */
@ -109,17 +70,32 @@ void stage2(char *pointsFileName, char *polygonFileName, char *outputFileName) {
int numPoints = 0;
points = readPoints(points, pointsFile, &numPoints);
/* There are half as many bisectors as points */
int numBisectors = numPoints / 2;
bisector_t **bisectors = malloc(sizeof(*bisectors) * numBisectors);
checkNullPointer(bisectors);
bisectors = getBisectors(bisectors, points, numBisectors);
/* Construct the DCEL from the polygon file */
DCEL_t *dcel = readPolygonFile(polygonFileName);
/* Calculate and print intersections to the output file */
intersection_t **intersections = malloc(sizeof(*intersections));
checkNullPointer(intersections);
int numIntersections = 0;
intersections = getIntersections(intersections, &numIntersections, bisectors, numBisectors, dcel, DEFAULT_FACE, \
DEFAULTMINLENGTH);
for (int i = 0; i < numIntersections; i++) {
stage2PrintIntersection(intersections[i], outputFile);
}
/* Clean up */
freePoints(points, numPoints);
freeBisectors(bisectors, numBisectors);
freeIntersections(intersections, numIntersections);
freeDCEL(dcel);
fclose(pointsFile);
fclose(polygonFile);
fclose(outputFile);
}

View file

@ -5,14 +5,11 @@
#ifndef VORONOI_HEADER
#define VORONOI_HEADER
/* Reads a points file and stores the information in the points array */
vertex_t **readPoints(vertex_t **points, FILE *pointsFile, int *numPoints);
/* Prints bisectors to an output file */
void stage1PrintBisector(bisector_t *bisector, FILE *outputFile);
/* Frees all points from a points array */
void freePoints(vertex_t **points, int numPoints);
/* Prints intersections to an output file */
void stage2PrintIntersection(intersection_t *intersection, FILE *outputFile);
/* Outputs the bisector equations from pointsFile into outputFile */
void stage1(char *pointsFileName, char *outputFileName);

BIN
voronoi.o

Binary file not shown.

BIN
voronoi2

Binary file not shown.