| | |
| | | // 无障碍物的情况 |
| | | if (grassType == 1) { |
| | | // 凸形地块,无障碍物 -> 调用 AoxinglujingNoObstacle |
| | | System.out.println("调用算法: 凸形无障碍物, 类名: AoxinglujingNoObstacle"); |
| | | List<AoxinglujingNoObstacle.PathSegment> segments = |
| | | AoxinglujingNoObstacle.planPath(boundary, plannerWidth, safetyMarginStr); |
| | | generated = formatAoxingPathSegments(segments); |
| | | } else if (grassType == 2) { |
| | | // 异形地块,无障碍物 -> 调用 YixinglujingNoObstacle |
| | | // 调用 YixinglujingNoObstacle.planPath 获取路径段列表 |
| | | System.out.println("调用算法: 异形无障碍物, 类名: YixinglujingNoObstacle"); |
| | | List<YixinglujingNoObstacle.PathSegment> segments = |
| | | YixinglujingNoObstacle.planPath(boundary, plannerWidth, safetyMarginStr); |
| | | // 格式化路径段列表为字符串 |
| | |
| | | JOptionPane.showMessageDialog(parentComponent, "无法判断地块类型,尝试按凸形地块处理", |
| | | "提示", JOptionPane.WARNING_MESSAGE); |
| | | } |
| | | System.out.println("调用算法: 无法判断类型(默认凸形无障碍物), 类名: AoxinglujingNoObstacle"); |
| | | List<AoxinglujingNoObstacle.PathSegment> segments = |
| | | AoxinglujingNoObstacle.planPath(boundary, plannerWidth, safetyMarginStr); |
| | | generated = formatAoxingPathSegments(segments); |
| | |
| | | if (grassType == 1) { |
| | | // 凸形地块,有障碍物 -> 调用 AoxinglujingHaveObstacel |
| | | // 传入参数:boundary(A), obstacles(B), plannerWidth(C), safetyMarginStr(D) |
| | | System.out.println("调用算法: 凸形有障碍物, 类名: AoxinglujingHaveObstacel"); |
| | | List<AoxinglujingHaveObstacel.PathSegment> segments = |
| | | AoxinglujingHaveObstacel.planPath(boundary, obstacles, plannerWidth, safetyMarginStr); |
| | | generated = formatAoxingHaveObstaclePathSegments(segments); |
| | | } else if (grassType == 2) { |
| | | // 异形地块,有障碍物 -> 调用 YixinglujingHaveObstacel |
| | | // 传入参数:boundary(A), obstacles(B), plannerWidth(C), safetyMarginStr(D) |
| | | System.out.println("调用算法: 异形有障碍物, 类名: YixinglujingHaveObstacel"); |
| | | List<YixinglujingHaveObstacel.PathSegment> segments = |
| | | YixinglujingHaveObstacel.planPath(boundary, obstacles, plannerWidth, safetyMarginStr); |
| | | generated = formatYixingHaveObstaclePathSegments(segments); |
| | |
| | | JOptionPane.showMessageDialog(parentComponent, "无法判断地块类型,尝试按凸形地块处理", |
| | | "提示", JOptionPane.WARNING_MESSAGE); |
| | | } |
| | | System.out.println("调用算法: 无法判断类型(默认凸形有障碍物), 类名: AoxinglujingHaveObstacel"); |
| | | List<AoxinglujingHaveObstacel.PathSegment> segments = |
| | | AoxinglujingHaveObstacel.planPath(boundary, obstacles, plannerWidth, safetyMarginStr); |
| | | generated = formatAoxingHaveObstaclePathSegments(segments); |
| | |
| | | return ""; |
| | | } |
| | | StringBuilder sb = new StringBuilder(); |
| | | AoxinglujingNoObstacle.Point last = null; |
| | | for (AoxinglujingNoObstacle.PathSegment segment : segments) { |
| | | // 只添加割草工作段,跳过过渡段 |
| | | if (segment.isMowing) { |
| | | // 如果起点与上一个终点不同,添加起点 |
| | | if (last == null || !equals2D(last, segment.start)) { |
| | | appendPoint(sb, segment.start); |
| | | } |
| | | // 添加终点 |
| | | appendPoint(sb, segment.end); |
| | | last = segment.end; |
| | | AoxinglujingNoObstacle.Point lastEnd = null; |
| | | boolean firstWritten = false; |
| | | for (AoxinglujingNoObstacle.PathSegment s : segments) { |
| | | if (!firstWritten) { |
| | | appendPoint(sb, s.start); |
| | | firstWritten = true; |
| | | lastEnd = s.start; |
| | | } else if (lastEnd == null || !equals2D(lastEnd, s.start)) { |
| | | // 非连续段,开始新的子路径 |
| | | appendPoint(sb, s.start); |
| | | lastEnd = s.start; |
| | | } |
| | | appendPointWithType(sb, s.end, s.isMowing); |
| | | lastEnd = s.end; |
| | | } |
| | | return sb.toString(); |
| | | } |
| | |
| | | return ""; |
| | | } |
| | | StringBuilder sb = new StringBuilder(); |
| | | YixinglujingNoObstacle.Point last = null; |
| | | for (YixinglujingNoObstacle.PathSegment segment : segments) { |
| | | // 只添加割草工作段,跳过过渡段 |
| | | if (segment.isMowing) { |
| | | // 如果起点与上一个终点不同,添加起点 |
| | | if (last == null || !equalsYixingPoint(last, segment.start)) { |
| | | appendYixingPoint(sb, segment.start); |
| | | } |
| | | // 添加终点 |
| | | appendYixingPoint(sb, segment.end); |
| | | last = segment.end; |
| | | YixinglujingNoObstacle.Point lastEnd = null; |
| | | boolean firstWritten = false; |
| | | for (YixinglujingNoObstacle.PathSegment s : segments) { |
| | | if (!firstWritten) { |
| | | appendYixingPoint(sb, s.start); |
| | | firstWritten = true; |
| | | lastEnd = s.start; |
| | | } else if (lastEnd == null || !equalsYixingPoint(lastEnd, s.start)) { |
| | | // 非连续段,开始新的子路径 |
| | | appendYixingPoint(sb, s.start); |
| | | lastEnd = s.start; |
| | | } |
| | | appendYixingPointWithType(sb, s.end, s.isMowing); |
| | | lastEnd = s.end; |
| | | } |
| | | return sb.toString(); |
| | | } |
| | |
| | | return ""; |
| | | } |
| | | StringBuilder sb = new StringBuilder(); |
| | | YixinglujingHaveObstacel.Point last = null; |
| | | for (YixinglujingHaveObstacel.PathSegment segment : segments) { |
| | | // 如果是第一段,或者当前段起点与上一段终点不连续,则添加起点 |
| | | if (last == null || !equalsYixingHaveObstaclePoint(last, segment.start)) { |
| | | appendYixingHaveObstaclePoint(sb, segment.start); |
| | | YixinglujingHaveObstacel.Point lastEnd = null; |
| | | boolean firstWritten = false; |
| | | for (YixinglujingHaveObstacel.PathSegment s : segments) { |
| | | if (!firstWritten) { |
| | | appendYixingHaveObstaclePoint(sb, s.start); |
| | | firstWritten = true; |
| | | lastEnd = s.start; |
| | | } else if (lastEnd == null || !equalsYixingHaveObstaclePoint(lastEnd, s.start)) { |
| | | appendYixingHaveObstaclePoint(sb, s.start); |
| | | lastEnd = s.start; |
| | | } |
| | | // 添加终点 |
| | | appendYixingHaveObstaclePoint(sb, segment.end); |
| | | last = segment.end; |
| | | appendYixingHaveObstaclePointWithType(sb, s.end, s.isMowing); |
| | | lastEnd = s.end; |
| | | } |
| | | return sb.toString(); |
| | | } |
| | |
| | | if (sb.length() > 0) { |
| | | sb.append(";"); |
| | | } |
| | | sb.append(String.format(Locale.US, "%.6f,%.6f", point.x, point.y)); |
| | | sb.append(String.format(Locale.US, "%.2f,%.2f", point.x, point.y)); |
| | | } |
| | | |
| | | private void appendYixingHaveObstaclePointWithType(StringBuilder sb, YixinglujingHaveObstacel.Point point, boolean isMowing) { |
| | | if (sb.length() > 0) { |
| | | sb.append(";"); |
| | | } |
| | | sb.append(String.format(Locale.US, "%.2f,%.2f,%s", point.x, point.y, isMowing ? "M" : "T")); |
| | | } |
| | | |
| | | /** |
| | |
| | | if (sb.length() > 0) { |
| | | sb.append(";"); |
| | | } |
| | | sb.append(String.format(Locale.US, "%.6f,%.6f", point.x, point.y)); |
| | | sb.append(String.format(Locale.US, "%.2f,%.2f", point.x, point.y)); |
| | | } |
| | | |
| | | private void appendPointWithType(StringBuilder sb, AoxinglujingNoObstacle.Point point, boolean isMowing) { |
| | | if (sb.length() > 0) { |
| | | sb.append(";"); |
| | | } |
| | | sb.append(String.format(Locale.US, "%.2f,%.2f,%s", point.x, point.y, isMowing ? "M" : "T")); |
| | | } |
| | | |
| | | /** |
| | |
| | | if (sb.length() > 0) { |
| | | sb.append(";"); |
| | | } |
| | | sb.append(String.format(Locale.US, "%.6f,%.6f", point.x, point.y)); |
| | | sb.append(String.format(Locale.US, "%.2f,%.2f", point.x, point.y)); |
| | | } |
| | | |
| | | private void appendYixingPointWithType(StringBuilder sb, YixinglujingNoObstacle.Point point, boolean isMowing) { |
| | | if (sb.length() > 0) { |
| | | sb.append(";"); |
| | | } |
| | | sb.append(String.format(Locale.US, "%.2f,%.2f,%s", point.x, point.y, isMowing ? "M" : "T")); |
| | | } |
| | | |
| | | /** |
| | |
| | | if (sb.length() > 0) { |
| | | sb.append(";"); |
| | | } |
| | | sb.append(String.format(Locale.US, "%.6f,%.6f", point.x, point.y)); |
| | | sb.append(String.format(Locale.US, "%.2f,%.2f", point.x, point.y)); |
| | | } |
| | | |
| | | // ========== UI辅助方法 ========== |