User:Devon McCormick/convexHull

From J Wiki
Jump to navigation Jump to search

Brief description of the concept of a convex hull and some code for finding one for a given set of points.

What is a Convex Hull?

Here is a description of a convex hull. Intuitively, it is an efficient border around a set of points where, by efficient, we mean that it in some sense minimizes the area enclosed. Here is an online Java application that may help develop an intuitive feel for the meaning of this concept.

What Use is a Convex Hull?

This article in Dr. Dobbs provides a good introduction to convex hulls and mentions a few uses such as

  • Collision detection in video games
  • Visual pattern matching and object discrimination
  • Mapping
  • Path determination

Additionally, the feasible set of points for the solution of a linear programming problem is always convex. In fact, the optimal solution to such a problem can be found among the extreme points of such a set (provided that the set is bounded). This is the basis of the simplex algortithm.

How Might we Find a Convex Hull in J?

Here's some code submitted to the J Forum by Lars Strand <> and to which I added a visualization function. He offers the following explanation of the algorithm used.

from Lars Strand <>  Jan 11 (2 days ago)
reply-to Programming forum <>	
date	 Jan 11, 2008 6:55 AM	
subject	 [Jprogramming] manuscript	

Constructing a convex hull in J.

A number of points are given. The problem is to determine the smallest,
convex region which includes all of the points. The solution starts with
the point (0) having the smallest x-value. The next point (1) will be
the point which together with the first point defines a line having
the smallest angle to the x-axis. Using this point as vertex, the task
is to find a third point (2) so that a line from the vertex has the
largest angle to the line 0-1. 3 points in the solution are now

The procedure is repeated after a shift of  (1) to (0), (2) to (1), and
a new point (2) found in the same way. The procedure stops when the new
point (2) is the same as the starting point. The solution contains the
point numbers of the hull.

His code for this, lightly edited, follows.

compl=: 3 : 0                 NB. First = last
   nopts=: #y
   list=: i.#y
   startpt=: 0{sort y         NB. start
   startno=: y i.startpt
   red=: y-startpt
   angels=: 1{"1 *.red
   mina=: <./angels

   pt0=: startno
   pt1=: angels i. mina
   alt=: pt0,.pt1,.(i.nopts)-.pt0,pt1
   ina=: y angle3 "1 alt
   maxa=: >./ina
   pt2=: 2{(ina i. maxa){alt
   solution=: pt0,pt1,pt2     NB. The first 3

   while. (-. pt2= startno) do.
      pt0=: pt1
      pt1=: pt2
      alt=: pt0,.pt1,.(i.nopts)-.pt0,pt1
      ina=: y angle3 "1 alt
      maxa=: >./ina
      pt2=: {:(ina i. maxa){alt
      solution=: solution,pt2

angle3=: 4 : 0
   'p0 p1 p2'=: y
   v=: 1{"1 *.x-p1{x
   v1=: p0{v
   if. v1<0 do.v1=: (o.2) + v1 end.
   v2=: p2{v
   if. v2<0 do.v2=: (o.2) + v2 end.
   diff=: |v1-v2
   if. diff>o.1 do. (o.2)-diff end.

To see a set of points in blue and trace the convex hull in red using this code, use the following code:

   load 'plot'
showSolution=: 3 : 0
   pd 'show' [ pd y [ pd 'type point;pensize 5'
   pd 'pensize 2' [ pd 'color RED'
   pd 'show' [ pd y{~compl y [ pd 'type line'

For example, enter this

   showSolution pts=. j./?2 20$10

to find and graph the solution for 20 randomly-generated points. You should see something like this: ConvexHull2DEGsmaller.png

As written, this code does not generalize beyond two dimensions.

Further Considerations

Henry Rich had this advice to offer for building an efficient algorithm:

Any convex-hull implementation should start out with the following step:

Pick any 4 points that you think are toward the outside of the point set (min/max x/y are good candidates).

Discard any points that are inside the quadrilateral defined by these points.

This is quick and for large sets can greatly reduce the number of points that the detailed calculation needs to handle.