노트 블럭별 추출
This commit is contained in:
@@ -507,30 +507,40 @@ namespace DwgExtractorManual.Models
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Note 우측아래에 있는 박스를 찾습니다 (교차선 기반 알고리즘).
|
||||
/// Note position에서 height*2 만큼 아래로 수평선을 그어서 교차하는 Line/Polyline을 찾습니다.
|
||||
/// Note 텍스트 아래에 있는 콘텐츠 박스를 찾습니다.
|
||||
/// Note의 정렬점을 기준으로 안정적인 검색 라인을 사용합니다.
|
||||
/// </summary>
|
||||
private (Point3d minPoint, Point3d maxPoint)? FindNoteBox(
|
||||
Transaction tran, DBText noteText, List<ObjectId> polylineIds, List<ObjectId> lineIds, HashSet<(Point3d minPoint, Point3d maxPoint)> usedBoxes)
|
||||
{
|
||||
var notePos = noteText.Position;
|
||||
var noteHeight = noteText.Height;
|
||||
|
||||
double stableX;
|
||||
if (noteText.HorizontalMode == TextHorizontalMode.TextLeft)
|
||||
{
|
||||
stableX = noteText.Position.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
stableX = noteText.AlignmentPoint.X;
|
||||
}
|
||||
|
||||
// Note position에서 height * 2 만큼 아래로 수평선 정의
|
||||
// 검색 라인 정의: 안정적인 X좌표를 기준으로 하되, 약간의 오차를 허용하는 너비
|
||||
double searchY = notePos.Y - (noteHeight * 2);
|
||||
var searchLineStart = new Point3d(notePos.X - noteHeight * 10, searchY, 0);
|
||||
var searchLineEnd = new Point3d(notePos.X + noteHeight * 50, searchY, 0);
|
||||
double searchWidth = noteHeight * 15;
|
||||
var searchLineStart = new Point3d(stableX - noteHeight * 2, searchY, 0);
|
||||
var searchLineEnd = new Point3d(stableX + searchWidth, searchY, 0);
|
||||
|
||||
Debug.WriteLine($"[DEBUG] 교차 검색선: ({searchLineStart.X}, {searchLineStart.Y}) to ({searchLineEnd.X}, {searchLineEnd.Y})");
|
||||
Debug.WriteLine($"[DEBUG] 안정화된 검색 라인: ({searchLineStart.X:F2}, {searchLineStart.Y:F2}) to ({searchLineEnd.X:F2}, {searchLineEnd.Y:F2}) for NOTE at ({notePos.X:F2}, {notePos.Y:F2}) with stableX={stableX:F2}");
|
||||
|
||||
// 1. Polyline과 교차하는지 확인
|
||||
// 1. Polyline과 교차 확인
|
||||
foreach (var polylineId in polylineIds)
|
||||
{
|
||||
using (var polyline = tran.GetObject(polylineId, OpenMode.ForRead) as Polyline)
|
||||
{
|
||||
if (polyline == null) continue;
|
||||
|
||||
// 교차점이 있는지 확인
|
||||
if (DoesLineIntersectPolyline(searchLineStart, searchLineEnd, polyline))
|
||||
{
|
||||
var box = GetPolylineBounds(polyline);
|
||||
@@ -539,18 +549,12 @@ namespace DwgExtractorManual.Models
|
||||
Debug.WriteLine($"[DEBUG] 교차하는 Polyline 박스 발견: {box.Value.minPoint} to {box.Value.maxPoint}");
|
||||
return box;
|
||||
}
|
||||
else if (box.HasValue && usedBoxes.Contains(box.Value))
|
||||
{
|
||||
Debug.WriteLine($"[DEBUG] 박스가 이미 사용됨: {box.Value.minPoint} to {box.Value.maxPoint}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Line들과 교차하여 닫힌 사각형 찾기
|
||||
// 2. Line들과 교차하여 사각형 찾기
|
||||
var intersectingLines = FindIntersectingLines(tran, lineIds, searchLineStart, searchLineEnd);
|
||||
Debug.WriteLine($"[DEBUG] 교차하는 Line 수: {intersectingLines.Count}");
|
||||
|
||||
foreach (var startLineId in intersectingLines)
|
||||
{
|
||||
var rectangle = TraceRectangleFromLine(tran, lineIds, startLineId, notePos, noteHeight);
|
||||
@@ -559,10 +563,6 @@ namespace DwgExtractorManual.Models
|
||||
Debug.WriteLine($"[DEBUG] 교차하는 Line 사각형 발견: {rectangle.Value.minPoint} to {rectangle.Value.maxPoint}");
|
||||
return rectangle;
|
||||
}
|
||||
else if (rectangle.HasValue && usedBoxes.Contains(rectangle.Value))
|
||||
{
|
||||
Debug.WriteLine($"[DEBUG] Line 사각형이 이미 사용됨: {rectangle.Value.minPoint} to {rectangle.Value.maxPoint}");
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -707,13 +707,13 @@ namespace DwgExtractorManual.Models
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Line에서 시작하여 반시계방향으로 사각형을 추적합니다.
|
||||
/// Line에서 시작하여 반시계방향으로 사각형을 추적합니다. (갭 허용)
|
||||
/// </summary>
|
||||
private (Point3d minPoint, Point3d maxPoint)? TraceRectangleFromLine(Transaction tran, List<ObjectId> lineIds, ObjectId startLineId, Point3d notePos, double noteHeight)
|
||||
{
|
||||
try
|
||||
{
|
||||
const double tolerance = 2.0; // 좌표 오차 허용 범위
|
||||
double tolerance = noteHeight * 2.0; // 갭 허용 오차를 Note 높이에 비례하여 설정
|
||||
var visitedLines = new HashSet<ObjectId>();
|
||||
var rectanglePoints = new List<Point3d>();
|
||||
|
||||
@@ -727,47 +727,44 @@ namespace DwgExtractorManual.Models
|
||||
rectanglePoints.Add(nextPoint);
|
||||
visitedLines.Add(startLineId);
|
||||
|
||||
Debug.WriteLine($"[DEBUG] 사각형 추적 시작: ({currentPoint.X}, {currentPoint.Y}) -> ({nextPoint.X}, {nextPoint.Y})");
|
||||
Debug.WriteLine($"[DEBUG] 사각형 추적 시작 (갭 허용): ({currentPoint.X:F2}, {currentPoint.Y:F2}) -> ({nextPoint.X:F2}, {nextPoint.Y:F2})");
|
||||
|
||||
// 최대 4개의 Line으로 사각형 완성 시도
|
||||
for (int step = 0; step < 3; step++) // 시작 Line 제외하고 3개 더 찾기
|
||||
for (int step = 0; step < 5; step++) // 최대 5번의 연결 시도
|
||||
{
|
||||
var nextLineId = FindNextConnectedLine(tran, lineIds, nextPoint, visitedLines, tolerance);
|
||||
if (nextLineId == ObjectId.Null) break;
|
||||
var findResult = FindNextConnectedLine(tran, lineIds, nextPoint, visitedLines, tolerance);
|
||||
if (findResult == null) break;
|
||||
|
||||
var nextLineId = findResult.Value.lineId;
|
||||
var connectionType = findResult.Value.connectionType;
|
||||
|
||||
using (var nextLine = tran.GetObject(nextLineId, OpenMode.ForRead) as Line)
|
||||
{
|
||||
if (nextLine == null) break;
|
||||
|
||||
// 현재 점과 가까운 쪽을 시작점으로 설정
|
||||
Point3d lineStart, lineEnd;
|
||||
if (nextPoint.DistanceTo(nextLine.StartPoint) < nextPoint.DistanceTo(nextLine.EndPoint))
|
||||
Point3d newNextPoint;
|
||||
if (connectionType == "Start")
|
||||
{
|
||||
lineStart = nextLine.StartPoint;
|
||||
lineEnd = nextLine.EndPoint;
|
||||
newNextPoint = nextLine.EndPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
lineStart = nextLine.EndPoint;
|
||||
lineEnd = nextLine.StartPoint;
|
||||
newNextPoint = nextLine.StartPoint;
|
||||
}
|
||||
|
||||
rectanglePoints.Add(lineEnd);
|
||||
rectanglePoints.Add(newNextPoint);
|
||||
visitedLines.Add(nextLineId);
|
||||
nextPoint = lineEnd;
|
||||
nextPoint = newNextPoint;
|
||||
|
||||
Debug.WriteLine($"[DEBUG] 다음 Line 추가: ({lineStart.X}, {lineStart.Y}) -> ({lineEnd.X}, {lineEnd.Y})");
|
||||
Debug.WriteLine($"[DEBUG] 다음 Line 추가 (갭 허용): {nextLine.StartPoint} -> {nextLine.EndPoint}");
|
||||
|
||||
// 시작점으로 돌아왔는지 확인 (사각형 완성)
|
||||
if (nextPoint.DistanceTo(currentPoint) < tolerance)
|
||||
{
|
||||
Debug.WriteLine("[DEBUG] 사각형 완성됨");
|
||||
Debug.WriteLine("[DEBUG] 사각형 완성됨 (갭 허용)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4개 이상의 점이 있고 닫힌 형태인지 확인
|
||||
if (rectanglePoints.Count >= 4)
|
||||
{
|
||||
var bounds = CalculateBounds(rectanglePoints);
|
||||
@@ -782,16 +779,20 @@ namespace DwgExtractorManual.Models
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"[DEBUG] 사각형 추적 중 오류: {ex.Message}");
|
||||
Debug.WriteLine($"[DEBUG] 사각형 추적 중 오류 (갭 허용): {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 현재 점에서 연결된 다음 Line을 찾습니다.
|
||||
/// 현재 점에서 가장 가까운 연결된 다음 Line을 찾습니다. (갭 허용)
|
||||
/// </summary>
|
||||
private ObjectId FindNextConnectedLine(Transaction tran, List<ObjectId> lineIds, Point3d currentPoint, HashSet<ObjectId> visitedLines, double tolerance)
|
||||
private (ObjectId lineId, string connectionType)? FindNextConnectedLine(Transaction tran, List<ObjectId> lineIds, Point3d currentPoint, HashSet<ObjectId> visitedLines, double tolerance)
|
||||
{
|
||||
ObjectId? bestMatchId = null;
|
||||
string? bestConnectionType = null;
|
||||
double minDistance = tolerance;
|
||||
|
||||
foreach (var lineId in lineIds)
|
||||
{
|
||||
if (visitedLines.Contains(lineId)) continue;
|
||||
@@ -800,16 +801,30 @@ namespace DwgExtractorManual.Models
|
||||
{
|
||||
if (line == null) continue;
|
||||
|
||||
// 현재 점과 연결되어 있는지 확인
|
||||
if (currentPoint.DistanceTo(line.StartPoint) < tolerance ||
|
||||
currentPoint.DistanceTo(line.EndPoint) < tolerance)
|
||||
double distToStart = currentPoint.DistanceTo(line.StartPoint);
|
||||
if (distToStart < minDistance)
|
||||
{
|
||||
return lineId;
|
||||
minDistance = distToStart;
|
||||
bestMatchId = lineId;
|
||||
bestConnectionType = "Start";
|
||||
}
|
||||
|
||||
double distToEnd = currentPoint.DistanceTo(line.EndPoint);
|
||||
if (distToEnd < minDistance)
|
||||
{
|
||||
minDistance = distToEnd;
|
||||
bestMatchId = lineId;
|
||||
bestConnectionType = "End";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ObjectId.Null;
|
||||
if (bestMatchId.HasValue)
|
||||
{
|
||||
return (bestMatchId.Value, bestConnectionType);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user