도면에서 표 추출
This commit is contained in:
@@ -17,7 +17,7 @@ namespace DwgExtractorManual
|
||||
{
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private DispatcherTimer _timer;
|
||||
private DispatcherTimer? _timer;
|
||||
private ExportExcel? _exportExcel;
|
||||
private SqlDatas? _sqlDatas;
|
||||
// 자동 처리 모드 플래그
|
||||
@@ -26,16 +26,76 @@ namespace DwgExtractorManual
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
InitializeDefaultPaths();
|
||||
InitializeTimer();
|
||||
LoadSettings();
|
||||
SetBuildTime();
|
||||
|
||||
// 앱 종료 시 Teigha 리소스 정리
|
||||
this.Closed += MainWindow_Closed;
|
||||
|
||||
LogMessage("🚀 DWG 정보 추출기가 시작되었습니다.");
|
||||
}
|
||||
|
||||
private void MainWindow_Closed(object sender, EventArgs e)
|
||||
private void LoadSettings()
|
||||
{
|
||||
LogMessage("⚙️ 설정을 불러옵니다...");
|
||||
var settings = SettingsManager.LoadSettings();
|
||||
if (settings != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(settings.SourceFolderPath) && Directory.Exists(settings.SourceFolderPath))
|
||||
{
|
||||
txtSourceFolder.Text = settings.SourceFolderPath;
|
||||
LogMessage($"📂 저장된 소스 폴더: {settings.SourceFolderPath}");
|
||||
CheckDwgFiles(settings.SourceFolderPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogMessage($"⚠️ 저장된 소스 폴더를 찾을 수 없습니다: {settings.SourceFolderPath}");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(settings.DestinationFolderPath) && Directory.Exists(settings.DestinationFolderPath))
|
||||
{
|
||||
txtResultFolder.Text = settings.DestinationFolderPath;
|
||||
LogMessage($"💾 저장된 결과 폴더: {settings.DestinationFolderPath}");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogMessage($"⚠️ 저장된 결과 폴더를 찾을 수 없습니다: {settings.DestinationFolderPath}");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(settings.LastExportType))
|
||||
{
|
||||
if (settings.LastExportType == "Excel")
|
||||
{
|
||||
rbExcel.IsChecked = true;
|
||||
}
|
||||
else if (settings.LastExportType == "Database")
|
||||
{
|
||||
rbDatabase.IsChecked = true;
|
||||
}
|
||||
LogMessage($"📋 저장된 출력 형식: {settings.LastExportType}");
|
||||
}
|
||||
LogMessage("✅ 설정 불러오기 완료.");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogMessage("ℹ️ 저장된 설정 파일이 없습니다. 기본값으로 시작합니다.");
|
||||
InitializeDefaultPaths(); // Fallback
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveSettings()
|
||||
{
|
||||
LogMessage("⚙️ 현재 설정을 저장합니다...");
|
||||
var settings = new AppSettings
|
||||
{
|
||||
SourceFolderPath = txtSourceFolder.Text,
|
||||
DestinationFolderPath = txtResultFolder.Text,
|
||||
LastExportType = rbExcel.IsChecked == true ? "Excel" : "Database"
|
||||
};
|
||||
SettingsManager.SaveSettings(settings);
|
||||
LogMessage("✅ 설정 저장 완료.");
|
||||
}
|
||||
|
||||
private void MainWindow_Closed(object? sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -70,7 +130,13 @@ namespace DwgExtractorManual
|
||||
{
|
||||
_timer = new DispatcherTimer();
|
||||
_timer.Interval = TimeSpan.FromSeconds(1);
|
||||
_timer.Tick += (s, e) => txtTime.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
_timer.Tick += (s, e) =>
|
||||
{
|
||||
if (_timer != null)
|
||||
{
|
||||
txtTime.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
};
|
||||
_timer.Start();
|
||||
}
|
||||
|
||||
@@ -176,6 +242,9 @@ namespace DwgExtractorManual
|
||||
|
||||
private async void BtnExtract_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 설정 저장
|
||||
SaveSettings();
|
||||
|
||||
// 입력 유효성 검사
|
||||
if (string.IsNullOrEmpty(txtSourceFolder.Text) || !Directory.Exists(txtSourceFolder.Text))
|
||||
{
|
||||
@@ -278,7 +347,7 @@ namespace DwgExtractorManual
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Windows.MessageBox.Show(message, title, button, image);
|
||||
System.Windows.MessageBox.Show(this, message, title, button, image);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,7 +363,7 @@ namespace DwgExtractorManual
|
||||
}
|
||||
else
|
||||
{
|
||||
return System.Windows.MessageBox.Show(message, title, MessageBoxButton.YesNo, MessageBoxImage.Question);
|
||||
return System.Windows.MessageBox.Show(this, message, title, MessageBoxButton.YesNo, MessageBoxImage.Question);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,12 +464,11 @@ namespace DwgExtractorManual
|
||||
|
||||
LogMessage("💾 Excel 파일과 매핑 데이터를 저장합니다...");
|
||||
|
||||
// 매핑 딕셔너리를 JSON 파일로 저장 (PDF 데이터 병합용)
|
||||
_exportExcel.SaveMappingDictionary(mappingDataFile);
|
||||
_exportExcel?.SaveMappingDictionary(mappingDataFile);
|
||||
LogMessage($"✅ 매핑 데이터 저장 완료: {Path.GetFileName(mappingDataFile)}");
|
||||
|
||||
// Excel 파일 저장
|
||||
_exportExcel.SaveAndCloseExcel(excelFileName);
|
||||
_exportExcel?.SaveAndCloseExcel(excelFileName);
|
||||
LogMessage($"✅ Excel 파일 저장 완료: {Path.GetFileName(excelFileName)}");
|
||||
|
||||
var elapsed = stopwatch.Elapsed;
|
||||
@@ -461,7 +529,7 @@ namespace DwgExtractorManual
|
||||
try
|
||||
{
|
||||
// 실제 DWG 처리 로직 (DwgToDB는 실패시 true 반환)
|
||||
bool failed = _sqlDatas.DwgToDB(file.FullName);
|
||||
bool failed = _sqlDatas?.DwgToDB(file.FullName) ?? true;
|
||||
bool success = !failed;
|
||||
|
||||
fileStopwatch.Stop();
|
||||
@@ -777,6 +845,9 @@ namespace DwgExtractorManual
|
||||
|
||||
private async void BtnPdfExtract_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 설정 저장
|
||||
SaveSettings();
|
||||
|
||||
// 입력 유효성 검사
|
||||
if (string.IsNullOrEmpty(txtSourceFolder.Text) || !Directory.Exists(txtSourceFolder.Text))
|
||||
{
|
||||
@@ -1092,7 +1163,12 @@ namespace DwgExtractorManual
|
||||
LogMessage($"📄 JSON 파일 확인됨: {Path.GetFileName(jsonFilePath)}");
|
||||
|
||||
// 최신 매핑 데이터 파일 찾기
|
||||
string resultDir = Path.GetDirectoryName(csvFilePath) ?? txtResultFolder.Text;
|
||||
string? resultDir = Path.GetDirectoryName(csvFilePath);
|
||||
if (string.IsNullOrEmpty(resultDir))
|
||||
{
|
||||
LogMessage("⚠️ 결과 디렉터리를 찾을 수 없습니다.");
|
||||
return;
|
||||
}
|
||||
var mappingDataFiles = Directory.GetFiles(resultDir, "*_mapping_data.json", SearchOption.TopDirectoryOnly)
|
||||
.OrderByDescending(f => File.GetCreationTime(f))
|
||||
.ToArray();
|
||||
@@ -1168,7 +1244,12 @@ namespace DwgExtractorManual
|
||||
LogMessage($"📄 JSON 파일 확인됨: {Path.GetFileName(jsonFilePath)}");
|
||||
|
||||
// 기존 Excel 매핑 파일 검색 (임시 파일 제외)
|
||||
string resultDir = Path.GetDirectoryName(csvFilePath) ?? txtResultFolder.Text;
|
||||
string? resultDir = Path.GetDirectoryName(csvFilePath);
|
||||
if (string.IsNullOrEmpty(resultDir))
|
||||
{
|
||||
LogMessage("⚠️ 결과 디렉터리를 찾을 수 없습니다.");
|
||||
return;
|
||||
}
|
||||
var allExcelFiles = Directory.GetFiles(resultDir, "*_Mapping.xlsx", SearchOption.TopDirectoryOnly);
|
||||
|
||||
// 임시 파일(~$로 시작하는 파일) 필터링
|
||||
@@ -1296,6 +1377,9 @@ namespace DwgExtractorManual
|
||||
|
||||
private async void BtnMerge_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 설정 저장
|
||||
SaveSettings();
|
||||
|
||||
// 입력 유효성 검사
|
||||
if (string.IsNullOrEmpty(txtResultFolder.Text) || !Directory.Exists(txtResultFolder.Text))
|
||||
{
|
||||
@@ -1560,6 +1644,9 @@ namespace DwgExtractorManual
|
||||
/// </summary>
|
||||
private async void BtnAuto_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 설정 저장
|
||||
SaveSettings();
|
||||
|
||||
try
|
||||
{
|
||||
// 입력 검증
|
||||
@@ -1656,6 +1743,9 @@ namespace DwgExtractorManual
|
||||
/// </summary>
|
||||
private async void BtnDwgOnly_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 설정 저장
|
||||
SaveSettings();
|
||||
|
||||
try
|
||||
{
|
||||
// 경로 검증
|
||||
@@ -1738,6 +1828,13 @@ namespace DwgExtractorManual
|
||||
/// </summary>
|
||||
private async void BtnDwgHeightSort_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 설정 저장
|
||||
SaveSettings();
|
||||
|
||||
// 시각화 데이터 초기화
|
||||
ClearVisualizationData();
|
||||
LogMessage("🧹 시각화 데이터 초기화 완료");
|
||||
|
||||
try
|
||||
{
|
||||
// 경로 검증
|
||||
@@ -2057,8 +2154,8 @@ namespace DwgExtractorManual
|
||||
|
||||
if (allDwgFiles.Count > 0)
|
||||
{
|
||||
// 단일 Excel 파일에 모든 DWG 파일 처리
|
||||
LogMessage("📏 단일 Height 정렬 Excel 파일 생성 중...");
|
||||
// Height 정렬 Excel 파일 생성 (Note 데이터 포함)
|
||||
LogMessage("📏 Height 정렬 Excel 파일 생성 중 (Note 표 데이터 포함)...");
|
||||
await ProcessAllFilesDwgHeightSort(allDwgFiles, resultBaseFolder);
|
||||
LogMessage("✅ Height 정렬 Excel 파일 생성 완료");
|
||||
}
|
||||
@@ -2109,7 +2206,91 @@ namespace DwgExtractorManual
|
||||
string savePath = Path.Combine(resultFolder, $"{timestamp}_AllDWG_HeightSorted.xlsx");
|
||||
|
||||
exportExcel.ExportAllDwgToExcelHeightSorted(allDwgFiles, savePath);
|
||||
|
||||
|
||||
// 시각화 데이터 캐시 초기화
|
||||
MainWindow.ClearVisualizationData();
|
||||
LogMessage("[DEBUG] 시각화 데이터 캐시 초기화 완료.");
|
||||
|
||||
foreach (var (filePath, folderName) in allDwgFiles)
|
||||
{
|
||||
LogMessage($"[DEBUG] DWG 파일에서 Note 추출 시작: {Path.GetFileName(filePath)}");
|
||||
var noteExtractionResult = exportExcel.DwgExtractor.ExtractNotesFromDrawing(filePath);
|
||||
var noteEntities = noteExtractionResult.NoteEntities;
|
||||
LogMessage($"[DEBUG] 추출된 Note 엔티티 수: {noteEntities.Count}");
|
||||
LogMessage($"[DEBUG] 추출된 IntersectionPoints 수: {noteExtractionResult.IntersectionPoints.Count}");
|
||||
LogMessage($"[DEBUG] 추출된 DiagonalLines 수: {noteExtractionResult.DiagonalLines.Count}");
|
||||
LogMessage($"[DEBUG] 추출된 TableSegments 수: {noteExtractionResult.TableSegments.Count}");
|
||||
|
||||
if (noteEntities.Any())
|
||||
{
|
||||
// 테이블이 있는 Note만 가시화 데이터 생성 (최소 4개 셀 이상)
|
||||
var notesWithTables = noteEntities.Where(ne =>
|
||||
ne.Type == "Note" &&
|
||||
ne.Cells != null &&
|
||||
ne.Cells.Count >= 4 && // 최소 4개 셀이 있어야 테이블로 인정
|
||||
ne.TableSegments != null &&
|
||||
ne.TableSegments.Count >= 4).ToList(); // 최소 4개 선분이 있어야 함
|
||||
|
||||
LogMessage($"[DEBUG] 테이블이 있는 Note: {notesWithTables.Count}개");
|
||||
|
||||
foreach (var noteWithTable in notesWithTables)
|
||||
{
|
||||
var visualizationData = new TableCellVisualizationData
|
||||
{
|
||||
FileName = $"{Path.GetFileName(filePath)} - {noteWithTable.Text}",
|
||||
NoteText = noteWithTable.Text,
|
||||
NoteBounds = (
|
||||
noteWithTable.Cells.Min(c => c.MinPoint.X),
|
||||
noteWithTable.Cells.Min(c => c.MinPoint.Y),
|
||||
noteWithTable.Cells.Max(c => c.MaxPoint.X),
|
||||
noteWithTable.Cells.Max(c => c.MaxPoint.Y)
|
||||
),
|
||||
Cells = noteWithTable.Cells.Select(tc => new CellBounds
|
||||
{
|
||||
MinX = tc.MinPoint.X, MinY = tc.MinPoint.Y, MaxX = tc.MaxPoint.X, MaxY = tc.MaxPoint.Y,
|
||||
Row = tc.Row, Column = tc.Column, Text = tc.CellText
|
||||
}).ToList(),
|
||||
TableSegments = noteWithTable.TableSegments.Select(ts => new SegmentInfo
|
||||
{
|
||||
StartX = ts.StartX, StartY = ts.StartY,
|
||||
EndX = ts.EndX, EndY = ts.EndY,
|
||||
IsHorizontal = ts.IsHorizontal
|
||||
}).ToList(),
|
||||
IntersectionPoints = noteWithTable.IntersectionPoints,
|
||||
DiagonalLines = noteWithTable.DiagonalLines ?? new List<DiagonalLine>(),
|
||||
CellBoundaries = noteWithTable.CellBoundaries?.Select(cb => new CellBoundaryInfo
|
||||
{
|
||||
TopLeftX = cb.TopLeft.X, TopLeftY = cb.TopLeft.Y,
|
||||
TopRightX = cb.TopRight.X, TopRightY = cb.TopRight.Y,
|
||||
BottomLeftX = cb.BottomLeft.X, BottomLeftY = cb.BottomLeft.Y,
|
||||
BottomRightX = cb.BottomRight.X, BottomRightY = cb.BottomRight.Y,
|
||||
Label = cb.Label, Width = cb.Width, Height = cb.Height,
|
||||
CellText = cb.CellText ?? ""
|
||||
}).ToList() ?? new List<CellBoundaryInfo>(),
|
||||
TextEntities = noteEntities.Where(ne => ne.Type == "NoteContent").Select(ne => new TextInfo
|
||||
{
|
||||
X = ne.X, Y = ne.Y, Text = ne.Text,
|
||||
IsInTable = noteWithTable.Cells.Any(cell =>
|
||||
ne.X >= cell.MinPoint.X && ne.X <= cell.MaxPoint.X &&
|
||||
ne.Y >= cell.MinPoint.Y && ne.Y <= cell.MaxPoint.Y)
|
||||
}).ToList()
|
||||
};
|
||||
MainWindow.SaveVisualizationData(visualizationData);
|
||||
LogMessage($"[DEBUG] 테이블 Note 시각화 데이터 추가: {visualizationData.FileName} (셀: {visualizationData.Cells.Count}개)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogMessage($"[DEBUG] Note 엔티티가 없어 시각화 데이터를 생성하지 않습니다: {Path.GetFileName(filePath)}");
|
||||
}
|
||||
}
|
||||
|
||||
LogMessage($"[DEBUG] 총 {allDwgFiles.Count}개 파일의 시각화 데이터 저장 완료.");
|
||||
|
||||
// 최종 시각화 데이터 확인
|
||||
var finalVisualizationData = MainWindow.GetVisualizationData();
|
||||
LogMessage($"[DEBUG] 최종 저장된 시각화 데이터: {finalVisualizationData.Count}개 항목");
|
||||
|
||||
LogMessage("✅ Height 정렬 Excel 파일 생성 완료");
|
||||
LogMessage($"📁 저장된 파일: {Path.GetFileName(savePath)}");
|
||||
}
|
||||
@@ -2388,5 +2569,298 @@ namespace DwgExtractorManual
|
||||
_sqlDatas?.Dispose();
|
||||
base.OnClosed(e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Note 추출 기능 테스트 메서드
|
||||
/// </summary>
|
||||
private async Task TestNoteExtraction()
|
||||
{
|
||||
try
|
||||
{
|
||||
LogMessage("🧪 === Note 추출 기능 테스트 시작 ===");
|
||||
|
||||
string sourceFolder = txtSourceFolder.Text;
|
||||
string resultFolder = txtResultFolder.Text;
|
||||
|
||||
if (string.IsNullOrEmpty(sourceFolder) || !Directory.Exists(sourceFolder))
|
||||
{
|
||||
LogMessage("❌ 소스 폴더가 선택되지 않았거나 존재하지 않습니다.");
|
||||
UpdateStatus("소스 폴더를 선택해주세요.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(resultFolder))
|
||||
{
|
||||
LogMessage("❌ 결과 폴더가 선택되지 않았습니다.");
|
||||
UpdateStatus("결과 폴더를 선택해주세요.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 결과 폴더가 없으면 생성
|
||||
if (!Directory.Exists(resultFolder))
|
||||
{
|
||||
Directory.CreateDirectory(resultFolder);
|
||||
LogMessage($"📁 결과 폴더 생성: {resultFolder}");
|
||||
}
|
||||
|
||||
// DWG 파일 찾기
|
||||
var dwgFiles = Directory.GetFiles(sourceFolder, "*.dwg", SearchOption.AllDirectories);
|
||||
LogMessage($"📊 발견된 DWG 파일 수: {dwgFiles.Length}개");
|
||||
|
||||
if (dwgFiles.Length == 0)
|
||||
{
|
||||
LogMessage("⚠️ DWG 파일이 없습니다.");
|
||||
UpdateStatus("DWG 파일이 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateStatus("🔧 Note 추출 중...");
|
||||
progressBar.Maximum = dwgFiles.Length;
|
||||
progressBar.Value = 0;
|
||||
|
||||
// Teigha 서비스 초기화
|
||||
LogMessage("🔧 Teigha 서비스 초기화 중...");
|
||||
TeighaServicesManager.Instance.AcquireServices();
|
||||
|
||||
// 간단한 빈 매핑 데이터로 FieldMapper 생성 (테스트용)
|
||||
var mappingData = new MappingTableData();
|
||||
var fieldMapper = new FieldMapper(mappingData);
|
||||
var extractor = new DwgDataExtractor(fieldMapper);
|
||||
var csvWriter = new CsvDataWriter();
|
||||
|
||||
int processedCount = 0;
|
||||
int successCount = 0;
|
||||
int failureCount = 0;
|
||||
|
||||
// 각 DWG 파일에 대해 Note 추출 테스트
|
||||
foreach (string dwgFile in dwgFiles.Take(3)) // 처음 3개 파일만 테스트
|
||||
{
|
||||
try
|
||||
{
|
||||
string fileName = Path.GetFileNameWithoutExtension(dwgFile);
|
||||
LogMessage($"🔍 [{processedCount + 1}/{Math.Min(3, dwgFiles.Length)}] Note 추출 중: {fileName}");
|
||||
|
||||
// Note 데이터 추출
|
||||
var noteExtractionResult = extractor.ExtractNotesFromDrawing(dwgFile);
|
||||
var noteEntities = noteExtractionResult.NoteEntities;
|
||||
|
||||
// 테이블이 있는 Note만 시각화 데이터 저장
|
||||
if (noteEntities.Any())
|
||||
{
|
||||
var notesWithTables = noteEntities.Where(ne =>
|
||||
ne.Type == "Note" &&
|
||||
ne.Cells != null &&
|
||||
ne.Cells.Count >= 4 && // 최소 4개 셀이 있어야 테이블로 인정
|
||||
ne.TableSegments != null &&
|
||||
ne.TableSegments.Count >= 4).ToList(); // 최소 4개 선분이 있어야 함
|
||||
|
||||
LogMessage($" 테이블이 있는 Note: {notesWithTables.Count}개");
|
||||
|
||||
foreach (var noteWithTable in notesWithTables)
|
||||
{
|
||||
var visualizationData = new TableCellVisualizationData
|
||||
{
|
||||
FileName = $"{Path.GetFileName(dwgFile)} - {noteWithTable.Text}",
|
||||
NoteText = noteWithTable.Text,
|
||||
NoteBounds = (
|
||||
noteWithTable.Cells.Min(c => c.MinPoint.X),
|
||||
noteWithTable.Cells.Min(c => c.MinPoint.Y),
|
||||
noteWithTable.Cells.Max(c => c.MaxPoint.X),
|
||||
noteWithTable.Cells.Max(c => c.MaxPoint.Y)
|
||||
),
|
||||
Cells = noteWithTable.Cells.Select(tc => new CellBounds
|
||||
{
|
||||
MinX = tc.MinPoint.X, MinY = tc.MinPoint.Y, MaxX = tc.MaxPoint.X, MaxY = tc.MaxPoint.Y,
|
||||
Row = tc.Row, Column = tc.Column, Text = tc.CellText
|
||||
}).ToList(),
|
||||
TableSegments = noteWithTable.TableSegments.Select(ts => new SegmentInfo
|
||||
{
|
||||
StartX = ts.StartX, StartY = ts.StartY,
|
||||
EndX = ts.EndX, EndY = ts.EndY,
|
||||
IsHorizontal = ts.IsHorizontal
|
||||
}).ToList(),
|
||||
IntersectionPoints = noteWithTable.IntersectionPoints,
|
||||
DiagonalLines = noteExtractionResult.DiagonalLines.Where(dl =>
|
||||
noteWithTable.Cells.Any(cell =>
|
||||
(dl.Item1.X >= cell.MinPoint.X && dl.Item1.X <= cell.MaxPoint.X &&
|
||||
dl.Item1.Y >= cell.MinPoint.Y && dl.Item1.Y <= cell.MaxPoint.Y) ||
|
||||
(dl.Item2.X >= cell.MinPoint.X && dl.Item2.X <= cell.MaxPoint.X &&
|
||||
dl.Item2.Y >= cell.MinPoint.Y && dl.Item2.Y <= cell.MaxPoint.Y))).Select(dl => new DiagonalLine
|
||||
{
|
||||
StartX = dl.Item1.X, StartY = dl.Item1.Y, EndX = dl.Item2.X, EndY = dl.Item2.Y, Label = dl.Item3
|
||||
}).ToList(),
|
||||
CellBoundaries = noteWithTable.CellBoundaries?.Select(cb => new CellBoundaryInfo
|
||||
{
|
||||
TopLeftX = cb.TopLeft.X, TopLeftY = cb.TopLeft.Y,
|
||||
TopRightX = cb.TopRight.X, TopRightY = cb.TopRight.Y,
|
||||
BottomLeftX = cb.BottomLeft.X, BottomLeftY = cb.BottomLeft.Y,
|
||||
BottomRightX = cb.BottomRight.X, BottomRightY = cb.BottomRight.Y,
|
||||
Label = cb.Label, Width = cb.Width, Height = cb.Height,
|
||||
CellText = cb.CellText ?? ""
|
||||
}).ToList() ?? new List<CellBoundaryInfo>(),
|
||||
TextEntities = noteEntities.Where(ne => ne.Type == "NoteContent").Select(ne => new TextInfo
|
||||
{
|
||||
X = ne.X, Y = ne.Y, Text = ne.Text,
|
||||
IsInTable = noteWithTable.Cells.Any(cell =>
|
||||
ne.X >= cell.MinPoint.X && ne.X <= cell.MaxPoint.X &&
|
||||
ne.Y >= cell.MinPoint.Y && ne.Y <= cell.MaxPoint.Y)
|
||||
}).ToList()
|
||||
};
|
||||
MainWindow.SaveVisualizationData(visualizationData);
|
||||
LogMessage($" ✅ 테이블 Note 시각화 데이터 저장: {visualizationData.FileName} (셀: {visualizationData.Cells.Count}개)");
|
||||
}
|
||||
}
|
||||
|
||||
LogMessage($" 추출된 엔터티: {noteEntities.Count}개");
|
||||
|
||||
var noteCount = noteEntities.Count(ne => ne.Type == "Note");
|
||||
var contentCount = noteEntities.Count(ne => ne.Type == "NoteContent");
|
||||
var tableCount = noteEntities.Count(ne => ne.Type == "Note" && !string.IsNullOrEmpty(ne.TableCsv));
|
||||
|
||||
LogMessage($" - Note 헤더: {noteCount}개");
|
||||
LogMessage($" - Note 콘텐츠: {contentCount}개");
|
||||
LogMessage($" - 테이블 포함 Note: {tableCount}개");
|
||||
|
||||
// CSV 파일 생성
|
||||
if (noteEntities.Count > 0)
|
||||
{
|
||||
// Note 박스 텍스트 CSV
|
||||
var noteTextCsvPath = Path.Combine(resultFolder, $"{fileName}_note_texts.csv");
|
||||
csvWriter.WriteNoteBoxTextToCsv(noteEntities, noteTextCsvPath);
|
||||
LogMessage($" ✅ Note 텍스트 CSV 저장: {Path.GetFileName(noteTextCsvPath)}");
|
||||
|
||||
// Note 테이블 CSV
|
||||
var noteTableCsvPath = Path.Combine(resultFolder, $"{fileName}_note_tables.csv");
|
||||
csvWriter.WriteNoteTablesToCsv(noteEntities, noteTableCsvPath);
|
||||
LogMessage($" ✅ Note 테이블 CSV 저장: {Path.GetFileName(noteTableCsvPath)}");
|
||||
|
||||
// 통합 CSV
|
||||
var combinedCsvPath = Path.Combine(resultFolder, $"{fileName}_note_combined.csv");
|
||||
csvWriter.WriteNoteDataToCombinedCsv(noteEntities, combinedCsvPath);
|
||||
LogMessage($" ✅ 통합 CSV 저장: {Path.GetFileName(combinedCsvPath)}");
|
||||
|
||||
// 개별 테이블 CSV
|
||||
if (tableCount > 0)
|
||||
{
|
||||
var individualTablesDir = Path.Combine(resultFolder, $"{fileName}_individual_tables");
|
||||
csvWriter.WriteIndividualNoteTablesCsv(noteEntities, individualTablesDir);
|
||||
LogMessage($" ✅ 개별 테이블 CSV 저장: {Path.GetFileName(individualTablesDir)}");
|
||||
}
|
||||
|
||||
// 통계 CSV
|
||||
var statisticsCsvPath = Path.Combine(resultFolder, $"{fileName}_note_statistics.csv");
|
||||
csvWriter.WriteNoteStatisticsToCsv(noteEntities, statisticsCsvPath);
|
||||
LogMessage($" ✅ 통계 CSV 저장: {Path.GetFileName(statisticsCsvPath)}");
|
||||
|
||||
// 첫 번째 테이블이 있는 Note의 내용 출력 (디버깅용)
|
||||
var firstTableNote = noteEntities.FirstOrDefault(ne => ne.Type == "Note" && !string.IsNullOrEmpty(ne.TableCsv));
|
||||
if (firstTableNote != null)
|
||||
{
|
||||
LogMessage($" 📋 첫 번째 테이블 Note: '{firstTableNote.Text}'");
|
||||
var tableLines = firstTableNote.TableCsv.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
LogMessage($" 📋 테이블 행 수: {tableLines.Length}");
|
||||
for (int i = 0; i < Math.Min(3, tableLines.Length); i++)
|
||||
{
|
||||
var line = tableLines[i];
|
||||
if (line.Length > 60) line = line.Substring(0, 60) + "...";
|
||||
LogMessage($" 행 {i + 1}: {line}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
successCount++;
|
||||
LogMessage($" ✅ 성공");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
failureCount++;
|
||||
LogMessage($" ❌ 실패: {ex.Message}");
|
||||
}
|
||||
|
||||
processedCount++;
|
||||
progressBar.Value = processedCount;
|
||||
|
||||
// UI 업데이트를 위한 지연
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
LogMessage($"🧪 === Note 추출 테스트 완료 ===");
|
||||
LogMessage($"📊 처리 결과: 성공 {successCount}개, 실패 {failureCount}개");
|
||||
LogMessage($"💾 결과 파일들이 저장되었습니다: {resultFolder}");
|
||||
|
||||
UpdateStatus($"Note 추출 테스트 완료: 성공 {successCount}개, 실패 {failureCount}개");
|
||||
|
||||
// 결과 폴더 열기
|
||||
if (successCount > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Diagnostics.Process.Start("explorer.exe", resultFolder);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage($"❌ Note 추출 테스트 중 오류: {ex.Message}");
|
||||
UpdateStatus("Note 추출 테스트 중 오류 발생");
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
TeighaServicesManager.Instance.ForceDisposeServices();
|
||||
LogMessage("🔄 Teigha 서비스 정리 완료");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage($"⚠️ Teigha 서비스 정리 중 오류: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 빌드 시간을 상태바에 표시합니다.
|
||||
/// </summary>
|
||||
private void SetBuildTime()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 현재 실행 파일의 빌드 시간을 가져옵니다
|
||||
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
|
||||
var buildDate = System.IO.File.GetLastWriteTime(assembly.Location);
|
||||
txtBuildTime.Text = $"빌드: {buildDate:yyyy-MM-dd HH:mm}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
txtBuildTime.Text = "빌드: 알 수 없음";
|
||||
LogMessage($"⚠️ 빌드 시간 조회 오류: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 교차점 테스트 버튼 클릭 이벤트
|
||||
/// </summary>
|
||||
private void BtnTestIntersection_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogMessage("🔬 교차점 생성 테스트 시작...");
|
||||
UpdateStatus("교차점 테스트 중...");
|
||||
|
||||
// 테스트 실행
|
||||
IntersectionTestDebugger.RunIntersectionTest();
|
||||
|
||||
LogMessage("✅ 교차점 테스트 완료 - Debug 창을 확인하세요");
|
||||
UpdateStatus("교차점 테스트 완료");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage($"❌ 교차점 테스트 중 오류: {ex.Message}");
|
||||
UpdateStatus("교차점 테스트 중 오류 발생");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user