def getPaths(self): paths = Paths.Paths() paths.closed_paths = self._closed_paths for hash_lists in self._endpoints_map.values(): for info in hash_lists: if info.point_index == 0: paths.open_paths.append(info.path) for distance in [100, 250]: n = 0 while n < len(paths.open_paths): m = self._findOpenPathCloseTo(paths.open_paths[n][-1], paths.open_paths, distance) if m is not None and m != n: paths.open_paths[n] += paths.open_paths[m] paths.open_paths.pop(m) if m < n: n -= 1 continue n += 1 n = 0 while n < len(paths.open_paths): if PointUtil.length(PointUtil.sub(paths.open_paths[n][0], paths.open_paths[n][-1])) < 200: paths.closed_paths.append(paths.open_paths[n]) paths.open_paths.pop(n) continue n += 1 return paths
def _findClosestIndexTo(self, point, path): best = None best_distance = None for m in range(0, len(path)): distance = PointUtil.lengthSquared(PointUtil.sub(point, path[m])) if best_distance is None or best_distance > distance: best_distance = distance best = m return best
def _orderStartPoints(self): if len(self._result.open_paths) > 1: start = self._result.open_paths[0][0] for n in range(1, len(self._result.open_paths)): if PointUtil.lengthSquared(PointUtil.sub(start, self._result.open_paths[n][0])) > PointUtil.lengthSquared(PointUtil.sub(start, self._result.open_paths[n][-1])): self._result.open_paths[n].reverse() start = self._result.open_paths[n][-1] if len(self._result.closed_paths) > 1: start = self._result.closed_paths[0][0] for n in range(1, len(self._result.closed_paths)): best = self._findClosestIndexTo(start, self._result.closed_paths[n]) self._result.closed_paths[n] = self._result.closed_paths[n][best:] + self._result.closed_paths[n][:best] start = self._result.closed_paths[n][0] best = self._findClosestIndexTo(self._result.closed_paths[1][0], self._result.closed_paths[0]) self._result.closed_paths[0] = self._result.closed_paths[0][best:] + self._result.closed_paths[0][:best]
def _findEndpoint(self, point): best = None best_hash = None best_distance = 10 * 10 for hash in _hashes(point): if hash in self._endpoints_map: for info in self._endpoints_map[hash]: p = info.path[info.point_index] distance = PointUtil.lengthSquared(PointUtil.sub(p, point)) if distance < best_distance: best_distance = distance best_hash = hash best = info if best is not None: self._endpoints_map[best_hash].remove(best) return best
def _centerPoints(self, paths): center_points = [] for poly in paths.closed_paths: center = (0, 0) for point in poly: center = PointUtil.add(center, point) center = (center[0] / len(poly), center[1] / len(poly)) center_points.append(center) return center_points
def _calculateClosedOrder(self, center_points): done = [False] * len(center_points) start = None for n in range(0, len(center_points)): if start is None or center_points[start][0] > center_points[n][0]: start = n if start is None: return [] done[start] = True result = [start] while len(result) < len(center_points): best_distance = None best = None for n in range(0, len(center_points)): if done[n]: continue distance = PointUtil.lengthSquared(PointUtil.sub(center_points[start], center_points[n])) if best_distance is None or best_distance > distance: best_distance = distance best = n done[best] = True result.append(best) start = best return result
def _findOpenPathCloseTo(self, point, open_paths, distance): for n in range(0, len(open_paths)): if PointUtil.length(PointUtil.sub(open_paths[n][0], point)) < distance: return n return None
def _calculateOpenOrder(self, paths): quick_finds = 0 slow_finds = 0 slow_time = 0.0 Logger.log("i", "Line order optimizer, start") hash_map = {} for n in range(0, len(paths)): h = _hash(paths[n][0]) if h not in hash_map: hash_map[h] = [] hash_map[h].append(n) h = _hash(paths[n][-1]) if h not in hash_map: hash_map[h] = [] hash_map[h].append(n) todo = set(range(0, len(paths))) start = None for n in range(0, len(paths)): if start is None or paths[start][0][0] > paths[n][0][0]: start = n if start is None: return [] todo.remove(start) result = [start] while len(result) < len(paths): best_distance = None best = None for h in _hashes(paths[start][0]): if h in hash_map: for n in hash_map[h]: if n not in todo: continue distance = min( PointUtil.lengthSquared(PointUtil.sub(paths[start][0], paths[n][0])), PointUtil.lengthSquared(PointUtil.sub(paths[start][0], paths[n][-1])), PointUtil.lengthSquared(PointUtil.sub(paths[start][-1], paths[n][0])), PointUtil.lengthSquared(PointUtil.sub(paths[start][-1], paths[n][-1])) ) if best_distance is None or best_distance > distance: best_distance = distance best = n for h in _hashes(paths[start][-1]): if h in hash_map: for n in hash_map[h]: if n not in todo: continue distance = min( PointUtil.lengthSquared(PointUtil.sub(paths[start][0], paths[n][0])), PointUtil.lengthSquared(PointUtil.sub(paths[start][0], paths[n][-1])), PointUtil.lengthSquared(PointUtil.sub(paths[start][-1], paths[n][0])), PointUtil.lengthSquared(PointUtil.sub(paths[start][-1], paths[n][-1])) ) if best_distance is None or best_distance > distance: best_distance = distance best = n if best is None: slow_finds += 1 t = time.time() for n in todo: distance = min( PointUtil.lengthSquared(PointUtil.sub(paths[start][0], paths[n][0])), PointUtil.lengthSquared(PointUtil.sub(paths[start][0], paths[n][-1])), PointUtil.lengthSquared(PointUtil.sub(paths[start][-1], paths[n][0])), PointUtil.lengthSquared(PointUtil.sub(paths[start][-1], paths[n][-1])) ) if best_distance is None or best_distance > distance: best_distance = distance best = n slow_time += time.time() - t else: quick_finds += 1 todo.remove(best) result.append(best) start = best Logger.log("i", "Line order optimizer, quick: %d, slow: %d (%f)", quick_finds, slow_finds, slow_time) return result