In computational geometry, rotating calipers is a method used to construct efficient algorithms for a number of problems.
The method was first used by Michael Shamos in 1978 for determining all antipodal pairs of points and vertices on a convex polygon. The term "rotating calipers" was later coined in 1983 by the computer scientist Godfried Toussaint,[1] who applied this approach to a number of other geometric problems.[2] The name comes from the analogy of rotating a spring-loaded vernier caliper around the outside of a convex polygon. Every time one blade of the caliper lies flat against an edge of the polygon, it forms an antipodal pair with the point or edge touching the opposite blade. It turns out that the complete "rotation" of the caliper around the polygon detects all antipodal pairs and may be carried out in O(n) time.[3]
|
Contents
|
ARRAY points := {P1, P2, ... , PN};
points.delete(middle vertices of any collinear sequence of three points);
REAL p_a := index of vertex with minimum y-coordinate;
REAL p_b := index of vertex with maximum y-coordinate;
REAL rotated_angle := 0;
REAL min_width := INFINITY;
VECTOR caliper_a(1,0); // Caliper A points along the positive x-axis
VECTOR caliper_b(-1,0); // Caliper B points along the negative x-axis
WHILE rotated_angle < PI
// Determine the angle between each caliper and the next adjacent edge in the polygon
VECTOR edge_a(points[p_a + 1].x - points[p_a].x, points[p_a + 1].y - points[p_a].y);
VECTOR edge_b(points[p_b + 1].x - points[p_b].x, points[p_b + 1].y - points[p_b].y);
REAL angle_a := angle(edge_a, caliper_a);
REAL angle_b := angle(edge_b, caliper_b);
REAL width := 0;
// Rotate the calipers by the smaller of these angles
caliper_a.rotate(min(angle_a, angle_b));
caliper_b.rotate(min(angle_a, angle_b));
IF angle_a < angle_b
p_a++; // This index should wrap around to the beginning of the array once it hits the end
width = caliper_a.distance(points[p_b]);
ELSE
p_b++; // This index should wrap around to the beginning of the array once it hits the end
width = caliper_b.distance(points[p_a]);
END IF
rotated_angle = rotated_angle + min(angle_a, angle_b);
IF (width < min_width)
min_width = width;
END IF
END WHILE
RETURN min_width;
This entry is from Wikipedia, the leading user-contributed encyclopedia. It may not have been reviewed by professional editors (see full disclaimer)