From 64ff2ecfb9b7586864bb95bf49f8a297edec732d Mon Sep 17 00:00:00 2001 From: backuppc Date: Thu, 15 Jan 2026 16:16:41 +0900 Subject: [PATCH] =?UTF-8?q?=EB=B0=A9=ED=96=A5=EA=B4=80=EB=A6=AC=EB=A5=BC?= =?UTF-8?q?=20=EB=85=B8=EB=93=9C=20=EC=A0=95=EB=B3=B4=EC=97=90=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AGVMapEditor/Forms/MainForm.Designer.cs | 107 +++++- .../AGVLogic/AGVMapEditor/Forms/MainForm.cs | 335 +++++++++++++++++- .../AGVLogic/AGVMapEditor/Forms/MainForm.resx | 70 +++- .../AGVNavigationCore/Models/MapNode.cs | 5 + 4 files changed, 496 insertions(+), 21 deletions(-) diff --git a/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.Designer.cs b/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.Designer.cs index 3afcd1e..12bd2ba 100644 --- a/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.Designer.cs +++ b/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.Designer.cs @@ -69,6 +69,13 @@ namespace AGVMapEditor.Forms this.allTurnLeftRightCrossOnToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.tabPage2 = new System.Windows.Forms.TabPage(); this.lstMagnetDirection = new System.Windows.Forms.ListBox(); + this.toolStrip4 = new System.Windows.Forms.ToolStrip(); + this.btDirDelete = new System.Windows.Forms.ToolStripButton(); + this.btMakeDirdata = new System.Windows.Forms.ToolStripButton(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.button3 = new System.Windows.Forms.Button(); this.statusStrip1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); @@ -81,6 +88,8 @@ namespace AGVMapEditor.Forms this.toolStrip3.SuspendLayout(); this.toolStrip2.SuspendLayout(); this.tabPage2.SuspendLayout(); + this.toolStrip4.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); this.SuspendLayout(); // // statusStrip1 @@ -451,6 +460,8 @@ namespace AGVMapEditor.Forms // tabPage2 // this.tabPage2.Controls.Add(this.lstMagnetDirection); + this.tabPage2.Controls.Add(this.tableLayoutPanel1); + this.tabPage2.Controls.Add(this.toolStrip4); this.tabPage2.Location = new System.Drawing.Point(4, 22); this.tabPage2.Name = "tabPage2"; this.tabPage2.Size = new System.Drawing.Size(292, 309); @@ -463,11 +474,92 @@ namespace AGVMapEditor.Forms this.lstMagnetDirection.Dock = System.Windows.Forms.DockStyle.Fill; this.lstMagnetDirection.FormattingEnabled = true; this.lstMagnetDirection.ItemHeight = 12; - this.lstMagnetDirection.Location = new System.Drawing.Point(0, 0); + this.lstMagnetDirection.Location = new System.Drawing.Point(0, 25); this.lstMagnetDirection.Name = "lstMagnetDirection"; - this.lstMagnetDirection.Size = new System.Drawing.Size(292, 309); + this.lstMagnetDirection.Size = new System.Drawing.Size(292, 246); this.lstMagnetDirection.TabIndex = 3; // + // toolStrip4 + // + this.toolStrip4.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.btDirDelete, + this.btMakeDirdata}); + this.toolStrip4.Location = new System.Drawing.Point(0, 0); + this.toolStrip4.Name = "toolStrip4"; + this.toolStrip4.Size = new System.Drawing.Size(292, 25); + this.toolStrip4.TabIndex = 5; + this.toolStrip4.Text = "toolStrip4"; + // + // btDirDelete + // + this.btDirDelete.Image = ((System.Drawing.Image)(resources.GetObject("btDirDelete.Image"))); + this.btDirDelete.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btDirDelete.Name = "btDirDelete"; + this.btDirDelete.Size = new System.Drawing.Size(61, 22); + this.btDirDelete.Text = "Delete"; + this.btDirDelete.Click += new System.EventHandler(this.btDirDelete_Click); + // + // btMakeDirdata + // + this.btMakeDirdata.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; + this.btMakeDirdata.Image = ((System.Drawing.Image)(resources.GetObject("btMakeDirdata.Image"))); + this.btMakeDirdata.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btMakeDirdata.Name = "btMakeDirdata"; + this.btMakeDirdata.Size = new System.Drawing.Size(69, 22); + this.btMakeDirdata.Text = "Remake"; + this.btMakeDirdata.Click += new System.EventHandler(this.toolStripButton3_Click); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 3; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel1.Controls.Add(this.button1, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.button2, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.button3, 2, 0); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 271); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 1; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(292, 38); + this.tableLayoutPanel1.TabIndex = 6; + // + // button1 + // + this.button1.Dock = System.Windows.Forms.DockStyle.Fill; + this.button1.Location = new System.Drawing.Point(3, 3); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(91, 32); + this.button1.TabIndex = 0; + this.button1.Text = "Left"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // button2 + // + this.button2.Dock = System.Windows.Forms.DockStyle.Fill; + this.button2.Location = new System.Drawing.Point(100, 3); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(91, 32); + this.button2.TabIndex = 0; + this.button2.Text = "Straight"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // button3 + // + this.button3.Dock = System.Windows.Forms.DockStyle.Fill; + this.button3.Location = new System.Drawing.Point(197, 3); + this.button3.Name = "button3"; + this.button3.Size = new System.Drawing.Size(92, 32); + this.button3.TabIndex = 0; + this.button3.Text = "Right"; + this.button3.UseVisualStyleBackColor = true; + this.button3.Click += new System.EventHandler(this.button3_Click); + // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F); @@ -500,6 +592,10 @@ namespace AGVMapEditor.Forms this.toolStrip2.ResumeLayout(false); this.toolStrip2.PerformLayout(); this.tabPage2.ResumeLayout(false); + this.tabPage2.PerformLayout(); + this.toolStrip4.ResumeLayout(false); + this.toolStrip4.PerformLayout(); + this.tableLayoutPanel1.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); @@ -547,5 +643,12 @@ namespace AGVMapEditor.Forms private System.Windows.Forms.ToolStripMenuItem allTurnLeftRightCrossOnToolStripMenuItem; private System.Windows.Forms.TabPage tabPage2; private System.Windows.Forms.ListBox lstMagnetDirection; + private System.Windows.Forms.ToolStrip toolStrip4; + private System.Windows.Forms.ToolStripButton btDirDelete; + private System.Windows.Forms.ToolStripButton btMakeDirdata; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button button3; } } \ No newline at end of file diff --git a/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.cs b/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.cs index b8d79a0..f53f8f3 100644 --- a/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.cs +++ b/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.cs @@ -10,6 +10,7 @@ using AGVNavigationCore.Models; using MapImage = AGVNavigationCore.Models.MapImage; using MapLabel = AGVNavigationCore.Models.MapLabel; using Newtonsoft.Json; +using System.ComponentModel; namespace AGVMapEditor.Forms { @@ -43,8 +44,8 @@ namespace AGVMapEditor.Forms public override string ToString() { // RFID가 있으면 RFID(노드이름), 없으면 NodeID(노드이름) 형태로 표시 - string fromDisplay = FromRfidId > 0 - ? $"{FromRfidId:0000}(*{FromNodeId.PadLeft(4,'0')})" + string fromDisplay = FromRfidId > 0 + ? $"{FromRfidId:0000}(*{FromNodeId.PadLeft(4, '0')})" : $"(*{FromNodeId})"; string toDisplay = ToRfidId > 0 @@ -58,6 +59,7 @@ namespace AGVMapEditor.Forms } + #endregion #region Constructor @@ -981,6 +983,9 @@ namespace AGVMapEditor.Forms // 이미지 노드인 경우 편집 버튼 활성화 UpdateImageEditButton(); + + // 마그넷 방향 리스트 업데이트 + RefreshMagnetDirectionList(); } /// @@ -996,6 +1001,7 @@ namespace AGVMapEditor.Forms { _propertyGrid.SelectedObject = null; DisableImageEditButton(); + lstMagnetDirection.DataSource = null; } /// @@ -1101,6 +1107,13 @@ namespace AGVMapEditor.Forms // 변경된 속성명 디버그 출력 System.Diagnostics.Debug.WriteLine($"[PropertyGrid] 속성 변경됨: {e.ChangedItem.PropertyDescriptor.Name}"); + // 🔥 MagnetDirectionInfo 변경 처리 + if (_propertyGrid.SelectedObject is MagnetDirectionInfo magInfo) + { + ApplyDirectionChange(magInfo); + return; + } + // RFID 값 변경시 중복 검사 if (e.ChangedItem.PropertyDescriptor.Name == "RFID") { @@ -1308,5 +1321,323 @@ namespace AGVMapEditor.Forms UpdateStatusBar($"모든 노드의 회전/교차 속성 활성화 완료"); } } + + /// + /// 마그넷 방향 정보를 표현하는 클래스 + /// + public class MagnetDirectionInfo + { + [JsonIgnore, Browsable(false)] + public MapNode FromNode { get; set; } + + [JsonIgnore, Browsable(false)] + public MapNode ToNode { get; set; } + + [Category("연결 정보")] + [DisplayName("출발 노드")] + [Description("출발 노드의 ID입니다.")] + [ReadOnly(true)] + public string FromNodeId => FromNode?.ID2 ?? "Unknown"; + + [Category("연결 정보")] + [DisplayName("도착 노드")] + [Description("도착 노드의 ID입니다.")] + [ReadOnly(true)] + public string ToNodeId => ToNode?.ID2 ?? "Unknown"; + + [Category("설정")] + [DisplayName("방향")] + [Description("이동할 마그넷 방향입니다.")] + public MagnetPosition? Direction { get; set; } + + public override string ToString() + { + string dirStr = Direction.HasValue ? Direction.Value.ToString() : "None"; + + string fromStr = FromNode != null ? FromNode.ID2 : "Unknown"; + string toStr = ToNode != null ? ToNode.ID2 : "Unknown"; + + return $"{fromStr} -> {toStr} : {dirStr}"; + } + } + + + + + private void RefreshMagnetDirectionList() + { + // 현재 선택된 항목 기억 + int selectedIndex = lstMagnetDirection.SelectedIndex; + + // 데이터 소스 초기화 (UI 갱신 강제) + lstMagnetDirection.DataSource = null; + lstMagnetDirection.Items.Clear(); + + if (this._mapCanvas.Nodes == null) return; + + var directions = new List(); + + // 모든 노드 검색 + foreach (var nodeItem in this._mapCanvas.Nodes) + { + if (nodeItem is MapNode node) + { + if (node.MagnetDirections != null && node.MagnetDirections.Count > 0) + { + foreach (var kvp in node.MagnetDirections) + { + var neighborId = kvp.Key; + var dir = kvp.Value; + var neighbor = this._mapCanvas.Nodes.FirstOrDefault(t => t.Id == neighborId); + + directions.Add(new MagnetDirectionInfo + { + FromNode = node, + ToNode = neighbor, + Direction = dir + }); + } + } + } + } + + // 보기 좋게 정렬 (FromNode ID 순) + directions.Sort((a, b) => string.Compare(a.FromNode.Id, b.FromNode.Id)); + + if (directions.Count > 0) + { + lstMagnetDirection.DataSource = directions; + } + + // 이벤트 연결 + lstMagnetDirection.SelectedIndexChanged -= LstMagnetDirection_SelectedIndexChanged; + lstMagnetDirection.SelectedIndexChanged += LstMagnetDirection_SelectedIndexChanged; + + lstMagnetDirection.DoubleClick -= LstMagnetDirection_DoubleClick; + lstMagnetDirection.DoubleClick += LstMagnetDirection_DoubleClick; + + // 선택 항목 복원 (가능한 경우) -> 선택된 객체가 다르게 생성되므로 인덱스로 복원 시도 + if (selectedIndex >= 0 && selectedIndex < lstMagnetDirection.Items.Count) + { + lstMagnetDirection.SelectedIndex = selectedIndex; + } + } + + private void LstMagnetDirection_SelectedIndexChanged(object sender, EventArgs e) + { + if (lstMagnetDirection.SelectedItem is MagnetDirectionInfo info) + { + // 버튼 상태 업데이트 + UpdateDirectionButtons(info); + } + } + + private void LstMagnetDirection_DoubleClick(object sender, EventArgs e) + { + if (lstMagnetDirection.SelectedItem is MagnetDirectionInfo info) + { + var node = info.FromNode; + if (node != null) + { + // 방향 순환 + if (info.Direction == MagnetPosition.S) info.Direction = MagnetPosition.L; + else if (info.Direction == MagnetPosition.L) info.Direction = MagnetPosition.R; + else if (info.Direction == MagnetPosition.R) info.Direction = MagnetPosition.S; + + ApplyDirectionChange(info); + } + } + } + + private void ApplyDirectionChange(MagnetDirectionInfo info) + { + var node = info.FromNode; + if (node == null) return; + + // 딕셔너리 업데이트 + if (node.MagnetDirections == null) + node.MagnetDirections = new Dictionary(); + + if (info.ToNode != null) + { + if (info.Direction == null) + { + if (node.MagnetDirections.ContainsKey(info.ToNode.Id)) + node.MagnetDirections.Remove(info.ToNode.Id); + } + else + { + node.MagnetDirections[info.ToNode.Id] = info.Direction.Value; + } + + _hasChanges = true; + UpdateTitle(); + + // 리스트 갱신 + RefreshMagnetDirectionList(); + + // 캔버스 등 갱신 + _mapCanvas.Invalidate(); + + // 속성창 갱신 (선택된 객체가 바뀌었을 수 있으므로 다시 설정은 RefreshMagnetDirectionList의 선택 복원에서 처리됨) + _propertyGrid.Refresh(); + } + } + + private void btMakeDirdata_Click(object sender, EventArgs e) + { + + } + + private void toolStripButton3_Click(object sender, EventArgs e) + { + if (this._mapCanvas.Nodes == null || this._mapCanvas.Nodes.Count == 0) + return; + + // 기존 목록을 모두 지울지 물어보고 + var result = MessageBox.Show( + "기존 설정된 마그넷 방향 정보를 모두 초기화하시겠습니까?\n'예'를 선택하면 모든 방향 정보가 삭제된 후 재설정됩니다.\n'아니오'를 선택하면 기존 정보는 유지되고 없는 부분만 추가됩니다.", + "마그넷 방향 자동 생성", + MessageBoxButtons.YesNoCancel, + MessageBoxIcon.Question); + + if (result == DialogResult.Cancel) + return; + + bool clearAll = (result == DialogResult.Yes); + + int updateCount = 0; + + foreach (var node in this._mapCanvas.Nodes) + { + // 연결 노드가 3개 이상인 노드들을 찾아서 + if (node.Type == NodeType.Normal && node is MapNode mapNode) + { + if (clearAll) + { + if (mapNode.MagnetDirections != null) + mapNode.MagnetDirections.Clear(); + else mapNode.MagnetDirections = new Dictionary(); + } + + if (mapNode.ConnectedNodes.Count >= 3) + { + // 마그넷 방향 딕셔너리가 없으면 생성 + if (mapNode.MagnetDirections == null) + mapNode.MagnetDirections = new Dictionary(); + + foreach (var connectedId in mapNode.ConnectedNodes) + { + // 이미 설정된 경우 건너뜀 (모두 초기화 안 한 경우) + if (!clearAll && mapNode.MagnetDirections.ContainsKey(connectedId)) + continue; + + // 모두 자동 생성을 해준다 (기본은 직진으로) + mapNode.MagnetDirections[connectedId] = MagnetPosition.S; + updateCount++; + } + } + } + } + + if (updateCount > 0) + { + _hasChanges = true; + UpdateTitle(); + + // 현재 선택된 노드의 속성창 및 리스트 갱신 + UpdateNodeProperties(); + + MessageBox.Show($"총 {updateCount}개의 연결에 대해 마그넷 방향(직진)이 설정되었습니다.", "완료", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else + { + MessageBox.Show("변경된 사항이 없습니다.", "알림", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } + + private void btDirDelete_Click(object sender, EventArgs e) + { + if (lstMagnetDirection.SelectedItem is MagnetDirectionInfo info) + { + // 선택된 방향정보를 삭제한다. + var result = MessageBox.Show( + $"선택한 마그넷 방향 정보를 삭제하시겠습니까?\n{info.FromNodeId} -> {info.ToNodeId} : {info.Direction}", + "삭제 확인", + MessageBoxButtons.YesNo, + MessageBoxIcon.Question); + + if (result == DialogResult.Yes) + { + if (info.FromNode != null && info.FromNode.MagnetDirections != null) + { + if (info.ToNode != null && info.FromNode.MagnetDirections.ContainsKey(info.ToNode.Id)) + { + info.FromNode.MagnetDirections.Remove(info.ToNode.Id); + + _hasChanges = true; + UpdateTitle(); + + // 리스트 및 UI 갱신 + RefreshMagnetDirectionList(); + + // 캔버스 갱신 + _mapCanvas.Invalidate(); + } + } + } + } + else + { + MessageBox.Show("삭제할 항목을 선택해주세요.", "알림", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } + + private void button1_Click(object sender, EventArgs e) + { + //set left + if (lstMagnetDirection.SelectedItem is MagnetDirectionInfo info) + { + info.Direction = MagnetPosition.L; + ApplyDirectionChange(info); + + UpdateDirectionButtons(info); + } + } + + private void button2_Click(object sender, EventArgs e) + { + //set straight + if (lstMagnetDirection.SelectedItem is MagnetDirectionInfo info) + { + info.Direction = MagnetPosition.S; + ApplyDirectionChange(info); + + UpdateDirectionButtons(info); + } + } + + private void button3_Click(object sender, EventArgs e) + { + //set right + if (lstMagnetDirection.SelectedItem is MagnetDirectionInfo info) + { + info.Direction = MagnetPosition.R; + ApplyDirectionChange(info); + + UpdateDirectionButtons(info); + } + } + + private void UpdateDirectionButtons(MagnetDirectionInfo info) + { + button1.BackColor = SystemColors.Control; + button2.BackColor = SystemColors.Control; + button3.BackColor = SystemColors.Control; + + if (info.Direction == MagnetPosition.L) button1.BackColor = Color.Lime; + else if (info.Direction == MagnetPosition.S) button2.BackColor = Color.Lime; + else if (info.Direction == MagnetPosition.R) button3.BackColor = Color.Lime; + } } } \ No newline at end of file diff --git a/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.resx b/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.resx index 7d5244f..4cc04c8 100644 --- a/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.resx +++ b/Cs_HMI/AGVLogic/AGVMapEditor/Forms/MainForm.resx @@ -123,6 +123,15 @@ 249, 17 + + 17, 56 + + + 462, 17 + + + 249, 17 + @@ -139,9 +148,6 @@ nOccAdABIDXXE1nzAAAAAElFTkSuQmCC - - 462, 17 - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 @@ -169,6 +175,20 @@ YIGDKaeH7rEGFFd1IN1M4c5nAYIcIXLXvmW+uOKfXMvpRO9rFnzJi9lqBKPZYVCedzYsH6SQ2l+Eu2SD bfNyWeHqqhbxahSCGIM2MwSKrYzDWboBx5sxIsP6yvTPH0lk3YoGI9lhaB8NQZO+gl8Dj7SN1tpAvgAA AABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHdSURBVDhPnZLra9NgFMb3T/hV8b8YFP+efZE5RL+qQxEV + dN6+OXfBTynNZtYmbeKSxfSS1pDSNq29UEpJW9tSULT6lvXCI+8LicTpij4QQs45z+85kLNSqVRQLpdR + KpVQLBZRKBSQz+dh2zZ9X1hZJsdxsFgszjzdbpdBDMM4H0KTqcF1XZbcbrd9CK1ZlnU+hK5Mh2ka/c7l + cvZ4PMZsNmN1CjRN8+8QmuoNplKp03Q67U4mEwy/dPDeOWS9VquFZDL5ZwhN9laez+eg5tHXT3ga3cDD + gzXozgHrNZtN6LoOSZKCEMuyyGg0YkPT6RSDzx1sRa/h1btb2NXu4ll0w4c0Gg2oqhqEZLPZK6ZpkuFw + yIY+uh/w6HANr4/v4I3+AHvavQCkXq9DluUgJJPJhFRVJYPBgA3VOnk8Edaxc7zpQ7aO1qEWw6xfrVYh + iiI4jvsFMQwjpCgK6ff7ZyD7J/fxUrqBF0c3MZtP2RbxeByRSOSSD6DSNC2USCRIr9fzIY/fXsXz2HVs + K5v4/uObb+Y47nLA7EmWZQahl8jWdW1sK7cxOSXLzZ5EUQzFYjFCL9H7xdQsSdJysydBEFYFQSD0wGq1 + 2r+ZPfE8v8rzPPkvsycKCYfDF3+ve/oJ+zEPR++RdtEAAAAASUVORK5CYII= @@ -197,20 +217,6 @@ lIotLMtCsVh8lQG4PM/L2bZNlstlBjno78Ds90jcG+zJLjMrivL6yCzlOI6A8EsUkEUP1PsItk/Om6UM w8jpuk74JcpfzM2maZ43S2madqlpGuEHNhwO/80sparqpaqq5L/MUhxSKBRe/l6X+gWA2x2MFEPZrwAA AABJRU5ErkJggg== - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHdSURBVDhPnZLra9NgFMb3T/hV8b8YFP+efZE5RL+qQxEV - dN6+OXfBTynNZtYmbeKSxfSS1pDSNq29UEpJW9tSULT6lvXCI+8LicTpij4QQs45z+85kLNSqVRQLpdR - KpVQLBZRKBSQz+dh2zZ9X1hZJsdxsFgszjzdbpdBDMM4H0KTqcF1XZbcbrd9CK1ZlnU+hK5Mh2ka/c7l - cvZ4PMZsNmN1CjRN8+8QmuoNplKp03Q67U4mEwy/dPDeOWS9VquFZDL5ZwhN9laez+eg5tHXT3ga3cDD - gzXozgHrNZtN6LoOSZKCEMuyyGg0YkPT6RSDzx1sRa/h1btb2NXu4ll0w4c0Gg2oqhqEZLPZK6ZpkuFw - yIY+uh/w6HANr4/v4I3+AHvavQCkXq9DluUgJJPJhFRVJYPBgA3VOnk8Edaxc7zpQ7aO1qEWw6xfrVYh - iiI4jvsFMQwjpCgK6ff7ZyD7J/fxUrqBF0c3MZtP2RbxeByRSOSSD6DSNC2USCRIr9fzIY/fXsXz2HVs - K5v4/uObb+Y47nLA7EmWZQahl8jWdW1sK7cxOSXLzZ5EUQzFYjFCL9H7xdQsSdJysydBEFYFQSD0wGq1 - 2r+ZPfE8v8rzPPkvsycKCYfDF3+ve/oJ+zEPR++RdtEAAAAASUVORK5CYII= @@ -398,6 +404,36 @@ HBUzHot52djqQ6HZhfR7IwK4mKpHtvEDMqvfCiQ6zaAAXM8x94aIWTNrLLG4kVUzgaTSPlzLtyJOZxbb 1wtfyg4Q+AfA3aZlButjSfxGcUJBk4g5tuP3haQKRKXcUQDOmbvNTpPOJeFFjordZmbWTNvMTHFUcpUC nOccAdABIDXXE1nzAAAAAElFTkSuQmCC + + + + + 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 + + + + + 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 \ No newline at end of file diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/Models/MapNode.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/Models/MapNode.cs index 8ad63d4..45b4d8a 100644 --- a/Cs_HMI/AGVLogic/AGVNavigationCore/Models/MapNode.cs +++ b/Cs_HMI/AGVLogic/AGVNavigationCore/Models/MapNode.cs @@ -40,6 +40,11 @@ namespace AGVNavigationCore.Models [Description("도킹/충전 노드의 진입 방향입니다.")] public DockingDirection DockDirection { get; set; } = DockingDirection.DontCare; + + [Category("노드 설정")] + [Description("각 연결된 노드로 향할 때의 마그넷 방향 정보입니다.")] + public Dictionary MagnetDirections { get; set; } = new Dictionary(); + [Category("연결 정보")] [Description("연결된 노드 ID 목록입니다.")] [ReadOnly(true)]