comp20003-project02/voronoi.c
2021-09-15 00:06:04 +10:00

208 lines
6.9 KiB
C

/* voronoi.c
*
* Created by Rory Healy (healyr@student.unimelb.edu.au)
* Created on 12th August 2021
* Last modified 14th September 2021
*
* Contains functions involving the generation of the Voronoi diagram, and
* running each stage of the assignment.
*
*/
#ifndef VORONOI_HEADER
#include "voronoi.h"
#endif
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->mid->x);
} else {
fprintf(outputFile, "y = %lf * (x - %lf) + %lf\n", \
bisector->slope, bisector->mid->x, bisector->mid->y);
}
}
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 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;
}
void stage1(char *pointsFileName, char *outputFileName) {
FILE *pointsFile = NULL, *outputFile = NULL;
pointsFile = safeFileOpen(&pointsFile, pointsFileName, "r");
outputFile = safeFileOpen(&outputFile, outputFileName, "w");
/* 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);
/* 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 < 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, *outputFile = NULL;
pointsFile = safeFileOpen(&pointsFile, pointsFileName, "r");
outputFile = safeFileOpen(&outputFile, outputFileName, "w");
/* 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);
/* 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(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");
/* 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 */
/* Get diameters and output to outputFile */
/* Clean up */
freeDCEL(dcel);
freeTowers(towers, numTowers);
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");
/* 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 */
/* Get diameters and sort, then output to outputFile */
/* Clean up */
freeDCEL(dcel);
freeTowers(towers, numTowers);
fclose(dataFile);
fclose(polygonFile);
fclose(outputFile);
}