This commit is contained in:
chi
2025-05-26 17:19:36 +09:00
parent 8d0f0f8c8f
commit d6e7c118fb
40 changed files with 1550 additions and 3133 deletions

View File

@@ -5,6 +5,9 @@ using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using AGVControl.Models;
@@ -18,7 +21,7 @@ namespace AGVControl
private List<MapText> mapTexts;
private List<CustomLine> customLines;
private List<RFIDLine> rfidLines;
private AGV agv;
public AGV agv;
private float zoom = 1.0f;
private PointF offset = PointF.Empty;
private Point lastMousePosition;
@@ -200,12 +203,12 @@ namespace AGVControl
);
}
public RFIDPoint FindRFIDPoint(string rfidValue)
public RFIDPoint FindRFIDPoint(uint rfidValue)
{
return rfidPoints.FirstOrDefault(r => r.RFIDValue.ToUpper() == rfidValue.ToUpper());
return rfidPoints.FirstOrDefault(r => r.RFIDValue == rfidValue);
}
public bool AGVMoveToRFID(string rfidValue)
public bool SetCurrentPosition(uint rfidValue)
{
var rfidPoint = FindRFIDPoint(rfidValue);
if (rfidPoint != null)
@@ -538,7 +541,7 @@ namespace AGVControl
return neighbors.Distinct().ToList();
}
public void SetPath(List<string> rfids)
public void SetPath(List<uint> rfids)
{
if (rfids == null || rfids.Count == 0)
return;
@@ -563,6 +566,62 @@ namespace AGVControl
public string RFIDStartNo { get; set; } = string.Empty;
public int RFIDLastNumber = 0;
string filename = string.Empty;
public struct PathResult
{
public bool Success { get; set; }
public string Message { get; set; }
public List<Point> Path { get; set; }
}
public PathResult CalculatePath(uint tagStrt, uint tagEnd)
{
var retval = new PathResult
{
Message = string.Empty,
Success = false,
Path = new List<Point>(),
};
var sp = tagStrt; //만약시작위치가 없다면 항상 충전기 기준으로 한다
var ep = tagEnd;
var startPoint = FindRFIDPoint(sp);
var endPoint = FindRFIDPoint(ep);
if (startPoint == null || endPoint == null)
{
retval.Message = "유효한 RFID 값을 입력해주세요.";
return retval;
}
var path = CalculatePath(startPoint.Location, endPoint.Location);
if (path != null && path.Count > 0)
{
DrawPath(path);
// 경로 상의 모든 RFID 값을 가져옴
var rfidPath = new List<uint>();
foreach (var point in path)
{
var rfid = GetRFIDPoints()
.FirstOrDefault(r => r.Location == point);
if (rfid != null)
{
rfidPath.Add(rfid.RFIDValue);
}
}
retval.Success = true;
}
else
{
retval.Message = "경로를 찾을 수 없습니다";
}
return retval;
}
private void MapControl_MouseClick(object sender, MouseEventArgs e)
{
var mapPoint = ScreenToMap(e.Location);
@@ -596,45 +655,34 @@ namespace AGVControl
var startRFID = input1.Item2;
var endRFID = input2.Item2;
var startPoint = FindRFIDPoint(startRFID);
var endPoint = FindRFIDPoint(endRFID);
if (startPoint == null || endPoint == null)
var valid1 = uint.TryParse(input1.Item2, out uint vstart);
var valid2 = uint.TryParse(input2.Item2, out uint vend);
if (valid1 == false || valid2 == false)
{
MessageBox.Show("유효한 RFID 값을 입력해주세요.", "경로 계산", MessageBoxButtons.OK, MessageBoxIcon.Warning);
MessageBox.Show("RFID값은 정수로 입력세요", "경로 계산", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
var path = CalculatePath(startPoint.Location, endPoint.Location);
if (path != null && path.Count > 0)
var rlt = CalculatePath(vstart, vend);
if (rlt.Success == false)
{
DrawPath(path);
// 경로 상의 모든 RFID 값을 가져옴
var rfidPath = new List<string>();
foreach (var point in path)
{
var rfid = GetRFIDPoints()
.FirstOrDefault(r => r.Location == point);
if (rfid != null)
{
rfidPath.Add(rfid.RFIDValue);
}
}
MessageBox.Show($"경로가 계산되었습니다.\nRFID 순서: {string.Join(" -> ", rfidPath)}",
"경로 계산", MessageBoxButtons.OK, MessageBoxIcon.Information);
MessageBox.Show(rlt.Message, "경로 계산", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
else
{
MessageBox.Show("경로를 찾을 수 없습니다.", "경로 계산", MessageBoxButtons.OK, MessageBoxIcon.Warning);
MessageBox.Show($"경로가 계산되었습니다.\nRFID 순서: {string.Join(" -> ", rlt.Path)}",
"경로 계산", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
break;
case "pos":
var tag = AR.UTIL.InputBox("input rfid tag value");
if (tag.Item1 && tag.Item2 != "")
if (tag.Item1 && tag.Item2 != "" && uint.TryParse(tag.Item2, out uint val) == true)
{
var targetRFID = AGVMoveToRFID(tag.Item2);
var targetRFID = SetCurrentPosition(val);
}
break;
case "save":
@@ -693,27 +741,30 @@ namespace AGVControl
case eMouseMode.addrfidpoint:
if (string.IsNullOrEmpty(this.RFIDStartNo) == false)
{
AddRFIDPoint(mapPoint, RFIDStartNo);
// 숫자로 끝나는 RFID 값인 경우 자동 증가
if (Regex.IsMatch(RFIDStartNo, @"^[A-Za-z]+\d+$"))
if (uint.TryParse(this.RFIDStartNo, out uint rfidvalue))
{
// 마지막 숫자 부분 추출
Match match = Regex.Match(RFIDStartNo, @"\d+$");
if (match.Success)
{
int currentNumber = int.Parse(match.Value);
if (currentNumber > this.RFIDLastNumber)
{
RFIDLastNumber = currentNumber;
}
RFIDLastNumber++;
AddRFIDPoint(mapPoint, rfidvalue);
// 숫자 부분을 새로운 번호로 교체
RFIDStartNo = RFIDStartNo.Substring(0, match.Index) + RFIDLastNumber.ToString("D4");
// 숫자로 끝나는 RFID 값인 경우 자동 증가
if (Regex.IsMatch(RFIDStartNo, @"^[A-Za-z]+\d+$"))
{
// 마지막 숫자 부분 추출
Match match = Regex.Match(RFIDStartNo, @"\d+$");
if (match.Success)
{
int currentNumber = int.Parse(match.Value);
if (currentNumber > this.RFIDLastNumber)
{
RFIDLastNumber = currentNumber;
}
RFIDLastNumber++;
// 숫자 부분을 새로운 번호로 교체
RFIDStartNo = RFIDStartNo.Substring(0, match.Index) + RFIDLastNumber.ToString("D4");
}
}
}
}
break;
case eMouseMode.addtext:
@@ -815,7 +866,7 @@ namespace AGVControl
nearbyPoints.Sort((a, b) => a.ProjectionRatio.CompareTo(b.ProjectionRatio));
// 이전 RFID 값과 위치를 저장
string prevRFID = line.StartRFID;
uint prevRFID = line.StartRFID;
Point prevPoint = line.StartPoint;
// 정렬된 포인트들을 순차적으로 연결
@@ -1155,7 +1206,7 @@ namespace AGVControl
foreach (var rfid in rfidPoints)
{
var MarkerSize = 5;
g.FillEllipse(Brushes.Green, rfid.Location.X - (MarkerSize/2f), rfid.Location.Y -(MarkerSize/2f), MarkerSize, MarkerSize);
g.FillEllipse(Brushes.Green, rfid.Location.X - (MarkerSize / 2f), rfid.Location.Y - (MarkerSize / 2f), MarkerSize, MarkerSize);
//g.DrawString(rfid.RFIDValue, Font, Brushes.WhiteSmoke, rfid.Location.X + 5, rfid.Location.Y - 5);
}
@@ -1163,15 +1214,13 @@ namespace AGVControl
foreach (var rfid in rfidPoints)
{
//g.FillEllipse(Brushes.Green, rfid.Location.X - 3, rfid.Location.Y - 3, 6, 6);
var fsize = g.MeasureString(rfid.RFIDValue, Font);
g.DrawString(rfid.RFIDValue, Font, Brushes.WhiteSmoke,
var tagstr = $"{rfid.RFIDValue}";
var fsize = g.MeasureString(tagstr, Font);
g.DrawString(tagstr, Font, Brushes.WhiteSmoke,
(rfid.Location.X - fsize.Width / 2f),
(rfid.Location.Y + 2));
}
//var rfidpts = rfidPoints.Select(t => t.Location).ToArray();
//g.DrawLines(new Pen(Color.FromArgb(100, Color.Magenta), 10), rfidpts);
}
private void DrawAGV(Graphics g)
@@ -1252,7 +1301,7 @@ namespace AGVControl
{
using (Pen linePen = new Pen(Color.FromArgb(50, Color.Wheat), 2))
{
if (!line.IsBidirectional)
if (line.IsBidirectional)
{
// 단방향 화살표 그리기
var arrowSize = 10;
@@ -1345,7 +1394,7 @@ namespace AGVControl
this.Invalidate();
}
public void AddRFIDLine(Point startPoint, Point endPoint, string startRFID, string endRFID, bool isBidirectional = true)
public void AddRFIDLine(Point startPoint, Point endPoint, uint startRFID, uint endRFID, bool isBidirectional = false)
{
// 시작점과 끝점 사이의 모든 RFID 포인트 찾기
var allPoints = new List<(RFIDPoint Point, float Distance)>();
@@ -1447,7 +1496,7 @@ namespace AGVControl
this.Invalidate();
}
public void AddRFIDPoint(Point mapLocation, string rfidValue)
public void AddRFIDPoint(Point mapLocation, uint rfidValue)
{
// 이미 맵 좌표로 변환된 위치를 사용
var rfidPoint = new RFIDPoint
@@ -1490,19 +1539,12 @@ namespace AGVControl
lines.Add($"{point.Location.X},{point.Location.Y},{point.RFIDValue}");
}
// 자석선 저장
lines.Add("[MAGNET_LINES]");
foreach (var line in magnetLines)
// RFID 라인 저장
lines.Add("[RFID_LINES]");
foreach (var line in rfidLines)
{
var branchInfo = "";
foreach (var branch in line.BranchPoints)
{
if (line.BranchDirections.ContainsKey(branch))
{
branchInfo += $"|{branch.X},{branch.Y},{(int)line.BranchDirections[branch]}";
}
}
lines.Add($"{line.StartPoint.X},{line.StartPoint.Y},{line.EndPoint.X},{line.EndPoint.Y}{branchInfo}");
lines.Add($"{line.StartPoint.X},{line.StartPoint.Y},{line.EndPoint.X},{line.EndPoint.Y}," +
$"{line.StartRFID},{line.EndRFID},{line.IsBidirectional},{line.Distance}");
}
// 텍스트 저장
@@ -1519,24 +1561,19 @@ namespace AGVControl
lines.Add($"{line.StartPoint.X},{line.StartPoint.Y},{line.EndPoint.X},{line.EndPoint.Y},{line.LineColor.ToArgb()},{line.LineWidth}");
}
// RFID 라인 저장
lines.Add("[RFID_LINES]");
foreach (var line in rfidLines)
{
lines.Add($"{line.StartPoint.X},{line.StartPoint.Y},{line.EndPoint.X},{line.EndPoint.Y}," +
$"{line.StartRFID},{line.EndRFID},{line.IsBidirectional},{line.Distance}");
}
File.WriteAllLines(filename, lines);
}
public void LoadFromFile(string filename)
public string LoadFromFile(string filename)
{
ClearMap();
var lines = File.ReadAllLines(filename);
var section = "";
var sb = new System.Text.StringBuilder();
foreach (var line in lines)
{
if (line.StartsWith("[") && line.EndsWith("]"))
@@ -1551,9 +1588,28 @@ namespace AGVControl
var rfidParts = line.Split(',');
if (rfidParts.Length >= 3)
{
AddRFIDPoint(
new Point(int.Parse(rfidParts[0]), int.Parse(rfidParts[1])),
rfidParts[2]
var validX = int.TryParse(rfidParts[0], out int valX);
var validY = int.TryParse(rfidParts[1], out int valY);
var validN = uint.TryParse(rfidParts[2], out uint valRfid);
if (validX && validY && validN)
{
AddRFIDPoint(new Point(valX, valY), valRfid);
}
else sb.AppendLine($"[{section}] {line}");
}
break;
case "[RFID_LINES]":
var rfidLineParts = line.Split(',');
if (rfidLineParts.Length >= 8)
{
AddRFIDLine(
new Point(int.Parse(rfidLineParts[0]), int.Parse(rfidLineParts[1])),
new Point(int.Parse(rfidLineParts[2]), int.Parse(rfidLineParts[3])),
uint.Parse(rfidLineParts[4]),
uint.Parse(rfidLineParts[5]),
(rfidLineParts[6].ToLower() == "true")
);
}
break;
@@ -1618,23 +1674,13 @@ namespace AGVControl
}
break;
case "[RFID_LINES]":
var rfidLineParts = line.Split(',');
if (rfidLineParts.Length >= 8)
{
AddRFIDLine(
new Point(int.Parse(rfidLineParts[0]), int.Parse(rfidLineParts[1])),
new Point(int.Parse(rfidLineParts[2]), int.Parse(rfidLineParts[3])),
rfidLineParts[4],
rfidLineParts[5],
bool.Parse(rfidLineParts[6])
);
}
break;
}
}
this.Invalidate();
return sb.ToString();
}
private void DeleteNearbyRFIDLine(Point clickPoint)