using CoreUnit.Control.UserControl.Canvas; using CoreUnit.Scanner.UserControl.ScannerCanvas; using IxMilia.Dxf.Entities; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Numerics; using System.Security.Cryptography; namespace GUI.Common { static class ParserHelper { static public AddObjectParam GetCandidate( this AddObjectParam insert, AddObjectParam nonInsert, RectangleF rect) { var startPoint = new UnitPoint( insert.Point1.X + rect.X, insert.Point1.Y + rect.Y); switch (nonInsert.ObjectType) { case "ArcCR": return new AddObjectParam { ObjectType = "ArcCR", Center = new UnitPoint(startPoint.X + nonInsert.MajorRadius, startPoint.Y + nonInsert.MajorRadius), StartAngle = (float)0, EndAngle = (float)360, MajorRadius = (float)nonInsert.MajorRadius }; case "Line": return new AddObjectParam { ObjectType = "Line", Point1 = nonInsert.Point1 + startPoint, Point2 = nonInsert.Point2 + startPoint, }; case "Dot": return new AddObjectParam { ObjectType = "Dot", Point1 = startPoint + nonInsert.Point1, }; case "PolyLine": return new AddObjectParam { ObjectType = "Polyline", Point1 = nonInsert.Point1 + startPoint, Point2 = nonInsert.Point2 + startPoint, }; case "Ellipse": return new AddObjectParam { ObjectType = "Ellipse", Center = new UnitPoint(startPoint.X + nonInsert.MajorRadius, startPoint.Y + nonInsert.MajorRadius), Point1 = startPoint + nonInsert.Point1, Point2 = startPoint + nonInsert.Point1, RotateAngle = nonInsert.RotateAngle }; case "ZigZag": return new AddObjectParam { ObjectType = "ZigZag", Point1 = nonInsert.Point1 + startPoint, Point2 = nonInsert.Point2 + startPoint, Pitch = nonInsert.Pitch, Amplitude = nonInsert.Amplitude, Radius = nonInsert.Radius, RotateAngle = nonInsert.RotateAngle, DrawDirection = nonInsert.DrawDirection }; default: Console.WriteLine($"Entity type: {nonInsert.ObjectType}"); return new AddObjectParam(); } } static public List AddObjects( this IEnumerable dataModelParams, ScannerCanvasUserCtrl scannerCanvas) { var drawObjects = new List(); dataModelParams.ToList().ForEach(param => drawObjects.Add(scannerCanvas.AddObject(param))); scannerCanvas.FinalizeGrouping(); return drawObjects; } static List FindArcCloseToNextLine(IList entities, double pointTolerance) { // Arc의 시작점과 그 다음 Line의 시작점이 tolerance 이하일 경우 해당 Arc를 List에 저장 var arcIndices = new List(); for (int i = 0; i < entities.Count - 1; i++) { if (entities[i].EntityType == DxfEntityType.Arc && entities[i + 1].EntityType == DxfEntityType.Line) { var arc = (DxfArc)entities[i]; var line = (DxfLine)entities[i + 1]; // Arc 시작점 계산 var arcStartX = arc.Center.X + arc.Radius * Math.Cos(DegreesToRadians(arc.StartAngle)); var arcStartY = arc.Center.Y + arc.Radius * Math.Sin(DegreesToRadians(arc.StartAngle)); // Line 시작점 var lineStartX = line.P1.X; var lineStartY = line.P1.Y; // 거리 계산 double dx = arcStartX - lineStartX; double dy = arcStartY - lineStartY; double dist = Math.Sqrt(dx * dx + dy * dy); if (dist <= pointTolerance) { arcIndices.Add(i); // 해당 Arc 인덱스 저장 } } } return arcIndices; } static double DegreesToRadians(double degrees) { return degrees * Math.PI / 180.0; } static public IEnumerable GetEntity( this IList dxfEntities) { var dataModelParams = new List(); // 1. Arc-다음 Line 시작점이 가까운 Arc 인덱스 찾기 var arcIndicesToCW = FindArcCloseToNextLine(dxfEntities, pointTolerance: 0.1); // 2. 엔티티 처리 for (int i = 0; i < dxfEntities.Count; i++) { var entity = dxfEntities[i]; bool isArcToCW = arcIndicesToCW.Contains(i); switch (entity.EntityType) { case DxfEntityType.Line: var line = (DxfLine)entity; Console.WriteLine($"Line from {line.P1} to {line.P2}"); dataModelParams.Add(new AddObjectParam { ObjectType = "Line", Point1 = new UnitPoint(line.P1.X, line.P1.Y), Point2 = new UnitPoint(line.P2.X, line.P2.Y) }); break; case DxfEntityType.Circle: var circle = (DxfCircle)entity; Console.WriteLine($"Circle with center {circle.Center} and radius {circle.Radius}"); dataModelParams.Add(new AddObjectParam { ObjectType = "ArcCR", Center = new UnitPoint(circle.Center.X, circle.Center.Y), StartAngle = 0f, EndAngle = 360f, MajorRadius = (float)circle.Radius }); break; case DxfEntityType.Arc: var arc = (DxfArc)entity; float startAngle = (float)Math.Round((float)arc.StartAngle, 0); float endAngle = (float)Math.Round((float)arc.EndAngle, 0); string direction = "CCW"; if (isArcToCW) { direction = "CW"; // CW이면 Start/End 스왑 float temp = startAngle; startAngle = endAngle; endAngle = temp; } float sweepAngle = endAngle - startAngle; if (direction == "CCW" && sweepAngle < 0) sweepAngle += 360; if (direction == "CW" && sweepAngle > 0) sweepAngle -= 360; Console.WriteLine($"Arc with center {arc.Center}, radius {arc.Radius}, start angle {startAngle}, end angle {endAngle}, direction {direction}"); dataModelParams.Add(new AddObjectParam { ObjectType = "ArcCR", Center = new UnitPoint(arc.Center.X, arc.Center.Y), StartAngle = startAngle, EndAngle = endAngle, SweepAngle = sweepAngle, MajorRadius = (float)arc.Radius, Direction = direction }); break; case DxfEntityType.LwPolyline: var polyline = (DxfLwPolyline)entity; Console.WriteLine($"LwPolyline with {polyline.Vertices.Count} vertices:"); for (int v = 0; v < polyline.Vertices.Count; v++) { var vertex = polyline.Vertices[v]; var nextVertex = v < polyline.Vertices.Count - 1 ? polyline.Vertices[v + 1] : polyline.Vertices[0]; dataModelParams.Add(new AddObjectParam { ObjectType = "PolyLine", Point1 = new UnitPoint(vertex.X, vertex.Y), Point2 = new UnitPoint(nextVertex.X, nextVertex.Y) }); } break; case DxfEntityType.Insert: var insert = (DxfInsert)entity; Console.WriteLine($"Insert block at position ({insert.Location.X}, {insert.Location.Y}, {insert.Location.Z})"); dataModelParams.Add(new AddObjectParam { ObjectType = "Insert", Point1 = new UnitPoint(insert.Location.X, insert.Location.Y) }); break; case DxfEntityType.Ellipse: var ellipse = (DxfEllipse)entity; Console.WriteLine($"Ellipse with center {ellipse.Center}, major axis direction {ellipse.MajorAxis}, and normal {ellipse.Normal}, start {ellipse.StartParameter}, end {ellipse.EndParameter}"); var point1 = new UnitPoint( ellipse.Center.X - ellipse.MajorAxis.Length, ellipse.Center.Y - ellipse.MinorAxis().Length); var point2 = new UnitPoint( ellipse.Center.X + ellipse.MajorAxis.Length, ellipse.Center.Y + ellipse.MinorAxis().Length); dataModelParams.Add(new AddObjectParam { ObjectType = "Ellipse", Center = new UnitPoint(ellipse.Center.X, ellipse.Center.Y), Point1 = point1, Point2 = point2, StartAngle = (float)HitUtil.RadiansToDegrees(ellipse.StartParameter), EndAngle = (float)HitUtil.RadiansToDegrees(ellipse.EndParameter), RotateAngle = CalculateRotationAngle(ellipse) }); break; case DxfEntityType.Point: var modelPoint = (DxfModelPoint)entity; Console.WriteLine($"ModelPoint at ({modelPoint.Location.X}, {modelPoint.Location.Y}, {modelPoint.Location.Z})"); dataModelParams.Add(new AddObjectParam { ObjectType = "Dot", Point1 = new UnitPoint(modelPoint.Location.X, modelPoint.Location.Y), }); break; // 다른 도형 타입에 대한 처리 추가 가능 default: Console.WriteLine($"Entity type: {entity.EntityType}"); break; } } return dataModelParams; } static public RectangleF GetRect( this IList drawObjects) { List ptList = new List(); drawObjects.ToList().ForEach(obj => { switch (obj) { case Line _: ptList.Add(((Line)obj).P1); ptList.Add(((Line)obj).P2); break; case Dot _: ptList.Add(((Dot)obj).P1); break; case Spline _: ptList.Add(((Spline)obj).Center); break; case SnowMan _: ptList.Add(((SnowMan)obj).P1); ptList.Add(((SnowMan)obj).P2); break; case Group _: ptList.Add(((Group)obj).P1); ptList.Add(((Group)obj).P2); ptList.Add(((Group)obj).P3); ptList.Add(((Group)obj).P4); break; case Arc3Point _: { RectangleF tempRect = ((Arc3Point)obj).ClientRect; ptList.Add(new UnitPoint(tempRect.Left, tempRect.Bottom)); ptList.Add(new UnitPoint(tempRect.Left, tempRect.Top)); ptList.Add(new UnitPoint(tempRect.Right, tempRect.Bottom)); ptList.Add(new UnitPoint(tempRect.Right, tempRect.Top)); break; } case Arc _: { RectangleF tempRect = ((Arc)obj).ClientRect; ptList.Add(new UnitPoint(tempRect.Left, tempRect.Bottom)); ptList.Add(new UnitPoint(tempRect.Left, tempRect.Top)); ptList.Add(new UnitPoint(tempRect.Right, tempRect.Bottom)); ptList.Add(new UnitPoint(tempRect.Right, tempRect.Top)); break; } case ZigZag _: ptList.Add(((ZigZag)obj).P1); ptList.Add(((ZigZag)obj).P2); break; case EllipseTool _: { RectangleF tempRect = ((EllipseTool)obj).ClientRect; ptList.Add(new UnitPoint(tempRect.Left, tempRect.Bottom)); ptList.Add(new UnitPoint(tempRect.Left, tempRect.Top)); ptList.Add(new UnitPoint(tempRect.Right, tempRect.Bottom)); ptList.Add(new UnitPoint(tempRect.Right, tempRect.Top)); break; } case RectangleTool _: { RectangleF tempRect = ((RectangleTool)obj).ClientRect; ptList.Add(new UnitPoint(tempRect.Left, tempRect.Bottom)); ptList.Add(new UnitPoint(tempRect.Left, tempRect.Top)); ptList.Add(new UnitPoint(tempRect.Right, tempRect.Bottom)); ptList.Add(new UnitPoint(tempRect.Right, tempRect.Top)); break; } } }); return ScreenUtils.GetRect(ptList, 0); } static public float CalculateRotationAngle( DxfEllipse ellipse) { // MajorAxis와 MinorAxis를 사용하여 회전 각도를 계산 var majorAxis = ellipse.MajorAxis; float angle = (float)(Math.Atan2(majorAxis.Y, majorAxis.X) * (180.0 / Math.PI)); return angle; } } }