def mapPointsToNearestLine(inputPoints, inputLineArray): linemapping = {} for p in inputPoints: mindist = 99999999999999999999999999999999999999999999999 nearestline = None dpl = [] for l in inputLineArray: x1, y1, x2, y2 = l xm, ym = (x1 + x2) / 2.0, (y1 + y2) / 2.0 dx = x1 - xm dy = y1 - ym dx, dy = -dy, dx ort_x1 = xm + dx ort_y1 = ym + dy d = distance((x1, y1), (x2, y2), p) + distance((xm, ym), (ort_x1, ort_y1), p) dpl.append(d) if d < mindist: mindist = d nearestline = l if str(nearestline) not in linemapping: linemapping[str(nearestline)] = [] linemapping[str(nearestline)].append(p) return linemapping
lines.append(line) for rounds in range(100): assignment = KMeans.mapPointsToNearestLine(points, lines) cols = itertools.cycle(["ro", "yo", "go", "mo", "bo", "co"]) new_lines = [] new_centers = [] for key, values in assignment.items(): xm = np.array([e[0] for e in values]).mean() ym = np.array([e[1] for e in values]).mean() new_possible_lines = [generate_line((xm, ym), 2 * math.pi * (angle / 360.0)) for angle in range(0, 361, 2)] lines_with_error = [ (sum([distance((_line[0], _line[1]), (_line[2], _line[3]), p) for p in values]), _line) for _line in new_possible_lines ] lines_with_error_sorted = sorted(lines_with_error, key=lambda fg: fg[0]) new_lines.append(lines_with_error_sorted[0][1]) new_centers.append((xm, ym)) lines = new_lines centers = new_centers # Calculate the center of the assignment # Calculate for each of those centers all lines through that center and recalculate the error # Choose the line for the new stuff which minimizes the error - do that for all # Repeat plt.figure(rounds)