7

Original post:

I'm trying to find the outermost vertices of a convex polygon (with relation to a point P outside the polygon). For now, I'm only concerned with rectangles (however, I'd like an algorithm that works with any convex polygon).

Point Demonstration

My plan is to construct a line from external point P to central point C. From this line of reference, I will construct lines from point P to points 1, 2, 3 and 4. Since points 2 and 4 will have the largest (most positive) and smallest (most negative) angles from the line of reference, they will be identified as the outermost vertices.

Is this the best algorithm for the job? How does one calculate angles from a reference angle (preferably in Java)?


Update for clarification:

enter image description here

I've drawn the lines (line of reference in red). As you can see, the line from P to 2 creates the largest angle on one side of the line of reference, while the line from P to 4 creates the largest angle of the other side. Hence, these are the outermost vertices.

Peter
  • 4,021
  • 5
  • 37
  • 58

3 Answers3

2

This is pretty much the convex hull problem. You would be looking for a set of vertices (x1, x2) around a polygon. The methodology that would be applied is called "quick-hull", analogous to quicksort (in that we divide our region of points every time we step through). It is also a safe assumption that P can be used as a mid-point between an arbitrary starting point and its parallel ending point, so you would get a convex hull around P.

It would take a while to produce some reliable Java to poke at (from my happenstance), but I think that the Wikipedia entry will give you a great starting point.

Makoto
  • 104,088
  • 27
  • 192
  • 230
  • I'm sorry... I don't think this is very similar to the convex hull problem. The boundaries of the shape are known, and I'm not using any Minkowski sums. Additionally, **P** *is* the starting point for the calculations. I'm looking for the *outermost vertices* with relation to external point **P**. Therefore, the operation is iterative and requires no step-wise division. – Peter Apr 02 '12 at 19:07
  • 2
    The convex hull of the points 1,2,3,4 is known. The convex hull of the points P,1,2,3,4 is not known. I think the outermost points are the two points adjacent to P in the convex hull of P,1,2,3,4. Notice 1 is not part of the convex hull of P,1,2,3,4. – emory Apr 02 '12 at 19:52
  • Ah. I understand now. So is a convex hull algorithm the quickest way to solve this? – Peter Apr 02 '12 at 20:35
  • 1
    @Peter: It would be a very quick way to solve it, yes; Quick-hull can achieve O(N*lg(N)) performance on average, with a worst-case of O(n^2) (highly unlikely). – Makoto Apr 02 '12 at 20:48
0

I solved the problem as follows:

            // code simplified for demonstration
            double angleBetweenVertices;
            double maxAngleBetweenVertices;
            vectorA.setStartingPoint(outerPoint);
            vectorA.setTerminationPoint(polygonCenter);
            vectorB.setStartingPoint(outerPount);

            // For each vertex, calculate the angle between the outer point, the polygon's center and the vertex
            for (Point2D.Double vertex : vertices) {    
                vectorB.setTerminationPoint(vertex);
                double angleBetweenVertices = 
                    Math.toDegrees(
                        Math.atan2(
                            (vectorA.perpDotProduct(vectorB)),
                            (vectorA.dotProduct(vectorB)) 
                        )
                    );

                // Update the min and Max
                if (angleBetweenVertices >= maxAngleBetweenVertices) {
                    maxVertex = vertex;
                    maxAngleBetweenVertices = angleBetweenVertices;
                } else if (angleBetweenVertices <= minAngleBetweenVertices) {
                    minVertex = vertex;
                    minAngleBetweenVertices = angleBetweenVertices;
                }
            }
Peter
  • 4,021
  • 5
  • 37
  • 58
0

The use of trigonometry is extremely slow. You should use another angle comparison.

For an angle between two flat vectors:

cos(OA, OB) = (OAx * OBx + OAy* OBy) / sqrt((OAx2 + OAy2)* (OBx 2 + OBy2))

I think, you can compare angles having cosines.

Gangnus
  • 24,044
  • 16
  • 90
  • 149