..
This commit is contained in:
24
Cs_HMI/SubProject/AGVControl/AGVControl.sln
Normal file
24
Cs_HMI/SubProject/AGVControl/AGVControl.sln
Normal file
@@ -0,0 +1,24 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.5.2.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "agvControl", "agvControl.csproj", "{EB23DC0D-9A07-407C-762D-DF1CC8B3D822}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{EB23DC0D-9A07-407C-762D-DF1CC8B3D822}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EB23DC0D-9A07-407C-762D-DF1CC8B3D822}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EB23DC0D-9A07-407C-762D-DF1CC8B3D822}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EB23DC0D-9A07-407C-762D-DF1CC8B3D822}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {586342A4-FEA6-4584-82F4-39BA06630ABB}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -24,6 +24,7 @@ namespace AGVControl
|
||||
public bool IsBidirectional { get; set; }
|
||||
public float Distance { get; set; }
|
||||
public List<uint> IntermediateRFIDs { get; set; } = new List<uint>();
|
||||
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
@@ -81,7 +82,7 @@ namespace AGVControl
|
||||
private const int SELECTION_DISTANCE = 15; // 선택 가능 거리를 늘림
|
||||
private bool isDraggingText = false;
|
||||
private Point dragOffset;
|
||||
private List<Point> currentPath;
|
||||
// private List<Point> currentPath;
|
||||
|
||||
|
||||
public MapText SelectedText => selectedText;
|
||||
@@ -210,6 +211,7 @@ namespace AGVControl
|
||||
|
||||
public RFIDPoint FindRFIDPoint(uint rfidValue)
|
||||
{
|
||||
if (rfidPoints == null || rfidPoints.Any() == false) return null;
|
||||
return rfidPoints.FirstOrDefault(r => r.RFIDValue == rfidValue);
|
||||
}
|
||||
|
||||
@@ -220,6 +222,57 @@ namespace AGVControl
|
||||
{
|
||||
agv.CurrentPosition = rfidPoint.Location;
|
||||
agv.CurrentRFID = rfidValue;
|
||||
|
||||
// 목적지가 설정되어 있고 경로가 있는 경우 검증
|
||||
if (agv.TargetPosition != Point.Empty && agv.CurrentPath.Count > 0)
|
||||
{
|
||||
// 현재 위치가 경로에 있는지 확인
|
||||
bool isOnPath = agv.CurrentPath.Contains(agv.CurrentPosition);
|
||||
|
||||
if (!isOnPath)
|
||||
{
|
||||
// 경로를 벗어났으므로 새로운 경로 계산
|
||||
var pathResult = CalculatePath(agv.CurrentRFID, agv.TargetRFID);
|
||||
if (pathResult.Success)
|
||||
{
|
||||
SetCurrentPath(pathResult.Path);
|
||||
}
|
||||
}
|
||||
|
||||
// AGV의 방향 결정
|
||||
if (agv.CurrentPath.Count > 0)
|
||||
{
|
||||
// 다음 목적지 찾기
|
||||
var nextPoint = agv.CurrentPath[0];
|
||||
|
||||
// 회전 가능 여부를 고려하여 방향 결정
|
||||
agv.TargetDirection = DetermineDirection(agv.CurrentPosition, nextPoint, agv.TargetPosition);
|
||||
}
|
||||
}
|
||||
|
||||
// 목적지 RFID에 도착했고, 해당 RFID에 고정방향이 있으면 TargetDirection을 강제 설정
|
||||
if (agv.TargetRFID == rfidValue)
|
||||
{
|
||||
var destRFID = FindRFIDPoint(rfidValue);
|
||||
if (destRFID != null && destRFID.FixedDirection.HasValue)
|
||||
{
|
||||
agv.TargetDirection = destRFID.FixedDirection.Value;
|
||||
}
|
||||
}
|
||||
|
||||
this.Invalidate();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool SetTargetPosition(uint rfidValue)
|
||||
{
|
||||
var rfidPoint = FindRFIDPoint(rfidValue);
|
||||
if (rfidPoint != null)
|
||||
{
|
||||
agv.TargetPosition = rfidPoint.Location;
|
||||
agv.TargetRFID = rfidValue;
|
||||
this.Invalidate();
|
||||
return true;
|
||||
}
|
||||
@@ -566,7 +619,7 @@ namespace AGVControl
|
||||
|
||||
if (path.Count > 0)
|
||||
{
|
||||
DrawPath(path);
|
||||
SetCurrentPath(path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,22 +658,22 @@ namespace AGVControl
|
||||
return retval;
|
||||
}
|
||||
|
||||
var path = CalculatePath(startPoint.Location, endPoint.Location);
|
||||
if (path != null && path.Count > 0)
|
||||
retval.Path = CalculatePath(startPoint.Location, endPoint.Location);
|
||||
if (retval.Path != null && retval.Path.Any())
|
||||
{
|
||||
DrawPath(path);
|
||||
//SetCurrentPath(retval.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);
|
||||
}
|
||||
}
|
||||
//// 경로 상의 모든 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
|
||||
@@ -683,8 +736,13 @@ namespace AGVControl
|
||||
}
|
||||
else
|
||||
{
|
||||
SetCurrentPath(rlt.Path); //현재 경로로 설정함
|
||||
MessageBox.Show($"경로가 계산되었습니다.\nRFID 순서: {string.Join(" -> ", rlt.Path)}",
|
||||
"경로 계산", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
if (SetTargetPosition(vend) == false)
|
||||
{
|
||||
MessageBox.Show("목적지 설정 실패");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "pos":
|
||||
@@ -700,12 +758,12 @@ namespace AGVControl
|
||||
od.Filter = "path data|*.route";
|
||||
od.FilterIndex = 0;
|
||||
od.RestoreDirectory = true;
|
||||
if(filename.isEmpty()==false)
|
||||
if (filename.isEmpty() == false)
|
||||
{
|
||||
od.FileName = System.IO.Path.GetFileName(filename);
|
||||
od.InitialDirectory = System.IO.Path.GetDirectoryName(filename);
|
||||
}
|
||||
|
||||
|
||||
if (od.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
filename = od.FileName;
|
||||
@@ -734,7 +792,7 @@ namespace AGVControl
|
||||
|
||||
if (od.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
|
||||
|
||||
this.LoadFromFile(filename, out string errmsg);
|
||||
if (errmsg.isEmpty() == false) UTIL.MsgE(errmsg);
|
||||
this.Invalidate();
|
||||
@@ -935,20 +993,21 @@ namespace AGVControl
|
||||
|
||||
if (e.Button == MouseButtons.Left)
|
||||
{
|
||||
// 화면 좌표를 맵 좌표로 변환
|
||||
var mapPoint = ScreenToMap(e.Location);
|
||||
|
||||
//RFID 포인트 찾기
|
||||
var selected_rfid = rfidPoints.Where(t => t.Bounds.Expand(SELECTION_DISTANCE, SELECTION_DISTANCE).Contains(mapPoint)).FirstOrDefault();
|
||||
if (selected_rfid != null)
|
||||
{
|
||||
var rlt = AR.UTIL.InputBox("rfid value", selected_rfid.RFIDValue.ToString());
|
||||
if (rlt.Item1 == true)
|
||||
{
|
||||
selected_rfid.RFIDValue = uint.Parse(rlt.Item2);// dialog.InputText;
|
||||
ProcessRFIDConnections();
|
||||
this.Invalidate();
|
||||
}
|
||||
// 고정방향 순환 변경: 없음→전진→후진→없음
|
||||
if (!selected_rfid.FixedDirection.HasValue)
|
||||
selected_rfid.FixedDirection = Direction.Forward;
|
||||
else if (selected_rfid.FixedDirection == Direction.Forward)
|
||||
selected_rfid.FixedDirection = Direction.Backward;
|
||||
else
|
||||
selected_rfid.FixedDirection = null;
|
||||
|
||||
this.Invalidate();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -959,7 +1018,7 @@ namespace AGVControl
|
||||
var rlt = AR.UTIL.InputBox("input", selected_txt.Text);
|
||||
if (rlt.Item1 == true)
|
||||
{
|
||||
selected_txt.Text = rlt.Item2;// dialog.InputText;
|
||||
selected_txt.Text = rlt.Item2;
|
||||
this.Invalidate();
|
||||
}
|
||||
return;
|
||||
@@ -1108,9 +1167,9 @@ namespace AGVControl
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawPath(List<Point> path)
|
||||
public void SetCurrentPath(List<Point> path)
|
||||
{
|
||||
currentPath = path;
|
||||
agv.CurrentPath = path;
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
@@ -1130,6 +1189,7 @@ namespace AGVControl
|
||||
|
||||
DrawPath(e.Graphics);
|
||||
DrawAGV(e.Graphics);
|
||||
DrawTargetFlag(e.Graphics); // 목적지 깃발 그리기 추가
|
||||
|
||||
// 선택된 개체 강조 표시
|
||||
if (selectedRFID != null)
|
||||
@@ -1180,51 +1240,85 @@ namespace AGVControl
|
||||
var MarkerSize = 5;
|
||||
var half = MarkerSize / 2f;
|
||||
rfid.Bounds = new RectangleF(rfid.Location.X - half, rfid.Location.Y - half, MarkerSize, MarkerSize);
|
||||
g.FillEllipse(Brushes.Green, rfid.Bounds);
|
||||
//g.DrawString(rfid.RFIDValue, Font, Brushes.WhiteSmoke, rfid.Location.X + 5, rfid.Location.Y - 5);
|
||||
|
||||
// 회전 가능 여부에 따라 다른 색상 사용
|
||||
using (var brush = new SolidBrush(rfid.IsRotatable ? Color.Yellow : Color.Green))
|
||||
{
|
||||
g.FillEllipse(brush, rfid.Bounds);
|
||||
}
|
||||
// 고정방향이 있으면 테두리 색상 표시
|
||||
if (rfid.FixedDirection.HasValue)
|
||||
{
|
||||
Color borderColor = rfid.FixedDirection.Value == Direction.Forward ? Color.DeepSkyBlue : Color.Gold; using (var pen = new Pen(borderColor, 2))
|
||||
{
|
||||
g.DrawEllipse(pen, rfid.Bounds.Expand(5,5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RFID 포인트 그리기
|
||||
// RFID 값 표시
|
||||
foreach (var rfid in rfidPoints)
|
||||
{
|
||||
//g.FillEllipse(Brushes.Green, rfid.Location.X - 3, rfid.Location.Y - 3, 6, 6);
|
||||
var tagstr = $"{rfid.RFIDValue}";
|
||||
var fsize = g.MeasureString(tagstr, Font);
|
||||
var rect = new RectangleF(rfid.Bounds.X - (fsize.Width / 2f) + 3,
|
||||
rfid.Bounds.Y + 6,
|
||||
fsize.Width,
|
||||
fsize.Height);
|
||||
//g.DrawRectangle(Pens.Red, rect);
|
||||
g.DrawString(tagstr, Font, Brushes.WhiteSmoke, rect, new StringFormat
|
||||
{
|
||||
Alignment = StringAlignment.Center,
|
||||
LineAlignment = StringAlignment.Center,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void DrawAGV(Graphics g)
|
||||
{
|
||||
var agvsize = 30;
|
||||
var halfsize = (int)(agvsize / 2);
|
||||
var rect = new Rectangle(agv.CurrentPosition.X - halfsize,
|
||||
agv.CurrentPosition.Y - halfsize,
|
||||
agvsize, agvsize);
|
||||
|
||||
var recti = new Rectangle(rect.X + 5, rect.Y + 5, rect.Width - 10, rect.Height - 10);
|
||||
// AGV의 현재 위치를 중심으로 하는 원
|
||||
var circleRect = new Rectangle(
|
||||
agv.CurrentPosition.X - halfsize,
|
||||
agv.CurrentPosition.Y - halfsize,
|
||||
agvsize, agvsize);
|
||||
|
||||
using (var sb = new SolidBrush(Color.FromArgb(150, Color.Gold)))
|
||||
g.FillEllipse(sb, rect);
|
||||
// 삼각형 화살표를 위한 포인트 배열
|
||||
Point[] trianglePoints = new Point[3];
|
||||
var arrowSize = halfsize - 5; // 삼각형 크기
|
||||
|
||||
using (var pen = new Pen(Color.Black))
|
||||
g.DrawEllipse(pen, rect);
|
||||
// AGV의 방향에 따라 삼각형 포인트 계산
|
||||
switch (agv.CurrentDirection)
|
||||
{
|
||||
case Direction.Forward:
|
||||
trianglePoints[0] = new Point(agv.CurrentPosition.X, agv.CurrentPosition.Y - arrowSize);
|
||||
trianglePoints[1] = new Point(agv.CurrentPosition.X - arrowSize, agv.CurrentPosition.Y + arrowSize);
|
||||
trianglePoints[2] = new Point(agv.CurrentPosition.X + arrowSize, agv.CurrentPosition.Y + arrowSize);
|
||||
break;
|
||||
case Direction.Backward:
|
||||
trianglePoints[0] = new Point(agv.CurrentPosition.X, agv.CurrentPosition.Y + arrowSize);
|
||||
trianglePoints[1] = new Point(agv.CurrentPosition.X - arrowSize, agv.CurrentPosition.Y - arrowSize);
|
||||
trianglePoints[2] = new Point(agv.CurrentPosition.X + arrowSize, agv.CurrentPosition.Y - arrowSize);
|
||||
break;
|
||||
}
|
||||
|
||||
using (var sb = new SolidBrush(Color.FromArgb(150, Color.White)))
|
||||
g.FillEllipse(sb, recti);
|
||||
|
||||
using (var pen = new Pen(Color.Black))
|
||||
g.DrawEllipse(pen, recti);
|
||||
|
||||
// 원 그리기
|
||||
Color bgcolor = agv.BatteryLevel > 80 ? Color.Lime : ( agv.BatteryLevel > 60 ? Color.Gold : Color.Tomato );
|
||||
using (var circleBrush = new SolidBrush(Color.FromArgb(150, bgcolor)))
|
||||
g.FillEllipse(circleBrush, circleRect);
|
||||
using (var circlePen = new Pen(Color.Black, 2))
|
||||
g.DrawEllipse(circlePen, circleRect);
|
||||
|
||||
// 삼각형 화살표 그리기
|
||||
using (var arrowBrush = new SolidBrush(Color.FromArgb(200, Color.White)))
|
||||
g.FillPolygon(arrowBrush, trianglePoints);
|
||||
using (var arrowPen = new Pen(Color.Black, 2))
|
||||
g.DrawPolygon(arrowPen, trianglePoints);
|
||||
|
||||
//g.DrawImage(Properties.Resources.ico_navi_40, circleRect);
|
||||
}
|
||||
|
||||
private void DrawCustomLines(Graphics g)
|
||||
@@ -1358,7 +1452,7 @@ namespace AGVControl
|
||||
|
||||
private void DrawPath(Graphics g)
|
||||
{
|
||||
if (currentPath == null || currentPath.Count < 2)
|
||||
if (agv.CurrentPath == null || agv.CurrentPath.Count < 2)
|
||||
return;
|
||||
|
||||
Color pathColor = Color.FromArgb(100, Color.Lime);
|
||||
@@ -1367,9 +1461,9 @@ namespace AGVControl
|
||||
using (Pen pathPen = new Pen(pathColor, pathWidth))
|
||||
{
|
||||
pathPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
|
||||
for (int i = 0; i < currentPath.Count - 1; i++)
|
||||
for (int i = 0; i < agv.CurrentPath.Count - 1; i++)
|
||||
{
|
||||
g.DrawLine(pathPen, currentPath[i], currentPath[i + 1]);
|
||||
g.DrawLine(pathPen, agv.CurrentPath[i], agv.CurrentPath[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1728,5 +1822,85 @@ namespace AGVControl
|
||||
g.DrawString(text, font, Brushes.Black, rect, format);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawTargetFlag(Graphics g)
|
||||
{
|
||||
if (agv.TargetPosition == Point.Empty) return;
|
||||
|
||||
// 바닥에 흰색 원 그리기
|
||||
using (var baseBrush = new SolidBrush(Color.Red))
|
||||
using (var basePen = new Pen(Color.Black, 1))
|
||||
{
|
||||
var baseSize = 8;
|
||||
g.FillEllipse(baseBrush,
|
||||
agv.TargetPosition.X - baseSize / 2,
|
||||
agv.TargetPosition.Y - baseSize / 2,
|
||||
baseSize, baseSize);
|
||||
g.DrawEllipse(basePen,
|
||||
agv.TargetPosition.X - baseSize / 2,
|
||||
agv.TargetPosition.Y - baseSize / 2,
|
||||
baseSize, baseSize);
|
||||
}
|
||||
|
||||
// 깃대 그리기 (길이를 2/3로 줄임)
|
||||
using (var polePen = new Pen(Color.Brown, 3))
|
||||
{
|
||||
var poleLength = 27; // 40 * 2/3 ≈ 27
|
||||
g.DrawLine(polePen,
|
||||
agv.TargetPosition.X,
|
||||
agv.TargetPosition.Y,
|
||||
agv.TargetPosition.X,
|
||||
agv.TargetPosition.Y - poleLength);
|
||||
}
|
||||
|
||||
// 깃발 그리기
|
||||
Point[] flagPoints = new Point[3];
|
||||
flagPoints[0] = new Point(agv.TargetPosition.X, agv.TargetPosition.Y - 27); // 깃대 길이에 맞춤
|
||||
flagPoints[1] = new Point(agv.TargetPosition.X + 20, agv.TargetPosition.Y - 22);
|
||||
flagPoints[2] = new Point(agv.TargetPosition.X, agv.TargetPosition.Y - 17);
|
||||
|
||||
using (var flagBrush = new SolidBrush(Color.Red))
|
||||
using (var flagPen = new Pen(Color.DarkRed, 1))
|
||||
{
|
||||
g.FillPolygon(flagBrush, flagPoints);
|
||||
g.DrawPolygon(flagPen, flagPoints);
|
||||
}
|
||||
}
|
||||
|
||||
// 회전 가능 여부 토글 함수
|
||||
public void ToggleRotatable(uint rfidValue)
|
||||
{
|
||||
var rfidPoint = FindRFIDPoint(rfidValue);
|
||||
if (rfidPoint != null)
|
||||
{
|
||||
rfidPoint.IsRotatable = !rfidPoint.IsRotatable;
|
||||
this.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
// 회전 가능 여부 확인 함수
|
||||
public bool IsPointRotatable(uint rfidValue)
|
||||
{
|
||||
var rfidPoint = FindRFIDPoint(rfidValue);
|
||||
return rfidPoint?.IsRotatable ?? false;
|
||||
}
|
||||
|
||||
// 경로 계산 시 회전 가능 여부를 고려하여 방향 결정
|
||||
private Direction DetermineDirection(Point current, Point next, Point target)
|
||||
{
|
||||
// 현재 위치가 회전 가능한 구간인 경우
|
||||
var currentRFID = rfidPoints.FirstOrDefault(p => p.Location == current);
|
||||
if (currentRFID?.IsRotatable ?? false)
|
||||
{
|
||||
// 목적지 방향으로 직접 방향 결정
|
||||
if (target.X > current.X) return Direction.Forward;
|
||||
if (target.X < current.X) return Direction.Backward;
|
||||
if (target.Y > current.Y) return Direction.Forward;
|
||||
if (target.Y < current.Y) return Direction.Backward;
|
||||
}
|
||||
|
||||
// 회전 불가능한 구간인 경우 현재 진행 방향 유지
|
||||
return agv.CurrentDirection;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,22 @@ namespace AGVControl.Models
|
||||
{
|
||||
public Point CurrentPosition { get; set; }
|
||||
public uint CurrentRFID { get; set; }
|
||||
public float BatteryLevel { get; set; } = 0f;
|
||||
/// <summary>
|
||||
/// AGV에서 방향값이 수산됩니다.
|
||||
/// </summary>
|
||||
public Direction CurrentDirection { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 현재위치가 수산되면 목적지까지의 방향값이 계산됩니다.
|
||||
/// </summary>
|
||||
public Direction TargetDirection { get; set; }
|
||||
public bool IsMoving { get; set; }
|
||||
public List<Point> CurrentPath { get; set; }
|
||||
public List<Point> PlannedPath { get; set; }
|
||||
public List<string> PathRFIDs { get; set; }
|
||||
public Point TargetPosition { get; set; }
|
||||
public uint TargetRFID { get; set; }
|
||||
|
||||
public AGV()
|
||||
{
|
||||
@@ -20,6 +31,9 @@ namespace AGVControl.Models
|
||||
PlannedPath = new List<Point>();
|
||||
PathRFIDs = new List<string>();
|
||||
CurrentDirection = Direction.Forward;
|
||||
TargetPosition = Point.Empty;
|
||||
TargetRFID = 0;
|
||||
TargetDirection = Direction.Forward;
|
||||
}
|
||||
|
||||
public void Move()
|
||||
@@ -31,16 +45,6 @@ namespace AGVControl.Models
|
||||
}
|
||||
}
|
||||
|
||||
public void SetNewPath(List<Point> path)
|
||||
{
|
||||
CurrentPath = new List<Point>(path);
|
||||
}
|
||||
|
||||
public void ClearPlannedPath()
|
||||
{
|
||||
PlannedPath.Clear();
|
||||
PathRFIDs.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public enum Direction
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Drawing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
namespace AGVControl.Models
|
||||
{
|
||||
public class RFIDPoint
|
||||
@@ -9,6 +9,15 @@ namespace AGVControl.Models
|
||||
public uint RFIDValue { get; set; }
|
||||
public string NextRFID { get; set; } // 다음 RFID 포인트의 값
|
||||
public bool IsBidirectional { get; set; } // 양방향 연결 여부
|
||||
public bool IsRotatable { get; set; } // 회전 가능 여부
|
||||
public Direction? FixedDirection { get; set; } // 고정 방향(없으면 null)
|
||||
public RectangleF Bounds { get; set; }
|
||||
|
||||
public RFIDPoint()
|
||||
{
|
||||
IsRotatable = false; // 기본값은 회전 불가능
|
||||
IsBidirectional = true; // 기본값은 양방향
|
||||
FixedDirection = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
73
Cs_HMI/SubProject/AGVControl/Properties/Resources.Designer.cs
generated
Normal file
73
Cs_HMI/SubProject/AGVControl/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,73 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 이 코드는 도구를 사용하여 생성되었습니다.
|
||||
// 런타임 버전:4.0.30319.42000
|
||||
//
|
||||
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
|
||||
// 이러한 변경 내용이 손실됩니다.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace AGVControl.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 지역화된 문자열 등을 찾기 위한 강력한 형식의 리소스 클래스입니다.
|
||||
/// </summary>
|
||||
// 이 클래스는 ResGen 또는 Visual Studio와 같은 도구를 통해 StronglyTypedResourceBuilder
|
||||
// 클래스에서 자동으로 생성되었습니다.
|
||||
// 멤버를 추가하거나 제거하려면 .ResX 파일을 편집한 다음 /str 옵션을 사용하여 ResGen을
|
||||
// 다시 실행하거나 VS 프로젝트를 다시 빌드하십시오.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 이 클래스에서 사용하는 캐시된 ResourceManager 인스턴스를 반환합니다.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AGVControl.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 이 강력한 형식의 리소스 클래스를 사용하여 모든 리소스 조회에 대해 현재 스레드의 CurrentUICulture 속성을
|
||||
/// 재정의합니다.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap ico_navi_40 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("ico_navi_40", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
124
Cs_HMI/SubProject/AGVControl/Properties/Resources.resx
Normal file
124
Cs_HMI/SubProject/AGVControl/Properties/Resources.resx
Normal file
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="ico_navi_40" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\ico_navi_40.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
||||
BIN
Cs_HMI/SubProject/AGVControl/Resources/ico_navi_40.png
Normal file
BIN
Cs_HMI/SubProject/AGVControl/Resources/ico_navi_40.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 718 B |
@@ -77,6 +77,11 @@
|
||||
<DependentUpon>MyRadioButton.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="RoundButton.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
@@ -94,6 +99,10 @@
|
||||
<EmbeddedResource Include="MapControl.resx">
|
||||
<DependentUpon>MapControl.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CommUtil\arCommUtil.csproj">
|
||||
@@ -101,5 +110,8 @@
|
||||
<Name>arCommUtil</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\ico_navi_40.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
Reference in New Issue
Block a user