2021-09-11 22:47:44 +10:00
|
|
|
#ifndef TOWERS_HEADER
|
|
|
|
#include "towers.h"
|
2021-09-08 21:48:00 +10:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef DCEL_HEADER
|
|
|
|
#define DCEL_HEADER
|
|
|
|
|
2021-09-11 22:47:44 +10:00
|
|
|
/* Here is the Base Code from Grady, with some alterations by me */
|
|
|
|
|
|
|
|
enum intersectType {
|
|
|
|
DOESNT_INTERSECT = 0, // Doesn't intersect
|
|
|
|
INTERSECT = 1, // Intersects
|
|
|
|
SAME_LINE_OVERLAP = 2, // Lines are the same
|
|
|
|
ENDS_OVERLAP = 3 // Intersects at exactly one point (endpoint)
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct vertex {
|
|
|
|
double x;
|
|
|
|
double y;
|
|
|
|
} vertex_t;
|
|
|
|
|
|
|
|
typedef struct bisector {
|
|
|
|
double startX;
|
|
|
|
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;
|
|
|
|
double slope;
|
|
|
|
} bisector_t;
|
|
|
|
|
|
|
|
typedef struct halfEdgeLabel {
|
|
|
|
struct halfEdgeLabel *previous;
|
|
|
|
struct halfEdgeLabel *next;
|
|
|
|
struct halfEdgeLabel *twin;
|
2021-09-09 17:10:24 +10:00
|
|
|
int face;
|
|
|
|
int edge;
|
2021-09-11 22:47:44 +10:00
|
|
|
int startVertex;
|
|
|
|
int endVertex;
|
2021-09-09 17:10:24 +10:00
|
|
|
} halfEdge_t;
|
|
|
|
|
|
|
|
typedef struct edge {
|
2021-09-11 22:47:44 +10:00
|
|
|
halfEdge_t *halfEdge;
|
2021-09-09 17:10:24 +10:00
|
|
|
} edge_t;
|
|
|
|
|
|
|
|
typedef struct face {
|
2021-09-11 22:47:44 +10:00
|
|
|
halfEdge_t *start;
|
|
|
|
tower_t *tower;
|
2021-09-09 17:10:24 +10:00
|
|
|
} face_t;
|
2021-09-08 21:48:00 +10:00
|
|
|
|
2021-09-11 22:47:44 +10:00
|
|
|
typedef struct split {
|
|
|
|
int startEdge;
|
|
|
|
int endEdge;
|
|
|
|
int verticesSpecified;
|
|
|
|
vertex_t startPoint;
|
|
|
|
vertex_t endPoint;
|
|
|
|
} split_t;
|
|
|
|
|
|
|
|
typedef struct intersection {
|
|
|
|
vertex_t intersectionPoint;
|
|
|
|
} intersection_t;
|
|
|
|
|
|
|
|
typedef struct DCEL {
|
|
|
|
edge_t *edges;
|
|
|
|
int edgesUsed;
|
|
|
|
int edgesAllocated;
|
|
|
|
|
|
|
|
face_t *faces;
|
|
|
|
int facesUsed;
|
|
|
|
int facesAllocated;
|
|
|
|
|
|
|
|
vertex_t *vertices;
|
|
|
|
int verticesUsed;
|
|
|
|
int verticesAllocated;
|
|
|
|
} DCEL_t;
|
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*/
|
|
|
|
void ensureSpaceForVertex(DCEL_t *dcel);
|
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*/
|
|
|
|
void ensureSpaceForFace(DCEL_t *dcel);
|
|
|
|
|
|
|
|
/* Add an edge from the startVertex index vertex to the endVertex index.
|
|
|
|
* Only fills one half-edge as other half-edges will always be added
|
|
|
|
* through geometry construction.
|
|
|
|
*/
|
|
|
|
void addEdge(DCEL_t *dcel, int startVertex, int endVertex);
|
|
|
|
|
|
|
|
/* Add a face to the DCEL given using the given halfEdge and sets the face. */
|
|
|
|
void addFace(DCEL_t *dcel, halfEdge_t *he);
|
|
|
|
|
|
|
|
/* Reads the polygon from the given file. */
|
|
|
|
DCEL_t *readPolygonFile(char *polygonfileName);
|
|
|
|
|
|
|
|
/* Reads the next split from the given file. */
|
|
|
|
split_t *readNextSplit(FILE *splitfile);
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
|
|
/* Frees the given bisector. */
|
|
|
|
void freeBisector(bisector_t *bisector);
|
|
|
|
|
|
|
|
/* 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)
|
|
|
|
|
|
|
|
/* 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. */
|
|
|
|
void applySplit(split_t *split, DCEL_t *dcel);
|
|
|
|
|
|
|
|
/* Frees the given DCEL */
|
|
|
|
void freeDCEL(DCEL_t *dcel);
|
|
|
|
|
|
|
|
/* Gets the number of faces in the DCEL. */
|
|
|
|
int getFaceCount(DCEL_t *dcel);
|
|
|
|
|
|
|
|
/* 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 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);
|
|
|
|
|
|
|
|
/* Returns the number of vertices in the DCEL. */
|
|
|
|
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 */
|
2021-09-08 21:48:00 +10:00
|
|
|
vertex_t **readPolygon(vertex_t **vertices, FILE *polygonFile, \
|
|
|
|
int *numVertices);
|
2021-09-11 22:47:44 +10:00
|
|
|
|
|
|
|
/* Frees an array of vertices */
|
2021-09-08 21:48:00 +10:00
|
|
|
void freeVertices(vertex_t **vertices, int numVertices);
|
2021-09-09 17:10:24 +10:00
|
|
|
|
2021-09-11 22:47:44 +10:00
|
|
|
/* 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
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
enum intersectType parallelIntersects(double heSx, double heSy, \
|
|
|
|
double heEx, double heEy, double bSx, double bSy, \
|
|
|
|
double bEx, double bEy, double *x, double *y);
|
|
|
|
|
|
|
|
/* Tests if */
|
|
|
|
enum intersectType intersects(halfEdge_t *he, bisector_t *b, \
|
|
|
|
DCEL_t *dcel, double minLength, double *x, double *y);
|
|
|
|
|
2021-09-08 21:48:00 +10:00
|
|
|
#endif
|