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