using System; using System.Collections.Generic; namespace AGVMapEditor.Models { /// /// A* 알고리즘에서 사용되는 경로 노드 /// public class PathNode : IComparable { /// /// 맵 노드 ID /// public string NodeId { get; set; } = string.Empty; /// /// AGV의 현재 방향 (이 노드에 도달했을 때의 방향) /// public AgvDirection Direction { get; set; } = AgvDirection.Forward; /// /// 시작점에서 이 노드까지의 실제 비용 (G) /// public float GCost { get; set; } = float.MaxValue; /// /// 이 노드에서 목표까지의 추정 비용 (H) /// public float HCost { get; set; } = 0; /// /// 총 비용 (F = G + H) /// public float FCost => GCost + HCost; /// /// 이전 노드 (경로 추적용) /// public PathNode Parent { get; set; } = null; /// /// 회전 횟수 (방향 전환 비용 계산용) /// public int RotationCount { get; set; } = 0; /// /// 이 노드에 도달하기 위한 이동 명령 시퀀스 /// public List MovementSequence { get; set; } = new List(); /// /// 기본 생성자 /// public PathNode() { } /// /// 매개변수 생성자 /// /// 노드 ID /// AGV 방향 public PathNode(string nodeId, AgvDirection direction) { NodeId = nodeId; Direction = direction; } /// /// 우선순위 큐를 위한 비교 (FCost 기준) /// public int CompareTo(PathNode other) { if (other == null) return 1; int compare = FCost.CompareTo(other.FCost); if (compare == 0) { // FCost가 같으면 HCost가 낮은 것을 우선 compare = HCost.CompareTo(other.HCost); } if (compare == 0) { // 그것도 같으면 회전 횟수가 적은 것을 우선 compare = RotationCount.CompareTo(other.RotationCount); } return compare; } /// /// 노드 상태 복사 /// public PathNode Clone() { return new PathNode { NodeId = NodeId, Direction = Direction, GCost = GCost, HCost = HCost, Parent = Parent, RotationCount = RotationCount, MovementSequence = new List(MovementSequence) }; } /// /// 고유 키 생성 (노드ID + 방향) /// public string GetKey() { return $"{NodeId}_{Direction}"; } /// /// 문자열 표현 /// public override string ToString() { return $"{NodeId}({Direction}) F:{FCost:F1} G:{GCost:F1} H:{HCost:F1} R:{RotationCount}"; } /// /// 해시코드 (딕셔너리 키용) /// public override int GetHashCode() { return GetKey().GetHashCode(); } /// /// 동등성 비교 /// public override bool Equals(object obj) { if (obj is PathNode other) { return NodeId == other.NodeId && Direction == other.Direction; } return false; } } }