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: # Link command:
voronoi2: common.o towers.o dcel.o voronoi.o input.o main.o 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 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
@ -31,8 +15,8 @@ dcel.o: dcel.c
voronoi.o: voronoi.c voronoi.o: voronoi.c
gcc -Wall -Wextra -Werror -pedantic -g -o voronoi.o voronoi.c -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 input.o: input.c
gcc -Wall -Wextra -Werror -pedantic -g -o input.o input.c -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 #endif
#ifndef MATH_HEADER
#define MATH_HEADER
#include <math.h>
#endif
#ifndef COMMON_HEADER #ifndef COMMON_HEADER
#define 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 by Rory Healy (healyr@student.unimelb.edu.au)
* Created on 25th August 2021 * Created on 25th August 2021
* Last modified 11th September 2021 * Last modified 13th September 2021
* *
* Contains functions for the DCEL data structure, including initialisation, * Contains functions for the DCEL data structure, including initialisation,
* splitting an edge, and identifying towers in faces. * splitting an edge, and identifying towers in faces.
@ -16,74 +16,145 @@
#include "dcel.h" #include "dcel.h"
#endif #endif
/* Deprecated by Grady's sample solution */ void freePoints(vertex_t **points, int numPoints) {
vertex_t **readPolygon(vertex_t **vertices, FILE *polygonFile, \ for (int i = 0; i < numPoints; i++) {
int *numVertices) { free(points[i]);
double currentX, currentY; }
int maxSizeVertices = 1; free(points);
while ((fscanf(polygonFile, "%lf %lf", &currentX, &currentY)) != EOF) { }
/* Check if there enough space in the towers array */
if (*numVertices == maxSizeVertices) { void freeBisectors(bisector_t **bisectors, int numBisectors) {
maxSizeVertices *= 2; for (int i = 0; i < numBisectors; i++) {
vertex_t **temp = realloc(vertices, \ free(bisectors[i]->mid);
maxSizeVertices * sizeof(*vertices)); 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); checkNullPointer(temp);
vertices = temp; points = temp;
} }
/* The current vertex being filled in with information */ double xCoordinateA, yCoordinateA, xCoordinateB, yCoordinateB;
vertices[*numVertices] = malloc(sizeof(*vertices[*numVertices])); sscanf(lineBuffer, "%lf %lf %lf %lf", &xCoordinateA, &yCoordinateA, \
vertices[*numVertices]->x = currentX; &xCoordinateB, &yCoordinateB);
vertices[*numVertices]->y = currentY;
*numVertices += 1;
}
return vertices;
}
void freeVertices(vertex_t **vertices, int numVertices) { points[*numPoints] = malloc(sizeof(*points[*numPoints]));
for (int i = 0; i < numVertices; i++) { points[*numPoints]->x = xCoordinateA;
free(vertices[i]); points[*numPoints]->y = yCoordinateA;
} *numPoints += 1;
free(vertices);
}
bisector_t *getBisector(vertex_t *pointA, vertex_t *pointB) { points[*numPoints] = malloc(sizeof(*points[*numPoints]));
bisector_t *newBisector = malloc(sizeof(*newBisector)); points[*numPoints]->x = xCoordinateB;
checkNullPointer(newBisector); points[*numPoints]->y = yCoordinateB;
*numPoints += 1;
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));
} }
return newBisector; free(lineBuffer);
return points;
} }
/* Here on out is the base code from Grady, with some alterations from me */ /* 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 OUTSIDE (-1)
#define NODIAMETER (-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 This intersection is based on code by Joseph O'Rourke and is provided for use in
COMP20003 Assignment 2. COMP20003 Assignment 2.
@ -246,14 +275,17 @@ enum intersectType intersects(halfEdge_t *he, bisector_t *b, \
double heEy = dcel->vertices[he->endVertex].y; double heEy = dcel->vertices[he->endVertex].y;
/* Bisector x, y twin */ /* Bisector x, y twin */
double bSx = b->startX; vertex_t *startPoint = getBisectorPoint(minLength, b, -1);
double bSy = b->startY; vertex_t *endPoint = getBisectorPoint(minLength, b, 1);
double bEx = b->endX; double bSx = startPoint->x;
double bEy = b->endY; double bSy = startPoint->y;
double bEx = endPoint->x;
double bEy = endPoint->y;
free(startPoint);
free(endPoint);
/* Fill in segment. */ /* Fill in segment. */
// min-length not used here?
printf("In intersets(): minlength = %lf\n", minLength);
/* Parametric equation parameters */ /* Parametric equation parameters */
double t1, t2; 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() { DCEL_t *newDCEL() {
/* Setup DCEL. */ /* Setup DCEL. */
DCEL_t *dcel = malloc(sizeof(*dcel)); DCEL_t *dcel = malloc(sizeof(*dcel));
@ -1026,82 +1011,72 @@ int inFace(DCEL_t *dcel, double x, double y, int faceIndex) {
return 1; return 1;
} }
int getDCELPointCount(DCEL_t *dcel) { intersection_t **getIntersections(intersection_t **intersections, \
if (!dcel) { int *numIntersections, bisector_t **bisectors, int numBisectors, \
return 0; 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 intersections;
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;
} }
double getDiameter(DCEL_t *dcel, int faceIndex) { double getDiameter(DCEL_t *dcel, int faceIndex) {

139
dcel.h
View file

@ -20,25 +20,15 @@ typedef struct vertex {
} vertex_t; } vertex_t;
typedef struct bisector { typedef struct bisector {
double startX; vertex_t *mid;
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;
int isSlopeInfinite; int isSlopeInfinite;
double slope; double slope;
} bisector_t; } bisector_t;
typedef struct halfEdgeLabel { typedef struct halfEdge {
struct halfEdgeLabel *previous; struct halfEdge *previous;
struct halfEdgeLabel *next; struct halfEdge *next;
struct halfEdgeLabel *twin; struct halfEdge *twin;
int face; int face;
int edge; int edge;
int startVertex; int startVertex;
@ -47,6 +37,7 @@ typedef struct halfEdgeLabel {
typedef struct edge { typedef struct edge {
halfEdge_t *halfEdge; halfEdge_t *halfEdge;
tower_t *tower;
} edge_t; } edge_t;
typedef struct face { typedef struct face {
@ -63,7 +54,10 @@ typedef struct split {
} split_t; } split_t;
typedef struct intersection { typedef struct intersection {
vertex_t intersectionPoint; int fromEdge;
int toEdge;
vertex_t *fromPoint;
vertex_t *toPoint;
} intersection_t; } intersection_t;
typedef struct DCEL { typedef struct DCEL {
@ -136,9 +130,6 @@ int vertexMatch(vertex_t *v1, vertex_t *v2);
/* Gets the string for the given bisector equation. */ /* Gets the string for the given bisector equation. */
char *getBisectorEquation(bisector_t *b); char *getBisectorEquation(bisector_t *b);
/* Frees the given bisector. */
void freeBisector(bisector_t *bisector);
/* Representation of no face */ /* Representation of no face */
#define NOFACE (-1) #define NOFACE (-1)
@ -148,18 +139,6 @@ void freeBisector(bisector_t *bisector);
/* Default minimum length for bisector in each direction */ /* Default minimum length for bisector in each direction */
#define DEFAULTMINLENGTH (200) #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. */ /* Applies a given split to the DCEL. */
void applySplit(split_t *split, DCEL_t *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. */ /* Returns 1 if the given x,y point is inside the given face. */
int inFace(DCEL_t *dcel, double x, double y, int faceIndex); 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. */ /* Gets the diameter of the given face. */
double getDiameter(DCEL_t *dcel, int faceIndex); 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); void incrementalVoronoi(DCEL_t *dcel, tower_t *watchTower);
/* Returns the number of vertices in the DCEL. */ /* O'Rourke's intersection functions */
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 */
/* Returns -1, 0 or 1, based on the area enclosed by the three points. 0 corresponds /* Returns -1, 0 or 1, based on the area enclosed by the three points. 0 corresponds
to no area enclosed. to no area enclosed.
*/ */
@ -254,8 +187,42 @@ enum intersectType parallelIntersects(double heSx, double heSy, \
double heEx, double heEy, double bSx, double bSy, \ double heEx, double heEy, double bSx, double bSy, \
double bEx, double bEy, double *x, double *y); 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, \ enum intersectType intersects(halfEdge_t *he, bisector_t *b, \
DCEL_t *dcel, double minLength, double *x, double *y); 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 #endif

BIN
dcel.o

Binary file not shown.

View file

@ -5,7 +5,7 @@
* Last modified 9th 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. 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 #ifndef VORONOI_HEADER
#include "voronoi.h" #include "voronoi.h"
#endif #endif
@ -28,38 +20,6 @@
#include "input.h" #include "input.h"
#endif #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) { int main(int argc, char **argv) {
/* Ensure input arguments are correct */ /* Ensure input arguments are correct */
if (argc == 1) { if (argc == 1) {
@ -96,7 +56,7 @@ int main(int argc, char **argv) {
/* Return error if stage number isn't defined. */ /* Return error if stage number isn't defined. */
case STAGE_ERROR: case STAGE_ERROR:
default: default:
fprintf(stderr, "Stage was not handled ENUM value (%d)\n", stage); printArgError(stage, "Invalid stage entered.");
exit(EXIT_FAILURE); 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 #ifndef TOWERS_HEADER
#include "towers.h" #include "towers.h"
@ -10,7 +19,7 @@
#define NUM_CSV_FIELDS 6 #define NUM_CSV_FIELDS 6
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 (+1 for null char in string) */
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 */
@ -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 */ /* Discard the header line, then read the rest of the CSV */
getline(&lineBuffer, &lineBufferSize, datasetFile); getline(&lineBuffer, &lineBufferSize, datasetFile);
while (getline(&lineBuffer, &lineBufferSize, datasetFile) > 0) { 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) { if (*numTowers == maxSizetowers) {
maxSizetowers *= 2; maxSizetowers *= 2;
tower_t **temp = realloc(towers, maxSizetowers * sizeof(*towers)); 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 by Rory Healy (healyr@student.unimelb.edu.au)
* Created on 12th August 2021 * 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 * Contains functions involving the generation of the Voronoi diagram, and
* running each stage of the assignment. * running each stage of the assignment.
* *
*/ */
#ifndef COMMON_HEADER
#include "common.h"
#endif
#ifndef VORONOI_HEADER #ifndef VORONOI_HEADER
#include "voronoi.h" #include "voronoi.h"
#endif #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) { void stage1PrintBisector(bisector_t *bisector, FILE *outputFile) {
if (bisector->isSlopeInfinite) { if (bisector->isSlopeInfinite) {
/* Cannot print infinite slope, so print only x-intercept */ /* 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 { } else {
fprintf(outputFile, "y = %lf * (x - %lf) + %lf\n", \ 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) { void stage2PrintIntersection(intersection_t *intersection, FILE *outputFile) {
for (int i = 0; i < numPoints; i++) { fprintf(outputFile, "From Edge %d (%lf, %lf) to Edge %d (%lf, %lf)\n", \
free(points[i]); intersection->fromEdge, intersection->fromPoint->x, \
} intersection->fromPoint->y, intersection->toEdge, \
free(points); intersection->toPoint->x, intersection->toPoint->y);
} }
void stage1(char *pointsFileName, char *outputFileName) { void stage1(char *pointsFileName, char *outputFileName) {
@ -84,23 +41,27 @@ void stage1(char *pointsFileName, char *outputFileName) {
int numPoints = 0; int numPoints = 0;
points = readPoints(points, pointsFile, &numPoints); 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 each pair, calculate and print the bisector to outputFile */
for (int i = 0; i < numPoints; i += 2) { for (int i = 0; i < numBisectors; i++) {
bisector_t *currBisector = getBisector(points[i], points[i + 1]); stage1PrintBisector(bisectors[i], outputFile);
stage1PrintBisector(currBisector, outputFile);
free(currBisector);
} }
/* Clean up */ /* Clean up */
freePoints(points, numPoints); freePoints(points, numPoints);
freeBisectors(bisectors, numBisectors);
fclose(pointsFile); fclose(pointsFile);
fclose(outputFile); fclose(outputFile);
} }
void stage2(char *pointsFileName, char *polygonFileName, char *outputFileName) { 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"); pointsFile = safeFileOpen(&pointsFile, pointsFileName, "r");
polygonFile = safeFileOpen(&polygonFile, polygonFileName, "r");
outputFile = safeFileOpen(&outputFile, outputFileName, "w"); outputFile = safeFileOpen(&outputFile, outputFileName, "w");
/* Points are given as pairs, so initialise 2 points */ /* Points are given as pairs, so initialise 2 points */
@ -109,17 +70,32 @@ void stage2(char *pointsFileName, char *polygonFileName, char *outputFileName) {
int numPoints = 0; int numPoints = 0;
points = readPoints(points, pointsFile, &numPoints); 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 */ /* Construct the DCEL from the polygon file */
DCEL_t *dcel = readPolygonFile(polygonFileName); DCEL_t *dcel = readPolygonFile(polygonFileName);
/* Calculate and print intersections to the output file */ /* 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 */ /* Clean up */
freePoints(points, numPoints); freePoints(points, numPoints);
freeBisectors(bisectors, numBisectors);
freeIntersections(intersections, numIntersections);
freeDCEL(dcel); freeDCEL(dcel);
fclose(pointsFile); fclose(pointsFile);
fclose(polygonFile);
fclose(outputFile); fclose(outputFile);
} }

View file

@ -5,14 +5,11 @@
#ifndef VORONOI_HEADER #ifndef VORONOI_HEADER
#define 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 */ /* Prints bisectors to an output file */
void stage1PrintBisector(bisector_t *bisector, FILE *outputFile); void stage1PrintBisector(bisector_t *bisector, FILE *outputFile);
/* Frees all points from a points array */ /* Prints intersections to an output file */
void freePoints(vertex_t **points, int numPoints); void stage2PrintIntersection(intersection_t *intersection, FILE *outputFile);
/* Outputs the bisector equations from pointsFile into outputFile */ /* Outputs the bisector equations from pointsFile into outputFile */
void stage1(char *pointsFileName, char *outputFileName); void stage1(char *pointsFileName, char *outputFileName);

BIN
voronoi.o

Binary file not shown.

BIN
voronoi2

Binary file not shown.