Final submission
This commit is contained in:
parent
11b8feaa6e
commit
d552f37321
21 changed files with 966 additions and 544 deletions
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"files.associations": {
|
||||
"type_traits": "c"
|
||||
}
|
||||
}
|
2
Makefile
2
Makefile
|
@ -1,6 +1,6 @@
|
|||
# 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
|
||||
gcc -Wall -Wextra -Werror -pedantic -g -o voronoi2 main.o input.o voronoi.o dcel.o towers.o common.o -lm
|
||||
|
||||
# Compilation commands
|
||||
common.o: common.c
|
||||
|
|
0
README.md
Normal file → Executable file
0
README.md
Normal file → Executable file
4
common.c
4
common.c
|
@ -2,9 +2,9 @@
|
|||
*
|
||||
* Created by Rory Healy (healyr@student.unimelb.edu.au)
|
||||
* Created on 25th August 2021
|
||||
* Last modified 9th September 2021
|
||||
* Last modified 14th September 2021
|
||||
*
|
||||
* Contains functions for general use throughout other files.
|
||||
* Contains functions and headers for general use throughout other files.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
880
dcel.c
880
dcel.c
|
@ -2,10 +2,10 @@
|
|||
*
|
||||
* Created by Rory Healy (healyr@student.unimelb.edu.au)
|
||||
* Created on 25th August 2021
|
||||
* Last modified 13th September 2021
|
||||
* Last modified 14th September 2021
|
||||
*
|
||||
* Contains functions for the DCEL data structure, including initialisation,
|
||||
* splitting an edge, and identifying towers in faces.
|
||||
* Contains functions for the DCEL data structure and related data structures
|
||||
* (including points, intersections, and bisectors).
|
||||
*
|
||||
* Contains several functions and structures from Grady Fitzpatrick's Base
|
||||
* Code on the Ed Discussion Forum.
|
||||
|
@ -16,106 +16,29 @@
|
|||
#include "dcel.h"
|
||||
#endif
|
||||
|
||||
void freePoints(vertex_t **points, int numPoints) {
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
free(points[i]);
|
||||
}
|
||||
free(points);
|
||||
#define INITIALVERTICES 4
|
||||
#define INITIALEDGES 4
|
||||
#define INITIALFACES 1
|
||||
#define NOVERTEX (-1)
|
||||
#define NOEDGE (-1)
|
||||
|
||||
#define DIR_UNDECIDED (0)
|
||||
#define INSIDE (1)
|
||||
#define OUTSIDE (-1)
|
||||
#define NODIAMETER (-1)
|
||||
|
||||
/* ----------------------- My points functions start ----------------------- */
|
||||
vertex_t *newPoint() {
|
||||
vertex_t *newPoint = malloc(sizeof(*newPoint));
|
||||
checkNullPointer(newPoint);
|
||||
return newPoint;
|
||||
}
|
||||
|
||||
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 *getAPoint(double x, double y) {
|
||||
vertex_t *point = newPoint();
|
||||
point->x = x;
|
||||
point->y = y;
|
||||
return point;
|
||||
}
|
||||
|
||||
vertex_t **readPoints(vertex_t **points, FILE *pointsFile, int *numPoints) {
|
||||
|
@ -157,224 +80,302 @@ vertex_t **readPoints(vertex_t **points, FILE *pointsFile, int *numPoints) {
|
|||
return points;
|
||||
}
|
||||
|
||||
/* Here on out is the base code from Grady, with some alterations from me */
|
||||
|
||||
#define INITIALVERTICES 4
|
||||
#define INITIALEDGES 4
|
||||
#define INITIALFACES 1
|
||||
#define NOVERTEX (-1)
|
||||
#define NOEDGE (-1)
|
||||
|
||||
#define DIR_UNDECIDED (0)
|
||||
#define INSIDE (1)
|
||||
#define OUTSIDE (-1)
|
||||
#define NODIAMETER (-1)
|
||||
|
||||
/*
|
||||
This intersection is based on code by Joseph O'Rourke and is provided for use in
|
||||
COMP20003 Assignment 2.
|
||||
|
||||
The approach for intersections is:
|
||||
- Use the bisector to construct a finite segment and test it against the half-edge.
|
||||
- Use O'Rourke's segseg intersection
|
||||
(https://hydra.smith.edu/~jorourke/books/ftp.html)
|
||||
to check if the values overlap/intersect
|
||||
|
||||
Generates a segment with each end at least minLength away in each direction
|
||||
from the bisector midpoint.
|
||||
Returns 1 if b intersects the given half-edge on this segment, 0 otherwise.
|
||||
Sets the intersection point to the given x, y positions.
|
||||
*/
|
||||
|
||||
int areaSign(double sx, double sy, double ex, double ey, double x, double y) {
|
||||
double areaSq;
|
||||
/* |AB x AC|^2, squared area */
|
||||
/* See https://mathworld.wolfram.com/CrossProduct.html */
|
||||
areaSq = (ex - sx) * (y - sy) -
|
||||
(x - sx) * (ey - sy);
|
||||
|
||||
if (areaSq > 0.0) {
|
||||
return 1;
|
||||
} else if (areaSq == 0.0) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
void freePoints(vertex_t **points, int numPoints) {
|
||||
if (!points) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int between(double sx, double sy, double ex, double ey, double x, double y) {
|
||||
if (sx != ex) {
|
||||
/* If not vertical, check whether between x. */
|
||||
if ((sx <= x && x <= ex) || (sx >= x && x >= ex)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* Vertical, so can't check _between_ x-values. Check y-axis. */
|
||||
if ((sy <= y && y <= ey) || (sy >= y && y >= ey)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
if (points[i]) {
|
||||
free(points[i]);
|
||||
}
|
||||
}
|
||||
free(points);
|
||||
}
|
||||
|
||||
int collinear(double sx, double sy, double ex, double ey, double x, double y) {
|
||||
/* If area of the parallelogram is 0, then the points
|
||||
* are in the same line.
|
||||
double distPoints(vertex_t *pointA, vertex_t *pointB) {
|
||||
double a = pointB->x - pointA->x;
|
||||
double b = pointB->y - pointA->y;
|
||||
return sqrt(a * a + b * b);
|
||||
}
|
||||
|
||||
/* ------------------------ My points functions end ------------------------ */
|
||||
|
||||
/* -------------------- My intersection functions start -------------------- */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
intersection_t *getAnIntersection(intersection_t *intersection, DCEL_t *dcel, \
|
||||
bisector_t *bisector, int face, int minLength) {
|
||||
|
||||
/* 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, bisector, dcel, minLength, &x, &y);
|
||||
|
||||
switch (typeOfIntersection) {
|
||||
case INTERSECT:
|
||||
case SAME_LINE_OVERLAP:
|
||||
case ENDS_OVERLAP:
|
||||
if (!isIntersectionFound) {
|
||||
/* First point of intersection */
|
||||
isIntersectionFound = 1;
|
||||
intersection = newIntersection();
|
||||
intersection->fromPoint->x = x;
|
||||
intersection->fromPoint->y = y;
|
||||
intersection->fromEdge = currentHE->edge;
|
||||
} else {
|
||||
/* Second point of intersection */
|
||||
intersection->toPoint->x = x;
|
||||
intersection->toPoint->y = y;
|
||||
intersection->toEdge = currentHE->edge;
|
||||
}
|
||||
break;
|
||||
case DOESNT_INTERSECT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
currentHE = currentHE->next;
|
||||
first = 0;
|
||||
}
|
||||
|
||||
return intersection;
|
||||
}
|
||||
|
||||
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 *intersection = NULL;
|
||||
intersection = getAnIntersection(intersection, dcel, bisectors[i], \
|
||||
face, minLength);
|
||||
|
||||
/* If there is an intersection, add it to the array */
|
||||
if (intersection != 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] = intersection;
|
||||
*numIntersections += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return intersections;
|
||||
}
|
||||
|
||||
void freeIntersections(intersection_t **intersections, int numIntersections) {
|
||||
if (!intersections) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numIntersections; i++) {
|
||||
if (intersections[i]->fromPoint) {
|
||||
free(intersections[i]->fromPoint);
|
||||
}
|
||||
if (intersections[i]->toPoint) {
|
||||
free(intersections[i]->toPoint);
|
||||
}
|
||||
if (intersections[i]) {
|
||||
free(intersections[i]);
|
||||
}
|
||||
}
|
||||
free(intersections);
|
||||
}
|
||||
|
||||
/* --------------------- My intersection functions end --------------------- */
|
||||
|
||||
/* ---------------------- My bisector functions start ---------------------- */
|
||||
|
||||
bisector_t *newBisector() {
|
||||
bisector_t *newBisector = malloc(sizeof(*newBisector));
|
||||
checkNullPointer(newBisector);
|
||||
newBisector->mid = malloc(sizeof(*newBisector->mid));
|
||||
checkNullPointer(newBisector->mid);
|
||||
return newBisector;
|
||||
}
|
||||
|
||||
bisector_t *getABisector(bisector_t *bisector, vertex_t *pointA, \
|
||||
vertex_t *pointB) {
|
||||
|
||||
/* Calculate midpoint of the two points */
|
||||
bisector->mid->x = (pointA->x + pointB->x) / 2;
|
||||
bisector->mid->y = (pointA->y + pointB->y) / 2;
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
bisector->slope = 0;
|
||||
bisector->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.
|
||||
*/
|
||||
bisector->isSlopeInfinite = 1;
|
||||
|
||||
/* Not actually zero, just a placeholder to prevent
|
||||
* accidental errors
|
||||
*/
|
||||
bisector->slope = 0;
|
||||
} else {
|
||||
/* The line segment AB has a non-zero and finite gradient,
|
||||
* so the gradient of the bisector can be calculated.
|
||||
*/
|
||||
bisector->isSlopeInfinite = 0;
|
||||
bisector->slope = -1 / ((pointB->y - pointA->y) / \
|
||||
(pointB->x - pointA->x));
|
||||
}
|
||||
|
||||
return bisector;
|
||||
}
|
||||
|
||||
bisector_t **getBisectors(bisector_t **bisectors, vertex_t **points, \
|
||||
int numBisectors) {
|
||||
|
||||
for (int i = 0; i < numBisectors; i++) {
|
||||
bisectors[i] = newBisector();
|
||||
bisectors[i] = getABisector(bisectors[i], points[2 * i], \
|
||||
points[2 * i + 1]);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void freeBisectors(bisector_t **bisectors, int numBisectors) {
|
||||
if (!bisectors) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numBisectors; i++) {
|
||||
if (bisectors[i]->mid) {
|
||||
free(bisectors[i]->mid);
|
||||
}
|
||||
if (bisectors[i]) {
|
||||
free(bisectors[i]);
|
||||
}
|
||||
}
|
||||
free(bisectors);
|
||||
}
|
||||
|
||||
/* ----------------------- My bisector functions end ----------------------- */
|
||||
|
||||
/* ------------------------ My DCEL functions start ------------------------ */
|
||||
|
||||
double getDiameter(DCEL_t *dcel, int faceIndex) {
|
||||
/* firstHE and firstVertex refer to the first HE/vertex from the face used
|
||||
* to control when the loop stops
|
||||
*
|
||||
* startHE and startVertex refer to the starting point used to
|
||||
* advance the new starting vertex after a complete cycle
|
||||
*
|
||||
* currentHE and currentVertex refer to the current HE/vertex being used to
|
||||
* compute the diameter
|
||||
*/
|
||||
if (areaSign(sx, sy, ex, ey, x, y) == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
halfEdge_t *firstHE = (dcel->faces)[faceIndex].start;
|
||||
halfEdge_t *startHE = firstHE;
|
||||
halfEdge_t *currentHE = startHE;
|
||||
int firstVertex = firstHE->startVertex;
|
||||
int startVertex = firstVertex;
|
||||
int currentVertex = startVertex;
|
||||
int first = 1;
|
||||
double currentDiameter = NODIAMETER, maxDiameter = NODIAMETER;
|
||||
|
||||
while (first || !(currentHE->startVertex == firstVertex && \
|
||||
startHE->startVertex == firstVertex)) {
|
||||
first = 0;
|
||||
|
||||
/* Compute currentDiameter, compare to maxDiameter */
|
||||
currentDiameter = distPoints(&(dcel->vertices)[startVertex], \
|
||||
&(dcel->vertices)[currentVertex]);
|
||||
if (currentDiameter >= maxDiameter) {
|
||||
maxDiameter = currentDiameter;
|
||||
}
|
||||
|
||||
/* Advance current HE, update currentVertex */
|
||||
currentHE = currentHE->next;
|
||||
currentVertex = currentHE->startVertex;
|
||||
|
||||
/* When the starting vertex is reached, move the startHE to the next HE
|
||||
* and update the vertices.
|
||||
*/
|
||||
if (currentVertex == startVertex) {
|
||||
startHE = startHE->next;
|
||||
currentHE = startHE;
|
||||
startVertex = startHE->startVertex;
|
||||
currentVertex = startVertex;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentDiameter == NODIAMETER) {
|
||||
return NODIAMETER;
|
||||
}
|
||||
|
||||
return maxDiameter;
|
||||
}
|
||||
|
||||
enum intersectType parallelIntersects(double heSx, double heSy, \
|
||||
double heEx, double heEy, double bSx, double bSy, \
|
||||
double bEx, double bEy, double *x, double *y) {
|
||||
if (!collinear(heSx, heSy, heEx, heEy, bSx, bSy)) {
|
||||
/* Parallel, no intersection so don't set (x, y) */
|
||||
return DOESNT_INTERSECT;
|
||||
}
|
||||
/* bS between heS and heE */
|
||||
if (between(heSx, heSy, heEx, heEy, bSx, bSy)) {
|
||||
*x = bSx;
|
||||
*y = bSy;
|
||||
return SAME_LINE_OVERLAP;
|
||||
}
|
||||
/* bE between heS and heE */
|
||||
if (between(heSx, heSy, heEx, heEy, bEx, bEy)) {
|
||||
*x = bEx;
|
||||
*y = bEy;
|
||||
return SAME_LINE_OVERLAP;
|
||||
}
|
||||
/* heS between bS and bE */
|
||||
if (between(bSx, bSy, bEx, bEy, heSx, heSy)) {
|
||||
*x = heSx;
|
||||
*y = heSy;
|
||||
return SAME_LINE_OVERLAP;
|
||||
}
|
||||
/* heE between bS and bE */
|
||||
if (between(bSx, bSy, bEx, bEy, heEx, heEy)) {
|
||||
*x = heEx;
|
||||
*y = heEy;
|
||||
return SAME_LINE_OVERLAP;
|
||||
}
|
||||
/* ------------------------- My DCEL functions end ------------------------- */
|
||||
|
||||
return DOESNT_INTERSECT;
|
||||
}
|
||||
|
||||
enum intersectType intersects(halfEdge_t *he, bisector_t *b, \
|
||||
DCEL_t *dcel, double minLength, double *x, double *y) {
|
||||
/* Half-edge x, y twin */
|
||||
double heSx = dcel->vertices[he->startVertex].x;
|
||||
double heSy = dcel->vertices[he->startVertex].y;
|
||||
double heEx = dcel->vertices[he->endVertex].x;
|
||||
double heEy = dcel->vertices[he->endVertex].y;
|
||||
|
||||
/* Bisector x, y twin */
|
||||
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. */
|
||||
|
||||
/* Parametric equation parameters */
|
||||
double t1, t2;
|
||||
|
||||
/* Numerators for X and Y coordinate of intersection. */
|
||||
double numeratorX, numeratorY;
|
||||
|
||||
/* Denominators of intersection coordinates. */
|
||||
double denominator;
|
||||
|
||||
/*
|
||||
See http://www.cs.jhu.edu/~misha/Spring20/15.pdf
|
||||
for explanation and intuition of the algorithm here.
|
||||
x_1 = heSx, y_1 = heSy | p_1 = heS
|
||||
x_2 = heEx, y_2 = heEy | q_1 = heE
|
||||
x_3 = bSx , y_3 = bSy | p_2 = bS
|
||||
x_4 = bEx , y_4 = bEy | q_2 = bE
|
||||
----------------------------------------
|
||||
So the parameters t1 and t2 are given by:
|
||||
| t1 | | heEx - heSx bSx - bEx | -1 | bSx - heSx |
|
||||
| | = | | | |
|
||||
| t2 | | heEy - heSy bSy - bEy | | bSy - heSy |
|
||||
|
||||
Hence:
|
||||
| t1 | 1 | bSy - bEy bEx - bSx | | bSx - heSx |
|
||||
| | = --------- | | | |
|
||||
| t2 | ad - bc | heSy - heEy heEx - heSx | | bSy - heSy |
|
||||
|
||||
where
|
||||
a = heEx - heSx
|
||||
b = bSx - bEx
|
||||
c = heEy - heSy
|
||||
d = bSy - bEy
|
||||
*/
|
||||
|
||||
/* Here we calculate ad - bc */
|
||||
denominator = heSx * (bEy - bSy) +
|
||||
heEx * (bSy - bEy) +
|
||||
bEx * (heEy - heSy) +
|
||||
bSx * (heSy - heEy);
|
||||
|
||||
if (denominator == 0) {
|
||||
/* In this case the two are parallel */
|
||||
return parallelIntersects(heSx, heSy, heEx, heEy, \
|
||||
bSx, bSy, bEx, bEy, x, y);
|
||||
}
|
||||
|
||||
/*
|
||||
Here we calculate the top row.
|
||||
| bSy - bEy bEx - bSx | | bSx - heSx |
|
||||
| | | |
|
||||
| | | bSy - heSy |
|
||||
*/
|
||||
numeratorX = heSx * (bEy - bSy) +
|
||||
bSx * (heSy - bEy) +
|
||||
bEx * (bSy - heSy);
|
||||
|
||||
/*
|
||||
Here we calculate the bottom row.
|
||||
| | | bSx - heSx |
|
||||
| | | |
|
||||
| heSy - heEy heEx - heSx | | bSy - heSy |
|
||||
*/
|
||||
numeratorY = -(heSx * (bSy - heEy) +
|
||||
heEx * (heSy - bSy) +
|
||||
bSx * (heEy - heSy));
|
||||
|
||||
/* Use parameters to convert to the intersection point */
|
||||
t1 = numeratorX/denominator;
|
||||
t2 = numeratorY/denominator;
|
||||
*x = heSx + t1 * (heEx - heSx);
|
||||
*y = heSy + t1 * (heEy - heSy);
|
||||
|
||||
/* Make final decision - if point is on segments, parameter values will be
|
||||
between 0, the start of the line segment, and 1, the end of the line segment.
|
||||
*/
|
||||
if (0.0 < t1 && t1 < 1.0 && 0.0 < t2 && t2 < 1.0) {
|
||||
return INTERSECT;
|
||||
} else if (t1 < 0.0 || 1.0 < t1 || t2 < 0.0 || 1.0 < t2) {
|
||||
/* s or t outside of line segment. */
|
||||
return DOESNT_INTERSECT;
|
||||
} else {
|
||||
/*
|
||||
((numeratorX == 0) || (numeratorY == 0) ||
|
||||
(numeratorX == denominator) || (numeratorY == denominator))
|
||||
*/
|
||||
return ENDS_OVERLAP;
|
||||
}
|
||||
}
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* */
|
||||
/* Here onwards are the functions from Grady's base code on Ed */
|
||||
/* */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
DCEL_t *newDCEL() {
|
||||
/* Setup DCEL. */
|
||||
|
@ -1011,83 +1012,208 @@ int inFace(DCEL_t *dcel, double x, double y, int faceIndex) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
intersection_t **getIntersections(intersection_t **intersections, \
|
||||
int *numIntersections, bisector_t **bisectors, int numBisectors, \
|
||||
DCEL_t *dcel, int face, double minLength) {
|
||||
int maxSizeIntersections = 1;
|
||||
/* This intersection is based on code by Joseph O'Rourke and is provided for
|
||||
* use in COMP20003 Assignment 2.
|
||||
*
|
||||
* The approach for intersections is:
|
||||
* - Use the bisector to construct a finite segment and test it against
|
||||
* the half-edge.
|
||||
* - Use O'Rourke's segseg intersection
|
||||
* (https://hydra.smith.edu/~jorourke/books/ftp.html) to check if the values
|
||||
* overlap/intersect
|
||||
*
|
||||
* Generates a segment with each end at least minLength away in each direction
|
||||
* from the bisector midpoint.
|
||||
*
|
||||
* Returns 1 if b intersects the given half-edge on this segment, 0 otherwise.
|
||||
* Sets the intersection point to the given x, y positions.
|
||||
*/
|
||||
|
||||
for (int i = 0; i < numBisectors; i++) {
|
||||
intersection_t *currentIntersection = NULL;
|
||||
int areaSign(double sx, double sy, double ex, double ey, double x, double y) {
|
||||
double areaSq;
|
||||
/* |AB x AC|^2, squared area */
|
||||
/* See https://mathworld.wolfram.com/CrossProduct.html */
|
||||
areaSq = (ex - sx) * (y - sy) -
|
||||
(x - sx) * (ey - sy);
|
||||
|
||||
/* Intersection coordinates */
|
||||
double x, y;
|
||||
if (areaSq > 0.0) {
|
||||
return 1;
|
||||
} else if (areaSq == 0.0) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
int between(double sx, double sy, double ex, double ey, double x, double y) {
|
||||
if (sx != ex) {
|
||||
/* If not vertical, check whether between x. */
|
||||
if ((sx <= x && x <= ex) || (sx >= x && x >= ex)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 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;
|
||||
} else {
|
||||
/* Vertical, so can't check _between_ x-values. Check y-axis. */
|
||||
if ((sy <= y && y <= ey) || (sy >= y && y >= ey)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return intersections;
|
||||
}
|
||||
|
||||
double getDiameter(DCEL_t *dcel, int faceIndex) {
|
||||
// FILL IN
|
||||
printf("in getDiamter(): faceIndex = %d, dcel faces = %d\n", \
|
||||
faceIndex, dcel->facesAllocated);
|
||||
return NODIAMETER;
|
||||
int collinear(double sx, double sy, double ex, double ey, double x, double y) {
|
||||
/* If area of the parallelogram is 0, then the points
|
||||
* are in the same line.
|
||||
*/
|
||||
if (areaSign(sx, sy, ex, ey, x, y) == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void incrementalVoronoi(DCEL_t *dcel, tower_t *tower) {
|
||||
// FILL IN
|
||||
printf("In incrementalVoronoi(): tower id = %s, dcel faces = %d\n", \
|
||||
tower->id, dcel->facesAllocated);
|
||||
enum intersectType parallelIntersects(double heSx, double heSy, \
|
||||
double heEx, double heEy, double bSx, double bSy, \
|
||||
double bEx, double bEy, double *x, double *y) {
|
||||
|
||||
if (!collinear(heSx, heSy, heEx, heEy, bSx, bSy)) {
|
||||
/* Parallel, no intersection so don't set (x, y) */
|
||||
return DOESNT_INTERSECT;
|
||||
}
|
||||
/* bS between heS and heE */
|
||||
if (between(heSx, heSy, heEx, heEy, bSx, bSy)) {
|
||||
*x = bSx;
|
||||
*y = bSy;
|
||||
return SAME_LINE_OVERLAP;
|
||||
}
|
||||
/* bE between heS and heE */
|
||||
if (between(heSx, heSy, heEx, heEy, bEx, bEy)) {
|
||||
*x = bEx;
|
||||
*y = bEy;
|
||||
return SAME_LINE_OVERLAP;
|
||||
}
|
||||
/* heS between bS and bE */
|
||||
if (between(bSx, bSy, bEx, bEy, heSx, heSy)) {
|
||||
*x = heSx;
|
||||
*y = heSy;
|
||||
return SAME_LINE_OVERLAP;
|
||||
}
|
||||
/* heE between bS and bE */
|
||||
if (between(bSx, bSy, bEx, bEy, heEx, heEy)) {
|
||||
*x = heEx;
|
||||
*y = heEy;
|
||||
return SAME_LINE_OVERLAP;
|
||||
}
|
||||
|
||||
return DOESNT_INTERSECT;
|
||||
}
|
||||
|
||||
enum intersectType intersects(halfEdge_t *he, bisector_t *b, \
|
||||
DCEL_t *dcel, double minLength, double *x, double *y) {
|
||||
|
||||
/* Half-edge x, y twin */
|
||||
double heSx = dcel->vertices[he->startVertex].x;
|
||||
double heSy = dcel->vertices[he->startVertex].y;
|
||||
double heEx = dcel->vertices[he->endVertex].x;
|
||||
double heEy = dcel->vertices[he->endVertex].y;
|
||||
|
||||
/* Bisector x, y twin */
|
||||
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);
|
||||
|
||||
/* Parametric equation parameters */
|
||||
double t1, t2;
|
||||
|
||||
/* Numerators for X and Y coordinate of intersection. */
|
||||
double numeratorX, numeratorY;
|
||||
|
||||
/* Denominators of intersection coordinates. */
|
||||
double denominator;
|
||||
|
||||
/*
|
||||
See http://www.cs.jhu.edu/~misha/Spring20/15.pdf
|
||||
for explanation and intuition of the algorithm here.
|
||||
x_1 = heSx, y_1 = heSy | p_1 = heS
|
||||
x_2 = heEx, y_2 = heEy | q_1 = heE
|
||||
x_3 = bSx , y_3 = bSy | p_2 = bS
|
||||
x_4 = bEx , y_4 = bEy | q_2 = bE
|
||||
----------------------------------------
|
||||
So the parameters t1 and t2 are given by:
|
||||
| t1 | | heEx - heSx bSx - bEx | -1 | bSx - heSx |
|
||||
| | = | | | |
|
||||
| t2 | | heEy - heSy bSy - bEy | | bSy - heSy |
|
||||
|
||||
Hence:
|
||||
| t1 | 1 | bSy - bEy bEx - bSx | | bSx - heSx |
|
||||
| | = --------- | | | |
|
||||
| t2 | ad - bc | heSy - heEy heEx - heSx | | bSy - heSy |
|
||||
|
||||
where
|
||||
a = heEx - heSx
|
||||
b = bSx - bEx
|
||||
c = heEy - heSy
|
||||
d = bSy - bEy
|
||||
*/
|
||||
|
||||
/* Here we calculate ad - bc */
|
||||
denominator = heSx * (bEy - bSy) +
|
||||
heEx * (bSy - bEy) +
|
||||
bEx * (heEy - heSy) +
|
||||
bSx * (heSy - heEy);
|
||||
|
||||
if (denominator == 0) {
|
||||
/* In this case the two are parallel */
|
||||
return parallelIntersects(heSx, heSy, heEx, heEy, \
|
||||
bSx, bSy, bEx, bEy, x, y);
|
||||
}
|
||||
|
||||
/*
|
||||
Here we calculate the top row.
|
||||
| bSy - bEy bEx - bSx | | bSx - heSx |
|
||||
| | | |
|
||||
| | | bSy - heSy |
|
||||
*/
|
||||
numeratorX = heSx * (bEy - bSy) +
|
||||
bSx * (heSy - bEy) +
|
||||
bEx * (bSy - heSy);
|
||||
|
||||
/*
|
||||
Here we calculate the bottom row.
|
||||
| | | bSx - heSx |
|
||||
| | | |
|
||||
| heSy - heEy heEx - heSx | | bSy - heSy |
|
||||
*/
|
||||
numeratorY = -(heSx * (bSy - heEy) +
|
||||
heEx * (heSy - bSy) +
|
||||
bSx * (heEy - heSy));
|
||||
|
||||
/* Use parameters to convert to the intersection point */
|
||||
t1 = numeratorX/denominator;
|
||||
t2 = numeratorY/denominator;
|
||||
*x = heSx + t1 * (heEx - heSx);
|
||||
*y = heSy + t1 * (heEy - heSy);
|
||||
|
||||
/* Make final decision - if point is on segments, parameter values will be
|
||||
between 0, the start of the line segment, and 1, the end of the line segment.
|
||||
*/
|
||||
if (0.0 < t1 && t1 < 1.0 && 0.0 < t2 && t2 < 1.0) {
|
||||
return INTERSECT;
|
||||
} else if (t1 < 0.0 || 1.0 < t1 || t2 < 0.0 || 1.0 < t2) {
|
||||
/* s or t outside of line segment. */
|
||||
return DOESNT_INTERSECT;
|
||||
} else {
|
||||
/*
|
||||
((numeratorX == 0) || (numeratorY == 0) ||
|
||||
(numeratorX == denominator) || (numeratorY == denominator))
|
||||
*/
|
||||
return ENDS_OVERLAP;
|
||||
}
|
||||
}
|
||||
|
|
226
dcel.h
226
dcel.h
|
@ -2,10 +2,23 @@
|
|||
#include "towers.h"
|
||||
#endif
|
||||
|
||||
#ifndef MATH_HEADER
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
#ifndef DCEL_HEADER
|
||||
#define DCEL_HEADER
|
||||
|
||||
/* Here is the Base Code from Grady, with some alterations by me */
|
||||
/* -------- Definitions, enums, and structs from Grady's base code --------- */
|
||||
|
||||
/* Representation of no face */
|
||||
#define NOFACE (-1)
|
||||
|
||||
/* Default face for intersections. */
|
||||
#define DEFAULT_FACE 0
|
||||
|
||||
/* Default minimum length for bisector in each direction */
|
||||
#define DEFAULTMINLENGTH (200)
|
||||
|
||||
enum intersectType {
|
||||
DOESNT_INTERSECT = 0, // Doesn't intersect
|
||||
|
@ -19,12 +32,6 @@ typedef struct vertex {
|
|||
double y;
|
||||
} vertex_t;
|
||||
|
||||
typedef struct bisector {
|
||||
vertex_t *mid;
|
||||
int isSlopeInfinite;
|
||||
double slope;
|
||||
} bisector_t;
|
||||
|
||||
typedef struct halfEdge {
|
||||
struct halfEdge *previous;
|
||||
struct halfEdge *next;
|
||||
|
@ -53,13 +60,6 @@ typedef struct split {
|
|||
vertex_t endPoint;
|
||||
} split_t;
|
||||
|
||||
typedef struct intersection {
|
||||
int fromEdge;
|
||||
int toEdge;
|
||||
vertex_t *fromPoint;
|
||||
vertex_t *toPoint;
|
||||
} intersection_t;
|
||||
|
||||
typedef struct DCEL {
|
||||
edge_t *edges;
|
||||
int edgesUsed;
|
||||
|
@ -74,35 +74,114 @@ typedef struct DCEL {
|
|||
int verticesAllocated;
|
||||
} DCEL_t;
|
||||
|
||||
/* ------------------------------ My structs ------------------------------- */
|
||||
|
||||
typedef struct bisector {
|
||||
vertex_t *mid;
|
||||
int isSlopeInfinite;
|
||||
double slope;
|
||||
} bisector_t;
|
||||
|
||||
typedef struct intersection {
|
||||
int fromEdge;
|
||||
int toEdge;
|
||||
vertex_t *fromPoint;
|
||||
vertex_t *toPoint;
|
||||
} intersection_t;
|
||||
|
||||
/* ----------------------- My points functions start ----------------------- */
|
||||
|
||||
/* Creates a new point */
|
||||
vertex_t *newPoint();
|
||||
|
||||
/* Gets a single point from an x-y pair */
|
||||
vertex_t *getAPoint(double x, double y);
|
||||
|
||||
/* Reads a points file and stores the information in the points array */
|
||||
vertex_t **readPoints(vertex_t **points, FILE *pointsFile, int *numPoints);
|
||||
|
||||
/* Frees an array of points */
|
||||
void freePoints(vertex_t **points, int numPoints);
|
||||
|
||||
/* Returns the distance between two points */
|
||||
double distPoints(vertex_t *pointA, vertex_t *pointB);
|
||||
|
||||
/* ------------------------ My points functions end ------------------------ */
|
||||
|
||||
/* -------------------- My intersection functions start -------------------- */
|
||||
|
||||
/* Create a new intersection */
|
||||
intersection_t *newIntersection();
|
||||
|
||||
/* Fills in a single intersection structure */
|
||||
intersection_t *getAnIntersection(intersection_t *intersection, DCEL_t *dcel, \
|
||||
bisector_t *bisector, int face, int minLength);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Frees an array of intersections */
|
||||
void freeIntersections(intersection_t **intersections, int numIntersections);
|
||||
|
||||
/* --------------------- My intersection functions end --------------------- */
|
||||
|
||||
/* ---------------------- My bisector functions start ---------------------- */
|
||||
|
||||
/* Creates a new bisector */
|
||||
bisector_t *newBisector();
|
||||
|
||||
/* Calculates and returns the equation of a bisector of two points */
|
||||
bisector_t *getABisector(bisector_t *bisector, vertex_t *pointA, \
|
||||
vertex_t *pointB);
|
||||
|
||||
/* Returns a list of bisectors built from a list of 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);
|
||||
|
||||
/* Frees an array of bisectors */
|
||||
void freeBisectors(bisector_t **bisectors, int numBisectors);
|
||||
|
||||
/* ----------------------- My bisector functions end ----------------------- */
|
||||
|
||||
/* ------------------------ My DCEL functions start ------------------------ */
|
||||
|
||||
/* Gets the diameter of the given face. */
|
||||
double getDiameter(DCEL_t *dcel, int faceIndex);
|
||||
|
||||
/* ------------------------- My DCEL functions end ------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Here on out are the functions from Grady's base code on Ed
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Allocate a new DCEL and return it. */
|
||||
DCEL_t *newDCEL();
|
||||
|
||||
/* Allocate a new halfEdge and return it. */
|
||||
halfEdge_t *newHalfEdge();
|
||||
|
||||
/* Returns INSIDE if the points is on the INSIDE of the vector twin by the CW
|
||||
* winding order, OUTSIDE if it is OUTSIDE by the CW winding order, and
|
||||
* DIR_UNDECIDED if the point lies on the vector between the points v1 and v2.
|
||||
*/
|
||||
int getRelativeDir(double x, double y, vertex_t *v1, vertex_t *v2);
|
||||
|
||||
/* Takes an established direction and a new direction, and returns 1 if the
|
||||
* direction matches the decidedDirection or if the direction is undecided.
|
||||
*/
|
||||
int directionOrUndecided(int decidedDirection, int direction);
|
||||
|
||||
/* Check there's space for another vertex in the DCEL,
|
||||
* or increase the allocated space.
|
||||
/* Check there's space for another vertex in the DCEL, or increase the
|
||||
* allocated space.
|
||||
*/
|
||||
void ensureSpaceForVertex(DCEL_t *dcel);
|
||||
|
||||
/* Check there's space for another edge in the DCEL,
|
||||
* or increase the allocated space.
|
||||
/* Check there's space for another edge in the DCEL, or increase the
|
||||
* allocated space.
|
||||
*/
|
||||
void ensureSpaceForEdge(DCEL_t *dcel);
|
||||
|
||||
/* Check there's space for another face in the DCEL,
|
||||
* or increase the allocated space.
|
||||
/* Check there's space for another face in the DCEL, or increase the
|
||||
* allocated space.
|
||||
*/
|
||||
void ensureSpaceForFace(DCEL_t *dcel);
|
||||
|
||||
|
@ -121,24 +200,12 @@ DCEL_t *readPolygonFile(char *polygonfileName);
|
|||
/* Reads the next split from the given file. */
|
||||
split_t *readNextSplit(FILE *splitfile);
|
||||
|
||||
/* Frees a given split. */
|
||||
/* Frees a given split. */
|
||||
void freeSplit(split_t *split);
|
||||
|
||||
/* Returns 1 if vertices are sufficiently close, 0 otherwise. */
|
||||
int vertexMatch(vertex_t *v1, vertex_t *v2);
|
||||
|
||||
/* Gets the string for the given bisector equation. */
|
||||
char *getBisectorEquation(bisector_t *b);
|
||||
|
||||
/* Representation of no face */
|
||||
#define NOFACE (-1)
|
||||
|
||||
/* Default face for intersections. */
|
||||
#define DEFAULT_FACE 0
|
||||
|
||||
/* Default minimum length for bisector in each direction */
|
||||
#define DEFAULTMINLENGTH (200)
|
||||
|
||||
/* Applies a given split to the DCEL. */
|
||||
void applySplit(split_t *split, DCEL_t *dcel);
|
||||
|
||||
|
@ -148,40 +215,37 @@ void freeDCEL(DCEL_t *dcel);
|
|||
/* Gets the number of faces in the DCEL. */
|
||||
int getFaceCount(DCEL_t *dcel);
|
||||
|
||||
/* Returns INSIDE if the points is on the INSIDE of the vector twin by the CW
|
||||
* winding order, OUTSIDE if it is OUTSIDE by the CW winding order, and
|
||||
* DIR_UNDECIDED if the point lies on the vector between the points v1 and v2.
|
||||
*/
|
||||
int getRelativeDir(double x, double y, vertex_t *v1, vertex_t *v2);
|
||||
|
||||
/* Takes an established direction and a new direction, and returns 1 if the
|
||||
* direction matches the decidedDirection or if the direction is undecided.
|
||||
*/
|
||||
int directionOrUndecided(int decidedDirection, int direction);
|
||||
|
||||
/* 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.
|
||||
/* ------------------- 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
|
||||
*/
|
||||
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);
|
||||
|
||||
/* Adds the watchtower to the Voronoi diagram represented by the given DCEL,
|
||||
* applying required splits and setting the watchtower as required.
|
||||
*/
|
||||
void incrementalVoronoi(DCEL_t *dcel, tower_t *watchTower);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
int areaSign(double sx, double sy, double ex, double ey, double x, double y);
|
||||
|
||||
/* Returns 1 if point (x, y) is between (sx, sy) and (ex, ey) */
|
||||
int between(double sx, double sy, double ex, double ey, double x, double y);
|
||||
|
||||
/* Returns 1 if the point (x, y) is in the line from s(x, y) to e(x, y),
|
||||
* 0 otherwise.
|
||||
* 0 otherwise
|
||||
*/
|
||||
int collinear(double sx, double sy, double ex, double ey, double x, double y);
|
||||
|
||||
/* Tests if the half edge and bisector are parallel and overlapping, or not
|
||||
* intersecting.
|
||||
* intersecting
|
||||
*/
|
||||
enum intersectType parallelIntersects(double heSx, double heSy, \
|
||||
double heEx, double heEy, double bSx, double bSy, \
|
||||
|
@ -191,38 +255,4 @@ enum intersectType parallelIntersects(double heSx, double heSy, \
|
|||
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
BIN
dcel.o
Binary file not shown.
156
ed.supp
Normal file
156
ed.supp
Normal file
|
@ -0,0 +1,156 @@
|
|||
{
|
||||
<insert_a_suppression_name_here>
|
||||
Memcheck:Cond
|
||||
fun:runtime.adjustframe
|
||||
fun:runtime.gentraceback
|
||||
fun:runtime.copystack
|
||||
fun:runtime.newstack
|
||||
fun:runtime.morestack
|
||||
fun:runtime.rt0_go
|
||||
}
|
||||
{
|
||||
<insert_a_suppression_name_here>
|
||||
Memcheck:Cond
|
||||
fun:runtime.adjustframe
|
||||
fun:runtime.gentraceback
|
||||
fun:runtime.copystack
|
||||
fun:runtime.newstack
|
||||
fun:runtime.morestack
|
||||
fun:runtime.rt0_go
|
||||
}
|
||||
{
|
||||
<insert_a_suppression_name_here>
|
||||
Memcheck:Cond
|
||||
fun:runtime.adjustpointer
|
||||
fun:runtime.adjustframe
|
||||
fun:runtime.gentraceback
|
||||
fun:runtime.copystack
|
||||
fun:runtime.newstack
|
||||
fun:runtime.morestack
|
||||
fun:runtime.rt0_go
|
||||
}
|
||||
{
|
||||
<insert_a_suppression_name_here>
|
||||
Memcheck:Cond
|
||||
fun:runtime.adjustpointer
|
||||
fun:runtime.adjustframe
|
||||
fun:runtime.gentraceback
|
||||
fun:runtime.copystack
|
||||
fun:runtime.newstack
|
||||
fun:runtime.morestack
|
||||
fun:runtime.rt0_go
|
||||
}
|
||||
{
|
||||
<insert_a_suppression_name_here>
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: possible
|
||||
fun:calloc
|
||||
fun:_dl_allocate_tls
|
||||
fun:pthread_create@@GLIBC_2.2.5
|
||||
fun:_cgo_try_pthread_create
|
||||
fun:x_cgo_sys_thread_create
|
||||
fun:_rt0_amd64_lib
|
||||
fun:call_init
|
||||
fun:_dl_init
|
||||
obj:/usr/lib/ld-2.33.so
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
}
|
||||
{
|
||||
<insert_a_suppression_name_here>
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: possible
|
||||
fun:calloc
|
||||
fun:_dl_allocate_tls
|
||||
fun:pthread_create@@GLIBC_2.2.5
|
||||
fun:_cgo_try_pthread_create
|
||||
fun:_cgo_sys_thread_start
|
||||
fun:runtime.asmcgocall
|
||||
obj:*
|
||||
fun:runtime.newm
|
||||
fun:runtime.main.func1
|
||||
fun:runtime.systemstack
|
||||
obj:/mnt/share/ed/libX11.so
|
||||
}
|
||||
{
|
||||
<insert_a_suppression_name_here>
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: possible
|
||||
fun:calloc
|
||||
fun:_dl_allocate_tls
|
||||
fun:pthread_create@@GLIBC_2.2.5
|
||||
fun:_cgo_try_pthread_create
|
||||
fun:_cgo_sys_thread_start
|
||||
fun:runtime.asmcgocall
|
||||
obj:*
|
||||
fun:runtime.newm
|
||||
fun:runtime.startm
|
||||
fun:runtime.newproc1
|
||||
fun:runtime.newproc.func1
|
||||
fun:runtime.systemstack
|
||||
}
|
||||
{
|
||||
<insert_a_suppression_name_here>
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: possible
|
||||
fun:calloc
|
||||
fun:_dl_allocate_tls
|
||||
fun:pthread_create@@GLIBC_2.2.5
|
||||
fun:_cgo_try_pthread_create
|
||||
fun:_cgo_sys_thread_start
|
||||
fun:runtime.asmcgocall
|
||||
obj:*
|
||||
fun:runtime.newm
|
||||
fun:runtime.startm
|
||||
fun:runtime.handoffp
|
||||
fun:runtime.stoplockedm
|
||||
fun:runtime.schedule
|
||||
}
|
||||
{
|
||||
<insert_a_suppression_name_here>
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: possible
|
||||
fun:calloc
|
||||
fun:_dl_allocate_tls
|
||||
fun:pthread_create@@GLIBC_2.2.5
|
||||
fun:_cgo_try_pthread_create
|
||||
fun:_cgo_sys_thread_start
|
||||
fun:runtime.asmcgocall
|
||||
obj:*
|
||||
fun:runtime.malg.func1
|
||||
fun:runtime.systemstack
|
||||
obj:/mnt/share/ed/libX11.so
|
||||
fun:runtime.rt0_go
|
||||
}
|
||||
{
|
||||
<edstem-suppression>
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: possible
|
||||
fun:calloc
|
||||
fun:_dl_allocate_tls
|
||||
fun:pthread_create@@GLIBC_2.2.5
|
||||
fun:_cgo_try_pthread_create
|
||||
fun:x_cgo_sys_thread_create
|
||||
fun:_rt0_amd64_lib
|
||||
fun:call_init
|
||||
fun:_dl_init
|
||||
obj:/usr/lib/ld-2.33.so
|
||||
}
|
||||
{
|
||||
<insert_a_suppression_name_here>
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: possible
|
||||
fun:calloc
|
||||
fun:_dl_allocate_tls
|
||||
fun:pthread_create@@GLIBC_2.2.5
|
||||
fun:_cgo_try_pthread_create
|
||||
fun:_cgo_sys_thread_start
|
||||
fun:runtime.asmcgocall
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
}
|
6
input.c
6
input.c
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* Created by Rory Healy (healyr@student.unimelb.edu.au)
|
||||
* Created on 8th September 2021
|
||||
* Last modified 9th September 2021
|
||||
* Last modified 14th September 2021
|
||||
*
|
||||
* Contains functions for ensuring correct input arguments are given for
|
||||
* each stage of the voronoi2 program. Adapted from Grady's base code on Ed.
|
||||
|
@ -13,10 +13,6 @@
|
|||
#include "input.h"
|
||||
#endif
|
||||
|
||||
#ifndef COMMON_HEADER
|
||||
#include "common.h"
|
||||
#endif
|
||||
|
||||
#define STAGE_1_ARG_COUNT 4
|
||||
#define STAGE_2_ARG_COUNT 5
|
||||
#define STAGE_3_ARG_COUNT 5
|
||||
|
|
4
input.h
4
input.h
|
@ -1,3 +1,7 @@
|
|||
#ifndef COMMON_HEADER
|
||||
#include "common.h"
|
||||
#endif
|
||||
|
||||
#ifndef INPUT_HEADER
|
||||
#define INPUT_HEADER
|
||||
|
||||
|
|
BIN
input.o
BIN
input.o
Binary file not shown.
15
main.c
15
main.c
|
@ -2,11 +2,16 @@
|
|||
*
|
||||
* Created by Rory Healy (healyr@student.unimelb.edu.au)
|
||||
* Created on 25th August 2021
|
||||
* Last modified 9th September 2021
|
||||
* Last modified 14th September 2021
|
||||
*
|
||||
* Lists the watchtowers that are in each face of the polygon.
|
||||
* The polygon can be split using a pair of integers, which represent
|
||||
* the edge numbers that should be connected. This comes from stdin.
|
||||
* Stage 1: Computes and outputs equations for the bisectors of points
|
||||
* Stage 2: Computes and outputs intersection points for bisectors against a
|
||||
* given polygon
|
||||
* Stage 3: Computes a Voronoi diagram using watchtowers as points and a
|
||||
* polygon as the outer boundary. Outputs diameters of each Voronoi
|
||||
* cell along with information about each watchtower.
|
||||
* Stage 4: Same as Stage 4, but the watchtowers are sorted by ascending order
|
||||
* by diameter.
|
||||
*
|
||||
* To see valid input arguments, run ./voronoi2
|
||||
*
|
||||
|
@ -25,6 +30,8 @@ int main(int argc, char **argv) {
|
|||
if (argc == 1) {
|
||||
printArgError(STAGE_ERROR, "Incorrect usage.");
|
||||
}
|
||||
|
||||
/* Get stage, ensure correct input args */
|
||||
enum stages stage = getStage(argv[1]);
|
||||
int expectedArgs = getExpectedArgs(stage);
|
||||
if (expectedArgs != argc) {
|
||||
|
|
BIN
main.o
BIN
main.o
Binary file not shown.
|
@ -1,6 +1 @@
|
|||
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)
|
||||
Watchtower ID: WT3765SHSPB, Postcode: 3765, Population Served: 3380, Watchtower Point of Contact Name: Eilene Horner, x: 145.362014, y: -37.818943, Diameter of Cell: 10.000000
|
||||
|
|
93
towers.c
93
towers.c
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* Created by Rory Healy (healyr@student.unimelb.edu.au)
|
||||
* Created on 11th September 2021
|
||||
* Last modified 13th September 2021
|
||||
* Last modified 14th September 2021
|
||||
*
|
||||
* Contains functions for reading a CSV of watchtower information into an
|
||||
* array of towers.
|
||||
|
@ -18,38 +18,7 @@
|
|||
#define MAX_FIELD_LEN 128
|
||||
#define NUM_CSV_FIELDS 6
|
||||
|
||||
tower_t **readTowers(tower_t **towers, FILE *datasetFile, int *numTowers) {
|
||||
/* 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 */
|
||||
char *lineBuffer = malloc(lineBufferSize * sizeof(*lineBuffer));
|
||||
checkNullPointer(lineBuffer);
|
||||
|
||||
int maxSizetowers = 1;
|
||||
|
||||
/* Discard the header line, then read the rest of the CSV */
|
||||
getline(&lineBuffer, &lineBufferSize, datasetFile);
|
||||
while (getline(&lineBuffer, &lineBufferSize, datasetFile) > 0) {
|
||||
/* Ensure there is enough space in the towers array */
|
||||
if (*numTowers == maxSizetowers) {
|
||||
maxSizetowers *= 2;
|
||||
tower_t **temp = realloc(towers, maxSizetowers * sizeof(*towers));
|
||||
checkNullPointer(temp);
|
||||
towers = temp;
|
||||
}
|
||||
|
||||
/* The current tower being filled in with information */
|
||||
towers[*numTowers] = malloc(sizeof(*towers[*numTowers]));
|
||||
|
||||
readCurrentTower(lineBuffer, towers[*numTowers]);
|
||||
*numTowers += 1;
|
||||
}
|
||||
free(lineBuffer);
|
||||
return towers;
|
||||
}
|
||||
|
||||
void readCurrentTower(char *lineBuffer, tower_t *tower) {
|
||||
void readATower(char *lineBuffer, tower_t *tower) {
|
||||
/* Stores the current CSV field for the current line */
|
||||
char *token = strtok(lineBuffer, ",");
|
||||
size_t tokenLength;
|
||||
|
@ -57,11 +26,8 @@ void readCurrentTower(char *lineBuffer, tower_t *tower) {
|
|||
for (int i = 0; i < NUM_CSV_FIELDS; i++) {
|
||||
tokenLength = strlen(token);
|
||||
switch(i) {
|
||||
/* Case 0, 1, and 3 deal with strings
|
||||
* Case 2 deals with an integer
|
||||
* Case 4 and 5 deal with doubles
|
||||
* Each case is handled seperately to fill in the
|
||||
* tower with no space wasted.
|
||||
/* Cases represent each field in the CSV, and as such are handled
|
||||
* differently.
|
||||
*/
|
||||
case 0:
|
||||
tower->id = malloc(sizeof(char) * tokenLength + 1);
|
||||
|
@ -95,12 +61,55 @@ void readCurrentTower(char *lineBuffer, tower_t *tower) {
|
|||
}
|
||||
}
|
||||
|
||||
tower_t **readTowers(tower_t **towers, FILE *datasetFile, int *numTowers) {
|
||||
/* 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 */
|
||||
char *lineBuffer = malloc(lineBufferSize * sizeof(*lineBuffer));
|
||||
checkNullPointer(lineBuffer);
|
||||
|
||||
int maxSizetowers = 1;
|
||||
|
||||
/* Discard the header line, then read the rest of the CSV */
|
||||
getline(&lineBuffer, &lineBufferSize, datasetFile);
|
||||
while (getline(&lineBuffer, &lineBufferSize, datasetFile) > 0) {
|
||||
/* Ensure there is enough space in the towers array */
|
||||
if (*numTowers == maxSizetowers) {
|
||||
maxSizetowers *= 2;
|
||||
tower_t **temp = realloc(towers, maxSizetowers * sizeof(*towers));
|
||||
checkNullPointer(temp);
|
||||
towers = temp;
|
||||
}
|
||||
|
||||
/* The current tower being filled in with information */
|
||||
towers[*numTowers] = malloc(sizeof(*towers[*numTowers]));
|
||||
|
||||
readATower(lineBuffer, towers[*numTowers]);
|
||||
*numTowers += 1;
|
||||
}
|
||||
free(lineBuffer);
|
||||
return towers;
|
||||
}
|
||||
|
||||
void freeTowers(tower_t **towers, int numTowers) {
|
||||
if (!towers) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numTowers; i++) {
|
||||
free(towers[i]->id);
|
||||
free(towers[i]->manager);
|
||||
free(towers[i]->postcode);
|
||||
free(towers[i]);
|
||||
if (towers[i]->id) {
|
||||
free(towers[i]->id);
|
||||
}
|
||||
if (towers[i]->manager) {
|
||||
free(towers[i]->manager);
|
||||
}
|
||||
if (towers[i]->postcode) {
|
||||
free(towers[i]->postcode);
|
||||
}
|
||||
if (towers[i]) {
|
||||
free(towers[i]);
|
||||
}
|
||||
}
|
||||
free(towers);
|
||||
}
|
||||
|
|
6
towers.h
6
towers.h
|
@ -14,12 +14,12 @@ typedef struct tower {
|
|||
double y;
|
||||
} tower_t;
|
||||
|
||||
/* Reads the current row from the CSV and converts it into a new tower */
|
||||
void readATower(char *lineBuffer, tower_t *tower);
|
||||
|
||||
/* Reads the CSV file and stores the information in the towers array */
|
||||
tower_t **readTowers(tower_t **towers, FILE *datasetFile, int *numTowers);
|
||||
|
||||
/* Reads the current row from the CSV and converts it into a new tower */
|
||||
void readCurrentTower(char *lineBuffer, tower_t *tower);
|
||||
|
||||
/* Frees all towers in a towers array */
|
||||
void freeTowers(tower_t **towers, int numTowers);
|
||||
|
||||
|
|
BIN
towers.o
BIN
towers.o
Binary file not shown.
88
voronoi.c
88
voronoi.c
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* Created by Rory Healy (healyr@student.unimelb.edu.au)
|
||||
* Created on 12th August 2021
|
||||
* Last modified 13th September 2021
|
||||
* Last modified 14th September 2021
|
||||
*
|
||||
* Contains functions involving the generation of the Voronoi diagram, and
|
||||
* running each stage of the assignment.
|
||||
|
@ -30,6 +30,58 @@ void stage2PrintIntersection(intersection_t *intersection, FILE *outputFile) {
|
|||
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");
|
||||
|
@ -59,7 +111,9 @@ void stage1(char *pointsFileName, char *outputFileName) {
|
|||
fclose(outputFile);
|
||||
}
|
||||
|
||||
void stage2(char *pointsFileName, char *polygonFileName, char *outputFileName) {
|
||||
void stage2(char *pointsFileName, char *polygonFileName, \
|
||||
char *outputFileName) {
|
||||
|
||||
FILE *pointsFile = NULL, *outputFile = NULL;
|
||||
pointsFile = safeFileOpen(&pointsFile, pointsFileName, "r");
|
||||
outputFile = safeFileOpen(&outputFile, outputFileName, "w");
|
||||
|
@ -83,8 +137,8 @@ void stage2(char *pointsFileName, char *polygonFileName, char *outputFileName) {
|
|||
intersection_t **intersections = malloc(sizeof(*intersections));
|
||||
checkNullPointer(intersections);
|
||||
int numIntersections = 0;
|
||||
intersections = getIntersections(intersections, &numIntersections, bisectors, numBisectors, dcel, DEFAULT_FACE, \
|
||||
DEFAULTMINLENGTH);
|
||||
intersections = getIntersections(intersections, &numIntersections, \
|
||||
bisectors, numBisectors, dcel, DEFAULT_FACE, DEFAULTMINLENGTH);
|
||||
|
||||
for (int i = 0; i < numIntersections; i++) {
|
||||
stage2PrintIntersection(intersections[i], outputFile);
|
||||
|
@ -105,9 +159,22 @@ void stage3(char *dataFileName, char *polygonFileName, char *outputFileName) {
|
|||
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);
|
||||
|
@ -119,9 +186,22 @@ void stage4(char *dataFileName, char *polygonFileName, char *outputFileName) {
|
|||
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);
|
||||
|
|
14
voronoi.h
14
voronoi.h
|
@ -11,6 +11,20 @@ void stage1PrintBisector(bisector_t *bisector, FILE *outputFile);
|
|||
/* Prints intersections to an output file */
|
||||
void stage2PrintIntersection(intersection_t *intersection, FILE *outputFile);
|
||||
|
||||
/* Prints the watchtower information to an output file */
|
||||
void stage34PrintTowers(tower_t *tower, FILE *outputFile, double diameter);
|
||||
|
||||
/* Returns the face a tower is in */
|
||||
int getFaceTowerIsIn(DCEL_t *dcel, tower_t *tower);
|
||||
|
||||
/* Adds the watchtower to the Voronoi diagram represented by the given DCEL,
|
||||
* applying required splits and setting the watchtower as required.
|
||||
*/
|
||||
void incrementalVoronoi(DCEL_t *voronoi, tower_t *tower);
|
||||
|
||||
/* Creates a new Voronoi structure */
|
||||
DCEL_t *newVoronoi(DCEL_t *voronoi, tower_t *towerA, tower_t *towerB);
|
||||
|
||||
/* Outputs the bisector equations from pointsFile into outputFile */
|
||||
void stage1(char *pointsFileName, char *outputFileName);
|
||||
|
||||
|
|
BIN
voronoi.o
BIN
voronoi.o
Binary file not shown.
BIN
voronoi2
BIN
voronoi2
Binary file not shown.
Loading…
Reference in a new issue