fix
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<OutputPath>..\..\..\..\..\..\Amkor\AGV4\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
|
||||
@@ -51,6 +51,8 @@ namespace AGVSimulator.Forms
|
||||
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.openMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.reloadMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.맵저장SToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.맵다른이름으로저장ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.launchMapEditorToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
|
||||
@@ -65,7 +67,6 @@ namespace AGVSimulator.Forms
|
||||
this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this._toolStrip = new System.Windows.Forms.ToolStrip();
|
||||
this.openMapToolStripButton = new System.Windows.Forms.ToolStripButton();
|
||||
this.reloadMapToolStripButton = new System.Windows.Forms.ToolStripButton();
|
||||
this.launchMapEditorToolStripButton = new System.Windows.Forms.ToolStripButton();
|
||||
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
|
||||
@@ -79,6 +80,7 @@ namespace AGVSimulator.Forms
|
||||
this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.toolStripButton1 = new System.Windows.Forms.ToolStripButton();
|
||||
this.btPredict = new System.Windows.Forms.ToolStripButton();
|
||||
this.btMakeMap = new System.Windows.Forms.ToolStripButton();
|
||||
this._statusStrip = new System.Windows.Forms.StatusStrip();
|
||||
this._statusLabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this._coordLabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
@@ -109,12 +111,12 @@ namespace AGVSimulator.Forms
|
||||
this._addAgvButton = new System.Windows.Forms.Button();
|
||||
this._agvListCombo = new System.Windows.Forms.ComboBox();
|
||||
this._canvasPanel = new System.Windows.Forms.Panel();
|
||||
this.lbPredict = new System.Windows.Forms.RichTextBox();
|
||||
this._agvInfoPanel = new System.Windows.Forms.Panel();
|
||||
this._pathDebugLabel = new System.Windows.Forms.TextBox();
|
||||
this._agvInfoTitleLabel = new System.Windows.Forms.Label();
|
||||
this._liftDirectionLabel = new System.Windows.Forms.Label();
|
||||
this._motorDirectionLabel = new System.Windows.Forms.Label();
|
||||
this.lbPredict = new System.Windows.Forms.RichTextBox();
|
||||
this.timer1 = new System.Windows.Forms.Timer(this.components);
|
||||
this._menuStrip.SuspendLayout();
|
||||
this._toolStrip.SuspendLayout();
|
||||
@@ -145,6 +147,8 @@ namespace AGVSimulator.Forms
|
||||
this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.openMapToolStripMenuItem,
|
||||
this.reloadMapToolStripMenuItem,
|
||||
this.맵저장SToolStripMenuItem,
|
||||
this.맵다른이름으로저장ToolStripMenuItem,
|
||||
this.toolStripSeparator1,
|
||||
this.launchMapEditorToolStripMenuItem,
|
||||
this.toolStripSeparator4,
|
||||
@@ -169,6 +173,20 @@ namespace AGVSimulator.Forms
|
||||
this.reloadMapToolStripMenuItem.Text = "맵 다시열기(&R)";
|
||||
this.reloadMapToolStripMenuItem.Click += new System.EventHandler(this.OnReloadMap_Click);
|
||||
//
|
||||
// 맵저장SToolStripMenuItem
|
||||
//
|
||||
this.맵저장SToolStripMenuItem.Name = "맵저장SToolStripMenuItem";
|
||||
this.맵저장SToolStripMenuItem.Size = new System.Drawing.Size(221, 22);
|
||||
this.맵저장SToolStripMenuItem.Text = "맵 저장(&S)";
|
||||
this.맵저장SToolStripMenuItem.Click += new System.EventHandler(this.맵저장SToolStripMenuItem_Click);
|
||||
//
|
||||
// 맵다른이름으로저장ToolStripMenuItem
|
||||
//
|
||||
this.맵다른이름으로저장ToolStripMenuItem.Name = "맵다른이름으로저장ToolStripMenuItem";
|
||||
this.맵다른이름으로저장ToolStripMenuItem.Size = new System.Drawing.Size(221, 22);
|
||||
this.맵다른이름으로저장ToolStripMenuItem.Text = "맵 다른 이름으로 저장";
|
||||
this.맵다른이름으로저장ToolStripMenuItem.Click += new System.EventHandler(this.btMapSaveAs_Click);
|
||||
//
|
||||
// toolStripSeparator1
|
||||
//
|
||||
this.toolStripSeparator1.Name = "toolStripSeparator1";
|
||||
@@ -272,7 +290,6 @@ namespace AGVSimulator.Forms
|
||||
// _toolStrip
|
||||
//
|
||||
this._toolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.openMapToolStripButton,
|
||||
this.reloadMapToolStripButton,
|
||||
this.launchMapEditorToolStripButton,
|
||||
this.toolStripSeparator2,
|
||||
@@ -285,22 +302,14 @@ namespace AGVSimulator.Forms
|
||||
this.resetZoomToolStripButton,
|
||||
this.toolStripSeparator5,
|
||||
this.toolStripButton1,
|
||||
this.btPredict});
|
||||
this.btPredict,
|
||||
this.btMakeMap});
|
||||
this._toolStrip.Location = new System.Drawing.Point(0, 24);
|
||||
this._toolStrip.Name = "_toolStrip";
|
||||
this._toolStrip.Size = new System.Drawing.Size(1034, 25);
|
||||
this._toolStrip.TabIndex = 1;
|
||||
this._toolStrip.Text = "toolStrip";
|
||||
//
|
||||
// openMapToolStripButton
|
||||
//
|
||||
this.openMapToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.openMapToolStripButton.Name = "openMapToolStripButton";
|
||||
this.openMapToolStripButton.Size = new System.Drawing.Size(51, 22);
|
||||
this.openMapToolStripButton.Text = "맵 열기";
|
||||
this.openMapToolStripButton.ToolTipText = "맵 파일을 엽니다";
|
||||
this.openMapToolStripButton.Click += new System.EventHandler(this.OnOpenMap_Click);
|
||||
//
|
||||
// reloadMapToolStripButton
|
||||
//
|
||||
this.reloadMapToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
@@ -406,6 +415,15 @@ namespace AGVSimulator.Forms
|
||||
this.btPredict.Text = "다음 행동 예측";
|
||||
this.btPredict.Click += new System.EventHandler(this.btPredict_Click);
|
||||
//
|
||||
// btMakeMap
|
||||
//
|
||||
this.btMakeMap.Image = ((System.Drawing.Image)(resources.GetObject("btMakeMap.Image")));
|
||||
this.btMakeMap.ImageTransparentColor = System.Drawing.Color.Magenta;
|
||||
this.btMakeMap.Name = "btMakeMap";
|
||||
this.btMakeMap.Size = new System.Drawing.Size(63, 22);
|
||||
this.btMakeMap.Text = "맵기록";
|
||||
this.btMakeMap.Click += new System.EventHandler(this.btMakeMap_Click);
|
||||
//
|
||||
// _statusStrip
|
||||
//
|
||||
this._statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
@@ -701,6 +719,15 @@ namespace AGVSimulator.Forms
|
||||
this._canvasPanel.Size = new System.Drawing.Size(801, 560);
|
||||
this._canvasPanel.TabIndex = 4;
|
||||
//
|
||||
// lbPredict
|
||||
//
|
||||
this.lbPredict.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.lbPredict.Location = new System.Drawing.Point(0, 513);
|
||||
this.lbPredict.Name = "lbPredict";
|
||||
this.lbPredict.Size = new System.Drawing.Size(801, 47);
|
||||
this.lbPredict.TabIndex = 0;
|
||||
this.lbPredict.Text = "";
|
||||
//
|
||||
// _agvInfoPanel
|
||||
//
|
||||
this._agvInfoPanel.BackColor = System.Drawing.Color.LightBlue;
|
||||
@@ -757,15 +784,6 @@ namespace AGVSimulator.Forms
|
||||
this._motorDirectionLabel.TabIndex = 2;
|
||||
this._motorDirectionLabel.Text = "모터 방향: -";
|
||||
//
|
||||
// lbPredict
|
||||
//
|
||||
this.lbPredict.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.lbPredict.Location = new System.Drawing.Point(0, 513);
|
||||
this.lbPredict.Name = "lbPredict";
|
||||
this.lbPredict.Size = new System.Drawing.Size(801, 47);
|
||||
this.lbPredict.TabIndex = 0;
|
||||
this.lbPredict.Text = "";
|
||||
//
|
||||
// timer1
|
||||
//
|
||||
this.timer1.Interval = 500;
|
||||
@@ -825,7 +843,6 @@ namespace AGVSimulator.Forms
|
||||
private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStrip _toolStrip;
|
||||
private System.Windows.Forms.ToolStripButton openMapToolStripButton;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
|
||||
private System.Windows.Forms.ToolStripButton startSimulationToolStripButton;
|
||||
private System.Windows.Forms.ToolStripButton stopSimulationToolStripButton;
|
||||
@@ -879,5 +896,8 @@ namespace AGVSimulator.Forms
|
||||
private System.Windows.Forms.ToolStripButton btPredict;
|
||||
private System.Windows.Forms.RichTextBox lbPredict;
|
||||
private System.Windows.Forms.Timer timer1;
|
||||
private System.Windows.Forms.ToolStripButton btMakeMap;
|
||||
private System.Windows.Forms.ToolStripMenuItem 맵저장SToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem 맵다른이름으로저장ToolStripMenuItem;
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,13 @@ namespace AGVSimulator.Forms
|
||||
private string _currentMapFilePath;
|
||||
private bool _isTargetCalcMode; // 타겟계산 모드 상태
|
||||
|
||||
// 맵 스캔 모드 관련
|
||||
private bool _isMapScanMode; // 맵 스캔 모드 상태
|
||||
private DateTime _lastNodeAddTime; // 마지막 노드 추가 시간
|
||||
private MapNode _lastScannedNode; // 마지막으로 스캔된 노드
|
||||
private int _scanNodeCounter; // 스캔 노드 카운터
|
||||
private AgvDirection _lastScanDirection; // 마지막 스캔 방향
|
||||
|
||||
// UI Controls - Designer에서 생성됨
|
||||
|
||||
#endregion
|
||||
@@ -238,7 +245,8 @@ namespace AGVSimulator.Forms
|
||||
UpdateAGVComboBox();
|
||||
UpdateUI();
|
||||
|
||||
_statusLabel.Text = $"{agvId} 추가됨";
|
||||
_statusLabel.Text = $"{agvId} 추가됨";
|
||||
_simulatorCanvas.FitToNodes();
|
||||
}
|
||||
|
||||
private void OnRemoveAGV_Click(object sender, EventArgs e)
|
||||
@@ -508,6 +516,165 @@ namespace AGVSimulator.Forms
|
||||
return closestNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 방향을 기호로 변환
|
||||
/// </summary>
|
||||
private string GetDirectionSymbol(AgvDirection direction)
|
||||
{
|
||||
switch (direction)
|
||||
{
|
||||
case AgvDirection.Forward: return "→";
|
||||
case AgvDirection.Backward: return "←";
|
||||
case AgvDirection.Left: return "↺";
|
||||
case AgvDirection.Right: return "↻";
|
||||
default: return "-";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 맵 스캔 모드에서 RFID로부터 노드 생성
|
||||
/// </summary>
|
||||
private void CreateNodeFromRfidScan(string rfidId, VirtualAGV selectedAGV)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 현재 선택된 방향 확인 (최상단에서 먼저 확인)
|
||||
var directionItem = _directionCombo.SelectedItem as DirectionItem;
|
||||
var currentDirection = directionItem?.Direction ?? AgvDirection.Forward;
|
||||
|
||||
// 중복 RFID 확인
|
||||
var existingNode = _mapNodes?.FirstOrDefault(n => n.RfidId.Equals(rfidId, StringComparison.OrdinalIgnoreCase));
|
||||
if (existingNode != null)
|
||||
{
|
||||
// 이미 존재하는 노드로 이동
|
||||
Program.WriteLine($"[맵 스캔] RFID '{rfidId}'는 이미 존재합니다 (노드: {existingNode.NodeId})");
|
||||
|
||||
// 기존 노드로 AGV 위치 설정
|
||||
_simulatorCanvas.SetAGVPosition(selectedAGV.AgvId, existingNode, currentDirection);
|
||||
selectedAGV.SetPosition(existingNode, currentDirection);
|
||||
|
||||
_lastScannedNode = existingNode;
|
||||
_lastNodeAddTime = DateTime.Now;
|
||||
_lastScanDirection = currentDirection; // 방향 업데이트
|
||||
|
||||
_statusLabel.Text = $"기존 노드로 이동: {existingNode.NodeId} [{GetDirectionSymbol(currentDirection)}]";
|
||||
_rfidTextBox.Text = "";
|
||||
return;
|
||||
}
|
||||
|
||||
// 새 노드 생성 위치 계산
|
||||
int newX = 100; // 기본 시작 X 위치
|
||||
int newY = 300; // 기본 시작 Y 위치
|
||||
|
||||
if (_lastScannedNode != null)
|
||||
{
|
||||
// 시간차 기반 X축 거리 계산
|
||||
var timeDiff = (DateTime.Now - _lastNodeAddTime).TotalSeconds;
|
||||
|
||||
// 10초당 10px, 최소 50px, 최대 100px
|
||||
int distanceX = Math.Max(50, Math.Min(100, (int)(timeDiff * 10)));
|
||||
|
||||
// 방향 전환 확인
|
||||
bool directionChanged = (_lastScanDirection != currentDirection);
|
||||
|
||||
if (directionChanged)
|
||||
{
|
||||
// 방향이 바뀌면 Y축을 50px 증가시켜서 겹치지 않게 함
|
||||
newY = _lastScannedNode.Position.Y + 50;
|
||||
newX = _lastScannedNode.Position.X; // X는 같은 위치에서 시작
|
||||
|
||||
Program.WriteLine($"[맵 스캔] 방향 전환: {_lastScanDirection} → {currentDirection}, Y축 +50px");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 방향이 같으면 Y축 유지
|
||||
newY = _lastScannedNode.Position.Y;
|
||||
|
||||
// 모터 방향에 따라 X축 증가/감소
|
||||
if (currentDirection == AgvDirection.Forward)
|
||||
{
|
||||
// 전진: X축 증가
|
||||
newX = _lastScannedNode.Position.X + distanceX;
|
||||
Program.WriteLine($"[맵 스캔] 전진 모드: X축 +{distanceX}px");
|
||||
}
|
||||
else if (currentDirection == AgvDirection.Backward)
|
||||
{
|
||||
// 후진: X축 감소
|
||||
newX = _lastScannedNode.Position.X - distanceX;
|
||||
Program.WriteLine($"[맵 스캔] 후진 모드: X축 -{distanceX}px");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 그 외(회전 등): 기본적으로 전진 방향 사용
|
||||
newX = _lastScannedNode.Position.X + distanceX;
|
||||
Program.WriteLine($"[맵 스캔] 기타 방향({currentDirection}): X축 +{distanceX}px");
|
||||
}
|
||||
}
|
||||
|
||||
Program.WriteLine($"[맵 스캔] 시간차: {timeDiff:F1}초 → 거리: {distanceX}px");
|
||||
}
|
||||
|
||||
// 새 노드 생성
|
||||
var newNodeId = $"{_scanNodeCounter:D3}";
|
||||
var newNode = new MapNode
|
||||
{
|
||||
NodeId = newNodeId,
|
||||
RfidId = rfidId,
|
||||
Position = new Point(newX, newY),
|
||||
Type = NodeType.Normal,
|
||||
IsActive = true,
|
||||
Name = $"N{_scanNodeCounter}"
|
||||
};
|
||||
|
||||
// 맵에 추가
|
||||
if (_mapNodes == null)
|
||||
_mapNodes = new List<MapNode>();
|
||||
|
||||
_mapNodes.Add(newNode);
|
||||
|
||||
// 이전 노드와 연결 생성
|
||||
if (_lastScannedNode != null)
|
||||
{
|
||||
// 양방향 연결 (ConnectedNodes에 추가 - JSON 저장됨)
|
||||
_lastScannedNode.AddConnection(newNode.NodeId);
|
||||
newNode.AddConnection(_lastScannedNode.NodeId);
|
||||
|
||||
Program.WriteLine($"[맵 스캔] 연결 생성: {_lastScannedNode.NodeId} ↔ {newNode.NodeId}");
|
||||
}
|
||||
|
||||
// AGV 위치 설정
|
||||
_simulatorCanvas.SetAGVPosition(selectedAGV.AgvId, newNode, currentDirection);
|
||||
selectedAGV.SetPosition(newNode, currentDirection);
|
||||
|
||||
// 캔버스 업데이트
|
||||
_simulatorCanvas.Nodes = _mapNodes;
|
||||
|
||||
// 화면을 새 노드 위치로 이동
|
||||
_simulatorCanvas.PanToNode(newNode.NodeId);
|
||||
_simulatorCanvas.Invalidate();
|
||||
|
||||
// 상태 업데이트
|
||||
_lastScannedNode = newNode;
|
||||
_lastNodeAddTime = DateTime.Now;
|
||||
_lastScanDirection = currentDirection; // 현재 방향 저장
|
||||
_scanNodeCounter++;
|
||||
|
||||
// UI 업데이트
|
||||
UpdateNodeComboBoxes();
|
||||
|
||||
_statusLabel.Text = $"노드 생성: {newNode.NodeId} (RFID: {rfidId}) [{GetDirectionSymbol(currentDirection)}] - 총 {_mapNodes.Count}개";
|
||||
_rfidTextBox.Text = "";
|
||||
|
||||
Program.WriteLine($"[맵 스캔] 노드 생성 완료: {newNode.NodeId} (RFID: {rfidId}) at ({newX}, {newY}), 방향: {currentDirection}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"노드 생성 중 오류 발생:\n{ex.Message}", "오류",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
Program.WriteLine($"[맵 스캔 오류] {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSetPosition_Click(object sender, EventArgs e)
|
||||
{
|
||||
SetAGVPositionByRfid();
|
||||
@@ -561,6 +728,19 @@ namespace AGVSimulator.Forms
|
||||
MessageBox.Show("RFID 값을 입력해주세요.", "알림", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
// 선택된 방향 확인
|
||||
var selectedDirectionItem = _directionCombo.SelectedItem as DirectionItem;
|
||||
var selectedDirection = selectedDirectionItem?.Direction ?? AgvDirection.Forward;
|
||||
|
||||
|
||||
// 맵 스캔 모드일 때: 노드 자동 생성
|
||||
if (_isMapScanMode)
|
||||
{
|
||||
CreateNodeFromRfidScan(rfidId, selectedAGV);
|
||||
this._simulatorCanvas.FitToNodes();
|
||||
return;
|
||||
}
|
||||
|
||||
// RFID에 해당하는 노드 직접 찾기
|
||||
var targetNode = _mapNodes?.FirstOrDefault(n => n.RfidId.Equals(rfidId, StringComparison.OrdinalIgnoreCase));
|
||||
@@ -571,10 +751,7 @@ namespace AGVSimulator.Forms
|
||||
return;
|
||||
}
|
||||
|
||||
// 선택된 방향 확인
|
||||
var selectedDirectionItem = _directionCombo.SelectedItem as DirectionItem;
|
||||
var selectedDirection = selectedDirectionItem?.Direction ?? AgvDirection.Forward;
|
||||
|
||||
|
||||
//이전위치와 동일한지 체크한다.
|
||||
if (selectedAGV.CurrentNodeId == targetNode.NodeId && selectedAGV.CurrentDirection == selectedDirection)
|
||||
{
|
||||
@@ -1625,6 +1802,184 @@ namespace AGVSimulator.Forms
|
||||
var command = agv.Predict();
|
||||
this.lbPredict.Text = $"Motor:{command.Motor},Magnet:{command.Magnet},Speed:{command.Speed} : {command.Reason}";
|
||||
}
|
||||
|
||||
|
||||
private void btMakeMap_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (!_isMapScanMode)
|
||||
{
|
||||
// 스캔 모드 시작
|
||||
var result = MessageBox.Show(
|
||||
"맵 스캔 모드를 시작합니다.\n\n" +
|
||||
"RFID를 입력하면 자동으로 맵 노드가 생성되고\n" +
|
||||
"이전 노드와 연결됩니다.\n\n" +
|
||||
"기존 맵 데이터를 삭제하고 시작하시겠습니까?\n\n" +
|
||||
"예: 새 맵 시작\n" +
|
||||
"아니오: 기존 맵에 추가",
|
||||
"맵 스캔 모드",
|
||||
MessageBoxButtons.YesNoCancel,
|
||||
MessageBoxIcon.Question);
|
||||
|
||||
if (result == DialogResult.Cancel)
|
||||
return;
|
||||
|
||||
if (result == DialogResult.Yes)
|
||||
{
|
||||
// 기존 맵 데이터 삭제
|
||||
_mapNodes?.Clear();
|
||||
_mapNodes = new List<MapNode>();
|
||||
_simulatorCanvas.Nodes = _mapNodes;
|
||||
_currentMapFilePath = string.Empty;
|
||||
UpdateNodeComboBoxes();
|
||||
_statusLabel.Text = "맵 초기화 완료 - 스캔 모드 시작";
|
||||
}
|
||||
|
||||
// 스캔 모드 활성화
|
||||
_isMapScanMode = true;
|
||||
_lastNodeAddTime = DateTime.Now;
|
||||
_lastScannedNode = null;
|
||||
_scanNodeCounter = 1;
|
||||
_lastScanDirection = AgvDirection.Forward; // 기본 방향은 전진
|
||||
btMakeMap.Text = "스캔 중지";
|
||||
btMakeMap.BackColor = Color.LightCoral;
|
||||
_statusLabel.Text = "맵 스캔 모드: RFID를 입력하여 노드를 생성하세요";
|
||||
|
||||
Program.WriteLine("[맵 스캔] 스캔 모드 시작");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 스캔 모드 종료
|
||||
_isMapScanMode = false;
|
||||
btMakeMap.Text = "맵 생성";
|
||||
btMakeMap.BackColor = SystemColors.Control;
|
||||
_statusLabel.Text = $"맵 스캔 완료 - {_mapNodes?.Count ?? 0}개 노드 생성됨";
|
||||
|
||||
Program.WriteLine($"[맵 스캔] 스캔 모드 종료 - 총 {_mapNodes?.Count ?? 0}개 노드");
|
||||
|
||||
// 맵 저장 권장
|
||||
if (_mapNodes != null && _mapNodes.Count > 0)
|
||||
{
|
||||
var saveResult = MessageBox.Show(
|
||||
$"맵 스캔이 완료되었습니다.\n\n" +
|
||||
$"생성된 노드: {_mapNodes.Count}개\n\n" +
|
||||
"맵을 저장하시겠습니까?",
|
||||
"맵 저장",
|
||||
MessageBoxButtons.YesNo,
|
||||
MessageBoxIcon.Question);
|
||||
|
||||
if (saveResult == DialogResult.Yes)
|
||||
{
|
||||
btMapSaveAs_Click(sender, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 맵 데이터를 파일에 저장 (MapLoader 공통 저장 로직 사용)
|
||||
/// </summary>
|
||||
private void SaveMapToFile(string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
// MapLoader의 표준 저장 메서드 사용 (AGVMapEditor와 동일한 형식)
|
||||
bool success = MapLoader.SaveMapToFile(filePath, _mapNodes);
|
||||
|
||||
if (success)
|
||||
{
|
||||
Program.WriteLine($"[맵 저장] 파일 저장 완료: {filePath} ({_mapNodes.Count}개 노드)");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("맵 저장에 실패했습니다.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Program.WriteLine($"[맵 저장 오류] {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void btMapSaveAs_Click(object sender, EventArgs e)
|
||||
{
|
||||
// 맵 데이터 확인
|
||||
if (_mapNodes == null || _mapNodes.Count == 0)
|
||||
{
|
||||
MessageBox.Show("저장할 맵 데이터가 없습니다.", "알림",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
using (var saveDialog = new SaveFileDialog())
|
||||
{
|
||||
saveDialog.Filter = "AGV Map Files (*.agvmap)|*.agvmap|모든 파일 (*.*)|*.*";
|
||||
saveDialog.Title = "맵 파일 저장";
|
||||
saveDialog.DefaultExt = "agvmap";
|
||||
|
||||
// 현재 파일이 있으면 기본 파일명으로 설정
|
||||
if (!string.IsNullOrEmpty(_currentMapFilePath))
|
||||
{
|
||||
saveDialog.FileName = Path.GetFileName(_currentMapFilePath);
|
||||
saveDialog.InitialDirectory = Path.GetDirectoryName(_currentMapFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 기본 파일명: 날짜_시간 형식
|
||||
saveDialog.FileName = $"ScanMap_{DateTime.Now:yyyyMMdd_HHmmss}.agvmap";
|
||||
}
|
||||
|
||||
if (saveDialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
try
|
||||
{
|
||||
SaveMapToFile(saveDialog.FileName);
|
||||
_currentMapFilePath = saveDialog.FileName;
|
||||
|
||||
// 설정에 마지막 맵 파일 경로 저장
|
||||
_config.LastMapFilePath = _currentMapFilePath;
|
||||
if (_config.AutoSave)
|
||||
{
|
||||
_config.Save();
|
||||
}
|
||||
|
||||
_statusLabel.Text = $"맵 저장 완료: {Path.GetFileName(_currentMapFilePath)}";
|
||||
MessageBox.Show($"맵이 저장되었습니다.\n\n파일: {_currentMapFilePath}", "저장 완료",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"맵 저장 중 오류 발생:\n{ex.Message}", "저장 오류",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void 맵저장SToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
// 현재 맵 파일 경로가 있는 경우 해당 파일에 저장
|
||||
if (string.IsNullOrEmpty(_currentMapFilePath))
|
||||
{
|
||||
// 경로가 없으면 다른 이름으로 저장 다이얼로그 표시
|
||||
btMapSaveAs_Click(sender, e);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
SaveMapToFile(_currentMapFilePath);
|
||||
_statusLabel.Text = $"맵 저장 완료: {Path.GetFileName(_currentMapFilePath)}";
|
||||
MessageBox.Show($"맵이 저장되었습니다.\n\n파일: {_currentMapFilePath}", "저장 완료",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"맵 저장 중 오류 발생:\n{ex.Message}", "저장 오류",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -152,6 +152,21 @@
|
||||
HBUzHot52djqQ6HZhfR7IwK4mKpHtvEDMqvfCiQ6zaAAXM8x94aIWTNrLLG4kVUzgaTSPlzLtyJOZxbb
|
||||
1wtfyg4Q+AfA3aZlButjSfxGcUJBk4g5tuP3haQKRKXcUQDOmbvNTpPOJeFFjordZmbWTNvMTHFUcpUC
|
||||
nOccAdABIDXXE1nzAAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<data name="btMakeMap.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIFSURBVDhPpZLtS1NhGMbPPxJmmlYSgqHiKzGU1EDxg4iK
|
||||
YKyG2WBogqMYJQOtCEVRFBGdTBCJfRnkS4VaaWNT5sqx1BUxRXxDHYxAJLvkusEeBaPAB+5z4Jzn+t3X
|
||||
/aLhnEfjo8m+dCoa+7/C3O2Hqe0zDC+8KG+cRZHZhdzaaWTVTCLDMIY0vfM04Nfh77/G/sEhwpEDbO3t
|
||||
I7TxE8urEVy99fT/AL5gWDLrTB/hnF4XsW0khCu5ln8DmJliT2AXrcNBsU1gj/MH4nMeKwBrPktM28xM
|
||||
cX79DFKrHHD5d9D26hvicx4pABt2lpg10zYzU0zr7+e3xXGcrkEB2O2TNec9nJFwB3alZn5jZorfeDZh
|
||||
6Q3g8s06BeCoKF4MRURoH1+BY2oNCbeb0TIclIYxOhzf8frTOuo7FxCbbVIAzpni0iceEc8vhzEwGkJD
|
||||
lx83ymxifejdKjRNk/8PWnyIyTQqAJek0jqHwfEVscu31baIu8+90sTE4nY025dQ2/5FIPpnXlzKuK8A
|
||||
HBUzHot52djqQ6HZhfR7IwK4mKpHtvEDMqvfCiQ6zaAAXM8x94aIWTNrLLG4kVUzgaTSPlzLtyJOZxbb
|
||||
1wtfyg4Q+AfA3aZlButjSfxGcUJBk4g5tuP3haQKRKXcUQDOmbvNTpPOJeFFjordZmbWTNvMTHFUcpUC
|
||||
nOccAdABIDXXE1nzAAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<metadata name="_statusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
|
||||
Reference in New Issue
Block a user