using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; namespace PathLogic.Models { /// /// 맵 노드 정보를 관리하는 클래스 /// 기존 AGVNavigationCore의 MapNode와 호환되도록 설계 /// public class MapNode { /// /// 논리적 노드 ID (맵 에디터에서 관리하는 고유 ID) /// public string NodeId { get; set; } = string.Empty; /// /// 노드 표시 이름 /// public string Name { get; set; } = string.Empty; /// /// 맵 상의 위치 좌표 (픽셀 단위) /// public Point Position { get; set; } = Point.Empty; /// /// 노드 타입 /// public NodeType Type { get; set; } = NodeType.Normal; /// /// 도킹 방향 /// public DockingDirection DockDirection { get; set; } = DockingDirection.DontCare; /// /// 연결된 노드 ID 목록 /// public List ConnectedNodes { get; set; } = new List(); /// /// 회전 가능 여부 /// public bool CanRotate { get; set; } = false; /// /// 장비 ID /// public string StationId { get; set; } = string.Empty; /// /// 장비 타입 /// public StationType? StationType { get; set; } = null; /// /// 노드 생성 일자 /// public DateTime CreatedDate { get; set; } = DateTime.Now; /// /// 노드 수정 일자 /// public DateTime ModifiedDate { get; set; } = DateTime.Now; /// /// 노드 활성화 여부 /// public bool IsActive { get; set; } = true; /// /// 노드 색상 (맵 에디터 표시용) /// public Color DisplayColor { get; set; } = Color.Blue; /// /// RFID 태그 ID /// public string RfidId { get; set; } = string.Empty; /// /// RFID 상태 /// public string RfidStatus { get; set; } = "정상"; /// /// RFID 설치 위치 설명 /// public string RfidDescription { get; set; } = string.Empty; // UI 관련 속성들 (맵 에디터 호환성을 위해 포함) public string LabelText { get; set; } = string.Empty; public string FontFamily { get; set; } = "Arial"; public float FontSize { get; set; } = 12.0f; public FontStyle FontStyle { get; set; } = FontStyle.Regular; public Color ForeColor { get; set; } = Color.Black; public Color BackColor { get; set; } = Color.Transparent; public bool ShowBackground { get; set; } = false; public string ImagePath { get; set; } = string.Empty; public SizeF Scale { get; set; } = new SizeF(1.0f, 1.0f); public float Opacity { get; set; } = 1.0f; public float Rotation { get; set; } = 0.0f; /// /// 기본 생성자 /// public MapNode() { } /// /// 매개변수 생성자 /// public MapNode(string nodeId, string name, Point position, NodeType type) { NodeId = nodeId; Name = name; Position = position; Type = type; CreatedDate = DateTime.Now; ModifiedDate = DateTime.Now; SetDefaultColorByType(type); } /// /// 노드 타입에 따른 기본 색상 설정 /// public void SetDefaultColorByType(NodeType type) { switch (type) { case NodeType.Normal: DisplayColor = Color.Blue; break; case NodeType.Rotation: DisplayColor = Color.Orange; break; case NodeType.Docking: DisplayColor = Color.Green; break; case NodeType.Charging: DisplayColor = Color.Red; break; case NodeType.Label: DisplayColor = Color.Purple; break; case NodeType.Image: DisplayColor = Color.Brown; break; } } /// /// 경로 찾기에 사용 가능한 노드인지 확인 /// public bool IsNavigationNode() { return Type != NodeType.Label && Type != NodeType.Image && IsActive; } /// /// RFID가 할당되어 있는지 확인 /// public bool HasRfid() { return !string.IsNullOrEmpty(RfidId); } /// /// 도킹이 필요한 노드인지 확인 /// public bool RequiresDocking() { return Type == NodeType.Docking || Type == NodeType.Charging; } /// /// 회전이 가능한 노드인지 확인 /// public bool CanPerformRotation() { return CanRotate || Type == NodeType.Rotation; } /// /// 노드의 필요한 도킹 방향 반환 /// public AgvDirection GetRequiredDirection() { switch (DockDirection) { case DockingDirection.Forward: return AgvDirection.Forward; case DockingDirection.Backward: return AgvDirection.Backward; default: return AgvDirection.Forward; // 기본값 } } /// /// 다른 노드와 연결되어 있는지 확인 /// public bool IsConnectedTo(string nodeId) { return ConnectedNodes.Contains(nodeId); } /// /// 두 노드 간의 유클리드 거리 계산 /// public double DistanceTo(MapNode other) { if (other == null) return double.MaxValue; double dx = Position.X - other.Position.X; double dy = Position.Y - other.Position.Y; return Math.Sqrt(dx * dx + dy * dy); } /// /// 두 노드 간의 맨하탄 거리 계산 /// public double ManhattanDistanceTo(MapNode other) { if (other == null) return double.MaxValue; return Math.Abs(Position.X - other.Position.X) + Math.Abs(Position.Y - other.Position.Y); } /// /// 노드 정보를 문자열로 반환 /// public override string ToString() { string rfidInfo = HasRfid() ? $"[{RfidId}]" : ""; return $"{NodeId}{rfidInfo}: {Name} ({Type}) at ({Position.X}, {Position.Y})"; } /// /// 표시용 텍스트 반환 /// public string DisplayText { get { var displayText = NodeId; if (!string.IsNullOrEmpty(Name)) { displayText += $" - {Name}"; } if (!string.IsNullOrEmpty(RfidId)) { displayText += $" - [{RfidId}]"; } return displayText; } } /// /// 노드 복사 /// public MapNode Clone() { return new MapNode { NodeId = NodeId, Name = Name, Position = Position, Type = Type, DockDirection = DockDirection, ConnectedNodes = new List(ConnectedNodes), CanRotate = CanRotate, StationId = StationId, StationType = StationType, CreatedDate = CreatedDate, ModifiedDate = ModifiedDate, IsActive = IsActive, DisplayColor = DisplayColor, RfidId = RfidId, RfidStatus = RfidStatus, RfidDescription = RfidDescription, LabelText = LabelText, FontFamily = FontFamily, FontSize = FontSize, FontStyle = FontStyle, ForeColor = ForeColor, BackColor = BackColor, ShowBackground = ShowBackground, ImagePath = ImagePath, Scale = Scale, Opacity = Opacity, Rotation = Rotation }; } } }