122 lines
3.1 KiB
Plaintext
122 lines
3.1 KiB
Plaintext
hullPts = {}
|
|
hullC = 0
|
|
|
|
# When called returns a list of points that forms a convex hull around
|
|
# the listPts Given (http://adultstudylife.blogspot.com/2016/06/quick-hull-in-python.html)
|
|
function QuickHull(focalpts) {
|
|
listPts = {}
|
|
hullPts = {}
|
|
jp = 0
|
|
foreach(focalpts, function(key, pt) {
|
|
ip = 0
|
|
while(ip<6){
|
|
listPts[jp*6+ip]=math.vec2.add(pt,math.vec2.newp(20, ip*math.pi/3))
|
|
#log("Created new pt: ", listPts[j*6+i].x, listPts[j*6+i].y, "(", pt.x, pt.y, ")")
|
|
ip=ip+1
|
|
}
|
|
jp=jp+1
|
|
})
|
|
|
|
# get the min, and max from the list of points
|
|
min_max = get_min_max_x(listPts)
|
|
|
|
hullPts = quickhull_rec(listPts, min_max.min, min_max.max)
|
|
|
|
hullPts = quickhull_rec(listPts, min_max.max, min_max.min)
|
|
|
|
return hullPts
|
|
}
|
|
|
|
# Does the sorting for the quick hull sorting algorithm
|
|
function quickhull_rec(listPts, minp, maxp) {
|
|
left_of_line_pts = get_points_left_of_line(minp, maxp, listPts)
|
|
|
|
ptC = point_max_from_line(minp, maxp, left_of_line_pts)
|
|
|
|
if(size(ptC) < 1){
|
|
hullPts[hullC] = maxp # max
|
|
hullC = hullC +1
|
|
return hullPts
|
|
#log("Add pt:", maxp.x, maxp.y)
|
|
}
|
|
|
|
hullPts = quickhull_rec(left_of_line_pts, minp, ptC)
|
|
|
|
hullPts = quickhull_rec(left_of_line_pts, ptC, maxp)
|
|
|
|
return hullPts
|
|
}
|
|
|
|
# Returns all points that are LEFT of a line start->end
|
|
function get_points_left_of_line(minp, maxp, listPts) {
|
|
pts = {}
|
|
ih = 0
|
|
|
|
foreach(listPts, function(key, pt) {
|
|
if(isCCW(minp, maxp, pt)){
|
|
pts[ih]=pt
|
|
ih=ih+1
|
|
}
|
|
})
|
|
|
|
return pts
|
|
}
|
|
|
|
# Returns the maximum point from a line start->end
|
|
function point_max_from_line(minp, maxp, points) {
|
|
max_dist = 0
|
|
max_point = {}
|
|
|
|
foreach(points, function(key, point) {
|
|
if((not(math.vec2.equal(point, minp))) and (not(math.vec2.equal(point, maxp)))) {
|
|
#log("Get distance of pt: ", point.x, point.y)
|
|
dist = distance_toline(minp, maxp, point)
|
|
if(dist > max_dist) {
|
|
max_dist = dist
|
|
max_point = point
|
|
}
|
|
}
|
|
})
|
|
|
|
return max_point
|
|
}
|
|
|
|
function get_min_max_x(list_pts) {
|
|
min_x = 100000
|
|
max_x = 0
|
|
min_y = 0
|
|
max_y = 0
|
|
|
|
foreach(list_pts, function(key, point) {
|
|
if(point.x < min_x){
|
|
min_x = point.x
|
|
min_y = point.y
|
|
}
|
|
if(point.x > max_x){
|
|
max_x = point.x
|
|
max_y = point.y
|
|
}
|
|
})
|
|
|
|
return {.min=math.vec2.new(min_x, min_y), .max=math.vec2.new(max_x, max_y)}
|
|
}
|
|
|
|
# Given a line of start->end, will return the distance that
|
|
# point, pt, is from the line.
|
|
function distance_toline(start, end, pt) { # pt is the point
|
|
x1 = start.x
|
|
y1 = start.y
|
|
x2 = end.x
|
|
y2 = end.y
|
|
x0 = pt.x
|
|
y0 = pt.y
|
|
nom = math.abs((y2 - y1) * x0 - (x2 - x1) * y0 + x2 * y1 - y2 * x1)
|
|
denom = math.vec2.length(math.vec2.sub(end,start))
|
|
result = nom / denom
|
|
return result
|
|
}
|
|
|
|
# Tests whether the turn formed by A, B, and C is ccw
|
|
function isCCW(A, B, C){
|
|
return (B.x - A.x) * (C.y - A.y) > (B.y - A.y) * (C.x - A.x)
|
|
} |