This repository has been archived by the owner on Jun 14, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
monotone-chain.c
94 lines (74 loc) · 3.32 KB
/
monotone-chain.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
Daniel Carvalho Dantas 10685702
Lucas Viana Vilela 10748409
*/
#include <stdio.h>
#include <stdlib.h>
#include "monotone-chain.h"
#include "./ADTs/stack.h"
#include "util.h"
list *convexHull(list *allPoints){
// If the list contains only 2 or fewer points they're always collinear
// If the list contains only collinear points, then a hull can't be determined
if(!list_isCollinear(allPoints)){
int noPoints = list_getLength(allPoints);
// Convex hull's upper and lower sections
stack *upperHull = stack_create();
stack *lowerHull = stack_create();
// In-focus point
point currentPoint;
// Auxiliar variable that'll store
// the second point from the top of the stack
point *auxPoint = NULL;
// Sorts the set of points from left to right (and bottom to top if there's a tie)
list_sort(allPoints, 'x');
// Lower Hull construction
for(int i = 0; i < noPoints; i++){
currentPoint = *(list_get(allPoints, i)); // Current point on the list
if(stack_getLength(lowerHull) >= 2){ auxPoint = stack_secondFromTop(lowerHull); } // Second point from the top of the stack
// If there's lees than 2 points in the stack --> the current point is ok
// If the last 2 points in the stack and the current point are not clockwise-oriented --> the current point is ok
// If the current point is ok --> push it to the stack
// If the current point is not ok --> pop a point from the stack and check again (and get new second point from the top)
while(stack_getLength(lowerHull) >= 2){
if(!isOriented(*auxPoint, *(stack_top(lowerHull)), currentPoint)){
free(stack_pop(lowerHull));
free(auxPoint);
if(stack_getLength(lowerHull) >= 2){ auxPoint = stack_secondFromTop(lowerHull); }
}
else{
free(auxPoint);
break;
}
}
stack_push(lowerHull, currentPoint);
}
// Upper Hull construction
for(int i = noPoints - 1; i >= 0; i--){
currentPoint = *(list_get(allPoints, i));
if(stack_getLength(upperHull) >= 2){ auxPoint = stack_secondFromTop(upperHull); }
while(stack_getLength(upperHull) >= 2){
if(!isOriented(*auxPoint, *(stack_top(upperHull)), currentPoint)){
free(stack_pop(upperHull));
free(auxPoint);
if(stack_getLength(lowerHull) >= 2){ auxPoint = stack_secondFromTop(upperHull); }
}
else{
free(auxPoint);
break;
}
}
stack_push(upperHull, currentPoint);
}
// The top point from each stack is the bottom point from the other one
free(stack_pop(lowerHull));
free(stack_pop(upperHull));
// Full convex hull
list *hull = list_create(stack_getLength(lowerHull) + stack_getLength(upperHull));
// Concatenates the stacks into the complete hull (counter-clockwise order)
list_attachStack(hull, lowerHull);
list_attachStack(hull, upperHull);
return hull;
}
return NULL;
}