Professional Documents
Culture Documents
O
in which case gsort expects a return of ~1 to indicate “less than.” See Figure 3.7.
When the area is zero, we fall into a sorting collinearity, which requires action as
discussed previously (Section 3.5.3). First we need to decide which point is closer to
po. We can avoid computing the distance by noting that if p; is closer, then r; = pi — Po
projects to a shorter length than does; = pj — po. The code computes these projections
"2 This is tue of many other languages as well, including any language that uses a fixed word size 10
represent either integers or floating-point numbers.
The quotes are from man qsort, the manual page on the routine,82 Convex Hulls in Two Dimensions
x and y and bases further decisions on them. If p; is closer, mark it for later deletion; if
p; is closer, mark it instead. If. x = y = 0, then p; — p, and we mark the one with lower
index for later deletion. (Which one we choose to delete doesn’t matter, but consistency
is required by qsort.) In all cases, one member of (—1, 0, +1} is returned according
to the angular sorting rule detailed earlier.
The peculiar casting from const void *tpitopi = (tPoint) tpi satisfies
the demands of qsort but permits natural use in the body of Compare.
int Compare( const void ‘tpi, const void *tpj }
£
int a; P* area!
int x, y; /* projs. of ri & rj in Ist quadrant %/
ePoint pi, pi;
pi = (tPoint) tpi;
Pj = (tPoine) tps
a = Area2( P[0}.v, pi->v, pi->v );
if (a> 0}
return -
else if (a < 0)
return 1;
else {/*Collinear with P(0] */
x = abs( pi->v[X] - P[0].v{X} )-abs( pj->v{X] - P[0].vIX] );
y = abs( pi->v[¥] - P[0).v[¥] )-abs( pj->v{¥] - P[0].v[¥] );
if ( (x <0) | ty <0) ) ¢
pi->delete = TRUE;
return -1;
}
else if ( (x > 0) i (y > 0) ) {
pj->delete = TRUE;
return
}
else {/* points are coincident */
if (pi->vaum > pj->vnum)
pj->delete = TRUE;
else
pi->delete = TRUE;
return 0;
}
ndelete++;
Code 3,5 Compare.3.5 Graham's Algorithm 83
Main
Having worked ont the sorting details, let us move to the top level and discuss main
(Code 3.6). The points are read in, the rightmost lowest is swapped with P[0] in
FindLowest, and P[1],...,P{n-1] are sorted by angle with qsort. The repeated
calls to Compare mark a number of points for deletion by setting the Boolean delete
field. The next (easy) task is to delete those points, which we accomplish with a simple
routine Squash (Code 3.7). This maintains two indices i and j into the points array P,
copying P[ i] on top of P{3] for all undeleted points i. After this the most problem-
atic cases are gone," and we can proceed with the Graham scan, with the call top =
Graham().
main()
(
tStack top:
n= ReadPointe();
FindLowest () ;
qsort (
P(t), J pointer to Ist elem */
n-1, /* number of elems */
sizeof( tsPoint ), /*size ofeach elem */
Compare /*—1,0,41 compare function */
%
Squash ();
top = Graham();
PrintStack( top );
Code 3.6 main.
Code for the Graham Scan
The code for the Graham scan is a nearly direct translation of the while loop in the
pseudocode presented earlier (Algorithm 3.6); see Code 3.8. We have the all too common
situation where the majority of the coding effort is on the periphery, with relatively little
needed for the heart of the geometric algorithm.
Example
The example in Figure 3.8 (a repeat of the points in Figure 3.6) was designed to be a
‘stringent test of the code, as it includes collinearities of all types. The points after angular
sorting, with marks for those to be deleted, are shown in Table 3.1. (The vnum indices
shown accord with the labels in Figure 3.8.) After deleting five points in Squash,
n= 14 points remain.
MQuite literally: If this code is embedding in another application, it may be necessary to avoid
‘corrupting the original input by copying into another array.84
Convex Hulls in Two Dimensions
void Squash( void }
(
int i, 5;
ee
while (i