Home » Convex Hulls (Gift Wrapping Algorithm)!

Convex Hulls (Gift Wrapping Algorithm)!

Solving Convex Hulls (Gift Wrapping Algorithm) challenge by Power Query, Power BI, Excel, Python and R

The Convex Hull Algorithm leads to the smallest convex area (Polygon) that includes all the points in the dataset. In the given table, a list of data points is provided. Extract the points that lie on the vertices of the smallest convex area created by the algorithm described below. The algorithm begins with i=0 and a point p0​ known to be on the convex hull, such as the leftmost point. It selects the point pi+1​ such that all points are to the right of the line pi pi+1​. This point can be found by comparing the polar angles of all points with respect to point pi​ taken as the center of polar coordinates. Letting i=i+1, and repeating until one reaches ph=p0​ again, yields the convex hull in h steps.

📌 Challenge Details and Links
Challenge Number: 80
Challenge Difficulty: ⭐⭐⭐⭐⭐
📥Download Sample File
📥Link to the solutions on LinkedIn

Solving the challenge of Convex Hulls (Gift Wrapping Algorithm)! with Excel

Excel solution 1 for Convex Hulls (Gift Wrapping Algorithm)!, proposed by Bo Rydobon 🇹🇭:
=LET(z,
    SORT(
        B3:C25,
        2
    ),
    s,
    SEQUENCE(
        ROWS(
            z
        )
    ),R,
    LAMBDA(r,
    a,
    LET(b,
    TAKE(
        a,
        -1,
        1
    ),
    f,
    VSTACK(
        FILTER(
            s,
            ISNA(
                XMATCH(
                    s,
                    TAKE(
                        a,
                        ,
                        1
                    )
                )
            )
        ),
        1
    ),m,
    ATAN2(INDEX(
        z,
        f,
        1
    )-INDEX(
        z,
        b,
        1
    ),
    INDEX(
        z,
        f,
        2
    )-INDEX(
        z,
        b,
        2
    )),x,
    XLOOKUP(
        0,
        MOD(
            m-TAKE(
                a,
                -1,
                -1
            ),
            2*PI()
        ),
        HSTACK(
            f,
            m
        ),
        ,
        1
    ),
    IF(
        @x=1,
        TAKE(
                        a,
                        ,
                        1
                    ),
        r(
            r,
            VSTACK(
                a,
                x
            )
        )
    ))),CHOOSEROWS(
    z,
    R(
        R,
        {1,
        0}
    )
))
Excel solution 2 for Convex Hulls (Gift Wrapping Algorithm)!, proposed by Bo Rydobon 🇹🇭:
=LET(z,
    SORT(
        B3:C25,
        {2,
        1}
    ),
    s,
    SEQUENCE(
        ROWS(
            z
        )
    ),CHOOSEROWS(z,
    TOCOL(SCAN(,
    s,
    LAMBDA(a,
    _,
    LET(d,
    MOD(ATAN2(TAKE(
        z,
        ,
        1
    )-INDEX(
        z,
        a,
        1
    ),
    DROP(
        z,
        ,
        1
    )-INDEX(
        z,
        a,
        2
    )),
    2*PI())/7,XLOOKUP(
    MOD(
        a,
        1
    ),
    d,
    s+d,
    ,
    1
)))),
    3)))
Excel solution 3 for Convex Hulls (Gift Wrapping Algorithm)!, proposed by محمد حلمي:
=LET(
e,
    SORT(
        B3:C25,
        2
    ),REDUCE(B2:C2,
    SEQUENCE(
        10
    ),
    LAMBDA(a,
    v,
    LET(
u,
    TAKE(
        a,
        -1,
        1
    ),y,
    TAKE(
        a,
        -1,
        -1
    ),j,
    FILTER(
        e,
        ISNA(
            XMATCH(
                TAKE(
                    e,
                    ,
                    1
                )&TAKE(
                    e,
                    ,
                    -1
                ),
                u&y
            )
        )
    ),i,
    IFERROR(ATAN2(TAKE(
        j,
        ,
        1
    )-u,
    TAKE(
        j,
        ,
        -1
    )-y),
    ""),UNIQUE(
    VSTACK(
        a,        XLOOKUP(
            IF(
                SUM(
                    N(
                        i>=1
                    )
                )>3,
                0,
                -9
            ),
            i,
            j,
            ,
            1
        )
    )
)))))
Excel solution 4 for Convex Hulls (Gift Wrapping Algorithm)!, proposed by Julian Poeltl:
=LET(X,
    B3:B25,
    Y,
    C3:C25,
    V,
    ROWS(
        X
    ),
    I,
    SEQUENCE(
        V
    ),
    MinY,
    MIN(
        Y
    ),
    MinYX,
    XLOOKUP(
        MinY,
        Y,
        X
    ),
    SPA,
    IFERROR(ATAN2(X-MinYX,
    Y-MinY),
    0),
    SP,
    SORTBY(
        I,
        SPA,
        -1
    ),
    ItPA,
    LAMBDA(A,
    LET(XP,
    INDEX(
        X,
        A
    ),
    YP,
    INDEX(
        Y,
        A
    ),
    PA,
    IFERROR(ATAN2(X-XP,
    Y-YP),
    0),
    TAKE(
        FILTER(
            SORTBY(
                I,
                PA,
                -1
            ),
            SORTBY(
                I,
                PA,
                -1
            )<>A
        ),
        1
    ))),
    S,
    REDUCE(
        VSTACK(
            XMATCH(
                MinYX&MinY,
                X&Y
            ),
            TAKE(
                SP,
                1
            )
        ),
        SEQUENCE(
            V,
            ,
            0,
            0
        ),
        LAMBDA(
            A,
            B,
            VSTACK(
                B+ItPA(
                    TAKE(
                        A,
                        1
                    )
                ),
                A
            )
        )
    ),
    XM,
    XMATCH(
        1,
        S,
        ,
        -1
    ),
    R,
    CHOOSEROWS(
        S,
        SEQUENCE(
            V-XM+1,
            ,
            XM+1
        )
    ),
    HSTACK(
        INDEX(
            X,
            R
        ),
        INDEX(
            Y,
            R
        )
    ))

Solving the challenge of Convex Hulls (Gift Wrapping Algorithm)! with Python

Python solution 1 for Convex Hulls (Gift Wrapping Algorithm)!, proposed by Konrad Gryczan, PhD:
import pandas as pd
import numpy as np
from scipy.spatial import ConvexHull
import matplotlib.pyplot as plt

path = "CH-80 Convex Hulls.xlsx"
input = pd.read_excel(path, usecols="B:C", nrows=24, skiprows = 1)
test = pd.read_excel(path, usecols="E:F", nrows=5, skiprows = 1)
test.columns = ['X', 'Y']

points = input[['X', 'Y']].values

hull = ConvexHull(points)

# Plotting the convex hull
plt.plot(points[:,0], points[:,1], 'o', label='Points')
for simplex in hull.simplices:
 plt.plot(points[simplex, 0], points[simplex, 1], 'k-') 

plt.xlabel('X-axis')
plt.ylabel('Y-axis')
plt.title('Convex Hull of DataFrame Points')
plt.legend()
plt.show()

# Validation 
vertices = pd.DataFrame(points[hull.vertices], columns=['X', 'Y']).sort_values(by=['X', 'Y']).reset_index(drop=True)
test = test.sort_values(by=['X', 'Y']).reset_index(drop=True)
print(test.equals(vertices)) # True
Python solution 2 for Convex Hulls (Gift Wrapping Algorithm)!, proposed by Alejandro Campos:
df=xl("B3:C25")
points=df.to_numpy()

def gift_wrapping(points):
 n = len(points)
 hull = []
 l = np.argmin(points[:, 0])
 p = l
 while True:
 hull.append(points[p])
 q = (p + 1) % n
 for i in range(n):
 if (orientation(points[p], points[i], points[q]) == 2):
 q = i
 p = q
 if (p == l):
 break

 return np.array(hull)

def orientation(p, q, r):
 val = (q[1] - p[1]) * (r[0] - q[0]) - (q[0] - p[0]) * (r[1] - q[1])
 if val == 0:
 return 0 # colinear
 elif val > 0:
 return 1 # horario
 else:
 return 2 # antihorario

hull = gift_wrapping(points)

hull

Solving the challenge of Convex Hulls (Gift Wrapping Algorithm)! with R

R solution 1 for Convex Hulls (Gift Wrapping Algorithm)!, proposed by Konrad Gryczan, PhD:
library(tidyverse)
library(readxl)
library(patchwork)

path = "files/CH-80 Convex Hulls.xlsx"
input = read_excel(path, range = "B2:C25")
test = read_excel(path, range = "E2:F7")

hull_indices = chull(input$X, input$Y)
hull_vertices = input[hull_indices,]
hull_vertices = rbind(hull_vertices, hull_vertices[1,])

# validation ----
hull_vertices_val = hull_vertices %>% distinct() %>% arrange(X, Y)
test = test %>% arrange(X, Y)

identical(hull_vertices_val, test)
R solution 2 for Convex Hulls (Gift Wrapping Algorithm)!, proposed by Anil Kumar Goyal:
nformative challenge.
Strategy similar to Konrad Gryczan, PhD but using tidyverse piped synatax

df <- read_excel("OM Challanges/CH-80 Convex Hulls.xlsx", range = "B2:C25")


df %>% 
 slice(chull(X, Y))

Leave a Reply