I have a set of objects (triangles) in the 2D-Plane and I want to separate them by a line into two sets of about the same size.
Because normally the line will intersect with some triangles, I get three sets. One on the left side, one on the right side and one with collisions with the line.
I now want to find a good line. I figured out a cost function:
cost=-min(len(set_left), len(set_right))
Unfortunately, I can't think of a nice algorithm to solve this. I have written a python exaple to show my problem: (I use the real part for x and the imaginary part for the y coordinate)
import scipy.optimize
import numpy as np
def scalar_prod (v1, v2):
return v1.real*v2.real + v1.imag*v2.imag
def intersect_line_triangle (line, triangle):
point = line[0]
dir_ = line[1]
# calculate normal vector
n_vec = 1j * dir_
# Calculate signed distance of each point
dist = tuple(scalar_prod(n_vec, p-point) for p in triangle)
if all(d > 0 for d in dist):
return 1 # right
if all(d < 0 for d in dist):
return -1 # left
return 0 # intersecting
def split_triangles_by_line (triangles, line):
out = {-1: [], 0:[], 1:[]}
for tri in triangles:
out[intersect_line_triangle(line,tri)].append(tri)
return out
def calc_cost (triangles, line):
split = split_triangles_by_line(triangles, line)
cost = -(min(len(split[-1]), len(split[1])))
return cost
def calc_line (triangles, method='Powell'):
# TODO: think about a good algorithm!
center_point = sum(sum(tri) for tri in triangles) / (len(triangles)*3)
init_point = center_point
fun = lambda args: calc_cost(triangles, (args[0] + 1j* args[1], np.exp(1j*args[2])))
res = scipy.optimize.minimize(fun, [init_point.real, init_point.imag, np.pi/2], method=method)
res_line = (res.x[0]+ 1j*res.x[1], np.exp(1j*res.x[2]))
return res_line
triangles = [(0, 3j, 2), (4, 2+2j, 6+2j),
(4j, 3+4j, 3+7j), (4+3j, 5+3j, 4+10j),
(-1+5j, -1+8j, 3+9j)]
line = calc_line(triangles)
sep_triangles = split_triangles_by_line(triangles, line)
print("The resulting line is {} + {} * t".format(line[0], line[1]))
print("The triangles are separated:\nleft: {}\nright: {}\nintersected: {}".format(sep_triangles[-1], sep_triangles[1], sep_triangles[0]))
print("The cost is {}".format(calc_cost(triangles, line)))
I want to replace the optimizer part by some efficient algorithm. I guess, that computer graphic experts may use similar things.
Thanks in advance!