This commit is contained in:
backuppc
2026-01-09 17:25:53 +09:00
parent efab3d042c
commit 880dc526da
9 changed files with 749 additions and 206 deletions

View File

@@ -421,7 +421,7 @@ namespace AGVNavigationCore.Controls
(int)(point.Y + arrowSize * Math.Sin(angle + 4 * Math.PI / 3))
);
var arrowColor = direction == AgvDirection.Forward ? Color.Blue : Color.Red;
var arrowColor = direction == AgvDirection.Forward ? Color.Blue : Color.Yellow;
var arrowBrush = new SolidBrush(arrowColor);
// 정삼각형으로 화살표 그리기 (내부 채움)
@@ -525,7 +525,15 @@ namespace AGVNavigationCore.Controls
var angle = Math.Atan2(nextNode.Position.Y - currentNode.Position.Y,
nextNode.Position.X - currentNode.Position.X);
DrawDirectionArrow(g, midPoint, angle, AgvDirection.Forward);
// 상세 경로 정보가 있으면 해당 방향 사용, 없으면 Forward
AgvDirection arrowDir = AgvDirection.Forward;
if (path.DetailedPath != null && i < path.DetailedPath.Count)
{
arrowDir = path.DetailedPath[i].MotorDirection;
}
DrawDirectionArrow(g, midPoint, angle, arrowDir);
}
}
@@ -535,57 +543,85 @@ namespace AGVNavigationCore.Controls
/// <summary>
/// 경로에 포함된 교차로(3개 이상의 노드가 연결된 노드)를 파란색으로 강조 표시
/// </summary>
/// <summary>
/// 경로에 포함된 특정 노드(Gateway 등)를 강조 표시
/// HighlightNodeId가 설정된 경우 해당 노드만 표시하고, 없으면 기존대로 교차로 표시(또는 표시 안함)
/// 사용자가 "교차로 대신 게이트웨이만 강조"를 원하므로 우선순위 적용
/// </summary>
private void HighlightJunctionsInPath(Graphics g, AGVPathResult path)
{
if (path?.Path == null || _nodes == null || _nodes.Count == 0)
return;
const int JUNCTION_CONNECTIONS = 3; // 교차로 판정 기준: 3개 이상의 연결
// 1. HighlightNodeId가 설정되어 있다면 해당 노드만 강조
if (!string.IsNullOrEmpty(HighlightNodeId))
{
var targetNode = path.Path.FirstOrDefault(n => n.Id == HighlightNodeId);
if (targetNode != null)
{
DrawJunctionHighlight(g, targetNode, true); // true = Gateway 강조 색상 사용
}
// HighlightNodeId가 설정된 경우 다른 교차로는 표시하지 않음 (사용자 요청)
return;
}
// 2. 설정이 없다면 기존 로직 (교차로 표시) 유지 여부 결정
// 사용자가 "게이트웨이만 강조해줘"라고 했으므로, 혼란을 피하기 위해
// HighlightNodeId가 없을 때는 아무것도 표시하지 않거나, 필요한 경우 복구.
// 현재는 사용자 요청에 따라 Gateway 지정이 안된 경우(일반 경로)에는 교차로 강조를 끄는 것이 맞아 보임.
// 하지만 일반 주행시에도 교차로 정보가 필요할 수 있으니 일단 둡니다.
// 단, Gateway 로직을 타는 경우(HighlightNodeId가 Set됨)에는 위에서 return 되므로 OK.
/*
const int JUNCTION_CONNECTIONS = 3;
foreach (var node in path.Path)
{
if (node == null) continue;
// 교차로 판정: 3개 이상의 노드가 연결된 경우
if (node.ConnectedMapNodes != null && node.ConnectedMapNodes.Count >= JUNCTION_CONNECTIONS)
{
DrawJunctionHighlight(g, node);
DrawJunctionHighlight(g, node, false);
}
}
*/
}
/// <summary>
/// 교차로 노드를 파란색 반투명 배경으로 강조 표시
/// 노드 강조 표시
/// </summary>
private void DrawJunctionHighlight(Graphics g, MapNode junctionNode)
private void DrawJunctionHighlight(Graphics g, MapNode junctionNode, bool isGateway)
{
if (junctionNode == null) return;
const int JUNCTION_HIGHLIGHT_RADIUS = 25; // 강조 표시 반경
int radius = isGateway ? 35 : 25; // 게이트웨이는 좀 더 크게
// 파란색 반투명 브러시로 배경 원 그리기
using (var highlightBrush = new SolidBrush(Color.FromArgb(80, 70, 130, 200))) // 파란색 (70, 130, 200) 알파 80
using (var highlightPen = new Pen(Color.FromArgb(150, 100, 150, 220), 2)) // 파란 테두리
// 색상 결정: Gateway=진한 주황/골드, 일반 교차로=기존 파랑
Color fillColor = isGateway ? Color.FromArgb(100, 255, 140, 0) : Color.FromArgb(80, 70, 130, 200);
Color penColor = isGateway ? Color.OrangeRed : Color.FromArgb(150, 100, 150, 220);
using (var highlightBrush = new SolidBrush(fillColor))
using (var highlightPen = new Pen(penColor, 3))
{
g.FillEllipse(
highlightBrush,
junctionNode.Position.X - JUNCTION_HIGHLIGHT_RADIUS,
junctionNode.Position.Y - JUNCTION_HIGHLIGHT_RADIUS,
JUNCTION_HIGHLIGHT_RADIUS * 2,
JUNCTION_HIGHLIGHT_RADIUS * 2
junctionNode.Position.X - radius,
junctionNode.Position.Y - radius,
radius * 2,
radius * 2
);
// 테두리 점선 효과 (Gateway 인 경우)
if (isGateway) highlightPen.DashStyle = DashStyle.Dot;
g.DrawEllipse(
highlightPen,
junctionNode.Position.X - JUNCTION_HIGHLIGHT_RADIUS,
junctionNode.Position.Y - JUNCTION_HIGHLIGHT_RADIUS,
JUNCTION_HIGHLIGHT_RADIUS * 2,
JUNCTION_HIGHLIGHT_RADIUS * 2
junctionNode.Position.X - radius,
junctionNode.Position.Y - radius,
radius * 2,
radius * 2
);
}
// 교차로 라벨 추가
//DrawJunctionLabel(g, junctionNode);
}
/// <summary>

