This program assumes that its Points array contains the points in a convex polygon in counterclockwise order. If you have some other group of points, first find their convex hull and then orient the resulting polygon counterclockwise. See these related articles:

- Determine whether a polygon is oriented clockwise or counterclockwise in C#
- Reverse the orientation of a polygon in C#
- Determine whether a polygon is convex in C#
- Find the convex hull of a set of points in C#

This example demonstrates the Rotating Calipers algorithm for finding a minimal bounding rectangle around the polygon. The algorithm is fairly involved, so I won’t show the code here. Instead I’ll describe the ideas.

The algorithm is also a bit tricky to visualize, so you may want to run the program a few times while you read the following description. Each time you click the Step button, the program performs one iteration of the algorithm and examines one candidate bounding rectangle.

Before I describe the algorithm, note that any minimal bounding rectangle has at least one edge that coincides with one of the polygon’s edges. The three other sides of the rectangle pass through at least one point on the polygon. (If another rectangle edge also coincides with a polygon edge, then that side will pass through more than one polygon point. It’s even possible that all four rectangle edges lie along polygon edges.)

To find all of the candidate bounding rectangles, you can build bounding rectangles for each of the polygon’s edges. Unfortunately the most straightforward way to find these bounding rectangles is relatively slow. For each edge, you would examine each of the polygon’s points to see which three can form edges that bound the polygon. Finding those points is an O(N) operation and you perform it for each of the polygon’s N edges so the total run time behavior is O(N^{2}). Furthermore the calculations are non-trivial.

The rotating caliper algorithm uses a trick to make finding the candidate bounding rectangles easier. It starts by building an initial bounding rectangle with edges parallel to the X and Y axes. This takes O(N) time: the program simply finds the points with the largest and smallest X and Y coordinates.

Next the program begins “rotating” the sides of this rectangle around the polygon. The next edge that it considers is adjacent to one of the four control points that determine the sides of the current rectangle.

The program examines the polygon’s edges that follow the four current control points and determines which one has the smallest angle of rotation from the previous edge. The next candidate rectangle uses this edge to determine one of its sides. Its other three sides pass through the three other control points.

The program uses the selected edge to calculate the slopes of the rectangle’s sides, finds the rectangle’s corners, and calculates the rectangle’s area.

It then moves the control point that comes before the selected edge to the following control point and repeats the process.

The program continues this series of steps:

- Find the edge following one of the current control points that has the smallest angle of change.
- Build a rectangle using the selected edge.
- Move the control point before the selected edge to the next point.

If the polygon has N points, it also has N edges so repeating this process N times makes the program consider every possible bounding rectangle. Each iteration takes a constant number of steps, so the total run time is only O(N).

Download the example program to see see the C# details. For a slightly more detailed description of the algorithm, see The minimum area enclosing rectangle for a convex polygon, which has a pretty good description.

Pingback: Perform geometric operations on polygons in C# |

Pingback: 最近demo 模块 算法总结 | ov智商捉急

Dear Rod,

I test this polygon, at the last step of the button “step”, the program make an error.

Could you help me, please.

Thanks.

Sorry but I don’t have time to look into this right now. I think it doesn’t like the fact that the final segment is vertical.

Hi Rod, thanks for the code.

It doesn’t matter if segments are parallel in FindIntersection();

…

One rectangle is found anyway.

I think it doesn’t matter in this example. The

FindIntersectionmethod only returns false if the segments do not intersect, but thedxanddyvalues are chosen so the segments are perpendicular and therefore always intersect.Also note that the point

pts[0]etc. cannot be null because aPointFis a structure and structures cannot be null. To make this test, you would need to do this: