Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PKG: Add convexhull computation package #1840

Merged
merged 2 commits into from
May 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ RUN(NAME test_package_01 LABELS cpython llvm)
RUN(NAME test_pkg_lpdraw LABELS cpython llvm wasm)
RUN(NAME test_pkg_lnn_01 LABELS cpython llvm)
RUN(NAME test_pkg_lnn_02 LABELS cpython llvm)
RUN(NAME test_pkg_lpconvexhull LABELS cpython c)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it work with llvm?

Copy link
Collaborator Author

@Shaikh-Ubaid Shaikh-Ubaid May 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it work with llvm?

It does not work with LLVM yet. I will create an issue for it soon.


RUN(NAME generics_01 LABELS cpython llvm c)
RUN(NAME generics_02 LABELS cpython llvm c)
Expand Down
1 change: 1 addition & 0 deletions integration_tests/lpconvexhull/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .lpconvexhull_main import convex_hull
56 changes: 56 additions & 0 deletions integration_tests/lpconvexhull/lpconvexhull_main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from lpython import i32
from .utils import min, distance

def orientation(p: tuple[i32, i32], q: tuple[i32, i32], r: tuple[i32, i32]) -> i32:
# Function to find the orientation of triplet (p, q, r)
# Returns the following values:
# 0: Colinear
# 1: Clockwise
# 2: Counterclockwise
value: i32 = (q[1] - p[1]) * (r[0] - q[0]) - (q[0] - p[0]) * (r[1] - q[1])
if value == 0:
return 0 # Colinear
elif value > 0:
return 1 # Clockwise
else:
return 2 # Counterclockwise


def convex_hull(points: list[tuple[i32, i32]]) -> list[tuple[i32, i32]]:
"""Finds the convex hull of a set of points.

Args:
points: A list of points.

Returns:
A list of points that form the convex hull.
"""

n: i32 = len(points)
if n < 3:
return [(-1, -1)] # Convex hull not possible
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that we do not support returning empty lists (#1841). Therefore, returning a list with single item with negative/invalid coordinates.


# Find the leftmost point
leftmost: tuple[i32, i32] = min(points)
hull: list[tuple[i32, i32]] = []

p: tuple[i32, i32] = leftmost

while True:
hull.append(p)
q: tuple[i32, i32] = points[0]

r: tuple[i32, i32]
for r in points:
if r == p or r == q:
continue
direction: i32 = orientation(p, q, r)
if direction == 1 or (direction == 0 and distance(p, r) > distance(p, q)):
q = r

p = q

if p == leftmost:
break

return hull
29 changes: 29 additions & 0 deletions integration_tests/lpconvexhull/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from lpython import i32, f64

def min(points: list[tuple[i32, i32]]) -> tuple[i32, i32]:
"""Finds the left-most point in a list of points.

Args:
points: A list of points.

Returns:
The left-most point in the list.
"""

left_most_point: tuple[i32, i32] = points[0]
point: tuple[i32, i32]
for point in points:
if point[0] < left_most_point[0]:
left_most_point = point

return left_most_point


def distance(p: tuple[i32, i32], q: tuple[i32, i32]) -> f64:
# Function to calculate the Euclidean distance between two points
x1: i32; y1: i32
x2: i32; y2: i32

x1, y1 = p
x2, y2 = q
return f64((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5
32 changes: 32 additions & 0 deletions integration_tests/test_pkg_lpconvexhull.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from lpython import Const, i32, f64

from lpdraw import Line, Circle, Clear, Display
from lpconvexhull import convex_hull
from numpy import empty, int32

def plot_graph(polygon: list[tuple[i32, i32]], points: list[tuple[i32, i32]]):
Width: Const[i32] = 500 # x-axis limits [0, 499]
Height: Const[i32] = 500 # y-axis limits [0, 499]
Screen: i32[Height, Width] = empty((Height, Width), dtype=int32)
Clear(Height, Width, Screen)

i: i32
n: i32 = len(polygon)
for i in range(n):
Line(Height, Width, Screen, polygon[i][0], polygon[i][1], polygon[(i + 1) % n][0], polygon[(i + 1) % n][1])

point_size: i32 = 5
for i in range(len(points)):
Circle(Height, Width, Screen, points[i][0], points[i][1], f64(point_size))

Display(Height, Width, Screen)

def main0():
points: list[tuple[i32, i32]] = [(445, 193), (138, 28), (418, 279), (62, 438), (168, 345), (435, 325), (293, 440), (158, 94), (403, 288), (136, 278), (141, 243), (287, 313), (338, 492), (172, 78), (29, 404), (79, 377), (184, 91), (69, 324), (408, 72), (494, 1)]
convex_hull_points: list[tuple[i32, i32]] = convex_hull(points)
# print(convex_hull_points)
plot_graph(convex_hull_points, points)

assert convex_hull_points == [(29, 404), (138, 28), (494, 1), (435, 325), (338, 492), (62, 438)]

main0()