note detection v2
This commit is contained in:
@@ -513,56 +513,189 @@ namespace DwgExtractorManual.Models
|
||||
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)
|
||||
var allLineSegments = new List<Line>();
|
||||
try
|
||||
{
|
||||
stableX = noteText.Position.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
stableX = noteText.AlignmentPoint.X;
|
||||
}
|
||||
var notePos = noteText.Position;
|
||||
var noteHeight = noteText.Height;
|
||||
|
||||
// 검색 라인 정의: 안정적인 X좌표를 기준으로 하되, 약간의 오차를 허용하는 너비
|
||||
double searchY = notePos.Y - (noteHeight * 2);
|
||||
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: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과 교차 확인
|
||||
foreach (var polylineId in polylineIds)
|
||||
{
|
||||
using (var polyline = tran.GetObject(polylineId, OpenMode.ForRead) as Polyline)
|
||||
// Polylines를 Line 세그먼트로 분해하여 추가
|
||||
foreach (var polylineId in polylineIds)
|
||||
{
|
||||
if (polyline == null) continue;
|
||||
|
||||
if (DoesLineIntersectPolyline(searchLineStart, searchLineEnd, polyline))
|
||||
using (var polyline = tran.GetObject(polylineId, OpenMode.ForRead) as Polyline)
|
||||
{
|
||||
var box = GetPolylineBounds(polyline);
|
||||
if (box.HasValue && IsValidNoteBox(box.Value, notePos, noteHeight) && !usedBoxes.Contains(box.Value))
|
||||
if (polyline == null) continue;
|
||||
var explodedEntities = new DBObjectCollection();
|
||||
try
|
||||
{
|
||||
Debug.WriteLine($"[DEBUG] 교차하는 Polyline 박스 발견: {box.Value.minPoint} to {box.Value.maxPoint}");
|
||||
return box;
|
||||
polyline.Explode(explodedEntities);
|
||||
foreach (DBObject obj in explodedEntities)
|
||||
{
|
||||
if (obj is Line line)
|
||||
{
|
||||
allLineSegments.Add(line.Clone() as Line);
|
||||
}
|
||||
obj.Dispose();
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"[DEBUG] Polyline 분해 중 오류: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
explodedEntities.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 기존 Line들을 추가
|
||||
foreach (var lineId in lineIds)
|
||||
{
|
||||
using (var line = tran.GetObject(lineId, OpenMode.ForRead) as Line)
|
||||
{
|
||||
if (line != null)
|
||||
{
|
||||
allLineSegments.Add(line.Clone() as Line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double stableX;
|
||||
if (noteText.HorizontalMode == TextHorizontalMode.TextLeft)
|
||||
{
|
||||
stableX = noteText.Position.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
stableX = noteText.AlignmentPoint.X;
|
||||
}
|
||||
|
||||
double searchY = notePos.Y - (noteHeight * 2);
|
||||
double searchWidth = noteHeight * 15;
|
||||
var searchLineStart = new Point3d(stableX - noteHeight * 6, searchY, 0); // 왼쪽으로 확장 (중간값)
|
||||
var searchLineEnd = new Point3d(stableX + searchWidth, searchY, 0);
|
||||
var searchLineEnd = new Point3d(stableX + searchWidth, searchY, 0);
|
||||
|
||||
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})");
|
||||
|
||||
var intersectingLines = FindIntersectingLineSegments(allLineSegments, searchLineStart, searchLineEnd);
|
||||
foreach (var startLine in intersectingLines)
|
||||
{
|
||||
var rectangle = TraceRectangleFromLineSegments(allLineSegments, startLine, notePos, noteHeight, usedBoxes);
|
||||
if (rectangle.HasValue)
|
||||
{
|
||||
Debug.WriteLine($"[DEBUG] 교차하는 Line/Polyline 조합 사각형 발견: {rectangle.Value.minPoint} to {rectangle.Value.maxPoint}");
|
||||
return rectangle;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 생성된 모든 Line 객체들을 Dispose
|
||||
foreach (var line in allLineSegments)
|
||||
{
|
||||
line.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<Line> FindIntersectingLineSegments(List<Line> allLineSegments, Point3d searchLineStart, Point3d searchLineEnd)
|
||||
{
|
||||
var intersectingLines = new List<Line>();
|
||||
foreach (var line in allLineSegments)
|
||||
{
|
||||
if (DoLinesIntersect(searchLineStart, searchLineEnd, line.StartPoint, line.EndPoint))
|
||||
{
|
||||
intersectingLines.Add(line);
|
||||
}
|
||||
}
|
||||
return intersectingLines;
|
||||
}
|
||||
|
||||
private (Point3d minPoint, Point3d maxPoint)? TraceRectangleFromLineSegments(List<Line> allLineSegments, Line startLine, Point3d notePos, double noteHeight, HashSet<(Point3d minPoint, Point3d maxPoint)> usedBoxes)
|
||||
{
|
||||
try
|
||||
{
|
||||
double tolerance = noteHeight * 2.0;
|
||||
var visitedLines = new HashSet<Line>();
|
||||
var rectanglePoints = new List<Point3d>();
|
||||
|
||||
var currentPoint = startLine.StartPoint;
|
||||
var nextPoint = startLine.EndPoint;
|
||||
rectanglePoints.Add(currentPoint);
|
||||
rectanglePoints.Add(nextPoint);
|
||||
visitedLines.Add(startLine);
|
||||
|
||||
for (int step = 0; step < 5; step++)
|
||||
{
|
||||
var findResult = FindNextConnectedLineSegment(allLineSegments, nextPoint, visitedLines, tolerance);
|
||||
if (findResult == null) break;
|
||||
|
||||
var nextLine = findResult.Value.line;
|
||||
var connectionType = findResult.Value.connectionType;
|
||||
|
||||
Point3d newNextPoint = (connectionType == "Start") ? nextLine.EndPoint : nextLine.StartPoint;
|
||||
|
||||
rectanglePoints.Add(newNextPoint);
|
||||
visitedLines.Add(nextLine);
|
||||
nextPoint = newNextPoint;
|
||||
|
||||
if (nextPoint.DistanceTo(currentPoint) < tolerance)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rectanglePoints.Count >= 4)
|
||||
{
|
||||
var bounds = CalculateBounds(rectanglePoints);
|
||||
if (bounds.HasValue && IsValidNoteBox(bounds.Value, notePos, noteHeight) && !usedBoxes.Contains(bounds.Value))
|
||||
{
|
||||
return bounds;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"[DEBUG] 통합 사각형 추적 중 오류: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private (Line line, string connectionType)? FindNextConnectedLineSegment(List<Line> allLineSegments, Point3d currentPoint, HashSet<Line> visitedLines, double tolerance)
|
||||
{
|
||||
Line bestMatch = null;
|
||||
string bestConnectionType = null;
|
||||
double minDistance = tolerance;
|
||||
|
||||
foreach (var line in allLineSegments)
|
||||
{
|
||||
if (visitedLines.Contains(line)) continue;
|
||||
|
||||
double distToStart = currentPoint.DistanceTo(line.StartPoint);
|
||||
if (distToStart < minDistance)
|
||||
{
|
||||
minDistance = distToStart;
|
||||
bestMatch = line;
|
||||
bestConnectionType = "Start";
|
||||
}
|
||||
|
||||
double distToEnd = currentPoint.DistanceTo(line.EndPoint);
|
||||
if (distToEnd < minDistance)
|
||||
{
|
||||
minDistance = distToEnd;
|
||||
bestMatch = line;
|
||||
bestConnectionType = "End";
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Line들과 교차하여 사각형 찾기
|
||||
var intersectingLines = FindIntersectingLines(tran, lineIds, searchLineStart, searchLineEnd);
|
||||
foreach (var startLineId in intersectingLines)
|
||||
if (bestMatch != null)
|
||||
{
|
||||
var rectangle = TraceRectangleFromLine(tran, lineIds, startLineId, notePos, noteHeight);
|
||||
if (rectangle.HasValue && !usedBoxes.Contains(rectangle.Value))
|
||||
{
|
||||
Debug.WriteLine($"[DEBUG] 교차하는 Line 사각형 발견: {rectangle.Value.minPoint} to {rectangle.Value.maxPoint}");
|
||||
return rectangle;
|
||||
}
|
||||
return (bestMatch, bestConnectionType);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -682,150 +815,7 @@ namespace DwgExtractorManual.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 수평선과 교차하는 Line들을 찾습니다.
|
||||
/// </summary>
|
||||
private List<ObjectId> FindIntersectingLines(Transaction tran, List<ObjectId> lineIds, Point3d searchLineStart, Point3d searchLineEnd)
|
||||
{
|
||||
var intersectingLines = new List<ObjectId>();
|
||||
|
||||
foreach (var lineId in lineIds)
|
||||
{
|
||||
using (var line = tran.GetObject(lineId, OpenMode.ForRead) as Line)
|
||||
{
|
||||
if (line == null) continue;
|
||||
|
||||
if (DoLinesIntersect(searchLineStart, searchLineEnd, line.StartPoint, line.EndPoint))
|
||||
{
|
||||
intersectingLines.Add(lineId);
|
||||
Debug.WriteLine($"[DEBUG] 교차 Line 발견: ({line.StartPoint.X}, {line.StartPoint.Y}) to ({line.EndPoint.X}, {line.EndPoint.Y})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return intersectingLines;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Line에서 시작하여 반시계방향으로 사각형을 추적합니다. (갭 허용)
|
||||
/// </summary>
|
||||
private (Point3d minPoint, Point3d maxPoint)? TraceRectangleFromLine(Transaction tran, List<ObjectId> lineIds, ObjectId startLineId, Point3d notePos, double noteHeight)
|
||||
{
|
||||
try
|
||||
{
|
||||
double tolerance = noteHeight * 2.0; // 갭 허용 오차를 Note 높이에 비례하여 설정
|
||||
var visitedLines = new HashSet<ObjectId>();
|
||||
var rectanglePoints = new List<Point3d>();
|
||||
|
||||
using (var startLine = tran.GetObject(startLineId, OpenMode.ForRead) as Line)
|
||||
{
|
||||
if (startLine == null) return null;
|
||||
|
||||
var currentPoint = startLine.StartPoint;
|
||||
var nextPoint = startLine.EndPoint;
|
||||
rectanglePoints.Add(currentPoint);
|
||||
rectanglePoints.Add(nextPoint);
|
||||
visitedLines.Add(startLineId);
|
||||
|
||||
Debug.WriteLine($"[DEBUG] 사각형 추적 시작 (갭 허용): ({currentPoint.X:F2}, {currentPoint.Y:F2}) -> ({nextPoint.X:F2}, {nextPoint.Y:F2})");
|
||||
|
||||
for (int step = 0; step < 5; step++) // 최대 5번의 연결 시도
|
||||
{
|
||||
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 newNextPoint;
|
||||
if (connectionType == "Start")
|
||||
{
|
||||
newNextPoint = nextLine.EndPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
newNextPoint = nextLine.StartPoint;
|
||||
}
|
||||
|
||||
rectanglePoints.Add(newNextPoint);
|
||||
visitedLines.Add(nextLineId);
|
||||
nextPoint = newNextPoint;
|
||||
|
||||
Debug.WriteLine($"[DEBUG] 다음 Line 추가 (갭 허용): {nextLine.StartPoint} -> {nextLine.EndPoint}");
|
||||
|
||||
if (nextPoint.DistanceTo(currentPoint) < tolerance)
|
||||
{
|
||||
Debug.WriteLine("[DEBUG] 사각형 완성됨 (갭 허용)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rectanglePoints.Count >= 4)
|
||||
{
|
||||
var bounds = CalculateBounds(rectanglePoints);
|
||||
if (bounds.HasValue && IsValidNoteBox(bounds.Value, notePos, noteHeight))
|
||||
{
|
||||
return bounds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"[DEBUG] 사각형 추적 중 오류 (갭 허용): {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 현재 점에서 가장 가까운 연결된 다음 Line을 찾습니다. (갭 허용)
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
using (var line = tran.GetObject(lineId, OpenMode.ForRead) as Line)
|
||||
{
|
||||
if (line == null) continue;
|
||||
|
||||
double distToStart = currentPoint.DistanceTo(line.StartPoint);
|
||||
if (distToStart < minDistance)
|
||||
{
|
||||
minDistance = distToStart;
|
||||
bestMatchId = lineId;
|
||||
bestConnectionType = "Start";
|
||||
}
|
||||
|
||||
double distToEnd = currentPoint.DistanceTo(line.EndPoint);
|
||||
if (distToEnd < minDistance)
|
||||
{
|
||||
minDistance = distToEnd;
|
||||
bestMatchId = lineId;
|
||||
bestConnectionType = "End";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestMatchId.HasValue)
|
||||
{
|
||||
return (bestMatchId.Value, bestConnectionType);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 점들의 경계 상자를 계산합니다.
|
||||
|
||||
Reference in New Issue
Block a user