/* 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); }