Rotating calipers

From Wikipedia, the free encyclopedia

Rotating calipers is a computational algorithm developed by Michael Shamos in 1978 for determining all antipodal pairs of points and vertices on a convex polygon or convex hull. The term "rotating calipers" was later coined in 1983 by the computer scientist Godfried Toussaint[1]. The name comes from the analogy of rotating a spring-loaded 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. The algorithm runs in O(n) time.

Contents

[edit] Applicable problems[2]

  • Diameter (maximum width) of a convex polygon
  • Width (minimum width) of a convex polygon
  • Maximum distance between two convex polygons
  • Minimum distance between two convex polygons
  • Minimum area oriented bounding box
  • Minimum perimeter oriented bounding box
  • Onion triangulations
  • Spiral triangulations
  • Quadrangulations
  • Merging two convex polygons
  • Common tangents to two convex polygons
  • Intersection points of two convex polygons
  • Critical support lines of two convex polygons
  • Vector sums of two convex polygons
  • Thinnest-strip transversals across multiple convex polygons

[edit] Minimum width of a convex polygon

 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;

[edit] References

  1. ^ Toussaint, G. T (1983). "Solving geometric problems with the rotating calipers". . Proc. MELECON '83, Athens
  2. ^ Rotating Calipers

[edit] See also