2021-09-08 21:48:00 +10:00
|
|
|
/* voronoi.c
|
|
|
|
*
|
|
|
|
* Created by Rory Healy (healyr@student.unimelb.edu.au)
|
|
|
|
* Created on 12th August 2021
|
2021-09-15 00:06:04 +10:00
|
|
|
* Last modified 14th September 2021
|
2021-09-08 21:48:00 +10:00
|
|
|
*
|
2021-09-09 17:10:24 +10:00
|
|
|
* Contains functions involving the generation of the Voronoi diagram, and
|
|
|
|
* running each stage of the assignment.
|
|
|
|
*
|
2021-09-08 21:48:00 +10:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef VORONOI_HEADER
|
|
|
|
#include "voronoi.h"
|
|
|
|
#endif
|
|
|
|
|
2021-09-11 22:47:44 +10:00
|
|
|
void stage1PrintBisector(bisector_t *bisector, FILE *outputFile) {
|
|
|
|
if (bisector->isSlopeInfinite) {
|
|
|
|
/* Cannot print infinite slope, so print only x-intercept */
|
2021-09-13 12:27:17 +10:00
|
|
|
fprintf(outputFile, "x = %lf\n", bisector->mid->x);
|
2021-09-11 22:47:44 +10:00
|
|
|
} else {
|
|
|
|
fprintf(outputFile, "y = %lf * (x - %lf) + %lf\n", \
|
2021-09-13 12:27:17 +10:00
|
|
|
bisector->slope, bisector->mid->x, bisector->mid->y);
|
2021-09-11 22:47:44 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-13 12:27:17 +10:00
|
|
|
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);
|
2021-09-09 17:10:24 +10:00
|
|
|
}
|
|
|
|
|
2021-09-15 00:06:04 +10:00
|
|
|
void stage34PrintTowers(tower_t *tower, FILE *outputFile, double diameter) {
|
|
|
|
fprintf(outputFile, "Watchtower ID: %s, Postcode: %s, Population " \
|
|
|
|
"Served: %d, Watchtower Point of Contact Name: %s, x: %lf, y: %lf, " \
|
|
|
|
"Diameter of Cell: %lf\n", tower->id, tower->postcode, \
|
|
|
|
tower->population, tower->manager, tower->x, tower->y, diameter);
|
|
|
|
}
|
|
|
|
|
|
|
|
int getFaceTowerIsIn(DCEL_t *dcel, tower_t *tower) {
|
|
|
|
for (int i = 0; i < getFaceCount(dcel); i++) {
|
|
|
|
if (inFace(dcel, tower->x, tower->y, i)) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void incrementalVoronoi(DCEL_t *voronoi, tower_t *tower) {
|
|
|
|
int faceTowerIsIn = getFaceTowerIsIn(voronoi, tower);
|
|
|
|
if (faceTowerIsIn == -1) {
|
|
|
|
fprintf(stderr, "Error: Watchtower %s is outside the polygon.\n", \
|
|
|
|
tower->id);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DCEL_t *newVoronoi(DCEL_t *voronoi, tower_t *towerA, tower_t *towerB) {
|
|
|
|
/* Get vertices from towers */
|
|
|
|
vertex_t *pointA = getAPoint(towerA->x, towerA->y);
|
|
|
|
vertex_t *pointB = getAPoint(towerB->x, towerB->y);
|
|
|
|
|
|
|
|
/* Create first bisector */
|
|
|
|
bisector_t *bisector = newBisector();
|
|
|
|
bisector = getABisector(bisector, pointA, pointB);
|
|
|
|
|
|
|
|
/* Get intersection of bisector with the polygon */
|
|
|
|
intersection_t *intersection = NULL;
|
|
|
|
intersection = getAnIntersection(intersection, voronoi, bisector, \
|
|
|
|
DEFAULT_FACE, DEFAULTMINLENGTH);
|
|
|
|
|
|
|
|
if (intersection) {
|
|
|
|
free(intersection->fromPoint);
|
|
|
|
free(intersection->toPoint);
|
|
|
|
free(intersection);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(bisector->mid);
|
|
|
|
free(bisector);
|
|
|
|
free(pointA);
|
|
|
|
free(pointB);
|
|
|
|
return voronoi;
|
|
|
|
}
|
|
|
|
|
2021-09-09 17:10:24 +10:00
|
|
|
void stage1(char *pointsFileName, char *outputFileName) {
|
|
|
|
FILE *pointsFile = NULL, *outputFile = NULL;
|
|
|
|
pointsFile = safeFileOpen(&pointsFile, pointsFileName, "r");
|
|
|
|
outputFile = safeFileOpen(&outputFile, outputFileName, "w");
|
|
|
|
|
2021-09-09 21:23:53 +10:00
|
|
|
/* Points are given as pairs, so initialise 2 points */
|
|
|
|
vertex_t **points = malloc(sizeof(*points) * 2);
|
2021-09-09 17:10:24 +10:00
|
|
|
checkNullPointer(points);
|
|
|
|
int numPoints = 0;
|
2021-09-09 21:23:53 +10:00
|
|
|
points = readPoints(points, pointsFile, &numPoints);
|
|
|
|
|
2021-09-13 12:27:17 +10:00
|
|
|
/* 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);
|
|
|
|
|
2021-09-09 21:23:53 +10:00
|
|
|
/* For each pair, calculate and print the bisector to outputFile */
|
2021-09-13 12:27:17 +10:00
|
|
|
for (int i = 0; i < numBisectors; i++) {
|
|
|
|
stage1PrintBisector(bisectors[i], outputFile);
|
2021-09-09 21:23:53 +10:00
|
|
|
}
|
2021-09-09 17:10:24 +10:00
|
|
|
|
2021-09-11 22:47:44 +10:00
|
|
|
/* Clean up */
|
2021-09-09 17:10:24 +10:00
|
|
|
freePoints(points, numPoints);
|
2021-09-13 12:27:17 +10:00
|
|
|
freeBisectors(bisectors, numBisectors);
|
2021-09-09 17:10:24 +10:00
|
|
|
fclose(pointsFile);
|
|
|
|
fclose(outputFile);
|
|
|
|
}
|
|
|
|
|
2021-09-15 00:06:04 +10:00
|
|
|
void stage2(char *pointsFileName, char *polygonFileName, \
|
|
|
|
char *outputFileName) {
|
|
|
|
|
2021-09-13 12:27:17 +10:00
|
|
|
FILE *pointsFile = NULL, *outputFile = NULL;
|
2021-09-09 17:10:24 +10:00
|
|
|
pointsFile = safeFileOpen(&pointsFile, pointsFileName, "r");
|
|
|
|
outputFile = safeFileOpen(&outputFile, outputFileName, "w");
|
|
|
|
|
2021-09-11 22:47:44 +10:00
|
|
|
/* Points are given as pairs, so initialise 2 points */
|
|
|
|
vertex_t **points = malloc(sizeof(*points) * 2);
|
|
|
|
checkNullPointer(points);
|
|
|
|
int numPoints = 0;
|
|
|
|
points = readPoints(points, pointsFile, &numPoints);
|
|
|
|
|
2021-09-13 12:27:17 +10:00
|
|
|
/* 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);
|
|
|
|
|
2021-09-11 22:47:44 +10:00
|
|
|
/* Construct the DCEL from the polygon file */
|
|
|
|
DCEL_t *dcel = readPolygonFile(polygonFileName);
|
|
|
|
|
|
|
|
/* Calculate and print intersections to the output file */
|
2021-09-13 12:27:17 +10:00
|
|
|
intersection_t **intersections = malloc(sizeof(*intersections));
|
|
|
|
checkNullPointer(intersections);
|
|
|
|
int numIntersections = 0;
|
2021-09-15 00:06:04 +10:00
|
|
|
intersections = getIntersections(intersections, &numIntersections, \
|
|
|
|
bisectors, numBisectors, dcel, DEFAULT_FACE, DEFAULTMINLENGTH);
|
2021-09-13 12:27:17 +10:00
|
|
|
|
|
|
|
for (int i = 0; i < numIntersections; i++) {
|
|
|
|
stage2PrintIntersection(intersections[i], outputFile);
|
|
|
|
}
|
2021-09-09 17:10:24 +10:00
|
|
|
|
2021-09-11 22:47:44 +10:00
|
|
|
/* Clean up */
|
|
|
|
freePoints(points, numPoints);
|
2021-09-13 12:27:17 +10:00
|
|
|
freeBisectors(bisectors, numBisectors);
|
|
|
|
freeIntersections(intersections, numIntersections);
|
2021-09-11 22:47:44 +10:00
|
|
|
freeDCEL(dcel);
|
2021-09-09 17:10:24 +10:00
|
|
|
fclose(pointsFile);
|
|
|
|
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");
|
|
|
|
|
2021-09-15 00:06:04 +10:00
|
|
|
/* Read towers from the data file */
|
|
|
|
tower_t **towers = malloc(sizeof(*towers));
|
|
|
|
checkNullPointer(towers);
|
|
|
|
int numTowers = 0;
|
|
|
|
towers = readTowers(towers, dataFile, &numTowers);
|
2021-09-09 17:10:24 +10:00
|
|
|
|
2021-09-15 00:06:04 +10:00
|
|
|
/* Construct the DCEL from the polygon file */
|
|
|
|
DCEL_t *dcel = readPolygonFile(polygonFileName);
|
|
|
|
|
|
|
|
/* Add each tower to the Voronoi DCEL */
|
2021-09-09 17:10:24 +10:00
|
|
|
|
2021-09-15 00:06:04 +10:00
|
|
|
/* Get diameters and output to outputFile */
|
|
|
|
|
2021-09-11 22:47:44 +10:00
|
|
|
/* Clean up */
|
2021-09-15 00:06:04 +10:00
|
|
|
freeDCEL(dcel);
|
|
|
|
freeTowers(towers, numTowers);
|
2021-09-09 17:10:24 +10:00
|
|
|
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");
|
|
|
|
|
2021-09-15 00:06:04 +10:00
|
|
|
/* Read towers from the data file */
|
|
|
|
tower_t **towers = malloc(sizeof(*towers));
|
|
|
|
checkNullPointer(towers);
|
|
|
|
int numTowers = 0;
|
|
|
|
towers = readTowers(towers, dataFile, &numTowers);
|
|
|
|
|
|
|
|
/* Construct the DCEL from the polygon file */
|
|
|
|
DCEL_t *dcel = readPolygonFile(polygonFileName);
|
|
|
|
|
|
|
|
/* Add each tower to the Voronoi DCEL */
|
2021-09-09 17:10:24 +10:00
|
|
|
|
2021-09-15 00:06:04 +10:00
|
|
|
/* Get diameters and sort, then output to outputFile */
|
2021-09-11 22:47:44 +10:00
|
|
|
|
|
|
|
/* Clean up */
|
2021-09-15 00:06:04 +10:00
|
|
|
freeDCEL(dcel);
|
|
|
|
freeTowers(towers, numTowers);
|
2021-09-09 17:10:24 +10:00
|
|
|
fclose(dataFile);
|
|
|
|
fclose(polygonFile);
|
|
|
|
fclose(outputFile);
|
|
|
|
}
|