Files
@ 8aaffb5565a2
Branch filter:
Location: EI/VirtualLeaf/src/hull.cpp
8aaffb5565a2
4.3 KiB
text/x-c++src
Corrected Compactness algorithm. Added algorithms to calculate circumference of convex hull and of the whole morph/
user: Roeland Merks <roeland.merks@cwi.nl>
branch 'default'
user: Roeland Merks <roeland.merks@cwi.nl>
branch 'default'
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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | // Copyright 2001, softSurfer (www.softsurfer.com)
// This code may be freely used and modified for any purpose
// providing that this copyright notice is included with it.
// SoftSurfer makes no warranty for this code, and cannot be held
// liable for any real or imagined damage resulting from its use.
// Users of this code must verify correctness for their application.
// Assume that a class is already given for the object:
// Point with coordinates {float x, y;}
//===================================================================
// isLeft(): tests if a point is Left|On|Right of an infinite line.
// Input: three points P0, P1, and P2
// Return: >0 for P2 left of the line through P0 and P1
// =0 for P2 on the line
// <0 for P2 right of the line
// See: the January 2001 Algorithm on Area of Triangles
#include "hull.h"
inline float
isLeft( Point P0, Point P1, Point P2 )
{
return (P1.x - P0.x)*(P2.y - P0.y) - (P2.x - P0.x)*(P1.y - P0.y);
}
// required to sort points (e.g. Qt's qSort())
bool operator<(const Point & p1, const Point & p2) {
if (p1.y<p2.y) return true;
else
if (p1.y>p2.y) return false;
else
if (p1.x<p2.x) return true;
else
return false;
}
//===================================================================
// chainHull_2D(): Andrew's monotone chain 2D convex hull algorithm
// Input: P[] = an array of 2D points
// presorted by increasing x- and y-coordinates
// n = the number of points in P[]
// Output: H[] = an array of the convex hull vertices (max is n)
// Return: the number of points in H[]
int
chainHull_2D( Point* P, int n, Point* H )
{
// the output array H[] will be used as the stack
int bot=0, top=(-1); // indices for bottom and top of the stack
int i; // array scan index
// Get the indices of points with min x-coord and min|max y-coord
int minmin = 0, minmax;
float xmin = P[0].x;
for (i=1; i<n; i++)
if (P[i].x != xmin) break;
minmax = i-1;
if (minmax == n-1) { // degenerate case: all x-coords == xmin
H[++top] = P[minmin];
if (P[minmax].y != P[minmin].y) // a nontrivial segment
H[++top] = P[minmax];
H[++top] = P[minmin]; // add polygon endpoint
return top+1;
}
// Get the indices of points with max x-coord and min|max y-coord
int maxmin, maxmax = n-1;
float xmax = P[n-1].x;
for (i=n-2; i>=0; i--)
if (P[i].x != xmax) break;
maxmin = i+1;
// Compute the lower hull on the stack H
H[++top] = P[minmin]; // push minmin point onto stack
i = minmax;
while (++i <= maxmin)
{
// the lower line joins P[minmin] with P[maxmin]
if (isLeft( P[minmin], P[maxmin], P[i]) >= 0 && i < maxmin)
continue; // ignore P[i] above or on the lower line
while (top > 0) // there are at least 2 points on the stack
{
// test if P[i] is left of the line at the stack top
if (isLeft( H[top-1], H[top], P[i]) > 0)
break; // P[i] is a new hull vertex
else
top--; // pop top point off stack
}
H[++top] = P[i]; // push P[i] onto stack
}
// Next, compute the upper hull on the stack H above the bottom hull
if (maxmax != maxmin) // if distinct xmax points
H[++top] = P[maxmax]; // push maxmax point onto stack
bot = top; // the bottom point of the upper hull stack
i = maxmin;
while (--i >= minmax)
{
// the upper line joins P[maxmax] with P[minmax]
if (isLeft( P[maxmax], P[minmax], P[i]) >= 0 && i > minmax)
continue; // ignore P[i] below or on the upper line
while (top > bot) // at least 2 points on the upper stack
{
// test if P[i] is left of the line at the stack top
if (isLeft( H[top-1], H[top], P[i]) > 0)
break; // P[i] is a new hull vertex
else
top--; // pop top point off stack
}
H[++top] = P[i]; // push P[i] onto stack
}
if (minmax != minmin)
H[++top] = P[minmin]; // push joining endpoint onto stack
return top+1;
}
|