Files
manual_wpf/Models/IntersectionTestDebugger.cs
2025-08-12 14:33:18 +09:00

267 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Teigha.Geometry;
namespace DwgExtractorManual.Models
{
/// <summary>
/// 교차점 생성 및 셀 추출 로직을 테스트하고 디버깅하는 클래스
/// </summary>
public class IntersectionTestDebugger
{
/// <summary>
/// 간단한 테스트 테이블을 만들어서 교차점과 셀 생성을 테스트합니다.
/// </summary>
public static void RunIntersectionTest()
{
Debug.WriteLine("=== 교차점 및 셀 생성 테스트 시작 ===");
try
{
// 테스트용 테이블 생성 (3x4 그리드)
var testSegments = CreateTestTable();
Debug.WriteLine($"테스트 선분 개수: {testSegments.Count}");
// DwgDataExtractor 인스턴스 생성 (실제 코드와 동일)
var mappingData = new MappingTableData();
var fieldMapper = new FieldMapper(mappingData);
var extractor = new DwgDataExtractor(fieldMapper);
// 교차점 찾기 테스트
var intersections = FindTestIntersections(testSegments, extractor);
Debug.WriteLine($"발견된 교차점 개수: {intersections.Count}");
// 각 교차점의 DirectionBits 출력
for (int i = 0; i < intersections.Count; i++)
{
var intersection = intersections[i];
Debug.WriteLine($"교차점 {i}: ({intersection.Position.X:F1}, {intersection.Position.Y:F1}) - DirectionBits: {intersection.DirectionBits} - R{intersection.Row}C{intersection.Column}");
// topLeft/bottomRight 검증
bool isTopLeft = extractor.IsValidTopLeft(intersection.DirectionBits);
bool isBottomRight = extractor.IsValidBottomRight(intersection.DirectionBits);
Debug.WriteLine($" IsTopLeft: {isTopLeft}, IsBottomRight: {isBottomRight}");
}
Debug.WriteLine("=== 테스트 완료 ===");
}
catch (Exception ex)
{
Debug.WriteLine($"테스트 중 오류 발생: {ex.Message}");
Debug.WriteLine(ex.StackTrace);
}
}
/// <summary>
/// 테스트용 3x4 테이블 선분들을 생성합니다.
/// </summary>
private static List<(Point3d start, Point3d end, bool isHorizontal)> CreateTestTable()
{
var segments = new List<(Point3d start, Point3d end, bool isHorizontal)>();
// 수평선들 (4개 - 0, 10, 20, 30 Y좌표)
for (int i = 0; i <= 3; i++)
{
double y = i * 10.0;
segments.Add((new Point3d(0, y, 0), new Point3d(40, y, 0), true));
}
// 수직선들 (5개 - 0, 10, 20, 30, 40 X좌표)
for (int i = 0; i <= 4; i++)
{
double x = i * 10.0;
segments.Add((new Point3d(x, 0, 0), new Point3d(x, 30, 0), false));
}
Debug.WriteLine($"생성된 테스트 테이블: 수평선 4개, 수직선 5개");
return segments;
}
/// <summary>
/// 테스트 선분들로부터 교차점을 찾습니다.
/// </summary>
private static List<IntersectionPoint> FindTestIntersections(List<(Point3d start, Point3d end, bool isHorizontal)> segments, DwgDataExtractor extractor)
{
var intersections = new List<IntersectionPoint>();
double tolerance = 0.1;
var horizontalSegments = segments.Where(s => s.isHorizontal).ToList();
var verticalSegments = segments.Where(s => !s.isHorizontal).ToList();
foreach (var hSeg in horizontalSegments)
{
foreach (var vSeg in verticalSegments)
{
// 교차점 계산
double intersectX = vSeg.start.X;
double intersectY = hSeg.start.Y;
var intersectPoint = new Point3d(intersectX, intersectY, 0);
// 교차점이 두 선분의 범위 내에 있는지 확인
bool onHorizontal = intersectX >= Math.Min(hSeg.start.X, hSeg.end.X) - tolerance &&
intersectX <= Math.Max(hSeg.start.X, hSeg.end.X) + tolerance;
bool onVertical = intersectY >= Math.Min(vSeg.start.Y, vSeg.end.Y) - tolerance &&
intersectY <= Math.Max(vSeg.start.Y, vSeg.end.Y) + tolerance;
if (onHorizontal && onVertical)
{
// DirectionBits 계산
int directionBits = CalculateDirectionBits(intersectPoint, segments, tolerance);
// Row, Column 계산 (1-based)
int row = (int)Math.Round(intersectY / 10.0) + 1;
int column = (int)Math.Round(intersectX / 10.0) + 1;
var intersection = new IntersectionPoint
{
Position = intersectPoint,
DirectionBits = directionBits,
Row = row,
Column = column
};
intersections.Add(intersection);
}
}
}
return intersections;
}
/// <summary>
/// 특정 점에서의 DirectionBits를 계산합니다.
/// </summary>
private static int CalculateDirectionBits(Point3d point, List<(Point3d start, Point3d end, bool isHorizontal)> segments, double tolerance)
{
int bits = 0;
// Right: 1, Up: 2, Left: 4, Down: 8
foreach (var segment in segments)
{
if (segment.isHorizontal)
{
// 수평선에서 점이 선분 위에 있는지 확인
if (Math.Abs(point.Y - segment.start.Y) < tolerance &&
point.X >= Math.Min(segment.start.X, segment.end.X) - tolerance &&
point.X <= Math.Max(segment.start.X, segment.end.X) + tolerance)
{
// 오른쪽으로 선분이 있는지 확인
if (Math.Max(segment.start.X, segment.end.X) > point.X + tolerance)
bits |= 1; // Right
// 왼쪽으로 선분이 있는지 확인
if (Math.Min(segment.start.X, segment.end.X) < point.X - tolerance)
bits |= 4; // Left
}
}
else
{
// 수직선에서 점이 선분 위에 있는지 확인
if (Math.Abs(point.X - segment.start.X) < tolerance &&
point.Y >= Math.Min(segment.start.Y, segment.end.Y) - tolerance &&
point.Y <= Math.Max(segment.start.Y, segment.end.Y) + tolerance)
{
// 위쪽으로 선분이 있는지 확인
if (Math.Max(segment.start.Y, segment.end.Y) > point.Y + tolerance)
bits |= 2; // Up
// 아래쪽으로 선분이 있는지 확인
if (Math.Min(segment.start.Y, segment.end.Y) < point.Y - tolerance)
bits |= 8; // Down
}
}
}
return bits;
}
/// <summary>
/// 교차점들로부터 셀을 추출합니다.
/// </summary>
private static List<TableCell> ExtractTestCells(List<IntersectionPoint> intersections,
List<(Point3d start, Point3d end, bool isHorizontal)> segments,
DwgDataExtractor extractor)
{
var cells = new List<TableCell>();
double tolerance = 0.1;
// topLeft 후보들을 찾아서 각각에 대해 bottomRight를 찾기
var topLeftCandidates = intersections.Where(i => extractor.IsValidTopLeft(i.DirectionBits)).ToList();
Debug.WriteLine($"TopLeft 후보 개수: {topLeftCandidates.Count}");
foreach (var topLeft in topLeftCandidates)
{
Debug.WriteLine($"\nTopLeft 후보 R{topLeft.Row}C{topLeft.Column} 처리 중...");
// bottomRight 찾기 (실제 코드와 동일한 방식)
var bottomRight = FindBottomRightForTest(topLeft, intersections, extractor);
if (bottomRight != null)
{
Debug.WriteLine($" BottomRight 발견: R{bottomRight.Row}C{bottomRight.Column}");
// 셀 생성
var cell = new TableCell
{
MinPoint = new Point3d(topLeft.Position.X, bottomRight.Position.Y, 0),
MaxPoint = new Point3d(bottomRight.Position.X, topLeft.Position.Y, 0),
Row = topLeft.Row,
Column = topLeft.Column,
CellText = $"R{topLeft.Row}C{topLeft.Column}"
};
cells.Add(cell);
Debug.WriteLine($" 셀 생성 완료: ({cell.MinPoint.X:F1},{cell.MinPoint.Y:F1}) to ({cell.MaxPoint.X:F1},{cell.MaxPoint.Y:F1})");
}
else
{
Debug.WriteLine($" BottomRight을 찾지 못함");
}
}
return cells;
}
/// <summary>
/// 테스트용 bottomRight 찾기 메서드
/// </summary>
private static IntersectionPoint FindBottomRightForTest(IntersectionPoint topLeft,
List<IntersectionPoint> intersections,
DwgDataExtractor extractor)
{
// 교차점들을 Row/Column으로 딕셔너리 구성
var intersectionLookup = intersections
.Where(i => i.Row > 0 && i.Column > 0)
.GroupBy(i => i.Row)
.ToDictionary(g => g.Key, g => g.ToDictionary(i => i.Column, i => i));
// topLeft에서 시작하여 bottomRight 찾기
int maxRow = intersectionLookup.Keys.Any() ? intersectionLookup.Keys.Max() : topLeft.Row;
for (int targetRow = topLeft.Row + 1; targetRow <= maxRow + 2; targetRow++)
{
if (!intersectionLookup.ContainsKey(targetRow)) continue;
var rowIntersections = intersectionLookup[targetRow];
var availableColumns = rowIntersections.Keys.Where(col => col >= topLeft.Column).OrderBy(col => col);
foreach (int targetColumn in availableColumns)
{
var candidate = rowIntersections[targetColumn];
if (extractor.IsValidBottomRight(candidate.DirectionBits) ||
(targetRow == maxRow && targetColumn == intersectionLookup.Values.SelectMany(row => row.Keys).Max()))
{
return candidate;
}
}
}
return null;
}
}
}