View File

@@ -211,6 +211,12 @@ namespace AGVNavigationCore.Controls
}
}
/// <summary>
/// 강조해서 표시할 특정 노드 ID (예: Gateway)
/// 이 값이 설정되면 해당 노드만 강조 표시됩니다.
/// </summary>
public string HighlightNodeId { get; set; }
public void RemoveItem(NodeBase item)
{
if (item is MapImage img) RemoveImage(img);

View File

@@ -116,7 +116,11 @@ namespace AGVNavigationCore.PathFinding.Planning
// 기본값으로 경로 탐색 (이전 위치 = 현재 위치, 방향 = 전진)
return FindPath(startNode, targetNode, startNode, AgvDirection.Forward, AgvDirection.Forward, false);
}
public AGVPathResult FindPathAStar(MapNode startNode, MapNode targetNode)
{
// 기본값으로 경로 탐색 (이전 위치 = 현재 위치, 방향 = 전진)
return _basicPathfinder.FindPathAStar(startNode.Id, targetNode.Id);
}
public AGVPathResult FindPath(MapNode startNode, MapNode targetNode,
MapNode prevNode, AgvDirection prevDirection, AgvDirection currentDirection, bool crossignore = false)
{
@@ -434,6 +438,48 @@ namespace AGVNavigationCore.PathFinding.Planning
/// <summary>
/// 이 작업후에 MakeMagnetDirection 를 추가로 실행 하세요
/// </summary>
/// <summary>
/// 단순 경로 찾기 (복잡한 제약조건/방향전환 로직 없이 A* 결과만 반환)
/// </summary>
public AGVPathResult FindBasicPath(MapNode startNode, MapNode targetNode, MapNode prevNode, AgvDirection prevDirection)
{
// 1. 입력 검증
if (startNode == null || targetNode == null)
return AGVPathResult.CreateFailure("노드 정보 오류", 0, 0);
// 2. A* 경로 탐색
var pathResult = _basicPathfinder.FindPathAStar(startNode.Id, targetNode.Id);
pathResult.PrevNode = prevNode;
pathResult.PrevDirection = prevDirection;
if (!pathResult.Success)
return AGVPathResult.CreateFailure(pathResult.ErrorMessage ?? "경로 없음", 0, 0);
// 3. 상세 데이터 생성 (단순화: 방향 전환 없이 현재 방향 유지)
if (pathResult.Path != null && pathResult.Path.Count > 0)
{
var detailedPath = new List<NodeMotorInfo>();
for (int i = 0; i < pathResult.Path.Count; i++)
{
var node = pathResult.Path[i];
string nextNodeId = (i + 1 < pathResult.Path.Count) ? pathResult.Path[i + 1].Id : null;
// 단순화: 입력된 현재 방향을 그대로 사용
var nodeInfo = new NodeMotorInfo(i + 1, node.Id, node.RfidId, prevDirection, nextNodeId, MagnetDirection.Straight);
// 속도 설정
var mapNode = _mapNodes.FirstOrDefault(n => n.Id == node.Id);
if (mapNode != null) nodeInfo.Speed = mapNode.SpeedLimit;
detailedPath.Add(nodeInfo);
}
pathResult.DetailedPath = detailedPath;
}
return pathResult;
}
/// <summary>
/// 이 작업후에 MakeMagnetDirection 를 추가로 실행 하세요
/// </summary>