feat: Improve path preview visualization in UnifiedAGVCanvas
Enhanced path drawing with better visibility: 1. Arrow improvements: - Changed from line-based arrows to filled triangle shapes - Increased arrow size by 1.5x for better visibility - Added polygon fill with outline for clearer identification 2. Path line improvements: - Added 50% transparency to purple path color (Alpha: 128) - Increased line thickness by 2x (from 4 to 8 pixels) - Improved visual contrast and clarity 3. Bidirectional path detection: - Detect routes that traverse the same segment multiple times - Display bidirectional paths with higher opacity (darker color, Alpha: 200) - Visual distinction helps identify round-trip routes Changes in UnifiedAGVCanvas.Events.cs: - Modified DrawDirectionArrow() to use FillPolygon instead of DrawLine - Enhanced DrawPath() with transparency, thickness, and bidirectional detection - Added System.Collections.Generic using statement Result: Much better visual identification of calculated paths in HMI 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ using AGVNavigationCore.Models;
|
|||||||
using AGVNavigationCore.PathFinding;
|
using AGVNavigationCore.PathFinding;
|
||||||
using AGVNavigationCore.PathFinding.Core;
|
using AGVNavigationCore.PathFinding.Core;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -153,28 +154,42 @@ namespace AGVNavigationCore.Controls
|
|||||||
|
|
||||||
private void DrawDirectionArrow(Graphics g, Point point, double angle, AgvDirection direction)
|
private void DrawDirectionArrow(Graphics g, Point point, double angle, AgvDirection direction)
|
||||||
{
|
{
|
||||||
var arrowSize = CONNECTION_ARROW_SIZE;
|
var arrowSize = CONNECTION_ARROW_SIZE * 1.5; // 화살표 크기 증가
|
||||||
var arrowAngle = Math.PI / 6; // 30도
|
var arrowAngle = Math.PI / 6; // 30도
|
||||||
|
|
||||||
var cos = Math.Cos(angle);
|
var cos = Math.Cos(angle);
|
||||||
var sin = Math.Sin(angle);
|
var sin = Math.Sin(angle);
|
||||||
|
|
||||||
|
// 화살표 끝점 (방향)
|
||||||
|
var arrowTipPoint = new Point(
|
||||||
|
(int)(point.X + arrowSize * Math.Cos(angle)),
|
||||||
|
(int)(point.Y + arrowSize * Math.Sin(angle))
|
||||||
|
);
|
||||||
|
|
||||||
|
// 화살표 좌측 점
|
||||||
var arrowPoint1 = new Point(
|
var arrowPoint1 = new Point(
|
||||||
(int)(point.X - arrowSize * Math.Cos(angle - arrowAngle)),
|
(int)(point.X - arrowSize * Math.Cos(angle - arrowAngle)),
|
||||||
(int)(point.Y - arrowSize * Math.Sin(angle - arrowAngle))
|
(int)(point.Y - arrowSize * Math.Sin(angle - arrowAngle))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 화살표 우측 점
|
||||||
var arrowPoint2 = new Point(
|
var arrowPoint2 = new Point(
|
||||||
(int)(point.X - arrowSize * Math.Cos(angle + arrowAngle)),
|
(int)(point.X - arrowSize * Math.Cos(angle + arrowAngle)),
|
||||||
(int)(point.Y - arrowSize * Math.Sin(angle + arrowAngle))
|
(int)(point.Y - arrowSize * Math.Sin(angle + arrowAngle))
|
||||||
);
|
);
|
||||||
|
|
||||||
var arrowColor = direction == AgvDirection.Forward ? Color.Blue : Color.Red;
|
var arrowColor = direction == AgvDirection.Forward ? Color.Blue : Color.Red;
|
||||||
var arrowPen = new Pen(arrowColor, 2);
|
var arrowBrush = new SolidBrush(arrowColor);
|
||||||
|
|
||||||
g.DrawLine(arrowPen, point, arrowPoint1);
|
// 삼각형으로 화살표 그리기 (내부 채움)
|
||||||
g.DrawLine(arrowPen, point, arrowPoint2);
|
var trianglePoints = new Point[] { arrowTipPoint, arrowPoint1, arrowPoint2 };
|
||||||
|
g.FillPolygon(arrowBrush, trianglePoints);
|
||||||
|
|
||||||
|
// 윤곽선 그리기
|
||||||
|
var arrowPen = new Pen(arrowColor, 1.5f);
|
||||||
|
g.DrawPolygon(arrowPen, trianglePoints);
|
||||||
|
|
||||||
|
arrowBrush.Dispose();
|
||||||
arrowPen.Dispose();
|
arrowPen.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,20 +219,55 @@ namespace AGVNavigationCore.Controls
|
|||||||
{
|
{
|
||||||
if (path?.Path == null || path.Path.Count < 2) return;
|
if (path?.Path == null || path.Path.Count < 2) return;
|
||||||
|
|
||||||
var pathPen = new Pen(color, 4) { DashStyle = DashStyle.Dash };
|
// 현재 선택된 경로인 경우 보라색 + 투명도 50% + 선 두께 2배
|
||||||
|
Color lineColor = color;
|
||||||
|
float lineThickness = 4;
|
||||||
|
|
||||||
|
if (color == Color.Purple)
|
||||||
|
{
|
||||||
|
// 투명도 50% (Alpha = 128 / 255)
|
||||||
|
lineColor = Color.FromArgb(128, color.R, color.G, color.B);
|
||||||
|
lineThickness = 8; // 2배 증가
|
||||||
|
}
|
||||||
|
|
||||||
|
var pathPen = new Pen(lineColor, lineThickness) { DashStyle = DashStyle.Dash };
|
||||||
|
|
||||||
|
// 왕복 경로 감지: 방문한 노드 추적
|
||||||
|
var visitedSegments = new Dictionary<string, int>();
|
||||||
|
|
||||||
for (int i = 0; i < path.Path.Count - 1; i++)
|
for (int i = 0; i < path.Path.Count - 1; i++)
|
||||||
{
|
{
|
||||||
var currentNodeId = path.Path[i];
|
var currentNodeId = path.Path[i];
|
||||||
var nextNodeId = path.Path[i + 1];
|
var nextNodeId = path.Path[i + 1];
|
||||||
|
|
||||||
|
// 왕복 구간 키 생성 (양방향 모두 같은 키)
|
||||||
|
var segmentKey = string.Compare(currentNodeId, nextNodeId) < 0
|
||||||
|
? $"{currentNodeId}_{nextNodeId}"
|
||||||
|
: $"{nextNodeId}_{currentNodeId}";
|
||||||
|
|
||||||
|
if (!visitedSegments.ContainsKey(segmentKey))
|
||||||
|
visitedSegments[segmentKey] = 0;
|
||||||
|
visitedSegments[segmentKey]++;
|
||||||
|
|
||||||
var currentNode = _nodes?.FirstOrDefault(n => n.NodeId == currentNodeId);
|
var currentNode = _nodes?.FirstOrDefault(n => n.NodeId == currentNodeId);
|
||||||
var nextNode = _nodes?.FirstOrDefault(n => n.NodeId == nextNodeId);
|
var nextNode = _nodes?.FirstOrDefault(n => n.NodeId == nextNodeId);
|
||||||
|
|
||||||
if (currentNode != null && nextNode != null)
|
if (currentNode != null && nextNode != null)
|
||||||
{
|
{
|
||||||
// 경로 선 그리기
|
// 왕복 경로면 더 진한 색상으로 표시
|
||||||
g.DrawLine(pathPen, currentNode.Position, nextNode.Position);
|
if (visitedSegments[segmentKey] > 1 && color == Color.Purple)
|
||||||
|
{
|
||||||
|
// 왕복 경로는 투명도를 낮춤 (더 진하게)
|
||||||
|
var darkPathColor = Color.FromArgb(200, color.R, color.G, color.B);
|
||||||
|
var darkPathPen = new Pen(darkPathColor, lineThickness) { DashStyle = DashStyle.Dash };
|
||||||
|
g.DrawLine(darkPathPen, currentNode.Position, nextNode.Position);
|
||||||
|
darkPathPen.Dispose();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 일반 경로 선 그리기
|
||||||
|
g.DrawLine(pathPen, currentNode.Position, nextNode.Position);
|
||||||
|
}
|
||||||
|
|
||||||
// 경로 방향 표시 (계산된 경로의 경우에만 방향 화살표 표시)
|
// 경로 방향 표시 (계산된 경로의 경우에만 방향 화살표 표시)
|
||||||
var midPoint = new Point(
|
var midPoint = new Point(
|
||||||
|
|||||||
Reference in New Issue
Block a user