Convex Hull

From APL Wiki
Jump to navigation Jump to search

The problem of finding convex hulls finds its practical applications in pattern recognition, digital image processing, statistics and geographic information systems. It also serves as a tool, a building block for a number of other computational-geometric algorithms. This page describes and implements an algorithm for computing a convex hull in R2.

Introduction

In a Euclidean Space the Convex Hull of a set I is defined as the intersection of all convex sets containing I.

For planar objects, i.e., lying in the plane R2, the convex hull may be easily visualized by imagining an elastic band stretched open to encompass the given object; when released, it will assume the shape of the required convex hull.

ConvexHull.svg

Graphical example

If the set I is a set of points in R2, then the convex hull is the smallest convex polygon which encloses I.

Gift wrapping algorithm

Many convex hull algorithms had been proposed for finding the points lying on the convex polygon.

Here a dfn is presented that implements a gift wrapping algorithm.

It follows a suggestion from Lars Strand, written in an email to programming@jsoftware.com at Jan 11, 2008.

A number of points in R2 are given. The problem is to determine the smallest convex region which includes all of the points.

The solution starts with the point p0 having the smallest x-value. The next point p1 will be the point which together with the first point defines a line having the smallest angle to the x-axis. Using this point p1 as vertex, the task is to find a third point p2 so that a line from the vertex has the largest angle to the line p0-p1.

Three points in the solution are now determined.

The procedure is repeated after a shift of p1 to p0, p2 to p1, and a new point p2 is found in the same way.

The procedure stops when the new point p2 is the same as the starting point.

The solution contains the coordinates of the points of the hull.

This dfn calls another dfn for computing the polar phase of all points with respect of a previously chosen point lying on the hull.

The iteration is implemented by means of primitive power operator.

Code

ConvexHull{
⍝ ⍵: matrix (2 rows) of points - first row:abscissae  second row:ordinates
⍝ return: matrix (2 rows) of points of convex hull

⍝ try:  ConvexHull ⍉9 2⍴1 0,1 ¯10,3 3,2 1,6 3,1 6,3 1,6 1,9 0

     ⎕IO0
     pts(⊂⍋⊃↓)[1]                        ⍝sort by x-values:first point←→start vertex
     phs{                                   ⍝ 12○⍵ polar phase ○¯1>≥○1.  see DFNS
         x y[1↓⍳⍴⍴]                      ⍝ x and y coordinates.
         x0 xn1 0=⊂0=x                      ⍝ points on/off y axis.
         top(x0×○0.5)+xnׯ3(|y)÷x+x0       ⍝ upper quadrants.
         (0.)×(1-2×y<0)×top+○x<0          ⍝ other quadrants.
     }
     anglesphs(0 1pts)-[0]0[1]pts         ⍝phases(radians) of the vectors
     ixStart0,1+⊃angles⍳⌊/angles            ⍝start with indexes of first segment
     ixHull{
         ix0 ix1¯2                        ⍝ix1: index of last point←→last vertex
         v{+(<0)×○2}phs pts-[0]ix1[1]pts ⍝phases with respect to the last vertex
         other(1↓⍴pts)~ix0 ix1             ⍝indexes of other points
         angles|(ix0v)-(other)v              ⍝       _______/\_______
         angles{f>○1  (×~f)+f×--○2}angles  ⍝angles (p0-p1)  (p1-px)
         ,(angles⍳⌈/angles)other           ⍝new vertex is where angle is largest
     }{
         0=⊃⌽                               ⍝repeat until first and last vertex coincide
     }ixStart
     (ixHull)[1]pts
 }