copilot file backup
This commit is contained in:
89
Cs_HMI/PathLogic/Models/Enums.cs
Normal file
89
Cs_HMI/PathLogic/Models/Enums.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
|
||||
namespace PathLogic.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 노드 타입 열거형
|
||||
/// </summary>
|
||||
public enum NodeType
|
||||
{
|
||||
/// <summary>일반 경로 노드</summary>
|
||||
Normal,
|
||||
/// <summary>회전 가능 지점</summary>
|
||||
Rotation,
|
||||
/// <summary>도킹 스테이션</summary>
|
||||
Docking,
|
||||
/// <summary>충전 스테이션</summary>
|
||||
Charging,
|
||||
/// <summary>라벨 (UI 요소)</summary>
|
||||
Label,
|
||||
/// <summary>이미지 (UI 요소)</summary>
|
||||
Image
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 도킹 방향 열거형
|
||||
/// </summary>
|
||||
public enum DockingDirection
|
||||
{
|
||||
/// <summary>도킹 방향 상관없음 (일반 경로 노드)</summary>
|
||||
DontCare,
|
||||
/// <summary>전진 도킹 (충전기)</summary>
|
||||
Forward,
|
||||
/// <summary>후진 도킹 (로더, 클리너, 오프로더, 버퍼)</summary>
|
||||
Backward
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AGV 이동 방향 열거형
|
||||
/// </summary>
|
||||
public enum AgvDirection
|
||||
{
|
||||
/// <summary>전진 (모니터 방향)</summary>
|
||||
Forward,
|
||||
/// <summary>후진 (리프트 방향)</summary>
|
||||
Backward,
|
||||
/// <summary>좌회전</summary>
|
||||
Left,
|
||||
/// <summary>우회전</summary>
|
||||
Right,
|
||||
/// <summary>정지</summary>
|
||||
Stop
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 장비 타입 열거형
|
||||
/// </summary>
|
||||
public enum StationType
|
||||
{
|
||||
/// <summary>로더</summary>
|
||||
Loader,
|
||||
/// <summary>클리너</summary>
|
||||
Cleaner,
|
||||
/// <summary>오프로더</summary>
|
||||
Offloader,
|
||||
/// <summary>버퍼</summary>
|
||||
Buffer,
|
||||
/// <summary>충전기</summary>
|
||||
Charger
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 경로 찾기 결과 상태
|
||||
/// </summary>
|
||||
public enum PathFindingStatus
|
||||
{
|
||||
/// <summary>성공</summary>
|
||||
Success,
|
||||
/// <summary>경로를 찾을 수 없음</summary>
|
||||
NoPathFound,
|
||||
/// <summary>시작 노드가 유효하지 않음</summary>
|
||||
InvalidStartNode,
|
||||
/// <summary>목표 노드가 유효하지 않음</summary>
|
||||
InvalidTargetNode,
|
||||
/// <summary>맵 데이터가 없음</summary>
|
||||
NoMapData,
|
||||
/// <summary>계산 오류</summary>
|
||||
CalculationError
|
||||
}
|
||||
}
|
||||
360
Cs_HMI/PathLogic/Models/MapData.cs
Normal file
360
Cs_HMI/PathLogic/Models/MapData.cs
Normal file
@@ -0,0 +1,360 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PathLogic.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 맵 데이터를 관리하는 클래스
|
||||
/// 기존 AGV 맵 파일 형식과 호환
|
||||
/// </summary>
|
||||
public class MapData
|
||||
{
|
||||
/// <summary>
|
||||
/// 맵의 모든 노드 목록
|
||||
/// </summary>
|
||||
public List<MapNode> Nodes { get; set; } = new List<MapNode>();
|
||||
|
||||
/// <summary>
|
||||
/// 맵 생성 일자
|
||||
/// </summary>
|
||||
public DateTime CreatedDate { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 맵 버전
|
||||
/// </summary>
|
||||
public string Version { get; set; } = "1.0";
|
||||
|
||||
/// <summary>
|
||||
/// 기본 생성자
|
||||
/// </summary>
|
||||
public MapData()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 노드 ID로 노드 찾기
|
||||
/// </summary>
|
||||
/// <param name="nodeId">노드 ID</param>
|
||||
/// <returns>해당 노드, 없으면 null</returns>
|
||||
public MapNode GetNodeById(string nodeId)
|
||||
{
|
||||
return Nodes.FirstOrDefault(n => n.NodeId == nodeId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RFID ID로 노드 찾기
|
||||
/// </summary>
|
||||
/// <param name="rfidId">RFID ID</param>
|
||||
/// <returns>해당 노드, 없으면 null</returns>
|
||||
public MapNode GetNodeByRfidId(string rfidId)
|
||||
{
|
||||
return Nodes.FirstOrDefault(n => n.RfidId == rfidId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 네비게이션 가능한 노드만 반환
|
||||
/// </summary>
|
||||
/// <returns>네비게이션 가능한 노드 목록</returns>
|
||||
public List<MapNode> GetNavigationNodes()
|
||||
{
|
||||
return Nodes.Where(n => n.IsNavigationNode()).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 특정 타입의 노드들 반환
|
||||
/// </summary>
|
||||
/// <param name="nodeType">노드 타입</param>
|
||||
/// <returns>해당 타입의 노드 목록</returns>
|
||||
public List<MapNode> GetNodesByType(NodeType nodeType)
|
||||
{
|
||||
return Nodes.Where(n => n.Type == nodeType).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 도킹 스테이션 노드들 반환
|
||||
/// </summary>
|
||||
/// <returns>도킹 스테이션 노드 목록</returns>
|
||||
public List<MapNode> GetDockingStations()
|
||||
{
|
||||
return Nodes.Where(n => n.Type == NodeType.Docking || n.Type == NodeType.Charging).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 충전 스테이션 노드들 반환
|
||||
/// </summary>
|
||||
/// <returns>충전 스테이션 노드 목록</returns>
|
||||
public List<MapNode> GetChargingStations()
|
||||
{
|
||||
return Nodes.Where(n => n.Type == NodeType.Charging).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 회전 가능한 노드들 반환
|
||||
/// </summary>
|
||||
/// <returns>회전 가능한 노드 목록</returns>
|
||||
public List<MapNode> GetRotationNodes()
|
||||
{
|
||||
return Nodes.Where(n => n.CanPerformRotation()).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 노드 추가
|
||||
/// </summary>
|
||||
/// <param name="node">추가할 노드</param>
|
||||
/// <returns>추가 성공 여부</returns>
|
||||
public bool AddNode(MapNode node)
|
||||
{
|
||||
if (node == null || GetNodeById(node.NodeId) != null)
|
||||
return false;
|
||||
|
||||
Nodes.Add(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 노드 제거
|
||||
/// </summary>
|
||||
/// <param name="nodeId">제거할 노드 ID</param>
|
||||
/// <returns>제거 성공 여부</returns>
|
||||
public bool RemoveNode(string nodeId)
|
||||
{
|
||||
var node = GetNodeById(nodeId);
|
||||
if (node == null) return false;
|
||||
|
||||
// 다른 노드들의 연결에서도 제거
|
||||
foreach (var otherNode in Nodes)
|
||||
{
|
||||
otherNode.ConnectedNodes.Remove(nodeId);
|
||||
}
|
||||
|
||||
return Nodes.Remove(node);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 두 노드 간 연결 추가
|
||||
/// </summary>
|
||||
/// <param name="fromNodeId">시작 노드 ID</param>
|
||||
/// <param name="toNodeId">도착 노드 ID</param>
|
||||
/// <param name="bidirectional">양방향 연결 여부</param>
|
||||
/// <returns>연결 성공 여부</returns>
|
||||
public bool AddConnection(string fromNodeId, string toNodeId, bool bidirectional = true)
|
||||
{
|
||||
var fromNode = GetNodeById(fromNodeId);
|
||||
var toNode = GetNodeById(toNodeId);
|
||||
|
||||
if (fromNode == null || toNode == null) return false;
|
||||
|
||||
// 단방향 연결
|
||||
if (!fromNode.ConnectedNodes.Contains(toNodeId))
|
||||
{
|
||||
fromNode.ConnectedNodes.Add(toNodeId);
|
||||
fromNode.ModifiedDate = DateTime.Now;
|
||||
}
|
||||
|
||||
// 양방향 연결
|
||||
if (bidirectional && !toNode.ConnectedNodes.Contains(fromNodeId))
|
||||
{
|
||||
toNode.ConnectedNodes.Add(fromNodeId);
|
||||
toNode.ModifiedDate = DateTime.Now;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 두 노드 간 연결 제거
|
||||
/// </summary>
|
||||
/// <param name="fromNodeId">시작 노드 ID</param>
|
||||
/// <param name="toNodeId">도착 노드 ID</param>
|
||||
/// <param name="bidirectional">양방향 제거 여부</param>
|
||||
/// <returns>제거 성공 여부</returns>
|
||||
public bool RemoveConnection(string fromNodeId, string toNodeId, bool bidirectional = true)
|
||||
{
|
||||
var fromNode = GetNodeById(fromNodeId);
|
||||
var toNode = GetNodeById(toNodeId);
|
||||
|
||||
if (fromNode == null || toNode == null) return false;
|
||||
|
||||
bool removed = false;
|
||||
|
||||
// 단방향 제거
|
||||
if (fromNode.ConnectedNodes.Remove(toNodeId))
|
||||
{
|
||||
fromNode.ModifiedDate = DateTime.Now;
|
||||
removed = true;
|
||||
}
|
||||
|
||||
// 양방향 제거
|
||||
if (bidirectional && toNode.ConnectedNodes.Remove(fromNodeId))
|
||||
{
|
||||
toNode.ModifiedDate = DateTime.Now;
|
||||
removed = true;
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 두 노드가 연결되어 있는지 확인
|
||||
/// </summary>
|
||||
/// <param name="fromNodeId">시작 노드 ID</param>
|
||||
/// <param name="toNodeId">도착 노드 ID</param>
|
||||
/// <returns>연결 여부</returns>
|
||||
public bool AreConnected(string fromNodeId, string toNodeId)
|
||||
{
|
||||
var fromNode = GetNodeById(fromNodeId);
|
||||
return fromNode?.IsConnectedTo(toNodeId) ?? false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 특정 노드의 이웃 노드들 반환
|
||||
/// </summary>
|
||||
/// <param name="nodeId">노드 ID</param>
|
||||
/// <returns>이웃 노드 목록</returns>
|
||||
public List<MapNode> GetNeighbors(string nodeId)
|
||||
{
|
||||
var node = GetNodeById(nodeId);
|
||||
if (node == null) return new List<MapNode>();
|
||||
|
||||
var neighbors = new List<MapNode>();
|
||||
foreach (var connectedId in node.ConnectedNodes)
|
||||
{
|
||||
var neighbor = GetNodeById(connectedId);
|
||||
if (neighbor != null && neighbor.IsNavigationNode())
|
||||
{
|
||||
neighbors.Add(neighbor);
|
||||
}
|
||||
}
|
||||
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 맵 데이터 유효성 검증
|
||||
/// </summary>
|
||||
/// <returns>검증 결과 메시지</returns>
|
||||
public List<string> ValidateMap()
|
||||
{
|
||||
var issues = new List<string>();
|
||||
|
||||
// 노드 ID 중복 검사
|
||||
var nodeIds = Nodes.Select(n => n.NodeId).ToList();
|
||||
var duplicateIds = nodeIds.GroupBy(id => id)
|
||||
.Where(g => g.Count() > 1)
|
||||
.Select(g => g.Key);
|
||||
|
||||
foreach (var duplicateId in duplicateIds)
|
||||
{
|
||||
issues.Add($"중복된 노드 ID: {duplicateId}");
|
||||
}
|
||||
|
||||
// RFID ID 중복 검사
|
||||
var rfidIds = Nodes.Where(n => n.HasRfid())
|
||||
.Select(n => n.RfidId)
|
||||
.ToList();
|
||||
var duplicateRfids = rfidIds.GroupBy(id => id)
|
||||
.Where(g => g.Count() > 1)
|
||||
.Select(g => g.Key);
|
||||
|
||||
foreach (var duplicateRfid in duplicateRfids)
|
||||
{
|
||||
issues.Add($"중복된 RFID ID: {duplicateRfid}");
|
||||
}
|
||||
|
||||
// 잘못된 연결 검사
|
||||
foreach (var node in Nodes)
|
||||
{
|
||||
foreach (var connectedId in node.ConnectedNodes)
|
||||
{
|
||||
if (GetNodeById(connectedId) == null)
|
||||
{
|
||||
issues.Add($"노드 {node.NodeId}가 존재하지 않는 노드 {connectedId}에 연결됨");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 고립된 네비게이션 노드 검사
|
||||
var navigationNodes = GetNavigationNodes();
|
||||
foreach (var node in navigationNodes)
|
||||
{
|
||||
if (node.ConnectedNodes.Count == 0)
|
||||
{
|
||||
issues.Add($"고립된 노드: {node.NodeId}");
|
||||
}
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 맵 통계 정보 반환
|
||||
/// </summary>
|
||||
/// <returns>맵 통계</returns>
|
||||
public MapStatistics GetStatistics()
|
||||
{
|
||||
var stats = new MapStatistics();
|
||||
var navigationNodes = GetNavigationNodes();
|
||||
|
||||
stats.TotalNodes = Nodes.Count;
|
||||
stats.NavigationNodes = navigationNodes.Count;
|
||||
stats.DockingStations = GetNodesByType(NodeType.Docking).Count;
|
||||
stats.ChargingStations = GetNodesByType(NodeType.Charging).Count;
|
||||
stats.RotationNodes = GetRotationNodes().Count;
|
||||
stats.LabelNodes = GetNodesByType(NodeType.Label).Count;
|
||||
stats.ImageNodes = GetNodesByType(NodeType.Image).Count;
|
||||
|
||||
// 연결 수 계산
|
||||
stats.TotalConnections = navigationNodes.Sum(n => n.ConnectedNodes.Count) / 2; // 양방향이므로 2로 나눔
|
||||
|
||||
// RFID 할당된 노드 수
|
||||
stats.NodesWithRfid = Nodes.Count(n => n.HasRfid());
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 맵 데이터 복사
|
||||
/// </summary>
|
||||
/// <returns>복사된 맵 데이터</returns>
|
||||
public MapData Clone()
|
||||
{
|
||||
var clonedMap = new MapData
|
||||
{
|
||||
CreatedDate = CreatedDate,
|
||||
Version = Version
|
||||
};
|
||||
|
||||
foreach (var node in Nodes)
|
||||
{
|
||||
clonedMap.Nodes.Add(node.Clone());
|
||||
}
|
||||
|
||||
return clonedMap;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 맵 통계 정보 클래스
|
||||
/// </summary>
|
||||
public class MapStatistics
|
||||
{
|
||||
public int TotalNodes { get; set; }
|
||||
public int NavigationNodes { get; set; }
|
||||
public int DockingStations { get; set; }
|
||||
public int ChargingStations { get; set; }
|
||||
public int RotationNodes { get; set; }
|
||||
public int LabelNodes { get; set; }
|
||||
public int ImageNodes { get; set; }
|
||||
public int TotalConnections { get; set; }
|
||||
public int NodesWithRfid { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"총 노드: {TotalNodes}, 네비게이션: {NavigationNodes}, " +
|
||||
$"도킹: {DockingStations}, 충전: {ChargingStations}, " +
|
||||
$"회전: {RotationNodes}, 연결: {TotalConnections}, " +
|
||||
$"RFID 할당: {NodesWithRfid}";
|
||||
}
|
||||
}
|
||||
}
|
||||
303
Cs_HMI/PathLogic/Models/MapNode.cs
Normal file
303
Cs_HMI/PathLogic/Models/MapNode.cs
Normal file
@@ -0,0 +1,303 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
|
||||
namespace PathLogic.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 맵 노드 정보를 관리하는 클래스
|
||||
/// 기존 AGVNavigationCore의 MapNode와 호환되도록 설계
|
||||
/// </summary>
|
||||
public class MapNode
|
||||
{
|
||||
/// <summary>
|
||||
/// 논리적 노드 ID (맵 에디터에서 관리하는 고유 ID)
|
||||
/// </summary>
|
||||
public string NodeId { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 노드 표시 이름
|
||||
/// </summary>
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 맵 상의 위치 좌표 (픽셀 단위)
|
||||
/// </summary>
|
||||
public Point Position { get; set; } = Point.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 노드 타입
|
||||
/// </summary>
|
||||
public NodeType Type { get; set; } = NodeType.Normal;
|
||||
|
||||
/// <summary>
|
||||
/// 도킹 방향
|
||||
/// </summary>
|
||||
public DockingDirection DockDirection { get; set; } = DockingDirection.DontCare;
|
||||
|
||||
/// <summary>
|
||||
/// 연결된 노드 ID 목록
|
||||
/// </summary>
|
||||
public List<string> ConnectedNodes { get; set; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 회전 가능 여부
|
||||
/// </summary>
|
||||
public bool CanRotate { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 장비 ID
|
||||
/// </summary>
|
||||
public string StationId { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 장비 타입
|
||||
/// </summary>
|
||||
public StationType? StationType { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// 노드 생성 일자
|
||||
/// </summary>
|
||||
public DateTime CreatedDate { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 노드 수정 일자
|
||||
/// </summary>
|
||||
public DateTime ModifiedDate { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 노드 활성화 여부
|
||||
/// </summary>
|
||||
public bool IsActive { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 노드 색상 (맵 에디터 표시용)
|
||||
/// </summary>
|
||||
public Color DisplayColor { get; set; } = Color.Blue;
|
||||
|
||||
/// <summary>
|
||||
/// RFID 태그 ID
|
||||
/// </summary>
|
||||
public string RfidId { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// RFID 상태
|
||||
/// </summary>
|
||||
public string RfidStatus { get; set; } = "정상";
|
||||
|
||||
/// <summary>
|
||||
/// RFID 설치 위치 설명
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// 기본 생성자
|
||||
/// </summary>
|
||||
public MapNode()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 매개변수 생성자
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 노드 타입에 따른 기본 색상 설정
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 경로 찾기에 사용 가능한 노드인지 확인
|
||||
/// </summary>
|
||||
public bool IsNavigationNode()
|
||||
{
|
||||
return Type != NodeType.Label && Type != NodeType.Image && IsActive;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RFID가 할당되어 있는지 확인
|
||||
/// </summary>
|
||||
public bool HasRfid()
|
||||
{
|
||||
return !string.IsNullOrEmpty(RfidId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 도킹이 필요한 노드인지 확인
|
||||
/// </summary>
|
||||
public bool RequiresDocking()
|
||||
{
|
||||
return Type == NodeType.Docking || Type == NodeType.Charging;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 회전이 가능한 노드인지 확인
|
||||
/// </summary>
|
||||
public bool CanPerformRotation()
|
||||
{
|
||||
return CanRotate || Type == NodeType.Rotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 노드의 필요한 도킹 방향 반환
|
||||
/// </summary>
|
||||
public AgvDirection GetRequiredDirection()
|
||||
{
|
||||
switch (DockDirection)
|
||||
{
|
||||
case DockingDirection.Forward:
|
||||
return AgvDirection.Forward;
|
||||
case DockingDirection.Backward:
|
||||
return AgvDirection.Backward;
|
||||
default:
|
||||
return AgvDirection.Forward; // 기본값
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 다른 노드와 연결되어 있는지 확인
|
||||
/// </summary>
|
||||
public bool IsConnectedTo(string nodeId)
|
||||
{
|
||||
return ConnectedNodes.Contains(nodeId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 두 노드 간의 유클리드 거리 계산
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 두 노드 간의 맨하탄 거리 계산
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 노드 정보를 문자열로 반환
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
string rfidInfo = HasRfid() ? $"[{RfidId}]" : "";
|
||||
return $"{NodeId}{rfidInfo}: {Name} ({Type}) at ({Position.X}, {Position.Y})";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 표시용 텍스트 반환
|
||||
/// </summary>
|
||||
public string DisplayText
|
||||
{
|
||||
get
|
||||
{
|
||||
var displayText = NodeId;
|
||||
|
||||
if (!string.IsNullOrEmpty(Name))
|
||||
{
|
||||
displayText += $" - {Name}";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(RfidId))
|
||||
{
|
||||
displayText += $" - [{RfidId}]";
|
||||
}
|
||||
|
||||
return displayText;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 노드 복사
|
||||
/// </summary>
|
||||
public MapNode Clone()
|
||||
{
|
||||
return new MapNode
|
||||
{
|
||||
NodeId = NodeId,
|
||||
Name = Name,
|
||||
Position = Position,
|
||||
Type = Type,
|
||||
DockDirection = DockDirection,
|
||||
ConnectedNodes = new List<string>(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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user